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

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

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26