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

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

  ViewVC Help
Powered by ViewVC 1.1.26