/[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 38 by matthewc, Thu Apr 4 12:04:33 2002 UTC revision 309 by jsorg71, Tue Feb 4 05:32:13 2003 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X Window System     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2001     Copyright (C) Matthew Chapman 1999-2002
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Line 24  Line 24 
24  #include <errno.h>  #include <errno.h>
25  #include "rdesktop.h"  #include "rdesktop.h"
26    
 extern char keymapname[16];  
 extern int keylayout;  
27  extern int width;  extern int width;
28  extern int height;  extern int height;
29  extern BOOL sendmotion;  extern BOOL sendmotion;
30  extern BOOL fullscreen;  extern BOOL fullscreen;
31    extern BOOL grab_keyboard;
32    extern BOOL hide_decorations;
33    extern char title[];
34    extern int server_bpp;
35    BOOL enable_compose = False;
36    BOOL focused;
37    BOOL mouse_in_wnd;
38    
39  static Display *display;  Display *display;
40  static int x_socket;  static int x_socket;
41    static Screen *screen;
42  static Window wnd;  static Window wnd;
43  static GC gc;  static GC gc;
44  static Visual *visual;  static Visual *visual;
45  static int depth;  static int depth;
46  static int bpp;  static int bpp;
47    static XIM IM;
48    static XIC IC;
49    static XModifierKeymap *mod_map;
50    static Cursor current_cursor;
51    static Atom protocol_atom, kill_atom;
52    
53  /* endianness */  /* endianness */
54  static BOOL host_be;  static BOOL host_be;
# Line 47  static BOOL xserver_be; Line 58  static BOOL xserver_be;
58  static BOOL ownbackstore;  static BOOL ownbackstore;
59  static Pixmap backstore;  static Pixmap backstore;
60    
61    /* MWM decorations */
62    #define MWM_HINTS_DECORATIONS   (1L << 1)
63    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
64    typedef struct
65    {
66            uint32 flags;
67            uint32 functions;
68            uint32 decorations;
69            sint32 inputMode;
70            uint32 status;
71    }
72    PropMotifWmHints;
73    
74    
75  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
76  { \  { \
77          XFillRectangle(display, wnd, gc, x, y, cx, cy); \          XFillRectangle(display, wnd, gc, x, y, cx, cy); \
# Line 54  static Pixmap backstore; Line 79  static Pixmap backstore;
79                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \
80  }  }
81    
82    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
83    { \
84            XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \
85    }
86    
87  /* colour maps */  /* colour maps */
88  static BOOL owncolmap;  BOOL owncolmap = False;
89  static Colormap xcolmap;  static Colormap xcolmap;
 static uint32 white;  
90  static uint32 *colmap;  static uint32 *colmap;
91    
92  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )  #define TRANSLATE(col)          ( server_bpp != 8 ? col : owncolmap ? col : translate_colour(colmap[col]) )
93  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
94  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
95    
# Line 86  static int rop2_map[] = { Line 115  static int rop2_map[] = {
115  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
116  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
117    
118    void
119    mwm_hide_decorations(void)
120    {
121            PropMotifWmHints motif_hints;
122            Atom hintsatom;
123    
124            /* setup the property */
125            motif_hints.flags = MWM_HINTS_DECORATIONS;
126            motif_hints.decorations = 0;
127    
128            /* get the atom for the property */
129            hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
130            if (!hintsatom)
131            {
132                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
133                    return;
134            }
135    
136            XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
137                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
138    }
139    
140  static void  static void
141  translate8(uint8 *data, uint8 *out, uint8 *end)  translate8(uint8 * data, uint8 * out, uint8 * end)
142  {  {
143          while (out < end)          while (out < end)
144                  *(out++) = (uint8)colmap[*(data++)];                  *(out++) = (uint8) colmap[*(data++)];
145  }  }
146    
147  static void  static void
148  translate16(uint8 *data, uint16 *out, uint16 *end)  translate16(uint8 * data, uint16 * out, uint16 * end)
149  {  {
150          while (out < end)          while (out < end)
151                  *(out++) = (uint16)colmap[*(data++)];                  *(out++) = (uint16) colmap[*(data++)];
152  }  }
153    
154  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
155  static void  static void
156  translate24(uint8 *data, uint8 *out, uint8 *end)  translate24(uint8 * data, uint8 * out, uint8 * end)
157  {  {
158          uint32 value;          uint32 value;
159    
# Line 116  translate24(uint8 *data, uint8 *out, uin Line 167  translate24(uint8 *data, uint8 *out, uin
167  }  }
168    
169  static void  static void
170  translate32(uint8 *data, uint32 *out, uint32 *end)  translate32(uint8 * data, uint32 * out, uint32 * end)
171  {  {
172          while (out < end)          while (out < end)
173                  *(out++) = colmap[*(data++)];                  *(out++) = colmap[*(data++)];
174  }  }
175    
176  static uint8 *  static uint8 *
177  translate_image(int width, int height, uint8 *data)  translate_image(int width, int height, uint8 * data)
178  {  {
179          int size = width * height * bpp/8;          int size = width * height * bpp / 8;
180          uint8 *out = xmalloc(size);          uint8 *out = xmalloc(size);
181          uint8 *end = out + size;          uint8 *end = out + size;
182    
# Line 136  translate_image(int width, int height, u Line 187  translate_image(int width, int height, u
187                          break;                          break;
188    
189                  case 16:                  case 16:
190                          translate16(data, (uint16 *)out, (uint16 *)end);                          translate16(data, (uint16 *) out, (uint16 *) end);
191                          break;                          break;
192    
193                  case 24:                  case 24:
# Line 144  translate_image(int width, int height, u Line 195  translate_image(int width, int height, u
195                          break;                          break;
196    
197                  case 32:                  case 32:
198                          translate32(data, (uint32 *)out, (uint32 *)end);                          translate32(data, (uint32 *) out, (uint32 *) end);
199                          break;                          break;
200          }          }
201    
# Line 181  translate_colour(uint32 colour) Line 232  translate_colour(uint32 colour)
232  }  }
233    
234  BOOL  BOOL
235  ui_create_window(char *title)  get_key_state(unsigned int state, uint32 keysym)
236    {
237            int modifierpos, key, keysymMask = 0;
238            int offset;
239    
240            KeyCode keycode = XKeysymToKeycode(display, keysym);
241    
242            if (keycode == NoSymbol)
243                    return False;
244    
245            for (modifierpos = 0; modifierpos < 8; modifierpos++)
246            {
247                    offset = mod_map->max_keypermod * modifierpos;
248    
249                    for (key = 0; key < mod_map->max_keypermod; key++)
250                    {
251                            if (mod_map->modifiermap[offset + key] == keycode)
252                                    keysymMask |= 1 << modifierpos;
253                    }
254            }
255    
256            return (state & keysymMask) ? True : False;
257    }
258    
259    BOOL
260    ui_init(void)
261  {  {
         XSetWindowAttributes attribs;  
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
262          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
         Screen *screen;  
263          uint16 test;          uint16 test;
264          int i;          int i;
265    
266          display = XOpenDisplay(NULL);          display = XOpenDisplay(NULL);
267          if (display == NULL)          if (display == NULL)
268          {          {
269                  error("Failed to open display\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
270                  return False;                  return False;
271          }          }
272    
# Line 211  ui_create_window(char *title) Line 282  ui_create_window(char *title)
282                     desirable, e.g. 24 bits->32 bits. */                     desirable, e.g. 24 bits->32 bits. */
283                  while (i--)                  while (i--)
284                  {                  {
285                          if ((pfm[i].depth == depth)                          if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
                             && (pfm[i].bits_per_pixel > bpp))  
286                          {                          {
287                                  bpp = pfm[i].bits_per_pixel;                                  bpp = pfm[i].bits_per_pixel;
288                          }                          }
# Line 227  ui_create_window(char *title) Line 297  ui_create_window(char *title)
297                  return False;                  return False;
298          }          }
299    
300          if (depth <= 8)          if (owncolmap != True)
301                  owncolmap = True;          {
         else  
302                  xcolmap = DefaultColormapOfScreen(screen);                  xcolmap = DefaultColormapOfScreen(screen);
303                    if (depth <= 8)
304                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
305            }
306    
307            gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
308    
309            if (DoesBackingStore(screen) != Always)
310                    ownbackstore = True;
311    
312          test = 1;          test = 1;
313          host_be = !(BOOL)(*(uint8 *)(&test));          host_be = !(BOOL) (*(uint8 *) (&test));
314          xserver_be = (ImageByteOrder(display) == MSBFirst);          xserver_be = (ImageByteOrder(display) == MSBFirst);
315    
316          white = WhitePixelOfScreen(screen);          if ((width == 0) || (height == 0))
317          attribs.background_pixel = BlackPixelOfScreen(screen);          {
318          attribs.backing_store = DoesBackingStore(screen);                  /* Fetch geometry from _NET_WORKAREA */
319                    uint32 x, y, cx, cy;
320    
321          if (attribs.backing_store == NotUseful)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
322                  ownbackstore = True;                  {
323                            width = cx;
324                            height = cy;
325                    }
326                    else
327                    {
328                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
329                            width = 800;
330                            height = 600;
331                    }
332            }
333    
334          if (fullscreen)          if (fullscreen)
335          {          {
                 attribs.override_redirect = True;  
336                  width = WidthOfScreen(screen);                  width = WidthOfScreen(screen);
337                  height = HeightOfScreen(screen);                  height = HeightOfScreen(screen);
338          }          }
339          else  
340            /* make sure width is a multiple of 4 */
341            width = (width + 3) & ~3;
342    
343            if (ownbackstore)
344          {          {
345                  attribs.override_redirect = False;                  backstore =
346                            XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
347    
348                    /* clear to prevent rubbish being exposed at startup */
349                    XSetForeground(display, gc, BlackPixelOfScreen(screen));
350                    XFillRectangle(display, backstore, gc, 0, 0, width, height);
351          }          }
352    
353          width = (width + 3) & ~3; /* make width a multiple of 32 bits */          mod_map = XGetModifierMapping(display);
354    
355          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          if (enable_compose)
356                              0, 0, width, height, 0, CopyFromParent,                  IM = XOpenIM(display, NULL, NULL, NULL);
357                              InputOutput, CopyFromParent,  
358                              CWBackingStore | CWBackPixel | CWOverrideRedirect,          xkeymap_init();
359                              &attribs);          return True;
360    }
361    
362    void
363    ui_deinit(void)
364    {
365            if (IM != NULL)
366                    XCloseIM(IM);
367    
368            XFreeModifiermap(mod_map);
369    
370            if (ownbackstore)
371                    XFreePixmap(display, backstore);
372    
373            XFreeGC(display, gc);
374            XCloseDisplay(display);
375            display = NULL;
376    }
377    
378    BOOL
379    ui_create_window(void)
380    {
381            XSetWindowAttributes attribs;
382            XClassHint *classhints;
383            XSizeHints *sizehints;
384            int wndwidth, wndheight;
385            long input_mask, ic_input_mask;
386            XEvent xevent;
387    
388            wndwidth = fullscreen ? WidthOfScreen(screen) : width;
389            wndheight = fullscreen ? HeightOfScreen(screen) : height;
390    
391            attribs.background_pixel = BlackPixelOfScreen(screen);
392            attribs.backing_store = ownbackstore ? NotUseful : Always;
393            attribs.override_redirect = fullscreen;
394    
395            wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
396                                0, CopyFromParent, InputOutput, CopyFromParent,
397                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
398    
399          XStoreName(display, wnd, title);          XStoreName(display, wnd, title);
400    
401            if (hide_decorations)
402                    mwm_hide_decorations();
403    
404          classhints = XAllocClassHint();          classhints = XAllocClassHint();
405          if (classhints != NULL)          if (classhints != NULL)
406          {          {
# Line 282  ui_create_window(char *title) Line 419  ui_create_window(char *title)
419                  XFree(sizehints);                  XFree(sizehints);
420          }          }
421    
422          xkeymap_init(display);          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
423                    VisibilityChangeMask | FocusChangeMask;
         input_mask = KeyPressMask | KeyReleaseMask  
                         | ButtonPressMask | ButtonReleaseMask  
                         | EnterWindowMask | LeaveWindowMask;  
424    
425          if (sendmotion)          if (sendmotion)
426                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
   
427          if (ownbackstore)          if (ownbackstore)
428                  input_mask |= ExposureMask;                  input_mask |= ExposureMask;
429            if (fullscreen || grab_keyboard)
430                    input_mask |= EnterWindowMask;
431            if (grab_keyboard)
432                    input_mask |= LeaveWindowMask;
433    
434            if (IM != NULL)
435            {
436                    IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
437                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
438    
439                    if ((IC != NULL)
440                        && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
441                            input_mask |= ic_input_mask;
442            }
443    
444          XSelectInput(display, wnd, input_mask);          XSelectInput(display, wnd, input_mask);
445          gc = XCreateGC(display, wnd, 0, NULL);          XMapWindow(display, wnd);
446    
447          if (ownbackstore)          /* wait for VisibilityNotify */
448                  backstore = XCreatePixmap(display, wnd, width, height, depth);          do
449            {
450                    XMaskEvent(display, VisibilityChangeMask, &xevent);
451            }
452            while (xevent.type != VisibilityNotify);
453    
454            focused = False;
455            mouse_in_wnd = False;
456    
457            /* handle the WM_DELETE_WINDOW protocol */
458            protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
459            kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
460            XSetWMProtocols(display, wnd, &kill_atom, 1);
461    
         XMapWindow(display, wnd);  
462          return True;          return True;
463  }  }
464    
465  void  void
466  ui_destroy_window()  ui_destroy_window(void)
467  {  {
468          if (ownbackstore)          if (IC != NULL)
469                  XFreePixmap(display, backstore);                  XDestroyIC(IC);
470    
         XFreeGC(display, gc);  
471          XDestroyWindow(display, wnd);          XDestroyWindow(display, wnd);
         XCloseDisplay(display);  
         display = NULL;  
472  }  }
473    
474  static void  void
475  xwin_process_events()  xwin_toggle_fullscreen(void)
476  {  {
477          XEvent event;          Pixmap contents = 0;
478    
479            if (!ownbackstore)
480            {
481                    /* need to save contents of window */
482                    contents = XCreatePixmap(display, wnd, width, height, depth);
483                    XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
484            }
485    
486            ui_destroy_window();
487            fullscreen = !fullscreen;
488            ui_create_window();
489    
490            XDefineCursor(display, wnd, current_cursor);
491    
492            if (!ownbackstore)
493            {
494                    XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
495                    XFreePixmap(display, contents);
496            }
497    }
498    
499    /* Process all events in Xlib queue
500       Returns 0 after user quit, 1 otherwise */
501    static int
502    xwin_process_events(void)
503    {
504            XEvent xevent;
505          KeySym keysym;          KeySym keysym;
506          uint8 scancode;          uint16 button, flags;
         uint16 button;  
507          uint32 ev_time;          uint32 ev_time;
508            key_translation tr;
509            char str[256];
510            Status status;
511            unsigned int state;
512            Window wdummy;
513            int dummy;
514    
515          if (display == NULL)          while (XPending(display) > 0)
                 return;  
   
         while (XCheckWindowEvent(display, wnd, ~0, &event))  
516          {          {
517                  ev_time = time(NULL);                  XNextEvent(display, &xevent);
518    
519                  switch (event.type)                  if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
520                  {                  {
521                            DEBUG_KBD(("Filtering event\n"));
522                            continue;
523                    }
524    
525                    flags = 0;
526    
527                    switch (xevent.type)
528                    {
529                            case ClientMessage:
530                                    /* the window manager told us to quit */
531                                    if ((xevent.xclient.message_type == protocol_atom)
532                                        && (xevent.xclient.data.l[0] == kill_atom))
533                                            /* Quit */
534                                            return 0;
535                                    break;
536    
537                          case KeyPress:                          case KeyPress:
538                                  keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);                                  if (IC != NULL)
539                                  scancode = xkeymap_translate_key(keysym, event.xkey.keycode);                                          /* Multi_key compatible version */
540                                  if (scancode == 0)                                  {
541                                            XmbLookupString(IC,
542                                                            (XKeyPressedEvent *) &
543                                                            xevent, str, sizeof(str), &keysym, &status);
544                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
545                                            {
546                                                    error("XmbLookupString failed with status 0x%x\n",
547                                                          status);
548                                                    break;
549                                            }
550                                    }
551                                    else
552                                    {
553                                            /* Plain old XLookupString */
554                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
555                                            XLookupString((XKeyEvent *) & xevent,
556                                                          str, sizeof(str), &keysym, NULL);
557                                    }
558    
559                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
560                                               get_ksname(keysym)));
561    
562                                    ev_time = time(NULL);
563                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
564                                          break;                                          break;
565    
566                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  tr = xkeymap_translate_key(keysym,
567                                                 scancode, 0);                                                             xevent.xkey.keycode, xevent.xkey.state);
568    
569                                    if (tr.scancode == 0)
570                                            break;
571    
572                                    ensure_remote_modifiers(ev_time, tr);
573    
574                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
575                                  break;                                  break;
576    
577                          case KeyRelease:                          case KeyRelease:
578                                  keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);                                  XLookupString((XKeyEvent *) & xevent, str,
579                                  scancode = xkeymap_translate_key(keysym, event.xkey.keycode);                                                sizeof(str), &keysym, NULL);
580                                  if (scancode == 0)  
581                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
582                                               get_ksname(keysym)));
583    
584                                    ev_time = time(NULL);
585                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
586                                          break;                                          break;
587    
588                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  tr = xkeymap_translate_key(keysym,
589                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                             xevent.xkey.keycode, xevent.xkey.state);
                                                scancode, 0);  
                                 break;  
590    
591                          case ButtonPress:                                  if (tr.scancode == 0)
                                 button = xkeymap_translate_button(event.xbutton.button);  
                                 if (button == 0)  
592                                          break;                                          break;
593    
594                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
                                                button | MOUSE_FLAG_DOWN,  
                                                event.xbutton.x,  
                                                event.xbutton.y);  
595                                  break;                                  break;
596    
597                            case ButtonPress:
598                                    flags = MOUSE_FLAG_DOWN;
599                                    /* fall through */
600    
601                          case ButtonRelease:                          case ButtonRelease:
602                                  button = xkeymap_translate_button(event.xbutton.button);                                  button = xkeymap_translate_button(xevent.xbutton.button);
603                                  if (button == 0)                                  if (button == 0)
604                                          break;                                          break;
605    
606                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
607                                                 button,                                                 flags | button, xevent.xbutton.x, xevent.xbutton.y);
                                                event.xbutton.x,  
                                                event.xbutton.y);  
608                                  break;                                  break;
609    
610                          case MotionNotify:                          case MotionNotify:
611                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (fullscreen && !focused)
612                                                 MOUSE_FLAG_MOVE,                                          XSetInputFocus(display, wnd, RevertToPointerRoot,
613                                                 event.xmotion.x,                                                         CurrentTime);
614                                                 event.xmotion.y);                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
615                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
616                                    break;
617    
618                            case FocusIn:
619                                    if (xevent.xfocus.mode == NotifyGrab)
620                                            break;
621                                    focused = True;
622                                    XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
623                                                  &dummy, &dummy, &state);
624                                    reset_modifier_keys(state);
625                                    if (grab_keyboard && mouse_in_wnd)
626                                            XGrabKeyboard(display, wnd, True,
627                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
628                                    break;
629    
630                            case FocusOut:
631                                    if (xevent.xfocus.mode == NotifyUngrab)
632                                            break;
633                                    focused = False;
634                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
635                                            XUngrabKeyboard(display, CurrentTime);
636                                  break;                                  break;
637    
638                          case EnterNotify:                          case EnterNotify:
639                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,                                  /* we only register for this event when in fullscreen mode */
640                                                GrabModeAsync, CurrentTime);                                  /* or grab_keyboard */
641                                    mouse_in_wnd = True;
642                                    if (fullscreen)
643                                    {
644                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
645                                                           CurrentTime);
646                                            break;
647                                    }
648                                    if (focused)
649                                            XGrabKeyboard(display, wnd, True,
650                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
651                                  break;                                  break;
652    
653                          case LeaveNotify:                          case LeaveNotify:
654                                    /* we only register for this event when grab_keyboard */
655                                    mouse_in_wnd = False;
656                                  XUngrabKeyboard(display, CurrentTime);                                  XUngrabKeyboard(display, CurrentTime);
657                                  break;                                  break;
658    
659                          case Expose:                          case Expose:
660                                  XCopyArea(display, backstore, wnd, gc,                                  XCopyArea(display, backstore, wnd, gc,
661                                            event.xexpose.x, event.xexpose.y,                                            xevent.xexpose.x, xevent.xexpose.y,
662                                            event.xexpose.width, event.xexpose.height,                                            xevent.xexpose.width,
663                                            event.xexpose.x, event.xexpose.y);                                            xevent.xexpose.height,
664                                              xevent.xexpose.x, xevent.xexpose.y);
665                                    break;
666    
667                            case MappingNotify:
668                                    /* Refresh keyboard mapping if it has changed. This is important for
669                                       Xvnc, since it allocates keycodes dynamically */
670                                    if (xevent.xmapping.request == MappingKeyboard
671                                        || xevent.xmapping.request == MappingModifier)
672                                            XRefreshKeyboardMapping(&xevent.xmapping);
673    
674                                    if (xevent.xmapping.request == MappingModifier)
675                                    {
676                                            XFreeModifiermap(mod_map);
677                                            mod_map = XGetModifierMapping(display);
678                                    }
679                                  break;                                  break;
680    
681                  }                  }
682          }          }
683            /* Keep going */
684            return 1;
685  }  }
686    
687  void  /* Returns 0 after user quit, 1 otherwise */
688    int
689  ui_select(int rdp_socket)  ui_select(int rdp_socket)
690  {  {
691          int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
692          fd_set rfds;          fd_set rfds;
693    
         XFlush(display);  
   
694          FD_ZERO(&rfds);          FD_ZERO(&rfds);
695    
696          while (True)          while (True)
697          {          {
698                    /* Process any events already waiting */
699                    if (!xwin_process_events())
700                            /* User quit */
701                            return 0;
702    
703                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
704                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
705                  FD_SET(x_socket, &rfds);                  FD_SET(x_socket, &rfds);
# Line 428  ui_select(int rdp_socket) Line 713  ui_select(int rdp_socket)
713                                  continue;                                  continue;
714                  }                  }
715    
                 if (FD_ISSET(x_socket, &rfds))  
                         xwin_process_events();  
   
716                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
717                          return;                          return 1;
718          }          }
719  }  }
720    
# Line 443  ui_move_pointer(int x, int y) Line 725  ui_move_pointer(int x, int y)
725  }  }
726    
727  HBITMAP  HBITMAP
728  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
729  {  {
730          XImage *image;          XImage *image;
731          Pixmap bitmap;          Pixmap bitmap;
# Line 451  ui_create_bitmap(int width, int height, Line 733  ui_create_bitmap(int width, int height,
733    
734          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (owncolmap ? data : translate_image(width, height, data));
735          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(display, wnd, width, height, depth);
736          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
737                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, 8, 0);
738    
739          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
740    
# Line 463  ui_create_bitmap(int width, int height, Line 745  ui_create_bitmap(int width, int height,
745  }  }
746    
747  void  void
748  ui_paint_bitmap(int x, int y, int cx, int cy,  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
                 int width, int height, uint8 *data)  
749  {  {
750          XImage *image;          XImage *image;
751          uint8 *tdata;          uint8 *tdata;
752    
753            if (server_bpp == 16)
754            {
755                    image = XCreateImage(display, visual, depth, ZPixmap, 0,
756                                         (char *) data, width, height, 16, 0);
757    
758                    if (ownbackstore)
759                    {
760                            XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
761                            XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
762                    }
763                    else
764                    {
765                            XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
766                    }
767    
768                    XFree(image);
769                    return;
770            }
771          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (owncolmap ? data : translate_image(width, height, data));
772          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
773                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, 8, 0);
774    
775          if (ownbackstore)          if (ownbackstore)
776          {          {
# Line 491  ui_paint_bitmap(int x, int y, int cx, in Line 790  ui_paint_bitmap(int x, int y, int cx, in
790  void  void
791  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
792  {  {
793          XFreePixmap(display, (Pixmap)bmp);          XFreePixmap(display, (Pixmap) bmp);
794  }  }
795    
796  HGLYPH  HGLYPH
797  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
798  {  {
799          XImage *image;          XImage *image;
800          Pixmap bitmap;          Pixmap bitmap;
# Line 507  ui_create_glyph(int width, int height, u Line 806  ui_create_glyph(int width, int height, u
806          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
807          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
808    
809          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
810                               data, width, height, 8, scanline);                               width, height, 8, scanline);
811          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
812          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
813          XInitImage(image);          XInitImage(image);
# Line 517  ui_create_glyph(int width, int height, u Line 816  ui_create_glyph(int width, int height, u
816    
817          XFree(image);          XFree(image);
818          XFreeGC(display, gc);          XFreeGC(display, gc);
819          return (HGLYPH)bitmap;          return (HGLYPH) bitmap;
820  }  }
821    
822  void  void
823  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
824  {  {
825          XFreePixmap(display, (Pixmap)glyph);          XFreePixmap(display, (Pixmap) glyph);
826  }  }
827    
828  HCURSOR  HCURSOR
829  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
830                   int height, uint8 *andmask, uint8 *xormask)                   uint8 * andmask, uint8 * xormask)
831  {  {
832          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
833          XColor bg, fg;          XColor bg, fg;
# Line 585  ui_create_cursor(unsigned int x, unsigne Line 884  ui_create_cursor(unsigned int x, unsigne
884    
885          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
886          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
887            
888          xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,          xcursor =
889                                  (Pixmap)maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(display, (Pixmap) cursorglyph,
890                                        (Pixmap) maskglyph, &fg, &bg, x, y);
891    
892          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
893          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
894          xfree(mask);          xfree(mask);
895          xfree(cursor);          xfree(cursor);
896          return (HCURSOR)xcursor;          return (HCURSOR) xcursor;
897  }  }
898    
899  void  void
900  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
901  {  {
902          XDefineCursor(display, wnd, (Cursor)cursor);          current_cursor = (Cursor) cursor;
903            XDefineCursor(display, wnd, current_cursor);
904  }  }
905    
906  void  void
907  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
908  {  {
909          XFreeCursor(display, (Cursor)cursor);          XFreeCursor(display, (Cursor) cursor);
910  }  }
911    
912  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 614  ui_destroy_cursor(HCURSOR cursor) Line 915  ui_destroy_cursor(HCURSOR cursor)
915                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
916                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
917    
918    
919  HCOLOURMAP  HCOLOURMAP
920  ui_create_colourmap(COLOURMAP *colours)  ui_create_colourmap(COLOURMAP * colours)
921  {  {
922          COLOURENTRY *entry;          COLOURENTRY *entry;
923          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
924            if (!owncolmap)
925            {
926                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
927                    XColor xentry;
928                    XColor xc_cache[256];
929                    uint32 colour;
930                    int colLookup = 256;
931                    for (i = 0; i < ncolours; i++)
932                    {
933                            entry = &colours->colours[i];
934                            MAKE_XCOLOR(&xentry, entry);
935    
936          if (owncolmap)                          if (XAllocColor(display, xcolmap, &xentry) == 0)
937                            {
938                                    /* Allocation failed, find closest match. */
939                                    int j = 256;
940                                    int nMinDist = 3 * 256 * 256;
941                                    long nDist = nMinDist;
942    
943                                    /* only get the colors once */
944                                    while (colLookup--)
945                                    {
946                                            xc_cache[colLookup].pixel = colLookup;
947                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
948                                                    xc_cache[colLookup].blue = 0;
949                                            xc_cache[colLookup].flags = 0;
950                                            XQueryColor(display,
951                                                        DefaultColormap(display,
952                                                                        DefaultScreen(display)),
953                                                        &xc_cache[colLookup]);
954                                    }
955                                    colLookup = 0;
956    
957                                    /* approximate the pixel */
958                                    while (j--)
959                                    {
960                                            if (xc_cache[j].flags)
961                                            {
962                                                    nDist = ((long) (xc_cache[j].red >> 8) -
963                                                             (long) (xentry.red >> 8)) *
964                                                            ((long) (xc_cache[j].red >> 8) -
965                                                             (long) (xentry.red >> 8)) +
966                                                            ((long) (xc_cache[j].green >> 8) -
967                                                             (long) (xentry.green >> 8)) *
968                                                            ((long) (xc_cache[j].green >> 8) -
969                                                             (long) (xentry.green >> 8)) +
970                                                            ((long) (xc_cache[j].blue >> 8) -
971                                                             (long) (xentry.blue >> 8)) *
972                                                            ((long) (xc_cache[j].blue >> 8) -
973                                                             (long) (xentry.blue >> 8));
974                                            }
975                                            if (nDist < nMinDist)
976                                            {
977                                                    nMinDist = nDist;
978                                                    xentry.pixel = j;
979                                            }
980                                    }
981                            }
982                            colour = xentry.pixel;
983    
984                            /* update our cache */
985                            if (xentry.pixel < 256)
986                            {
987                                    xc_cache[xentry.pixel].red = xentry.red;
988                                    xc_cache[xentry.pixel].green = xentry.green;
989                                    xc_cache[xentry.pixel].blue = xentry.blue;
990    
991                            }
992    
993    
994                            /* byte swap here to make translate_image faster */
995                            map[i] = translate_colour(colour);
996                    }
997                    return map;
998            }
999            else
1000          {          {
1001                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
1002                  Colormap map;                  Colormap map;
# Line 638  ui_create_colourmap(COLOURMAP *colours) Line 1014  ui_create_colourmap(COLOURMAP *colours)
1014                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(display, map, xcolours, ncolours);
1015    
1016                  xfree(xcolours);                  xfree(xcolours);
1017                  return (HCOLOURMAP)map;                  return (HCOLOURMAP) map;
         }  
         else  
         {  
                 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);  
                 XColor xentry;  
                 uint32 colour;  
   
                 for (i = 0; i < ncolours; i++)  
                 {  
                         entry = &colours->colours[i];  
                         MAKE_XCOLOR(&xentry, entry);  
   
                         if (XAllocColor(display, xcolmap, &xentry) != 0)  
                                 colour = xentry.pixel;  
                         else  
                                 colour = white;  
   
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
                 }  
   
                 return map;  
1018          }          }
1019  }  }
1020    
1021  void  void
1022  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1023  {  {
1024          if (owncolmap)          if (!owncolmap)
                 XFreeColormap(display, (Colormap)map);  
         else  
1025                  xfree(map);                  xfree(map);
1026            else
1027                    XFreeColormap(display, (Colormap) map);
1028  }  }
1029    
1030  void  void
1031  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1032  {  {
1033          if (owncolmap)          if (!owncolmap)
                 XSetWindowColormap(display, wnd, (Colormap)map);  
         else  
1034                  colmap = map;                  colmap = map;
1035            else
1036                    XSetWindowColormap(display, wnd, (Colormap) map);
1037  }  }
1038    
1039  void  void
# Line 695  ui_set_clip(int x, int y, int cx, int cy Line 1049  ui_set_clip(int x, int y, int cx, int cy
1049  }  }
1050    
1051  void  void
1052  ui_reset_clip()  ui_reset_clip(void)
1053  {  {
1054          XRectangle rect;          XRectangle rect;
1055    
# Line 707  ui_reset_clip() Line 1061  ui_reset_clip()
1061  }  }
1062    
1063  void  void
1064  ui_bell()  ui_bell(void)
1065  {  {
1066          XBell(display, 0);          XBell(display, 0);
1067  }  }
# Line 724  ui_destblt(uint8 opcode, Line 1078  ui_destblt(uint8 opcode,
1078  void  void
1079  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1080            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1081            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1082  {  {
1083          Pixmap fill;          Pixmap fill;
1084            uint8 i, ipattern[8];
1085    
1086          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1087    
# Line 738  ui_patblt(uint8 opcode, Line 1093  ui_patblt(uint8 opcode,
1093                          break;                          break;
1094    
1095                  case 3: /* Pattern */                  case 3: /* Pattern */
1096                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);                          for (i = 0; i != 8; i++)
1097                                    ipattern[7 - i] = brush->pattern[i];
1098                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1099    
1100                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
1101                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
# Line 749  ui_patblt(uint8 opcode, Line 1106  ui_patblt(uint8 opcode,
1106                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1107    
1108                          XSetFillStyle(display, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
1109                          ui_destroy_glyph((HGLYPH)fill);                          XSetTSOrigin(display, gc, 0, 0);
1110                            ui_destroy_glyph((HGLYPH) fill);
1111                          break;                          break;
1112    
1113                  default:                  default:
# Line 767  ui_screenblt(uint8 opcode, Line 1125  ui_screenblt(uint8 opcode,
1125          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1126          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1127          if (ownbackstore)          if (ownbackstore)
1128                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,                  XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1129          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1130  }  }
1131    
# Line 778  ui_memblt(uint8 opcode, Line 1135  ui_memblt(uint8 opcode,
1135            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1136  {  {
1137          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1138          XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1139          if (ownbackstore)          if (ownbackstore)
1140                  XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,                  XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1141          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1142  }  }
1143    
# Line 789  void Line 1145  void
1145  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1146            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1147            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1148            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1149  {  {
1150          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1151             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 798  ui_triblt(uint8 opcode, Line 1154  ui_triblt(uint8 opcode,
1154          {          {
1155                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1156                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1157                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1158                          break;                          break;
1159    
1160                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1161                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1162                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1163                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1164                          break;                          break;
1165    
1166                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
1167                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1168                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1169                          break;                          break;
1170    
1171                  default:                  default:
# Line 825  ui_triblt(uint8 opcode, Line 1177  ui_triblt(uint8 opcode,
1177  void  void
1178  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1179          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1180          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1181  {  {
1182          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1183          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
# Line 844  ui_rect( Line 1196  ui_rect(
1196          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
1197  }  }
1198    
1199    /* warning, this function only draws on wnd or backstore, not both */
1200  void  void
1201  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1202                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1203                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1204                int fgcolour)                int bgcolour, int fgcolour)
1205  {  {
1206          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
1207          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
1208    
1209          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(display, gc,
1210                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1211          XSetStipple(display, gc, (Pixmap)glyph);          XSetStipple(display, gc, (Pixmap) glyph);
1212          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(display, gc, x, y);
1213    
1214          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1215    
1216          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(display, gc, FillSolid);
1217  }  }
1218    
1219    #define DO_GLYPH(ttext,idx) \
1220    {\
1221      glyph = cache_get_font (font, ttext[idx]);\
1222      if (!(flags & TEXT2_IMPLICIT_X))\
1223        {\
1224          xyoffset = ttext[++idx];\
1225          if ((xyoffset & 0x80))\
1226            {\
1227              if (flags & TEXT2_VERTICAL) \
1228                y += ttext[idx+1] | (ttext[idx+2] << 8);\
1229              else\
1230                x += ttext[idx+1] | (ttext[idx+2] << 8);\
1231              idx += 2;\
1232            }\
1233          else\
1234            {\
1235              if (flags & TEXT2_VERTICAL) \
1236                y += xyoffset;\
1237              else\
1238                x += xyoffset;\
1239            }\
1240        }\
1241      if (glyph != NULL)\
1242        {\
1243          ui_draw_glyph (mixmode, x + glyph->offset,\
1244                         y + glyph->baseline,\
1245                         glyph->width, glyph->height,\
1246                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1247          if (flags & TEXT2_IMPLICIT_X)\
1248            x += glyph->width;\
1249        }\
1250    }
1251    
1252  void  void
1253  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,
1254               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
1255               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1256               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1257  {  {
1258          FONTGLYPH *glyph;          FONTGLYPH *glyph;
1259          int i, offset;          int i, j, xyoffset;
1260            DATABLOB *entry;
1261    
1262          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
1263    
1264          if (boxcx > 1)          if (boxcx > 1)
1265          {          {
1266                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1267          }          }
1268          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1269          {          {
1270                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1271          }          }
1272    
1273          /* Paint text, character by character */          /* Paint text, character by character */
1274          for (i = 0; i < length; i++)          for (i = 0; i < length;)
1275          {          {
1276                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
1277                  {                  {
1278                          offset = text[++i];                          case 0xff:
1279                          if (offset & 0x80)                                  if (i + 2 < length)
1280                                  offset = ((offset & 0x7f) << 8) | text[++i];                                          cache_put_text(text[i + 1], text, text[i + 2]);
1281                                    else
1282                          if (flags & TEXT2_VERTICAL)                                  {
1283                                  y += offset;                                          error("this shouldn't be happening\n");
1284                          else                                          exit(1);
1285                                  x += offset;                                  }
1286                  }                                  /* this will move pointer from start to first character after FF command */
1287                                    length -= i + 3;
1288                                    text = &(text[i + 3]);
1289                                    i = 0;
1290                                    break;
1291    
1292                  if (glyph != NULL)                          case 0xfe:
1293                  {                                  entry = cache_get_text(text[i + 1]);
1294                          ui_draw_glyph(mixmode, x + (short) glyph->offset,                                  if (entry != NULL)
1295                                        y + (short) glyph->baseline,                                  {
1296                                        glyph->width, glyph->height,                                          if ((((uint8 *) (entry->data))[1] ==
1297                                        glyph->pixmap, 0, 0,                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
1298                                        bgcolour, fgcolour);                                          {
1299                                                    if (flags & TEXT2_VERTICAL)
1300                                                            y += text[i + 2];
1301                                                    else
1302                                                            x += text[i + 2];
1303                                            }
1304                                            for (j = 0; j < entry->size; j++)
1305                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1306                                    }
1307                                    if (i + 2 < length)
1308                                            i += 3;
1309                                    else
1310                                            i += 2;
1311                                    length -= i;
1312                                    /* this will move pointer from start to first character after FE command */
1313                                    text = &(text[i]);
1314                                    i = 0;
1315                                    break;
1316    
1317                          if (flags & TEXT2_IMPLICIT_X)                          default:
1318                                  x += glyph->width;                                  DO_GLYPH(text, i);
1319                                    i++;
1320                                    break;
1321                  }                  }
1322          }          }
1323            if (ownbackstore)
1324            {
1325                    if (boxcx > 1)
1326                            XCopyArea(display, backstore, wnd, gc, boxx,
1327                                      boxy, boxcx, boxcy, boxx, boxy);
1328                    else
1329                            XCopyArea(display, backstore, wnd, gc, clipx,
1330                                      clipy, clipcx, clipcy, clipx, clipy);
1331            }
1332  }  }
1333    
1334  void  void
# Line 922  ui_desktop_save(uint32 offset, int x, in Line 1339  ui_desktop_save(uint32 offset, int x, in
1339    
1340          if (ownbackstore)          if (ownbackstore)
1341          {          {
1342                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
1343          }          }
1344          else          else
1345          {          {
1346                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(display, wnd, cx, cy, depth);
1347                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1348                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
1349                  XFreePixmap(display, pix);                  XFreePixmap(display, pix);
1350          }          }
1351    
1352          offset *= bpp/8;          offset *= bpp / 8;
1353          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
                           bpp/8, (uint8 *)image->data);  
1354    
1355          XDestroyImage(image);          XDestroyImage(image);
1356  }  }
# Line 947  ui_desktop_restore(uint32 offset, int x, Line 1361  ui_desktop_restore(uint32 offset, int x,
1361          XImage *image;          XImage *image;
1362          uint8 *data;          uint8 *data;
1363    
1364          offset *= bpp/8;          offset *= bpp / 8;
1365          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, bpp / 8);
1366          if (data == NULL)          if (data == NULL)
1367                  return;                  return;
1368    
1369          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1370                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
                              cx * bpp/8);  
1371    
1372          if (ownbackstore)          if (ownbackstore)
1373          {          {

Legend:
Removed from v.38  
changed lines
  Added in v.309

  ViewVC Help
Powered by ViewVC 1.1.26