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

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

  ViewVC Help
Powered by ViewVC 1.1.26