/[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 50 by matthewc, Sat Apr 20 09:41:03 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
# Line 21  Line 21 
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23  #include <time.h>  #include <time.h>
24    #include <errno.h>
25  #include "rdesktop.h"  #include "rdesktop.h"
26    
27    extern char keymapname[16];
28    extern int keylayout;
29  extern int width;  extern int width;
30  extern int height;  extern int height;
31  extern BOOL motion;  extern BOOL sendmotion;
 extern BOOL grab_keyboard;  
32  extern BOOL fullscreen;  extern BOOL fullscreen;
 extern int private_colormap;  
33    
34  static int bpp;  Display *display;
35  static int depth;  static int x_socket;
 static Display *display;  
36  static Window wnd;  static Window wnd;
37  static GC gc;  static GC gc;
38  static Visual *visual;  static Visual *visual;
39  static uint32 *colmap;  static int depth;
40    static int bpp;
 #define Ctrans(col) ( private_colormap ? col : colmap[col])  
41    
42  #define L_ENDIAN  /* endianness */
43  int screen_msbfirst = 0;  static BOOL host_be;
44    static BOOL xserver_be;
45    
46    /* software backing store */
47    static BOOL ownbackstore;
48    static Pixmap backstore;
49    
50    #define FILL_RECTANGLE(x,y,cx,cy)\
51    { \
52            XFillRectangle(display, wnd, gc, x, y, cx, cy); \
53            if (ownbackstore) \
54                    XFillRectangle(display, backstore, gc, x, y, cx, cy); \
55    }
56    
57    /* colour maps */
58    static BOOL owncolmap;
59    static Colormap xcolmap;
60    static uint32 white;
61    static uint32 *colmap;
62    
63  static uint8 *translate(int width, int height, uint8 *data);  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )
64    #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
65    #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
66    
67  static int rop2_map[] = {  static int rop2_map[] = {
68          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 64  static int rop2_map[] = { Line 83  static int rop2_map[] = {
83          GXset                   /* 1 */          GXset                   /* 1 */
84  };  };
85    
86    #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
87    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
88    
89    static void
90    translate8(uint8 *data, uint8 *out, uint8 *end)
91    {
92            while (out < end)
93                    *(out++) = (uint8)colmap[*(data++)];
94    }
95    
96    static void
97    translate16(uint8 *data, uint16 *out, uint16 *end)
98    {
99            while (out < end)
100                    *(out++) = (uint16)colmap[*(data++)];
101    }
102    
103    /* little endian - conversion happens when colourmap is built */
104  static void  static void
105  xwin_set_function(uint8 rop2)  translate24(uint8 *data, uint8 *out, uint8 *end)
106  {  {
107          static uint8 last_rop2 = ROP2_COPY;          uint32 value;
108    
109          if (last_rop2 != rop2)          while (out < end)
110          {          {
111                  XSetFunction(display, gc, rop2_map[rop2]);                  value = colmap[*(data++)];
112                  last_rop2 = rop2;                  *(out++) = value;
113                    *(out++) = value >> 8;
114                    *(out++) = value >> 16;
115          }          }
116  }  }
117    
118  static void  static void
119  xwin_grab_keyboard()  translate32(uint8 *data, uint32 *out, uint32 *end)
120  {  {
121          XGrabKeyboard(display, wnd, True, GrabModeAsync, GrabModeAsync,          while (out < end)
122                        CurrentTime);                  *(out++) = colmap[*(data++)];
123  }  }
124    
125  static void  static uint8 *
126  xwin_ungrab_keyboard()  translate_image(int width, int height, uint8 *data)
127  {  {
128          XUngrabKeyboard(display, CurrentTime);          int size = width * height * bpp/8;
129            uint8 *out = xmalloc(size);
130            uint8 *end = out + size;
131    
132            switch (bpp)
133            {
134                    case 8:
135                            translate8(data, out, end);
136                            break;
137    
138                    case 16:
139                            translate16(data, (uint16 *)out, (uint16 *)end);
140                            break;
141    
142                    case 24:
143                            translate24(data, out, end);
144                            break;
145    
146                    case 32:
147                            translate32(data, (uint32 *)out, (uint32 *)end);
148                            break;
149            }
150    
151            return out;
152    }
153    
154    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
155    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
156    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
157                            x = (x << 16) | (x >> 16); }
158    
159    static uint32
160    translate_colour(uint32 colour)
161    {
162            switch (bpp)
163            {
164                    case 16:
165                            if (host_be != xserver_be)
166                                    BSWAP16(colour);
167                            break;
168    
169                    case 24:
170                            if (xserver_be)
171                                    BSWAP24(colour);
172                            break;
173    
174                    case 32:
175                            if (host_be != xserver_be)
176                                    BSWAP32(colour);
177                            break;
178            }
179    
180            return colour;
181  }  }
182    
183  BOOL  BOOL
# Line 97  ui_create_window(char *title) Line 188  ui_create_window(char *title)
188          XSizeHints *sizehints;          XSizeHints *sizehints;
189          unsigned long input_mask;          unsigned long input_mask;
190          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
191          int count;          Screen *screen;
192            uint16 test;
193            int i;
194    
195          display = XOpenDisplay(NULL);          display = XOpenDisplay(NULL);
196          if (display == NULL)          if (display == NULL)
197          {          {
198                  ERROR("Failed to open display\n");                  error("Failed to open display\n");
199                  return False;                  return False;
200          }          }
201    
202          visual = DefaultVisual(display, DefaultScreen(display));          x_socket = ConnectionNumber(display);
203          depth = DefaultDepth(display, DefaultScreen(display));          screen = DefaultScreenOfDisplay(display);
204          pfm = XListPixmapFormats(display, &count);          visual = DefaultVisualOfScreen(screen);
205            depth = DefaultDepthOfScreen(screen);
206    
207            pfm = XListPixmapFormats(display, &i);
208          if (pfm != NULL)          if (pfm != NULL)
209          {          {
210                  while (count--)                  /* Use maximum bpp for this depth - this is generally
211                       desirable, e.g. 24 bits->32 bits. */
212                    while (i--)
213                  {                  {
214                          if ((pfm + count)->depth == depth                          if ((pfm[i].depth == depth)
215                              && (pfm + count)->bits_per_pixel > bpp)                              && (pfm[i].bits_per_pixel > bpp))
216                          {                          {
217                                  bpp = (pfm + count)->bits_per_pixel;                                  bpp = pfm[i].bits_per_pixel;
218                          }                          }
219                  }                  }
220                  XFree(pfm);                  XFree(pfm);
# Line 124  ui_create_window(char *title) Line 222  ui_create_window(char *title)
222    
223          if (bpp < 8)          if (bpp < 8)
224          {          {
225                  ERROR("Less than 8 bpp not currently supported.\n");                  error("Less than 8 bpp not currently supported.\n");
226                  XCloseDisplay(display);                  XCloseDisplay(display);
227                  return False;                  return False;
228          }          }
229    
230          width &= ~3; /* make width nicely divisible */          if (depth <= 8)
231                    owncolmap = True;
232            else
233                    xcolmap = DefaultColormapOfScreen(screen);
234    
235          attribs.background_pixel = BlackPixel(display, DefaultScreen(display));          test = 1;
236          attribs.backing_store = Always;          host_be = !(BOOL)(*(uint8 *)(&test));
237            xserver_be = (ImageByteOrder(display) == MSBFirst);
238    
239            white = WhitePixelOfScreen(screen);
240            attribs.background_pixel = BlackPixelOfScreen(screen);
241            attribs.backing_store = DoesBackingStore(screen);
242    
243            if (attribs.backing_store == NotUseful)
244                    ownbackstore = True;
245    
246          if (fullscreen)          if (fullscreen)
247          {          {
248                  attribs.override_redirect = True;                  attribs.override_redirect = True;
249                  width = WidthOfScreen(DefaultScreenOfDisplay(display));                  width = WidthOfScreen(screen);
250                  height = HeightOfScreen(DefaultScreenOfDisplay(display));                  height = HeightOfScreen(screen);
                 XSetInputFocus(display, PointerRoot, RevertToPointerRoot,  
                                CurrentTime);  
251          }          }
252          else          else
253          {          {
254                  attribs.override_redirect = False;                  attribs.override_redirect = False;
255          }          }
256    
257          wnd = XCreateWindow(display, DefaultRootWindow(display),          width = (width + 3) & ~3; /* make width a multiple of 32 bits */
258    
259            wnd = XCreateWindow(display, RootWindowOfScreen(screen),
260                              0, 0, width, height, 0, CopyFromParent,                              0, 0, width, height, 0, CopyFromParent,
261                              InputOutput, CopyFromParent,                              InputOutput, CopyFromParent,
262                              CWBackingStore | CWBackPixel | CWOverrideRedirect,                              CWBackingStore | CWBackPixel | CWOverrideRedirect,
# Line 157  ui_create_window(char *title) Line 266  ui_create_window(char *title)
266    
267          classhints = XAllocClassHint();          classhints = XAllocClassHint();
268          if (classhints != NULL)          if (classhints != NULL)
   
269          {          {
270                  classhints->res_name = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
                 classhints->res_class = "rdesktop";  
271                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(display, wnd, classhints);
272                  XFree(classhints);                  XFree(classhints);
273          }          }
# Line 168  ui_create_window(char *title) Line 275  ui_create_window(char *title)
275          sizehints = XAllocSizeHints();          sizehints = XAllocSizeHints();
276          if (sizehints)          if (sizehints)
277          {          {
278                  sizehints->flags =                  sizehints->flags = PMinSize | PMaxSize;
279                          PPosition | PSize | PMinSize | PMaxSize | PBaseSize;                  sizehints->min_width = sizehints->max_width = width;
280                  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;  
281                  XSetWMNormalHints(display, wnd, sizehints);                  XSetWMNormalHints(display, wnd, sizehints);
282                  XFree(sizehints);                  XFree(sizehints);
283          }          }
284    
285          input_mask = KeyPressMask | KeyReleaseMask;          xkeymap_init();
286          input_mask |= ButtonPressMask | ButtonReleaseMask;  
287          if (motion)          input_mask = KeyPressMask | KeyReleaseMask
288                            | ButtonPressMask | ButtonReleaseMask
289                            | EnterWindowMask | LeaveWindowMask;
290    
291            if (sendmotion)
292                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
293          if (grab_keyboard)  
294                  input_mask |= EnterWindowMask | LeaveWindowMask;          if (ownbackstore)
295                    input_mask |= ExposureMask;
296    
297          XSelectInput(display, wnd, input_mask);          XSelectInput(display, wnd, input_mask);
298          gc = XCreateGC(display, wnd, 0, NULL);          gc = XCreateGC(display, wnd, 0, NULL);
299    
300            if (ownbackstore)
301                    backstore = XCreatePixmap(display, wnd, width, height, depth);
302    
303          XMapWindow(display, wnd);          XMapWindow(display, wnd);
304          return True;          return True;
305  }  }
# Line 197  ui_create_window(char *title) Line 307  ui_create_window(char *title)
307  void  void
308  ui_destroy_window()  ui_destroy_window()
309  {  {
310            if (ownbackstore)
311                    XFreePixmap(display, backstore);
312    
313          XFreeGC(display, gc);          XFreeGC(display, gc);
314          XDestroyWindow(display, wnd);          XDestroyWindow(display, wnd);
315          XCloseDisplay(display);          XCloseDisplay(display);
316          display = NULL;          display = NULL;
317  }  }
318    
319  static uint8  static void
320  xwin_translate_key(unsigned long key)  xwin_process_events()
 {  
         DEBUG("KEY(code=0x%lx)\n", key);  
   
         if ((key > 8) && (key <= 0x60))  
                 return (key - 8);  
   
         switch (key)  
         {  
                 case 0x61:      /* home */  
                         return 0x47 | 0x80;  
                 case 0x62:      /* up arrow */  
                         return 0x48 | 0x80;  
                 case 0x63:      /* page up */  
                         return 0x49 | 0x80;  
                 case 0x64:      /* left arrow */  
                         return 0x4b | 0x80;  
                 case 0x66:      /* right arrow */  
                         return 0x4d | 0x80;  
                 case 0x67:      /* end */  
                         return 0x4f | 0x80;  
                 case 0x68:      /* down arrow */  
                         return 0x50 | 0x80;  
                 case 0x69:      /* page down */  
                         return 0x51 | 0x80;  
                 case 0x6a:      /* insert */  
                         return 0x52 | 0x80;  
                 case 0x6b:      /* delete */  
                         return 0x53 | 0x80;  
                 case 0x6c:      /* keypad enter */  
                         return 0x1c | 0x80;  
                 case 0x6d:      /* right ctrl */  
                         return 0x1d | 0x80;  
                 case 0x6f:      /* ctrl - print screen */  
                         return 0x37 | 0x80;  
                 case 0x70:      /* keypad '/' */  
                         return 0x35 | 0x80;  
                 case 0x71:      /* right alt */  
                         return 0x38 | 0x80;  
                 case 0x72:      /* ctrl break */  
                         return 0x46 | 0x80;  
                 case 0x73:      /* left window key */  
                         return 0xff;    /* real scancode is 5b */  
                 case 0x74:      /* right window key */  
                         return 0xff;    /* real scancode is 5c */  
                 case 0x75:      /* menu key */  
                         return 0x5d | 0x80;  
         }  
   
         return 0;  
 }  
   
 static uint16  
 xwin_translate_mouse(unsigned long button)  
 {  
         switch (button)  
         {  
                 case Button1:   /* left */  
                         return MOUSE_FLAG_BUTTON1;  
                 case Button2:   /* middle */  
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3:   /* right */  
                         return MOUSE_FLAG_BUTTON2;  
         }  
   
         return 0;  
 }  
   
 void  
 ui_process_events()  
321  {  {
322          XEvent event;          XEvent event;
323            KeySym keysym;
324          uint8 scancode;          uint8 scancode;
325          uint16 button;          uint16 button, flags;
326          uint32 ev_time;          uint32 ev_time;
327    
328          if (display == NULL)          if (display == NULL)
329                  return;                  return;
330    
331          while (XCheckWindowEvent(display, wnd, ~0, &event))          while (XCheckMaskEvent(display, ~0, &event))
332          {          {
333                  ev_time = time(NULL);                  ev_time = time(NULL);
334                    flags = 0;
335    
336                  switch (event.type)                  switch (event.type)
337                  {                  {
                         case KeyPress:  
                                 scancode = xwin_translate_key(event.xkey.keycode);  
                                 if (scancode == 0)  
                                         break;  
   
                                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,  
                                                scancode, 0);  
                                 break;  
   
338                          case KeyRelease:                          case KeyRelease:
339                                  scancode = xwin_translate_key(event.xkey.keycode);                                  flags = KBD_FLAG_DOWN | KBD_FLAG_UP;
340                                    /* fall through */
341    
342                            case KeyPress:
343                                    keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);
344                                    scancode = xkeymap_translate_key(keysym, event.xkey.keycode, &flags);
345                                  if (scancode == 0)                                  if (scancode == 0)
346                                          break;                                          break;
347    
348                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, flags, scancode, 0);
                                                KBD_FLAG_DOWN | KBD_FLAG_UP,  
                                                scancode, 0);  
349                                  break;                                  break;
350    
351                          case ButtonPress:                          case ButtonPress:
352                                  button = xwin_translate_mouse(event.xbutton.button);                                  flags = MOUSE_FLAG_DOWN;
353                                  if (button == 0)                                  /* fall through */
                                         break;  
   
                                 rdp_send_input(ev_time, RDP_INPUT_MOUSE,  
                                                button | MOUSE_FLAG_DOWN,  
                                                event.xbutton.x,  
                                                event.xbutton.y);  
                                 break;  
354    
355                          case ButtonRelease:                          case ButtonRelease:
356                                  button = xwin_translate_mouse(event.xbutton.button);                                  button = xkeymap_translate_button(event.xbutton.button);
357                                  if (button == 0)                                  if (button == 0)
358                                          break;                                          break;
359    
360                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
361                                                 button,                                                 flags | button,
362                                                 event.xbutton.x,                                                 event.xbutton.x,
363                                                 event.xbutton.y);                                                 event.xbutton.y);
364                                  break;                                  break;
# Line 338  ui_process_events() Line 371  ui_process_events()
371                                  break;                                  break;
372    
373                          case EnterNotify:                          case EnterNotify:
374                                  if (grab_keyboard)                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,
375                                          xwin_grab_keyboard();                                                GrabModeAsync, CurrentTime);
376                                  break;                                  break;
377    
378                          case LeaveNotify:                          case LeaveNotify:
379                                  if (grab_keyboard)                                  XUngrabKeyboard(display, CurrentTime);
                                         xwin_ungrab_keyboard();  
380                                  break;                                  break;
381    
382                            case Expose:
383                                    XCopyArea(display, backstore, wnd, gc,
384                                              event.xexpose.x, event.xexpose.y,
385                                              event.xexpose.width, event.xexpose.height,
386                                              event.xexpose.x, event.xexpose.y);
387                                    break;
388                    }
389            }
390    }
391    
392    void
393    ui_select(int rdp_socket)
394    {
395            int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;
396            fd_set rfds;
397    
398            XFlush(display);
399    
400            FD_ZERO(&rfds);
401    
402            while (True)
403            {
404                    FD_ZERO(&rfds);
405                    FD_SET(rdp_socket, &rfds);
406                    FD_SET(x_socket, &rfds);
407    
408                    switch (select(n, &rfds, NULL, NULL, NULL))
409                    {
410                            case -1:
411                                    error("select: %s\n", strerror(errno));
412    
413                            case 0:
414                                    continue;
415                  }                  }
416    
417                    if (FD_ISSET(x_socket, &rfds))
418                            xwin_process_events();
419    
420                    if (FD_ISSET(rdp_socket, &rfds))
421                            return;
422          }          }
423  }  }
424    
# Line 362  ui_create_bitmap(int width, int height, Line 434  ui_create_bitmap(int width, int height,
434          XImage *image;          XImage *image;
435          Pixmap bitmap;          Pixmap bitmap;
436          uint8 *tdata;          uint8 *tdata;
437          tdata = (private_colormap ? data : translate(width, height, data));  
438            tdata = (owncolmap ? data : translate_image(width, height, data));
439          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(display, wnd, width, height, depth);
440          image =          image = XCreateImage(display, visual, depth, ZPixmap,
441                  XCreateImage(display, visual,                               0, tdata, width, height, 8, 0);
                              depth, ZPixmap,  
                              0, tdata, width, height, BitmapPad(display), 0);  
442    
         xwin_set_function(ROP2_COPY);  
443          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
444    
445          XFree(image);          XFree(image);
446          if (!private_colormap)          if (!owncolmap)
447                  xfree(tdata);                  xfree(tdata);
448          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
449  }  }
# Line 383  ui_paint_bitmap(int x, int y, int cx, in Line 453  ui_paint_bitmap(int x, int y, int cx, in
453                  int width, int height, uint8 *data)                  int width, int height, uint8 *data)
454  {  {
455          XImage *image;          XImage *image;
456          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);  
 }  
457    
458  HCURSOR          tdata = (owncolmap ? data : translate_image(width, height, data));
459  ui_create_cursor(unsigned int x, unsigned int y, int width,          image = XCreateImage(display, visual, depth, ZPixmap,
460                   int height, uint8 *mask, uint8 *data)                               0, 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;  
461    
462          if (!screen_msbfirst)          if (ownbackstore)
463          {          {
464                  while (i >= 0)                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
465                  {                  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;  
                 }  
466          }          }
467          else          else
468          {          {
469                  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;  
                 }  
470          }          }
471    
472            XFree(image);
473          fg.red = 0;          if (!owncolmap)
474          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);  
475  }  }
476    
477  void  void
478  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_bitmap(HBITMAP bmp)
479  {  {
480          XFreeCursor(display, (Cursor) cursor);          XFreePixmap(display, (Pixmap)bmp);
481  }  }
482    
483  HGLYPH  HGLYPH
# Line 544  ui_create_glyph(int width, int height, u Line 499  ui_create_glyph(int width, int height, u
499          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
500          XInitImage(image);          XInitImage(image);
501    
         XSetFunction(display, gc, GXcopy);  
502          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
503    
504          XFree(image);          XFree(image);
505          XFreeGC(display, gc);          XFreeGC(display, gc);
506            return (HGLYPH)bitmap;
         return (HGLYPH) bitmap;  
507  }  }
508    
509  void  void
510  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
511  {  {
512          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(display, (Pixmap)glyph);
513  }  }
514    
515  HCOLOURMAP  HCURSOR
516  ui_create_colourmap(COLOURMAP *colours)  ui_create_cursor(unsigned int x, unsigned int y, int width,
517                     int height, uint8 *andmask, uint8 *xormask)
518  {  {
519          if (!private_colormap)          HGLYPH maskglyph, cursorglyph;
520            XColor bg, fg;
521            Cursor xcursor;
522            uint8 *cursor, *pcursor;
523            uint8 *mask, *pmask;
524            uint8 nextbit;
525            int scanline, offset;
526            int i, j;
527    
528            scanline = (width + 7) / 8;
529            offset = scanline * height;
530    
531            cursor = xmalloc(offset);
532            memset(cursor, 0, offset);
533    
534            mask = xmalloc(offset);
535            memset(mask, 0, offset);
536    
537            /* approximate AND and XOR masks with a monochrome X pointer */
538            for (i = 0; i < height; i++)
539          {          {
540                  COLOURENTRY *entry;                  offset -= scanline;
541                  int i, ncolours = colours->ncolours;                  pcursor = &cursor[offset];
542                  uint32 *nc = xmalloc(sizeof(*colmap) * ncolours);                  pmask = &mask[offset];
543                  for (i = 0; i < ncolours; i++)  
544                    for (j = 0; j < scanline; j++)
545                  {                  {
546                          XColor xc;                          for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
547                          entry = &colours->colours[i];                          {
548                          xc.red = entry->red << 8;                                  if (xormask[0] || xormask[1] || xormask[2])
549                          xc.green = entry->green << 8;                                  {
550                          xc.blue = entry->blue << 8;                                          *pcursor |= (~(*andmask) & nextbit);
551                          XAllocColor(display,                                          *pmask |= nextbit;
552                                      DefaultColormap(display,                                  }
553                                                      DefaultScreen(display)),                                  else
554                                      &xc);                                  {
555                          /* XXX Check return value */                                          *pcursor |= ((*andmask) & nextbit);
556                          nc[i] = xc.pixel;                                          *pmask |= (~(*andmask) & nextbit);
557                                    }
558    
559                                    xormask += 3;
560                            }
561    
562                            andmask++;
563                            pcursor++;
564                            pmask++;
565                  }                  }
                 return nc;  
566          }          }
567          else  
568            fg.red = fg.blue = fg.green = 0xffff;
569            bg.red = bg.blue = bg.green = 0x0000;
570            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
571    
572            cursorglyph = ui_create_glyph(width, height, cursor);
573            maskglyph = ui_create_glyph(width, height, mask);
574            
575            xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,
576                                    (Pixmap)maskglyph, &fg, &bg, x, y);
577    
578            ui_destroy_glyph(maskglyph);
579            ui_destroy_glyph(cursorglyph);
580            xfree(mask);
581            xfree(cursor);
582            return (HCURSOR)xcursor;
583    }
584    
585    void
586    ui_set_cursor(HCURSOR cursor)
587    {
588            XDefineCursor(display, wnd, (Cursor)cursor);
589    }
590    
591    void
592    ui_destroy_cursor(HCURSOR cursor)
593    {
594            XFreeCursor(display, (Cursor)cursor);
595    }
596    
597    #define MAKE_XCOLOR(xc,c) \
598                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
599                    (xc)->green = ((c)->green << 8) | (c)->green; \
600                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
601                    (xc)->flags = DoRed | DoGreen | DoBlue;
602    
603    HCOLOURMAP
604    ui_create_colourmap(COLOURMAP *colours)
605    {
606            COLOURENTRY *entry;
607            int i, ncolours = colours->ncolours;
608    
609            if (owncolmap)
610          {          {
                 COLOURENTRY *entry;  
611                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
612                  Colormap map;                  Colormap map;
613                  int i, ncolours = colours->ncolours;  
614                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = xmalloc(sizeof(XColor) * ncolours);
615                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
616                  {                  {
617                          entry = &colours->colours[i];                          entry = &colours->colours[i];
618                          xentry = &xcolours[i];                          xentry = &xcolours[i];
   
619                          xentry->pixel = i;                          xentry->pixel = i;
620                          xentry->red = entry->red << 8;                          MAKE_XCOLOR(xentry, entry);
                         xentry->blue = entry->blue << 8;  
                         xentry->green = entry->green << 8;  
                         xentry->flags = DoRed | DoBlue | DoGreen;  
621                  }                  }
622    
623                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(display, wnd, visual, AllocAll);
624                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(display, map, xcolours, ncolours);
625    
626                  xfree(xcolours);                  xfree(xcolours);
627                  return (HCOLOURMAP) map;                  return (HCOLOURMAP)map;
628            }
629            else
630            {
631                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
632                    XColor xentry;
633                    uint32 colour;
634    
635                    for (i = 0; i < ncolours; i++)
636                    {
637                            entry = &colours->colours[i];
638                            MAKE_XCOLOR(&xentry, entry);
639    
640                            if (XAllocColor(display, xcolmap, &xentry) != 0)
641                                    colour = xentry.pixel;
642                            else
643                                    colour = white;
644    
645                            /* byte swap here to make translate_image faster */
646                            map[i] = translate_colour(colour);
647                    }
648    
649                    return map;
650          }          }
651  }  }
652    
653  void  void
654  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
655  {  {
656          XFreeColormap(display, (Colormap) map);          if (owncolmap)
657                    XFreeColormap(display, (Colormap)map);
658            else
659                    xfree(map);
660  }  }
661    
662  void  void
663  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
664  {  {
665            if (owncolmap)
666          /* XXX, change values of all pixels on the screen if the new colmap                  XSetWindowColormap(display, wnd, (Colormap)map);
          * doesn't have the same values as the old one? */  
         if (!private_colormap)  
                 colmap = map;  
667          else          else
668          {                  colmap = map;
                 XSetWindowColormap(display, wnd, (Colormap) map);  
                 if (fullscreen)  
                         XInstallColormap(display, (Colormap) map);  
         }  
669  }  }
670    
671  void  void
# Line 665  void Line 702  void
702  ui_destblt(uint8 opcode,  ui_destblt(uint8 opcode,
703             /* dest */ int x, int y, int cx, int cy)             /* dest */ int x, int y, int cx, int cy)
704  {  {
705          xwin_set_function(opcode);          SET_FUNCTION(opcode);
706            FILL_RECTANGLE(x, y, cx, cy);
707          XFillRectangle(display, wnd, gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
708  }  }
709    
710  void  void
# Line 675  ui_patblt(uint8 opcode, Line 712  ui_patblt(uint8 opcode,
712            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
713            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
714  {  {
         Display *dpy = display;  
715          Pixmap fill;          Pixmap fill;
         uint8 i, ipattern[8];  
716    
717          xwin_set_function(opcode);          SET_FUNCTION(opcode);
718    
719          switch (brush->style)          switch (brush->style)
720          {          {
721                  case 0: /* Solid */                  case 0: /* Solid */
722                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_FOREGROUND(fgcolour);
723                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
724                          break;                          break;
725    
726                  case 3: /* Pattern */                  case 3: /* Pattern */
727                          for (i = 0; i != 8; i++)                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);
728                                  ipattern[i] = ~brush->pattern[i];  
729                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          SET_FOREGROUND(bgcolour);
730                            SET_BACKGROUND(fgcolour);
731                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          XSetFillStyle(display, gc, FillOpaqueStippled);
732                          XSetBackground(dpy, gc, Ctrans(bgcolour));                          XSetStipple(display, gc, fill);
733                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                          XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
                         XSetStipple(dpy, gc, fill);  
734    
735                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
736    
737                          XSetFillStyle(dpy, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
738                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH)fill);
739                          break;                          break;
740    
741                  default:                  default:
742                          NOTIMP("brush %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
743          }          }
744    
745            RESET_FUNCTION(opcode);
746  }  }
747    
748  void  void
# Line 714  ui_screenblt(uint8 opcode, Line 750  ui_screenblt(uint8 opcode,
750               /* dest */ int x, int y, int cx, int cy,               /* dest */ int x, int y, int cx, int cy,
751               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
752  {  {
753          xwin_set_function(opcode);          SET_FUNCTION(opcode);
   
754          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
755            if (ownbackstore)
756                    XCopyArea(display, backstore, backstore, gc, srcx, srcy,
757                              cx, cy, x, y);
758            RESET_FUNCTION(opcode);
759  }  }
760    
761  void  void
# Line 724  ui_memblt(uint8 opcode, Line 763  ui_memblt(uint8 opcode,
763            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
764            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
765  {  {
766          xwin_set_function(opcode);          SET_FUNCTION(opcode);
767            XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);
768          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          if (ownbackstore)
769                    XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,
770                              cx, cy, x, y);
771            RESET_FUNCTION(opcode);
772  }  }
773    
774  void  void
# Line 754  ui_triblt(uint8 opcode, Line 796  ui_triblt(uint8 opcode,
796                                    brush, bgcolour, fgcolour);                                    brush, bgcolour, fgcolour);
797                          break;                          break;
798    
799                  case 0xc0:                  case 0xc0:      /* PSa */
800                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
801                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
802                                    fgcolour);                                    fgcolour);
803                          break;                          break;
804    
805                  default:                  default:
806                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
807                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
808          }          }
809  }  }
# Line 771  ui_line(uint8 opcode, Line 813  ui_line(uint8 opcode,
813          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
814          /* pen */ PEN *pen)          /* pen */ PEN *pen)
815  {  {
816          xwin_set_function(opcode);          SET_FUNCTION(opcode);
817            SET_FOREGROUND(pen->colour);
         XSetForeground(display, gc, Ctrans(pen->colour));  
818          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(display, wnd, gc, startx, starty, endx, endy);
819            if (ownbackstore)
820                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
821            RESET_FUNCTION(opcode);
822  }  }
823    
824  void  void
# Line 782  ui_rect( Line 826  ui_rect(
826                 /* dest */ int x, int y, int cx, int cy,                 /* dest */ int x, int y, int cx, int cy,
827                 /* brush */ int colour)                 /* brush */ int colour)
828  {  {
829          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(colour);
830            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(display, gc, Ctrans(colour));  
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
831  }  }
832    
833  void  void
# Line 794  ui_draw_glyph(int mixmode, Line 836  ui_draw_glyph(int mixmode,
836                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,
837                int fgcolour)                int fgcolour)
838  {  {
839          Pixmap pixmap = (Pixmap) glyph;          SET_FOREGROUND(fgcolour);
840            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;  
841    
842                  case MIX_OPAQUE:          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)
843                          XSetBackground(display, gc, Ctrans(bgcolour));                        ? FillStippled : FillOpaqueStippled);
844  /*      XCopyPlane (display, pixmap, back_pixmap, back_gc, srcx, srcy, cx, cy, x, y, 1); */          XSetStipple(display, gc, (Pixmap)glyph);
845                          XSetStipple(display, gc, pixmap);          XSetTSOrigin(display, gc, x, y);
846                          XSetFillStyle(display, gc, FillOpaqueStippled);  
847                          XSetTSOrigin(display, gc, x, y);          FILL_RECTANGLE(x, y, cx, cy);
848                          XFillRectangle(display, wnd, gc, x, y, cx, cy);  
849                          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(display, gc, FillSolid);
850                          break;  }
851    
852                  default:  #define DO_GLYPH(ttext,idx) \
853                          NOTIMP("mix %d\n", mixmode);  {\
854          }    glyph = cache_get_font (font, ttext[idx]);\
855      if (!(flags & TEXT2_IMPLICIT_X))\
856        {\
857          xyoffset = ttext[++idx];\
858          if ((xyoffset & 0x80))\
859            {\
860              if (flags & TEXT2_VERTICAL) \
861                y += ttext[++idx] | (ttext[++idx] << 8);\
862              else\
863                x += ttext[++idx] | (ttext[++idx] << 8);\
864            }\
865          else\
866            {\
867              if (flags & TEXT2_VERTICAL) \
868                y += xyoffset;\
869              else\
870                x += xyoffset;\
871            }\
872        }\
873      if (glyph != NULL)\
874        {\
875          ui_draw_glyph (mixmode, x + (short) glyph->offset,\
876                         y + (short) glyph->baseline,\
877                         glyph->width, glyph->height,\
878                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
879          if (flags & TEXT2_IMPLICIT_X)\
880            x += glyph->width;\
881        }\
882  }  }
883    
884  void  void
885  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,
886               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy, int boxx,
887               int boxx, int boxy, int boxcx, int boxcy,               int boxy, int boxcx, int boxcy, int bgcolour,
888               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
889  {  {
890          FONTGLYPH *glyph;          FONTGLYPH *glyph;
891          int i, xyoffset;          int i, j, xyoffset;
892            DATABLOB *entry;
893    
894          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(bgcolour);
         XSetForeground(display, gc, Ctrans(bgcolour));  
895    
896          if (boxcx > 1)          if (boxcx > 1)
897                  XFillRectangle(display, wnd, gc, boxx, boxy, boxcx, boxcy);          {
898                    FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
899            }
900          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
                 XFillRectangle(display, wnd, gc, clipx, clipy, clipcx, clipcy);  
   
         /* Paint text, character by character */  
         for (i = 0; i < length; i++)  
901          {          {
902                  glyph = cache_get_font(font, text[i]);                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
903            }
                 if (!(flags & TEXT2_IMPLICIT_X))  
904    
905                  {          /* Paint text, character by character */
906                          xyoffset = text[++i];          for (i = 0; i < length;) {
907                          if ((xyoffset & 0x80))                  switch (text[i]) {
908                          {                  case 0xff:
909                                  if (flags & 0x04)       /* vertical text */                          if (i + 2 < length)
910                                          y += text[++i] | (text[++i] << 8);                                  cache_put_text(text[i + 1], text, text[i + 2]);
911                                  else                          else {
912                                          x += text[++i] | (text[++i] << 8);                                  error("this shouldn't be happening\n");
913                                    break;
914                          }                          }
915                          else                          /* this will move pointer from start to first character after FF command */
916                          {                          length -= i + 3;
917                                  if (flags & 0x04)       /* vertical text */                          text = &(text[i + 3]);
918                                          y += xyoffset;                          i = 0;
919                            break;
920    
921                    case 0xfe:
922                            entry = cache_get_text(text[i + 1]);
923                            if (entry != NULL) {
924                                    if ((((uint8 *) (entry->data))[1] == 0)
925                                        && (!(flags & TEXT2_IMPLICIT_X))) {
926                                            if (flags & TEXT2_VERTICAL)      
927                                                    y += text[i + 2];
928                                            else
929                                                    x += text[i + 2];
930                                    }
931                                    if (i + 2 < length)
932                                            i += 3;
933                                  else                                  else
934                                          x += xyoffset;                                          i += 2;
935                                    length -= i;  
936                                    /* this will move pointer from start to first character after FE command */
937                                    text = &(text[i]);
938                                    i = 0;
939                                    for (j = 0; j < entry->size; j++)
940                                            DO_GLYPH(((uint8 *) (entry->data)), j);
941                          }                          }
942                            break;
943    
944                  }                  default:
945                  if (glyph != NULL)                          DO_GLYPH(text, i);
946                  {                          i++;
947                          ui_draw_glyph(mixmode, x + (short) glyph->offset,                          break;
                                       y + (short) glyph->baseline,  
                                       glyph->width, glyph->height,  
                                       glyph->pixmap, 0, 0,  
                                       bgcolour, fgcolour);  
   
                         if (flags & TEXT2_IMPLICIT_X)  
                                 x += glyph->width;  
948                  }                  }
949          }          }
950    
951    
952  }  }
953    
954  void  void
# Line 887  ui_desktop_save(uint32 offset, int x, in Line 957  ui_desktop_save(uint32 offset, int x, in
957          Pixmap pix;          Pixmap pix;
958          XImage *image;          XImage *image;
959    
960          pix = XCreatePixmap(display, wnd, cx, cy, depth);          if (ownbackstore)
961          xwin_set_function(ROP2_COPY);          {
962                    image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
963          XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                                    ZPixmap);
964          image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);          }
965            else
966            {
967                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
968                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
969                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,
970                                      ZPixmap);
971                    XFreePixmap(display, pix);
972            }
973    
974          offset *= bpp/8;          offset *= bpp/8;
975          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line,
976                            bpp/8, image->data);                            bpp/8, (uint8 *)image->data);
977    
978          XDestroyImage(image);          XDestroyImage(image);
         XFreePixmap(display, pix);  
979  }  }
980    
981  void  void
# Line 911  ui_desktop_restore(uint32 offset, int x, Line 988  ui_desktop_restore(uint32 offset, int x,
988          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, bpp/8);
989          if (data == NULL)          if (data == NULL)
990                  return;                  return;
991          image =  
992                  XCreateImage(display, visual,          image = XCreateImage(display, visual, depth, ZPixmap,
                              depth, ZPixmap,  
993                               0, data, cx, cy, BitmapPad(display),                               0, data, cx, cy, BitmapPad(display),
994                               cx * bpp/8);                               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  
995    
996  static uint8 *          if (ownbackstore)
 translate(int width, int height, uint8 *data)  
 {  
         uint32 i;  
         uint32 size = width * height;  
         uint8 *d2 = xmalloc(size * bpp/8);  
         uint8 *d3 = d2;  
         uint32 pix;  
         i = (size & ~0x7);  
   
         /* XXX: where are the bits swapped??? */  
 #ifdef L_ENDIAN                 /* little-endian */  
         /* big-endian screen */  
         if (screen_msbfirst)  
997          {          {
998                  switch (bpp)                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
999                  {                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix >> 24;  
                                                     *d3++ = pix >> 16;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix;) i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      24;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix >> 16;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix;) i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix;) i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                 }  
1000          }          }
1001          else          else
         {                       /* little-endian screen */  
                 switch (bpp)  
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(*((uint32 *) d3) =  
                                                     colmap[*data++];  
                                                     d3 += sizeof(uint32);  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(*  
                                                                      ((uint32  
                                                                        *) d3)  
 = colmap[*data++];  
 d3 += sizeof(uint32);  
                                         )}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                         )}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                 }  
         }  
   
 #else /* bigendian-compiled */  
         if (screen_msbfirst)  
1002          {          {
1003                  /* big-endian screen */                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
                 switch (bpp)  
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(*((uint32 *) d3) =  
                                                     colmap[*data++];  
                                                     d3 += sizeof(uint32);  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(*  
                                                                      ((uint32  
                                                                        *) d3)  
 = colmap[*data++];  
 d3 += sizeof(uint32);  
                                         )}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                         )}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                 }  
1004          }          }
         else  
         {  
                 /* little-endian screen */  
                 switch (bpp)  
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                     *d3++ = pix >> 24;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      24;)}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                         )}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                 }  
         }  
 #endif  
1005    
1006          return d2;          XFree(image);
1007  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26