/[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 17 by matty, Thu Sep 28 15:54:11 2000 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  BOOL ui_create_window(char *title)  /* 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
208    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");
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          attribs.background_pixel = BlackPixel(display, DefaultScreen(display));          if (attribs.backing_store == NotUseful)
302          attribs.backing_store = Always;                  ownbackstore = True;
303          wnd = XCreateWindow(display, DefaultRootWindow(display),  
304                          0, 0, width, height, 0, 8, InputOutput, visual,          if (fullscreen)
305                          CWBackingStore | CWBackPixel, &attribs);          {
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            wnd = XCreateWindow(display, RootWindowOfScreen(screen),
318                                0, 0, width, height, 0, CopyFromParent,
319                                InputOutput, CopyFromParent,
320                                CWBackingStore | CWBackPixel | CWOverrideRedirect,
321                                &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 xwin_translate_key(unsigned long key)          XMapWindow(display, wnd);
 {  
         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 xwin_translate_mouse(unsigned long button)  void
385    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 ui_process_events()  void
433    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 = xwin_translate_key(event.xkey.keycode);                                  if (XkbTranslateKeyCode
470                                  if (scancode == 0)                                      (xkb, xevent.xkey.keycode,
471                                         xevent.xkey.state, &tmpmods,
472                                         &keysym) == False)
473                                          break;                                          break;
474                                    scancode =
475                                            xkeymap_translate_key(keysym,
476                                                                  xevent.xkey.
477                                                                  keycode,
478                                                                  &flags);
479    
                                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,  
                                                 scancode, 0);  
                                 break;  
   
                         case KeyRelease:  
                                 scancode = xwin_translate_key(event.xkey.keycode);  
480                                  if (scancode == 0)                                  if (scancode == 0)
481                                          break;                                          break;
482    
483                                    /* keep track of the modifiers -- needed for stickykeys... */
484                                    if (xevent.type == KeyPress)
485                                            xwin_mod_press(xevent.xkey.state,
486                                                           ev_time, scancode);
487    
488                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
489                                                  KBD_FLAG_DOWN | KBD_FLAG_UP,                                                 flags, scancode, 0);
                                                 scancode, 0);  
                                 break;  
490    
491                          case ButtonPress:                                  if (xevent.type == KeyRelease)
492                                  button = xwin_translate_mouse(event.xbutton.button);                                          xwin_mod_release(xevent.xkey.state,
493                                                             ev_time, scancode);
494    
                                 if (button == 0)  
                                         break;  
   
                                 rdp_send_input(ev_time, RDP_INPUT_MOUSE,  
                                                 button | MOUSE_FLAG_DOWN,  
                                                 event.xbutton.x,  
                                                 event.xbutton.y);  
495                                  break;                                  break;
496    
497                            case ButtonPress:
498                                    flags = MOUSE_FLAG_DOWN;
499                                    /* fall through */
500    
501                          case ButtonRelease:                          case ButtonRelease:
502                                  button = xwin_translate_mouse(event.xbutton.button);                                  button = xkeymap_translate_button(xevent.
503                                                                      xbutton.
504                                                                      button);
505                                  if (button == 0)                                  if (button == 0)
506                                          break;                                          break;
507    
508                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
509                                                  button,                                                 flags | button,
510                                                  event.xbutton.x,                                                 xevent.xbutton.x,
511                                                  event.xbutton.y);                                                 xevent.xbutton.y);
512                                  break;                                  break;
513    
514                          case MotionNotify:                          case MotionNotify:
515                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
516                                                  MOUSE_FLAG_MOVE,                                                 MOUSE_FLAG_MOVE,
517                                                  event.xmotion.x,                                                 xevent.xmotion.x,
518                                                  event.xmotion.y);                                                 xevent.xmotion.y);
519                                    break;
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 ui_move_pointer(int x, int y)  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)
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 ui_create_bitmap(int width, int height, uint8 *data)  HBITMAP
759    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);
771    
772          XFree(image);          XFree(image);
773                    if (!owncolmap)
774          return (HBITMAP)bitmap;                  xfree(tdata);
775            return (HBITMAP) bitmap;
776  }  }
777    
778  void ui_paint_bitmap(int x, int y, int cx, int cy,  void
779                          int width, int height, uint8 *data)  ui_paint_bitmap(int x, int y, int cx, int cy,
780                    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    
799          image = XCreateImage(display, visual, 8, ZPixmap, 0,          XFree(image);
800                                  data, width, height, 8, width);          if (!owncolmap)
801          XSetFunction(display, gc, GXcopy);                  xfree(tdata);
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
         XFree(image);  
802  }  }
803    
804  void ui_destroy_bitmap(HBITMAP bmp)  void
805    ui_destroy_bitmap(HBITMAP bmp)
806  {  {
807          XFreePixmap(display, (Pixmap)bmp);          XFreePixmap(display, (Pixmap) bmp);
808  }  }
809    
810  HGLYPH ui_create_glyph(int width, int height, uint8 *data)  HGLYPH
811    ui_create_glyph(int width, int height, uint8 * data)
812  {  {
813          XImage *image;          XImage *image;
814          Pixmap bitmap;          Pixmap bitmap;
# Line 244  HGLYPH ui_create_glyph(int width, int he Line 821  HGLYPH ui_create_glyph(int width, int he
821          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
822    
823          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(display, visual, 1, ZPixmap, 0,
824                                  data, width, height, 8, scanline);                               data, width, height, 8, scanline);
825          XSetFunction(display, gc, GXcopy);          image->byte_order = MSBFirst;
826            image->bitmap_bit_order = MSBFirst;
827            XInitImage(image);
828    
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;
834          return (HGLYPH)bitmap;  }
835    
836    void
837    ui_destroy_glyph(HGLYPH glyph)
838    {
839            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 ui_destroy_glyph(HGLYPH glyph)  void
913    ui_set_cursor(HCURSOR cursor)
914  {  {
915          XFreePixmap(display, (Pixmap)glyph);          XDefineCursor(display, wnd, (Cursor) cursor);
916  }  }
917    
918  HCOLOURMAP ui_create_colourmap(COLOURMAP *colours)  void
919    ui_destroy_cursor(HCURSOR cursor)
920    {
921            XFreeCursor(display, (Cursor) cursor);
922    }
923    
924    #define MAKE_XCOLOR(xc,c) \
925                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
926                    (xc)->green = ((c)->green << 8) | (c)->green; \
927                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
928                    (xc)->flags = DoRed | DoGreen | DoBlue;
929    
930    HCOLOURMAP
931    ui_create_colourmap(COLOURMAP * colours)
932  {  {
933          COLOURENTRY *entry;          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                    map = XCreateColormap(display, wnd, visual, AllocAll);
951                    XStoreColors(display, map, xcolours, ncolours);
952    
953                  xentry->pixel = i;                  xfree(xcolours);
954                  xentry->red = entry->red << 8;                  return (HCOLOURMAP) map;
                 xentry->blue = entry->blue << 8;  
                 xentry->green = entry->green << 8;  
                 xentry->flags = DoRed | DoBlue | DoGreen;  
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          map = XCreateColormap(display, wnd, visual, AllocAll);                          if (XAllocColor(display, xcolmap, &xentry) != 0)
968          XStoreColors(display, map, xcolours, ncolours);                                  colour = xentry.pixel;
969                            else
970                                    colour = white;
971    
972          xfree(xcolours);                          /* byte swap here to make translate_image faster */
973          return (HCOLOURMAP)map;                          map[i] = translate_colour(colour);
974                    }
975    
976                    return map;
977            }
978  }  }
979    
980  void ui_destroy_colourmap(HCOLOURMAP map)  void
981    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 ui_set_colourmap(HCOLOURMAP map)  void
990    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 ui_set_clip(int x, int y, int cx, int cy)  void
999    ui_set_clip(int x, int y, int cx, int cy)
1000  {  {
1001          XRectangle rect;          XRectangle rect;
1002    
# Line 306  void ui_set_clip(int x, int y, int cx, i Line 1007  void ui_set_clip(int x, int y, int cx, i
1007          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1008  }  }
1009    
1010  void ui_reset_clip()  void
1011    ui_reset_clip()
1012  {  {
1013          XRectangle rect;          XRectangle rect;
1014    
# Line 317  void ui_reset_clip() Line 1019  void ui_reset_clip()
1019          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1020  }  }
1021    
1022  void ui_bell()  void
1023    ui_bell()
1024  {  {
1025          XBell(display, 0);          XBell(display, 0);
1026  }  }
1027    
1028  static int rop2_map[] = {  void
1029          GXclear,        /* 0 */  ui_destblt(uint8 opcode,
1030          GXnor,          /* DPon */             /* dest */ int x, int y, int cx, int cy)
1031          GXandInverted,  /* DPna */  {
1032          GXcopyInverted, /* Pn */          SET_FUNCTION(opcode);
1033          GXandReverse,   /* PDna */          FILL_RECTANGLE(x, y, cx, cy);
1034          GXinvert,       /* Dn */          RESET_FUNCTION(opcode);
         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]);  
 }  
   
 void ui_destblt(uint8 opcode,  
         /* dest */  int x, int y, int cx, int cy)  
 {  
         xwin_set_function(opcode);  
   
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1035  }  }
1036    
1037  void ui_patblt(uint8 opcode,  void
1038          /* dest */  int x, int y, int cx, int cy,  ui_patblt(uint8 opcode,
1039          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* dest */ int x, int y, int cx, int cy,
1040              /* 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                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1058    
1059                            SET_FOREGROUND(bgcolour);
1060                            SET_BACKGROUND(fgcolour);
1061                            XSetFillStyle(display, gc, FillOpaqueStippled);
1062                            XSetStipple(display, gc, fill);
1063                            XSetTSOrigin(display, gc, brush->xorigin,
1064                                         brush->yorigin);
1065    
1066                          XSetForeground(dpy, gc, fgcolour);                          FILL_RECTANGLE(x, y, cx, cy);
                         XSetBackground(dpy, gc, bgcolour);  
                         XSetFillStyle(dpy, gc, FillOpaqueStippled);  
                         XSetStipple(dpy, gc, fill);  
1067    
1068                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          XSetFillStyle(display, gc, FillSolid);
1069                            ui_destroy_glyph((HGLYPH) fill);
                         XSetFillStyle(dpy, gc, FillSolid);  
                         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          }          }
 }  
   
 void ui_screenblt(uint8 opcode,  
                 /* dest */ int x, int y, int cx, int cy,  
                 /* src */  int srcx, int srcy)  
 {  
         xwin_set_function(opcode);  
1075    
1076          XCopyArea(display, wnd, wnd, gc, srcx, srcy,          RESET_FUNCTION(opcode);
                         cx, cy, x, y);  
1077  }  }
1078    
1079  void ui_memblt(uint8 opcode,  void
1080          /* dest */  int x, int y, int cx, int cy,  ui_screenblt(uint8 opcode,
1081          /* src */   HBITMAP src, int srcx, int srcy)               /* dest */ int x, int y, int cx, int cy,
1082  {               /* src */ int srcx, int srcy)
1083          xwin_set_function(opcode);  {
1084            SET_FUNCTION(opcode);
1085          XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy,          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1086                          cx, cy, x, y);          if (ownbackstore)
1087  }                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,
1088                              cx, cy, x, y);
1089  void ui_triblt(uint8 opcode,          RESET_FUNCTION(opcode);
1090          /* dest */  int x, int y, int cx, int cy,  }
1091          /* src */   HBITMAP src, int srcx, int srcy,  
1092          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)  void
1093    ui_memblt(uint8 opcode,
1094              /* dest */ int x, int y, int cx, int cy,
1095              /* src */ HBITMAP src, int srcx, int srcy)
1096    {
1097            SET_FUNCTION(opcode);
1098            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
1106    ui_triblt(uint8 opcode,
1107              /* dest */ int x, int y, int cx, int cy,
1108              /* src */ HBITMAP src, int srcx, int srcy,
1109              /* 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. */
1113    
1114          switch (opcode)          switch (opcode)
1115          {          {
1116                  case 0x69: /* PDSxxn */                  case 0x69:      /* PDSxxn */
1117                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1118                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy,
1119                                          brush, bgcolour, fgcolour);                                    brush, bgcolour, fgcolour);
1120                          break;                          break;
1121    
1122                  case 0xb8: /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1123                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy,
1124                                          brush, bgcolour, fgcolour);                                    brush, bgcolour, fgcolour);
1125                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1126                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy,
1127                                          brush, bgcolour, fgcolour);                                    brush, bgcolour, fgcolour);
1128                          break;                          break;
1129    
1130                  default:                  case 0xc0:      /* PSa */
                         NOTIMP("triblt 0x%x\n", opcode);  
1131                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1132          }                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
1133  }                                    fgcolour);
   
 void ui_line(uint8 opcode,  
         /* dest */  int startx, int starty, int endx, int endy,  
         /* pen */   PEN *pen)  
 {  
         xwin_set_function(opcode);  
   
         XSetForeground(display, gc, pen->colour);  
         XDrawLine(display, wnd, gc, startx, starty, endx, endy);  
 }  
   
 void ui_rect(  
         /* dest */  int x, int y, int cx, int cy,  
         /* brush */ int colour)  
 {  
         xwin_set_function(ROP2_COPY);  
   
         XSetForeground(display, gc, colour);  
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
 }  
   
 void ui_draw_glyph(int mixmode,  
         /* dest */ int x, int y, int cx, int cy,  
         /* src */  HGLYPH glyph, int srcx, int srcy, int bgcolour, int fgcolour)  
 {  
         Pixmap pixmap = (Pixmap)glyph;  
   
         xwin_set_function(ROP2_COPY);  
   
         XSetForeground(display, gc, fgcolour);  
   
         switch (mixmode)  
         {  
                 case MIX_TRANSPARENT:  
                         XSetStipple(display, gc, pixmap);  
                         XSetFillStyle(display, gc, FillStippled);  
                         XSetTSOrigin(display, gc, x, y);  
                         XFillRectangle(display, wnd, gc,  
                                         x, y, cx, cy);  
                         XSetFillStyle(display, gc, FillSolid);  
                         break;  
   
                 case MIX_OPAQUE:  
                         XSetBackground(display, gc, bgcolour);  
                         XCopyPlane(display, pixmap, wnd, gc,  
                                         srcx, srcy, cx, cy, x, y, 1);  
1134                          break;                          break;
1135    
1136                  default:                  default:
1137                          NOTIMP("mix %d\n", mixmode);                          unimpl("triblt 0x%x\n", opcode);
1138                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1139          }          }
1140  }  }
1141    
1142  void ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  void
1143                          int clipx, int clipy, int clipcx, int clipcy,  ui_line(uint8 opcode,
1144                          int boxx, int boxy, int boxcx, int boxcy,          /* dest */ int startx, int starty, int endx, int endy,
1145                          int bgcolour, int fgcolour, uint8 *text, uint8 length)          /* pen */ PEN * pen)
1146    {
1147            SET_FUNCTION(opcode);
1148            SET_FOREGROUND(pen->colour);
1149            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
1156    ui_rect(
1157                   /* dest */ int x, int y, int cx, int cy,
1158                   /* brush */ int colour)
1159    {
1160            SET_FOREGROUND(colour);
1161            FILL_RECTANGLE(x, y, cx, cy);
1162    }
1163    
1164    void
1165    ui_draw_glyph(int mixmode,
1166                  /* dest */ int x, int y, int cx, int cy,
1167                  /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,
1168                  int fgcolour)
1169    {
1170            SET_FOREGROUND(fgcolour);
1171            SET_BACKGROUND(bgcolour);
1172    
1173            XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)
1174                          ? FillStippled : FillOpaqueStippled);
1175            XSetStipple(display, gc, (Pixmap) glyph);
1176            XSetTSOrigin(display, gc, x, y);
1177    
1178            FILL_RECTANGLE(x, y, cx, cy);
1179    
1180            XSetFillStyle(display, gc, FillSolid);
1181    }
1182    
1183    #define DO_GLYPH(ttext,idx) \
1184    {\
1185      glyph = cache_get_font (font, ttext[idx]);\
1186      if (!(flags & TEXT2_IMPLICIT_X))\
1187        {\
1188          xyoffset = ttext[++idx];\
1189          if ((xyoffset & 0x80))\
1190            {\
1191              if (flags & TEXT2_VERTICAL) \
1192                y += ttext[++idx] | (ttext[++idx] << 8);\
1193              else\
1194                x += ttext[++idx] | (ttext[++idx] << 8);\
1195            }\
1196          else\
1197            {\
1198              if (flags & TEXT2_VERTICAL) \
1199                y += xyoffset;\
1200              else\
1201                x += xyoffset;\
1202            }\
1203        }\
1204      if (glyph != NULL)\
1205        {\
1206          ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1207                         y + (short) glyph->baseline,\
1208                         glyph->width, glyph->height,\
1209                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1210          if (flags & TEXT2_IMPLICIT_X)\
1211            x += glyph->width;\
1212        }\
1213    }
1214    
1215    void
1216    ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1217                 int clipx, int clipy, int clipcx, int clipcy, int boxx,
1218                 int boxy, int boxcx, int boxcy, int bgcolour,
1219                 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,                          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                          if (flags & TEXT2_IMPLICIT_X)                          case 0xfe:
1257                                  x += glyph->width;                                  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                            default:
1285                                    DO_GLYPH(text, i);
1286                                    i++;
1287                                    break;
1288                  }                  }
1289          }          }
1290    
1291    
1292  }  }
1293    
1294  void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)  void
1295    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 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)  void
1322    ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1323  {  {
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.17  
changed lines
  Added in v.64

  ViewVC Help
Powered by ViewVC 1.1.26