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

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

  ViewVC Help
Powered by ViewVC 1.1.26