/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 54 by n-ki, Fri Jun 7 07:49:59 2002 UTC revision 1042 by astrand, Tue Jan 24 12:40:24 2006 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
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-2005
5    
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 20  Line 20 
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23  #include <X11/XKBlib.h>  #include <unistd.h>
24    #include <sys/time.h>
25  #include <time.h>  #include <time.h>
26  #include <errno.h>  #include <errno.h>
27    #include <strings.h>
28  #include "rdesktop.h"  #include "rdesktop.h"
29    #include "xproto.h"
30    
31  extern char keymapname[16];  extern int g_width;
32  extern int keylayout;  extern int g_height;
33  extern int width;  extern int g_xpos;
34  extern int height;  extern int g_ypos;
35  extern BOOL sendmotion;  extern int g_pos;
36  extern BOOL fullscreen;  extern BOOL g_sendmotion;
37    extern BOOL g_fullscreen;
38  Display *display;  extern BOOL g_grab_keyboard;
39  XkbDescPtr xkb;  extern BOOL g_hide_decorations;
40  static int x_socket;  extern char g_title[];
41  static Window wnd;  /* Color depth of the RDP session.
42  static GC gc;     As of RDP 5.1, it may be 8, 15, 16 or 24. */
43  static Visual *visual;  extern int g_server_depth;
44  static int depth;  extern int g_win_button_size;
45  static int bpp;  
46    Display *g_display;
47    Time g_last_gesturetime;
48    static int g_x_socket;
49    static Screen *g_screen;
50    Window g_wnd;
51    extern uint32 g_embed_wnd;
52    BOOL g_enable_compose = False;
53    BOOL g_Unobscured;              /* used for screenblt */
54    static GC g_gc = NULL;
55    static GC g_create_bitmap_gc = NULL;
56    static GC g_create_glyph_gc = NULL;
57    static Visual *g_visual;
58    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
59       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
60       as far as we're concerned. */
61    static int g_depth;
62    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
63       This may be larger than g_depth, in which case some of the bits would
64       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
65    static int g_bpp;
66    static XIM g_IM;
67    static XIC g_IC;
68    static XModifierKeymap *g_mod_map;
69    static Cursor g_current_cursor;
70    static HCURSOR g_null_cursor = NULL;
71    static Atom g_protocol_atom, g_kill_atom;
72    static BOOL g_focused;
73    static BOOL g_mouse_in_wnd;
74    /* Indicates the visual is has 15, 16 or 24 depth
75       and the same color channel masks as its RDP equivalent. */
76    static BOOL g_compatible_depth;
77    /* Indicates whether RDP's bitmaps and our XImages have the same
78       binary format. If so, we can avoid an expensive translation.
79       If this is True, so is g_compatible_depth. */
80    static BOOL g_no_translate_image = False;
81    
82  /* endianness */  /* endianness */
83  static BOOL host_be;  static BOOL g_host_be;
84  static BOOL xserver_be;  static BOOL g_xserver_be;
85    static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
86    static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
87    
88  /* software backing store */  /* software backing store */
89  static BOOL ownbackstore;  extern BOOL g_ownbackstore;
90  static Pixmap backstore;  static Pixmap g_backstore = 0;
91    
92    /* Moving in single app mode */
93    static BOOL g_moving_wnd;
94    static int g_move_x_offset = 0;
95    static int g_move_y_offset = 0;
96    static BOOL g_using_full_workarea = False;
97    
98    #ifdef WITH_RDPSND
99    extern int g_dsp_fd;
100    extern BOOL g_dsp_busy;
101    extern BOOL g_rdpsnd;
102    #endif
103    
104    /* MWM decorations */
105    #define MWM_HINTS_DECORATIONS   (1L << 1)
106    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
107    typedef struct
108    {
109            unsigned long flags;
110            unsigned long functions;
111            unsigned long decorations;
112            long inputMode;
113            unsigned long status;
114    }
115    PropMotifWmHints;
116    
117    typedef struct
118    {
119            uint32 red;
120            uint32 green;
121            uint32 blue;
122    }
123    PixelColour;
124    
 /* needed to keep track of the modifiers */  
 static unsigned int numlock_modifier_mask = 0;  
 static unsigned int key_down_state = 0;  
   
   
 #define DShift1Mask   (1<<0)  
 #define DLockMask     (1<<1)  
 #define DControl1Mask (1<<2)  
 #define DMod1Mask     (1<<3)  
 #define DMod2Mask     (1<<4)  
 #define DMod3Mask     (1<<5)  
 #define DMod4Mask     (1<<6)  
 #define DMod5Mask     (1<<7)  
 #define DShift2Mask   (1<<8)  
 #define DControl2Mask (1<<9)  
 #define DNumLockMask  (1<<10)  
125    
126  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
127  { \  { \
128          XFillRectangle(display, wnd, gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
129          if (ownbackstore) \          if (g_ownbackstore) \
130                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
131    }
132    
133    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
134    { \
135            XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
136    }
137    
138    #define FILL_POLYGON(p,np)\
139    { \
140            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
141            if (g_ownbackstore) \
142                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
143    }
144    
145    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
146    { \
147            switch (m) \
148            { \
149                    case 0: /* Outline */ \
150                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
151                            if (g_ownbackstore) \
152                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
153                            break; \
154                    case 1: /* Filled */ \
155                            XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
156                            if (g_ownbackstore) \
157                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
158                            break; \
159            } \
160  }  }
161    
162  /* colour maps */  /* colour maps */
163  static BOOL owncolmap;  extern BOOL g_owncolmap;
164  static Colormap xcolmap;  static Colormap g_xcolmap;
165  static uint32 white;  static uint32 *g_colmap = NULL;
166  static uint32 *colmap;  
167    #define TRANSLATE(col)          ( g_server_depth != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
168  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
169  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
 #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  
170    
171  static int rop2_map[] = {  static int rop2_map[] = {
172          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 102  static int rop2_map[] = { Line 187  static int rop2_map[] = {
187          GXset                   /* 1 */          GXset                   /* 1 */
188  };  };
189    
190  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
191  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
   
 void xwin_get_numlock_mask();  
 void xwin_mod_update(uint32 state, uint32 ev_time );  
 void xwin_mod_release(uint32 state, uint32 ev_time, uint32 scancode);  
 void xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode);  
   
 static void  
 translate8(uint8 *data, uint8 *out, uint8 *end)  
 {  
         while (out < end)  
                 *(out++) = (uint8)colmap[*(data++)];  
 }  
192    
193  static void  static void
194  translate16(uint8 *data, uint16 *out, uint16 *end)  mwm_hide_decorations(void)
195  {  {
196          while (out < end)          PropMotifWmHints motif_hints;
197                  *(out++) = (uint16)colmap[*(data++)];          Atom hintsatom;
 }  
198    
199  /* little endian - conversion happens when colourmap is built */          /* setup the property */
200  static void          motif_hints.flags = MWM_HINTS_DECORATIONS;
201  translate24(uint8 *data, uint8 *out, uint8 *end)          motif_hints.decorations = 0;
 {  
         uint32 value;  
202    
203          while (out < end)          /* get the atom for the property */
204            hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
205            if (!hintsatom)
206          {          {
207                  value = colmap[*(data++)];                  warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
208                  *(out++) = value;                  return;
                 *(out++) = value >> 8;  
                 *(out++) = value >> 16;  
209          }          }
 }  
210    
211  static void          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
212  translate32(uint8 *data, uint32 *out, uint32 *end)                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
 {  
         while (out < end)  
                 *(out++) = colmap[*(data++)];  
213  }  }
214    
215  static uint8 *  #define SPLITCOLOUR15(colour, rv) \
216  translate_image(int width, int height, uint8 *data)  { \
217  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
218          int size = width * height * bpp/8;          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
219          uint8 *out = xmalloc(size);          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
220          uint8 *end = out + size;  }
   
         switch (bpp)  
         {  
                 case 8:  
                         translate8(data, out, end);  
                         break;  
   
                 case 16:  
                         translate16(data, (uint16 *)out, (uint16 *)end);  
                         break;  
   
                 case 24:  
                         translate24(data, out, end);  
                         break;  
221    
222                  case 32:  #define SPLITCOLOUR16(colour, rv) \
223                          translate32(data, (uint32 *)out, (uint32 *)end);  { \
224                          break;          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
225          }          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
226            rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
227    } \
228    
229          return out;  #define SPLITCOLOUR24(colour, rv) \
230    { \
231            rv.blue = (colour & 0xff0000) >> 16; \
232            rv.green = (colour & 0x00ff00) >> 8; \
233            rv.red = (colour & 0x0000ff); \
234  }  }
235    
236    #define MAKECOLOUR(pc) \
237            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
238                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
239                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
240    
241  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
242  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
243  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
244                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
245    
246    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
247    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
248    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
249    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
250    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
251    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
252    
253  static uint32  static uint32
254  translate_colour(uint32 colour)  translate_colour(uint32 colour)
255  {  {
256          switch (bpp)          PixelColour pc;
257            switch (g_server_depth)
258          {          {
259                    case 15:
260                            SPLITCOLOUR15(colour, pc);
261                            break;
262                  case 16:                  case 16:
263                          if (host_be != xserver_be)                          SPLITCOLOUR16(colour, pc);
                                 BSWAP16(colour);  
264                          break;                          break;
   
265                  case 24:                  case 24:
266                          if (xserver_be)                          SPLITCOLOUR24(colour, pc);
                                 BSWAP24(colour);  
267                          break;                          break;
268                    default:
269                  case 32:                          /* Avoid warning */
270                          if (host_be != xserver_be)                          pc.red = 0;
271                                  BSWAP32(colour);                          pc.green = 0;
272                            pc.blue = 0;
273                          break;                          break;
274          }          }
275            return MAKECOLOUR(pc);
276    }
277    
278          return colour;  /* indent is confused by UNROLL8 */
279    /* *INDENT-OFF* */
280    
281    /* repeat and unroll, similar to bitmap.c */
282    /* potentialy any of the following translate */
283    /* functions can use repeat but just doing */
284    /* the most common ones */
285    
286    #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
287    /* 2 byte output repeat */
288    #define REPEAT2(stm) \
289    { \
290            while (out <= end - 8 * 2) \
291                    UNROLL8(stm) \
292            while (out < end) \
293                    { stm } \
294  }  }
295    /* 3 byte output repeat */
296    #define REPEAT3(stm) \
297    { \
298            while (out <= end - 8 * 3) \
299                    UNROLL8(stm) \
300            while (out < end) \
301                    { stm } \
302    }
303    /* 4 byte output repeat */
304    #define REPEAT4(stm) \
305    { \
306            while (out <= end - 8 * 4) \
307                    UNROLL8(stm) \
308            while (out < end) \
309                    { stm } \
310    }
311    /* *INDENT-ON* */
312    
313  BOOL  static void
314  ui_create_window(char *title)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
315  {  {
316          XSetWindowAttributes attribs;          while (out < end)
317          XClassHint *classhints;                  *(out++) = (uint8) g_colmap[*(data++)];
318          XSizeHints *sizehints;  }
319          unsigned long input_mask;  
320          XPixmapFormatValues *pfm;  static void
321          Screen *screen;  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
322          uint16 test;  {
323          int i;          uint16 value;
324            
325          int xkb_minor, xkb_major;          if (g_compatible_depth)
         int xkb_event, xkb_error, xkb_reason;  
   
         /* compare compiletime libs with runtime libs. */  
         xkb_major = XkbMajorVersion;  
         xkb_minor = XkbMinorVersion;  
         if( XkbLibraryVersion( &xkb_major, &xkb_minor ) == False )  
326          {          {
327                  error("please re-compile rdesktop\ncompile time version of xkb is not compatible with\nyour runtime version of the library\n");                  /* *INDENT-OFF* */
328                  return False;                  REPEAT2
329                    (
330                            *((uint16 *) out) = g_colmap[*(data++)];
331                            out += 2;
332                    )
333                    /* *INDENT-ON* */
334          }          }
335            else if (g_xserver_be)
336            {
337                    while (out < end)
338                    {
339                            value = (uint16) g_colmap[*(data++)];
340                            BOUT16(out, value);
341                    }
342            }
343            else
344            {
345                    while (out < end)
346                    {
347                            value = (uint16) g_colmap[*(data++)];
348                            LOUT16(out, value);
349                    }
350            }
351    }
352    
353    /* little endian - conversion happens when colourmap is built */
354    static void
355    translate8to24(const uint8 * data, uint8 * out, uint8 * end)
356    {
357            uint32 value;
358    
359          display = XkbOpenDisplay( NULL, &xkb_event, &xkb_error, &xkb_major, &xkb_minor, &xkb_reason );          if (g_compatible_depth)
         switch(xkb_reason)  
360          {          {
361                  case XkbOD_BadLibraryVersion:                  while (out < end)
362                          error("XkbOD_BadLibraryVersion: XKB extensions in server and the library rdesktop is linked against aren't compatible with each other.\n");                  {
363                          break;                          value = g_colmap[*(data++)];
364                  case XkbOD_ConnectionRefused:                          BOUT24(out, value);
365                          error("XkbOD_ConnectionRefused\n");                  }
366                          break;          }
367                  case XkbOD_BadServerVersion:          else
368                          error("XkbOD_BadServerVersion\n");          {
369                          break;                  while (out < end)
370                  case XkbOD_NonXkbServer:                  {
371                          error("XkbOD_NonXkbServer: XKB extension not present in server\nupdate your X server.\n");                          value = g_colmap[*(data++)];
372                          break;                          LOUT24(out, value);
373                  case XkbOD_Success:                  }
                         DEBUG("XkbOD_Success: Connection established with display\n");  
                         break;  
374          }          }
375    }
376    
377          if (display == NULL)  static void
378    translate8to32(const uint8 * data, uint8 * out, uint8 * end)
379    {
380            uint32 value;
381    
382            if (g_compatible_depth)
383          {          {
384                  error("Failed to open display\n");                  /* *INDENT-OFF* */
385                  return False;                  REPEAT4
386                    (
387                            *((uint32 *) out) = g_colmap[*(data++)];
388                            out += 4;
389                    )
390                    /* *INDENT-ON* */
391            }
392            else if (g_xserver_be)
393            {
394                    while (out < end)
395                    {
396                            value = g_colmap[*(data++)];
397                            BOUT32(out, value);
398                    }
399            }
400            else
401            {
402                    while (out < end)
403                    {
404                            value = g_colmap[*(data++)];
405                            LOUT32(out, value);
406                    }
407          }          }
408    }
409    
410          x_socket = ConnectionNumber(display);  static void
411          screen = DefaultScreenOfDisplay(display);  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
412          visual = DefaultVisualOfScreen(screen);  {
413          depth = DefaultDepthOfScreen(screen);          uint16 pixel;
414                    uint16 value;
415          pfm = XListPixmapFormats(display, &i);          PixelColour pc;
416          if (pfm != NULL)  
417            if (g_xserver_be)
418          {          {
419                  /* Use maximum bpp for this depth - this is generally                  while (out < end)
                    desirable, e.g. 24 bits->32 bits. */  
                 while (i--)  
420                  {                  {
421                          if ((pfm[i].depth == depth)                          pixel = *(data++);
422                              && (pfm[i].bits_per_pixel > bpp))                          if (g_host_be)
423                          {                          {
424                                  bpp = pfm[i].bits_per_pixel;                                  BSWAP16(pixel);
425                          }                          }
426                            SPLITCOLOUR15(pixel, pc);
427                            value = MAKECOLOUR(pc);
428                            BOUT16(out, value);
429                  }                  }
                 XFree(pfm);  
430          }          }
431            else
         if (bpp < 8)  
432          {          {
433                  error("Less than 8 bpp not currently supported.\n");                  while (out < end)
434                  XCloseDisplay(display);                  {
435                  return False;                          pixel = *(data++);
436                            if (g_host_be)
437                            {
438                                    BSWAP16(pixel);
439                            }
440                            SPLITCOLOUR15(pixel, pc);
441                            value = MAKECOLOUR(pc);
442                            LOUT16(out, value);
443                    }
444          }          }
445    }
446    
447          if (depth <= 8)  static void
448                  owncolmap = True;  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
449    {
450            uint32 value;
451            uint16 pixel;
452            PixelColour pc;
453    
454            if (g_compatible_depth)
455            {
456                    /* *INDENT-OFF* */
457                    REPEAT3
458                    (
459                            pixel = *(data++);
460                            SPLITCOLOUR15(pixel, pc);
461                            *(out++) = pc.blue;
462                            *(out++) = pc.green;
463                            *(out++) = pc.red;
464                    )
465                    /* *INDENT-ON* */
466            }
467            else if (g_xserver_be)
468            {
469                    while (out < end)
470                    {
471                            pixel = *(data++);
472                            if (g_host_be)
473                            {
474                                    BSWAP16(pixel);
475                            }
476                            SPLITCOLOUR15(pixel, pc);
477                            value = MAKECOLOUR(pc);
478                            BOUT24(out, value);
479                    }
480            }
481          else          else
482                  xcolmap = DefaultColormapOfScreen(screen);          {
483                    while (out < end)
484                    {
485                            pixel = *(data++);
486                            if (g_host_be)
487                            {
488                                    BSWAP16(pixel);
489                            }
490                            SPLITCOLOUR15(pixel, pc);
491                            value = MAKECOLOUR(pc);
492                            LOUT24(out, value);
493                    }
494            }
495    }
496    
497          test = 1;  static void
498          host_be = !(BOOL)(*(uint8 *)(&test));  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
499          xserver_be = (ImageByteOrder(display) == MSBFirst);  {
500            uint16 pixel;
501            uint32 value;
502            PixelColour pc;
503    
504          white = WhitePixelOfScreen(screen);          if (g_compatible_depth)
505          attribs.background_pixel = BlackPixelOfScreen(screen);          {
506          attribs.backing_store = DoesBackingStore(screen);                  /* *INDENT-OFF* */
507                    REPEAT4
508                    (
509                            pixel = *(data++);
510                            SPLITCOLOUR15(pixel, pc);
511                            *(out++) = pc.blue;
512                            *(out++) = pc.green;
513                            *(out++) = pc.red;
514                            *(out++) = 0;
515                    )
516                    /* *INDENT-ON* */
517            }
518            else if (g_xserver_be)
519            {
520                    while (out < end)
521                    {
522                            pixel = *(data++);
523                            if (g_host_be)
524                            {
525                                    BSWAP16(pixel);
526                            }
527                            SPLITCOLOUR15(pixel, pc);
528                            value = MAKECOLOUR(pc);
529                            BOUT32(out, value);
530                    }
531            }
532            else
533            {
534                    while (out < end)
535                    {
536                            pixel = *(data++);
537                            if (g_host_be)
538                            {
539                                    BSWAP16(pixel);
540                            }
541                            SPLITCOLOUR15(pixel, pc);
542                            value = MAKECOLOUR(pc);
543                            LOUT32(out, value);
544                    }
545            }
546    }
547    
548          if (attribs.backing_store == NotUseful)  static void
549                  ownbackstore = True;  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
550    {
551            uint16 pixel;
552            uint16 value;
553            PixelColour pc;
554    
555          if (fullscreen)          if (g_xserver_be)
556          {          {
557                  attribs.override_redirect = True;                  if (g_host_be)
558                  width = WidthOfScreen(screen);                  {
559                  height = HeightOfScreen(screen);                          while (out < end)
560                            {
561                                    pixel = *(data++);
562                                    BSWAP16(pixel);
563                                    SPLITCOLOUR16(pixel, pc);
564                                    value = MAKECOLOUR(pc);
565                                    BOUT16(out, value);
566                            }
567                    }
568                    else
569                    {
570                            while (out < end)
571                            {
572                                    pixel = *(data++);
573                                    SPLITCOLOUR16(pixel, pc);
574                                    value = MAKECOLOUR(pc);
575                                    BOUT16(out, value);
576                            }
577                    }
578          }          }
579          else          else
580          {          {
581                  attribs.override_redirect = False;                  if (g_host_be)
582                    {
583                            while (out < end)
584                            {
585                                    pixel = *(data++);
586                                    BSWAP16(pixel);
587                                    SPLITCOLOUR16(pixel, pc);
588                                    value = MAKECOLOUR(pc);
589                                    LOUT16(out, value);
590                            }
591                    }
592                    else
593                    {
594                            while (out < end)
595                            {
596                                    pixel = *(data++);
597                                    SPLITCOLOUR16(pixel, pc);
598                                    value = MAKECOLOUR(pc);
599                                    LOUT16(out, value);
600                            }
601                    }
602          }          }
603    }
604    
605          width = (width + 3) & ~3; /* make width a multiple of 32 bits */  static void
606    translate16to24(const uint16 * data, uint8 * out, uint8 * end)
607    {
608            uint32 value;
609            uint16 pixel;
610            PixelColour pc;
611    
612          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          if (g_compatible_depth)
613                              0, 0, width, height, 0, CopyFromParent,          {
614                              InputOutput, CopyFromParent,                  /* *INDENT-OFF* */
615                              CWBackingStore | CWBackPixel | CWOverrideRedirect,                  REPEAT3
616                              &attribs);                  (
617                            pixel = *(data++);
618                            SPLITCOLOUR16(pixel, pc);
619                            *(out++) = pc.blue;
620                            *(out++) = pc.green;
621                            *(out++) = pc.red;
622                    )
623                    /* *INDENT-ON* */
624            }
625            else if (g_xserver_be)
626            {
627                    if (g_host_be)
628                    {
629                            while (out < end)
630                            {
631                                    pixel = *(data++);
632                                    BSWAP16(pixel);
633                                    SPLITCOLOUR16(pixel, pc);
634                                    value = MAKECOLOUR(pc);
635                                    BOUT24(out, value);
636                            }
637                    }
638                    else
639                    {
640                            while (out < end)
641                            {
642                                    pixel = *(data++);
643                                    SPLITCOLOUR16(pixel, pc);
644                                    value = MAKECOLOUR(pc);
645                                    BOUT24(out, value);
646                            }
647                    }
648            }
649            else
650            {
651                    if (g_host_be)
652                    {
653                            while (out < end)
654                            {
655                                    pixel = *(data++);
656                                    BSWAP16(pixel);
657                                    SPLITCOLOUR16(pixel, pc);
658                                    value = MAKECOLOUR(pc);
659                                    LOUT24(out, value);
660                            }
661                    }
662                    else
663                    {
664                            while (out < end)
665                            {
666                                    pixel = *(data++);
667                                    SPLITCOLOUR16(pixel, pc);
668                                    value = MAKECOLOUR(pc);
669                                    LOUT24(out, value);
670                            }
671                    }
672            }
673    }
674    
675          XStoreName(display, wnd, title);  static void
676    translate16to32(const uint16 * data, uint8 * out, uint8 * end)
677    {
678            uint16 pixel;
679            uint32 value;
680            PixelColour pc;
681    
682          classhints = XAllocClassHint();          if (g_compatible_depth)
         if (classhints != NULL)  
683          {          {
684                  classhints->res_name = classhints->res_class = "rdesktop";                  /* *INDENT-OFF* */
685                  XSetClassHint(display, wnd, classhints);                  REPEAT4
686                  XFree(classhints);                  (
687                            pixel = *(data++);
688                            SPLITCOLOUR16(pixel, pc);
689                            *(out++) = pc.blue;
690                            *(out++) = pc.green;
691                            *(out++) = pc.red;
692                            *(out++) = 0;
693                    )
694                    /* *INDENT-ON* */
695          }          }
696            else if (g_xserver_be)
         sizehints = XAllocSizeHints();  
         if (sizehints)  
697          {          {
698                  sizehints->flags = PMinSize | PMaxSize;                  if (g_host_be)
699                  sizehints->min_width = sizehints->max_width = width;                  {
700                  sizehints->min_height = sizehints->max_height = height;                          while (out < end)
701                  XSetWMNormalHints(display, wnd, sizehints);                          {
702                  XFree(sizehints);                                  pixel = *(data++);
703                                    BSWAP16(pixel);
704                                    SPLITCOLOUR16(pixel, pc);
705                                    value = MAKECOLOUR(pc);
706                                    BOUT32(out, value);
707                            }
708                    }
709                    else
710                    {
711                            while (out < end)
712                            {
713                                    pixel = *(data++);
714                                    SPLITCOLOUR16(pixel, pc);
715                                    value = MAKECOLOUR(pc);
716                                    BOUT32(out, value);
717                            }
718                    }
719          }          }
720            else
721            {
722                    if (g_host_be)
723                    {
724                            while (out < end)
725                            {
726                                    pixel = *(data++);
727                                    BSWAP16(pixel);
728                                    SPLITCOLOUR16(pixel, pc);
729                                    value = MAKECOLOUR(pc);
730                                    LOUT32(out, value);
731                            }
732                    }
733                    else
734                    {
735                            while (out < end)
736                            {
737                                    pixel = *(data++);
738                                    SPLITCOLOUR16(pixel, pc);
739                                    value = MAKECOLOUR(pc);
740                                    LOUT32(out, value);
741                            }
742                    }
743            }
744    }
745    
746          xkeymap_init();  static void
747    translate24to16(const uint8 * data, uint8 * out, uint8 * end)
748    {
749            uint32 pixel = 0;
750            uint16 value;
751            PixelColour pc;
752    
753          input_mask = KeyPressMask | KeyReleaseMask |          while (out < end)
754                           ButtonPressMask | ButtonReleaseMask |          {
755                           EnterWindowMask | LeaveWindowMask;                  pixel = *(data++) << 16;
756          if (sendmotion)                  pixel |= *(data++) << 8;
757                  input_mask |= PointerMotionMask;                  pixel |= *(data++);
758                    SPLITCOLOUR24(pixel, pc);
759                    value = MAKECOLOUR(pc);
760                    if (g_xserver_be)
761                    {
762                            BOUT16(out, value);
763                    }
764                    else
765                    {
766                            LOUT16(out, value);
767                    }
768            }
769    }
770    
771          if (ownbackstore)  static void
772                  input_mask |= ExposureMask;  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
773    {
774            uint32 pixel;
775            uint32 value;
776            PixelColour pc;
777    
778          XSelectInput(display, wnd, input_mask);          if (g_xserver_be)
779          gc = XCreateGC(display, wnd, 0, NULL);          {
780                    while (out < end)
781                    {
782                            pixel = *(data++) << 16;
783                            pixel |= *(data++) << 8;
784                            pixel |= *(data++);
785                            SPLITCOLOUR24(pixel, pc);
786                            value = MAKECOLOUR(pc);
787                            BOUT24(out, value);
788                    }
789            }
790            else
791            {
792                    while (out < end)
793                    {
794                            pixel = *(data++) << 16;
795                            pixel |= *(data++) << 8;
796                            pixel |= *(data++);
797                            SPLITCOLOUR24(pixel, pc);
798                            value = MAKECOLOUR(pc);
799                            LOUT24(out, value);
800                    }
801            }
802    }
803    
804          if (ownbackstore)  static void
805                  backstore = XCreatePixmap(display, wnd, width, height, depth);  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
806    {
807            uint32 pixel;
808            uint32 value;
809            PixelColour pc;
810    
811          XMapWindow(display, wnd);          if (g_compatible_depth)
812            {
813                    /* *INDENT-OFF* */
814    #ifdef NEED_ALIGN
815                    REPEAT4
816                    (
817                            *(out++) = *(data++);
818                            *(out++) = *(data++);
819                            *(out++) = *(data++);
820                            *(out++) = 0;
821                    )
822    #else
823                    REPEAT4
824                    (
825                     /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
826                     *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
827                     out += 4;
828                     data += 3;
829                    )
830    #endif
831                    /* *INDENT-ON* */
832            }
833            else if (g_xserver_be)
834            {
835                    while (out < end)
836                    {
837                            pixel = *(data++) << 16;
838                            pixel |= *(data++) << 8;
839                            pixel |= *(data++);
840                            SPLITCOLOUR24(pixel, pc);
841                            value = MAKECOLOUR(pc);
842                            BOUT32(out, value);
843                    }
844            }
845            else
846            {
847                    while (out < end)
848                    {
849                            pixel = *(data++) << 16;
850                            pixel |= *(data++) << 8;
851                            pixel |= *(data++);
852                            SPLITCOLOUR24(pixel, pc);
853                            value = MAKECOLOUR(pc);
854                            LOUT32(out, value);
855                    }
856            }
857    }
858    
859          /* TODO: error texts... make them friendly. */  static uint8 *
860          xkb = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);  translate_image(int width, int height, uint8 * data)
861          if ((int)xkb == BadAlloc || xkb == NULL)  {
862          {          int size;
863                          error( "XkbGetKeyboard failed.\n");          uint8 *out;
864                          exit(0);          uint8 *end;
865          }  
866            /*
867               If RDP depth and X Visual depths match,
868               and arch(endian) matches, no need to translate:
869               just return data.
870               Note: select_visual should've already ensured g_no_translate
871               is only set for compatible depths, but the RDP depth might've
872               changed during connection negotiations.
873             */
874            if (g_no_translate_image)
875            {
876                    if ((g_depth == 15 && g_server_depth == 15) ||
877                        (g_depth == 16 && g_server_depth == 16) ||
878                        (g_depth == 24 && g_server_depth == 24))
879                            return data;
880            }
881    
882            size = width * height * (g_bpp / 8);
883            out = (uint8 *) xmalloc(size);
884            end = out + size;
885    
886          /* TODO: error texts... make them friendly. */          switch (g_server_depth)
         if( XkbSelectEvents(display, xkb->device_spec, XkbAllEventsMask, XkbAllEventsMask) == False )  
887          {          {
888                          error( "XkbSelectEvents failed.\n");                  case 24:
889                          exit(0);                          switch (g_bpp)
890                            {
891                                    case 32:
892                                            translate24to32(data, out, end);
893                                            break;
894                                    case 24:
895                                            translate24to24(data, out, end);
896                                            break;
897                                    case 16:
898                                            translate24to16(data, out, end);
899                                            break;
900                            }
901                            break;
902                    case 16:
903                            switch (g_bpp)
904                            {
905                                    case 32:
906                                            translate16to32((uint16 *) data, out, end);
907                                            break;
908                                    case 24:
909                                            translate16to24((uint16 *) data, out, end);
910                                            break;
911                                    case 16:
912                                            translate16to16((uint16 *) data, out, end);
913                                            break;
914                            }
915                            break;
916                    case 15:
917                            switch (g_bpp)
918                            {
919                                    case 32:
920                                            translate15to32((uint16 *) data, out, end);
921                                            break;
922                                    case 24:
923                                            translate15to24((uint16 *) data, out, end);
924                                            break;
925                                    case 16:
926                                            translate15to16((uint16 *) data, out, end);
927                                            break;
928                            }
929                            break;
930                    case 8:
931                            switch (g_bpp)
932                            {
933                                    case 8:
934                                            translate8to8(data, out, end);
935                                            break;
936                                    case 16:
937                                            translate8to16(data, out, end);
938                                            break;
939                                    case 24:
940                                            translate8to24(data, out, end);
941                                            break;
942                                    case 32:
943                                            translate8to32(data, out, end);
944                                            break;
945                            }
946                            break;
947          }          }
948                    return out;
         xwin_get_numlock_mask();  
   
         return True;  
949  }  }
950    
951  void  BOOL
952  xwin_get_numlock_mask()  get_key_state(unsigned int state, uint32 keysym)
953  {  {
954          KeyCode numlockcode;          int modifierpos, key, keysymMask = 0;
955          KeyCode* keycode;          int offset;
956          XModifierKeymap *modmap;  
957          int i,j;          KeyCode keycode = XKeysymToKeycode(g_display, keysym);
958    
959          /* Find out if numlock is already defined as a modifier key, and if so where */          if (keycode == NoSymbol)
960          numlockcode = XKeysymToKeycode(display, 0xFF7F);        /* XF_Num_Lock = 0xFF7F */                  return False;
961          if (numlockcode) {  
962                  modmap = XGetModifierMapping(display);          for (modifierpos = 0; modifierpos < 8; modifierpos++)
963                  if (modmap) {          {
964                          keycode = modmap->modifiermap;                  offset = g_mod_map->max_keypermod * modifierpos;
965                          for (i = 0; i < 8; i++)  
966                                  for (j = modmap->max_keypermod; j--;) {                  for (key = 0; key < g_mod_map->max_keypermod; key++)
967                                          if (*keycode == numlockcode) {                  {
968                                                  numlock_modifier_mask = (1 << i);                          if (g_mod_map->modifiermap[offset + key] == keycode)
969                                                  i = 8;                                  keysymMask |= 1 << modifierpos;
                                                 break;  
                                         }  
                                         keycode++;  
                                 }  
                 if (!numlock_modifier_mask) {  
                                 modmap->modifiermap[7 * modmap->max_keypermod] = numlockcode;  
                                 if (XSetModifierMapping(display, modmap) == MappingSuccess)  
                                         numlock_modifier_mask = (1 << 7);  
                                 else  
                                         printf("XSetModifierMapping failed!\n");  
                         }  
                         XFreeModifiermap(modmap);  
970                  }                  }
971          }          }
972    
973          if (!numlock_modifier_mask)          return (state & keysymMask) ? True : False;
                 printf("WARNING: Failed to get a numlock modifier mapping.\n");  
                   
974  }  }
975    
976  void  static void
977  ui_destroy_window()  calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
978  {  {
979          if( xkb != NULL )          *shift_l = ffs(mask) - 1;
980                  XkbFreeKeyboard(xkb, XkbAllControlsMask, True);          mask >>= *shift_l;
981            *shift_r = 8 - ffs(mask & ~(mask >> 1));
982          if (ownbackstore)  }
                 XFreePixmap(display, backstore);  
983    
984          XFreeGC(display, gc);  /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
985          XDestroyWindow(display, wnd);     calculates the bits-per-pixel of this channel (a.k.a. colour weight).
986          XCloseDisplay(display);   */
987          display = NULL;  static unsigned
988    calculate_mask_weight(uint32 mask)
989    {
990            unsigned weight = 0;
991            do
992            {
993                    weight += (mask & 1);
994            }
995            while (mask >>= 1);
996            return weight;
997  }  }
998    
999  static void  static BOOL
1000  xwin_process_events()  select_visual()
1001  {  {
1002          XEvent xevent;          XPixmapFormatValues *pfm;
1003            int pixmap_formats_count, visuals_count;
1004            XVisualInfo *vmatches = NULL;
1005            XVisualInfo template;
1006            int i;
1007            unsigned red_weight, blue_weight, green_weight;
1008    
1009          KeySym keysym;          red_weight = blue_weight = green_weight = 0;
         uint8 scancode;  
         uint16 button, flags;  
         uint32 ev_time;  
         uint32 tmpmods;  
1010    
1011          while (XCheckMaskEvent(display, ~0, &xevent))          pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1012            if (pfm == NULL)
1013          {          {
1014                  ev_time = time(NULL);                  error("Unable to get list of pixmap formats from display.\n");
1015                  flags = 0;                  XCloseDisplay(g_display);
1016                    return False;
1017            }
1018    
1019                  switch (xevent.type)          /* Search for best TrueColor visual */
1020            template.class = TrueColor;
1021            vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1022            g_visual = NULL;
1023            g_no_translate_image = False;
1024            g_compatible_depth = False;
1025            if (vmatches != NULL)
1026            {
1027                    for (i = 0; i < visuals_count; ++i)
1028                  {                  {
1029                          case KeyRelease:                          XVisualInfo *visual_info = &vmatches[i];
1030                                  flags = KBD_FLAG_DOWN | KBD_FLAG_UP;  
1031                                  /* fall through */                          /* Try to find a no-translation visual that'll
1032                          case KeyPress:                             allow us to use RDP bitmaps directly as ZPixmaps. */
1033                                  if( XkbTranslateKeyCode(xkb, xevent.xkey.keycode, xevent.xkey.state, &tmpmods, &keysym) == False )                          if (!g_xserver_be && (((visual_info->depth == 15) &&
1034                                                   /* R5G5B5 */
1035                                                   (visual_info->red_mask == 0x7c00) &&
1036                                                   (visual_info->green_mask == 0x3e0) &&
1037                                                   (visual_info->blue_mask == 0x1f)) ||
1038                                                  ((visual_info->depth == 16) &&
1039                                                   /* R5G6B5 */
1040                                                   (visual_info->red_mask == 0xf800) &&
1041                                                   (visual_info->green_mask == 0x7e0) &&
1042                                                   (visual_info->blue_mask == 0x1f)) ||
1043                                                  ((visual_info->depth == 24) &&
1044                                                   /* R8G8B8 */
1045                                                   (visual_info->red_mask == 0xff0000) &&
1046                                                   (visual_info->green_mask == 0xff00) &&
1047                                                   (visual_info->blue_mask == 0xff))))
1048                            {
1049                                    g_visual = visual_info->visual;
1050                                    g_depth = visual_info->depth;
1051                                    g_compatible_depth = True;
1052                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1053                                    if (g_no_translate_image)
1054                                            /* We found the best visual */
1055                                          break;                                          break;
1056                                  scancode = xkeymap_translate_key(keysym, xevent.xkey.keycode, &flags);                          }
1057                            else
1058                            {
1059                                    g_compatible_depth = False;
1060                            }
1061    
1062                                  if (scancode == 0 )                          if (visual_info->depth > 24)
1063                            {
1064                                    /* Avoid 32-bit visuals and likes like the plague.
1065                                       They're either untested or proven to work bad
1066                                       (e.g. nvidia's Composite 32-bit visual).
1067                                       Most implementation offer a 24-bit visual anyway. */
1068                                    continue;
1069                            }
1070    
1071                            /* Only care for visuals, for whose BPPs (not depths!)
1072                               we have a translateXtoY function. */
1073                            BOOL can_translate_to_bpp = False;
1074                            int j;
1075                            for (j = 0; j < pixmap_formats_count; ++j)
1076                            {
1077                                    if (pfm[j].depth == visual_info->depth)
1078                                    {
1079                                            if ((pfm[j].bits_per_pixel == 16) ||
1080                                                (pfm[j].bits_per_pixel == 24) ||
1081                                                (pfm[j].bits_per_pixel == 32))
1082                                            {
1083                                                    can_translate_to_bpp = True;
1084                                            }
1085                                          break;                                          break;
1086                                    }
1087                            }
1088    
1089                                  /* keep track of the modifiers -- needed for stickykeys... */                          /* Prefer formats which have the most colour depth.
1090                                  if( xevent.type == KeyPress )                             We're being truly aristocratic here, minding each
1091                                          xwin_mod_press( xevent.xkey.state, ev_time, scancode );                             weight on its own. */
1092                            if (can_translate_to_bpp)
1093                            {
1094                                    unsigned vis_red_weight =
1095                                            calculate_mask_weight(visual_info->red_mask);
1096                                    unsigned vis_green_weight =
1097                                            calculate_mask_weight(visual_info->green_mask);
1098                                    unsigned vis_blue_weight =
1099                                            calculate_mask_weight(visual_info->blue_mask);
1100                                    if ((vis_red_weight >= red_weight)
1101                                        && (vis_green_weight >= green_weight)
1102                                        && (vis_blue_weight >= blue_weight))
1103                                    {
1104                                            red_weight = vis_red_weight;
1105                                            green_weight = vis_green_weight;
1106                                            blue_weight = vis_blue_weight;
1107                                            g_visual = visual_info->visual;
1108                                            g_depth = visual_info->depth;
1109                                    }
1110                            }
1111                    }
1112                    XFree(vmatches);
1113            }
1114    
1115                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, flags, scancode, 0);          if (g_visual != NULL)
1116            {
1117                    g_owncolmap = False;
1118                    calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1119                    calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1120                    calculate_shifts(g_visual->blue_mask, &g_blue_shift_r, &g_blue_shift_l);
1121            }
1122            else
1123            {
1124                    template.class = PseudoColor;
1125                    template.depth = 8;
1126                    template.colormap_size = 256;
1127                    vmatches =
1128                            XGetVisualInfo(g_display,
1129                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1130                                           &template, &visuals_count);
1131                    if (vmatches == NULL)
1132                    {
1133                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1134                            XCloseDisplay(g_display);
1135                            XFree(pfm);
1136                            return False;
1137                    }
1138    
1139                                  if( xevent.type == KeyRelease )                  /* we use a colourmap, so the default visual should do */
1140                                          xwin_mod_release( xevent.xkey.state, ev_time, scancode );                  g_owncolmap = True;
1141                    g_visual = vmatches[0].visual;
1142                    g_depth = vmatches[0].depth;
1143            }
1144    
1145                                  break;          g_bpp = 0;
1146            for (i = 0; i < pixmap_formats_count; ++i)
1147            {
1148                    XPixmapFormatValues *pf = &pfm[i];
1149                    if (pf->depth == g_depth)
1150                    {
1151                            g_bpp = pf->bits_per_pixel;
1152    
1153                          case ButtonPress:                          if (g_no_translate_image)
1154                                  flags = MOUSE_FLAG_DOWN;                          {
1155                                  /* fall through */                                  switch (g_server_depth)
1156                                    {
1157                                            case 15:
1158                                            case 16:
1159                                                    if (g_bpp != 16)
1160                                                            g_no_translate_image = False;
1161                                                    break;
1162                                            case 24:
1163                                                    /* Yes, this will force image translation
1164                                                       on most modern servers which use 32 bits
1165                                                       for R8G8B8. */
1166                                                    if (g_bpp != 24)
1167                                                            g_no_translate_image = False;
1168                                                    break;
1169                                            default:
1170                                                    g_no_translate_image = False;
1171                                                    break;
1172                                    }
1173                            }
1174    
1175                          case ButtonRelease:                          /* Pixmap formats list is a depth-to-bpp mapping --
1176                                  button = xkeymap_translate_button(xevent.xbutton.button);                             there's just a single entry for every depth,
1177                                  if (button == 0)                             so we can safely break here */
1178                                          break;                          break;
1179                    }
1180            }
1181            XFree(pfm);
1182            pfm = NULL;
1183            return True;
1184    }
1185    
1186                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,  BOOL
1187                                                 flags | button,  ui_init(void)
1188                                                 xevent.xbutton.x,  {
1189                                                 xevent.xbutton.y);          int screen_num;
                                 break;  
1190    
1191                          case MotionNotify:          g_display = XOpenDisplay(NULL);
1192                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,          if (g_display == NULL)
1193                                                 MOUSE_FLAG_MOVE,          {
1194                                                 xevent.xmotion.x,                  error("Failed to open display: %s\n", XDisplayName(NULL));
1195                                                 xevent.xmotion.y);                  return False;
1196                                  break;          }
1197    
1198                          case EnterNotify:          {
1199                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,                  uint16 endianess_test = 1;
1200                                                GrabModeAsync, CurrentTime);                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1201            }
1202    
1203                                   xwin_mod_update( xevent.xcrossing.state, ev_time );          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1204                                  break;          screen_num = DefaultScreen(g_display);
1205            g_x_socket = ConnectionNumber(g_display);
1206            g_screen = ScreenOfDisplay(g_display, screen_num);
1207            g_depth = DefaultDepthOfScreen(g_screen);
1208    
1209                          case LeaveNotify:          if (!select_visual())
1210                                  XUngrabKeyboard(display, CurrentTime);                  return False;
                                 break;  
1211    
1212                          case Expose:          if (g_no_translate_image)
1213                                  XCopyArea(display, backstore, wnd, gc,          {
1214                                            xevent.xexpose.x, xevent.xexpose.y,                  DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1215                                            xevent.xexpose.width, xevent.xexpose.height,          }
1216                                            xevent.xexpose.x, xevent.xexpose.y);  
1217                                  break;          if (g_server_depth > g_bpp)
1218            {
1219                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1220                            g_server_depth, g_bpp);
1221            }
1222    
1223            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1224                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1225    
1226            if (!g_owncolmap)
1227            {
1228                    g_xcolmap =
1229                            XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1230                                            AllocNone);
1231                    if (g_depth <= 8)
1232                            warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", g_depth);
1233            }
1234    
1235            if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1236            {
1237                    warning("External BackingStore not available. Using internal.\n");
1238                    g_ownbackstore = True;
1239            }
1240    
1241            /*
1242             * Determine desktop size
1243             */
1244            if (g_fullscreen)
1245            {
1246                    g_width = WidthOfScreen(g_screen);
1247                    g_height = HeightOfScreen(g_screen);
1248            }
1249            else if (g_width < 0)
1250            {
1251                    /* Percent of screen */
1252                    if (-g_width >= 100)
1253                            g_using_full_workarea = True;
1254                    g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1255                    g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1256            }
1257            else if (g_width == 0)
1258            {
1259                    /* Fetch geometry from _NET_WORKAREA */
1260                    uint32 x, y, cx, cy;
1261                    g_using_full_workarea = True;
1262    
1263                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1264                    {
1265                            g_width = cx;
1266                            g_height = cy;
1267                    }
1268                    else
1269                    {
1270                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1271                            g_width = 800;
1272                            g_height = 600;
1273                  }                  }
1274          }          }
1275    
1276            /* make sure width is a multiple of 4 */
1277            g_width = (g_width + 3) & ~3;
1278    
1279            g_mod_map = XGetModifierMapping(g_display);
1280    
1281            xkeymap_init();
1282    
1283            if (g_enable_compose)
1284                    g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1285    
1286            xclip_init();
1287    
1288            DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
1289    
1290            return True;
1291  }  }
1292    
1293  void  void
1294  xwin_mod_update(uint32 state, uint32 ev_time )  ui_deinit(void)
1295  {  {
1296          xwin_mod_press(state, ev_time, 0);          if (g_IM != NULL)
1297          xwin_mod_release(state, ev_time, 0);                  XCloseIM(g_IM);
1298    
1299            if (g_null_cursor != NULL)
1300                    ui_destroy_cursor(g_null_cursor);
1301    
1302            XFreeModifiermap(g_mod_map);
1303    
1304            if (g_ownbackstore)
1305                    XFreePixmap(g_display, g_backstore);
1306    
1307            XFreeGC(g_display, g_gc);
1308            XCloseDisplay(g_display);
1309            g_display = NULL;
1310  }  }
1311    
1312  void  BOOL
1313  xwin_mod_release(uint32 state, uint32 ev_time, uint32 scancode)  ui_create_window(void)
1314  {  {
1315          switch (scancode) {          uint8 null_pointer_mask[1] = { 0x80 };
1316          case 0x2a:          uint8 null_pointer_data[24] = { 0x00 };
1317                  key_down_state &= ~DShift1Mask;  
1318                  break;          XSetWindowAttributes attribs;
1319          case 0x36:          XClassHint *classhints;
1320                  key_down_state &= ~DShift2Mask;          XSizeHints *sizehints;
1321                  break;          int wndwidth, wndheight;
1322          case 0x1d:          long input_mask, ic_input_mask;
1323                  key_down_state &= ~DControl1Mask;          XEvent xevent;
1324                  break;  
1325          case 0x9d:          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1326                  key_down_state &= ~DControl2Mask;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1327                  break;  
1328          case 0x38:          /* Handle -x-y portion of geometry string */
1329                  key_down_state &= ~DMod1Mask;          if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1330                  break;                  g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1331          case 0xb8:          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1332                  key_down_state &= ~DMod2Mask;                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1333                  break;  
1334            attribs.background_pixel = BlackPixelOfScreen(g_screen);
1335            attribs.border_pixel = WhitePixelOfScreen(g_screen);
1336            attribs.backing_store = g_ownbackstore ? NotUseful : Always;
1337            attribs.override_redirect = g_fullscreen;
1338            attribs.colormap = g_xcolmap;
1339    
1340            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1341                                  wndheight, 0, g_depth, InputOutput, g_visual,
1342                                  CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1343                                  CWBorderPixel, &attribs);
1344    
1345            if (g_gc == NULL)
1346                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1347    
1348            if (g_create_bitmap_gc == NULL)
1349                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1350    
1351            if ((g_ownbackstore) && (g_backstore == 0))
1352            {
1353                    g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1354    
1355                    /* clear to prevent rubbish being exposed at startup */
1356                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1357                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
1358          }          }
1359    
1360          if( !(numlock_modifier_mask & state) && (key_down_state & DNumLockMask) )          XStoreName(g_display, g_wnd, g_title);
1361    
1362            if (g_hide_decorations)
1363                    mwm_hide_decorations();
1364    
1365            classhints = XAllocClassHint();
1366            if (classhints != NULL)
1367          {          {
1368                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x45, 0);                  classhints->res_name = classhints->res_class = "rdesktop";
1369                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN | KBD_FLAG_UP, 0x45, 0);                  XSetClassHint(g_display, g_wnd, classhints);
1370                  key_down_state &= ~DNumLockMask;                  XFree(classhints);
1371          }          }
1372    
1373          if( !(LockMask & state) && (key_down_state & DLockMask))          sizehints = XAllocSizeHints();
1374            if (sizehints)
1375          {          {
1376                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);                  sizehints->flags = PMinSize | PMaxSize;
1377                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN | KBD_FLAG_UP, 0x3a, 0);                  if (g_pos)
1378                  key_down_state &= ~DLockMask;                          sizehints->flags |= PPosition;
1379                    sizehints->min_width = sizehints->max_width = g_width;
1380                    sizehints->min_height = sizehints->max_height = g_height;
1381                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1382                    XFree(sizehints);
1383            }
1384    
1385            if (g_embed_wnd)
1386            {
1387                    XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1388          }          }
1389    
1390            input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1391                    VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1392    
1393            if (g_sendmotion)
1394                    input_mask |= PointerMotionMask;
1395            if (g_ownbackstore)
1396                    input_mask |= ExposureMask;
1397            if (g_fullscreen || g_grab_keyboard)
1398                    input_mask |= EnterWindowMask;
1399            if (g_grab_keyboard)
1400                    input_mask |= LeaveWindowMask;
1401    
1402          if( !(ShiftMask & state) && (key_down_state & DShift1Mask))          if (g_IM != NULL)
1403          {          {
1404                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a, 0);                  g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1405                  key_down_state &= ~DShift1Mask;                                   XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1406    
1407                    if ((g_IC != NULL)
1408                        && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1409                            input_mask |= ic_input_mask;
1410          }          }
1411    
1412          if( !(ControlMask & state) && (key_down_state & DControl1Mask))          XSelectInput(g_display, g_wnd, input_mask);
1413          {          XMapWindow(g_display, g_wnd);
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d, 0);  
                 key_down_state &= ~DControl1Mask;  
1414    
1415            /* wait for VisibilityNotify */
1416            do
1417            {
1418                    XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1419          }          }
1420            while (xevent.type != VisibilityNotify);
1421            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1422    
1423            g_focused = False;
1424            g_mouse_in_wnd = False;
1425    
1426            /* handle the WM_DELETE_WINDOW protocol */
1427            g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1428            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1429            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1430    
1431            /* create invisible 1x1 cursor to be used as null cursor */
1432            if (g_null_cursor == NULL)
1433                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1434    
1435            return True;
1436    }
1437    
1438          if( !(Mod1Mask & state) && (key_down_state & DMod1Mask))  void
1439    ui_resize_window()
1440    {
1441            XSizeHints *sizehints;
1442            Pixmap bs;
1443    
1444            sizehints = XAllocSizeHints();
1445            if (sizehints)
1446          {          {
1447                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38, 0);                  sizehints->flags = PMinSize | PMaxSize;
1448                  key_down_state &= ~DMod1Mask;                  sizehints->min_width = sizehints->max_width = g_width;
1449                    sizehints->min_height = sizehints->max_height = g_height;
1450                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1451                    XFree(sizehints);
1452            }
1453    
1454            if (!(g_fullscreen || g_embed_wnd))
1455            {
1456                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1457          }          }
1458    
1459          if( !(Mod2Mask & state) && (key_down_state & DMod2Mask))          /* create new backstore pixmap */
1460            if (g_backstore != 0)
1461          {          {
1462                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8, 0);                  bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1463                  key_down_state &= ~DMod2Mask;                  XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1464                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1465                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1466                    XFreePixmap(g_display, g_backstore);
1467                    g_backstore = bs;
1468          }          }
1469  }  }
1470    
1471    void
1472    ui_destroy_window(void)
1473    {
1474            if (g_IC != NULL)
1475                    XDestroyIC(g_IC);
1476    
1477            XDestroyWindow(g_display, g_wnd);
1478    }
1479    
1480  void  void
1481  xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode)  xwin_toggle_fullscreen(void)
1482  {  {
1483            Pixmap contents = 0;
1484    
1485          switch (scancode) {          if (!g_ownbackstore)
1486          case 0x2a:          {
1487                  key_down_state |= DShift1Mask;                  /* need to save contents of window */
1488                  break;                  contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1489          case 0x36:                  XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
                 key_down_state |= DShift2Mask;  
                 break;  
         case 0x1d:  
                 key_down_state |= DControl1Mask;  
                 break;  
         case 0x9d:  
                 key_down_state |= DControl2Mask;  
                 break;  
         case 0x3a:  
                 key_down_state ^= DLockMask;  
                 break;  
         case 0x45:  
                 key_down_state ^= DNumLockMask;  
                 break;  
         case 0x38:  
                 key_down_state |= DMod1Mask;  
                 break;  
         case 0xb8:  
                 key_down_state |= DMod2Mask;  
                 break;  
1490          }          }
1491    
1492          if( (numlock_modifier_mask && state) && !(key_down_state & DNumLockMask) )          ui_destroy_window();
1493            g_fullscreen = !g_fullscreen;
1494            ui_create_window();
1495    
1496            XDefineCursor(g_display, g_wnd, g_current_cursor);
1497    
1498            if (!g_ownbackstore)
1499          {          {
1500                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x45, 0);                  XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1501                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN | KBD_FLAG_UP, 0x45, 0);                  XFreePixmap(g_display, contents);
                 key_down_state |= DNumLockMask;  
1502          }          }
1503    }
1504    
1505          if( (LockMask & state) && !(key_down_state & DLockMask))  static void
1506          {  handle_button_event(XEvent xevent, BOOL down)
1507                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);  {
1508                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN | KBD_FLAG_UP, 0x3a, 0);          uint16 button, flags = 0;
1509                  key_down_state |= DLockMask;          g_last_gesturetime = xevent.xbutton.time;
1510            button = xkeymap_translate_button(xevent.xbutton.button);
1511            if (button == 0)
1512                    return;
1513    
1514          }          if (down)
1515                    flags = MOUSE_FLAG_DOWN;
1516    
1517            /* Stop moving window when button is released, regardless of cursor position */
1518            if (g_moving_wnd && (xevent.type == ButtonRelease))
1519                    g_moving_wnd = False;
1520    
1521          if( (ShiftMask & state) && !((key_down_state & DShift1Mask) || (key_down_state & DShift2Mask)))          /* If win_button_size is nonzero, enable single app mode */
1522            if (xevent.xbutton.y < g_win_button_size)
1523          {          {
1524                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x2a, 0);                  /*  Check from right to left: */
1525                  key_down_state |= DShift1Mask;                  if (xevent.xbutton.x >= g_width - g_win_button_size)
1526                    {
1527                            /* The close button, continue */
1528                            ;
1529                    }
1530                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1531                    {
1532                            /* The maximize/restore button. Do not send to
1533                               server.  It might be a good idea to change the
1534                               cursor or give some other visible indication
1535                               that rdesktop inhibited this click */
1536                            if (xevent.type == ButtonPress)
1537                                    return;
1538                    }
1539                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1540                    {
1541                            /* The minimize button. Iconify window. */
1542                            if (xevent.type == ButtonRelease)
1543                            {
1544                                    /* Release the mouse button outside the minimize button, to prevent the
1545                                       actual minimazation to happen */
1546                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1547                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1548                                    return;
1549                            }
1550                    }
1551                    else if (xevent.xbutton.x <= g_win_button_size)
1552                    {
1553                            /* The system menu. Ignore. */
1554                            if (xevent.type == ButtonPress)
1555                                    return;
1556                    }
1557                    else
1558                    {
1559                            /* The title bar. */
1560                            if (xevent.type == ButtonPress)
1561                            {
1562                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1563                                    {
1564                                            g_moving_wnd = True;
1565                                            g_move_x_offset = xevent.xbutton.x;
1566                                            g_move_y_offset = xevent.xbutton.y;
1567                                    }
1568                                    return;
1569                            }
1570                    }
1571          }          }
1572    
1573          if( (ControlMask & state) && !((key_down_state & DControl1Mask) || (key_down_state & DControl2Mask)))          rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1574          {                         flags | button, xevent.xbutton.x, xevent.xbutton.y);
1575                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x1d, 0);  }
                 key_down_state |= DControl1Mask;  
1576    
1577          }  /* Process events in Xlib queue
1578       Returns 0 after user quit, 1 otherwise */
1579    static int
1580    xwin_process_events(void)
1581    {
1582            XEvent xevent;
1583            KeySym keysym;
1584            uint32 ev_time;
1585            char str[256];
1586            Status status;
1587            int events = 0;
1588    
1589          if( (Mod1Mask & state) && !(key_down_state & DMod1Mask))          while ((XPending(g_display) > 0) && events++ < 20)
1590          {          {
1591                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x38, 0);                  XNextEvent(g_display, &xevent);
                 key_down_state |= DMod1Mask;  
1592    
1593          }                  if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1594                    {
1595                            DEBUG_KBD(("Filtering event\n"));
1596                            continue;
1597                    }
1598    
1599          if( (Mod2Mask & state) && !(key_down_state & DMod2Mask))                  switch (xevent.type)
1600          {                  {
1601                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0xb8, 0);                          case VisibilityNotify:
1602                  key_down_state |= DMod2Mask;                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1603                                    break;
1604                            case ClientMessage:
1605                                    /* the window manager told us to quit */
1606                                    if ((xevent.xclient.message_type == g_protocol_atom)
1607                                        && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1608                                            /* Quit */
1609                                            return 0;
1610                                    break;
1611    
1612                            case KeyPress:
1613                                    g_last_gesturetime = xevent.xkey.time;
1614                                    if (g_IC != NULL)
1615                                            /* Multi_key compatible version */
1616                                    {
1617                                            XmbLookupString(g_IC,
1618                                                            &xevent.xkey, str, sizeof(str), &keysym,
1619                                                            &status);
1620                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1621                                            {
1622                                                    error("XmbLookupString failed with status 0x%x\n",
1623                                                          status);
1624                                                    break;
1625                                            }
1626                                    }
1627                                    else
1628                                    {
1629                                            /* Plain old XLookupString */
1630                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1631                                            XLookupString((XKeyEvent *) & xevent,
1632                                                          str, sizeof(str), &keysym, NULL);
1633                                    }
1634    
1635                                    DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1636                                               get_ksname(keysym)));
1637    
1638                                    ev_time = time(NULL);
1639                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1640                                            break;
1641    
1642                                    xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1643                                                      ev_time, True, 0);
1644                                    break;
1645    
1646                            case KeyRelease:
1647                                    g_last_gesturetime = xevent.xkey.time;
1648                                    XLookupString((XKeyEvent *) & xevent, str,
1649                                                  sizeof(str), &keysym, NULL);
1650    
1651                                    DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1652                                               get_ksname(keysym)));
1653    
1654                                    ev_time = time(NULL);
1655                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1656                                            break;
1657    
1658                                    xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1659                                                      ev_time, False, 0);
1660                                    break;
1661    
1662                            case ButtonPress:
1663                                    handle_button_event(xevent, True);
1664                                    break;
1665    
1666                            case ButtonRelease:
1667                                    handle_button_event(xevent, False);
1668                                    break;
1669    
1670                            case MotionNotify:
1671                                    if (g_moving_wnd)
1672                                    {
1673                                            XMoveWindow(g_display, g_wnd,
1674                                                        xevent.xmotion.x_root - g_move_x_offset,
1675                                                        xevent.xmotion.y_root - g_move_y_offset);
1676                                            break;
1677                                    }
1678    
1679                                    if (g_fullscreen && !g_focused)
1680                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1681                                                           CurrentTime);
1682                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1683                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1684                                    break;
1685    
1686                            case FocusIn:
1687                                    if (xevent.xfocus.mode == NotifyGrab)
1688                                            break;
1689                                    g_focused = True;
1690                                    reset_modifier_keys();
1691                                    if (g_grab_keyboard && g_mouse_in_wnd)
1692                                            XGrabKeyboard(g_display, g_wnd, True,
1693                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1694                                    break;
1695    
1696                            case FocusOut:
1697                                    if (xevent.xfocus.mode == NotifyUngrab)
1698                                            break;
1699                                    g_focused = False;
1700                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1701                                            XUngrabKeyboard(g_display, CurrentTime);
1702                                    break;
1703    
1704                            case EnterNotify:
1705                                    /* we only register for this event when in fullscreen mode */
1706                                    /* or grab_keyboard */
1707                                    g_mouse_in_wnd = True;
1708                                    if (g_fullscreen)
1709                                    {
1710                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1711                                                           CurrentTime);
1712                                            break;
1713                                    }
1714                                    if (g_focused)
1715                                            XGrabKeyboard(g_display, g_wnd, True,
1716                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1717                                    break;
1718    
1719                            case LeaveNotify:
1720                                    /* we only register for this event when grab_keyboard */
1721                                    g_mouse_in_wnd = False;
1722                                    XUngrabKeyboard(g_display, CurrentTime);
1723                                    break;
1724    
1725                            case Expose:
1726                                    XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1727                                              xevent.xexpose.x, xevent.xexpose.y,
1728                                              xevent.xexpose.width,
1729                                              xevent.xexpose.height,
1730                                              xevent.xexpose.x, xevent.xexpose.y);
1731                                    break;
1732    
1733                            case MappingNotify:
1734                                    /* Refresh keyboard mapping if it has changed. This is important for
1735                                       Xvnc, since it allocates keycodes dynamically */
1736                                    if (xevent.xmapping.request == MappingKeyboard
1737                                        || xevent.xmapping.request == MappingModifier)
1738                                            XRefreshKeyboardMapping(&xevent.xmapping);
1739    
1740                                    if (xevent.xmapping.request == MappingModifier)
1741                                    {
1742                                            XFreeModifiermap(g_mod_map);
1743                                            g_mod_map = XGetModifierMapping(g_display);
1744                                    }
1745                                    break;
1746    
1747                                    /* clipboard stuff */
1748                            case SelectionNotify:
1749                                    xclip_handle_SelectionNotify(&xevent.xselection);
1750                                    break;
1751                            case SelectionRequest:
1752                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1753                                    break;
1754                            case SelectionClear:
1755                                    xclip_handle_SelectionClear();
1756                                    break;
1757                            case PropertyNotify:
1758                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1759                                    break;
1760                            case MapNotify:
1761                                    rdp_send_client_window_status(1);
1762                                    break;
1763                            case UnmapNotify:
1764                                    rdp_send_client_window_status(0);
1765                                    break;
1766                    }
1767          }          }
1768            /* Keep going */
1769            return 1;
1770  }  }
1771    
1772  void  /* Returns 0 after user quit, 1 otherwise */
1773    int
1774  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1775  {  {
1776          int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;          int n;
1777          fd_set rfds;          fd_set rfds, wfds;
1778            struct timeval tv;
1779          FD_ZERO(&rfds);          BOOL s_timeout = False;
1780    
1781          while (True)          while (True)
1782          {          {
1783                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1784                    /* Process any events already waiting */
1785                    if (!xwin_process_events())
1786                            /* User quit */
1787                            return 0;
1788    
1789                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
1790                    FD_ZERO(&wfds);
1791                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
1792                  if (display != NULL)                  FD_SET(g_x_socket, &rfds);
1793    
1794    #ifdef WITH_RDPSND
1795                    /* FIXME: there should be an API for registering fds */
1796                    if (g_dsp_busy)
1797                  {                  {
1798                          FD_SET(x_socket, &rfds);                          FD_SET(g_dsp_fd, &wfds);
1799                          XFlush(display);                          n = (g_dsp_fd > n) ? g_dsp_fd : n;
1800                  }                  }
1801    #endif
1802                    /* default timeout */
1803                    tv.tv_sec = 60;
1804                    tv.tv_usec = 0;
1805    
1806                    /* add redirection handles */
1807                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1808    
1809                  switch (select(n, &rfds, NULL, NULL, NULL))                  n++;
1810    
1811                    switch (select(n, &rfds, &wfds, NULL, &tv))
1812                  {                  {
1813                          case -1:                          case -1:
1814                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
1815    
1816                          case 0:                          case 0:
1817                                    /* Abort serial read calls */
1818                                    if (s_timeout)
1819                                            rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1820                                  continue;                                  continue;
1821                  }                  }
1822    
1823                  if (FD_ISSET(x_socket, &rfds))                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
                         xwin_process_events();  
1824    
1825                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1826                          return;                          return 1;
1827    
1828    #ifdef WITH_RDPSND
1829                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1830                            wave_out_play();
1831    #endif
1832          }          }
1833  }  }
1834    
1835  void  void
1836  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
1837  {  {
1838          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1839  }  }
1840    
1841  HBITMAP  HBITMAP
1842  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1843  {  {
1844          XImage *image;          XImage *image;
1845          Pixmap bitmap;          Pixmap bitmap;
1846          uint8 *tdata;          uint8 *tdata;
1847            int bitmap_pad;
1848    
1849            if (g_server_depth == 8)
1850            {
1851                    bitmap_pad = 8;
1852            }
1853            else
1854            {
1855                    bitmap_pad = g_bpp;
1856    
1857                    if (g_bpp == 24)
1858                            bitmap_pad = 32;
1859            }
1860    
1861          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1862          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1863          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1864                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
1865    
1866          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
1867    
1868          XFree(image);          XFree(image);
1869          if (!owncolmap)          if (tdata != data)
1870                  xfree(tdata);                  xfree(tdata);
1871          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1872  }  }
1873    
1874  void  void
1875  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)  
1876  {  {
1877          XImage *image;          XImage *image;
1878          uint8 *tdata;          uint8 *tdata;
1879            int bitmap_pad;
1880    
1881          tdata = (owncolmap ? data : translate_image(width, height, data));          if (g_server_depth == 8)
1882          image = XCreateImage(display, visual, depth, ZPixmap,          {
1883                               0, tdata, width, height, 8, 0);                  bitmap_pad = 8;
1884            }
1885            else
1886            {
1887                    bitmap_pad = g_bpp;
1888    
1889          if (ownbackstore)                  if (g_bpp == 24)
1890                            bitmap_pad = 32;
1891            }
1892    
1893            tdata = (g_owncolmap ? data : translate_image(width, height, data));
1894            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1895                                 (char *) tdata, width, height, bitmap_pad, 0);
1896    
1897            if (g_ownbackstore)
1898          {          {
1899                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1900                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1901          }          }
1902          else          else
1903          {          {
1904                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1905          }          }
1906    
1907          XFree(image);          XFree(image);
1908          if (!owncolmap)          if (tdata != data)
1909                  xfree(tdata);                  xfree(tdata);
1910  }  }
1911    
1912  void  void
1913  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1914  {  {
1915          XFreePixmap(display, (Pixmap)bmp);          XFreePixmap(g_display, (Pixmap) bmp);
1916  }  }
1917    
1918  HGLYPH  HGLYPH
1919  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1920  {  {
1921          XImage *image;          XImage *image;
1922          Pixmap bitmap;          Pixmap bitmap;
1923          int scanline;          int scanline;
         GC gc;  
1924    
1925          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1926    
1927          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1928          gc = XCreateGC(display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
1929                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1930    
1931          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1932                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1933          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1934          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1935          XInitImage(image);          XInitImage(image);
1936    
1937          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
1938    
1939          XFree(image);          XFree(image);
1940          XFreeGC(display, gc);          return (HGLYPH) bitmap;
         return (HGLYPH)bitmap;  
1941  }  }
1942    
1943  void  void
1944  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1945  {  {
1946          XFreePixmap(display, (Pixmap)glyph);          XFreePixmap(g_display, (Pixmap) glyph);
1947  }  }
1948    
1949  HCURSOR  HCURSOR
1950  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1951                   int height, uint8 *andmask, uint8 *xormask)                   uint8 * andmask, uint8 * xormask)
1952  {  {
1953          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
1954          XColor bg, fg;          XColor bg, fg;
# Line 807  ui_create_cursor(unsigned int x, unsigne Line 1962  ui_create_cursor(unsigned int x, unsigne
1962          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1963          offset = scanline * height;          offset = scanline * height;
1964    
1965          cursor = xmalloc(offset);          cursor = (uint8 *) xmalloc(offset);
1966          memset(cursor, 0, offset);          memset(cursor, 0, offset);
1967    
1968          mask = xmalloc(offset);          mask = (uint8 *) xmalloc(offset);
1969          memset(mask, 0, offset);          memset(mask, 0, offset);
1970    
1971          /* approximate AND and XOR masks with a monochrome X pointer */          /* approximate AND and XOR masks with a monochrome X pointer */
# Line 850  ui_create_cursor(unsigned int x, unsigne Line 2005  ui_create_cursor(unsigned int x, unsigne
2005    
2006          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
2007          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
2008            
2009          xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,          xcursor =
2010                                  (Pixmap)maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
2011                                        (Pixmap) maskglyph, &fg, &bg, x, y);
2012    
2013          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
2014          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
2015          xfree(mask);          xfree(mask);
2016          xfree(cursor);          xfree(cursor);
2017          return (HCURSOR)xcursor;          return (HCURSOR) xcursor;
2018  }  }
2019    
2020  void  void
2021  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
2022  {  {
2023          XDefineCursor(display, wnd, (Cursor)cursor);          g_current_cursor = (Cursor) cursor;
2024            XDefineCursor(g_display, g_wnd, g_current_cursor);
2025  }  }
2026    
2027  void  void
2028  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
2029  {  {
2030          XFreeCursor(display, (Cursor)cursor);          XFreeCursor(g_display, (Cursor) cursor);
2031    }
2032    
2033    void
2034    ui_set_null_cursor(void)
2035    {
2036            ui_set_cursor(g_null_cursor);
2037  }  }
2038    
2039  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 879  ui_destroy_cursor(HCURSOR cursor) Line 2042  ui_destroy_cursor(HCURSOR cursor)
2042                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
2043                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
2044    
2045    
2046  HCOLOURMAP  HCOLOURMAP
2047  ui_create_colourmap(COLOURMAP *colours)  ui_create_colourmap(COLOURMAP * colours)
2048  {  {
2049          COLOURENTRY *entry;          COLOURENTRY *entry;
2050          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
2051            if (!g_owncolmap)
         if (owncolmap)  
2052          {          {
2053                  XColor *xcolours, *xentry;                  uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
2054                  Colormap map;                  XColor xentry;
2055                    XColor xc_cache[256];
2056                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  uint32 colour;
2057                    int colLookup = 256;
2058                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
2059                  {                  {
2060                          entry = &colours->colours[i];                          entry = &colours->colours[i];
2061                          xentry = &xcolours[i];                          MAKE_XCOLOR(&xentry, entry);
                         xentry->pixel = i;  
                         MAKE_XCOLOR(xentry, entry);  
                 }  
2062    
2063                  map = XCreateColormap(display, wnd, visual, AllocAll);                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
2064                  XStoreColors(display, map, xcolours, ncolours);                          {
2065                                    /* Allocation failed, find closest match. */
2066                                    int j = 256;
2067                                    int nMinDist = 3 * 256 * 256;
2068                                    long nDist = nMinDist;
2069    
2070                  xfree(xcolours);                                  /* only get the colors once */
2071                  return (HCOLOURMAP)map;                                  while (colLookup--)
2072                                    {
2073                                            xc_cache[colLookup].pixel = colLookup;
2074                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
2075                                                    xc_cache[colLookup].blue = 0;
2076                                            xc_cache[colLookup].flags = 0;
2077                                            XQueryColor(g_display,
2078                                                        DefaultColormap(g_display,
2079                                                                        DefaultScreen(g_display)),
2080                                                        &xc_cache[colLookup]);
2081                                    }
2082                                    colLookup = 0;
2083    
2084                                    /* approximate the pixel */
2085                                    while (j--)
2086                                    {
2087                                            if (xc_cache[j].flags)
2088                                            {
2089                                                    nDist = ((long) (xc_cache[j].red >> 8) -
2090                                                             (long) (xentry.red >> 8)) *
2091                                                            ((long) (xc_cache[j].red >> 8) -
2092                                                             (long) (xentry.red >> 8)) +
2093                                                            ((long) (xc_cache[j].green >> 8) -
2094                                                             (long) (xentry.green >> 8)) *
2095                                                            ((long) (xc_cache[j].green >> 8) -
2096                                                             (long) (xentry.green >> 8)) +
2097                                                            ((long) (xc_cache[j].blue >> 8) -
2098                                                             (long) (xentry.blue >> 8)) *
2099                                                            ((long) (xc_cache[j].blue >> 8) -
2100                                                             (long) (xentry.blue >> 8));
2101                                            }
2102                                            if (nDist < nMinDist)
2103                                            {
2104                                                    nMinDist = nDist;
2105                                                    xentry.pixel = j;
2106                                            }
2107                                    }
2108                            }
2109                            colour = xentry.pixel;
2110    
2111                            /* update our cache */
2112                            if (xentry.pixel < 256)
2113                            {
2114                                    xc_cache[xentry.pixel].red = xentry.red;
2115                                    xc_cache[xentry.pixel].green = xentry.green;
2116                                    xc_cache[xentry.pixel].blue = xentry.blue;
2117    
2118                            }
2119    
2120                            map[i] = colour;
2121                    }
2122                    return map;
2123          }          }
2124          else          else
2125          {          {
2126                  uint32 *map = xmalloc(sizeof(*colmap) * ncolours);                  XColor *xcolours, *xentry;
2127                  XColor xentry;                  Colormap map;
                 uint32 colour;  
2128    
2129                    xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
2130                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
2131                  {                  {
2132                          entry = &colours->colours[i];                          entry = &colours->colours[i];
2133                          MAKE_XCOLOR(&xentry, entry);                          xentry = &xcolours[i];
2134                            xentry->pixel = i;
2135                          if (XAllocColor(display, xcolmap, &xentry) != 0)                          MAKE_XCOLOR(xentry, entry);
                                 colour = xentry.pixel;  
                         else  
                                 colour = white;  
   
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
2136                  }                  }
2137    
2138                  return map;                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
2139                    XStoreColors(g_display, map, xcolours, ncolours);
2140    
2141                    xfree(xcolours);
2142                    return (HCOLOURMAP) map;
2143          }          }
2144  }  }
2145    
2146  void  void
2147  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
2148  {  {
2149          if (owncolmap)          if (!g_owncolmap)
                 XFreeColormap(display, (Colormap)map);  
         else  
2150                  xfree(map);                  xfree(map);
2151            else
2152                    XFreeColormap(g_display, (Colormap) map);
2153  }  }
2154    
2155  void  void
2156  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
2157  {  {
2158          if (owncolmap)          if (!g_owncolmap)
2159                  XSetWindowColormap(display, wnd, (Colormap)map);          {
2160                    if (g_colmap)
2161                            xfree(g_colmap);
2162    
2163                    g_colmap = (uint32 *) map;
2164            }
2165          else          else
2166                  colmap = map;                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2167  }  }
2168    
2169  void  void
# Line 956  ui_set_clip(int x, int y, int cx, int cy Line 2175  ui_set_clip(int x, int y, int cx, int cy
2175          rect.y = y;          rect.y = y;
2176          rect.width = cx;          rect.width = cx;
2177          rect.height = cy;          rect.height = cy;
2178          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
2179  }  }
2180    
2181  void  void
2182  ui_reset_clip()  ui_reset_clip(void)
2183  {  {
2184          XRectangle rect;          XRectangle rect;
2185    
2186          rect.x = 0;          rect.x = 0;
2187          rect.y = 0;          rect.y = 0;
2188          rect.width = width;          rect.width = g_width;
2189          rect.height = height;          rect.height = g_height;
2190          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
2191  }  }
2192    
2193  void  void
2194  ui_bell()  ui_bell(void)
2195  {  {
2196          XBell(display, 0);          XBell(g_display, 0);
2197  }  }
2198    
2199  void  void
# Line 986  ui_destblt(uint8 opcode, Line 2205  ui_destblt(uint8 opcode,
2205          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2206  }  }
2207    
2208    static uint8 hatch_patterns[] = {
2209            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
2210            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
2211            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
2212            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
2213            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
2214            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
2215    };
2216    
2217  void  void
2218  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
2219            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2220            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2221  {  {
2222          Pixmap fill;          Pixmap fill;
2223            uint8 i, ipattern[8];
2224    
2225          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2226    
# Line 999  ui_patblt(uint8 opcode, Line 2228  ui_patblt(uint8 opcode,
2228          {          {
2229                  case 0: /* Solid */                  case 0: /* Solid */
2230                          SET_FOREGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
2231                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2232                          break;                          break;
2233    
2234                  case 3: /* Pattern */                  case 2: /* Hatch */
2235                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);                          fill = (Pixmap) ui_create_glyph(8, 8,
2236                                                            hatch_patterns + brush->pattern[0] * 8);
2237                            SET_FOREGROUND(fgcolour);
2238                            SET_BACKGROUND(bgcolour);
2239                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2240                            XSetStipple(g_display, g_gc, fill);
2241                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2242                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2243                            XSetFillStyle(g_display, g_gc, FillSolid);
2244                            XSetTSOrigin(g_display, g_gc, 0, 0);
2245                            ui_destroy_glyph((HGLYPH) fill);
2246                            break;
2247    
2248                    case 3: /* Pattern */
2249                            for (i = 0; i != 8; i++)
2250                                    ipattern[7 - i] = brush->pattern[i];
2251                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2252                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
2253                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
2254                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2255                          XSetStipple(display, gc, fill);                          XSetStipple(g_display, g_gc, fill);
2256                          XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2257                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2258                          FILL_RECTANGLE(x, y, cx, cy);                          XSetFillStyle(g_display, g_gc, FillSolid);
2259                            XSetTSOrigin(g_display, g_gc, 0, 0);
2260                          XSetFillStyle(display, gc, FillSolid);                          ui_destroy_glyph((HGLYPH) fill);
                         ui_destroy_glyph((HGLYPH)fill);  
2261                          break;                          break;
2262    
2263                  default:                  default:
# Line 1022  ui_patblt(uint8 opcode, Line 2265  ui_patblt(uint8 opcode,
2265          }          }
2266    
2267          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2268    
2269            if (g_ownbackstore)
2270                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2271  }  }
2272    
2273  void  void
# Line 1030  ui_screenblt(uint8 opcode, Line 2276  ui_screenblt(uint8 opcode,
2276               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
2277  {  {
2278          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2279          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          if (g_ownbackstore)
2280          if (ownbackstore)          {
2281                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,                  if (g_Unobscured)
2282                            cx, cy, x, y);                  {
2283                            XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2284                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2285                                      y);
2286                    }
2287                    else
2288                    {
2289                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2290                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2291                                      y);
2292                    }
2293            }
2294            else
2295            {
2296                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2297            }
2298          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2299  }  }
2300    
# Line 1043  ui_memblt(uint8 opcode, Line 2304  ui_memblt(uint8 opcode,
2304            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
2305  {  {
2306          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2307          XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2308          if (ownbackstore)          if (g_ownbackstore)
2309                  XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,                  XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
2310          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2311  }  }
2312    
# Line 1054  void Line 2314  void
2314  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
2315            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2316            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
2317            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2318  {  {
2319          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
2320             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 1063  ui_triblt(uint8 opcode, Line 2323  ui_triblt(uint8 opcode,
2323          {          {
2324                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
2325                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
2326                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2327                          break;                          break;
2328    
2329                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
2330                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2331                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
2332                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2333                          break;                          break;
2334    
2335                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
2336                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2337                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
2338                          break;                          break;
2339    
2340                  default:                  default:
# Line 1090  ui_triblt(uint8 opcode, Line 2346  ui_triblt(uint8 opcode,
2346  void  void
2347  ui_line(uint8 opcode,  ui_line(uint8 opcode,
2348          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
2349          /* pen */ PEN *pen)          /* pen */ PEN * pen)
2350  {  {
2351          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2352          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2353          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2354          if (ownbackstore)          if (g_ownbackstore)
2355                  XDrawLine(display, backstore, gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2356          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2357  }  }
2358    
# Line 1110  ui_rect( Line 2366  ui_rect(
2366  }  }
2367    
2368  void  void
2369    ui_polygon(uint8 opcode,
2370               /* mode */ uint8 fillmode,
2371               /* dest */ POINT * point, int npoints,
2372               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2373    {
2374            uint8 style, i, ipattern[8];
2375            Pixmap fill;
2376    
2377            SET_FUNCTION(opcode);
2378    
2379            switch (fillmode)
2380            {
2381                    case ALTERNATE:
2382                            XSetFillRule(g_display, g_gc, EvenOddRule);
2383                            break;
2384                    case WINDING:
2385                            XSetFillRule(g_display, g_gc, WindingRule);
2386                            break;
2387                    default:
2388                            unimpl("fill mode %d\n", fillmode);
2389            }
2390    
2391            if (brush)
2392                    style = brush->style;
2393            else
2394                    style = 0;
2395    
2396            switch (style)
2397            {
2398                    case 0: /* Solid */
2399                            SET_FOREGROUND(fgcolour);
2400                            FILL_POLYGON((XPoint *) point, npoints);
2401                            break;
2402    
2403                    case 2: /* Hatch */
2404                            fill = (Pixmap) ui_create_glyph(8, 8,
2405                                                            hatch_patterns + brush->pattern[0] * 8);
2406                            SET_FOREGROUND(fgcolour);
2407                            SET_BACKGROUND(bgcolour);
2408                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2409                            XSetStipple(g_display, g_gc, fill);
2410                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2411                            FILL_POLYGON((XPoint *) point, npoints);
2412                            XSetFillStyle(g_display, g_gc, FillSolid);
2413                            XSetTSOrigin(g_display, g_gc, 0, 0);
2414                            ui_destroy_glyph((HGLYPH) fill);
2415                            break;
2416    
2417                    case 3: /* Pattern */
2418                            for (i = 0; i != 8; i++)
2419                                    ipattern[7 - i] = brush->pattern[i];
2420                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2421                            SET_FOREGROUND(bgcolour);
2422                            SET_BACKGROUND(fgcolour);
2423                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2424                            XSetStipple(g_display, g_gc, fill);
2425                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2426                            FILL_POLYGON((XPoint *) point, npoints);
2427                            XSetFillStyle(g_display, g_gc, FillSolid);
2428                            XSetTSOrigin(g_display, g_gc, 0, 0);
2429                            ui_destroy_glyph((HGLYPH) fill);
2430                            break;
2431    
2432                    default:
2433                            unimpl("brush %d\n", brush->style);
2434            }
2435    
2436            RESET_FUNCTION(opcode);
2437    }
2438    
2439    void
2440    ui_polyline(uint8 opcode,
2441                /* dest */ POINT * points, int npoints,
2442                /* pen */ PEN * pen)
2443    {
2444            /* TODO: set join style */
2445            SET_FUNCTION(opcode);
2446            SET_FOREGROUND(pen->colour);
2447            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2448            if (g_ownbackstore)
2449                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2450                               CoordModePrevious);
2451            RESET_FUNCTION(opcode);
2452    }
2453    
2454    void
2455    ui_ellipse(uint8 opcode,
2456               /* mode */ uint8 fillmode,
2457               /* dest */ int x, int y, int cx, int cy,
2458               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2459    {
2460            uint8 style, i, ipattern[8];
2461            Pixmap fill;
2462    
2463            SET_FUNCTION(opcode);
2464    
2465            if (brush)
2466                    style = brush->style;
2467            else
2468                    style = 0;
2469    
2470            switch (style)
2471            {
2472                    case 0: /* Solid */
2473                            SET_FOREGROUND(fgcolour);
2474                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2475                            break;
2476    
2477                    case 2: /* Hatch */
2478                            fill = (Pixmap) ui_create_glyph(8, 8,
2479                                                            hatch_patterns + brush->pattern[0] * 8);
2480                            SET_FOREGROUND(fgcolour);
2481                            SET_BACKGROUND(bgcolour);
2482                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2483                            XSetStipple(g_display, g_gc, fill);
2484                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2485                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2486                            XSetFillStyle(g_display, g_gc, FillSolid);
2487                            XSetTSOrigin(g_display, g_gc, 0, 0);
2488                            ui_destroy_glyph((HGLYPH) fill);
2489                            break;
2490    
2491                    case 3: /* Pattern */
2492                            for (i = 0; i != 8; i++)
2493                                    ipattern[7 - i] = brush->pattern[i];
2494                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2495                            SET_FOREGROUND(bgcolour);
2496                            SET_BACKGROUND(fgcolour);
2497                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2498                            XSetStipple(g_display, g_gc, fill);
2499                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2500                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2501                            XSetFillStyle(g_display, g_gc, FillSolid);
2502                            XSetTSOrigin(g_display, g_gc, 0, 0);
2503                            ui_destroy_glyph((HGLYPH) fill);
2504                            break;
2505    
2506                    default:
2507                            unimpl("brush %d\n", brush->style);
2508            }
2509    
2510            RESET_FUNCTION(opcode);
2511    }
2512    
2513    /* warning, this function only draws on wnd or backstore, not both */
2514    void
2515  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
2516                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
2517                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
2518                int fgcolour)                int bgcolour, int fgcolour)
2519  {  {
2520          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
2521          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
2522    
2523          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(g_display, g_gc,
2524                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2525          XSetStipple(display, gc, (Pixmap)glyph);          XSetStipple(g_display, g_gc, (Pixmap) glyph);
2526          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(g_display, g_gc, x, y);
2527    
2528          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2529    
2530          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(g_display, g_gc, FillSolid);
2531  }  }
2532    
2533  #define DO_GLYPH(ttext,idx) \  #define DO_GLYPH(ttext,idx) \
2534  {\  {\
2535    glyph = cache_get_font (font, ttext[idx]);\    glyph = cache_get_font (font, ttext[idx]);\
2536    if (!(flags & TEXT2_IMPLICIT_X))\    if (!(flags & TEXT2_IMPLICIT_X))\
2537      {\
2538        xyoffset = ttext[++idx];\
2539        if ((xyoffset & 0x80))\
2540      {\      {\
2541        xyoffset = ttext[++idx];\        if (flags & TEXT2_VERTICAL)\
2542        if ((xyoffset & 0x80))\          y += ttext[idx+1] | (ttext[idx+2] << 8);\
         {\  
           if (flags & TEXT2_VERTICAL) \  
             y += ttext[++idx] | (ttext[++idx] << 8);\  
           else\  
             x += ttext[++idx] | (ttext[++idx] << 8);\  
         }\  
2543        else\        else\
2544          {\          x += ttext[idx+1] | (ttext[idx+2] << 8);\
2545            if (flags & TEXT2_VERTICAL) \        idx += 2;\
             y += xyoffset;\  
           else\  
             x += xyoffset;\  
         }\  
2546      }\      }\
2547    if (glyph != NULL)\      else\
2548      {\      {\
2549        ui_draw_glyph (mixmode, x + (short) glyph->offset,\        if (flags & TEXT2_VERTICAL)\
2550                       y + (short) glyph->baseline,\          y += xyoffset;\
2551                       glyph->width, glyph->height,\        else\
2552                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\          x += xyoffset;\
       if (flags & TEXT2_IMPLICIT_X)\  
         x += glyph->width;\  
2553      }\      }\
2554      }\
2555      if (glyph != NULL)\
2556      {\
2557        x1 = x + glyph->offset;\
2558        y1 = y + glyph->baseline;\
2559        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2560        XSetTSOrigin(g_display, g_gc, x1, y1);\
2561        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2562        if (flags & TEXT2_IMPLICIT_X)\
2563          x += glyph->width;\
2564      }\
2565  }  }
2566    
2567  void  void
2568  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y,
2569               int clipx, int clipy, int clipcx, int clipcy, int boxx,               int clipx, int clipy, int clipcx, int clipcy,
2570               int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2571               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2572  {  {
2573            /* TODO: use brush appropriately */
2574    
2575          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2576          int i, j, xyoffset;          int i, j, xyoffset, x1, y1;
2577          DATABLOB *entry;          DATABLOB *entry;
2578    
2579          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
2580    
2581            /* Sometimes, the boxcx value is something really large, like
2582               32691. This makes XCopyArea fail with Xvnc. The code below
2583               is a quick fix. */
2584            if (boxx + boxcx > g_width)
2585                    boxcx = g_width - boxx;
2586    
2587          if (boxcx > 1)          if (boxcx > 1)
2588          {          {
2589                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2590          }          }
2591          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
2592          {          {
2593                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2594          }          }
2595    
2596            SET_FOREGROUND(fgcolour);
2597            SET_BACKGROUND(bgcolour);
2598            XSetFillStyle(g_display, g_gc, FillStippled);
2599    
2600          /* Paint text, character by character */          /* Paint text, character by character */
2601          for (i = 0; i < length;) {          for (i = 0; i < length;)
2602                  switch (text[i]) {          {
2603                  case 0xff:                  switch (text[i])
2604                          if (i + 2 < length)                  {
2605                            case 0xff:
2606                                    /* At least two bytes needs to follow */
2607                                    if (i + 3 > length)
2608                                    {
2609                                            warning("Skipping short 0xff command:");
2610                                            for (j = 0; j < length; j++)
2611                                                    fprintf(stderr, "%02x ", text[j]);
2612                                            fprintf(stderr, "\n");
2613                                            i = length = 0;
2614                                            break;
2615                                    }
2616                                  cache_put_text(text[i + 1], text, text[i + 2]);                                  cache_put_text(text[i + 1], text, text[i + 2]);
2617                          else {                                  i += 3;
2618                                  error("this shouldn't be happening\n");                                  length -= i;
2619                                    /* this will move pointer from start to first character after FF command */
2620                                    text = &(text[i]);
2621                                    i = 0;
2622                                  break;                                  break;
2623                          }  
2624                          /* this will move pointer from start to first character after FF command */                          case 0xfe:
2625                          length -= i + 3;                                  /* At least one byte needs to follow */
2626                          text = &(text[i + 3]);                                  if (i + 2 > length)
2627                          i = 0;                                  {
2628                          break;                                          warning("Skipping short 0xfe command:");
2629                                            for (j = 0; j < length; j++)
2630                  case 0xfe:                                                  fprintf(stderr, "%02x ", text[j]);
2631                          entry = cache_get_text(text[i + 1]);                                          fprintf(stderr, "\n");
2632                          if (entry != NULL) {                                          i = length = 0;
2633                                  if ((((uint8 *) (entry->data))[1] == 0)                                          break;
2634                                      && (!(flags & TEXT2_IMPLICIT_X))) {                                  }
2635                                          if (flags & TEXT2_VERTICAL)                                  entry = cache_get_text(text[i + 1]);
2636                                                  y += text[i + 2];                                  if (entry->data != NULL)
2637                                          else                                  {
2638                                                  x += text[i + 2];                                          if ((((uint8 *) (entry->data))[1] == 0)
2639                                                && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
2640                                            {
2641                                                    if (flags & TEXT2_VERTICAL)
2642                                                            y += text[i + 2];
2643                                                    else
2644                                                            x += text[i + 2];
2645                                            }
2646                                            for (j = 0; j < entry->size; j++)
2647                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
2648                                  }                                  }
2649                                  if (i + 2 < length)                                  if (i + 2 < length)
2650                                          i += 3;                                          i += 3;
2651                                  else                                  else
2652                                          i += 2;                                          i += 2;
2653                                  length -= i;                                  length -= i;
2654                                  /* this will move pointer from start to first character after FE command */                                  /* this will move pointer from start to first character after FE command */
2655                                  text = &(text[i]);                                  text = &(text[i]);
2656                                  i = 0;                                  i = 0;
2657                                  for (j = 0; j < entry->size; j++)                                  break;
                                         DO_GLYPH(((uint8 *) (entry->data)), j);  
                         }  
                         break;  
2658    
2659                  default:                          default:
2660                          DO_GLYPH(text, i);                                  DO_GLYPH(text, i);
2661                          i++;                                  i++;
2662                          break;                                  break;
2663                  }                  }
2664          }          }
2665    
2666            XSetFillStyle(g_display, g_gc, FillSolid);
2667    
2668            if (g_ownbackstore)
2669            {
2670                    if (boxcx > 1)
2671                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2672                                      boxy, boxcx, boxcy, boxx, boxy);
2673                    else
2674                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2675                                      clipy, clipcx, clipcy, clipx, clipy);
2676            }
2677  }  }
2678    
2679  void  void
# Line 1236  ui_desktop_save(uint32 offset, int x, in Line 2682  ui_desktop_save(uint32 offset, int x, in
2682          Pixmap pix;          Pixmap pix;
2683          XImage *image;          XImage *image;
2684    
2685          if (ownbackstore)          if (g_ownbackstore)
2686          {          {
2687                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
2688          }          }
2689          else          else
2690          {          {
2691                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2692                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                  XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
2693                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2694                                    ZPixmap);                  XFreePixmap(g_display, pix);
                 XFreePixmap(display, pix);  
2695          }          }
2696    
2697          offset *= bpp/8;          offset *= g_bpp / 8;
2698          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
                           bpp/8, (uint8 *)image->data);  
2699    
2700          XDestroyImage(image);          XDestroyImage(image);
2701  }  }
# Line 1263  ui_desktop_restore(uint32 offset, int x, Line 2706  ui_desktop_restore(uint32 offset, int x,
2706          XImage *image;          XImage *image;
2707          uint8 *data;          uint8 *data;
2708    
2709          offset *= bpp/8;          offset *= g_bpp / 8;
2710          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2711          if (data == NULL)          if (data == NULL)
2712                  return;                  return;
2713    
2714          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2715                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
                              cx * bpp/8);  
2716    
2717          if (ownbackstore)          if (g_ownbackstore)
2718          {          {
2719                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2720                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2721          }          }
2722          else          else
2723          {          {
2724                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2725          }          }
2726    
2727          XFree(image);          XFree(image);
2728  }  }
2729    
2730    /* these do nothing here but are used in uiports */
2731    void
2732    ui_begin_update(void)
2733    {
2734    }
2735    
2736    void
2737    ui_end_update(void)
2738    {
2739    }

Legend:
Removed from v.54  
changed lines
  Added in v.1042

  ViewVC Help
Powered by ViewVC 1.1.26