/[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 64 by astrand, Thu Jul 18 16:38:31 2002 UTC revision 695 by stargo, Tue May 11 07:34:03 2004 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-2002
5    
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# 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 BOOL g_sendmotion;
34  extern int height;  extern BOOL g_fullscreen;
35  extern BOOL sendmotion;  extern BOOL g_grab_keyboard;
36  extern BOOL fullscreen;  extern BOOL g_hide_decorations;
37    extern char g_title[];
38  Display *display;  extern int g_server_bpp;
39  XkbDescPtr xkb;  extern int g_win_button_size;
40  static int x_socket;  
41  static Window wnd;  Display *g_display;
42  static GC gc;  Time g_last_gesturetime;
43  static Visual *visual;  static int g_x_socket;
44  static int depth;  static Screen *g_screen;
45  static int bpp;  Window g_wnd;
46    extern uint32 g_embed_wnd;
47    BOOL g_enable_compose = False;
48    BOOL g_Unobscured;              /* used for screenblt */
49    static GC g_gc = NULL;
50    static Visual *g_visual;
51    static int g_depth;
52    static int g_bpp;
53    static XIM g_IM;
54    static XIC g_IC;
55    static XModifierKeymap *g_mod_map;
56    static Cursor g_current_cursor;
57    static HCURSOR g_null_cursor = NULL;
58    static Atom g_protocol_atom, g_kill_atom;
59    static BOOL g_focused;
60    static BOOL g_mouse_in_wnd;
61    static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */
62    
63  /* endianness */  /* endianness */
64  static BOOL host_be;  static BOOL g_host_be;
65  static BOOL xserver_be;  static BOOL g_xserver_be;
66    static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
67    static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
68    
69  /* software backing store */  /* software backing store */
70  static BOOL ownbackstore;  extern BOOL g_ownbackstore;
71  static Pixmap backstore;  static Pixmap g_backstore = 0;
72    
73    /* Moving in single app mode */
74    static BOOL g_moving_wnd;
75    static int g_move_x_offset = 0;
76    static int g_move_y_offset = 0;
77    
78    #ifdef WITH_RDPSND
79    extern int g_dsp_fd;
80    extern BOOL g_dsp_busy;
81    extern BOOL g_rdpsnd;
82    #endif
83    
84    /* MWM decorations */
85    #define MWM_HINTS_DECORATIONS   (1L << 1)
86    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
87    typedef struct
88    {
89            uint32 flags;
90            uint32 functions;
91            uint32 decorations;
92            sint32 inputMode;
93            uint32 status;
94    }
95    PropMotifWmHints;
96    
97    typedef struct
98    {
99            uint32 red;
100            uint32 green;
101            uint32 blue;
102    }
103    PixelColour;
104    
 /* 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)  
105    
106  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
107  { \  { \
108          XFillRectangle(display, wnd, gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
109          if (ownbackstore) \          if (g_ownbackstore) \
110                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
111    }
112    
113    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
114    { \
115            XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
116  }  }
117    
118  /* colour maps */  /* colour maps */
119  static BOOL owncolmap;  extern BOOL g_owncolmap;
120  static Colormap xcolmap;  static Colormap g_xcolmap;
121  static uint32 white;  static uint32 *g_colmap = NULL;
122  static uint32 *colmap;  
123    #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
124  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
125  #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));  
126    
127  static int rop2_map[] = {  static int rop2_map[] = {
128          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 102  static int rop2_map[] = { Line 143  static int rop2_map[] = {
143          GXset                   /* 1 */          GXset                   /* 1 */
144  };  };
145    
146  #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]); }
147  #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); }
148    
149  void xwin_get_numlock_mask();  static void
150  void xwin_mod_update(uint32 state, uint32 ev_time);  mwm_hide_decorations(void)
151  void xwin_mod_release(uint32 state, uint32 ev_time, uint32 scancode);  {
152  void xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode);          PropMotifWmHints motif_hints;
153            Atom hintsatom;
154    
155            /* setup the property */
156            motif_hints.flags = MWM_HINTS_DECORATIONS;
157            motif_hints.decorations = 0;
158    
159            /* get the atom for the property */
160            hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
161            if (!hintsatom)
162            {
163                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
164                    return;
165            }
166    
167            XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
168                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
169    }
170    
171    static PixelColour
172    split_colour15(uint32 colour)
173    {
174            PixelColour rv;
175            rv.red = (colour & 0x7c00) >> 7;
176            rv.green = (colour & 0x03e0) >> 2;
177            rv.blue = (colour & 0x001f) << 3;
178            return rv;
179    }
180    
181    static PixelColour
182    split_colour16(uint32 colour)
183    {
184            PixelColour rv;
185            rv.red = (colour & 0xf800) >> 8;
186            rv.green = (colour & 0x07e0) >> 3;
187            rv.blue = (colour & 0x001f) << 3;
188            return rv;
189    }
190    
191    static PixelColour
192    split_colour24(uint32 colour)
193    {
194            PixelColour rv;
195            rv.blue = (colour & 0xff0000) >> 16;
196            rv.green = (colour & 0x00ff00) >> 8;
197            rv.red = (colour & 0x0000ff);
198            return rv;
199    }
200    
201    static uint32
202    make_colour(PixelColour pc)
203    {
204            return (((pc.red >> g_red_shift_r) << g_red_shift_l)
205                    | ((pc.green >> g_green_shift_r) << g_green_shift_l)
206                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l));
207    }
208    
209    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
210    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
211    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
212                            x = (x << 16) | (x >> 16); }
213    
214    static uint32
215    translate_colour(uint32 colour)
216    {
217            PixelColour pc;
218            switch (g_server_bpp)
219            {
220                    case 15:
221                            pc = split_colour15(colour);
222                            break;
223                    case 16:
224                            pc = split_colour16(colour);
225                            break;
226                    case 24:
227                            pc = split_colour24(colour);
228                            break;
229            }
230            return make_colour(pc);
231    }
232    
233    #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
234    #define REPEAT(stm) \
235    { \
236            while (out <= end - 8 * 4) \
237                    UNROLL8(stm) \
238            while (out < end) \
239                    { stm } \
240    }
241    
242  static void  static void
243  translate8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(uint8 * data, uint8 * out, uint8 * end)
244  {  {
245          while (out < end)          while (out < end)
246                  *(out++) = (uint8) colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
247  }  }
248    
249  static void  static void
250  translate16(uint8 * data, uint16 * out, uint16 * end)  translate8to16(uint8 * data, uint8 * out, uint8 * end)
251  {  {
252          while (out < end)          uint16 value;
253                  *(out++) = (uint16) colmap[*(data++)];  
254            if (g_arch_match)
255                    REPEAT(*((uint16*)out) = g_colmap[*(data++)]; out += 2;
256                    )
257            else if (g_xserver_be)
258            {
259                    while (out < end)
260                    {
261                            value = (uint16) g_colmap[*(data++)];
262                            *(out++) = value >> 8;
263                            *(out++) = value;
264                    }
265            }
266            else
267            {
268                    while (out < end)
269                    {
270                            value = (uint16) g_colmap[*(data++)];
271                            *(out++) = value;
272                            *(out++) = value >> 8;
273                    }
274            }
275  }  }
276    
277  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
278  static void  static void
279  translate24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(uint8 * data, uint8 * out, uint8 * end)
280    {
281            uint32 value;
282    
283            if (g_xserver_be)
284            {
285                    while (out < end)
286                    {
287                            value = g_colmap[*(data++)];
288                            *(out++) = value >> 16;
289                            *(out++) = value >> 8;
290                            *(out++) = value;
291                    }
292            }
293            else
294            {
295                    while (out < end)
296                    {
297                            value = g_colmap[*(data++)];
298                            *(out++) = value;
299                            *(out++) = value >> 8;
300                            *(out++) = value >> 16;
301                    }
302            }
303    }
304    
305    static void
306    translate8to32(uint8 * data, uint8 * out, uint8 * end)
307  {  {
308          uint32 value;          uint32 value;
309    
310            if (g_arch_match)
311                    REPEAT(*((uint32 *)out) = g_colmap[*(data++)]; out += 4;
312                    )
313            else if (g_xserver_be)
314            {
315                    while (out < end)
316                    {
317                            value = g_colmap[*(data++)];
318                            *(out++) = value >> 24;
319                            *(out++) = value >> 16;
320                            *(out++) = value >> 8;
321                            *(out++) = value;
322                    }
323            }
324            else
325            {
326                    while (out < end)
327                    {
328                            value = g_colmap[*(data++)];
329                            *(out++) = value;
330                            *(out++) = value >> 8;
331                            *(out++) = value >> 16;
332                            *(out++) = value >> 24;
333                    }
334            }
335    }
336    
337    static void
338    translate15to16(uint16 * data, uint8 * out, uint8 * end)
339    {
340            uint16 pixel;
341            uint16 value;
342    
343          while (out < end)          while (out < end)
344          {          {
345                  value = colmap[*(data++)];                  pixel = *(data++);
346                  *(out++) = value;  
347                  *(out++) = value >> 8;                  if (g_host_be)
348                  *(out++) = value >> 16;                  {
349                            BSWAP16(pixel);
350                    }
351    
352                    value = make_colour(split_colour15(pixel));
353    
354                    if (g_xserver_be)
355                    {
356                            *(out++) = value >> 8;
357                            *(out++) = value;
358                    }
359                    else
360                    {
361                            *(out++) = value;
362                            *(out++) = value >> 8;
363                    }
364          }          }
365  }  }
366    
367  static void  static void
368  translate32(uint8 * data, uint32 * out, uint32 * end)  translate15to24(uint16 * data, uint8 * out, uint8 * end)
369  {  {
370            uint32 value;
371            uint16 pixel;
372    
373          while (out < end)          while (out < end)
374                  *(out++) = colmap[*(data++)];          {
375                    pixel = *(data++);
376    
377                    if (g_host_be)
378                    {
379                            BSWAP16(pixel);
380                    }
381    
382                    value = make_colour(split_colour15(pixel));
383                    if (g_xserver_be)
384                    {
385                            *(out++) = value >> 16;
386                            *(out++) = value >> 8;
387                            *(out++) = value;
388                    }
389                    else
390                    {
391                            *(out++) = value;
392                            *(out++) = value >> 8;
393                            *(out++) = value >> 16;
394                    }
395            }
396  }  }
397    
398  static uint8 *  static void
399  translate_image(int width, int height, uint8 * data)  translate15to32(uint16 * data, uint8 * out, uint8 * end)
400  {  {
401          int size = width * height * bpp / 8;          uint16 pixel;
402          uint8 *out = xmalloc(size);          uint32 value;
         uint8 *end = out + size;  
403    
404          switch (bpp)          while (out < end)
405          {          {
406                  case 8:                  pixel = *(data++);
                         translate8(data, out, end);  
                         break;  
407    
408                  case 16:                  if (g_host_be)
409                          translate16(data, (uint16 *) out, (uint16 *) end);                  {
410                          break;                          BSWAP16(pixel);
411                    }
412    
413                  case 24:                  value = make_colour(split_colour15(pixel));
                         translate24(data, out, end);  
                         break;  
414    
415                  case 32:                  if (g_xserver_be)
416                          translate32(data, (uint32 *) out, (uint32 *) end);                  {
417                          break;                          *(out++) = value >> 24;
418                            *(out++) = value >> 16;
419                            *(out++) = value >> 8;
420                            *(out++) = value;
421                    }
422                    else
423                    {
424                            *(out++) = value;
425                            *(out++) = value >> 8;
426                            *(out++) = value >> 16;
427                            *(out++) = value >> 24;
428                    }
429          }          }
430    }
431    
432          return out;  static void
433    translate16to16(uint16 * data, uint8 * out, uint8 * end)
434    {
435            uint16 pixel;
436            uint16 value;
437    
438            while (out < end)
439            {
440                    pixel = *(data++);
441    
442                    if (g_host_be)
443                    {
444                            BSWAP16(pixel);
445                    }
446    
447                    value = make_colour(split_colour16(pixel));
448    
449                    if (g_xserver_be)
450                    {
451                            *(out++) = value >> 8;
452                            *(out++) = value;
453                    }
454                    else
455                    {
456                            *(out++) = value;
457                            *(out++) = value >> 8;
458                    }
459            }
460  }  }
461    
462  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  static void
463  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  translate16to24(uint16 * data, uint8 * out, uint8 * end)
464  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  {
465                          x = (x << 16) | (x >> 16); }          uint32 value;
466            uint16 pixel;
467    
468  static uint32          while (out < end)
469  translate_colour(uint32 colour)          {
470                    pixel = *(data++);
471    
472                    if (g_host_be)
473                    {
474                            BSWAP16(pixel);
475                    }
476    
477                    value = make_colour(split_colour16(pixel));
478    
479                    if (g_xserver_be)
480                    {
481                            *(out++) = value >> 16;
482                            *(out++) = value >> 8;
483                            *(out++) = value;
484                    }
485                    else
486                    {
487                            *(out++) = value;
488                            *(out++) = value >> 8;
489                            *(out++) = value >> 16;
490                    }
491            }
492    }
493    
494    static void
495    translate16to32(uint16 * data, uint8 * out, uint8 * end)
496  {  {
497          switch (bpp)          uint16 pixel;
498            uint32 value;
499    
500            while (out < end)
501          {          {
502                  case 16:                  pixel = *(data++);
                         if (host_be != xserver_be)  
                                 BSWAP16(colour);  
                         break;  
503    
504                  case 24:                  if (g_host_be)
505                          if (xserver_be)                  {
506                                  BSWAP24(colour);                          BSWAP16(pixel);
507                          break;                  }
508    
509                  case 32:                  value = make_colour(split_colour16(pixel));
510                          if (host_be != xserver_be)  
511                                  BSWAP32(colour);                  if (g_xserver_be)
512                          break;                  {
513                            *(out++) = value >> 24;
514                            *(out++) = value >> 16;
515                            *(out++) = value >> 8;
516                            *(out++) = value;
517                    }
518                    else
519                    {
520                            *(out++) = value;
521                            *(out++) = value >> 8;
522                            *(out++) = value >> 16;
523                            *(out++) = value >> 24;
524                    }
525          }          }
526    }
527    
528          return colour;  static void
529    translate24to16(uint8 * data, uint8 * out, uint8 * end)
530    {
531            uint32 pixel = 0;
532            uint16 value;
533            while (out < end)
534            {
535                    pixel = *(data++) << 16;
536                    pixel |= *(data++) << 8;
537                    pixel |= *(data++);
538    
539                    value = (uint16) make_colour(split_colour24(pixel));
540    
541                    if (g_xserver_be)
542                    {
543                            *(out++) = value >> 8;
544                            *(out++) = value;
545                    }
546                    else
547                    {
548                            *(out++) = value;
549                            *(out++) = value >> 8;
550                    }
551            }
552  }  }
553    
554  BOOL  static void
555  ui_create_window(char *title)  translate24to24(uint8 * data, uint8 * out, uint8 * end)
556  {  {
557          XSetWindowAttributes attribs;          uint32 pixel;
558          XClassHint *classhints;          uint32 value;
559          XSizeHints *sizehints;  
560          unsigned long input_mask;          while (out < end)
561          XPixmapFormatValues *pfm;          {
562          Screen *screen;                  pixel = *(data++) << 16;
563          uint16 test;                  pixel |= *(data++) << 8;
564          int i;                  pixel |= *(data++);
565    
566          int xkb_minor, xkb_major;                  value = make_colour(split_colour24(pixel));
         int xkb_event, xkb_error, xkb_reason;  
567    
568          /* compare compiletime libs with runtime libs. */                  if (g_xserver_be)
569          xkb_major = XkbMajorVersion;                  {
570          xkb_minor = XkbMinorVersion;                          *(out++) = value >> 16;
571          if (XkbLibraryVersion(&xkb_major, &xkb_minor) == False)                          *(out++) = value >> 8;
572                            *(out++) = value;
573                    }
574                    else
575                    {
576                            *(out++) = value;
577                            *(out++) = value >> 8;
578                            *(out++) = value >> 16;
579                    }
580            }
581    }
582    
583    static void
584    translate24to32(uint8 * data, uint8 * out, uint8 * end)
585    {
586            uint32 pixel;
587            uint32 value;
588    
589            while (out < end)
590          {          {
591                  error("please re-compile rdesktop\ncompile time version of xkb is not compatible with\nyour runtime version of the library\n");                  pixel = *(data++) << 16;
592                  return False;                  pixel |= *(data++) << 8;
593                    pixel |= *(data++);
594    
595                    value = make_colour(split_colour24(pixel));
596    
597                    if (g_xserver_be)
598                    {
599                            *(out++) = value >> 24;
600                            *(out++) = value >> 16;
601                            *(out++) = value >> 8;
602                            *(out++) = value;
603                    }
604                    else
605                    {
606                            *(out++) = value;
607                            *(out++) = value >> 8;
608                            *(out++) = value >> 16;
609                            *(out++) = value >> 24;
610                    }
611          }          }
612    }
613    
614    static uint8 *
615    translate_image(int width, int height, uint8 * data)
616    {
617            int size;
618            uint8 *out;
619            uint8 *end;
620    
621            /* if server and xserver bpp match, */
622            /* and arch(endian) matches, no need to translate */
623            /* just return data */
624            if (g_arch_match)
625            {
626                    if (g_depth == 15 && g_server_bpp == 15)
627                            return data;
628                    if (g_depth == 16 && g_server_bpp == 16)
629                            return data;
630            }
631    
632            size = width * height * (g_bpp / 8);
633            out = (uint8 *) xmalloc(size);
634            end = out + size;
635    
636          display =          switch (g_server_bpp)
                 XkbOpenDisplay(NULL, &xkb_event, &xkb_error, &xkb_major,  
                                &xkb_minor, &xkb_reason);  
         switch (xkb_reason)  
637          {          {
638                  case XkbOD_BadLibraryVersion:                  case 24:
639                          error("XkbOD_BadLibraryVersion: XKB extensions in server and the library rdesktop is linked against aren't compatible with each other.\n");                          switch (g_bpp)
640                          break;                          {
641                  case XkbOD_ConnectionRefused:                                  case 32:
642                          error("XkbOD_ConnectionRefused\n");                                          translate24to32(data, out, end);
643                                            break;
644                                    case 24:
645                                            translate24to24(data, out, end);
646                                            break;
647                                    case 16:
648                                            translate24to16(data, out, end);
649                                            break;
650                            }
651                          break;                          break;
652                  case XkbOD_BadServerVersion:                  case 16:
653                          error("XkbOD_BadServerVersion\n");                          switch (g_bpp)
654                            {
655                                    case 32:
656                                            translate16to32((uint16 *) data, out, end);
657                                            break;
658                                    case 24:
659                                            translate16to24((uint16 *) data, out, end);
660                                            break;
661                                    case 16:
662                                            translate16to16((uint16 *) data, out, end);
663                                            break;
664                            }
665                          break;                          break;
666                  case XkbOD_NonXkbServer:                  case 15:
667                          error("XkbOD_NonXkbServer: XKB extension not present in server\nupdate your X server.\n");                          switch (g_bpp)
668                            {
669                                    case 32:
670                                            translate15to32((uint16 *) data, out, end);
671                                            break;
672                                    case 24:
673                                            translate15to24((uint16 *) data, out, end);
674                                            break;
675                                    case 16:
676                                            translate15to16((uint16 *) data, out, end);
677                                            break;
678                            }
679                          break;                          break;
680                  case XkbOD_Success:                  case 8:
681                          DEBUG("XkbOD_Success: Connection established with display\n");                          switch (g_bpp)
682                            {
683                                    case 8:
684                                            translate8to8(data, out, end);
685                                            break;
686                                    case 16:
687                                            translate8to16(data, out, end);
688                                            break;
689                                    case 24:
690                                            translate8to24(data, out, end);
691                                            break;
692                                    case 32:
693                                            translate8to32(data, out, end);
694                                            break;
695                            }
696                          break;                          break;
697          }          }
698            return out;
699    }
700    
701    BOOL
702    get_key_state(unsigned int state, uint32 keysym)
703    {
704            int modifierpos, key, keysymMask = 0;
705            int offset;
706    
707            KeyCode keycode = XKeysymToKeycode(g_display, keysym);
708    
709            if (keycode == NoSymbol)
710                    return False;
711    
712            for (modifierpos = 0; modifierpos < 8; modifierpos++)
713            {
714                    offset = g_mod_map->max_keypermod * modifierpos;
715    
716                    for (key = 0; key < g_mod_map->max_keypermod; key++)
717                    {
718                            if (g_mod_map->modifiermap[offset + key] == keycode)
719                                    keysymMask |= 1 << modifierpos;
720                    }
721            }
722    
723            return (state & keysymMask) ? True : False;
724    }
725    
726    static void
727    calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
728    {
729            *shift_l = ffs(mask) - 1;
730            mask >>= *shift_l;
731            *shift_r = 8 - ffs(mask & ~(mask >> 1));
732    }
733    
734    BOOL
735    ui_init(void)
736    {
737            XVisualInfo vi;
738            XPixmapFormatValues *pfm;
739            uint16 test;
740            int i, screen_num, nvisuals;
741            XVisualInfo *vmatches = NULL;
742            XVisualInfo template;
743            Bool TrueColorVisual = False;
744    
745          if (display == NULL)          g_display = XOpenDisplay(NULL);
746            if (g_display == NULL)
747          {          {
748                  error("Failed to open display\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
749                  return False;                  return False;
750          }          }
751    
752          x_socket = ConnectionNumber(display);          screen_num = DefaultScreen(g_display);
753          screen = DefaultScreenOfDisplay(display);          g_x_socket = ConnectionNumber(g_display);
754          visual = DefaultVisualOfScreen(screen);          g_screen = ScreenOfDisplay(g_display, screen_num);
755          depth = DefaultDepthOfScreen(screen);          g_depth = DefaultDepthOfScreen(g_screen);
756    
757            /* Search for best TrueColor depth */
758            template.class = TrueColor;
759            vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);
760    
761            nvisuals--;
762            while (nvisuals >= 0)
763            {
764                    if ((vmatches + nvisuals)->depth > g_depth)
765                    {
766                            g_depth = (vmatches + nvisuals)->depth;
767                    }
768                    nvisuals--;
769                    TrueColorVisual = True;
770            }
771    
772            test = 1;
773            g_host_be = !(BOOL) (*(uint8 *) (&test));
774            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
775    
776            if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))
777            {
778                    /* we use a colourmap, so the default visual should do */
779                    g_visual = DefaultVisualOfScreen(g_screen);
780                    g_depth = DefaultDepthOfScreen(g_screen);
781    
782                    /* Do not allocate colours on a TrueColor visual */
783                    if (g_visual->class == TrueColor)
784                    {
785                            g_owncolmap = False;
786                    }
787            }
788            else
789            {
790                    /* need a truecolour visual */
791                    if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))
792                    {
793                            error("The display does not support true colour - high colour support unavailable.\n");
794                            return False;
795                    }
796    
797                    g_visual = vi.visual;
798                    g_owncolmap = False;
799                    calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);
800                    calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);
801                    calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);
802    
803                    /* if RGB video and averything is little endian */
804                    if (vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask)
805                            if (!g_xserver_be && !g_host_be)
806                                    g_arch_match = True;
807            }
808    
809          pfm = XListPixmapFormats(display, &i);          pfm = XListPixmapFormats(g_display, &i);
810          if (pfm != NULL)          if (pfm != NULL)
811          {          {
812                  /* Use maximum bpp for this depth - this is generally                  /* Use maximum bpp for this depth - this is generally
813                     desirable, e.g. 24 bits->32 bits. */                     desirable, e.g. 24 bits->32 bits. */
814                  while (i--)                  while (i--)
815                  {                  {
816                          if ((pfm[i].depth == depth)                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
                             && (pfm[i].bits_per_pixel > bpp))  
817                          {                          {
818                                  bpp = pfm[i].bits_per_pixel;                                  g_bpp = pfm[i].bits_per_pixel;
819                          }                          }
820                  }                  }
821                  XFree(pfm);                  XFree(pfm);
822          }          }
823    
824          if (bpp < 8)          if (g_bpp < 8)
825          {          {
826                  error("Less than 8 bpp not currently supported.\n");                  error("Less than 8 bpp not currently supported.\n");
827                  XCloseDisplay(display);                  XCloseDisplay(g_display);
828                  return False;                  return False;
829          }          }
830    
831          if (depth <= 8)          if (!g_owncolmap)
832                  owncolmap = True;          {
833          else                  g_xcolmap =
834                  xcolmap = DefaultColormapOfScreen(screen);                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
835                                            AllocNone);
836          test = 1;                  if (g_depth <= 8)
837          host_be = !(BOOL) (*(uint8 *) (&test));                          warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
838          xserver_be = (ImageByteOrder(display) == MSBFirst);          }
   
         white = WhitePixelOfScreen(screen);  
         attribs.background_pixel = BlackPixelOfScreen(screen);  
         attribs.backing_store = DoesBackingStore(screen);  
839    
840          if (attribs.backing_store == NotUseful)          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
841                  ownbackstore = True;          {
842                    warning("External BackingStore not available, using internal\n");
843                    g_ownbackstore = True;
844            }
845    
846          if (fullscreen)          /*
847             * Determine desktop size
848             */
849            if (g_fullscreen)
850          {          {
851                  attribs.override_redirect = True;                  g_width = WidthOfScreen(g_screen);
852                  width = WidthOfScreen(screen);                  g_height = HeightOfScreen(g_screen);
                 height = HeightOfScreen(screen);  
853          }          }
854          else          else if (g_width < 0)
855            {
856                    /* Percent of screen */
857                    g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
858                    g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
859            }
860            else if (g_width == 0)
861          {          {
862                  attribs.override_redirect = False;                  /* Fetch geometry from _NET_WORKAREA */
863                    uint32 x, y, cx, cy;
864    
865                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
866                    {
867                            g_width = cx;
868                            g_height = cy;
869                    }
870                    else
871                    {
872                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
873                            g_width = 800;
874                            g_height = 600;
875                    }
876          }          }
877    
878          width = (width + 3) & ~3;       /* make width a multiple of 32 bits */          /* make sure width is a multiple of 4 */
879            g_width = (g_width + 3) & ~3;
880    
881            g_mod_map = XGetModifierMapping(g_display);
882    
883            xkeymap_init();
884    
885            if (g_enable_compose)
886                    g_IM = XOpenIM(g_display, NULL, NULL, NULL);
887    
888            xclip_init();
889    
890            DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));
891    
892            return True;
893    }
894    
895    void
896    ui_deinit(void)
897    {
898            if (g_IM != NULL)
899                    XCloseIM(g_IM);
900    
901          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          if (g_null_cursor != NULL)
902                              0, 0, width, height, 0, CopyFromParent,                  ui_destroy_cursor(g_null_cursor);
                             InputOutput, CopyFromParent,  
                             CWBackingStore | CWBackPixel | CWOverrideRedirect,  
                             &attribs);  
903    
904          XStoreName(display, wnd, title);          XFreeModifiermap(g_mod_map);
905    
906            if (g_ownbackstore)
907                    XFreePixmap(g_display, g_backstore);
908    
909            XFreeGC(g_display, g_gc);
910            XCloseDisplay(g_display);
911            g_display = NULL;
912    }
913    
914    BOOL
915    ui_create_window(void)
916    {
917            uint8 null_pointer_mask[1] = { 0x80 };
918            uint8 null_pointer_data[4] = { 0x00, 0x00, 0x00, 0x00 };
919            XSetWindowAttributes attribs;
920            XClassHint *classhints;
921            XSizeHints *sizehints;
922            int wndwidth, wndheight;
923            long input_mask, ic_input_mask;
924            XEvent xevent;
925    
926            wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
927            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
928    
929            attribs.background_pixel = BlackPixelOfScreen(g_screen);
930            attribs.border_pixel = WhitePixelOfScreen(g_screen);
931            attribs.backing_store = g_ownbackstore ? NotUseful : Always;
932            attribs.override_redirect = g_fullscreen;
933            attribs.colormap = g_xcolmap;
934    
935            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
936                                  0, g_depth, InputOutput, g_visual,
937                                  CWBackPixel | CWBackingStore | CWOverrideRedirect |
938                                  CWColormap | CWBorderPixel, &attribs);
939    
940            if (g_gc == NULL)
941                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
942    
943            if ((g_ownbackstore) && (g_backstore == 0))
944            {
945                    g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
946    
947                    /* clear to prevent rubbish being exposed at startup */
948                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
949                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
950            }
951    
952            XStoreName(g_display, g_wnd, g_title);
953    
954            if (g_hide_decorations)
955                    mwm_hide_decorations();
956    
957          classhints = XAllocClassHint();          classhints = XAllocClassHint();
958          if (classhints != NULL)          if (classhints != NULL)
959          {          {
960                  classhints->res_name = classhints->res_class = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
961                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(g_display, g_wnd, classhints);
962                  XFree(classhints);                  XFree(classhints);
963          }          }
964    
# Line 334  ui_create_window(char *title) Line 966  ui_create_window(char *title)
966          if (sizehints)          if (sizehints)
967          {          {
968                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
969                  sizehints->min_width = sizehints->max_width = width;                  sizehints->min_width = sizehints->max_width = g_width;
970                  sizehints->min_height = sizehints->max_height = height;                  sizehints->min_height = sizehints->max_height = g_height;
971                  XSetWMNormalHints(display, wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
972                  XFree(sizehints);                  XFree(sizehints);
973          }          }
974    
975          xkeymap_init();          if (g_embed_wnd)
976            {
977                    XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
978            }
979    
980          input_mask = KeyPressMask | KeyReleaseMask |          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
981                  ButtonPressMask | ButtonReleaseMask |                  VisibilityChangeMask | FocusChangeMask;
                 EnterWindowMask | LeaveWindowMask;  
         if (sendmotion)  
                 input_mask |= PointerMotionMask;  
982    
983          if (ownbackstore)          if (g_sendmotion)
984                    input_mask |= PointerMotionMask;
985            if (g_ownbackstore)
986                  input_mask |= ExposureMask;                  input_mask |= ExposureMask;
987            if (g_fullscreen || g_grab_keyboard)
988                    input_mask |= EnterWindowMask;
989            if (g_grab_keyboard)
990                    input_mask |= LeaveWindowMask;
991    
992          XSelectInput(display, wnd, input_mask);          if (g_IM != NULL)
993          gc = XCreateGC(display, wnd, 0, NULL);          {
994                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
995                                     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
996    
997          if (ownbackstore)                  if ((g_IC != NULL)
998                  backstore = XCreatePixmap(display, wnd, width, height, depth);                      && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
999                            input_mask |= ic_input_mask;
1000            }
1001    
1002          XMapWindow(display, wnd);          XSelectInput(g_display, g_wnd, input_mask);
1003            XMapWindow(g_display, g_wnd);
1004    
1005          /* TODO: error texts... make them friendly. */          /* wait for VisibilityNotify */
1006          xkb = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);          do
         if ((int) xkb == BadAlloc || xkb == NULL)  
1007          {          {
1008                  error("XkbGetKeyboard failed.\n");                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);
                 exit(0);  
1009          }          }
1010            while (xevent.type != VisibilityNotify);
1011            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1012    
1013          /* TODO: error texts... make them friendly. */          g_focused = False;
1014          if (XkbSelectEvents          g_mouse_in_wnd = False;
             (display, xkb->device_spec, XkbAllEventsMask,  
              XkbAllEventsMask) == False)  
         {  
                 error("XkbSelectEvents failed.\n");  
                 exit(0);  
         }  
1015    
1016          xwin_get_numlock_mask();          /* handle the WM_DELETE_WINDOW protocol */
1017            g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1018            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1019            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1020    
1021            /* create invisible 1x1 cursor to be used as null cursor */
1022            if (g_null_cursor == NULL)
1023                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1024    
1025          return True;          return True;
1026  }  }
1027    
1028  void  void
1029  xwin_get_numlock_mask()  ui_resize_window()
1030  {  {
1031          KeyCode numlockcode;          XSizeHints *sizehints;
         KeyCode *keycode;  
         XModifierKeymap *modmap;  
         int i, j;  
1032    
1033          /* Find out if numlock is already defined as a modifier key, and if so where */          sizehints = XAllocSizeHints();
1034          numlockcode = XKeysymToKeycode(display, 0xFF7F);        /* XF_Num_Lock = 0xFF7F */          if (sizehints)
1035          if (numlockcode)          {
1036          {                  sizehints->flags = PMinSize | PMaxSize;
1037                  modmap = XGetModifierMapping(display);                  sizehints->min_width = sizehints->max_width = g_width;
1038                  if (modmap)                  sizehints->min_height = sizehints->max_height = g_height;
1039                  {                  XSetWMNormalHints(g_display, g_wnd, sizehints);
1040                          keycode = modmap->modifiermap;                  XFree(sizehints);
                         for (i = 0; i < 8; i++)  
                                 for (j = modmap->max_keypermod; j--;)  
                                 {  
                                         if (*keycode == numlockcode)  
                                         {  
                                                 numlock_modifier_mask =  
                                                         (1 << i);  
                                                 i = 8;  
                                                 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);  
                 }  
1041          }          }
1042    
1043          if (!numlock_modifier_mask)          if (!(g_fullscreen || g_embed_wnd))
1044                  printf("WARNING: Failed to get a numlock modifier mapping.\n");          {
1045                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1046            }
1047    }
1048    
1049    void
1050    ui_destroy_window(void)
1051    {
1052            if (g_IC != NULL)
1053                    XDestroyIC(g_IC);
1054    
1055            XDestroyWindow(g_display, g_wnd);
1056  }  }
1057    
1058  void  void
1059  ui_destroy_window()  xwin_toggle_fullscreen(void)
1060  {  {
1061          if (xkb != NULL)          Pixmap contents = 0;
1062                  XkbFreeKeyboard(xkb, XkbAllControlsMask, True);  
1063            if (!g_ownbackstore)
1064            {
1065                    /* need to save contents of window */
1066                    contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1067                    XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1068            }
1069    
1070            ui_destroy_window();
1071            g_fullscreen = !g_fullscreen;
1072            ui_create_window();
1073    
1074          if (ownbackstore)          XDefineCursor(g_display, g_wnd, g_current_cursor);
                 XFreePixmap(display, backstore);  
1075    
1076          XFreeGC(display, gc);          if (!g_ownbackstore)
1077          XDestroyWindow(display, wnd);          {
1078          XCloseDisplay(display);                  XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1079          display = NULL;                  XFreePixmap(g_display, contents);
1080            }
1081  }  }
1082    
1083  static void  /* Process all events in Xlib queue
1084  xwin_process_events()     Returns 0 after user quit, 1 otherwise */
1085    static int
1086    xwin_process_events(void)
1087  {  {
1088          XEvent xevent;          XEvent xevent;
   
1089          KeySym keysym;          KeySym keysym;
         uint8 scancode;  
1090          uint16 button, flags;          uint16 button, flags;
1091          uint32 ev_time;          uint32 ev_time;
1092          uint32 tmpmods;          key_translation tr;
1093            char str[256];
1094            Status status;
1095    
1096          while (XCheckMaskEvent(display, ~0, &xevent))          while (XPending(g_display) > 0)
1097          {          {
1098                  ev_time = time(NULL);                  XNextEvent(g_display, &xevent);
                 flags = 0;  
1099    
1100                  switch (xevent.type)                  if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1101                  {                  {
1102                          case KeyRelease:                          DEBUG_KBD(("Filtering event\n"));
1103                                  flags = KBD_FLAG_DOWN | KBD_FLAG_UP;                          continue;
1104                                  /* fall through */                  }
                         case KeyPress:  
                                 if (XkbTranslateKeyCode  
                                     (xkb, xevent.xkey.keycode,  
                                      xevent.xkey.state, &tmpmods,  
                                      &keysym) == False)  
                                         break;  
                                 scancode =  
                                         xkeymap_translate_key(keysym,  
                                                               xevent.xkey.  
                                                               keycode,  
                                                               &flags);  
   
                                 if (scancode == 0)  
                                         break;  
   
                                 /* keep track of the modifiers -- needed for stickykeys... */  
                                 if (xevent.type == KeyPress)  
                                         xwin_mod_press(xevent.xkey.state,  
                                                        ev_time, scancode);  
   
                                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                                flags, scancode, 0);  
   
                                 if (xevent.type == KeyRelease)  
                                         xwin_mod_release(xevent.xkey.state,  
                                                          ev_time, scancode);  
   
                                 break;  
   
                         case ButtonPress:  
                                 flags = MOUSE_FLAG_DOWN;  
                                 /* fall through */  
1105    
1106                          case ButtonRelease:                  flags = 0;
                                 button = xkeymap_translate_button(xevent.  
                                                                   xbutton.  
                                                                   button);  
                                 if (button == 0)  
                                         break;  
1107    
1108                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                  switch (xevent.type)
1109                                                 flags | button,                  {
1110                                                 xevent.xbutton.x,                          case VisibilityNotify:
1111                                                 xevent.xbutton.y);                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1112                                  break;                                  break;
1113                            case ClientMessage:
1114                          case MotionNotify:                                  /* the window manager told us to quit */
1115                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if ((xevent.xclient.message_type == g_protocol_atom)
1116                                                 MOUSE_FLAG_MOVE,                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1117                                                 xevent.xmotion.x,                                          /* Quit */
1118                                                 xevent.xmotion.y);                                          return 0;
1119                                  break;                                  break;
1120    
1121                          case EnterNotify:                          case KeyPress:
1122                                  XGrabKeyboard(display, wnd, True,                                  g_last_gesturetime = xevent.xkey.time;
1123                                                GrabModeAsync, GrabModeAsync,                                  if (g_IC != NULL)
1124                                                CurrentTime);                                          /* Multi_key compatible version */
1125                                    {
1126                                  xwin_mod_update(xevent.xcrossing.state,                                          XmbLookupString(g_IC,
1127                                                  ev_time);                                                          &xevent.xkey, str, sizeof(str), &keysym,
1128                                  break;                                                          &status);
1129                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1130                          case LeaveNotify:                                          {
1131                                  XUngrabKeyboard(display, CurrentTime);                                                  error("XmbLookupString failed with status 0x%x\n",
1132                                  break;                                                        status);
1133                                                    break;
1134                                            }
1135                                    }
1136                                    else
1137                                    {
1138                                            /* Plain old XLookupString */
1139                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1140                                            XLookupString((XKeyEvent *) & xevent,
1141                                                          str, sizeof(str), &keysym, NULL);
1142                                    }
1143    
1144                          case Expose:                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1145                                  XCopyArea(display, backstore, wnd, gc,                                             get_ksname(keysym)));
                                           xevent.xexpose.x, xevent.xexpose.y,  
                                           xevent.xexpose.width,  
                                           xevent.xexpose.height,  
                                           xevent.xexpose.x, xevent.xexpose.y);  
                                 break;  
                 }  
         }  
 }  
1146    
1147  void                                  ev_time = time(NULL);
1148  xwin_mod_update(uint32 state, uint32 ev_time)                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1149  {                                          break;
         xwin_mod_press(state, ev_time, 0);  
         xwin_mod_release(state, ev_time, 0);  
 }  
1150    
1151  void                                  tr = xkeymap_translate_key(keysym,
1152  xwin_mod_release(uint32 state, uint32 ev_time, uint32 scancode)                                                             xevent.xkey.keycode, xevent.xkey.state);
 {  
         switch (scancode)  
         {  
                 case 0x2a:  
                         key_down_state &= ~DShift1Mask;  
                         break;  
                 case 0x36:  
                         key_down_state &= ~DShift2Mask;  
                         break;  
                 case 0x1d:  
                         key_down_state &= ~DControl1Mask;  
                         break;  
                 case 0x9d:  
                         key_down_state &= ~DControl2Mask;  
                         break;  
                 case 0x38:  
                         key_down_state &= ~DMod1Mask;  
                         break;  
                 case 0xb8:  
                         key_down_state &= ~DMod2Mask;  
                         break;  
         }  
1153    
1154          if (!(numlock_modifier_mask & state)                                  if (tr.scancode == 0)
1155              && (key_down_state & DNumLockMask))                                          break;
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x45, 0);  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                KBD_FLAG_DOWN | KBD_FLAG_UP, 0x45, 0);  
                 key_down_state &= ~DNumLockMask;  
         }  
1156    
1157          if (!(LockMask & state) && (key_down_state & DLockMask))                                  save_remote_modifiers(tr.scancode);
1158          {                                  ensure_remote_modifiers(ev_time, tr);
1159                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);                                  rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1160                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  restore_remote_modifiers(ev_time, tr.scancode);
                                KBD_FLAG_DOWN | KBD_FLAG_UP, 0x3a, 0);  
                 key_down_state &= ~DLockMask;  
1161    
1162          }                                  break;
1163    
1164                            case KeyRelease:
1165                                    g_last_gesturetime = xevent.xkey.time;
1166                                    XLookupString((XKeyEvent *) & xevent, str,
1167                                                  sizeof(str), &keysym, NULL);
1168    
1169          if (!(ShiftMask & state) && (key_down_state & DShift1Mask))                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1170          {                                             get_ksname(keysym)));
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a,  
                                0);  
                 key_down_state &= ~DShift1Mask;  
1171    
1172          }                                  ev_time = time(NULL);
1173                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1174                                            break;
1175    
1176          if (!(ControlMask & state) && (key_down_state & DControl1Mask))                                  tr = xkeymap_translate_key(keysym,
1177          {                                                             xevent.xkey.keycode, xevent.xkey.state);
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d,  
                                0);  
                 key_down_state &= ~DControl1Mask;  
1178    
1179          }                                  if (tr.scancode == 0)
1180                                            break;
1181    
1182          if (!(Mod1Mask & state) && (key_down_state & DMod1Mask))                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
1183          {                                  break;
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38,  
                                0);  
                 key_down_state &= ~DMod1Mask;  
1184    
1185          }                          case ButtonPress:
1186                                    flags = MOUSE_FLAG_DOWN;
1187                                    /* fall through */
1188    
1189          if (!(Mod2Mask & state) && (key_down_state & DMod2Mask))                          case ButtonRelease:
1190          {                                  g_last_gesturetime = xevent.xbutton.time;
1191                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8,                                  button = xkeymap_translate_button(xevent.xbutton.button);
1192                                 0);                                  if (button == 0)
1193                  key_down_state &= ~DMod2Mask;                                          break;
         }  
 }  
1194    
1195                                    /* If win_button_size is nonzero, enable single app mode */
1196                                    if (xevent.xbutton.y < g_win_button_size)
1197                                    {
1198                                            /* Stop moving window when button is released, regardless of cursor position */
1199                                            if (g_moving_wnd && (xevent.type == ButtonRelease))
1200                                                    g_moving_wnd = False;
1201    
1202  void                                          /*  Check from right to left: */
 xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode)  
 {  
1203    
1204          switch (scancode)                                          if (xevent.xbutton.x >= g_width - g_win_button_size)
1205          {                                          {
1206                  case 0x2a:                                                  /* The close button, continue */
1207                          key_down_state |= DShift1Mask;                                                  ;
1208                          break;                                          }
1209                  case 0x36:                                          else if (xevent.xbutton.x >=
1210                          key_down_state |= DShift2Mask;                                                   g_width - g_win_button_size * 2)
1211                          break;                                          {
1212                  case 0x1d:                                                  /* The maximize/restore button. Do not send to
1213                          key_down_state |= DControl1Mask;                                                     server.  It might be a good idea to change the
1214                          break;                                                     cursor or give some other visible indication
1215                  case 0x9d:                                                     that rdesktop inhibited this click */
1216                          key_down_state |= DControl2Mask;                                                  break;
1217                          break;                                          }
1218                  case 0x3a:                                          else if (xevent.xbutton.x >=
1219                          key_down_state ^= DLockMask;                                                   g_width - g_win_button_size * 3)
1220                          break;                                          {
1221                  case 0x45:                                                  /* The minimize button. Iconify window. */
1222                          key_down_state ^= DNumLockMask;                                                  XIconifyWindow(g_display, g_wnd,
1223                          break;                                                                 DefaultScreen(g_display));
1224                  case 0x38:                                                  break;
1225                          key_down_state |= DMod1Mask;                                          }
1226                          break;                                          else if (xevent.xbutton.x <= g_win_button_size)
1227                  case 0xb8:                                          {
1228                          key_down_state |= DMod2Mask;                                                  /* The system menu. Ignore. */
1229                          break;                                                  break;
1230          }                                          }
1231                                            else
1232                                            {
1233                                                    /* The title bar. */
1234                                                    if ((xevent.type == ButtonPress) && !g_fullscreen
1235                                                        && g_hide_decorations)
1236                                                    {
1237                                                            g_moving_wnd = True;
1238                                                            g_move_x_offset = xevent.xbutton.x;
1239                                                            g_move_y_offset = xevent.xbutton.y;
1240                                                    }
1241                                                    break;
1242    
1243          if ((numlock_modifier_mask && state)                                          }
1244              && !(key_down_state & DNumLockMask))                                  }
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x45, 0);  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                KBD_FLAG_DOWN | KBD_FLAG_UP, 0x45, 0);  
                 key_down_state |= DNumLockMask;  
         }  
1245    
1246          if ((LockMask & state) && !(key_down_state & DLockMask))                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1247          {                                                 flags | button, xevent.xbutton.x, xevent.xbutton.y);
1248                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);                                  break;
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,  
                                KBD_FLAG_DOWN | KBD_FLAG_UP, 0x3a, 0);  
                 key_down_state |= DLockMask;  
1249    
1250          }                          case MotionNotify:
1251                                    if (g_moving_wnd)
1252                                    {
1253                                            XMoveWindow(g_display, g_wnd,
1254                                                        xevent.xmotion.x_root - g_move_x_offset,
1255                                                        xevent.xmotion.y_root - g_move_y_offset);
1256                                            break;
1257                                    }
1258    
1259                                    if (g_fullscreen && !g_focused)
1260                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1261                                                           CurrentTime);
1262                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1263                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1264                                    break;
1265    
1266          if ((ShiftMask & state)                          case FocusIn:
1267              && !((key_down_state & DShift1Mask)                                  if (xevent.xfocus.mode == NotifyGrab)
1268                   || (key_down_state & DShift2Mask)))                                          break;
1269          {                                  g_focused = True;
1270                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,                                  reset_modifier_keys();
1271                                 0x2a, 0);                                  if (g_grab_keyboard && g_mouse_in_wnd)
1272                  key_down_state |= DShift1Mask;                                          XGrabKeyboard(g_display, g_wnd, True,
1273                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1274                                    break;
1275    
1276          }                          case FocusOut:
1277                                    if (xevent.xfocus.mode == NotifyUngrab)
1278                                            break;
1279                                    g_focused = False;
1280                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1281                                            XUngrabKeyboard(g_display, CurrentTime);
1282                                    break;
1283    
1284          if ((ControlMask & state)                          case EnterNotify:
1285              && !((key_down_state & DControl1Mask)                                  /* we only register for this event when in fullscreen mode */
1286                   || (key_down_state & DControl2Mask)))                                  /* or grab_keyboard */
1287          {                                  g_mouse_in_wnd = True;
1288                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,                                  if (g_fullscreen)
1289                                 0x1d, 0);                                  {
1290                  key_down_state |= DControl1Mask;                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1291                                                           CurrentTime);
1292                                            break;
1293                                    }
1294                                    if (g_focused)
1295                                            XGrabKeyboard(g_display, g_wnd, True,
1296                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1297                                    break;
1298    
1299          }                          case LeaveNotify:
1300                                    /* we only register for this event when grab_keyboard */
1301                                    g_mouse_in_wnd = False;
1302                                    XUngrabKeyboard(g_display, CurrentTime);
1303                                    break;
1304    
1305          if ((Mod1Mask & state) && !(key_down_state & DMod1Mask))                          case Expose:
1306          {                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1307                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,                                            xevent.xexpose.x, xevent.xexpose.y,
1308                                 0x38, 0);                                            xevent.xexpose.width,
1309                  key_down_state |= DMod1Mask;                                            xevent.xexpose.height,
1310                                              xevent.xexpose.x, xevent.xexpose.y);
1311                                    break;
1312    
1313          }                          case MappingNotify:
1314                                    /* Refresh keyboard mapping if it has changed. This is important for
1315                                       Xvnc, since it allocates keycodes dynamically */
1316                                    if (xevent.xmapping.request == MappingKeyboard
1317                                        || xevent.xmapping.request == MappingModifier)
1318                                            XRefreshKeyboardMapping(&xevent.xmapping);
1319    
1320          if ((Mod2Mask & state) && !(key_down_state & DMod2Mask))                                  if (xevent.xmapping.request == MappingModifier)
1321          {                                  {
1322                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,                                          XFreeModifiermap(g_mod_map);
1323                                 0xb8, 0);                                          g_mod_map = XGetModifierMapping(g_display);
1324                  key_down_state |= DMod2Mask;                                  }
1325                                    break;
1326    
1327                                    /* clipboard stuff */
1328                            case SelectionNotify:
1329                                    xclip_handle_SelectionNotify(&xevent.xselection);
1330                                    break;
1331                            case SelectionRequest:
1332                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1333                                    break;
1334                            case SelectionClear:
1335                                    xclip_handle_SelectionClear();
1336                                    break;
1337                            case PropertyNotify:
1338                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1339                                    break;
1340                    }
1341          }          }
1342            /* Keep going */
1343            return 1;
1344  }  }
1345    
1346  void  /* Returns 0 after user quit, 1 otherwise */
1347    int
1348  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1349  {  {
1350          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;          int n;
1351          fd_set rfds;          fd_set rfds, wfds;
1352            struct timeval tv;
1353          FD_ZERO(&rfds);          BOOL s_timeout = False;
1354    
1355          while (True)          while (True)
1356          {          {
1357                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1358                    /* Process any events already waiting */
1359                    if (!xwin_process_events())
1360                            /* User quit */
1361                            return 0;
1362    
1363                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
1364                    FD_ZERO(&wfds);
1365                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
1366                  if (display != NULL)                  FD_SET(g_x_socket, &rfds);
1367    
1368    #ifdef WITH_RDPSND
1369                    /* FIXME: there should be an API for registering fds */
1370                    if (g_dsp_busy)
1371                  {                  {
1372                          FD_SET(x_socket, &rfds);                          FD_SET(g_dsp_fd, &wfds);
1373                          XFlush(display);                          n = (g_dsp_fd > n) ? g_dsp_fd : n;
1374                  }                  }
1375    #endif
1376                    /* default timeout */
1377                    tv.tv_sec = 60;
1378                    tv.tv_usec = 0;
1379    
1380                    /* add redirection handles */
1381                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1382    
1383                    n++;
1384    
1385                  switch (select(n, &rfds, NULL, NULL, NULL))                  switch (select(n, &rfds, &wfds, NULL, &tv))
1386                  {                  {
1387                          case -1:                          case -1:
1388                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
1389    
1390                          case 0:                          case 0:
1391                                    /* TODO: if tv.tv_sec just times out
1392                                     * we will segfault.
1393                                     * FIXME:
1394                                     */
1395                                    //s_timeout = True;
1396                                    //rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1397                                  continue;                                  continue;
1398                  }                  }
1399    
1400                  if (FD_ISSET(x_socket, &rfds))                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
                         xwin_process_events();  
1401    
1402                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1403                          return;                          return 1;
1404    
1405    #ifdef WITH_RDPSND
1406                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1407                            wave_out_play();
1408    #endif
1409          }          }
1410  }  }
1411    
1412  void  void
1413  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
1414  {  {
1415          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1416  }  }
1417    
1418  HBITMAP  HBITMAP
# Line 761  ui_create_bitmap(int width, int height, Line 1421  ui_create_bitmap(int width, int height,
1421          XImage *image;          XImage *image;
1422          Pixmap bitmap;          Pixmap bitmap;
1423          uint8 *tdata;          uint8 *tdata;
1424            int bitmap_pad;
1425    
1426            if (g_server_bpp == 8)
1427            {
1428                    bitmap_pad = 8;
1429            }
1430            else
1431            {
1432                    bitmap_pad = g_bpp;
1433    
1434                    if (g_bpp == 24)
1435                            bitmap_pad = 32;
1436            }
1437    
1438          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1439          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1440          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1441                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
1442    
1443          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1444    
1445          XFree(image);          XFree(image);
1446          if (!owncolmap)          if (tdata != data)
1447                  xfree(tdata);                  xfree(tdata);
1448          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1449  }  }
1450    
1451  void  void
1452  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)  
1453  {  {
1454          XImage *image;          XImage *image;
1455          uint8 *tdata;          uint8 *tdata;
1456            int bitmap_pad;
1457    
1458            if (g_server_bpp == 8)
1459            {
1460                    bitmap_pad = 8;
1461            }
1462            else
1463            {
1464                    bitmap_pad = g_bpp;
1465    
1466                    if (g_bpp == 24)
1467                            bitmap_pad = 32;
1468            }
1469    
1470          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1471          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1472                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
1473    
1474          if (ownbackstore)          if (g_ownbackstore)
1475          {          {
1476                  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);
1477                  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);
1478          }          }
1479          else          else
1480          {          {
1481                  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);
1482          }          }
1483    
1484          XFree(image);          XFree(image);
1485          if (!owncolmap)          if (tdata != data)
1486                  xfree(tdata);                  xfree(tdata);
1487  }  }
1488    
1489  void  void
1490  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1491  {  {
1492          XFreePixmap(display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
1493  }  }
1494    
1495  HGLYPH  HGLYPH
# Line 817  ui_create_glyph(int width, int height, u Line 1502  ui_create_glyph(int width, int height, u
1502    
1503          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1504    
1505          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1506          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(g_display, bitmap, 0, NULL);
1507    
1508          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1509                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1510          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1511          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1512          XInitImage(image);          XInitImage(image);
1513    
1514          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1515    
1516          XFree(image);          XFree(image);
1517          XFreeGC(display, gc);          XFreeGC(g_display, gc);
1518          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1519  }  }
1520    
1521  void  void
1522  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1523  {  {
1524          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
1525  }  }
1526    
1527  HCURSOR  HCURSOR
1528  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1529                   int height, uint8 * andmask, uint8 * xormask)                   uint8 * andmask, uint8 * xormask)
1530  {  {
1531          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
1532          XColor bg, fg;          XColor bg, fg;
# Line 855  ui_create_cursor(unsigned int x, unsigne Line 1540  ui_create_cursor(unsigned int x, unsigne
1540          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1541          offset = scanline * height;          offset = scanline * height;
1542    
1543          cursor = xmalloc(offset);          cursor = (uint8 *) xmalloc(offset);
1544          memset(cursor, 0, offset);          memset(cursor, 0, offset);
1545    
1546          mask = xmalloc(offset);          mask = (uint8 *) xmalloc(offset);
1547          memset(mask, 0, offset);          memset(mask, 0, offset);
1548    
1549          /* approximate AND and XOR masks with a monochrome X pointer */          /* approximate AND and XOR masks with a monochrome X pointer */
# Line 899  ui_create_cursor(unsigned int x, unsigne Line 1584  ui_create_cursor(unsigned int x, unsigne
1584          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
1585          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
1586    
1587          xcursor = XCreatePixmapCursor(display, (Pixmap) cursorglyph,          xcursor =
1588                                        (Pixmap) maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1589                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1590    
1591          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
1592          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
# Line 912  ui_create_cursor(unsigned int x, unsigne Line 1598  ui_create_cursor(unsigned int x, unsigne
1598  void  void
1599  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
1600  {  {
1601          XDefineCursor(display, wnd, (Cursor) cursor);          g_current_cursor = (Cursor) cursor;
1602            XDefineCursor(g_display, g_wnd, g_current_cursor);
1603  }  }
1604    
1605  void  void
1606  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
1607  {  {
1608          XFreeCursor(display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
1609    }
1610    
1611    void
1612    ui_set_null_cursor(void)
1613    {
1614            ui_set_cursor(g_null_cursor);
1615  }  }
1616    
1617  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 927  ui_destroy_cursor(HCURSOR cursor) Line 1620  ui_destroy_cursor(HCURSOR cursor)
1620                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1621                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
1622    
1623    
1624  HCOLOURMAP  HCOLOURMAP
1625  ui_create_colourmap(COLOURMAP * colours)  ui_create_colourmap(COLOURMAP * colours)
1626  {  {
1627          COLOURENTRY *entry;          COLOURENTRY *entry;
1628          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1629            if (!g_owncolmap)
1630            {
1631                    uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1632                    XColor xentry;
1633                    XColor xc_cache[256];
1634                    uint32 colour;
1635                    int colLookup = 256;
1636                    for (i = 0; i < ncolours; i++)
1637                    {
1638                            entry = &colours->colours[i];
1639                            MAKE_XCOLOR(&xentry, entry);
1640    
1641                            if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1642                            {
1643                                    /* Allocation failed, find closest match. */
1644                                    int j = 256;
1645                                    int nMinDist = 3 * 256 * 256;
1646                                    long nDist = nMinDist;
1647    
1648                                    /* only get the colors once */
1649                                    while (colLookup--)
1650                                    {
1651                                            xc_cache[colLookup].pixel = colLookup;
1652                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1653                                                    xc_cache[colLookup].blue = 0;
1654                                            xc_cache[colLookup].flags = 0;
1655                                            XQueryColor(g_display,
1656                                                        DefaultColormap(g_display,
1657                                                                        DefaultScreen(g_display)),
1658                                                        &xc_cache[colLookup]);
1659                                    }
1660                                    colLookup = 0;
1661    
1662                                    /* approximate the pixel */
1663                                    while (j--)
1664                                    {
1665                                            if (xc_cache[j].flags)
1666                                            {
1667                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1668                                                             (long) (xentry.red >> 8)) *
1669                                                            ((long) (xc_cache[j].red >> 8) -
1670                                                             (long) (xentry.red >> 8)) +
1671                                                            ((long) (xc_cache[j].green >> 8) -
1672                                                             (long) (xentry.green >> 8)) *
1673                                                            ((long) (xc_cache[j].green >> 8) -
1674                                                             (long) (xentry.green >> 8)) +
1675                                                            ((long) (xc_cache[j].blue >> 8) -
1676                                                             (long) (xentry.blue >> 8)) *
1677                                                            ((long) (xc_cache[j].blue >> 8) -
1678                                                             (long) (xentry.blue >> 8));
1679                                            }
1680                                            if (nDist < nMinDist)
1681                                            {
1682                                                    nMinDist = nDist;
1683                                                    xentry.pixel = j;
1684                                            }
1685                                    }
1686                            }
1687                            colour = xentry.pixel;
1688    
1689                            /* update our cache */
1690                            if (xentry.pixel < 256)
1691                            {
1692                                    xc_cache[xentry.pixel].red = xentry.red;
1693                                    xc_cache[xentry.pixel].green = xentry.green;
1694                                    xc_cache[xentry.pixel].blue = xentry.blue;
1695    
1696          if (owncolmap)                          }
1697    
1698                            map[i] = colour;
1699                    }
1700                    return map;
1701            }
1702            else
1703          {          {
1704                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
1705                  Colormap map;                  Colormap map;
1706    
1707                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1708                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1709                  {                  {
1710                          entry = &colours->colours[i];                          entry = &colours->colours[i];
# Line 947  ui_create_colourmap(COLOURMAP * colours) Line 1713  ui_create_colourmap(COLOURMAP * colours)
1713                          MAKE_XCOLOR(xentry, entry);                          MAKE_XCOLOR(xentry, entry);
1714                  }                  }
1715    
1716                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1717                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
1718    
1719                  xfree(xcolours);                  xfree(xcolours);
1720                  return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
1721          }          }
         else  
         {  
                 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);  
                 XColor xentry;  
                 uint32 colour;  
   
                 for (i = 0; i < ncolours; i++)  
                 {  
                         entry = &colours->colours[i];  
                         MAKE_XCOLOR(&xentry, entry);  
   
                         if (XAllocColor(display, xcolmap, &xentry) != 0)  
                                 colour = xentry.pixel;  
                         else  
                                 colour = white;  
   
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
                 }  
   
                 return map;  
         }  
1722  }  }
1723    
1724  void  void
1725  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1726  {  {
1727          if (owncolmap)          if (!g_owncolmap)
                 XFreeColormap(display, (Colormap) map);  
         else  
1728                  xfree(map);                  xfree(map);
1729            else
1730                    XFreeColormap(g_display, (Colormap) map);
1731  }  }
1732    
1733  void  void
1734  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1735  {  {
1736          if (owncolmap)          if (!g_owncolmap)
1737                  XSetWindowColormap(display, wnd, (Colormap) map);          {
1738                    if (g_colmap)
1739                            xfree(g_colmap);
1740    
1741                    g_colmap = (uint32 *) map;
1742            }
1743          else          else
1744                  colmap = map;                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1745  }  }
1746    
1747  void  void
# Line 1004  ui_set_clip(int x, int y, int cx, int cy Line 1753  ui_set_clip(int x, int y, int cx, int cy
1753          rect.y = y;          rect.y = y;
1754          rect.width = cx;          rect.width = cx;
1755          rect.height = cy;          rect.height = cy;
1756          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1757  }  }
1758    
1759  void  void
1760  ui_reset_clip()  ui_reset_clip(void)
1761  {  {
1762          XRectangle rect;          XRectangle rect;
1763    
1764          rect.x = 0;          rect.x = 0;
1765          rect.y = 0;          rect.y = 0;
1766          rect.width = width;          rect.width = g_width;
1767          rect.height = height;          rect.height = g_height;
1768          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1769  }  }
1770    
1771  void  void
1772  ui_bell()  ui_bell(void)
1773  {  {
1774          XBell(display, 0);          XBell(g_display, 0);
1775  }  }
1776    
1777  void  void
# Line 1034  ui_destblt(uint8 opcode, Line 1783  ui_destblt(uint8 opcode,
1783          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1784  }  }
1785    
1786    static uint8 hatch_patterns[] = {
1787            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1788            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1789            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1790            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1791            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1792            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
1793    };
1794    
1795  void  void
1796  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1797            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
# Line 1048  ui_patblt(uint8 opcode, Line 1806  ui_patblt(uint8 opcode,
1806          {          {
1807                  case 0: /* Solid */                  case 0: /* Solid */
1808                          SET_FOREGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
1809                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1810                            break;
1811    
1812                    case 2: /* Hatch */
1813                            fill = (Pixmap) ui_create_glyph(8, 8,
1814                                                            hatch_patterns + brush->pattern[0] * 8);
1815                            SET_FOREGROUND(fgcolour);
1816                            SET_BACKGROUND(bgcolour);
1817                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1818                            XSetStipple(g_display, g_gc, fill);
1819                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1820                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1821                            XSetFillStyle(g_display, g_gc, FillSolid);
1822                            XSetTSOrigin(g_display, g_gc, 0, 0);
1823                            ui_destroy_glyph((HGLYPH) fill);
1824                          break;                          break;
1825    
1826                  case 3: /* Pattern */                  case 3: /* Pattern */
1827                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
1828                                  ipattern[7 - i] = brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
1829                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
   
1830                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
1831                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
1832                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1833                          XSetStipple(display, gc, fill);                          XSetStipple(g_display, g_gc, fill);
1834                          XSetTSOrigin(display, gc, brush->xorigin,                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1835                                       brush->yorigin);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1836                            XSetFillStyle(g_display, g_gc, FillSolid);
1837                          FILL_RECTANGLE(x, y, cx, cy);                          XSetTSOrigin(g_display, g_gc, 0, 0);
   
                         XSetFillStyle(display, gc, FillSolid);  
1838                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
1839                          break;                          break;
1840    
# Line 1074  ui_patblt(uint8 opcode, Line 1843  ui_patblt(uint8 opcode,
1843          }          }
1844    
1845          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1846    
1847            if (g_ownbackstore)
1848                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1849  }  }
1850    
1851  void  void
# Line 1082  ui_screenblt(uint8 opcode, Line 1854  ui_screenblt(uint8 opcode,
1854               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
1855  {  {
1856          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1857          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          if (g_ownbackstore)
1858          if (ownbackstore)          {
1859                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,                  if (g_Unobscured)
1860                            cx, cy, x, y);                  {
1861                            XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1862                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
1863                                      y);
1864                    }
1865                    else
1866                    {
1867                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1868                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
1869                                      y);
1870                    }
1871            }
1872            else
1873            {
1874                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1875            }
1876          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1877  }  }
1878    
# Line 1095  ui_memblt(uint8 opcode, Line 1882  ui_memblt(uint8 opcode,
1882            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1883  {  {
1884          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1885          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);
1886          if (ownbackstore)          if (g_ownbackstore)
1887                  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);  
1888          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1889  }  }
1890    
# Line 1115  ui_triblt(uint8 opcode, Line 1901  ui_triblt(uint8 opcode,
1901          {          {
1902                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1903                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1904                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1905                          break;                          break;
1906    
1907                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1908                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1909                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1910                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1911                          break;                          break;
1912    
1913                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
1914                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1915                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1916                          break;                          break;
1917    
1918                  default:                  default:
# Line 1146  ui_line(uint8 opcode, Line 1928  ui_line(uint8 opcode,
1928  {  {
1929          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1930          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
1931          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1932          if (ownbackstore)          if (g_ownbackstore)
1933                  XDrawLine(display, backstore, gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1934          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1935  }  }
1936    
# Line 1161  ui_rect( Line 1943  ui_rect(
1943          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
1944  }  }
1945    
1946    /* warning, this function only draws on wnd or backstore, not both */
1947  void  void
1948  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1949                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1950                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1951                int fgcolour)                int bgcolour, int fgcolour)
1952  {  {
1953          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
1954          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
1955    
1956          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(g_display, g_gc,
1957                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1958          XSetStipple(display, gc, (Pixmap) glyph);          XSetStipple(g_display, g_gc, (Pixmap) glyph);
1959          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(g_display, g_gc, x, y);
1960    
1961          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1962    
1963          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(g_display, g_gc, FillSolid);
1964  }  }
1965    
1966  #define DO_GLYPH(ttext,idx) \  #define DO_GLYPH(ttext,idx) \
1967  {\  {\
1968    glyph = cache_get_font (font, ttext[idx]);\    glyph = cache_get_font (font, ttext[idx]);\
1969    if (!(flags & TEXT2_IMPLICIT_X))\    if (!(flags & TEXT2_IMPLICIT_X))\
1970      {\
1971        xyoffset = ttext[++idx];\
1972        if ((xyoffset & 0x80))\
1973      {\      {\
1974        xyoffset = ttext[++idx];\        if (flags & TEXT2_VERTICAL)\
1975        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);\  
         }\  
1976        else\        else\
1977          {\          x += ttext[idx+1] | (ttext[idx+2] << 8);\
1978            if (flags & TEXT2_VERTICAL) \        idx += 2;\
             y += xyoffset;\  
           else\  
             x += xyoffset;\  
         }\  
1979      }\      }\
1980    if (glyph != NULL)\      else\
1981      {\      {\
1982        ui_draw_glyph (mixmode, x + (short) glyph->offset,\        if (flags & TEXT2_VERTICAL)\
1983                       y + (short) glyph->baseline,\          y += xyoffset;\
1984                       glyph->width, glyph->height,\        else\
1985                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\          x += xyoffset;\
       if (flags & TEXT2_IMPLICIT_X)\  
         x += glyph->width;\  
1986      }\      }\
1987      }\
1988      if (glyph != NULL)\
1989      {\
1990        x1 = x + glyph->offset;\
1991        y1 = y + glyph->baseline;\
1992        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
1993        XSetTSOrigin(g_display, g_gc, x1, y1);\
1994        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
1995        if (flags & TEXT2_IMPLICIT_X)\
1996          x += glyph->width;\
1997      }\
1998  }  }
1999    
2000  void  void
2001  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
2002               int clipx, int clipy, int clipcx, int clipcy, int boxx,               int clipx, int clipy, int clipcx, int clipcy,
2003               int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
2004               int fgcolour, uint8 * text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
2005  {  {
2006          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2007          int i, j, xyoffset;          int i, j, xyoffset, x1, y1;
2008          DATABLOB *entry;          DATABLOB *entry;
2009    
2010          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
2011    
2012            /* Sometimes, the boxcx value is something really large, like
2013               32691. This makes XCopyArea fail with Xvnc. The code below
2014               is a quick fix. */
2015            if (boxx + boxcx > g_width)
2016                    boxcx = g_width - boxx;
2017    
2018          if (boxcx > 1)          if (boxcx > 1)
2019          {          {
2020                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2021          }          }
2022          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
2023          {          {
2024                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2025          }          }
2026    
2027            SET_FOREGROUND(fgcolour);
2028            SET_BACKGROUND(bgcolour);
2029            XSetFillStyle(g_display, g_gc, FillStippled);
2030    
2031          /* Paint text, character by character */          /* Paint text, character by character */
2032          for (i = 0; i < length;)          for (i = 0; i < length;)
2033          {          {
# Line 1240  ui_draw_text(uint8 font, uint8 flags, in Line 2035  ui_draw_text(uint8 font, uint8 flags, in
2035                  {                  {
2036                          case 0xff:                          case 0xff:
2037                                  if (i + 2 < length)                                  if (i + 2 < length)
2038                                          cache_put_text(text[i + 1], text,                                          cache_put_text(text[i + 1], text, text[i + 2]);
                                                        text[i + 2]);  
2039                                  else                                  else
2040                                  {                                  {
2041                                          error("this shouldn't be happening\n");                                          error("this shouldn't be happening\n");
2042                                          break;                                          exit(1);
2043                                  }                                  }
2044                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2045                                  length -= i + 3;                                  length -= i + 3;
# Line 1258  ui_draw_text(uint8 font, uint8 flags, in Line 2052  ui_draw_text(uint8 font, uint8 flags, in
2052                                  if (entry != NULL)                                  if (entry != NULL)
2053                                  {                                  {
2054                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] ==
2055                                               0)                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
                                             && (!(flags & TEXT2_IMPLICIT_X)))  
2056                                          {                                          {
2057                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2058                                                          y += text[i + 2];                                                          y += text[i + 2];
2059                                                  else                                                  else
2060                                                          x += text[i + 2];                                                          x += text[i + 2];
2061                                          }                                          }
                                         if (i + 2 < length)  
                                                 i += 3;  
                                         else  
                                                 i += 2;  
                                         length -= i;  
                                         /* this will move pointer from start to first character after FE command */  
                                         text = &(text[i]);  
                                         i = 0;  
2062                                          for (j = 0; j < entry->size; j++)                                          for (j = 0; j < entry->size; j++)
2063                                                  DO_GLYPH(((uint8 *) (entry->                                                  DO_GLYPH(((uint8 *) (entry->data)), j);
                                                                      data)),  
                                                          j);  
2064                                  }                                  }
2065                                    if (i + 2 < length)
2066                                            i += 3;
2067                                    else
2068                                            i += 2;
2069                                    length -= i;
2070                                    /* this will move pointer from start to first character after FE command */
2071                                    text = &(text[i]);
2072                                    i = 0;
2073                                  break;                                  break;
2074    
2075                          default:                          default:
# Line 1288  ui_draw_text(uint8 font, uint8 flags, in Line 2079  ui_draw_text(uint8 font, uint8 flags, in
2079                  }                  }
2080          }          }
2081    
2082            XSetFillStyle(g_display, g_gc, FillSolid);
2083    
2084            if (g_ownbackstore)
2085            {
2086                    if (boxcx > 1)
2087                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2088                                      boxy, boxcx, boxcy, boxx, boxy);
2089                    else
2090                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2091                                      clipy, clipcx, clipcy, clipx, clipy);
2092            }
2093  }  }
2094    
2095  void  void
# Line 1297  ui_desktop_save(uint32 offset, int x, in Line 2098  ui_desktop_save(uint32 offset, int x, in
2098          Pixmap pix;          Pixmap pix;
2099          XImage *image;          XImage *image;
2100    
2101          if (ownbackstore)          if (g_ownbackstore)
2102          {          {
2103                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
2104          }          }
2105          else          else
2106          {          {
2107                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2108                  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);
2109                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2110                                    ZPixmap);                  XFreePixmap(g_display, pix);
                 XFreePixmap(display, pix);  
2111          }          }
2112    
2113          offset *= bpp / 8;          offset *= g_bpp / 8;
2114          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);  
2115    
2116          XDestroyImage(image);          XDestroyImage(image);
2117  }  }
# Line 1324  ui_desktop_restore(uint32 offset, int x, Line 2122  ui_desktop_restore(uint32 offset, int x,
2122          XImage *image;          XImage *image;
2123          uint8 *data;          uint8 *data;
2124    
2125          offset *= bpp / 8;          offset *= g_bpp / 8;
2126          data = cache_get_desktop(offset, cx, cy, bpp / 8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2127          if (data == NULL)          if (data == NULL)
2128                  return;                  return;
2129    
2130          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2131                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
                              cx * bpp / 8);  
2132    
2133          if (ownbackstore)          if (g_ownbackstore)
2134          {          {
2135                  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);
2136                  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);
2137          }          }
2138          else          else
2139          {          {
2140                  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);
2141          }          }
2142    
2143          XFree(image);          XFree(image);

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

  ViewVC Help
Powered by ViewVC 1.1.26