/[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 64 by astrand, Thu Jul 18 16:38:31 2002 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X-Windows     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2001
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 20  Line 20 
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23    #include <X11/XKBlib.h>
24  #include <time.h>  #include <time.h>
25    #include <errno.h>
26  #include "rdesktop.h"  #include "rdesktop.h"
27    
28    extern char keymapname[16];
29    extern int keylayout;
30  extern int width;  extern int width;
31  extern int height;  extern int height;
32  extern BOOL motion;  extern BOOL sendmotion;
 extern BOOL grab_keyboard;  
33  extern BOOL fullscreen;  extern BOOL fullscreen;
 extern int private_colormap;  
34    
35  static int bpp;  Display *display;
36  static int depth;  XkbDescPtr xkb;
37  static Display *display;  static int x_socket;
38  static Window wnd;  static Window wnd;
39  static GC gc;  static GC gc;
40  static Visual *visual;  static Visual *visual;
41  static uint32 *colmap;  static int depth;
42    static int bpp;
 #define Ctrans(col) ( private_colormap ? col : colmap[col])  
43    
44  #define L_ENDIAN  /* endianness */
45  int screen_msbfirst = 0;  static BOOL host_be;
46    static BOOL xserver_be;
47    
48    /* software backing store */
49    static BOOL ownbackstore;
50    static Pixmap backstore;
51    
52    /* needed to keep track of the modifiers */
53    static unsigned int numlock_modifier_mask = 0;
54    static unsigned int key_down_state = 0;
55    
56    
57    #define DShift1Mask   (1<<0)
58    #define DLockMask     (1<<1)
59    #define DControl1Mask (1<<2)
60    #define DMod1Mask     (1<<3)
61    #define DMod2Mask     (1<<4)
62    #define DMod3Mask     (1<<5)
63    #define DMod4Mask     (1<<6)
64    #define DMod5Mask     (1<<7)
65    #define DShift2Mask   (1<<8)
66    #define DControl2Mask (1<<9)
67    #define DNumLockMask  (1<<10)
68    
69    #define FILL_RECTANGLE(x,y,cx,cy)\
70    { \
71            XFillRectangle(display, wnd, gc, x, y, cx, cy); \
72            if (ownbackstore) \
73                    XFillRectangle(display, backstore, gc, x, y, cx, cy); \
74    }
75    
76    /* colour maps */
77    static BOOL owncolmap;
78    static Colormap xcolmap;
79    static uint32 white;
80    static uint32 *colmap;
81    
82  static uint8 *translate(int width, int height, uint8 *data);  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )
83    #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
84    #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
85    
86  static int rop2_map[] = {  static int rop2_map[] = {
87          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 64  static int rop2_map[] = { Line 102  static int rop2_map[] = {
102          GXset                   /* 1 */          GXset                   /* 1 */
103  };  };
104    
105    #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
106    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
107    
108    void xwin_get_numlock_mask();
109    void xwin_mod_update(uint32 state, uint32 ev_time);
110    void xwin_mod_release(uint32 state, uint32 ev_time, uint32 scancode);
111    void xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode);
112    
113  static void  static void
114  xwin_set_function(uint8 rop2)  translate8(uint8 * data, uint8 * out, uint8 * end)
115  {  {
116          static uint8 last_rop2 = ROP2_COPY;          while (out < end)
117                    *(out++) = (uint8) colmap[*(data++)];
118    }
119    
120          if (last_rop2 != rop2)  static void
121    translate16(uint8 * data, uint16 * out, uint16 * end)
122    {
123            while (out < end)
124                    *(out++) = (uint16) colmap[*(data++)];
125    }
126    
127    /* little endian - conversion happens when colourmap is built */
128    static void
129    translate24(uint8 * data, uint8 * out, uint8 * end)
130    {
131            uint32 value;
132    
133            while (out < end)
134          {          {
135                  XSetFunction(display, gc, rop2_map[rop2]);                  value = colmap[*(data++)];
136                  last_rop2 = rop2;                  *(out++) = value;
137                    *(out++) = value >> 8;
138                    *(out++) = value >> 16;
139          }          }
140  }  }
141    
142  static void  static void
143  xwin_grab_keyboard()  translate32(uint8 * data, uint32 * out, uint32 * end)
144  {  {
145          XGrabKeyboard(display, wnd, True, GrabModeAsync, GrabModeAsync,          while (out < end)
146                        CurrentTime);                  *(out++) = colmap[*(data++)];
147  }  }
148    
149  static void  static uint8 *
150  xwin_ungrab_keyboard()  translate_image(int width, int height, uint8 * data)
151  {  {
152          XUngrabKeyboard(display, CurrentTime);          int size = width * height * bpp / 8;
153            uint8 *out = xmalloc(size);
154            uint8 *end = out + size;
155    
156            switch (bpp)
157            {
158                    case 8:
159                            translate8(data, out, end);
160                            break;
161    
162                    case 16:
163                            translate16(data, (uint16 *) out, (uint16 *) end);
164                            break;
165    
166                    case 24:
167                            translate24(data, out, end);
168                            break;
169    
170                    case 32:
171                            translate32(data, (uint32 *) out, (uint32 *) end);
172                            break;
173            }
174    
175            return out;
176    }
177    
178    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
179    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
180    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
181                            x = (x << 16) | (x >> 16); }
182    
183    static uint32
184    translate_colour(uint32 colour)
185    {
186            switch (bpp)
187            {
188                    case 16:
189                            if (host_be != xserver_be)
190                                    BSWAP16(colour);
191                            break;
192    
193                    case 24:
194                            if (xserver_be)
195                                    BSWAP24(colour);
196                            break;
197    
198                    case 32:
199                            if (host_be != xserver_be)
200                                    BSWAP32(colour);
201                            break;
202            }
203    
204            return colour;
205  }  }
206    
207  BOOL  BOOL
# Line 97  ui_create_window(char *title) Line 212  ui_create_window(char *title)
212          XSizeHints *sizehints;          XSizeHints *sizehints;
213          unsigned long input_mask;          unsigned long input_mask;
214          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
215          int count;          Screen *screen;
216            uint16 test;
217            int i;
218    
219            int xkb_minor, xkb_major;
220            int xkb_event, xkb_error, xkb_reason;
221    
222            /* compare compiletime libs with runtime libs. */
223            xkb_major = XkbMajorVersion;
224            xkb_minor = XkbMinorVersion;
225            if (XkbLibraryVersion(&xkb_major, &xkb_minor) == False)
226            {
227                    error("please re-compile rdesktop\ncompile time version of xkb is not compatible with\nyour runtime version of the library\n");
228                    return False;
229            }
230    
231    
232            display =
233                    XkbOpenDisplay(NULL, &xkb_event, &xkb_error, &xkb_major,
234                                   &xkb_minor, &xkb_reason);
235            switch (xkb_reason)
236            {
237                    case XkbOD_BadLibraryVersion:
238                            error("XkbOD_BadLibraryVersion: XKB extensions in server and the library rdesktop is linked against aren't compatible with each other.\n");
239                            break;
240                    case XkbOD_ConnectionRefused:
241                            error("XkbOD_ConnectionRefused\n");
242                            break;
243                    case XkbOD_BadServerVersion:
244                            error("XkbOD_BadServerVersion\n");
245                            break;
246                    case XkbOD_NonXkbServer:
247                            error("XkbOD_NonXkbServer: XKB extension not present in server\nupdate your X server.\n");
248                            break;
249                    case XkbOD_Success:
250                            DEBUG("XkbOD_Success: Connection established with display\n");
251                            break;
252            }
253    
         display = XOpenDisplay(NULL);  
254          if (display == NULL)          if (display == NULL)
255          {          {
256                  ERROR("Failed to open display\n");                  error("Failed to open display\n");
257                  return False;                  return False;
258          }          }
259    
260          visual = DefaultVisual(display, DefaultScreen(display));          x_socket = ConnectionNumber(display);
261          depth = DefaultDepth(display, DefaultScreen(display));          screen = DefaultScreenOfDisplay(display);
262          pfm = XListPixmapFormats(display, &count);          visual = DefaultVisualOfScreen(screen);
263            depth = DefaultDepthOfScreen(screen);
264    
265            pfm = XListPixmapFormats(display, &i);
266          if (pfm != NULL)          if (pfm != NULL)
267          {          {
268                  while (count--)                  /* Use maximum bpp for this depth - this is generally
269                       desirable, e.g. 24 bits->32 bits. */
270                    while (i--)
271                  {                  {
272                          if ((pfm + count)->depth == depth                          if ((pfm[i].depth == depth)
273                              && (pfm + count)->bits_per_pixel > bpp)                              && (pfm[i].bits_per_pixel > bpp))
274                          {                          {
275                                  bpp = (pfm + count)->bits_per_pixel;                                  bpp = pfm[i].bits_per_pixel;
276                          }                          }
277                  }                  }
278                  XFree(pfm);                  XFree(pfm);
# Line 124  ui_create_window(char *title) Line 280  ui_create_window(char *title)
280    
281          if (bpp < 8)          if (bpp < 8)
282          {          {
283                  ERROR("Less than 8 bpp not currently supported.\n");                  error("Less than 8 bpp not currently supported.\n");
284                  XCloseDisplay(display);                  XCloseDisplay(display);
285                  return False;                  return False;
286          }          }
287    
288          width &= ~3; /* make width nicely divisible */          if (depth <= 8)
289                    owncolmap = True;
290            else
291                    xcolmap = DefaultColormapOfScreen(screen);
292    
293            test = 1;
294            host_be = !(BOOL) (*(uint8 *) (&test));
295            xserver_be = (ImageByteOrder(display) == MSBFirst);
296    
297            white = WhitePixelOfScreen(screen);
298            attribs.background_pixel = BlackPixelOfScreen(screen);
299            attribs.backing_store = DoesBackingStore(screen);
300    
301          attribs.background_pixel = BlackPixel(display, DefaultScreen(display));          if (attribs.backing_store == NotUseful)
302          attribs.backing_store = Always;                  ownbackstore = True;
303    
304          if (fullscreen)          if (fullscreen)
305          {          {
306                  attribs.override_redirect = True;                  attribs.override_redirect = True;
307                  width = WidthOfScreen(DefaultScreenOfDisplay(display));                  width = WidthOfScreen(screen);
308                  height = HeightOfScreen(DefaultScreenOfDisplay(display));                  height = HeightOfScreen(screen);
                 XSetInputFocus(display, PointerRoot, RevertToPointerRoot,  
                                CurrentTime);  
309          }          }
310          else          else
311          {          {
312                  attribs.override_redirect = False;                  attribs.override_redirect = False;
313          }          }
314    
315          wnd = XCreateWindow(display, DefaultRootWindow(display),          width = (width + 3) & ~3;       /* make width a multiple of 32 bits */
316    
317            wnd = XCreateWindow(display, RootWindowOfScreen(screen),
318                              0, 0, width, height, 0, CopyFromParent,                              0, 0, width, height, 0, CopyFromParent,
319                              InputOutput, CopyFromParent,                              InputOutput, CopyFromParent,
320                              CWBackingStore | CWBackPixel | CWOverrideRedirect,                              CWBackingStore | CWBackPixel | CWOverrideRedirect,
# Line 157  ui_create_window(char *title) Line 324  ui_create_window(char *title)
324    
325          classhints = XAllocClassHint();          classhints = XAllocClassHint();
326          if (classhints != NULL)          if (classhints != NULL)
   
327          {          {
328                  classhints->res_name = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
                 classhints->res_class = "rdesktop";  
329                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(display, wnd, classhints);
330                  XFree(classhints);                  XFree(classhints);
331          }          }
# Line 168  ui_create_window(char *title) Line 333  ui_create_window(char *title)
333          sizehints = XAllocSizeHints();          sizehints = XAllocSizeHints();
334          if (sizehints)          if (sizehints)
335          {          {
336                  sizehints->flags =                  sizehints->flags = PMinSize | PMaxSize;
337                          PPosition | PSize | PMinSize | PMaxSize | PBaseSize;                  sizehints->min_width = sizehints->max_width = width;
338                  sizehints->min_width = width;                  sizehints->min_height = sizehints->max_height = height;
                 sizehints->max_width = width;  
                 sizehints->min_height = height;  
                 sizehints->max_height = height;  
                 sizehints->base_width = width;  
                 sizehints->base_height = height;  
339                  XSetWMNormalHints(display, wnd, sizehints);                  XSetWMNormalHints(display, wnd, sizehints);
340                  XFree(sizehints);                  XFree(sizehints);
341          }          }
342    
343          input_mask = KeyPressMask | KeyReleaseMask;          xkeymap_init();
344          input_mask |= ButtonPressMask | ButtonReleaseMask;  
345          if (motion)          input_mask = KeyPressMask | KeyReleaseMask |
346                    ButtonPressMask | ButtonReleaseMask |
347                    EnterWindowMask | LeaveWindowMask;
348            if (sendmotion)
349                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
350          if (grab_keyboard)  
351                  input_mask |= EnterWindowMask | LeaveWindowMask;          if (ownbackstore)
352                    input_mask |= ExposureMask;
353    
354          XSelectInput(display, wnd, input_mask);          XSelectInput(display, wnd, input_mask);
355          gc = XCreateGC(display, wnd, 0, NULL);          gc = XCreateGC(display, wnd, 0, NULL);
356    
357            if (ownbackstore)
358                    backstore = XCreatePixmap(display, wnd, width, height, depth);
359    
360          XMapWindow(display, wnd);          XMapWindow(display, wnd);
361    
362            /* TODO: error texts... make them friendly. */
363            xkb = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);
364            if ((int) xkb == BadAlloc || xkb == NULL)
365            {
366                    error("XkbGetKeyboard failed.\n");
367                    exit(0);
368            }
369    
370            /* TODO: error texts... make them friendly. */
371            if (XkbSelectEvents
372                (display, xkb->device_spec, XkbAllEventsMask,
373                 XkbAllEventsMask) == False)
374            {
375                    error("XkbSelectEvents failed.\n");
376                    exit(0);
377            }
378    
379            xwin_get_numlock_mask();
380    
381          return True;          return True;
382  }  }
383    
384  void  void
385    xwin_get_numlock_mask()
386    {
387            KeyCode numlockcode;
388            KeyCode *keycode;
389            XModifierKeymap *modmap;
390            int i, j;
391    
392            /* Find out if numlock is already defined as a modifier key, and if so where */
393            numlockcode = XKeysymToKeycode(display, 0xFF7F);        /* XF_Num_Lock = 0xFF7F */
394            if (numlockcode)
395            {
396                    modmap = XGetModifierMapping(display);
397                    if (modmap)
398                    {
399                            keycode = modmap->modifiermap;
400                            for (i = 0; i < 8; i++)
401                                    for (j = modmap->max_keypermod; j--;)
402                                    {
403                                            if (*keycode == numlockcode)
404                                            {
405                                                    numlock_modifier_mask =
406                                                            (1 << i);
407                                                    i = 8;
408                                                    break;
409                                            }
410                                            keycode++;
411                                    }
412                            if (!numlock_modifier_mask)
413                            {
414                                    modmap->modifiermap[7 *
415                                                        modmap->max_keypermod] =
416                                            numlockcode;
417                                    if (XSetModifierMapping(display, modmap) ==
418                                        MappingSuccess)
419                                            numlock_modifier_mask = (1 << 7);
420                                    else
421                                            printf("XSetModifierMapping failed!\n");
422                            }
423                            XFreeModifiermap(modmap);
424                    }
425            }
426    
427            if (!numlock_modifier_mask)
428                    printf("WARNING: Failed to get a numlock modifier mapping.\n");
429    
430    }
431    
432    void
433  ui_destroy_window()  ui_destroy_window()
434  {  {
435            if (xkb != NULL)
436                    XkbFreeKeyboard(xkb, XkbAllControlsMask, True);
437    
438            if (ownbackstore)
439                    XFreePixmap(display, backstore);
440    
441          XFreeGC(display, gc);          XFreeGC(display, gc);
442          XDestroyWindow(display, wnd);          XDestroyWindow(display, wnd);
443          XCloseDisplay(display);          XCloseDisplay(display);
444          display = NULL;          display = NULL;
445  }  }
446    
447  static uint8  static void
448  xwin_translate_key(unsigned long key)  xwin_process_events()
449  {  {
450          DEBUG("KEY(code=0x%lx)\n", key);          XEvent xevent;
   
         if ((key > 8) && (key <= 0x60))  
                 return (key - 8);  
451    
452          switch (key)          KeySym keysym;
         {  
                 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;  
453          uint8 scancode;          uint8 scancode;
454          uint16 button;          uint16 button, flags;
455          uint32 ev_time;          uint32 ev_time;
456            uint32 tmpmods;
457    
458          if (display == NULL)          while (XCheckMaskEvent(display, ~0, &xevent))
                 return;  
   
         while (XCheckWindowEvent(display, wnd, ~0, &event))  
459          {          {
460                  ev_time = time(NULL);                  ev_time = time(NULL);
461                    flags = 0;
462    
463                  switch (event.type)                  switch (xevent.type)
464                  {                  {
465                            case KeyRelease:
466                                    flags = KBD_FLAG_DOWN | KBD_FLAG_UP;
467                                    /* fall through */
468                          case KeyPress:                          case KeyPress:
469                                  scancode = xwin_translate_key(event.xkey.keycode);                                  if (XkbTranslateKeyCode
470                                  if (scancode == 0)                                      (xkb, xevent.xkey.keycode,
471                                         xevent.xkey.state, &tmpmods,
472                                         &keysym) == False)
473                                          break;                                          break;
474                                    scancode =
475                                            xkeymap_translate_key(keysym,
476                                                                  xevent.xkey.
477                                                                  keycode,
478                                                                  &flags);
479    
                                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,  
                                                scancode, 0);  
                                 break;  
   
                         case KeyRelease:  
                                 scancode = xwin_translate_key(event.xkey.keycode);  
480                                  if (scancode == 0)                                  if (scancode == 0)
481                                          break;                                          break;
482    
483                                    /* keep track of the modifiers -- needed for stickykeys... */
484                                    if (xevent.type == KeyPress)
485                                            xwin_mod_press(xevent.xkey.state,
486                                                           ev_time, scancode);
487    
488                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
489                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                 flags, scancode, 0);
                                                scancode, 0);  
                                 break;  
490    
491                          case ButtonPress:                                  if (xevent.type == KeyRelease)
492                                  button = xwin_translate_mouse(event.xbutton.button);                                          xwin_mod_release(xevent.xkey.state,
493                                  if (button == 0)                                                           ev_time, scancode);
                                         break;  
494    
                                 rdp_send_input(ev_time, RDP_INPUT_MOUSE,  
                                                button | MOUSE_FLAG_DOWN,  
                                                event.xbutton.x,  
                                                event.xbutton.y);  
495                                  break;                                  break;
496    
497                            case ButtonPress:
498                                    flags = MOUSE_FLAG_DOWN;
499                                    /* fall through */
500    
501                          case ButtonRelease:                          case ButtonRelease:
502                                  button = xwin_translate_mouse(event.xbutton.button);                                  button = xkeymap_translate_button(xevent.
503                                                                      xbutton.
504                                                                      button);
505                                  if (button == 0)                                  if (button == 0)
506                                          break;                                          break;
507    
508                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
509                                                 button,                                                 flags | button,
510                                                 event.xbutton.x,                                                 xevent.xbutton.x,
511                                                 event.xbutton.y);                                                 xevent.xbutton.y);
512                                  break;                                  break;
513    
514                          case MotionNotify:                          case MotionNotify:
515                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
516                                                 MOUSE_FLAG_MOVE,                                                 MOUSE_FLAG_MOVE,
517                                                 event.xmotion.x,                                                 xevent.xmotion.x,
518                                                 event.xmotion.y);                                                 xevent.xmotion.y);
519                                  break;                                  break;
520    
521                          case EnterNotify:                          case EnterNotify:
522                                  if (grab_keyboard)                                  XGrabKeyboard(display, wnd, True,
523                                          xwin_grab_keyboard();                                                GrabModeAsync, GrabModeAsync,
524                                                  CurrentTime);
525    
526                                    xwin_mod_update(xevent.xcrossing.state,
527                                                    ev_time);
528                                  break;                                  break;
529    
530                          case LeaveNotify:                          case LeaveNotify:
531                                  if (grab_keyboard)                                  XUngrabKeyboard(display, CurrentTime);
532                                          xwin_ungrab_keyboard();                                  break;
533    
534                            case Expose:
535                                    XCopyArea(display, backstore, wnd, gc,
536                                              xevent.xexpose.x, xevent.xexpose.y,
537                                              xevent.xexpose.width,
538                                              xevent.xexpose.height,
539                                              xevent.xexpose.x, xevent.xexpose.y);
540                                  break;                                  break;
541                  }                  }
542          }          }
543  }  }
544    
545  void  void
546  ui_move_pointer(int x, int y)  xwin_mod_update(uint32 state, uint32 ev_time)
547  {  {
548          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          xwin_mod_press(state, ev_time, 0);
549            xwin_mod_release(state, ev_time, 0);
550  }  }
551    
552  HBITMAP  void
553  ui_create_bitmap(int width, int height, uint8 *data)  xwin_mod_release(uint32 state, uint32 ev_time, uint32 scancode)
554  {  {
555          XImage *image;          switch (scancode)
556          Pixmap bitmap;          {
557          uint8 *tdata;                  case 0x2a:
558          tdata = (private_colormap ? data : translate(width, height, data));                          key_down_state &= ~DShift1Mask;
559          bitmap = XCreatePixmap(display, wnd, width, height, depth);                          break;
560          image =                  case 0x36:
561                  XCreateImage(display, visual,                          key_down_state &= ~DShift2Mask;
562                               depth, ZPixmap,                          break;
563                               0, tdata, width, height, BitmapPad(display), 0);                  case 0x1d:
564                            key_down_state &= ~DControl1Mask;
565                            break;
566                    case 0x9d:
567                            key_down_state &= ~DControl2Mask;
568                            break;
569                    case 0x38:
570                            key_down_state &= ~DMod1Mask;
571                            break;
572                    case 0xb8:
573                            key_down_state &= ~DMod2Mask;
574                            break;
575            }
576    
577          xwin_set_function(ROP2_COPY);          if (!(numlock_modifier_mask & state)
578          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);              && (key_down_state & DNumLockMask))
579            {
580                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x45, 0);
581                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
582                                   KBD_FLAG_DOWN | KBD_FLAG_UP, 0x45, 0);
583                    key_down_state &= ~DNumLockMask;
584            }
585    
586          XFree(image);          if (!(LockMask & state) && (key_down_state & DLockMask))
587          if (!private_colormap)          {
588                  xfree(tdata);                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);
589          return (HBITMAP) bitmap;                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
590                                   KBD_FLAG_DOWN | KBD_FLAG_UP, 0x3a, 0);
591                    key_down_state &= ~DLockMask;
592    
593            }
594    
595    
596            if (!(ShiftMask & state) && (key_down_state & DShift1Mask))
597            {
598                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a,
599                                   0);
600                    key_down_state &= ~DShift1Mask;
601    
602            }
603    
604            if (!(ControlMask & state) && (key_down_state & DControl1Mask))
605            {
606                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d,
607                                   0);
608                    key_down_state &= ~DControl1Mask;
609    
610            }
611    
612            if (!(Mod1Mask & state) && (key_down_state & DMod1Mask))
613            {
614                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38,
615                                   0);
616                    key_down_state &= ~DMod1Mask;
617    
618            }
619    
620            if (!(Mod2Mask & state) && (key_down_state & DMod2Mask))
621            {
622                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8,
623                                   0);
624                    key_down_state &= ~DMod2Mask;
625            }
626  }  }
627    
628    
629  void  void
630  ui_paint_bitmap(int x, int y, int cx, int cy,  xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode)
                 int width, int height, uint8 *data)  
631  {  {
         XImage *image;  
         uint8 *tdata =  
                 (private_colormap ? data : translate(width, height, data));  
         image =  
                 XCreateImage(display, visual, depth, ZPixmap, 0, tdata, width,  
                              height, BitmapPad(display), 0);  
632    
633          xwin_set_function(ROP2_COPY);          switch (scancode)
634            {
635                    case 0x2a:
636                            key_down_state |= DShift1Mask;
637                            break;
638                    case 0x36:
639                            key_down_state |= DShift2Mask;
640                            break;
641                    case 0x1d:
642                            key_down_state |= DControl1Mask;
643                            break;
644                    case 0x9d:
645                            key_down_state |= DControl2Mask;
646                            break;
647                    case 0x3a:
648                            key_down_state ^= DLockMask;
649                            break;
650                    case 0x45:
651                            key_down_state ^= DNumLockMask;
652                            break;
653                    case 0x38:
654                            key_down_state |= DMod1Mask;
655                            break;
656                    case 0xb8:
657                            key_down_state |= DMod2Mask;
658                            break;
659            }
660    
661            if ((numlock_modifier_mask && state)
662                && !(key_down_state & DNumLockMask))
663            {
664                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x45, 0);
665                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
666                                   KBD_FLAG_DOWN | KBD_FLAG_UP, 0x45, 0);
667                    key_down_state |= DNumLockMask;
668            }
669    
670            if ((LockMask & state) && !(key_down_state & DLockMask))
671            {
672                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);
673                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
674                                   KBD_FLAG_DOWN | KBD_FLAG_UP, 0x3a, 0);
675                    key_down_state |= DLockMask;
676    
677          /* Window */          }
678          XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
679          XFree(image);  
680          if (!private_colormap)          if ((ShiftMask & state)
681                  xfree(tdata);              && !((key_down_state & DShift1Mask)
682                     || (key_down_state & DShift2Mask)))
683            {
684                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,
685                                   0x2a, 0);
686                    key_down_state |= DShift1Mask;
687    
688            }
689    
690            if ((ControlMask & state)
691                && !((key_down_state & DControl1Mask)
692                     || (key_down_state & DControl2Mask)))
693            {
694                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,
695                                   0x1d, 0);
696                    key_down_state |= DControl1Mask;
697    
698            }
699    
700            if ((Mod1Mask & state) && !(key_down_state & DMod1Mask))
701            {
702                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,
703                                   0x38, 0);
704                    key_down_state |= DMod1Mask;
705    
706            }
707    
708            if ((Mod2Mask & state) && !(key_down_state & DMod2Mask))
709            {
710                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,
711                                   0xb8, 0);
712                    key_down_state |= DMod2Mask;
713    
714            }
715  }  }
716    
717  void  void
718  ui_destroy_bitmap(HBITMAP bmp)  ui_select(int rdp_socket)
719  {  {
720          XFreePixmap(display, (Pixmap) bmp);          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
721  }          fd_set rfds;
722    
723  HCURSOR          FD_ZERO(&rfds);
 ui_create_cursor(unsigned int x, unsigned int y, int width,  
                  int height, uint8 *mask, uint8 *data)  
 {  
         XImage *imagecursor;  
         XImage *imagemask;  
         Pixmap maskbitmap, cursorbitmap;  
         Cursor cursor;  
         XColor bg, fg;  
         GC lgc;  
         int i, x1, y1, scanlinelen;  
         uint8 *cdata, *cmask;  
         uint8 c;  
         cdata = (uint8 *) malloc(sizeof(uint8) * width * height);  
         if (!cdata)  
                 return NULL;  
         scanlinelen = (width + 7) >> 3;  
         cmask = (uint8 *) malloc(sizeof(uint8) * scanlinelen * height);  
         if (!cmask)  
         {  
                 free(cdata);  
                 return NULL;  
         }  
         i = (height - 1) * scanlinelen;  
724    
725          if (!screen_msbfirst)          while (True)
726          {          {
727                  while (i >= 0)                  FD_ZERO(&rfds);
728                    FD_SET(rdp_socket, &rfds);
729                    if (display != NULL)
730                  {                  {
731                          for (x1 = 0; x1 < scanlinelen; x1++)                          FD_SET(x_socket, &rfds);
732                          {                          XFlush(display);
                                 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;  
733                  }                  }
734          }  
735          else                  switch (select(n, &rfds, NULL, NULL, NULL))
         {  
                 while (i >= 0)  
736                  {                  {
737                          for (x1 = 0; x1 < scanlinelen; x1++)                          case -1:
738                          {                                  error("select: %s\n", strerror(errno));
739                                  cmask[i + x1] = *(mask++);  
740                          }                          case 0:
741                          i -= scanlinelen;                                  continue;
742                  }                  }
743    
744                    if (FD_ISSET(x_socket, &rfds))
745                            xwin_process_events();
746    
747                    if (FD_ISSET(rdp_socket, &rfds))
748                            return;
749          }          }
750    }
751    
752    void
753    ui_move_pointer(int x, int y)
754    {
755            XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
756    }
757    
758          fg.red = 0;  HBITMAP
759          fg.blue = 0;  ui_create_bitmap(int width, int height, uint8 * data)
760          fg.green = 0;  {
761          fg.flags = DoRed | DoBlue | DoGreen;          XImage *image;
762          bg.red = 65535;          Pixmap bitmap;
763          bg.blue = 65535;          uint8 *tdata;
         bg.green = 65535;  
         bg.flags = DoRed | DoBlue | DoGreen;  
         maskbitmap = XCreatePixmap(display, wnd, width, height, 1);  
         cursorbitmap = XCreatePixmap(display, wnd, width, height, 1);  
         lgc = XCreateGC(display, maskbitmap, 0, NULL);  
         XSetFunction(display, lgc, GXcopy);  
         imagemask =  
                 XCreateImage(display, visual, 1, XYBitmap, 0, cmask, width,  
                              height, 8, 0);  
         imagecursor =  
                 XCreateImage(display, visual, 1, XYBitmap, 0, cdata, width,  
                              height, 8, 0);  
         for (y1 = height - 1; y1 >= 0; y1--)  
                 for (x1 = 0; x1 < width; x1++)  
                 {  
                         if (data[0] >= 0x80 || data[1] >= 0x80  
                             || data[2] >= 0x80)  
                                 if (XGetPixel(imagemask, x1, y1))  
764    
765                                  {          tdata = (owncolmap ? data : translate_image(width, height, data));
766                                          XPutPixel(imagecursor, x1, y1, 0);          bitmap = XCreatePixmap(display, wnd, width, height, depth);
767                                          XPutPixel(imagemask, x1, y1, 0);        /* mask is blank for text cursor! */          image = XCreateImage(display, visual, depth, ZPixmap,
768                                  }                               0, tdata, width, height, 8, 0);
769    
770                                  else          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
                                         XPutPixel(imagecursor, x1, y1, 1);  
771    
772                          else          XFree(image);
773                                  XPutPixel(imagecursor, x1, y1,          if (!owncolmap)
774                                            XGetPixel(imagemask, x1, y1));                  xfree(tdata);
775                          data += 3;          return (HBITMAP) bitmap;
                 }  
         XPutImage(display, maskbitmap, lgc, imagemask, 0, 0, 0, 0, width,  
                   height);  
         XPutImage(display, cursorbitmap, lgc, imagecursor, 0, 0, 0, 0, width,  
                   height); XFree(imagemask);  
         XFree(imagecursor);  
         free(cmask);  
         free(cdata);  
         XFreeGC(display, lgc);  
         cursor =  
                 XCreatePixmapCursor(display, cursorbitmap, maskbitmap, &fg,  
                                     &bg, x, y);  
         XFreePixmap(display, maskbitmap);  
         XFreePixmap(display, cursorbitmap);  
         return (HCURSOR) cursor;  
776  }  }
777    
778  void  void
779  ui_set_cursor(HCURSOR cursor)  ui_paint_bitmap(int x, int y, int cx, int cy,
780                    int width, int height, uint8 * data)
781  {  {
782          XDefineCursor(display, wnd, (Cursor) cursor);          XImage *image;
783            uint8 *tdata;
784    
785            tdata = (owncolmap ? data : translate_image(width, height, data));
786            image = XCreateImage(display, visual, depth, ZPixmap,
787                                 0, tdata, width, height, 8, 0);
788    
789            if (ownbackstore)
790            {
791                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
792                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
793            }
794            else
795            {
796                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
797            }
798    
799            XFree(image);
800            if (!owncolmap)
801                    xfree(tdata);
802  }  }
803    
804  void  void
805  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_bitmap(HBITMAP bmp)
806  {  {
807          XFreeCursor(display, (Cursor) cursor);          XFreePixmap(display, (Pixmap) bmp);
808  }  }
809    
810  HGLYPH  HGLYPH
811  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
812  {  {
813          XImage *image;          XImage *image;
814          Pixmap bitmap;          Pixmap bitmap;
# Line 544  ui_create_glyph(int width, int height, u Line 826  ui_create_glyph(int width, int height, u
826          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
827          XInitImage(image);          XInitImage(image);
828    
         XSetFunction(display, gc, GXcopy);  
829          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
830    
831          XFree(image);          XFree(image);
832          XFreeGC(display, gc);          XFreeGC(display, gc);
   
833          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
834  }  }
835    
# Line 558  ui_destroy_glyph(HGLYPH glyph) Line 839  ui_destroy_glyph(HGLYPH glyph)
839          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(display, (Pixmap) glyph);
840  }  }
841    
842  HCOLOURMAP  HCURSOR
843  ui_create_colourmap(COLOURMAP *colours)  ui_create_cursor(unsigned int x, unsigned int y, int width,
844                     int height, uint8 * andmask, uint8 * xormask)
845  {  {
846          if (!private_colormap)          HGLYPH maskglyph, cursorglyph;
847            XColor bg, fg;
848            Cursor xcursor;
849            uint8 *cursor, *pcursor;
850            uint8 *mask, *pmask;
851            uint8 nextbit;
852            int scanline, offset;
853            int i, j;
854    
855            scanline = (width + 7) / 8;
856            offset = scanline * height;
857    
858            cursor = xmalloc(offset);
859            memset(cursor, 0, offset);
860    
861            mask = xmalloc(offset);
862            memset(mask, 0, offset);
863    
864            /* approximate AND and XOR masks with a monochrome X pointer */
865            for (i = 0; i < height; i++)
866          {          {
867                  COLOURENTRY *entry;                  offset -= scanline;
868                  int i, ncolours = colours->ncolours;                  pcursor = &cursor[offset];
869                  uint32 *nc = xmalloc(sizeof(*colmap) * ncolours);                  pmask = &mask[offset];
870                  for (i = 0; i < ncolours; i++)  
871                    for (j = 0; j < scanline; j++)
872                  {                  {
873                          XColor xc;                          for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
874                          entry = &colours->colours[i];                          {
875                          xc.red = entry->red << 8;                                  if (xormask[0] || xormask[1] || xormask[2])
876                          xc.green = entry->green << 8;                                  {
877                          xc.blue = entry->blue << 8;                                          *pcursor |= (~(*andmask) & nextbit);
878                          XAllocColor(display,                                          *pmask |= nextbit;
879                                      DefaultColormap(display,                                  }
880                                                      DefaultScreen(display)),                                  else
881                                      &xc);                                  {
882                          /* XXX Check return value */                                          *pcursor |= ((*andmask) & nextbit);
883                          nc[i] = xc.pixel;                                          *pmask |= (~(*andmask) & nextbit);
884                                    }
885    
886                                    xormask += 3;
887                            }
888    
889                            andmask++;
890                            pcursor++;
891                            pmask++;
892                  }                  }
                 return nc;  
893          }          }
894          else  
895            fg.red = fg.blue = fg.green = 0xffff;
896            bg.red = bg.blue = bg.green = 0x0000;
897            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
898    
899            cursorglyph = ui_create_glyph(width, height, cursor);
900            maskglyph = ui_create_glyph(width, height, mask);
901    
902            xcursor = XCreatePixmapCursor(display, (Pixmap) cursorglyph,
903                                          (Pixmap) maskglyph, &fg, &bg, x, y);
904    
905            ui_destroy_glyph(maskglyph);
906            ui_destroy_glyph(cursorglyph);
907            xfree(mask);
908            xfree(cursor);
909            return (HCURSOR) xcursor;
910    }
911    
912    void
913    ui_set_cursor(HCURSOR cursor)
914    {
915            XDefineCursor(display, wnd, (Cursor) cursor);
916    }
917    
918    void
919    ui_destroy_cursor(HCURSOR cursor)
920    {
921            XFreeCursor(display, (Cursor) cursor);
922    }
923    
924    #define MAKE_XCOLOR(xc,c) \
925                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
926                    (xc)->green = ((c)->green << 8) | (c)->green; \
927                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
928                    (xc)->flags = DoRed | DoGreen | DoBlue;
929    
930    HCOLOURMAP
931    ui_create_colourmap(COLOURMAP * colours)
932    {
933            COLOURENTRY *entry;
934            int i, ncolours = colours->ncolours;
935    
936            if (owncolmap)
937          {          {
                 COLOURENTRY *entry;  
938                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
939                  Colormap map;                  Colormap map;
940                  int i, ncolours = colours->ncolours;  
941                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = xmalloc(sizeof(XColor) * ncolours);
942                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
943                  {                  {
944                          entry = &colours->colours[i];                          entry = &colours->colours[i];
945                          xentry = &xcolours[i];                          xentry = &xcolours[i];
   
946                          xentry->pixel = i;                          xentry->pixel = i;
947                          xentry->red = entry->red << 8;                          MAKE_XCOLOR(xentry, entry);
                         xentry->blue = entry->blue << 8;  
                         xentry->green = entry->green << 8;  
                         xentry->flags = DoRed | DoBlue | DoGreen;  
948                  }                  }
949    
950                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(display, wnd, visual, AllocAll);
# Line 607  ui_create_colourmap(COLOURMAP *colours) Line 953  ui_create_colourmap(COLOURMAP *colours)
953                  xfree(xcolours);                  xfree(xcolours);
954                  return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
955          }          }
956            else
957            {
958                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
959                    XColor xentry;
960                    uint32 colour;
961    
962                    for (i = 0; i < ncolours; i++)
963                    {
964                            entry = &colours->colours[i];
965                            MAKE_XCOLOR(&xentry, entry);
966    
967                            if (XAllocColor(display, xcolmap, &xentry) != 0)
968                                    colour = xentry.pixel;
969                            else
970                                    colour = white;
971    
972                            /* byte swap here to make translate_image faster */
973                            map[i] = translate_colour(colour);
974                    }
975    
976                    return map;
977            }
978  }  }
979    
980  void  void
981  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
982  {  {
983          XFreeColormap(display, (Colormap) map);          if (owncolmap)
984                    XFreeColormap(display, (Colormap) map);
985            else
986                    xfree(map);
987  }  }
988    
989  void  void
990  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
991  {  {
992            if (owncolmap)
         /* XXX, change values of all pixels on the screen if the new colmap  
          * doesn't have the same values as the old one? */  
         if (!private_colormap)  
                 colmap = map;  
         else  
         {  
993                  XSetWindowColormap(display, wnd, (Colormap) map);                  XSetWindowColormap(display, wnd, (Colormap) map);
994                  if (fullscreen)          else
995                          XInstallColormap(display, (Colormap) map);                  colmap = map;
         }  
996  }  }
997    
998  void  void
# Line 665  void Line 1029  void
1029  ui_destblt(uint8 opcode,  ui_destblt(uint8 opcode,
1030             /* dest */ int x, int y, int cx, int cy)             /* dest */ int x, int y, int cx, int cy)
1031  {  {
1032          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1033            FILL_RECTANGLE(x, y, cx, cy);
1034          XFillRectangle(display, wnd, gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
1035  }  }
1036    
1037  void  void
1038  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1039            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1040            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1041  {  {
         Display *dpy = display;  
1042          Pixmap fill;          Pixmap fill;
1043          uint8 i, ipattern[8];          uint8 i, ipattern[8];
1044    
1045          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1046    
1047          switch (brush->style)          switch (brush->style)
1048          {          {
1049                  case 0: /* Solid */                  case 0: /* Solid */
1050                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_FOREGROUND(fgcolour);
1051                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1052                          break;                          break;
1053    
1054                  case 3: /* Pattern */                  case 3: /* Pattern */
1055                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
1056                                  ipattern[i] = ~brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
1057                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1058    
1059                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_FOREGROUND(bgcolour);
1060                          XSetBackground(dpy, gc, Ctrans(bgcolour));                          SET_BACKGROUND(fgcolour);
1061                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                          XSetFillStyle(display, gc, FillOpaqueStippled);
1062                          XSetStipple(dpy, gc, fill);                          XSetStipple(display, gc, fill);
1063                            XSetTSOrigin(display, gc, brush->xorigin,
1064                                         brush->yorigin);
1065    
1066                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1067    
1068                          XSetFillStyle(dpy, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
1069                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
1070                          break;                          break;
1071    
1072                  default:                  default:
1073                          NOTIMP("brush %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
1074          }          }
1075    
1076            RESET_FUNCTION(opcode);
1077  }  }
1078    
1079  void  void
# Line 714  ui_screenblt(uint8 opcode, Line 1081  ui_screenblt(uint8 opcode,
1081               /* dest */ int x, int y, int cx, int cy,               /* dest */ int x, int y, int cx, int cy,
1082               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
1083  {  {
1084          xwin_set_function(opcode);          SET_FUNCTION(opcode);
   
1085          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1086            if (ownbackstore)
1087                    XCopyArea(display, backstore, backstore, gc, srcx, srcy,
1088                              cx, cy, x, y);
1089            RESET_FUNCTION(opcode);
1090  }  }
1091    
1092  void  void
# Line 724  ui_memblt(uint8 opcode, Line 1094  ui_memblt(uint8 opcode,
1094            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1095            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1096  {  {
1097          xwin_set_function(opcode);          SET_FUNCTION(opcode);
   
1098          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1099            if (ownbackstore)
1100                    XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy,
1101                              cx, cy, x, y);
1102            RESET_FUNCTION(opcode);
1103  }  }
1104    
1105  void  void
1106  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1107            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1108            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1109            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1110  {  {
1111          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1112             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 754  ui_triblt(uint8 opcode, Line 1127  ui_triblt(uint8 opcode,
1127                                    brush, bgcolour, fgcolour);                                    brush, bgcolour, fgcolour);
1128                          break;                          break;
1129    
1130                  case 0xc0:                  case 0xc0:      /* PSa */
1131                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1132                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
1133                                    fgcolour);                                    fgcolour);
1134                          break;                          break;
1135    
1136                  default:                  default:
1137                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
1138                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1139          }          }
1140  }  }
# Line 769  ui_triblt(uint8 opcode, Line 1142  ui_triblt(uint8 opcode,
1142  void  void
1143  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1144          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1145          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1146  {  {
1147          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1148            SET_FOREGROUND(pen->colour);
         XSetForeground(display, gc, Ctrans(pen->colour));  
1149          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1150            if (ownbackstore)
1151                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1152            RESET_FUNCTION(opcode);
1153  }  }
1154    
1155  void  void
# Line 782  ui_rect( Line 1157  ui_rect(
1157                 /* dest */ int x, int y, int cx, int cy,                 /* dest */ int x, int y, int cx, int cy,
1158                 /* brush */ int colour)                 /* brush */ int colour)
1159  {  {
1160          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(colour);
1161            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(display, gc, Ctrans(colour));  
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1162  }  }
1163    
1164  void  void
# Line 794  ui_draw_glyph(int mixmode, Line 1167  ui_draw_glyph(int mixmode,
1167                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,
1168                int fgcolour)                int fgcolour)
1169  {  {
1170          Pixmap pixmap = (Pixmap) glyph;          SET_FOREGROUND(fgcolour);
1171            SET_BACKGROUND(bgcolour);
         xwin_set_function(ROP2_COPY);  
   
   
         XSetForeground(display, gc, Ctrans(fgcolour));  
         switch (mixmode)  
         {  
                 case MIX_TRANSPARENT:  
                         XSetStipple(display, gc, pixmap);  
                         XSetFillStyle(display, gc, FillStippled);  
                         XSetTSOrigin(display, gc, x, y);  
                         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
                         XSetFillStyle(display, gc, FillSolid);  
                         break;  
1172    
1173                  case MIX_OPAQUE:          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)
1174                          XSetBackground(display, gc, Ctrans(bgcolour));                        ? FillStippled : FillOpaqueStippled);
1175  /*      XCopyPlane (display, pixmap, back_pixmap, back_gc, srcx, srcy, cx, cy, x, y, 1); */          XSetStipple(display, gc, (Pixmap) glyph);
1176                          XSetStipple(display, gc, pixmap);          XSetTSOrigin(display, gc, x, y);
1177                          XSetFillStyle(display, gc, FillOpaqueStippled);  
1178                          XSetTSOrigin(display, gc, x, y);          FILL_RECTANGLE(x, y, cx, cy);
1179                          XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1180                          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(display, gc, FillSolid);
1181                          break;  }
1182    
1183                  default:  #define DO_GLYPH(ttext,idx) \
1184                          NOTIMP("mix %d\n", mixmode);  {\
1185          }    glyph = cache_get_font (font, ttext[idx]);\
1186      if (!(flags & TEXT2_IMPLICIT_X))\
1187        {\
1188          xyoffset = ttext[++idx];\
1189          if ((xyoffset & 0x80))\
1190            {\
1191              if (flags & TEXT2_VERTICAL) \
1192                y += ttext[++idx] | (ttext[++idx] << 8);\
1193              else\
1194                x += ttext[++idx] | (ttext[++idx] << 8);\
1195            }\
1196          else\
1197            {\
1198              if (flags & TEXT2_VERTICAL) \
1199                y += xyoffset;\
1200              else\
1201                x += xyoffset;\
1202            }\
1203        }\
1204      if (glyph != NULL)\
1205        {\
1206          ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1207                         y + (short) glyph->baseline,\
1208                         glyph->width, glyph->height,\
1209                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1210          if (flags & TEXT2_IMPLICIT_X)\
1211            x += glyph->width;\
1212        }\
1213  }  }
1214    
1215  void  void
1216  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,
1217               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy, int boxx,
1218               int boxx, int boxy, int boxcx, int boxcy,               int boxy, int boxcx, int boxcy, int bgcolour,
1219               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1220  {  {
1221          FONTGLYPH *glyph;          FONTGLYPH *glyph;
1222          int i, xyoffset;          int i, j, xyoffset;
1223            DATABLOB *entry;
1224    
1225          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(bgcolour);
         XSetForeground(display, gc, Ctrans(bgcolour));  
1226    
1227          if (boxcx > 1)          if (boxcx > 1)
1228                  XFillRectangle(display, wnd, gc, boxx, boxy, boxcx, boxcy);          {
1229                    FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1230            }
1231          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1232                  XFillRectangle(display, wnd, gc, clipx, clipy, clipcx, clipcy);          {
1233                    FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1234            }
1235    
1236          /* Paint text, character by character */          /* Paint text, character by character */
1237          for (i = 0; i < length; i++)          for (i = 0; i < length;)
1238          {          {
1239                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
   
1240                  {                  {
1241                          xyoffset = text[++i];                          case 0xff:
1242                          if ((xyoffset & 0x80))                                  if (i + 2 < length)
1243                          {                                          cache_put_text(text[i + 1], text,
1244                                  if (flags & 0x04)       /* vertical text */                                                         text[i + 2]);
                                         y += text[++i] | (text[++i] << 8);  
1245                                  else                                  else
1246                                          x += text[++i] | (text[++i] << 8);                                  {
1247                          }                                          error("this shouldn't be happening\n");
1248                          else                                          break;
1249                          {                                  }
1250                                  if (flags & 0x04)       /* vertical text */                                  /* this will move pointer from start to first character after FF command */
1251                                          y += xyoffset;                                  length -= i + 3;
1252                                  else                                  text = &(text[i + 3]);
1253                                          x += xyoffset;                                  i = 0;
1254                          }                                  break;
1255    
1256                  }                          case 0xfe:
1257                  if (glyph != NULL)                                  entry = cache_get_text(text[i + 1]);
1258                  {                                  if (entry != NULL)
1259                          ui_draw_glyph(mixmode, x + (short) glyph->offset,                                  {
1260                                        y + (short) glyph->baseline,                                          if ((((uint8 *) (entry->data))[1] ==
1261                                        glyph->width, glyph->height,                                               0)
1262                                        glyph->pixmap, 0, 0,                                              && (!(flags & TEXT2_IMPLICIT_X)))
1263                                        bgcolour, fgcolour);                                          {
1264                                                    if (flags & TEXT2_VERTICAL)
1265                                                            y += text[i + 2];
1266                                                    else
1267                                                            x += text[i + 2];
1268                                            }
1269                                            if (i + 2 < length)
1270                                                    i += 3;
1271                                            else
1272                                                    i += 2;
1273                                            length -= i;
1274                                            /* this will move pointer from start to first character after FE command */
1275                                            text = &(text[i]);
1276                                            i = 0;
1277                                            for (j = 0; j < entry->size; j++)
1278                                                    DO_GLYPH(((uint8 *) (entry->
1279                                                                         data)),
1280                                                             j);
1281                                    }
1282                                    break;
1283    
1284                          if (flags & TEXT2_IMPLICIT_X)                          default:
1285                                  x += glyph->width;                                  DO_GLYPH(text, i);
1286                                    i++;
1287                                    break;
1288                  }                  }
1289          }          }
1290    
1291    
1292  }  }
1293    
1294  void  void
# Line 887  ui_desktop_save(uint32 offset, int x, in Line 1297  ui_desktop_save(uint32 offset, int x, in
1297          Pixmap pix;          Pixmap pix;
1298          XImage *image;          XImage *image;
1299    
1300          pix = XCreatePixmap(display, wnd, cx, cy, depth);          if (ownbackstore)
1301          xwin_set_function(ROP2_COPY);          {
1302                    image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
1303          XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                                    ZPixmap);
1304          image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);          }
1305            else
1306            {
1307                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
1308                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1309                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,
1310                                      ZPixmap);
1311                    XFreePixmap(display, pix);
1312            }
1313    
1314          offset *= bpp/8;          offset *= bpp / 8;
1315          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line,
1316                            bpp/8, image->data);                            bpp / 8, (uint8 *) image->data);
1317    
1318          XDestroyImage(image);          XDestroyImage(image);
         XFreePixmap(display, pix);  
1319  }  }
1320    
1321  void  void
# Line 907  ui_desktop_restore(uint32 offset, int x, Line 1324  ui_desktop_restore(uint32 offset, int x,
1324          XImage *image;          XImage *image;
1325          uint8 *data;          uint8 *data;
1326    
1327          offset *= bpp/8;          offset *= bpp / 8;
1328          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, bpp / 8);
1329          if (data == NULL)          if (data == NULL)
1330                  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);  
 }  
   
 /* unroll defines, used to make the loops a bit more readable... */  
 #define unroll8Expr(uexp) uexp uexp uexp uexp uexp uexp uexp uexp  
 #define unroll8Lefts(uexp) case 7: uexp \  
         case 6: uexp \  
         case 5: uexp \  
         case 4: uexp \  
         case 3: uexp \  
         case 2: uexp \  
         case 1: uexp  
1331    
1332  static uint8 *          image = XCreateImage(display, visual, depth, ZPixmap,
1333  translate(int width, int height, uint8 *data)                               0, data, cx, cy, BitmapPad(display),
1334  {                               cx * bpp / 8);
         uint32 i;  
         uint32 size = width * height;  
         uint8 *d2 = xmalloc(size * bpp/8);  
         uint8 *d3 = d2;  
         uint32 pix;  
         i = (size & ~0x7);  
   
         /* XXX: where are the bits swapped??? */  
 #ifdef L_ENDIAN                 /* little-endian */  
         /* big-endian screen */  
         if (screen_msbfirst)  
         {  
                 switch (bpp)  
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix >> 24;  
                                                     *d3++ = pix >> 16;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix;) i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      24;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix >> 16;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix;) i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix;) i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                 }  
         }  
         else  
         {                       /* little-endian screen */  
                 switch (bpp)  
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(*((uint32 *) d3) =  
                                                     colmap[*data++];  
                                                     d3 += sizeof(uint32);  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(*  
                                                                      ((uint32  
                                                                        *) d3)  
 = colmap[*data++];  
 d3 += sizeof(uint32);  
                                         )}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                         )}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                 }  
         }  
1335    
1336  #else /* bigendian-compiled */          if (ownbackstore)
         if (screen_msbfirst)  
1337          {          {
1338                  /* big-endian screen */                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1339                  switch (bpp)                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(*((uint32 *) d3) =  
                                                     colmap[*data++];  
                                                     d3 += sizeof(uint32);  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(*  
                                                                      ((uint32  
                                                                        *) d3)  
 = colmap[*data++];  
 d3 += sizeof(uint32);  
                                         )}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                         )}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                 }  
1340          }          }
1341          else          else
1342          {          {
1343                  /* little-endian screen */                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
                 switch (bpp)  
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                     *d3++ = pix >> 24;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      24;)}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                         )}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                 }  
1344          }          }
 #endif  
1345    
1346          return d2;          XFree(image);
1347  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26