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

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

  ViewVC Help
Powered by ViewVC 1.1.26