/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

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

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

Legend:
Removed from v.52  
changed lines
  Added in v.566

  ViewVC Help
Powered by ViewVC 1.1.26