/[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 81 by jsorg71, Tue Jul 30 01:57:39 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 21  Line 21 
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23  #include <time.h>  #include <time.h>
24    #include <errno.h>
25    #define XK_MISCELLANY
26    #include <X11/keysymdef.h>
27  #include "rdesktop.h"  #include "rdesktop.h"
28    #include "scancodes.h"
29    
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;
34  extern int private_colormap;  extern BOOL grab_keyboard;
35    
36  static int bpp;  Display *display = NULL;
37  static int depth;  static int x_socket;
 static Display *display;  
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;
43    
44  #define Ctrans(col) ( private_colormap ? col : colmap[col])  /* endianness */
45    static BOOL host_be;
46    static BOOL xserver_be;
47    
48    /* software backing store */
49    static BOOL ownbackstore;
50    static Pixmap backstore;
51    
52    #define FILL_RECTANGLE(x,y,cx,cy)\
53    { \
54            XFillRectangle(display, wnd, gc, x, y, cx, cy); \
55            if (ownbackstore) \
56                    XFillRectangle(display, backstore, gc, x, y, cx, cy); \
57    }
58    
59    /* colour maps */
60    static BOOL owncolmap;
61    static Colormap xcolmap;
62    static uint32 white;
63    static uint32 *colmap;
64    static XIM IM = NULL;
65    static XIC IC = NULL;
66    
67  #define L_ENDIAN  /* Compose support */
68  int screen_msbfirst = 0;  BOOL enable_compose = False;
69    
70  static uint8 *translate(int width, int height, uint8 *data);  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )
71    #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
72    #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
73    
74  static int rop2_map[] = {  static int rop2_map[] = {
75          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 64  static int rop2_map[] = { Line 90  static int rop2_map[] = {
90          GXset                   /* 1 */          GXset                   /* 1 */
91  };  };
92    
93    #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
94    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
95    
96    static void
97    translate8(uint8 * data, uint8 * out, uint8 * end)
98    {
99            while (out < end)
100                    *(out++) = (uint8) colmap[*(data++)];
101    }
102    
103    static void
104    translate16(uint8 * data, uint16 * out, uint16 * end)
105    {
106            while (out < end)
107                    *(out++) = (uint16) colmap[*(data++)];
108    }
109    
110    /* little endian - conversion happens when colourmap is built */
111  static void  static void
112  xwin_set_function(uint8 rop2)  translate24(uint8 * data, uint8 * out, uint8 * end)
113  {  {
114          static uint8 last_rop2 = ROP2_COPY;          uint32 value;
115    
116          if (last_rop2 != rop2)          while (out < end)
117          {          {
118                  XSetFunction(display, gc, rop2_map[rop2]);                  value = colmap[*(data++)];
119                  last_rop2 = rop2;                  *(out++) = value;
120                    *(out++) = value >> 8;
121                    *(out++) = value >> 16;
122          }          }
123  }  }
124    
125  static void  static void
126  xwin_grab_keyboard()  translate32(uint8 * data, uint32 * out, uint32 * end)
127  {  {
128          XGrabKeyboard(display, wnd, True, GrabModeAsync, GrabModeAsync,          while (out < end)
129                        CurrentTime);                  *(out++) = colmap[*(data++)];
130    }
131    
132    static uint8 *
133    translate_image(int width, int height, uint8 * data)
134    {
135            int size = width * height * bpp / 8;
136            uint8 *out = xmalloc(size);
137            uint8 *end = out + size;
138    
139            switch (bpp)
140            {
141                    case 8:
142                            translate8(data, out, end);
143                            break;
144    
145                    case 16:
146                            translate16(data, (uint16 *) out, (uint16 *) end);
147                            break;
148    
149                    case 24:
150                            translate24(data, out, end);
151                            break;
152    
153                    case 32:
154                            translate32(data, (uint32 *) out, (uint32 *) end);
155                            break;
156            }
157    
158            return out;
159    }
160    
161    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
162    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
163    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
164                            x = (x << 16) | (x >> 16); }
165    
166    static uint32
167    translate_colour(uint32 colour)
168    {
169            switch (bpp)
170            {
171                    case 16:
172                            if (host_be != xserver_be)
173                                    BSWAP16(colour);
174                            break;
175    
176                    case 24:
177                            if (xserver_be)
178                                    BSWAP24(colour);
179                            break;
180    
181                    case 32:
182                            if (host_be != xserver_be)
183                                    BSWAP32(colour);
184                            break;
185            }
186    
187            return colour;
188    }
189    
190    static unsigned long
191    init_inputmethod(void)
192    {
193            unsigned long filtered_events = 0;
194    
195            IM = XOpenIM(display, NULL, NULL, NULL);
196            if (IM == NULL)
197            {
198                    error("Failed to open input method\n");
199            }
200    
201            if (IM != NULL)
202            {
203                    /* Must be done after XCreateWindow */
204                    IC = XCreateIC(IM, XNInputStyle,
205                                   (XIMPreeditNothing | XIMStatusNothing),
206                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
207    
208                    if (IC == NULL)
209                    {
210                            error("Failed to create input context\n");
211                            XCloseIM(IM);
212                            IM = NULL;
213                    }
214            }
215    
216            /* For correct Multi_key/Compose processing, I guess.
217               It seems to work alright anyway, though. */
218            if (IC != NULL)
219            {
220                    if (XGetICValues(IC, XNFilterEvents, &filtered_events, NULL)
221                        != NULL)
222                    {
223                            error("Failed to obtain XNFilterEvents value from IC\n");
224                            filtered_events = 0;
225                    }
226            }
227            return filtered_events;
228  }  }
229    
230  static void  static void
231  xwin_ungrab_keyboard()  close_inputmethod(void)
232  {  {
233          XUngrabKeyboard(display, CurrentTime);          if (IC != NULL)
234            {
235                    XDestroyIC(IC);
236                    if (IM != NULL)
237                    {
238                            XCloseIM(IM);
239                            IM = NULL;
240                    }
241            }
242    }
243    
244    BOOL
245    ui_init()
246    {
247            Screen *screen;
248            display = XOpenDisplay(NULL);
249            if (display == NULL)
250            {
251                    error("Failed to open display\n");
252                    return False;
253            }
254            if(fullscreen)
255            {
256                    screen = DefaultScreenOfDisplay(display);
257                    width = WidthOfScreen(screen);
258                    height = HeightOfScreen(screen);
259            }
260            return True;
261  }  }
262    
263  BOOL  BOOL
# Line 97  ui_create_window(char *title) Line 268  ui_create_window(char *title)
268          XSizeHints *sizehints;          XSizeHints *sizehints;
269          unsigned long input_mask;          unsigned long input_mask;
270          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
271          int count;          Screen *screen;
272            uint16 test;
273            int i;
274    
275            x_socket = ConnectionNumber(display);
276            screen = DefaultScreenOfDisplay(display);
277            visual = DefaultVisualOfScreen(screen);
278            depth = DefaultDepthOfScreen(screen);
279    
280          display = XOpenDisplay(NULL);          pfm = XListPixmapFormats(display, &i);
         if (display == NULL)  
         {  
                 ERROR("Failed to open display\n");  
                 return False;  
         }  
   
         visual = DefaultVisual(display, DefaultScreen(display));  
         depth = DefaultDepth(display, DefaultScreen(display));  
         pfm = XListPixmapFormats(display, &count);  
281          if (pfm != NULL)          if (pfm != NULL)
282          {          {
283                  while (count--)                  /* Use maximum bpp for this depth - this is generally
284                       desirable, e.g. 24 bits->32 bits. */
285                    while (i--)
286                  {                  {
287                          if ((pfm + count)->depth == depth                          if ((pfm[i].depth == depth)
288                              && (pfm + count)->bits_per_pixel > bpp)                              && (pfm[i].bits_per_pixel > bpp))
289                          {                          {
290                                  bpp = (pfm + count)->bits_per_pixel;                                  bpp = pfm[i].bits_per_pixel;
291                          }                          }
292                  }                  }
293                  XFree(pfm);                  XFree(pfm);
# Line 124  ui_create_window(char *title) Line 295  ui_create_window(char *title)
295    
296          if (bpp < 8)          if (bpp < 8)
297          {          {
298                  ERROR("Less than 8 bpp not currently supported.\n");                  error("Less than 8 bpp not currently supported.\n");
299                  XCloseDisplay(display);                  XCloseDisplay(display);
300                  return False;                  return False;
301          }          }
302    
303          width &= ~3; /* make width nicely divisible */          if (depth <= 8)
304                    owncolmap = True;
305            else
306                    xcolmap = DefaultColormapOfScreen(screen);
307    
308            test = 1;
309            host_be = !(BOOL) (*(uint8 *) (&test));
310            xserver_be = (ImageByteOrder(display) == MSBFirst);
311    
312            white = WhitePixelOfScreen(screen);
313            attribs.background_pixel = BlackPixelOfScreen(screen);
314            attribs.backing_store = DoesBackingStore(screen);
315    
316          attribs.background_pixel = BlackPixel(display, DefaultScreen(display));          if (attribs.backing_store == NotUseful)
317          attribs.backing_store = Always;                  ownbackstore = True;
318    
319          if (fullscreen)          if (fullscreen)
320          {          {
321                  attribs.override_redirect = True;                  attribs.override_redirect = True;
322                  width = WidthOfScreen(DefaultScreenOfDisplay(display));                  width = WidthOfScreen(screen);
323                  height = HeightOfScreen(DefaultScreenOfDisplay(display));                  height = HeightOfScreen(screen);
                 XSetInputFocus(display, PointerRoot, RevertToPointerRoot,  
                                CurrentTime);  
324          }          }
325          else          else
326          {          {
327                  attribs.override_redirect = False;                  attribs.override_redirect = False;
328          }          }
329    
330          wnd = XCreateWindow(display, DefaultRootWindow(display),          width = (width + 3) & ~3;       /* make width a multiple of 32 bits */
331    
332            wnd = XCreateWindow(display, RootWindowOfScreen(screen),
333                              0, 0, width, height, 0, CopyFromParent,                              0, 0, width, height, 0, CopyFromParent,
334                              InputOutput, CopyFromParent,                              InputOutput, CopyFromParent,
335                              CWBackingStore | CWBackPixel | CWOverrideRedirect,                              CWBackingStore | CWBackPixel | CWOverrideRedirect,
# Line 157  ui_create_window(char *title) Line 339  ui_create_window(char *title)
339    
340          classhints = XAllocClassHint();          classhints = XAllocClassHint();
341          if (classhints != NULL)          if (classhints != NULL)
   
342          {          {
343                  classhints->res_name = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
                 classhints->res_class = "rdesktop";  
344                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(display, wnd, classhints);
345                  XFree(classhints);                  XFree(classhints);
346          }          }
# Line 168  ui_create_window(char *title) Line 348  ui_create_window(char *title)
348          sizehints = XAllocSizeHints();          sizehints = XAllocSizeHints();
349          if (sizehints)          if (sizehints)
350          {          {
351                  sizehints->flags =                  sizehints->flags = PMinSize | PMaxSize;
352                          PPosition | PSize | PMinSize | PMaxSize | PBaseSize;                  sizehints->min_width = sizehints->max_width = width;
353                  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;  
354                  XSetWMNormalHints(display, wnd, sizehints);                  XSetWMNormalHints(display, wnd, sizehints);
355                  XFree(sizehints);                  XFree(sizehints);
356          }          }
357    
358          input_mask = KeyPressMask | KeyReleaseMask;          xkeymap_init2();
359          input_mask |= ButtonPressMask | ButtonReleaseMask;  
360          if (motion)          input_mask =
361                  input_mask |= PointerMotionMask;                  KeyPressMask | KeyReleaseMask | ButtonPressMask |
362                    ButtonReleaseMask;
363          if (grab_keyboard)          if (grab_keyboard)
364                  input_mask |= EnterWindowMask | LeaveWindowMask;                  input_mask |= EnterWindowMask | LeaveWindowMask;
365            if (sendmotion)
366                    input_mask |= PointerMotionMask;
367    
368            if (ownbackstore)
369                    input_mask |= ExposureMask;
370    
371            if (enable_compose)
372                    input_mask |= init_inputmethod();
373    
374          XSelectInput(display, wnd, input_mask);          XSelectInput(display, wnd, input_mask);
375    
376          gc = XCreateGC(display, wnd, 0, NULL);          gc = XCreateGC(display, wnd, 0, NULL);
377    
378            if (ownbackstore)
379                    backstore = XCreatePixmap(display, wnd, width, height, depth);
380    
381          XMapWindow(display, wnd);          XMapWindow(display, wnd);
382    
383          return True;          return True;
384  }  }
385    
386  void  void
387  ui_destroy_window()  ui_destroy_window()
388  {  {
389            if (ownbackstore)
390                    XFreePixmap(display, backstore);
391    
392          XFreeGC(display, gc);          XFreeGC(display, gc);
393    
394            close_inputmethod();
395    
396          XDestroyWindow(display, wnd);          XDestroyWindow(display, wnd);
397          XCloseDisplay(display);          XCloseDisplay(display);
398          display = NULL;          display = NULL;
399  }  }
400    
401  static uint8  static void
402  xwin_translate_key(unsigned long key)  xwin_process_events()
403  {  {
404          DEBUG("KEY(code=0x%lx)\n", key);          XEvent xevent;
   
         if ((key > 8) && (key <= 0x60))  
                 return (key - 8);  
405    
406          switch (key)          KeySym keysym;
407          {          uint16 button, flags;
                 case 0x61:      /* home */  
                         return 0x47 | 0x80;  
                 case 0x62:      /* up arrow */  
                         return 0x48 | 0x80;  
                 case 0x63:      /* page up */  
                         return 0x49 | 0x80;  
                 case 0x64:      /* left arrow */  
                         return 0x4b | 0x80;  
                 case 0x66:      /* right arrow */  
                         return 0x4d | 0x80;  
                 case 0x67:      /* end */  
                         return 0x4f | 0x80;  
                 case 0x68:      /* down arrow */  
                         return 0x50 | 0x80;  
                 case 0x69:      /* page down */  
                         return 0x51 | 0x80;  
                 case 0x6a:      /* insert */  
                         return 0x52 | 0x80;  
                 case 0x6b:      /* delete */  
                         return 0x53 | 0x80;  
                 case 0x6c:      /* keypad enter */  
                         return 0x1c | 0x80;  
                 case 0x6d:      /* right ctrl */  
                         return 0x1d | 0x80;  
                 case 0x6f:      /* ctrl - print screen */  
                         return 0x37 | 0x80;  
                 case 0x70:      /* keypad '/' */  
                         return 0x35 | 0x80;  
                 case 0x71:      /* right alt */  
                         return 0x38 | 0x80;  
                 case 0x72:      /* ctrl break */  
                         return 0x46 | 0x80;  
                 case 0x73:      /* left window key */  
                         return 0xff;    /* real scancode is 5b */  
                 case 0x74:      /* right window key */  
                         return 0xff;    /* real scancode is 5c */  
                 case 0x75:      /* menu key */  
                         return 0x5d | 0x80;  
         }  
   
         return 0;  
 }  
   
 static uint16  
 xwin_translate_mouse(unsigned long button)  
 {  
         switch (button)  
         {  
                 case Button1:   /* left */  
                         return MOUSE_FLAG_BUTTON1;  
                 case Button2:   /* middle */  
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3:   /* right */  
                         return MOUSE_FLAG_BUTTON2;  
         }  
   
         return 0;  
 }  
   
 void  
 ui_process_events()  
 {  
         XEvent event;  
         uint8 scancode;  
         uint16 button;  
408          uint32 ev_time;          uint32 ev_time;
409            key_translation tr;
410            char *ksname = NULL;
411            char str[256];
412            Status status;
413    
414          if (display == NULL)          /* Refresh keyboard mapping if it has changed. This is important for
415                  return;             Xvnc, since it allocates keycodes dynamically */
416            if (XCheckTypedEvent(display, MappingNotify, &xevent))
417            {
418                    if (xevent.xmapping.request == MappingKeyboard
419                        || xevent.xmapping.request == MappingModifier)
420                            XRefreshKeyboardMapping(&xevent.xmapping);
421            }
422    
423          while (XCheckWindowEvent(display, wnd, ~0, &event))          while (XCheckMaskEvent(display, ~0, &xevent))
424          {          {
425                    if (enable_compose && (XFilterEvent(&xevent, None) == True))
426                    {
427                            DEBUG_KBD("Filtering event\n");
428                            continue;
429                    }
430    
431                  ev_time = time(NULL);                  ev_time = time(NULL);
432                    flags = 0;
433    
434                  switch (event.type)                  switch (xevent.type)
435                  {                  {
436                          case KeyPress:                          case KeyPress:
437                                  scancode = xwin_translate_key(event.xkey.keycode);                                  if (IC != NULL)
438                                  if (scancode == 0)                                          /* Multi_key compatible version */
439                                    {
440                                            XmbLookupString(IC,
441                                                            (XKeyPressedEvent *) &
442                                                            xevent, str,
443                                                            sizeof(str), &keysym,
444                                                            &status);
445                                            if (!
446                                                ((status == XLookupKeySym)
447                                                 || (status == XLookupBoth)))
448                                            {
449                                                    error("XmbLookupString failed with status 0x%x\n", status);
450                                                    break;
451                                            }
452                                    }
453                                    else
454                                    {
455                                            /* Plain old XLookupString */
456                                            DEBUG_KBD
457                                                    ("No input context, using XLookupString\n");
458                                            XLookupString((XKeyEvent *) & xevent,
459                                                          str, sizeof(str),
460                                                          &keysym, NULL);
461                                    }
462    
463                                    ksname = get_ksname(keysym);
464                                    DEBUG_KBD
465                                            ("\nKeyPress for (keysym 0x%lx, %s)\n",
466                                             keysym, ksname);
467    
468                                    if (inhibit_key(keysym))
469                                    {
470                                            DEBUG_KBD("Inhibiting key\n");
471                                          break;                                          break;
472                                    }
473    
474                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  tr = xkeymap_translate_key(keysym,
475                                                 scancode, 0);                                                             xevent.xkey.
476                                  break;                                                             keycode,
477                                                               xevent.xkey.state);
478    
479                          case KeyRelease:                                  ensure_remote_modifiers(ev_time, tr);
480                                  scancode = xwin_translate_key(event.xkey.keycode);  
481                                  if (scancode == 0)                                  if (tr.scancode == 0)
482                                          break;                                          break;
483    
484                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  rdp_send_scancode(ev_time, RDP_KEYPRESS,
485                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                    tr.scancode);
                                                scancode, 0);  
486                                  break;                                  break;
487                            case KeyRelease:
488                                    XLookupString((XKeyEvent *) & xevent, str,
489                                                  sizeof(str), &keysym, NULL);
490    
491                          case ButtonPress:                                  ksname = get_ksname(keysym);
492                                  button = xwin_translate_mouse(event.xbutton.button);                                  DEBUG_KBD
493                                  if (button == 0)                                          ("\nKeyRelease for (keysym 0x%lx, %s)\n",
494                                             keysym, ksname);
495    
496                                    if (inhibit_key(keysym))
497                                          break;                                          break;
498    
499                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  tr = xkeymap_translate_key(keysym,
500                                                 button | MOUSE_FLAG_DOWN,                                                             xevent.xkey.
501                                                 event.xbutton.x,                                                             keycode,
502                                                 event.xbutton.y);                                                             xevent.xkey.state);
503    
504                                    if (tr.scancode == 0)
505                                            break;
506    
507                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE,
508                                                      tr.scancode);
509                                  break;                                  break;
510    
511                            case ButtonPress:
512                                    flags = MOUSE_FLAG_DOWN;
513                                    /* fall through */
514    
515                          case ButtonRelease:                          case ButtonRelease:
516                                  button = xwin_translate_mouse(event.xbutton.button);                                  button = xkeymap_translate_button(xevent.
517                                                                      xbutton.
518                                                                      button);
519                                  if (button == 0)                                  if (button == 0)
520                                          break;                                          break;
521    
522                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
523                                                 button,                                                 flags | button,
524                                                 event.xbutton.x,                                                 xevent.xbutton.x,
525                                                 event.xbutton.y);                                                 xevent.xbutton.y);
526                                  break;                                  break;
527    
528                          case MotionNotify:                          case MotionNotify:
529                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
530                                                 MOUSE_FLAG_MOVE,                                                 MOUSE_FLAG_MOVE,
531                                                 event.xmotion.x,                                                 xevent.xmotion.x,
532                                                 event.xmotion.y);                                                 xevent.xmotion.y);
533                                  break;                                  break;
534    
535                            case FocusIn:
536                                    /* fall through */
537                          case EnterNotify:                          case EnterNotify:
538                                  if (grab_keyboard)                                  if (grab_keyboard)
539                                          xwin_grab_keyboard();                                          XGrabKeyboard(display, wnd, True,
540                                                          GrabModeAsync,
541                                                          GrabModeAsync,
542                                                          CurrentTime);
543                                  break;                                  break;
544    
545                            case FocusOut:
546                                    /* reset keys */
547                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
548                                                   KBD_FLAG_DOWN | KBD_FLAG_UP,
549                                                   SCANCODE_CHAR_LCTRL, 0);
550                                    rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
551                                                   KBD_FLAG_DOWN | KBD_FLAG_UP,
552                                                   SCANCODE_CHAR_LALT, 0);
553                                    /* fall through */
554                          case LeaveNotify:                          case LeaveNotify:
555                                  if (grab_keyboard)                                  if (grab_keyboard)
556                                          xwin_ungrab_keyboard();                                          XUngrabKeyboard(display, CurrentTime);
557                                  break;                                  break;
558    
559                            case Expose:
560                                    XCopyArea(display, backstore, wnd, gc,
561                                              xevent.xexpose.x, xevent.xexpose.y,
562                                              xevent.xexpose.width,
563                                              xevent.xexpose.height,
564                                              xevent.xexpose.x, xevent.xexpose.y);
565                                    break;
566                    }
567            }
568    }
569    
570    void
571    ui_select(int rdp_socket)
572    {
573            int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
574            fd_set rfds;
575    
576            FD_ZERO(&rfds);
577    
578            while (True)
579            {
580                    FD_ZERO(&rfds);
581                    FD_SET(rdp_socket, &rfds);
582                    if (display != NULL)
583                    {
584                            FD_SET(x_socket, &rfds);
585                            XFlush(display);
586                  }                  }
587    
588                    switch (select(n, &rfds, NULL, NULL, NULL))
589                    {
590                            case -1:
591                                    error("select: %s\n", strerror(errno));
592    
593                            case 0:
594                                    continue;
595                    }
596    
597                    if (FD_ISSET(x_socket, &rfds))
598                            xwin_process_events();
599    
600                    if (FD_ISSET(rdp_socket, &rfds))
601                            return;
602          }          }
603  }  }
604    
# Line 357  ui_move_pointer(int x, int y) Line 609  ui_move_pointer(int x, int y)
609  }  }
610    
611  HBITMAP  HBITMAP
612  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
613  {  {
614          XImage *image;          XImage *image;
615          Pixmap bitmap;          Pixmap bitmap;
616          uint8 *tdata;          uint8 *tdata;
617          tdata = (private_colormap ? data : translate(width, height, data));  
618            tdata = (owncolmap ? data : translate_image(width, height, data));
619          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(display, wnd, width, height, depth);
620          image =          image = XCreateImage(display, visual, depth, ZPixmap, 0,
621                  XCreateImage(display, visual,                               (char *) tdata, width, height, 8, 0);
                              depth, ZPixmap,  
                              0, tdata, width, height, BitmapPad(display), 0);  
622    
         xwin_set_function(ROP2_COPY);  
623          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
624    
625          XFree(image);          XFree(image);
626          if (!private_colormap)          if (!owncolmap)
627                  xfree(tdata);                  xfree(tdata);
628          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
629  }  }
630    
631  void  void
632  ui_paint_bitmap(int x, int y, int cx, int cy,  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height,
633                  int width, int height, uint8 *data)                  uint8 * data)
634  {  {
635          XImage *image;          XImage *image;
636          uint8 *tdata =          uint8 *tdata;
                 (private_colormap ? data : translate(width, height, data));  
         image =  
                 XCreateImage(display, visual, depth, ZPixmap, 0, tdata, width,  
                              height, BitmapPad(display), 0);  
   
         xwin_set_function(ROP2_COPY);  
   
         /* Window */  
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
         XFree(image);  
         if (!private_colormap)  
                 xfree(tdata);  
 }  
   
 void  
 ui_destroy_bitmap(HBITMAP bmp)  
 {  
         XFreePixmap(display, (Pixmap) bmp);  
 }  
637    
638  HCURSOR          tdata = (owncolmap ? data : translate_image(width, height, data));
639  ui_create_cursor(unsigned int x, unsigned int y, int width,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
640                   int height, uint8 *mask, uint8 *data)                               (char *) tdata, width, height, 8, 0);
 {  
         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;  
641    
642          if (!screen_msbfirst)          if (ownbackstore)
643          {          {
644                  while (i >= 0)                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
645                  {                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
                         for (x1 = 0; x1 < scanlinelen; x1++)  
                         {  
                                 c = *(mask++);  
                                 cmask[i + x1] =  
                                         ((c & 0x1) << 7) | ((c & 0x2) << 5) |  
                                         ((c & 0x4) << 3) | ((c & 0x8) << 1) |  
                                         ((c & 0x10) >> 1) | ((c & 0x20) >> 3)  
                                         | ((c & 0x40) >> 5) | ((c & 0x80) >>  
                                                                7);  
                         }  
                         i -= scanlinelen;  
                 }  
646          }          }
647          else          else
648          {          {
649                  while (i >= 0)                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
                 {  
                         for (x1 = 0; x1 < scanlinelen; x1++)  
                         {  
                                 cmask[i + x1] = *(mask++);  
                         }  
                         i -= scanlinelen;  
                 }  
650          }          }
651    
652            XFree(image);
653          fg.red = 0;          if (!owncolmap)
654          fg.blue = 0;                  xfree(tdata);
         fg.green = 0;  
         fg.flags = DoRed | DoBlue | DoGreen;  
         bg.red = 65535;  
         bg.blue = 65535;  
         bg.green = 65535;  
         bg.flags = DoRed | DoBlue | DoGreen;  
         maskbitmap = XCreatePixmap(display, wnd, width, height, 1);  
         cursorbitmap = XCreatePixmap(display, wnd, width, height, 1);  
         lgc = XCreateGC(display, maskbitmap, 0, NULL);  
         XSetFunction(display, lgc, GXcopy);  
         imagemask =  
                 XCreateImage(display, visual, 1, XYBitmap, 0, cmask, width,  
                              height, 8, 0);  
         imagecursor =  
                 XCreateImage(display, visual, 1, XYBitmap, 0, cdata, width,  
                              height, 8, 0);  
         for (y1 = height - 1; y1 >= 0; y1--)  
                 for (x1 = 0; x1 < width; x1++)  
                 {  
                         if (data[0] >= 0x80 || data[1] >= 0x80  
                             || data[2] >= 0x80)  
                                 if (XGetPixel(imagemask, x1, y1))  
   
                                 {  
                                         XPutPixel(imagecursor, x1, y1, 0);  
                                         XPutPixel(imagemask, x1, y1, 0);        /* mask is blank for text cursor! */  
                                 }  
   
                                 else  
                                         XPutPixel(imagecursor, x1, y1, 1);  
   
                         else  
                                 XPutPixel(imagecursor, x1, y1,  
                                           XGetPixel(imagemask, x1, y1));  
                         data += 3;  
                 }  
         XPutImage(display, maskbitmap, lgc, imagemask, 0, 0, 0, 0, width,  
                   height);  
         XPutImage(display, cursorbitmap, lgc, imagecursor, 0, 0, 0, 0, width,  
                   height); XFree(imagemask);  
         XFree(imagecursor);  
         free(cmask);  
         free(cdata);  
         XFreeGC(display, lgc);  
         cursor =  
                 XCreatePixmapCursor(display, cursorbitmap, maskbitmap, &fg,  
                                     &bg, x, y);  
         XFreePixmap(display, maskbitmap);  
         XFreePixmap(display, cursorbitmap);  
         return (HCURSOR) cursor;  
 }  
   
 void  
 ui_set_cursor(HCURSOR cursor)  
 {  
         XDefineCursor(display, wnd, (Cursor) cursor);  
655  }  }
656    
657  void  void
658  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_bitmap(HBITMAP bmp)
659  {  {
660          XFreeCursor(display, (Cursor) cursor);          XFreePixmap(display, (Pixmap) bmp);
661  }  }
662    
663  HGLYPH  HGLYPH
664  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
665  {  {
666          XImage *image;          XImage *image;
667          Pixmap bitmap;          Pixmap bitmap;
# Line 538  ui_create_glyph(int width, int height, u Line 673  ui_create_glyph(int width, int height, u
673          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
674          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
675    
676          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
677                               data, width, height, 8, scanline);                               width, height, 8, scanline);
678          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
679          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
680          XInitImage(image);          XInitImage(image);
681    
         XSetFunction(display, gc, GXcopy);  
682          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
683    
684          XFree(image);          XFree(image);
685          XFreeGC(display, gc);          XFreeGC(display, gc);
   
686          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
687  }  }
688    
# Line 558  ui_destroy_glyph(HGLYPH glyph) Line 692  ui_destroy_glyph(HGLYPH glyph)
692          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(display, (Pixmap) glyph);
693  }  }
694    
695  HCOLOURMAP  HCURSOR
696  ui_create_colourmap(COLOURMAP *colours)  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
697                     uint8 * andmask, uint8 * xormask)
698  {  {
699          if (!private_colormap)          HGLYPH maskglyph, cursorglyph;
700            XColor bg, fg;
701            Cursor xcursor;
702            uint8 *cursor, *pcursor;
703            uint8 *mask, *pmask;
704            uint8 nextbit;
705            int scanline, offset;
706            int i, j;
707    
708            scanline = (width + 7) / 8;
709            offset = scanline * height;
710    
711            cursor = xmalloc(offset);
712            memset(cursor, 0, offset);
713    
714            mask = xmalloc(offset);
715            memset(mask, 0, offset);
716    
717            /* approximate AND and XOR masks with a monochrome X pointer */
718            for (i = 0; i < height; i++)
719          {          {
720                  COLOURENTRY *entry;                  offset -= scanline;
721                  int i, ncolours = colours->ncolours;                  pcursor = &cursor[offset];
722                  uint32 *nc = xmalloc(sizeof(*colmap) * ncolours);                  pmask = &mask[offset];
723                  for (i = 0; i < ncolours; i++)  
724                    for (j = 0; j < scanline; j++)
725                  {                  {
726                          XColor xc;                          for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
727                          entry = &colours->colours[i];                          {
728                          xc.red = entry->red << 8;                                  if (xormask[0] || xormask[1] || xormask[2])
729                          xc.green = entry->green << 8;                                  {
730                          xc.blue = entry->blue << 8;                                          *pcursor |= (~(*andmask) & nextbit);
731                          XAllocColor(display,                                          *pmask |= nextbit;
732                                      DefaultColormap(display,                                  }
733                                                      DefaultScreen(display)),                                  else
734                                      &xc);                                  {
735                          /* XXX Check return value */                                          *pcursor |= ((*andmask) & nextbit);
736                          nc[i] = xc.pixel;                                          *pmask |= (~(*andmask) & nextbit);
737                                    }
738    
739                                    xormask += 3;
740                            }
741    
742                            andmask++;
743                            pcursor++;
744                            pmask++;
745                  }                  }
                 return nc;  
746          }          }
747          else  
748            fg.red = fg.blue = fg.green = 0xffff;
749            bg.red = bg.blue = bg.green = 0x0000;
750            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
751    
752            cursorglyph = ui_create_glyph(width, height, cursor);
753            maskglyph = ui_create_glyph(width, height, mask);
754    
755            xcursor =
756                    XCreatePixmapCursor(display, (Pixmap) cursorglyph,
757                                        (Pixmap) maskglyph, &fg, &bg, x, y);
758    
759            ui_destroy_glyph(maskglyph);
760            ui_destroy_glyph(cursorglyph);
761            xfree(mask);
762            xfree(cursor);
763            return (HCURSOR) xcursor;
764    }
765    
766    void
767    ui_set_cursor(HCURSOR cursor)
768    {
769            XDefineCursor(display, wnd, (Cursor) cursor);
770    }
771    
772    void
773    ui_destroy_cursor(HCURSOR cursor)
774    {
775            XFreeCursor(display, (Cursor) cursor);
776    }
777    
778    #define MAKE_XCOLOR(xc,c) \
779                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
780                    (xc)->green = ((c)->green << 8) | (c)->green; \
781                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
782                    (xc)->flags = DoRed | DoGreen | DoBlue;
783    
784    HCOLOURMAP
785    ui_create_colourmap(COLOURMAP * colours)
786    {
787            COLOURENTRY *entry;
788            int i, ncolours = colours->ncolours;
789    
790            if (owncolmap)
791          {          {
                 COLOURENTRY *entry;  
792                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
793                  Colormap map;                  Colormap map;
794                  int i, ncolours = colours->ncolours;  
795                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = xmalloc(sizeof(XColor) * ncolours);
796                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
797                  {                  {
798                          entry = &colours->colours[i];                          entry = &colours->colours[i];
799                          xentry = &xcolours[i];                          xentry = &xcolours[i];
   
800                          xentry->pixel = i;                          xentry->pixel = i;
801                          xentry->red = entry->red << 8;                          MAKE_XCOLOR(xentry, entry);
                         xentry->blue = entry->blue << 8;  
                         xentry->green = entry->green << 8;  
                         xentry->flags = DoRed | DoBlue | DoGreen;  
802                  }                  }
803    
804                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(display, wnd, visual, AllocAll);
# Line 607  ui_create_colourmap(COLOURMAP *colours) Line 807  ui_create_colourmap(COLOURMAP *colours)
807                  xfree(xcolours);                  xfree(xcolours);
808                  return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
809          }          }
810            else
811            {
812                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
813                    XColor xentry;
814                    uint32 colour;
815    
816                    for (i = 0; i < ncolours; i++)
817                    {
818                            entry = &colours->colours[i];
819                            MAKE_XCOLOR(&xentry, entry);
820    
821                            if (XAllocColor(display, xcolmap, &xentry) != 0)
822                                    colour = xentry.pixel;
823                            else
824                                    colour = white;
825    
826                            /* byte swap here to make translate_image faster */
827                            map[i] = translate_colour(colour);
828                    }
829    
830                    return map;
831            }
832  }  }
833    
834  void  void
835  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
836  {  {
837          XFreeColormap(display, (Colormap) map);          if (owncolmap)
838                    XFreeColormap(display, (Colormap) map);
839            else
840                    xfree(map);
841  }  }
842    
843  void  void
844  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
845  {  {
846            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  
         {  
847                  XSetWindowColormap(display, wnd, (Colormap) map);                  XSetWindowColormap(display, wnd, (Colormap) map);
848                  if (fullscreen)          else
849                          XInstallColormap(display, (Colormap) map);                  colmap = map;
         }  
850  }  }
851    
852  void  void
# Line 665  void Line 883  void
883  ui_destblt(uint8 opcode,  ui_destblt(uint8 opcode,
884             /* dest */ int x, int y, int cx, int cy)             /* dest */ int x, int y, int cx, int cy)
885  {  {
886          xwin_set_function(opcode);          SET_FUNCTION(opcode);
887            FILL_RECTANGLE(x, y, cx, cy);
888          XFillRectangle(display, wnd, gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
889  }  }
890    
891  void  void
892  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
893            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
894            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
895  {  {
         Display *dpy = display;  
896          Pixmap fill;          Pixmap fill;
897          uint8 i, ipattern[8];          uint8 i, ipattern[8];
898    
899          xwin_set_function(opcode);          SET_FUNCTION(opcode);
900    
901          switch (brush->style)          switch (brush->style)
902          {          {
903                  case 0: /* Solid */                  case 0: /* Solid */
904                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_FOREGROUND(fgcolour);
905                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
906                          break;                          break;
907    
908                  case 3: /* Pattern */                  case 3: /* Pattern */
909                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
910                                  ipattern[i] = ~brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
911                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
912    
913                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_FOREGROUND(bgcolour);
914                          XSetBackground(dpy, gc, Ctrans(bgcolour));                          SET_BACKGROUND(fgcolour);
915                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                          XSetFillStyle(display, gc, FillOpaqueStippled);
916                          XSetStipple(dpy, gc, fill);                          XSetStipple(display, gc, fill);
917                            XSetTSOrigin(display, gc, brush->xorigin,
918                                         brush->yorigin);
919    
920                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
921    
922                          XSetFillStyle(dpy, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
923                            XSetTSOrigin(display, gc, 0, 0);
924                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
925                          break;                          break;
926    
927                  default:                  default:
928                          NOTIMP("brush %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
929          }          }
930    
931            RESET_FUNCTION(opcode);
932  }  }
933    
934  void  void
# Line 714  ui_screenblt(uint8 opcode, Line 936  ui_screenblt(uint8 opcode,
936               /* dest */ int x, int y, int cx, int cy,               /* dest */ int x, int y, int cx, int cy,
937               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
938  {  {
939          xwin_set_function(opcode);          SET_FUNCTION(opcode);
   
940          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
941            if (ownbackstore)
942                    XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx,
943                              cy, x, y);
944            RESET_FUNCTION(opcode);
945  }  }
946    
947  void  void
# Line 724  ui_memblt(uint8 opcode, Line 949  ui_memblt(uint8 opcode,
949            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
950            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
951  {  {
952          xwin_set_function(opcode);          SET_FUNCTION(opcode);
   
953          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
954            if (ownbackstore)
955                    XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy,
956                              cx, cy, x, y);
957            RESET_FUNCTION(opcode);
958  }  }
959    
960  void  void
961  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
962            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
963            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
964            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
965  {  {
966          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
967             comes up with a more efficient way of doing it I am using cases. */             comes up with a more efficient way of doing it I am using cases. */
# Line 742  ui_triblt(uint8 opcode, Line 970  ui_triblt(uint8 opcode,
970          {          {
971                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
972                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
973                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour,
974                                    brush, bgcolour, fgcolour);                                    fgcolour);
975                          break;                          break;
976    
977                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
978                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour,
979                                    brush, bgcolour, fgcolour);                                    fgcolour);
980                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
981                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour,
982                                    brush, bgcolour, fgcolour);                                    fgcolour);
983                          break;                          break;
984    
985                  case 0xc0:                  case 0xc0:      /* PSa */
986                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
987                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
988                                    fgcolour);                                    fgcolour);
989                          break;                          break;
990    
991                  default:                  default:
992                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
993                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
994          }          }
995  }  }
# Line 769  ui_triblt(uint8 opcode, Line 997  ui_triblt(uint8 opcode,
997  void  void
998  ui_line(uint8 opcode,  ui_line(uint8 opcode,
999          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1000          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1001  {  {
1002          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1003            SET_FOREGROUND(pen->colour);
         XSetForeground(display, gc, Ctrans(pen->colour));  
1004          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1005            if (ownbackstore)
1006                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1007            RESET_FUNCTION(opcode);
1008  }  }
1009    
1010  void  void
# Line 782  ui_rect( Line 1012  ui_rect(
1012                 /* dest */ int x, int y, int cx, int cy,                 /* dest */ int x, int y, int cx, int cy,
1013                 /* brush */ int colour)                 /* brush */ int colour)
1014  {  {
1015          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(colour);
1016            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(display, gc, Ctrans(colour));  
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1017  }  }
1018    
1019  void  void
1020  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1021                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1022                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1023                int fgcolour)                int bgcolour, int fgcolour)
1024  {  {
1025          Pixmap pixmap = (Pixmap) glyph;          SET_FOREGROUND(fgcolour);
1026            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;  
   
                 case MIX_OPAQUE:  
                         XSetBackground(display, gc, Ctrans(bgcolour));  
 /*      XCopyPlane (display, pixmap, back_pixmap, back_gc, srcx, srcy, cx, cy, x, y, 1); */  
                         XSetStipple(display, gc, pixmap);  
                         XSetFillStyle(display, gc, FillOpaqueStippled);  
                         XSetTSOrigin(display, gc, x, y);  
                         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
                         XSetFillStyle(display, gc, FillSolid);  
                         break;  
1027    
1028                  default:          XSetFillStyle(display, gc,
1029                          NOTIMP("mix %d\n", mixmode);                        (mixmode ==
1030          }                         MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1031            XSetStipple(display, gc, (Pixmap) glyph);
1032            XSetTSOrigin(display, gc, x, y);
1033    
1034            FILL_RECTANGLE(x, y, cx, cy);
1035    
1036            XSetFillStyle(display, gc, FillSolid);
1037    }
1038    
1039    #define DO_GLYPH(ttext,idx) \
1040    {\
1041      glyph = cache_get_font (font, ttext[idx]);\
1042      if (!(flags & TEXT2_IMPLICIT_X))\
1043        {\
1044          xyoffset = ttext[++idx];\
1045          if ((xyoffset & 0x80))\
1046            {\
1047              if (flags & TEXT2_VERTICAL) \
1048                y += ttext[idx+1] | (ttext[idx+2] << 8);\
1049              else\
1050                x += ttext[idx+1] | (ttext[idx+2] << 8);\
1051              idx += 2;\
1052            }\
1053          else\
1054            {\
1055              if (flags & TEXT2_VERTICAL) \
1056                y += xyoffset;\
1057              else\
1058                x += xyoffset;\
1059            }\
1060        }\
1061      if (glyph != NULL)\
1062        {\
1063          ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1064                         y + (short) glyph->baseline,\
1065                         glyph->width, glyph->height,\
1066                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1067          if (flags & TEXT2_IMPLICIT_X)\
1068            x += glyph->width;\
1069        }\
1070  }  }
1071    
1072  void  void
1073  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,
1074               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
1075               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1076               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1077  {  {
1078          FONTGLYPH *glyph;          FONTGLYPH *glyph;
1079          int i, xyoffset;          int i, j, xyoffset;
1080            DATABLOB *entry;
1081    
1082          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(bgcolour);
         XSetForeground(display, gc, Ctrans(bgcolour));  
1083    
1084          if (boxcx > 1)          if (boxcx > 1)
1085                  XFillRectangle(display, wnd, gc, boxx, boxy, boxcx, boxcy);          {
1086                    FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1087            }
1088          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1089                  XFillRectangle(display, wnd, gc, clipx, clipy, clipcx, clipcy);          {
1090                    FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1091            }
1092    
1093          /* Paint text, character by character */          /* Paint text, character by character */
1094          for (i = 0; i < length; i++)          for (i = 0; i < length;)
1095          {          {
1096                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
   
1097                  {                  {
1098                          xyoffset = text[++i];                          case 0xff:
1099                          if ((xyoffset & 0x80))                                  if (i + 2 < length)
1100                          {                                          cache_put_text(text[i + 1], text,
1101                                  if (flags & 0x04)       /* vertical text */                                                         text[i + 2]);
                                         y += text[++i] | (text[++i] << 8);  
1102                                  else                                  else
1103                                          x += text[++i] | (text[++i] << 8);                                  {
1104                          }                                          error("this shouldn't be happening\n");
1105                          else                                          break;
1106                          {                                  }
1107                                  if (flags & 0x04)       /* vertical text */                                  /* this will move pointer from start to first character after FF command */
1108                                          y += xyoffset;                                  length -= i + 3;
1109                                  else                                  text = &(text[i + 3]);
1110                                          x += xyoffset;                                  i = 0;
1111                          }                                  break;
1112    
1113                  }                          case 0xfe:
1114                  if (glyph != NULL)                                  entry = cache_get_text(text[i + 1]);
1115                  {                                  if (entry != NULL)
1116                          ui_draw_glyph(mixmode, x + (short) glyph->offset,                                  {
1117                                        y + (short) glyph->baseline,                                          if ((((uint8 *) (entry->data))[1] ==
1118                                        glyph->width, glyph->height,                                               0)
1119                                        glyph->pixmap, 0, 0,                                              && (!(flags & TEXT2_IMPLICIT_X)))
1120                                        bgcolour, fgcolour);                                          {
1121                                                    if (flags & TEXT2_VERTICAL)
1122                                                            y += text[i + 2];
1123                                                    else
1124                                                            x += text[i + 2];
1125                                            }
1126                                            if (i + 2 < length)
1127                                                    i += 3;
1128                                            else
1129                                                    i += 2;
1130                                            length -= i;
1131                                            /* this will move pointer from start to first character after FE command */
1132                                            text = &(text[i]);
1133                                            i = 0;
1134                                            for (j = 0; j < entry->size; j++)
1135                                                    DO_GLYPH(((uint8 *) (entry->
1136                                                                         data)),
1137                                                             j);
1138                                    }
1139                                    break;
1140    
1141                          if (flags & TEXT2_IMPLICIT_X)                          default:
1142                                  x += glyph->width;                                  DO_GLYPH(text, i);
1143                                    i++;
1144                                    break;
1145                  }                  }
1146          }          }
1147    
1148    
1149  }  }
1150    
1151  void  void
# Line 887  ui_desktop_save(uint32 offset, int x, in Line 1154  ui_desktop_save(uint32 offset, int x, in
1154          Pixmap pix;          Pixmap pix;
1155          XImage *image;          XImage *image;
1156    
1157          pix = XCreatePixmap(display, wnd, cx, cy, depth);          if (ownbackstore)
1158          xwin_set_function(ROP2_COPY);          {
1159                    image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
1160          XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                                    ZPixmap);
1161          image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);          }
1162            else
1163            {
1164                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
1165                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1166                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,
1167                                      ZPixmap);
1168                    XFreePixmap(display, pix);
1169            }
1170    
1171          offset *= bpp/8;          offset *= bpp / 8;
1172          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8,
1173                            bpp/8, image->data);                            (uint8 *) image->data);
1174    
1175          XDestroyImage(image);          XDestroyImage(image);
         XFreePixmap(display, pix);  
1176  }  }
1177    
1178  void  void
# Line 907  ui_desktop_restore(uint32 offset, int x, Line 1181  ui_desktop_restore(uint32 offset, int x,
1181          XImage *image;          XImage *image;
1182          uint8 *data;          uint8 *data;
1183    
1184          offset *= bpp/8;          offset *= bpp / 8;
1185          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, bpp / 8);
1186          if (data == NULL)          if (data == NULL)
1187                  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  
1188    
1189  static uint8 *          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1190  translate(int width, int height, uint8 *data)                               (char *) data, cx, cy, BitmapPad(display),
1191  {                               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;)}  
                 }  
         }  
1192    
1193  #else /* bigendian-compiled */          if (ownbackstore)
         if (screen_msbfirst)  
1194          {          {
1195                  /* big-endian screen */                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1196                  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;)}  
                 }  
1197          }          }
1198          else          else
1199          {          {
1200                  /* 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;)}  
                 }  
1201          }          }
 #endif  
1202    
1203          return d2;          XFree(image);
1204  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26