/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 28 by matty, Wed Jun 20 13:54:48 2001 UTC revision 368 by matthewc, Wed Apr 16 13:48:17 2003 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X-Windows     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2002
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Line 21  Line 21 
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23  #include <time.h>  #include <time.h>
24    #include <errno.h>
25  #include "rdesktop.h"  #include "rdesktop.h"
26    
27  extern int width;  extern int width;
28  extern int height;  extern int height;
29  extern BOOL motion;  extern BOOL sendmotion;
 extern BOOL grab_keyboard;  
30  extern BOOL fullscreen;  extern BOOL fullscreen;
31  extern int private_colormap;  extern BOOL grab_keyboard;
32    extern BOOL hide_decorations;
33  static int bpp;  extern char title[];
34  static int depth;  extern int server_bpp;
35  static Display *display;  extern int win_button_size;
36    BOOL enable_compose = False;
37    BOOL focused;
38    BOOL mouse_in_wnd;
39    
40    Display *display;
41    static int x_socket;
42    static Screen *screen;
43  static Window wnd;  static Window wnd;
44  static GC gc;  static GC gc;
45  static Visual *visual;  static Visual *visual;
46  static uint32 *colmap;  static int depth;
47    static int bpp;
48    static XIM IM;
49    static XIC IC;
50    static XModifierKeymap *mod_map;
51    static Cursor current_cursor;
52    static Atom protocol_atom, kill_atom;
53    
54    /* endianness */
55    static BOOL host_be;
56    static BOOL xserver_be;
57    
58    /* software backing store */
59    static BOOL ownbackstore;
60    static Pixmap backstore;
61    
62    /* Moving in single app mode */
63    static BOOL moving_wnd;
64    static int move_x_offset = 0;
65    static int move_y_offset = 0;
66    
67    /* MWM decorations */
68    #define MWM_HINTS_DECORATIONS   (1L << 1)
69    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
70    typedef struct
71    {
72            uint32 flags;
73            uint32 functions;
74            uint32 decorations;
75            sint32 inputMode;
76            uint32 status;
77    }
78    PropMotifWmHints;
79    
80    typedef struct
81    {
82            uint32 red;
83            uint32 green;
84            uint32 blue;
85    }
86    PixelColour;
87    
88  #define Ctrans(col) ( private_colormap ? col : colmap[col])  #define FILL_RECTANGLE(x,y,cx,cy)\
89    { \
90            XFillRectangle(display, wnd, gc, x, y, cx, cy); \
91            if (ownbackstore) \
92                    XFillRectangle(display, backstore, gc, x, y, cx, cy); \
93    }
94    
95  #define L_ENDIAN  #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
96  int screen_msbfirst = 0;  { \
97            XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \
98    }
99    
100  static uint8 *translate(int width, int height, uint8 *data);  /* colour maps */
101    BOOL owncolmap = False;
102    static Colormap xcolmap;
103    static uint32 *colmap;
104    
105    #define TRANSLATE(col)          ( server_bpp != 8 ? translate_colour(col) : owncolmap ? col : translate_colour(colmap[col]) )
106    #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
107    #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
108    
109  static int rop2_map[] = {  static int rop2_map[] = {
110          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 64  static int rop2_map[] = { Line 125  static int rop2_map[] = {
125          GXset                   /* 1 */          GXset                   /* 1 */
126  };  };
127    
128    #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
129    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
130    
131    static void
132    mwm_hide_decorations(void)
133    {
134            PropMotifWmHints motif_hints;
135            Atom hintsatom;
136    
137            /* setup the property */
138            motif_hints.flags = MWM_HINTS_DECORATIONS;
139            motif_hints.decorations = 0;
140    
141            /* get the atom for the property */
142            hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
143            if (!hintsatom)
144            {
145                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
146                    return;
147            }
148    
149            XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
150                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
151    }
152    
153    static PixelColour
154    split_colour15(uint32 colour)
155    {
156            PixelColour rv;
157            rv.red = (colour & 0x7c00) >> 10;
158            rv.red = (rv.red * 0xff) / 0x1f;
159            rv.green = (colour & 0x03e0) >> 5;
160            rv.green = (rv.green * 0xff) / 0x1f;
161            rv.blue = (colour & 0x1f);
162            rv.blue = (rv.blue * 0xff) / 0x1f;
163            return rv;
164    }
165    
166    static PixelColour
167    split_colour16(uint32 colour)
168    {
169            PixelColour rv;
170            rv.red = (colour & 0xf800) >> 11;
171            rv.red = (rv.red * 0xff) / 0x1f;
172            rv.green = (colour & 0x07e0) >> 5;
173            rv.green = (rv.green * 0xff) / 0x3f;
174            rv.blue = (colour & 0x001f);
175            rv.blue = (rv.blue * 0xff) / 0x1f;
176            return rv;
177    }
178    
179    static PixelColour
180    split_colour24(uint32 colour)
181    {
182            PixelColour rv;
183            rv.blue = (colour & 0xff0000) >> 16;
184            rv.green = (colour & 0xff00) >> 8;
185            rv.red = (colour & 0xff);
186            return rv;
187    }
188    
189    static uint32
190    make_colour16(PixelColour pc)
191    {
192            pc.red = (pc.red * 0x1f) / 0xff;
193            pc.green = (pc.green * 0x3f) / 0xff;
194            pc.blue = (pc.blue * 0x1f) / 0xff;
195            return (pc.red << 11) | (pc.green << 5) | pc.blue;
196    }
197    
198    static uint32
199    make_colour24(PixelColour pc)
200    {
201            return (pc.red << 16) | (pc.green << 8) | pc.blue;
202    }
203    
204    static uint32
205    make_colour32(PixelColour pc)
206    {
207            return (pc.red << 16) | (pc.green << 8) | pc.blue;
208    }
209    
210    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
211    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
212    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
213                            x = (x << 16) | (x >> 16); }
214    
215    static uint32
216    translate_colour(uint32 colour)
217    {
218            switch (server_bpp)
219            {
220                    case 15:
221                            switch (bpp)
222                            {
223                                    case 16:
224                                            colour = make_colour16(split_colour15(colour));
225                                            break;
226                                    case 24:
227                                            colour = make_colour24(split_colour15(colour));
228                                            break;
229                                    case 32:
230                                            colour = make_colour32(split_colour15(colour));
231                                            break;
232                            }
233                            break;
234                    case 16:
235                            switch (bpp)
236                            {
237                                    case 16:
238                                            break;
239                                    case 24:
240                                            colour = make_colour24(split_colour16(colour));
241                                            break;
242                                    case 32:
243                                            colour = make_colour32(split_colour16(colour));
244                                            break;
245                            }
246                            break;
247                    case 24:
248                            switch (bpp)
249                            {
250                                    case 16:
251                                            colour = make_colour16(split_colour24(colour));
252                                            break;
253                                    case 24:
254                                            break;
255                                    case 32:
256                                            colour = make_colour32(split_colour24(colour));
257                                            break;
258                            }
259                            break;
260            }
261            switch (bpp)
262            {
263                    case 16:
264                            if (host_be != xserver_be)
265                                    BSWAP16(colour);
266                            break;
267    
268                    case 24:
269                            if (xserver_be)
270                                    BSWAP24(colour);
271                            break;
272    
273                    case 32:
274                            if (host_be != xserver_be)
275                                    BSWAP32(colour);
276                            break;
277            }
278    
279            return colour;
280    }
281    
282    static void
283    translate8to8(uint8 * data, uint8 * out, uint8 * end)
284    {
285            while (out < end)
286                    *(out++) = (uint8) colmap[*(data++)];
287    }
288    
289  static void  static void
290  xwin_set_function(uint8 rop2)  translate8to16(uint8 * data, uint16 * out, uint16 * end)
291  {  {
292          static uint8 last_rop2 = ROP2_COPY;          while (out < end)
293                    *(out++) = (uint16) colmap[*(data++)];
294    }
295    
296          if (last_rop2 != rop2)  /* little endian - conversion happens when colourmap is built */
297    static void
298    translate8to24(uint8 * data, uint8 * out, uint8 * end)
299    {
300            uint32 value;
301    
302            while (out < end)
303          {          {
304                  XSetFunction(display, gc, rop2_map[rop2]);                  value = colmap[*(data++)];
305                  last_rop2 = rop2;                  *(out++) = value;
306                    *(out++) = value >> 8;
307                    *(out++) = value >> 16;
308          }          }
309  }  }
310    
311  static void  static void
312  xwin_grab_keyboard()  translate8to32(uint8 * data, uint32 * out, uint32 * end)
313    {
314            while (out < end)
315                    *(out++) = colmap[*(data++)];
316    }
317    
318    /* todo the remaining translate function might need some big endian check ?? */
319    
320    static void
321    translate15to16(uint16 * data, uint16 * out, uint16 * end)
322    {
323            while (out < end)
324                    *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
325    }
326    
327    static void
328    translate15to24(uint16 * data, uint8 * out, uint8 * end)
329  {  {
330          XGrabKeyboard(display, wnd, True, GrabModeAsync, GrabModeAsync,          uint32 value;
331                        CurrentTime);  
332            while (out < end)
333            {
334                    value = make_colour24(split_colour15(*(data++)));
335                    *(out++) = value;
336                    *(out++) = value >> 8;
337                    *(out++) = value >> 16;
338            }
339  }  }
340    
341  static void  static void
342  xwin_ungrab_keyboard()  translate15to32(uint16 * data, uint32 * out, uint32 * end)
343    {
344            while (out < end)
345                    *(out++) = make_colour32(split_colour15(*(data++)));
346    }
347    
348    static void
349    translate16to16(uint16 * data, uint16 * out, uint16 * end)
350    {
351            while (out < end)
352                    *(out++) = (uint16) (*(data++));
353    }
354    
355    
356    static void
357    translate16to24(uint16 * data, uint8 * out, uint8 * end)
358    {
359            uint32 value;
360    
361            while (out < end)
362            {
363                    value = make_colour24(split_colour16(*(data++)));
364                    *(out++) = value;
365                    *(out++) = value >> 8;
366                    *(out++) = value >> 16;
367            }
368    }
369    
370    static void
371    translate16to32(uint16 * data, uint32 * out, uint32 * end)
372    {
373            while (out < end)
374                    *(out++) = make_colour32(split_colour16(*(data++)));
375    }
376    
377    static void
378    translate24to16(uint8 * data, uint16 * out, uint16 * end)
379    {
380            uint32 pixel = 0;
381            while (out < end)
382            {
383                    pixel = *(data++) << 16;
384                    pixel |= *(data++) << 8;
385                    pixel |= *(data++);
386                    *(out++) = (uint16) make_colour16(split_colour24(pixel));
387            }
388    }
389    
390    static void
391    translate24to24(uint8 * data, uint8 * out, uint8 * end)
392    {
393            while (out < end)
394            {
395                    *(out++) = (*(data++));
396            }
397    }
398    
399    static void
400    translate24to32(uint8 * data, uint32 * out, uint32 * end)
401    {
402            uint32 pixel = 0;
403            while (out < end)
404            {
405                    pixel = *(data++);
406                    pixel |= *(data++) << 8;
407                    pixel |= *(data++) << 16;
408                    *(out++) = pixel;
409            }
410    }
411    
412    static uint8 *
413    translate_image(int width, int height, uint8 * data)
414  {  {
415          XUngrabKeyboard(display, CurrentTime);          int size = width * height * bpp / 8;
416            uint8 *out = xmalloc(size);
417            uint8 *end = out + size;
418    
419            switch (server_bpp)
420            {
421                    case 24:
422                            switch (bpp)
423                            {
424                                    case 32:
425                                            translate24to32(data, (uint32 *) out, (uint32 *) end);
426                                            break;
427                                    case 24:
428                                            translate24to24(data, out, end);
429                                            break;
430                                    case 16:
431                                            translate24to16(data, (uint16 *) out, (uint16 *) end);
432                                            break;
433                            }
434                            break;
435                    case 16:
436                            switch (bpp)
437                            {
438                                    case 32:
439                                            translate16to32((uint16 *) data, (uint32 *) out,
440                                                            (uint32 *) end);
441                                            break;
442                                    case 24:
443                                            translate16to24((uint16 *) data, out, end);
444                                            break;
445                                    case 16:
446                                            translate16to16((uint16 *) data, (uint16 *) out,
447                                                            (uint16 *) end);
448                                            break;
449                            }
450                            break;
451                    case 15:
452                            switch (bpp)
453                            {
454                                    case 32:
455                                            translate15to32((uint16 *) data, (uint32 *) out,
456                                                            (uint32 *) end);
457                                            break;
458                                    case 24:
459                                            translate15to24((uint16 *) data, out, end);
460                                            break;
461                                    case 16:
462                                            translate15to16((uint16 *) data, (uint16 *) out,
463                                                            (uint16 *) end);
464                                            break;
465                            }
466                            break;
467                    case 8:
468                            switch (bpp)
469                            {
470                                    case 8:
471                                            translate8to8(data, out, end);
472                                            break;
473                                    case 16:
474                                            translate8to16(data, (uint16 *) out, (uint16 *) end);
475                                            break;
476                                    case 24:
477                                            translate8to24(data, out, end);
478                                            break;
479                                    case 32:
480                                            translate8to32(data, (uint32 *) out, (uint32 *) end);
481                                            break;
482                            }
483                            break;
484            }
485            return out;
486  }  }
487    
488  BOOL  BOOL
489  ui_create_window(char *title)  get_key_state(unsigned int state, uint32 keysym)
490    {
491            int modifierpos, key, keysymMask = 0;
492            int offset;
493    
494            KeyCode keycode = XKeysymToKeycode(display, keysym);
495    
496            if (keycode == NoSymbol)
497                    return False;
498    
499            for (modifierpos = 0; modifierpos < 8; modifierpos++)
500            {
501                    offset = mod_map->max_keypermod * modifierpos;
502    
503                    for (key = 0; key < mod_map->max_keypermod; key++)
504                    {
505                            if (mod_map->modifiermap[offset + key] == keycode)
506                                    keysymMask |= 1 << modifierpos;
507                    }
508            }
509    
510            return (state & keysymMask) ? True : False;
511    }
512    
513    BOOL
514    ui_init(void)
515  {  {
         XSetWindowAttributes attribs;  
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
516          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
517          int count;          uint16 test;
518            int i;
519    
520          display = XOpenDisplay(NULL);          display = XOpenDisplay(NULL);
521          if (display == NULL)          if (display == NULL)
522          {          {
523                  ERROR("Failed to open display\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
524                  return False;                  return False;
525          }          }
526    
527          visual = DefaultVisual(display, DefaultScreen(display));          x_socket = ConnectionNumber(display);
528          depth = DefaultDepth(display, DefaultScreen(display));          screen = DefaultScreenOfDisplay(display);
529          pfm = XListPixmapFormats(display, &count);          visual = DefaultVisualOfScreen(screen);
530            depth = DefaultDepthOfScreen(screen);
531    
532            pfm = XListPixmapFormats(display, &i);
533          if (pfm != NULL)          if (pfm != NULL)
534          {          {
535                  while (count--)                  /* Use maximum bpp for this depth - this is generally
536                       desirable, e.g. 24 bits->32 bits. */
537                    while (i--)
538                  {                  {
539                          if ((pfm + count)->depth == depth                          if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
                             && (pfm + count)->bits_per_pixel > bpp)  
540                          {                          {
541                                  bpp = (pfm + count)->bits_per_pixel;                                  bpp = pfm[i].bits_per_pixel;
542                          }                          }
543                  }                  }
544                  XFree(pfm);                  XFree(pfm);
# Line 124  ui_create_window(char *title) Line 546  ui_create_window(char *title)
546    
547          if (bpp < 8)          if (bpp < 8)
548          {          {
549                  ERROR("Less than 8 bpp not currently supported.\n");                  error("Less than 8 bpp not currently supported.\n");
550                  XCloseDisplay(display);                  XCloseDisplay(display);
551                  return False;                  return False;
552          }          }
553    
554          width &= ~3; /* make width nicely divisible */          if (owncolmap != True)
555            {
556                    xcolmap = DefaultColormapOfScreen(screen);
557                    if (depth <= 8)
558                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
559            }
560    
561            gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
562    
563          attribs.background_pixel = BlackPixel(display, DefaultScreen(display));          if (DoesBackingStore(screen) != Always)
564          attribs.backing_store = Always;                  ownbackstore = True;
565    
566            test = 1;
567            host_be = !(BOOL) (*(uint8 *) (&test));
568            xserver_be = (ImageByteOrder(display) == MSBFirst);
569    
570            if ((width == 0) || (height == 0))
571            {
572                    /* Fetch geometry from _NET_WORKAREA */
573                    uint32 x, y, cx, cy;
574    
575                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
576                    {
577                            width = cx;
578                            height = cy;
579                    }
580                    else
581                    {
582                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
583                            width = 800;
584                            height = 600;
585                    }
586            }
587    
588          if (fullscreen)          if (fullscreen)
589          {          {
590                  attribs.override_redirect = True;                  width = WidthOfScreen(screen);
591                  width = WidthOfScreen(DefaultScreenOfDisplay(display));                  height = HeightOfScreen(screen);
                 height = HeightOfScreen(DefaultScreenOfDisplay(display));  
                 XSetInputFocus(display, PointerRoot, RevertToPointerRoot,  
                                CurrentTime);  
592          }          }
593          else  
594            /* make sure width is a multiple of 4 */
595            width = (width + 3) & ~3;
596    
597            if (ownbackstore)
598          {          {
599                  attribs.override_redirect = False;                  backstore =
600                            XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
601    
602                    /* clear to prevent rubbish being exposed at startup */
603                    XSetForeground(display, gc, BlackPixelOfScreen(screen));
604                    XFillRectangle(display, backstore, gc, 0, 0, width, height);
605          }          }
606    
607          wnd = XCreateWindow(display, DefaultRootWindow(display),          mod_map = XGetModifierMapping(display);
608                              0, 0, width, height, 0, CopyFromParent,  
609                              InputOutput, CopyFromParent,          if (enable_compose)
610                              CWBackingStore | CWBackPixel | CWOverrideRedirect,                  IM = XOpenIM(display, NULL, NULL, NULL);
611                              &attribs);  
612            xkeymap_init();
613    
614            /* todo take this out when high colour is done */
615            printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth);
616    
617            return True;
618    }
619    
620    void
621    ui_deinit(void)
622    {
623            if (IM != NULL)
624                    XCloseIM(IM);
625    
626            XFreeModifiermap(mod_map);
627    
628            if (ownbackstore)
629                    XFreePixmap(display, backstore);
630    
631            XFreeGC(display, gc);
632            XCloseDisplay(display);
633            display = NULL;
634    }
635    
636    BOOL
637    ui_create_window(void)
638    {
639            XSetWindowAttributes attribs;
640            XClassHint *classhints;
641            XSizeHints *sizehints;
642            int wndwidth, wndheight;
643            long input_mask, ic_input_mask;
644            XEvent xevent;
645    
646            wndwidth = fullscreen ? WidthOfScreen(screen) : width;
647            wndheight = fullscreen ? HeightOfScreen(screen) : height;
648    
649            attribs.background_pixel = BlackPixelOfScreen(screen);
650            attribs.backing_store = ownbackstore ? NotUseful : Always;
651            attribs.override_redirect = fullscreen;
652    
653            wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
654                                0, CopyFromParent, InputOutput, CopyFromParent,
655                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
656    
657          XStoreName(display, wnd, title);          XStoreName(display, wnd, title);
658    
659            if (hide_decorations)
660                    mwm_hide_decorations();
661    
662          classhints = XAllocClassHint();          classhints = XAllocClassHint();
663          if (classhints != NULL)          if (classhints != NULL)
   
664          {          {
665                  classhints->res_name = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
                 classhints->res_class = "rdesktop";  
666                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(display, wnd, classhints);
667                  XFree(classhints);                  XFree(classhints);
668          }          }
# Line 168  ui_create_window(char *title) Line 670  ui_create_window(char *title)
670          sizehints = XAllocSizeHints();          sizehints = XAllocSizeHints();
671          if (sizehints)          if (sizehints)
672          {          {
673                  sizehints->flags =                  sizehints->flags = PMinSize | PMaxSize;
674                          PPosition | PSize | PMinSize | PMaxSize | PBaseSize;                  sizehints->min_width = sizehints->max_width = width;
675                  sizehints->min_width = width;                  sizehints->min_height = sizehints->max_height = height;
                 sizehints->max_width = width;  
                 sizehints->min_height = height;  
                 sizehints->max_height = height;  
                 sizehints->base_width = width;  
                 sizehints->base_height = height;  
676                  XSetWMNormalHints(display, wnd, sizehints);                  XSetWMNormalHints(display, wnd, sizehints);
677                  XFree(sizehints);                  XFree(sizehints);
678          }          }
679    
680          input_mask = KeyPressMask | KeyReleaseMask;          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
681          input_mask |= ButtonPressMask | ButtonReleaseMask;                  VisibilityChangeMask | FocusChangeMask;
682          if (motion)  
683            if (sendmotion)
684                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
685            if (ownbackstore)
686                    input_mask |= ExposureMask;
687            if (fullscreen || grab_keyboard)
688                    input_mask |= EnterWindowMask;
689          if (grab_keyboard)          if (grab_keyboard)
690                  input_mask |= EnterWindowMask | LeaveWindowMask;                  input_mask |= LeaveWindowMask;
691    
692          XSelectInput(display, wnd, input_mask);          if (IM != NULL)
693          gc = XCreateGC(display, wnd, 0, NULL);          {
694                    IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
695                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
696    
697                    if ((IC != NULL)
698                        && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
699                            input_mask |= ic_input_mask;
700            }
701    
702            XSelectInput(display, wnd, input_mask);
703          XMapWindow(display, wnd);          XMapWindow(display, wnd);
704    
705            /* wait for VisibilityNotify */
706            do
707            {
708                    XMaskEvent(display, VisibilityChangeMask, &xevent);
709            }
710            while (xevent.type != VisibilityNotify);
711    
712            focused = False;
713            mouse_in_wnd = False;
714    
715            /* handle the WM_DELETE_WINDOW protocol */
716            protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
717            kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
718            XSetWMProtocols(display, wnd, &kill_atom, 1);
719    
720          return True;          return True;
721  }  }
722    
723  void  void
724  ui_destroy_window()  ui_destroy_window(void)
725  {  {
726          XFreeGC(display, gc);          if (IC != NULL)
727                    XDestroyIC(IC);
728    
729          XDestroyWindow(display, wnd);          XDestroyWindow(display, wnd);
         XCloseDisplay(display);  
         display = NULL;  
730  }  }
731    
732  static uint8  void
733  xwin_translate_key(unsigned long key)  xwin_toggle_fullscreen(void)
734  {  {
735          DEBUG("KEY(code=0x%lx)\n", key);          Pixmap contents = 0;
736    
737          if ((key > 8) && (key <= 0x60))          if (!ownbackstore)
738                  return (key - 8);          {
739                    /* need to save contents of window */
740                    contents = XCreatePixmap(display, wnd, width, height, depth);
741                    XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
742            }
743    
744          switch (key)          ui_destroy_window();
745          {          fullscreen = !fullscreen;
746                  case 0x61:      /* home */          ui_create_window();
                         return 0x47 | 0x80;  
                 case 0x62:      /* up arrow */  
                         return 0x48 | 0x80;  
                 case 0x63:      /* page up */  
                         return 0x49 | 0x80;  
                 case 0x64:      /* left arrow */  
                         return 0x4b | 0x80;  
                 case 0x66:      /* right arrow */  
                         return 0x4d | 0x80;  
                 case 0x67:      /* end */  
                         return 0x4f | 0x80;  
                 case 0x68:      /* down arrow */  
                         return 0x50 | 0x80;  
                 case 0x69:      /* page down */  
                         return 0x51 | 0x80;  
                 case 0x6a:      /* insert */  
                         return 0x52 | 0x80;  
                 case 0x6b:      /* delete */  
                         return 0x53 | 0x80;  
                 case 0x6c:      /* keypad enter */  
                         return 0x1c | 0x80;  
                 case 0x6d:      /* right ctrl */  
                         return 0x1d | 0x80;  
                 case 0x6f:      /* ctrl - print screen */  
                         return 0x37 | 0x80;  
                 case 0x70:      /* keypad '/' */  
                         return 0x35 | 0x80;  
                 case 0x71:      /* right alt */  
                         return 0x38 | 0x80;  
                 case 0x72:      /* ctrl break */  
                         return 0x46 | 0x80;  
                 case 0x73:      /* left window key */  
                         return 0xff;    /* real scancode is 5b */  
                 case 0x74:      /* right window key */  
                         return 0xff;    /* real scancode is 5c */  
                 case 0x75:      /* menu key */  
                         return 0x5d | 0x80;  
         }  
   
         return 0;  
 }  
   
 static uint16  
 xwin_translate_mouse(unsigned long button)  
 {  
         switch (button)  
         {  
                 case Button1:   /* left */  
                         return MOUSE_FLAG_BUTTON1;  
                 case Button2:   /* middle */  
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3:   /* right */  
                         return MOUSE_FLAG_BUTTON2;  
         }  
   
         return 0;  
 }  
   
 void  
 ui_process_events()  
 {  
         XEvent event;  
         uint8 scancode;  
         uint16 button;  
         uint32 ev_time;  
747    
748          if (display == NULL)          XDefineCursor(display, wnd, current_cursor);
749                  return;  
750            if (!ownbackstore)
751            {
752                    XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
753                    XFreePixmap(display, contents);
754            }
755    }
756    
757    /* Process all events in Xlib queue
758       Returns 0 after user quit, 1 otherwise */
759    static int
760    xwin_process_events(void)
761    {
762            XEvent xevent;
763            KeySym keysym;
764            uint16 button, flags;
765            uint32 ev_time;
766            key_translation tr;
767            char str[256];
768            Status status;
769            unsigned int state;
770            Window wdummy;
771            int dummy;
772    
773          while (XCheckWindowEvent(display, wnd, ~0, &event))          while (XPending(display) > 0)
774          {          {
775                  ev_time = time(NULL);                  XNextEvent(display, &xevent);
776    
777                  switch (event.type)                  if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
778                  {                  {
779                            DEBUG_KBD(("Filtering event\n"));
780                            continue;
781                    }
782    
783                    flags = 0;
784    
785                    switch (xevent.type)
786                    {
787                            case ClientMessage:
788                                    /* the window manager told us to quit */
789                                    if ((xevent.xclient.message_type == protocol_atom)
790                                        && (xevent.xclient.data.l[0] == kill_atom))
791                                            /* Quit */
792                                            return 0;
793                                    break;
794    
795                          case KeyPress:                          case KeyPress:
796                                  scancode = xwin_translate_key(event.xkey.keycode);                                  if (IC != NULL)
797                                  if (scancode == 0)                                          /* Multi_key compatible version */
798                                    {
799                                            XmbLookupString(IC,
800                                                            (XKeyPressedEvent *) &
801                                                            xevent, str, sizeof(str), &keysym, &status);
802                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
803                                            {
804                                                    error("XmbLookupString failed with status 0x%x\n",
805                                                          status);
806                                                    break;
807                                            }
808                                    }
809                                    else
810                                    {
811                                            /* Plain old XLookupString */
812                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
813                                            XLookupString((XKeyEvent *) & xevent,
814                                                          str, sizeof(str), &keysym, NULL);
815                                    }
816    
817                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
818                                               get_ksname(keysym)));
819    
820                                    ev_time = time(NULL);
821                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
822                                          break;                                          break;
823    
824                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  tr = xkeymap_translate_key(keysym,
825                                                 scancode, 0);                                                             xevent.xkey.keycode, xevent.xkey.state);
826    
827                                    if (tr.scancode == 0)
828                                            break;
829    
830                                    ensure_remote_modifiers(ev_time, tr);
831    
832                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
833                                  break;                                  break;
834    
835                          case KeyRelease:                          case KeyRelease:
836                                  scancode = xwin_translate_key(event.xkey.keycode);                                  XLookupString((XKeyEvent *) & xevent, str,
837                                  if (scancode == 0)                                                sizeof(str), &keysym, NULL);
838    
839                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
840                                               get_ksname(keysym)));
841    
842                                    ev_time = time(NULL);
843                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
844                                          break;                                          break;
845    
846                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  tr = xkeymap_translate_key(keysym,
847                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                             xevent.xkey.keycode, xevent.xkey.state);
                                                scancode, 0);  
                                 break;  
848    
849                          case ButtonPress:                                  if (tr.scancode == 0)
                                 button = xwin_translate_mouse(event.xbutton.button);  
                                 if (button == 0)  
850                                          break;                                          break;
851    
852                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
                                                button | MOUSE_FLAG_DOWN,  
                                                event.xbutton.x,  
                                                event.xbutton.y);  
853                                  break;                                  break;
854    
855                            case ButtonPress:
856                                    flags = MOUSE_FLAG_DOWN;
857                                    /* fall through */
858    
859                          case ButtonRelease:                          case ButtonRelease:
860                                  button = xwin_translate_mouse(event.xbutton.button);                                  button = xkeymap_translate_button(xevent.xbutton.button);
861                                  if (button == 0)                                  if (button == 0)
862                                          break;                                          break;
863    
864                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
865                                                 button,                                  if (xevent.xbutton.y < win_button_size)
866                                                 event.xbutton.x,                                  {
867                                                 event.xbutton.y);                                          /* Stop moving window when button is released, regardless of cursor position */
868                                            if (moving_wnd && (xevent.type == ButtonRelease))
869                                                    moving_wnd = False;
870    
871                                            /*  Check from right to left: */
872    
873                                            if (xevent.xbutton.x >= width - win_button_size)
874                                            {
875                                                    /* The close button, continue */
876                                                    ;
877                                            }
878                                            else if (xevent.xbutton.x >= width - win_button_size * 2)
879                                            {
880                                                    /* The maximize/restore button. Do not send to
881                                                       server.  It might be a good idea to change the
882                                                       cursor or give some other visible indication
883                                                       that rdesktop inhibited this click */
884                                                    break;
885                                            }
886                                            else if (xevent.xbutton.x >= width - win_button_size * 3)
887                                            {
888                                                    /* The minimize button. Iconify window. */
889                                                    XIconifyWindow(display, wnd,
890                                                                   DefaultScreen(display));
891                                                    break;
892                                            }
893                                            else if (xevent.xbutton.x <= win_button_size)
894                                            {
895                                                    /* The system menu. Ignore. */
896                                                    break;
897                                            }
898                                            else
899                                            {
900                                                    /* The title bar. */
901                                                    if ((xevent.type == ButtonPress) && !fullscreen
902                                                        && hide_decorations)
903                                                    {
904                                                            moving_wnd = True;
905                                                            move_x_offset = xevent.xbutton.x;
906                                                            move_y_offset = xevent.xbutton.y;
907                                                    }
908                                                    break;
909    
910                                            }
911                                    }
912    
913                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
914                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
915                                  break;                                  break;
916    
917                          case MotionNotify:                          case MotionNotify:
918                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (moving_wnd)
919                                                 MOUSE_FLAG_MOVE,                                  {
920                                                 event.xmotion.x,                                          XMoveWindow(display, wnd,
921                                                 event.xmotion.y);                                                      xevent.xmotion.x_root - move_x_offset,
922                                                        xevent.xmotion.y_root - move_y_offset);
923                                            break;
924                                    }
925    
926                                    if (fullscreen && !focused)
927                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
928                                                           CurrentTime);
929                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
930                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
931                                    break;
932    
933                            case FocusIn:
934                                    if (xevent.xfocus.mode == NotifyGrab)
935                                            break;
936                                    focused = True;
937                                    XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
938                                                  &dummy, &dummy, &state);
939                                    reset_modifier_keys(state);
940                                    if (grab_keyboard && mouse_in_wnd)
941                                            XGrabKeyboard(display, wnd, True,
942                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
943                                    break;
944    
945                            case FocusOut:
946                                    if (xevent.xfocus.mode == NotifyUngrab)
947                                            break;
948                                    focused = False;
949                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
950                                            XUngrabKeyboard(display, CurrentTime);
951                                  break;                                  break;
952    
953                          case EnterNotify:                          case EnterNotify:
954                                  if (grab_keyboard)                                  /* we only register for this event when in fullscreen mode */
955                                          xwin_grab_keyboard();                                  /* or grab_keyboard */
956                                    mouse_in_wnd = True;
957                                    if (fullscreen)
958                                    {
959                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
960                                                           CurrentTime);
961                                            break;
962                                    }
963                                    if (focused)
964                                            XGrabKeyboard(display, wnd, True,
965                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
966                                  break;                                  break;
967    
968                          case LeaveNotify:                          case LeaveNotify:
969                                  if (grab_keyboard)                                  /* we only register for this event when grab_keyboard */
970                                          xwin_ungrab_keyboard();                                  mouse_in_wnd = False;
971                                    XUngrabKeyboard(display, CurrentTime);
972                                    break;
973    
974                            case Expose:
975                                    XCopyArea(display, backstore, wnd, gc,
976                                              xevent.xexpose.x, xevent.xexpose.y,
977                                              xevent.xexpose.width,
978                                              xevent.xexpose.height,
979                                              xevent.xexpose.x, xevent.xexpose.y);
980                                    break;
981    
982                            case MappingNotify:
983                                    /* Refresh keyboard mapping if it has changed. This is important for
984                                       Xvnc, since it allocates keycodes dynamically */
985                                    if (xevent.xmapping.request == MappingKeyboard
986                                        || xevent.xmapping.request == MappingModifier)
987                                            XRefreshKeyboardMapping(&xevent.xmapping);
988    
989                                    if (xevent.xmapping.request == MappingModifier)
990                                    {
991                                            XFreeModifiermap(mod_map);
992                                            mod_map = XGetModifierMapping(display);
993                                    }
994                                  break;                                  break;
995    
996                  }                  }
997          }          }
998            /* Keep going */
999            return 1;
1000    }
1001    
1002    /* Returns 0 after user quit, 1 otherwise */
1003    int
1004    ui_select(int rdp_socket)
1005    {
1006            int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
1007            fd_set rfds;
1008    
1009            FD_ZERO(&rfds);
1010    
1011            while (True)
1012            {
1013                    /* Process any events already waiting */
1014                    if (!xwin_process_events())
1015                            /* User quit */
1016                            return 0;
1017    
1018                    FD_ZERO(&rfds);
1019                    FD_SET(rdp_socket, &rfds);
1020                    FD_SET(x_socket, &rfds);
1021    
1022                    switch (select(n, &rfds, NULL, NULL, NULL))
1023                    {
1024                            case -1:
1025                                    error("select: %s\n", strerror(errno));
1026    
1027                            case 0:
1028                                    continue;
1029                    }
1030    
1031                    if (FD_ISSET(rdp_socket, &rfds))
1032                            return 1;
1033            }
1034  }  }
1035    
1036  void  void
# Line 357  ui_move_pointer(int x, int y) Line 1040  ui_move_pointer(int x, int y)
1040  }  }
1041    
1042  HBITMAP  HBITMAP
1043  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1044  {  {
1045          XImage *image;          XImage *image;
1046          Pixmap bitmap;          Pixmap bitmap;
1047          uint8 *tdata;          uint8 *tdata;
1048          tdata = (private_colormap ? data : translate(width, height, data));  
1049            tdata = (owncolmap ? data : translate_image(width, height, data));
1050          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(display, wnd, width, height, depth);
1051          image =          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1052                  XCreateImage(display, visual,                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
                              depth, ZPixmap,  
                              0, tdata, width, height, BitmapPad(display), 0);  
1053    
         xwin_set_function(ROP2_COPY);  
1054          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1055    
1056          XFree(image);          XFree(image);
1057          if (!private_colormap)          if (!owncolmap)
1058                  xfree(tdata);                  xfree(tdata);
1059          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1060  }  }
1061    
1062  void  void
1063  ui_paint_bitmap(int x, int y, int cx, int cy,  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
                 int width, int height, uint8 *data)  
1064  {  {
1065          XImage *image;          XImage *image;
1066          uint8 *tdata =          uint8 *tdata;
1067                  (private_colormap ? data : translate(width, height, data));          tdata = (owncolmap ? data : translate_image(width, height, data));
1068          image =          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1069                  XCreateImage(display, visual, depth, ZPixmap, 0, tdata, width,                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
                              height, BitmapPad(display), 0);  
   
         xwin_set_function(ROP2_COPY);  
   
         /* Window */  
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
         XFree(image);  
         if (!private_colormap)  
                 xfree(tdata);  
 }  
   
 void  
 ui_destroy_bitmap(HBITMAP bmp)  
 {  
         XFreePixmap(display, (Pixmap) bmp);  
 }  
1070    
1071  HCURSOR          if (ownbackstore)
 ui_create_cursor(unsigned int x, unsigned int y, int width,  
                  int height, uint8 *mask, uint8 *data)  
 {  
         XImage *imagecursor;  
         XImage *imagemask;  
         Pixmap maskbitmap, cursorbitmap;  
         Cursor cursor;  
         XColor bg, fg;  
         GC lgc;  
         int i, x1, y1, scanlinelen;  
         uint8 *cdata, *cmask;  
         uint8 c;  
         cdata = (uint8 *) malloc(sizeof(uint8) * width * height);  
         if (!cdata)  
                 return NULL;  
         scanlinelen = (width + 7) >> 3;  
         cmask = (uint8 *) malloc(sizeof(uint8) * scanlinelen * height);  
         if (!cmask)  
1072          {          {
1073                  free(cdata);                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1074                  return NULL;                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
         }  
         i = (height - 1) * scanlinelen;  
   
         if (!screen_msbfirst)  
         {  
                 while (i >= 0)  
                 {  
                         for (x1 = 0; x1 < scanlinelen; x1++)  
                         {  
                                 c = *(mask++);  
                                 cmask[i + x1] =  
                                         ((c & 0x1) << 7) | ((c & 0x2) << 5) |  
                                         ((c & 0x4) << 3) | ((c & 0x8) << 1) |  
                                         ((c & 0x10) >> 1) | ((c & 0x20) >> 3)  
                                         | ((c & 0x40) >> 5) | ((c & 0x80) >>  
                                                                7);  
                         }  
                         i -= scanlinelen;  
                 }  
1075          }          }
1076          else          else
1077          {          {
1078                  while (i >= 0)                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
                 {  
                         for (x1 = 0; x1 < scanlinelen; x1++)  
                         {  
                                 cmask[i + x1] = *(mask++);  
                         }  
                         i -= scanlinelen;  
                 }  
1079          }          }
1080    
1081            XFree(image);
1082          fg.red = 0;          if (!owncolmap)
1083          fg.blue = 0;                  xfree(tdata);
         fg.green = 0;  
         fg.flags = DoRed | DoBlue | DoGreen;  
         bg.red = 65535;  
         bg.blue = 65535;  
         bg.green = 65535;  
         bg.flags = DoRed | DoBlue | DoGreen;  
         maskbitmap = XCreatePixmap(display, wnd, width, height, 1);  
         cursorbitmap = XCreatePixmap(display, wnd, width, height, 1);  
         lgc = XCreateGC(display, maskbitmap, 0, NULL);  
         XSetFunction(display, lgc, GXcopy);  
         imagemask =  
                 XCreateImage(display, visual, 1, XYBitmap, 0, cmask, width,  
                              height, 8, 0);  
         imagecursor =  
                 XCreateImage(display, visual, 1, XYBitmap, 0, cdata, width,  
                              height, 8, 0);  
         for (y1 = height - 1; y1 >= 0; y1--)  
                 for (x1 = 0; x1 < width; x1++)  
                 {  
                         if (data[0] >= 0x80 || data[1] >= 0x80  
                             || data[2] >= 0x80)  
                                 if (XGetPixel(imagemask, x1, y1))  
   
                                 {  
                                         XPutPixel(imagecursor, x1, y1, 0);  
                                         XPutPixel(imagemask, x1, y1, 0);        /* mask is blank for text cursor! */  
                                 }  
   
                                 else  
                                         XPutPixel(imagecursor, x1, y1, 1);  
   
                         else  
                                 XPutPixel(imagecursor, x1, y1,  
                                           XGetPixel(imagemask, x1, y1));  
                         data += 3;  
                 }  
         XPutImage(display, maskbitmap, lgc, imagemask, 0, 0, 0, 0, width,  
                   height);  
         XPutImage(display, cursorbitmap, lgc, imagecursor, 0, 0, 0, 0, width,  
                   height); XFree(imagemask);  
         XFree(imagecursor);  
         free(cmask);  
         free(cdata);  
         XFreeGC(display, lgc);  
         cursor =  
                 XCreatePixmapCursor(display, cursorbitmap, maskbitmap, &fg,  
                                     &bg, x, y);  
         XFreePixmap(display, maskbitmap);  
         XFreePixmap(display, cursorbitmap);  
         return (HCURSOR) cursor;  
 }  
   
 void  
 ui_set_cursor(HCURSOR cursor)  
 {  
         XDefineCursor(display, wnd, (Cursor) cursor);  
1084  }  }
1085    
1086  void  void
1087  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_bitmap(HBITMAP bmp)
1088  {  {
1089          XFreeCursor(display, (Cursor) cursor);          XFreePixmap(display, (Pixmap) bmp);
1090  }  }
1091    
1092  HGLYPH  HGLYPH
1093  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1094  {  {
1095          XImage *image;          XImage *image;
1096          Pixmap bitmap;          Pixmap bitmap;
# Line 538  ui_create_glyph(int width, int height, u Line 1102  ui_create_glyph(int width, int height, u
1102          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
1103          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
1104    
1105          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1106                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1107          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1108          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1109          XInitImage(image);          XInitImage(image);
1110    
         XSetFunction(display, gc, GXcopy);  
1111          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1112    
1113          XFree(image);          XFree(image);
1114          XFreeGC(display, gc);          XFreeGC(display, gc);
   
1115          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1116  }  }
1117    
# Line 558  ui_destroy_glyph(HGLYPH glyph) Line 1121  ui_destroy_glyph(HGLYPH glyph)
1121          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(display, (Pixmap) glyph);
1122  }  }
1123    
1124  HCOLOURMAP  HCURSOR
1125  ui_create_colourmap(COLOURMAP *colours)  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1126                     uint8 * andmask, uint8 * xormask)
1127  {  {
1128          if (!private_colormap)          HGLYPH maskglyph, cursorglyph;
1129            XColor bg, fg;
1130            Cursor xcursor;
1131            uint8 *cursor, *pcursor;
1132            uint8 *mask, *pmask;
1133            uint8 nextbit;
1134            int scanline, offset;
1135            int i, j;
1136    
1137            scanline = (width + 7) / 8;
1138            offset = scanline * height;
1139    
1140            cursor = xmalloc(offset);
1141            memset(cursor, 0, offset);
1142    
1143            mask = xmalloc(offset);
1144            memset(mask, 0, offset);
1145    
1146            /* approximate AND and XOR masks with a monochrome X pointer */
1147            for (i = 0; i < height; i++)
1148          {          {
1149                  COLOURENTRY *entry;                  offset -= scanline;
1150                  int i, ncolours = colours->ncolours;                  pcursor = &cursor[offset];
1151                  uint32 *nc = xmalloc(sizeof(*colmap) * ncolours);                  pmask = &mask[offset];
1152    
1153                    for (j = 0; j < scanline; j++)
1154                    {
1155                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1156                            {
1157                                    if (xormask[0] || xormask[1] || xormask[2])
1158                                    {
1159                                            *pcursor |= (~(*andmask) & nextbit);
1160                                            *pmask |= nextbit;
1161                                    }
1162                                    else
1163                                    {
1164                                            *pcursor |= ((*andmask) & nextbit);
1165                                            *pmask |= (~(*andmask) & nextbit);
1166                                    }
1167    
1168                                    xormask += 3;
1169                            }
1170    
1171                            andmask++;
1172                            pcursor++;
1173                            pmask++;
1174                    }
1175            }
1176    
1177            fg.red = fg.blue = fg.green = 0xffff;
1178            bg.red = bg.blue = bg.green = 0x0000;
1179            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1180    
1181            cursorglyph = ui_create_glyph(width, height, cursor);
1182            maskglyph = ui_create_glyph(width, height, mask);
1183    
1184            xcursor =
1185                    XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1186                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1187    
1188            ui_destroy_glyph(maskglyph);
1189            ui_destroy_glyph(cursorglyph);
1190            xfree(mask);
1191            xfree(cursor);
1192            return (HCURSOR) xcursor;
1193    }
1194    
1195    void
1196    ui_set_cursor(HCURSOR cursor)
1197    {
1198            current_cursor = (Cursor) cursor;
1199            XDefineCursor(display, wnd, current_cursor);
1200    }
1201    
1202    void
1203    ui_destroy_cursor(HCURSOR cursor)
1204    {
1205            XFreeCursor(display, (Cursor) cursor);
1206    }
1207    
1208    #define MAKE_XCOLOR(xc,c) \
1209                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
1210                    (xc)->green = ((c)->green << 8) | (c)->green; \
1211                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1212                    (xc)->flags = DoRed | DoGreen | DoBlue;
1213    
1214    
1215    HCOLOURMAP
1216    ui_create_colourmap(COLOURMAP * colours)
1217    {
1218            COLOURENTRY *entry;
1219            int i, ncolours = colours->ncolours;
1220            if (!owncolmap)
1221            {
1222                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
1223                    XColor xentry;
1224                    XColor xc_cache[256];
1225                    uint32 colour;
1226                    int colLookup = 256;
1227                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1228                  {                  {
                         XColor xc;  
1229                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1230                          xc.red = entry->red << 8;                          MAKE_XCOLOR(&xentry, entry);
1231                          xc.green = entry->green << 8;  
1232                          xc.blue = entry->blue << 8;                          if (XAllocColor(display, xcolmap, &xentry) == 0)
1233                          XAllocColor(display,                          {
1234                                      DefaultColormap(display,                                  /* Allocation failed, find closest match. */
1235                                                      DefaultScreen(display)),                                  int j = 256;
1236                                      &xc);                                  int nMinDist = 3 * 256 * 256;
1237                          /* XXX Check return value */                                  long nDist = nMinDist;
1238                          nc[i] = xc.pixel;  
1239                                    /* only get the colors once */
1240                                    while (colLookup--)
1241                                    {
1242                                            xc_cache[colLookup].pixel = colLookup;
1243                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1244                                                    xc_cache[colLookup].blue = 0;
1245                                            xc_cache[colLookup].flags = 0;
1246                                            XQueryColor(display,
1247                                                        DefaultColormap(display,
1248                                                                        DefaultScreen(display)),
1249                                                        &xc_cache[colLookup]);
1250                                    }
1251                                    colLookup = 0;
1252    
1253                                    /* approximate the pixel */
1254                                    while (j--)
1255                                    {
1256                                            if (xc_cache[j].flags)
1257                                            {
1258                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1259                                                             (long) (xentry.red >> 8)) *
1260                                                            ((long) (xc_cache[j].red >> 8) -
1261                                                             (long) (xentry.red >> 8)) +
1262                                                            ((long) (xc_cache[j].green >> 8) -
1263                                                             (long) (xentry.green >> 8)) *
1264                                                            ((long) (xc_cache[j].green >> 8) -
1265                                                             (long) (xentry.green >> 8)) +
1266                                                            ((long) (xc_cache[j].blue >> 8) -
1267                                                             (long) (xentry.blue >> 8)) *
1268                                                            ((long) (xc_cache[j].blue >> 8) -
1269                                                             (long) (xentry.blue >> 8));
1270                                            }
1271                                            if (nDist < nMinDist)
1272                                            {
1273                                                    nMinDist = nDist;
1274                                                    xentry.pixel = j;
1275                                            }
1276                                    }
1277                            }
1278                            colour = xentry.pixel;
1279    
1280                            /* update our cache */
1281                            if (xentry.pixel < 256)
1282                            {
1283                                    xc_cache[xentry.pixel].red = xentry.red;
1284                                    xc_cache[xentry.pixel].green = xentry.green;
1285                                    xc_cache[xentry.pixel].blue = xentry.blue;
1286    
1287                            }
1288    
1289    
1290                            /* byte swap here to make translate_image faster */
1291                            map[i] = translate_colour(colour);
1292                  }                  }
1293                  return nc;                  return map;
1294          }          }
1295          else          else
1296          {          {
                 COLOURENTRY *entry;  
1297                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
1298                  Colormap map;                  Colormap map;
1299                  int i, ncolours = colours->ncolours;  
1300                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = xmalloc(sizeof(XColor) * ncolours);
1301                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1302                  {                  {
1303                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1304                          xentry = &xcolours[i];                          xentry = &xcolours[i];
   
1305                          xentry->pixel = i;                          xentry->pixel = i;
1306                          xentry->red = entry->red << 8;                          MAKE_XCOLOR(xentry, entry);
                         xentry->blue = entry->blue << 8;  
                         xentry->green = entry->green << 8;  
                         xentry->flags = DoRed | DoBlue | DoGreen;  
1307                  }                  }
1308    
1309                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(display, wnd, visual, AllocAll);
# Line 612  ui_create_colourmap(COLOURMAP *colours) Line 1317  ui_create_colourmap(COLOURMAP *colours)
1317  void  void
1318  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1319  {  {
1320          XFreeColormap(display, (Colormap) map);          if (!owncolmap)
1321                    xfree(map);
1322            else
1323                    XFreeColormap(display, (Colormap) map);
1324  }  }
1325    
1326  void  void
1327  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1328  {  {
1329            if (!owncolmap)
         /* XXX, change values of all pixels on the screen if the new colmap  
          * doesn't have the same values as the old one? */  
         if (!private_colormap)  
1330                  colmap = map;                  colmap = map;
1331          else          else
         {  
1332                  XSetWindowColormap(display, wnd, (Colormap) map);                  XSetWindowColormap(display, wnd, (Colormap) map);
                 if (fullscreen)  
                         XInstallColormap(display, (Colormap) map);  
         }  
1333  }  }
1334    
1335  void  void
# Line 644  ui_set_clip(int x, int y, int cx, int cy Line 1345  ui_set_clip(int x, int y, int cx, int cy
1345  }  }
1346    
1347  void  void
1348  ui_reset_clip()  ui_reset_clip(void)
1349  {  {
1350          XRectangle rect;          XRectangle rect;
1351    
# Line 656  ui_reset_clip() Line 1357  ui_reset_clip()
1357  }  }
1358    
1359  void  void
1360  ui_bell()  ui_bell(void)
1361  {  {
1362          XBell(display, 0);          XBell(display, 0);
1363  }  }
# Line 665  void Line 1366  void
1366  ui_destblt(uint8 opcode,  ui_destblt(uint8 opcode,
1367             /* dest */ int x, int y, int cx, int cy)             /* dest */ int x, int y, int cx, int cy)
1368  {  {
1369          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1370            FILL_RECTANGLE(x, y, cx, cy);
1371          XFillRectangle(display, wnd, gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
1372  }  }
1373    
1374  void  void
1375  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1376            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1377            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1378  {  {
         Display *dpy = display;  
1379          Pixmap fill;          Pixmap fill;
1380          uint8 i, ipattern[8];          uint8 i, ipattern[8];
1381    
1382          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1383    
1384          switch (brush->style)          switch (brush->style)
1385          {          {
1386                  case 0: /* Solid */                  case 0: /* Solid */
1387                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_FOREGROUND(fgcolour);
1388                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1389                          break;                          break;
1390    
1391                  case 3: /* Pattern */                  case 3: /* Pattern */
1392                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
1393                                  ipattern[i] = ~brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
1394                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1395    
1396                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_FOREGROUND(bgcolour);
1397                          XSetBackground(dpy, gc, Ctrans(bgcolour));                          SET_BACKGROUND(fgcolour);
1398                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                          XSetFillStyle(display, gc, FillOpaqueStippled);
1399                          XSetStipple(dpy, gc, fill);                          XSetStipple(display, gc, fill);
1400                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1401    
1402                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1403    
1404                          XSetFillStyle(dpy, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
1405                            XSetTSOrigin(display, gc, 0, 0);
1406                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
1407                          break;                          break;
1408    
1409                  default:                  default:
1410                          NOTIMP("brush %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
1411          }          }
1412    
1413            RESET_FUNCTION(opcode);
1414  }  }
1415    
1416  void  void
# Line 714  ui_screenblt(uint8 opcode, Line 1418  ui_screenblt(uint8 opcode,
1418               /* dest */ int x, int y, int cx, int cy,               /* dest */ int x, int y, int cx, int cy,
1419               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
1420  {  {
1421          xwin_set_function(opcode);          SET_FUNCTION(opcode);
   
1422          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1423            if (ownbackstore)
1424                    XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1425            RESET_FUNCTION(opcode);
1426  }  }
1427    
1428  void  void
# Line 724  ui_memblt(uint8 opcode, Line 1430  ui_memblt(uint8 opcode,
1430            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1431            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1432  {  {
1433          xwin_set_function(opcode);          SET_FUNCTION(opcode);
   
1434          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1435            if (ownbackstore)
1436                    XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1437            RESET_FUNCTION(opcode);
1438  }  }
1439    
1440  void  void
1441  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1442            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1443            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1444            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1445  {  {
1446          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1447             comes up with a more efficient way of doing it I am using cases. */             comes up with a more efficient way of doing it I am using cases. */
# Line 742  ui_triblt(uint8 opcode, Line 1450  ui_triblt(uint8 opcode,
1450          {          {
1451                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1452                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1453                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1454                          break;                          break;
1455    
1456                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1457                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1458                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1459                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1460                          break;                          break;
1461    
1462                  case 0xc0:                  case 0xc0:      /* PSa */
1463                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1464                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1465                          break;                          break;
1466    
1467                  default:                  default:
1468                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
1469                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1470          }          }
1471  }  }
# Line 769  ui_triblt(uint8 opcode, Line 1473  ui_triblt(uint8 opcode,
1473  void  void
1474  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1475          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1476          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1477  {  {
1478          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1479            SET_FOREGROUND(pen->colour);
         XSetForeground(display, gc, Ctrans(pen->colour));  
1480          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1481            if (ownbackstore)
1482                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1483            RESET_FUNCTION(opcode);
1484  }  }
1485    
1486  void  void
# Line 782  ui_rect( Line 1488  ui_rect(
1488                 /* dest */ int x, int y, int cx, int cy,                 /* dest */ int x, int y, int cx, int cy,
1489                 /* brush */ int colour)                 /* brush */ int colour)
1490  {  {
1491          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(colour);
1492            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(display, gc, Ctrans(colour));  
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1493  }  }
1494    
1495    /* warning, this function only draws on wnd or backstore, not both */
1496  void  void
1497  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1498                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1499                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1500                int fgcolour)                int bgcolour, int fgcolour)
1501  {  {
1502          Pixmap pixmap = (Pixmap) glyph;          SET_FOREGROUND(fgcolour);
1503            SET_BACKGROUND(bgcolour);
         xwin_set_function(ROP2_COPY);  
   
   
         XSetForeground(display, gc, Ctrans(fgcolour));  
         switch (mixmode)  
         {  
                 case MIX_TRANSPARENT:  
                         XSetStipple(display, gc, pixmap);  
                         XSetFillStyle(display, gc, FillStippled);  
                         XSetTSOrigin(display, gc, x, y);  
                         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
                         XSetFillStyle(display, gc, FillSolid);  
                         break;  
1504    
1505                  case MIX_OPAQUE:          XSetFillStyle(display, gc,
1506                          XSetBackground(display, gc, Ctrans(bgcolour));                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1507  /*      XCopyPlane (display, pixmap, back_pixmap, back_gc, srcx, srcy, cx, cy, x, y, 1); */          XSetStipple(display, gc, (Pixmap) glyph);
1508                          XSetStipple(display, gc, pixmap);          XSetTSOrigin(display, gc, x, y);
1509                          XSetFillStyle(display, gc, FillOpaqueStippled);  
1510                          XSetTSOrigin(display, gc, x, y);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1511                          XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1512                          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(display, gc, FillSolid);
1513                          break;  }
1514    
1515                  default:  #define DO_GLYPH(ttext,idx) \
1516                          NOTIMP("mix %d\n", mixmode);  {\
1517          }    glyph = cache_get_font (font, ttext[idx]);\
1518      if (!(flags & TEXT2_IMPLICIT_X))\
1519        {\
1520          xyoffset = ttext[++idx];\
1521          if ((xyoffset & 0x80))\
1522            {\
1523              if (flags & TEXT2_VERTICAL) \
1524                y += ttext[idx+1] | (ttext[idx+2] << 8);\
1525              else\
1526                x += ttext[idx+1] | (ttext[idx+2] << 8);\
1527              idx += 2;\
1528            }\
1529          else\
1530            {\
1531              if (flags & TEXT2_VERTICAL) \
1532                y += xyoffset;\
1533              else\
1534                x += xyoffset;\
1535            }\
1536        }\
1537      if (glyph != NULL)\
1538        {\
1539          ui_draw_glyph (mixmode, x + glyph->offset,\
1540                         y + glyph->baseline,\
1541                         glyph->width, glyph->height,\
1542                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1543          if (flags & TEXT2_IMPLICIT_X)\
1544            x += glyph->width;\
1545        }\
1546  }  }
1547    
1548  void  void
1549  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1550               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
1551               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1552               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1553  {  {
1554          FONTGLYPH *glyph;          FONTGLYPH *glyph;
1555          int i, xyoffset;          int i, j, xyoffset;
1556            DATABLOB *entry;
1557    
1558          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(bgcolour);
         XSetForeground(display, gc, Ctrans(bgcolour));  
1559    
1560          if (boxcx > 1)          if (boxcx > 1)
1561                  XFillRectangle(display, wnd, gc, boxx, boxy, boxcx, boxcy);          {
1562                    FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1563            }
1564          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1565                  XFillRectangle(display, wnd, gc, clipx, clipy, clipcx, clipcy);          {
1566                    FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1567            }
1568    
1569          /* Paint text, character by character */          /* Paint text, character by character */
1570          for (i = 0; i < length; i++)          for (i = 0; i < length;)
1571          {          {
1572                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
   
1573                  {                  {
1574                          xyoffset = text[++i];                          case 0xff:
1575                          if ((xyoffset & 0x80))                                  if (i + 2 < length)
1576                          {                                          cache_put_text(text[i + 1], text, text[i + 2]);
                                 if (flags & 0x04)       /* vertical text */  
                                         y += text[++i] | (text[++i] << 8);  
1577                                  else                                  else
1578                                          x += text[++i] | (text[++i] << 8);                                  {
1579                          }                                          error("this shouldn't be happening\n");
1580                          else                                          exit(1);
1581                          {                                  }
1582                                  if (flags & 0x04)       /* vertical text */                                  /* this will move pointer from start to first character after FF command */
1583                                          y += xyoffset;                                  length -= i + 3;
1584                                  else                                  text = &(text[i + 3]);
1585                                          x += xyoffset;                                  i = 0;
1586                          }                                  break;
1587    
1588                  }                          case 0xfe:
1589                  if (glyph != NULL)                                  entry = cache_get_text(text[i + 1]);
1590                  {                                  if (entry != NULL)
1591                          ui_draw_glyph(mixmode, x + (short) glyph->offset,                                  {
1592                                        y + (short) glyph->baseline,                                          if ((((uint8 *) (entry->data))[1] ==
1593                                        glyph->width, glyph->height,                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
1594                                        glyph->pixmap, 0, 0,                                          {
1595                                        bgcolour, fgcolour);                                                  if (flags & TEXT2_VERTICAL)
1596                                                            y += text[i + 2];
1597                                                    else
1598                                                            x += text[i + 2];
1599                                            }
1600                                            for (j = 0; j < entry->size; j++)
1601                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1602                                    }
1603                                    if (i + 2 < length)
1604                                            i += 3;
1605                                    else
1606                                            i += 2;
1607                                    length -= i;
1608                                    /* this will move pointer from start to first character after FE command */
1609                                    text = &(text[i]);
1610                                    i = 0;
1611                                    break;
1612    
1613                          if (flags & TEXT2_IMPLICIT_X)                          default:
1614                                  x += glyph->width;                                  DO_GLYPH(text, i);
1615                                    i++;
1616                                    break;
1617                  }                  }
1618          }          }
1619            if (ownbackstore)
1620            {
1621                    if (boxcx > 1)
1622                            XCopyArea(display, backstore, wnd, gc, boxx,
1623                                      boxy, boxcx, boxcy, boxx, boxy);
1624                    else
1625                            XCopyArea(display, backstore, wnd, gc, clipx,
1626                                      clipy, clipcx, clipcy, clipx, clipy);
1627            }
1628  }  }
1629    
1630  void  void
# Line 887  ui_desktop_save(uint32 offset, int x, in Line 1633  ui_desktop_save(uint32 offset, int x, in
1633          Pixmap pix;          Pixmap pix;
1634          XImage *image;          XImage *image;
1635    
1636          pix = XCreatePixmap(display, wnd, cx, cy, depth);          if (ownbackstore)
1637          xwin_set_function(ROP2_COPY);          {
1638                    image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1639          XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);          }
1640          image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);          else
1641            {
1642                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
1643                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1644                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1645                    XFreePixmap(display, pix);
1646            }
1647    
1648          offset *= bpp/8;          offset *= bpp / 8;
1649          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
                           bpp/8, image->data);  
1650    
1651          XDestroyImage(image);          XDestroyImage(image);
         XFreePixmap(display, pix);  
1652  }  }
1653    
1654  void  void
# Line 907  ui_desktop_restore(uint32 offset, int x, Line 1657  ui_desktop_restore(uint32 offset, int x,
1657          XImage *image;          XImage *image;
1658          uint8 *data;          uint8 *data;
1659    
1660          offset *= bpp/8;          offset *= bpp / 8;
1661          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, bpp / 8);
1662          if (data == NULL)          if (data == NULL)
1663                  return;                  return;
         image =  
                 XCreateImage(display, visual,  
                              depth, ZPixmap,  
                              0, data, cx, cy, BitmapPad(display),  
                              cx * bpp/8);  
         xwin_set_function(ROP2_COPY);  
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
         XFree(image);  
 }  
1664    
1665  /* unroll defines, used to make the loops a bit more readable... */          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1666  #define unroll8Expr(uexp) uexp uexp uexp uexp uexp uexp uexp uexp                               (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
 #define unroll8Lefts(uexp) case 7: uexp \  
         case 6: uexp \  
         case 5: uexp \  
         case 4: uexp \  
         case 3: uexp \  
         case 2: uexp \  
         case 1: uexp  
   
 static uint8 *  
 translate(int width, int height, uint8 *data)  
 {  
         uint32 i;  
         uint32 size = width * height;  
         uint8 *d2 = xmalloc(size * bpp/8);  
         uint8 *d3 = d2;  
         uint32 pix;  
         i = (size & ~0x7);  
   
         /* XXX: where are the bits swapped??? */  
 #ifdef L_ENDIAN                 /* little-endian */  
         /* big-endian screen */  
         if (screen_msbfirst)  
         {  
                 switch (bpp)  
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix >> 24;  
                                                     *d3++ = pix >> 16;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix;) i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      24;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix >> 16;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix;) i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix;) i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                 }  
         }  
         else  
         {                       /* little-endian screen */  
                 switch (bpp)  
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(*((uint32 *) d3) =  
                                                     colmap[*data++];  
                                                     d3 += sizeof(uint32);  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(*  
                                                                      ((uint32  
                                                                        *) d3)  
 = colmap[*data++];  
 d3 += sizeof(uint32);  
                                         )}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                         )}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                 }  
         }  
1667    
1668  #else /* bigendian-compiled */          if (ownbackstore)
         if (screen_msbfirst)  
1669          {          {
1670                  /* big-endian screen */                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1671                  switch (bpp)                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(*((uint32 *) d3) =  
                                                     colmap[*data++];  
                                                     d3 += sizeof(uint32);  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(*  
                                                                      ((uint32  
                                                                        *) d3)  
 = colmap[*data++];  
 d3 += sizeof(uint32);  
                                         )}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                         )}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                 }  
1672          }          }
1673          else          else
1674          {          {
1675                  /* little-endian screen */                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
                 switch (bpp)  
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                     *d3++ = pix >> 24;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      24;)}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                         )}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                 }  
1676          }          }
 #endif  
1677    
1678          return d2;          XFree(image);
1679  }  }

Legend:
Removed from v.28  
changed lines
  Added in v.368

  ViewVC Help
Powered by ViewVC 1.1.26