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

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

  ViewVC Help
Powered by ViewVC 1.1.26