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

Diff of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26