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

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

  ViewVC Help
Powered by ViewVC 1.1.26