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

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

  ViewVC Help
Powered by ViewVC 1.1.26