/[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 754 by stargo, Mon Aug 23 11:28:23 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          if (display == NULL)          return (state & keysymMask) ? True : False;
755    }
756    
757    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                    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            xclip_init();
920    
921            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          width = (width + 3) & ~3;       /* make width a multiple of 32 bits */          if (g_null_cursor != NULL)
933                    ui_destroy_cursor(g_null_cursor);
934    
935          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          XFreeModifiermap(g_mod_map);
                             0, 0, width, height, 0, CopyFromParent,  
                             InputOutput, CopyFromParent,  
                             CWBackingStore | CWBackPixel | CWOverrideRedirect,  
                             &attribs);  
936    
937          XStoreName(display, wnd, title);          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[4] = { 0x00, 0x00, 0x00, 0x00 };
950            XSetWindowAttributes attribs;
951            XClassHint *classhints;
952            XSizeHints *sizehints;
953            int wndwidth, wndheight;
954            long input_mask, ic_input_mask;
955            XEvent xevent;
956    
957            wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
958            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
959    
960            attribs.background_pixel = BlackPixelOfScreen(g_screen);
961            attribs.border_pixel = WhitePixelOfScreen(g_screen);
962            attribs.backing_store = g_ownbackstore ? NotUseful : Always;
963            attribs.override_redirect = g_fullscreen;
964            attribs.colormap = g_xcolmap;
965    
966            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
967                                  0, g_depth, InputOutput, g_visual,
968                                  CWBackPixel | CWBackingStore | CWOverrideRedirect |
969                                  CWColormap | CWBorderPixel, &attribs);
970    
971            if (g_gc == NULL)
972                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
973    
974            if (g_create_bitmap_gc == NULL)
975                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
976    
977            if ((g_ownbackstore) && (g_backstore == 0))
978            {
979                    g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
980    
981                    /* clear to prevent rubbish being exposed at startup */
982                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
983                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
984            }
985    
986            XStoreName(g_display, g_wnd, g_title);
987    
988            if (g_hide_decorations)
989                    mwm_hide_decorations();
990    
991          classhints = XAllocClassHint();          classhints = XAllocClassHint();
992          if (classhints != NULL)          if (classhints != NULL)
993          {          {
994                  classhints->res_name = classhints->res_class = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
995                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(g_display, g_wnd, classhints);
996                  XFree(classhints);                  XFree(classhints);
997          }          }
998    
# Line 334  ui_create_window(char *title) Line 1000  ui_create_window(char *title)
1000          if (sizehints)          if (sizehints)
1001          {          {
1002                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1003                  sizehints->min_width = sizehints->max_width = width;                  sizehints->min_width = sizehints->max_width = g_width;
1004                  sizehints->min_height = sizehints->max_height = height;                  sizehints->min_height = sizehints->max_height = g_height;
1005                  XSetWMNormalHints(display, wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
1006                  XFree(sizehints);                  XFree(sizehints);
1007          }          }
1008    
1009          xkeymap_init();          if (g_embed_wnd)
1010            {
1011                    XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1012            }
1013    
1014          input_mask = KeyPressMask | KeyReleaseMask |          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1015                  ButtonPressMask | ButtonReleaseMask |                  VisibilityChangeMask | FocusChangeMask;
                 EnterWindowMask | LeaveWindowMask;  
         if (sendmotion)  
                 input_mask |= PointerMotionMask;  
1016    
1017          if (ownbackstore)          if (g_sendmotion)
1018                    input_mask |= PointerMotionMask;
1019            if (g_ownbackstore)
1020                  input_mask |= ExposureMask;                  input_mask |= ExposureMask;
1021            if (g_fullscreen || g_grab_keyboard)
1022                    input_mask |= EnterWindowMask;
1023            if (g_grab_keyboard)
1024                    input_mask |= LeaveWindowMask;
1025    
1026          XSelectInput(display, wnd, input_mask);          if (g_IM != NULL)
1027          gc = XCreateGC(display, wnd, 0, NULL);          {
1028                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1029                                     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1030    
1031          if (ownbackstore)                  if ((g_IC != NULL)
1032                  backstore = XCreatePixmap(display, wnd, width, height, depth);                      && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1033                            input_mask |= ic_input_mask;
1034            }
1035    
1036          XMapWindow(display, wnd);          XSelectInput(g_display, g_wnd, input_mask);
1037            XMapWindow(g_display, g_wnd);
1038    
1039          /* TODO: error texts... make them friendly. */          /* wait for VisibilityNotify */
1040          xkb = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);          do
         if ((int) xkb == BadAlloc || xkb == NULL)  
1041          {          {
1042                  error("XkbGetKeyboard failed.\n");                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);
                 exit(0);  
1043          }          }
1044            while (xevent.type != VisibilityNotify);
1045            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1046    
1047          /* TODO: error texts... make them friendly. */          g_focused = False;
1048          if (XkbSelectEvents          g_mouse_in_wnd = False;
1049              (display, xkb->device_spec, XkbAllEventsMask,  
1050               XkbAllEventsMask) == False)          /* handle the WM_DELETE_WINDOW protocol */
1051          {          g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1052                  error("XkbSelectEvents failed.\n");          g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1053                  exit(0);          XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
         }  
1054    
1055          xwin_get_numlock_mask();          /* create invisible 1x1 cursor to be used as null cursor */
1056            if (g_null_cursor == NULL)
1057                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1058    
1059          return True;          return True;
1060  }  }
1061    
1062  void  void
1063  xwin_get_numlock_mask()  ui_resize_window()
1064  {  {
1065          KeyCode numlockcode;          XSizeHints *sizehints;
1066          KeyCode *keycode;          Pixmap bs;
         XModifierKeymap *modmap;  
         int i, j;  
1067    
1068          /* Find out if numlock is already defined as a modifier key, and if so where */          sizehints = XAllocSizeHints();
1069          numlockcode = XKeysymToKeycode(display, 0xFF7F);        /* XF_Num_Lock = 0xFF7F */          if (sizehints)
1070          if (numlockcode)          {
1071          {                  sizehints->flags = PMinSize | PMaxSize;
1072                  modmap = XGetModifierMapping(display);                  sizehints->min_width = sizehints->max_width = g_width;
1073                  if (modmap)                  sizehints->min_height = sizehints->max_height = g_height;
1074                  {                  XSetWMNormalHints(g_display, g_wnd, sizehints);
1075                          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);  
                 }  
1076          }          }
1077    
1078          if (!numlock_modifier_mask)          if (!(g_fullscreen || g_embed_wnd))
1079                  printf("WARNING: Failed to get a numlock modifier mapping.\n");          {
1080                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1081            }
1082    
1083            /* create new backstore pixmap */
1084            if (g_backstore != 0)
1085            {
1086                    bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1087                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1088                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1089                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1090                    XFreePixmap(g_display, g_backstore);
1091                    g_backstore = bs;
1092            }
1093  }  }
1094    
1095  void  void
1096  ui_destroy_window()  ui_destroy_window(void)
1097  {  {
1098          if (xkb != NULL)          if (g_IC != NULL)
1099                  XkbFreeKeyboard(xkb, XkbAllControlsMask, True);                  XDestroyIC(g_IC);
1100    
1101          if (ownbackstore)          XDestroyWindow(g_display, g_wnd);
1102                  XFreePixmap(display, backstore);  }
1103    
1104          XFreeGC(display, gc);  void
1105          XDestroyWindow(display, wnd);  xwin_toggle_fullscreen(void)
1106          XCloseDisplay(display);  {
1107          display = NULL;          Pixmap contents = 0;
1108    
1109            if (!g_ownbackstore)
1110            {
1111                    /* need to save contents of window */
1112                    contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1113                    XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1114            }
1115    
1116            ui_destroy_window();
1117            g_fullscreen = !g_fullscreen;
1118            ui_create_window();
1119    
1120            XDefineCursor(g_display, g_wnd, g_current_cursor);
1121    
1122            if (!g_ownbackstore)
1123            {
1124                    XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1125                    XFreePixmap(g_display, contents);
1126            }
1127  }  }
1128    
1129  static void  /* Process all events in Xlib queue
1130  xwin_process_events()     Returns 0 after user quit, 1 otherwise */
1131    static int
1132    xwin_process_events(void)
1133  {  {
1134          XEvent xevent;          XEvent xevent;
   
1135          KeySym keysym;          KeySym keysym;
         uint8 scancode;  
1136          uint16 button, flags;          uint16 button, flags;
1137          uint32 ev_time;          uint32 ev_time;
1138          uint32 tmpmods;          key_translation tr;
1139            char str[256];
1140            Status status;
1141    
1142          while (XCheckMaskEvent(display, ~0, &xevent))          while (XPending(g_display) > 0)
1143          {          {
1144                  ev_time = time(NULL);                  XNextEvent(g_display, &xevent);
                 flags = 0;  
1145    
1146                  switch (xevent.type)                  if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1147                  {                  {
1148                          case KeyRelease:                          DEBUG_KBD(("Filtering event\n"));
1149                                  flags = KBD_FLAG_DOWN | KBD_FLAG_UP;                          continue;
1150                                  /* 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 */  
1151    
1152                          case ButtonRelease:                  flags = 0;
                                 button = xkeymap_translate_button(xevent.  
                                                                   xbutton.  
                                                                   button);  
                                 if (button == 0)  
                                         break;  
1153    
1154                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                  switch (xevent.type)
1155                                                 flags | button,                  {
1156                                                 xevent.xbutton.x,                          case VisibilityNotify:
1157                                                 xevent.xbutton.y);                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1158                                  break;                                  break;
1159                            case ClientMessage:
1160                          case MotionNotify:                                  /* the window manager told us to quit */
1161                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if ((xevent.xclient.message_type == g_protocol_atom)
1162                                                 MOUSE_FLAG_MOVE,                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1163                                                 xevent.xmotion.x,                                          /* Quit */
1164                                                 xevent.xmotion.y);                                          return 0;
1165                                  break;                                  break;
1166    
1167                          case EnterNotify:                          case KeyPress:
1168                                  XGrabKeyboard(display, wnd, True,                                  g_last_gesturetime = xevent.xkey.time;
1169                                                GrabModeAsync, GrabModeAsync,                                  if (g_IC != NULL)
1170                                                CurrentTime);                                          /* Multi_key compatible version */
1171                                    {
1172                                  xwin_mod_update(xevent.xcrossing.state,                                          XmbLookupString(g_IC,
1173                                                  ev_time);                                                          &xevent.xkey, str, sizeof(str), &keysym,
1174                                  break;                                                          &status);
1175                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1176                          case LeaveNotify:                                          {
1177                                  XUngrabKeyboard(display, CurrentTime);                                                  error("XmbLookupString failed with status 0x%x\n",
1178                                  break;                                                        status);
1179                                                    break;
1180                                            }
1181                                    }
1182                                    else
1183                                    {
1184                                            /* Plain old XLookupString */
1185                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1186                                            XLookupString((XKeyEvent *) & xevent,
1187                                                          str, sizeof(str), &keysym, NULL);
1188                                    }
1189    
1190                          case Expose:                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1191                                  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;  
                 }  
         }  
 }  
1192    
1193  void                                  ev_time = time(NULL);
1194  xwin_mod_update(uint32 state, uint32 ev_time)                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1195  {                                          break;
         xwin_mod_press(state, ev_time, 0);  
         xwin_mod_release(state, ev_time, 0);  
 }  
1196    
1197  void                                  tr = xkeymap_translate_key(keysym,
1198  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;  
         }  
1199    
1200          if (!(numlock_modifier_mask & state)                                  if (tr.scancode == 0)
1201              && (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;  
         }  
1202    
1203          if (!(LockMask & state) && (key_down_state & DLockMask))                                  save_remote_modifiers(tr.scancode);
1204          {                                  ensure_remote_modifiers(ev_time, tr);
1205                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);                                  rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1206                  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;  
1207    
1208          }                                  break;
1209    
1210                            case KeyRelease:
1211                                    g_last_gesturetime = xevent.xkey.time;
1212                                    XLookupString((XKeyEvent *) & xevent, str,
1213                                                  sizeof(str), &keysym, NULL);
1214    
1215          if (!(ShiftMask & state) && (key_down_state & DShift1Mask))                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1216          {                                             get_ksname(keysym)));
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a,  
                                0);  
                 key_down_state &= ~DShift1Mask;  
1217    
1218          }                                  ev_time = time(NULL);
1219                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1220                                            break;
1221    
1222          if (!(ControlMask & state) && (key_down_state & DControl1Mask))                                  tr = xkeymap_translate_key(keysym,
1223          {                                                             xevent.xkey.keycode, xevent.xkey.state);
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d,  
                                0);  
                 key_down_state &= ~DControl1Mask;  
1224    
1225          }                                  if (tr.scancode == 0)
1226                                            break;
1227    
1228          if (!(Mod1Mask & state) && (key_down_state & DMod1Mask))                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
1229          {                                  break;
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38,  
                                0);  
                 key_down_state &= ~DMod1Mask;  
1230    
1231          }                          case ButtonPress:
1232                                    flags = MOUSE_FLAG_DOWN;
1233                                    /* fall through */
1234    
1235          if (!(Mod2Mask & state) && (key_down_state & DMod2Mask))                          case ButtonRelease:
1236          {                                  g_last_gesturetime = xevent.xbutton.time;
1237                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8,                                  button = xkeymap_translate_button(xevent.xbutton.button);
1238                                 0);                                  if (button == 0)
1239                  key_down_state &= ~DMod2Mask;                                          break;
         }  
 }  
1240    
1241                                    /* If win_button_size is nonzero, enable single app mode */
1242                                    if (xevent.xbutton.y < g_win_button_size)
1243                                    {
1244                                            /* Stop moving window when button is released, regardless of cursor position */
1245                                            if (g_moving_wnd && (xevent.type == ButtonRelease))
1246                                                    g_moving_wnd = False;
1247    
1248  void                                          /*  Check from right to left: */
 xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode)  
 {  
1249    
1250          switch (scancode)                                          if (xevent.xbutton.x >= g_width - g_win_button_size)
1251          {                                          {
1252                  case 0x2a:                                                  /* The close button, continue */
1253                          key_down_state |= DShift1Mask;                                                  ;
1254                          break;                                          }
1255                  case 0x36:                                          else if (xevent.xbutton.x >=
1256                          key_down_state |= DShift2Mask;                                                   g_width - g_win_button_size * 2)
1257                          break;                                          {
1258                  case 0x1d:                                                  /* The maximize/restore button. Do not send to
1259                          key_down_state |= DControl1Mask;                                                     server.  It might be a good idea to change the
1260                          break;                                                     cursor or give some other visible indication
1261                  case 0x9d:                                                     that rdesktop inhibited this click */
1262                          key_down_state |= DControl2Mask;                                                  break;
1263                          break;                                          }
1264                  case 0x3a:                                          else if (xevent.xbutton.x >=
1265                          key_down_state ^= DLockMask;                                                   g_width - g_win_button_size * 3)
1266                          break;                                          {
1267                  case 0x45:                                                  /* The minimize button. Iconify window. */
1268                          key_down_state ^= DNumLockMask;                                                  XIconifyWindow(g_display, g_wnd,
1269                          break;                                                                 DefaultScreen(g_display));
1270                  case 0x38:                                                  break;
1271                          key_down_state |= DMod1Mask;                                          }
1272                          break;                                          else if (xevent.xbutton.x <= g_win_button_size)
1273                  case 0xb8:                                          {
1274                          key_down_state |= DMod2Mask;                                                  /* The system menu. Ignore. */
1275                          break;                                                  break;
1276          }                                          }
1277                                            else
1278                                            {
1279                                                    /* The title bar. */
1280                                                    if ((xevent.type == ButtonPress) && !g_fullscreen
1281                                                        && g_hide_decorations)
1282                                                    {
1283                                                            g_moving_wnd = True;
1284                                                            g_move_x_offset = xevent.xbutton.x;
1285                                                            g_move_y_offset = xevent.xbutton.y;
1286                                                    }
1287                                                    break;
1288    
1289          if ((numlock_modifier_mask && state)                                          }
1290              && !(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;  
         }  
1291    
1292          if ((LockMask & state) && !(key_down_state & DLockMask))                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1293          {                                                 flags | button, xevent.xbutton.x, xevent.xbutton.y);
1294                  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;  
1295    
1296          }                          case MotionNotify:
1297                                    if (g_moving_wnd)
1298                                    {
1299                                            XMoveWindow(g_display, g_wnd,
1300                                                        xevent.xmotion.x_root - g_move_x_offset,
1301                                                        xevent.xmotion.y_root - g_move_y_offset);
1302                                            break;
1303                                    }
1304    
1305                                    if (g_fullscreen && !g_focused)
1306                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1307                                                           CurrentTime);
1308                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1309                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1310                                    break;
1311    
1312          if ((ShiftMask & state)                          case FocusIn:
1313              && !((key_down_state & DShift1Mask)                                  if (xevent.xfocus.mode == NotifyGrab)
1314                   || (key_down_state & DShift2Mask)))                                          break;
1315          {                                  g_focused = True;
1316                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,                                  reset_modifier_keys();
1317                                 0x2a, 0);                                  if (g_grab_keyboard && g_mouse_in_wnd)
1318                  key_down_state |= DShift1Mask;                                          XGrabKeyboard(g_display, g_wnd, True,
1319                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1320                                    break;
1321    
1322          }                          case FocusOut:
1323                                    if (xevent.xfocus.mode == NotifyUngrab)
1324                                            break;
1325                                    g_focused = False;
1326                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1327                                            XUngrabKeyboard(g_display, CurrentTime);
1328                                    break;
1329    
1330          if ((ControlMask & state)                          case EnterNotify:
1331              && !((key_down_state & DControl1Mask)                                  /* we only register for this event when in fullscreen mode */
1332                   || (key_down_state & DControl2Mask)))                                  /* or grab_keyboard */
1333          {                                  g_mouse_in_wnd = True;
1334                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,                                  if (g_fullscreen)
1335                                 0x1d, 0);                                  {
1336                  key_down_state |= DControl1Mask;                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1337                                                           CurrentTime);
1338                                            break;
1339                                    }
1340                                    if (g_focused)
1341                                            XGrabKeyboard(g_display, g_wnd, True,
1342                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1343                                    break;
1344    
1345          }                          case LeaveNotify:
1346                                    /* we only register for this event when grab_keyboard */
1347                                    g_mouse_in_wnd = False;
1348                                    XUngrabKeyboard(g_display, CurrentTime);
1349                                    break;
1350    
1351          if ((Mod1Mask & state) && !(key_down_state & DMod1Mask))                          case Expose:
1352          {                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1353                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,                                            xevent.xexpose.x, xevent.xexpose.y,
1354                                 0x38, 0);                                            xevent.xexpose.width,
1355                  key_down_state |= DMod1Mask;                                            xevent.xexpose.height,
1356                                              xevent.xexpose.x, xevent.xexpose.y);
1357                                    break;
1358    
1359          }                          case MappingNotify:
1360                                    /* Refresh keyboard mapping if it has changed. This is important for
1361                                       Xvnc, since it allocates keycodes dynamically */
1362                                    if (xevent.xmapping.request == MappingKeyboard
1363                                        || xevent.xmapping.request == MappingModifier)
1364                                            XRefreshKeyboardMapping(&xevent.xmapping);
1365    
1366          if ((Mod2Mask & state) && !(key_down_state & DMod2Mask))                                  if (xevent.xmapping.request == MappingModifier)
1367          {                                  {
1368                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,                                          XFreeModifiermap(g_mod_map);
1369                                 0xb8, 0);                                          g_mod_map = XGetModifierMapping(g_display);
1370                  key_down_state |= DMod2Mask;                                  }
1371                                    break;
1372    
1373                                    /* clipboard stuff */
1374                            case SelectionNotify:
1375                                    xclip_handle_SelectionNotify(&xevent.xselection);
1376                                    break;
1377                            case SelectionRequest:
1378                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1379                                    break;
1380                            case SelectionClear:
1381                                    xclip_handle_SelectionClear();
1382                                    break;
1383                            case PropertyNotify:
1384                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1385                                    break;
1386                    }
1387          }          }
1388            /* Keep going */
1389            return 1;
1390  }  }
1391    
1392  void  /* Returns 0 after user quit, 1 otherwise */
1393    int
1394  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1395  {  {
1396          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;          int n;
1397          fd_set rfds;          fd_set rfds, wfds;
1398            struct timeval tv;
1399          FD_ZERO(&rfds);          BOOL s_timeout = False;
1400    
1401          while (True)          while (True)
1402          {          {
1403                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1404                    /* Process any events already waiting */
1405                    if (!xwin_process_events())
1406                            /* User quit */
1407                            return 0;
1408    
1409                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
1410                    FD_ZERO(&wfds);
1411                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
1412                  if (display != NULL)                  FD_SET(g_x_socket, &rfds);
1413    
1414    #ifdef WITH_RDPSND
1415                    /* FIXME: there should be an API for registering fds */
1416                    if (g_dsp_busy)
1417                  {                  {
1418                          FD_SET(x_socket, &rfds);                          FD_SET(g_dsp_fd, &wfds);
1419                          XFlush(display);                          n = (g_dsp_fd > n) ? g_dsp_fd : n;
1420                  }                  }
1421    #endif
1422                    /* default timeout */
1423                    tv.tv_sec = 60;
1424                    tv.tv_usec = 0;
1425    
1426                    /* add redirection handles */
1427                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1428    
1429                    n++;
1430    
1431                  switch (select(n, &rfds, NULL, NULL, NULL))                  switch (select(n, &rfds, &wfds, NULL, &tv))
1432                  {                  {
1433                          case -1:                          case -1:
1434                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
1435    
1436                          case 0:                          case 0:
1437                                    /* TODO: if tv.tv_sec just times out
1438                                     * we will segfault.
1439                                     * FIXME:
1440                                     */
1441                                    //s_timeout = True;
1442                                    //rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1443                                  continue;                                  continue;
1444                  }                  }
1445    
1446                  if (FD_ISSET(x_socket, &rfds))                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
                         xwin_process_events();  
1447    
1448                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1449                          return;                          return 1;
1450    
1451    #ifdef WITH_RDPSND
1452                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1453                            wave_out_play();
1454    #endif
1455          }          }
1456  }  }
1457    
1458  void  void
1459  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
1460  {  {
1461          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1462  }  }
1463    
1464  HBITMAP  HBITMAP
# Line 761  ui_create_bitmap(int width, int height, Line 1467  ui_create_bitmap(int width, int height,
1467          XImage *image;          XImage *image;
1468          Pixmap bitmap;          Pixmap bitmap;
1469          uint8 *tdata;          uint8 *tdata;
1470            int bitmap_pad;
1471    
1472            if (g_server_bpp == 8)
1473            {
1474                    bitmap_pad = 8;
1475            }
1476            else
1477            {
1478                    bitmap_pad = g_bpp;
1479    
1480          tdata = (owncolmap ? data : translate_image(width, height, data));                  if (g_bpp == 24)
1481          bitmap = XCreatePixmap(display, wnd, width, height, depth);                          bitmap_pad = 32;
1482          image = XCreateImage(display, visual, depth, ZPixmap,          }
                              0, tdata, width, height, 8, 0);  
1483    
1484          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1485            bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1486            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1487                                 (char *) tdata, width, height, bitmap_pad, 0);
1488    
1489            XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
1490    
1491          XFree(image);          XFree(image);
1492          if (!owncolmap)          if (tdata != data)
1493                  xfree(tdata);                  xfree(tdata);
1494          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1495  }  }
1496    
1497  void  void
1498  ui_paint_bitmap(int x, int y, int cx, int cy,  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
                 int width, int height, uint8 * data)  
1499  {  {
1500          XImage *image;          XImage *image;
1501          uint8 *tdata;          uint8 *tdata;
1502            int bitmap_pad;
1503    
1504            if (g_server_bpp == 8)
1505            {
1506                    bitmap_pad = 8;
1507            }
1508            else
1509            {
1510                    bitmap_pad = g_bpp;
1511    
1512                    if (g_bpp == 24)
1513                            bitmap_pad = 32;
1514            }
1515    
1516          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1517          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1518                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
1519    
1520          if (ownbackstore)          if (g_ownbackstore)
1521          {          {
1522                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1523                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1524          }          }
1525          else          else
1526          {          {
1527                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1528          }          }
1529    
1530          XFree(image);          XFree(image);
1531          if (!owncolmap)          if (tdata != data)
1532                  xfree(tdata);                  xfree(tdata);
1533  }  }
1534    
1535  void  void
1536  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1537  {  {
1538          XFreePixmap(display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
1539  }  }
1540    
1541  HGLYPH  HGLYPH
# Line 813  ui_create_glyph(int width, int height, u Line 1544  ui_create_glyph(int width, int height, u
1544          XImage *image;          XImage *image;
1545          Pixmap bitmap;          Pixmap bitmap;
1546          int scanline;          int scanline;
         GC gc;  
1547    
1548          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1549    
1550          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1551          gc = XCreateGC(display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
1552                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1553    
1554          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1555                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1556          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1557          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1558          XInitImage(image);          XInitImage(image);
1559    
1560          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
1561    
1562          XFree(image);          XFree(image);
         XFreeGC(display, gc);  
1563          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1564  }  }
1565    
1566  void  void
1567  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1568  {  {
1569          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
1570  }  }
1571    
1572  HCURSOR  HCURSOR
1573  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1574                   int height, uint8 * andmask, uint8 * xormask)                   uint8 * andmask, uint8 * xormask)
1575  {  {
1576          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
1577          XColor bg, fg;          XColor bg, fg;
# Line 855  ui_create_cursor(unsigned int x, unsigne Line 1585  ui_create_cursor(unsigned int x, unsigne
1585          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1586          offset = scanline * height;          offset = scanline * height;
1587    
1588          cursor = xmalloc(offset);          cursor = (uint8 *) xmalloc(offset);
1589          memset(cursor, 0, offset);          memset(cursor, 0, offset);
1590    
1591          mask = xmalloc(offset);          mask = (uint8 *) xmalloc(offset);
1592          memset(mask, 0, offset);          memset(mask, 0, offset);
1593    
1594          /* approximate AND and XOR masks with a monochrome X pointer */          /* approximate AND and XOR masks with a monochrome X pointer */
# Line 899  ui_create_cursor(unsigned int x, unsigne Line 1629  ui_create_cursor(unsigned int x, unsigne
1629          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
1630          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
1631    
1632          xcursor = XCreatePixmapCursor(display, (Pixmap) cursorglyph,          xcursor =
1633                                        (Pixmap) maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1634                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1635    
1636          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
1637          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
# Line 912  ui_create_cursor(unsigned int x, unsigne Line 1643  ui_create_cursor(unsigned int x, unsigne
1643  void  void
1644  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
1645  {  {
1646          XDefineCursor(display, wnd, (Cursor) cursor);          g_current_cursor = (Cursor) cursor;
1647            XDefineCursor(g_display, g_wnd, g_current_cursor);
1648  }  }
1649    
1650  void  void
1651  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
1652  {  {
1653          XFreeCursor(display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
1654    }
1655    
1656    void
1657    ui_set_null_cursor(void)
1658    {
1659            ui_set_cursor(g_null_cursor);
1660  }  }
1661    
1662  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 927  ui_destroy_cursor(HCURSOR cursor) Line 1665  ui_destroy_cursor(HCURSOR cursor)
1665                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1666                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
1667    
1668    
1669  HCOLOURMAP  HCOLOURMAP
1670  ui_create_colourmap(COLOURMAP * colours)  ui_create_colourmap(COLOURMAP * colours)
1671  {  {
1672          COLOURENTRY *entry;          COLOURENTRY *entry;
1673          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1674            if (!g_owncolmap)
1675            {
1676                    uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1677                    XColor xentry;
1678                    XColor xc_cache[256];
1679                    uint32 colour;
1680                    int colLookup = 256;
1681                    for (i = 0; i < ncolours; i++)
1682                    {
1683                            entry = &colours->colours[i];
1684                            MAKE_XCOLOR(&xentry, entry);
1685    
1686          if (owncolmap)                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1687                            {
1688                                    /* Allocation failed, find closest match. */
1689                                    int j = 256;
1690                                    int nMinDist = 3 * 256 * 256;
1691                                    long nDist = nMinDist;
1692    
1693                                    /* only get the colors once */
1694                                    while (colLookup--)
1695                                    {
1696                                            xc_cache[colLookup].pixel = colLookup;
1697                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1698                                                    xc_cache[colLookup].blue = 0;
1699                                            xc_cache[colLookup].flags = 0;
1700                                            XQueryColor(g_display,
1701                                                        DefaultColormap(g_display,
1702                                                                        DefaultScreen(g_display)),
1703                                                        &xc_cache[colLookup]);
1704                                    }
1705                                    colLookup = 0;
1706    
1707                                    /* approximate the pixel */
1708                                    while (j--)
1709                                    {
1710                                            if (xc_cache[j].flags)
1711                                            {
1712                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1713                                                             (long) (xentry.red >> 8)) *
1714                                                            ((long) (xc_cache[j].red >> 8) -
1715                                                             (long) (xentry.red >> 8)) +
1716                                                            ((long) (xc_cache[j].green >> 8) -
1717                                                             (long) (xentry.green >> 8)) *
1718                                                            ((long) (xc_cache[j].green >> 8) -
1719                                                             (long) (xentry.green >> 8)) +
1720                                                            ((long) (xc_cache[j].blue >> 8) -
1721                                                             (long) (xentry.blue >> 8)) *
1722                                                            ((long) (xc_cache[j].blue >> 8) -
1723                                                             (long) (xentry.blue >> 8));
1724                                            }
1725                                            if (nDist < nMinDist)
1726                                            {
1727                                                    nMinDist = nDist;
1728                                                    xentry.pixel = j;
1729                                            }
1730                                    }
1731                            }
1732                            colour = xentry.pixel;
1733    
1734                            /* update our cache */
1735                            if (xentry.pixel < 256)
1736                            {
1737                                    xc_cache[xentry.pixel].red = xentry.red;
1738                                    xc_cache[xentry.pixel].green = xentry.green;
1739                                    xc_cache[xentry.pixel].blue = xentry.blue;
1740    
1741                            }
1742    
1743                            map[i] = colour;
1744                    }
1745                    return map;
1746            }
1747            else
1748          {          {
1749                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
1750                  Colormap map;                  Colormap map;
1751    
1752                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1753                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1754                  {                  {
1755                          entry = &colours->colours[i];                          entry = &colours->colours[i];
# Line 947  ui_create_colourmap(COLOURMAP * colours) Line 1758  ui_create_colourmap(COLOURMAP * colours)
1758                          MAKE_XCOLOR(xentry, entry);                          MAKE_XCOLOR(xentry, entry);
1759                  }                  }
1760    
1761                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1762                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
1763    
1764                  xfree(xcolours);                  xfree(xcolours);
1765                  return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
1766          }          }
         else  
         {  
                 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);  
                 XColor xentry;  
                 uint32 colour;  
   
                 for (i = 0; i < ncolours; i++)  
                 {  
                         entry = &colours->colours[i];  
                         MAKE_XCOLOR(&xentry, entry);  
   
                         if (XAllocColor(display, xcolmap, &xentry) != 0)  
                                 colour = xentry.pixel;  
                         else  
                                 colour = white;  
   
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
                 }  
   
                 return map;  
         }  
1767  }  }
1768    
1769  void  void
1770  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1771  {  {
1772          if (owncolmap)          if (!g_owncolmap)
                 XFreeColormap(display, (Colormap) map);  
         else  
1773                  xfree(map);                  xfree(map);
1774            else
1775                    XFreeColormap(g_display, (Colormap) map);
1776  }  }
1777    
1778  void  void
1779  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1780  {  {
1781          if (owncolmap)          if (!g_owncolmap)
1782                  XSetWindowColormap(display, wnd, (Colormap) map);          {
1783                    if (g_colmap)
1784                            xfree(g_colmap);
1785    
1786                    g_colmap = (uint32 *) map;
1787            }
1788          else          else
1789                  colmap = map;                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1790  }  }
1791    
1792  void  void
# Line 1004  ui_set_clip(int x, int y, int cx, int cy Line 1798  ui_set_clip(int x, int y, int cx, int cy
1798          rect.y = y;          rect.y = y;
1799          rect.width = cx;          rect.width = cx;
1800          rect.height = cy;          rect.height = cy;
1801          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1802  }  }
1803    
1804  void  void
1805  ui_reset_clip()  ui_reset_clip(void)
1806  {  {
1807          XRectangle rect;          XRectangle rect;
1808    
1809          rect.x = 0;          rect.x = 0;
1810          rect.y = 0;          rect.y = 0;
1811          rect.width = width;          rect.width = g_width;
1812          rect.height = height;          rect.height = g_height;
1813          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1814  }  }
1815    
1816  void  void
1817  ui_bell()  ui_bell(void)
1818  {  {
1819          XBell(display, 0);          XBell(g_display, 0);
1820  }  }
1821    
1822  void  void
# Line 1034  ui_destblt(uint8 opcode, Line 1828  ui_destblt(uint8 opcode,
1828          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1829  }  }
1830    
1831    static uint8 hatch_patterns[] = {
1832            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1833            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1834            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1835            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1836            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1837            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
1838    };
1839    
1840  void  void
1841  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1842            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
# Line 1048  ui_patblt(uint8 opcode, Line 1851  ui_patblt(uint8 opcode,
1851          {          {
1852                  case 0: /* Solid */                  case 0: /* Solid */
1853                          SET_FOREGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
1854                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1855                            break;
1856    
1857                    case 2: /* Hatch */
1858                            fill = (Pixmap) ui_create_glyph(8, 8,
1859                                                            hatch_patterns + brush->pattern[0] * 8);
1860                            SET_FOREGROUND(fgcolour);
1861                            SET_BACKGROUND(bgcolour);
1862                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1863                            XSetStipple(g_display, g_gc, fill);
1864                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1865                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1866                            XSetFillStyle(g_display, g_gc, FillSolid);
1867                            XSetTSOrigin(g_display, g_gc, 0, 0);
1868                            ui_destroy_glyph((HGLYPH) fill);
1869                          break;                          break;
1870    
1871                  case 3: /* Pattern */                  case 3: /* Pattern */
1872                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
1873                                  ipattern[7 - i] = brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
1874                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
   
1875                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
1876                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
1877                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1878                          XSetStipple(display, gc, fill);                          XSetStipple(g_display, g_gc, fill);
1879                          XSetTSOrigin(display, gc, brush->xorigin,                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1880                                       brush->yorigin);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1881                            XSetFillStyle(g_display, g_gc, FillSolid);
1882                          FILL_RECTANGLE(x, y, cx, cy);                          XSetTSOrigin(g_display, g_gc, 0, 0);
   
                         XSetFillStyle(display, gc, FillSolid);  
1883                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
1884                          break;                          break;
1885    
# Line 1074  ui_patblt(uint8 opcode, Line 1888  ui_patblt(uint8 opcode,
1888          }          }
1889    
1890          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1891    
1892            if (g_ownbackstore)
1893                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1894  }  }
1895    
1896  void  void
# Line 1082  ui_screenblt(uint8 opcode, Line 1899  ui_screenblt(uint8 opcode,
1899               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
1900  {  {
1901          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1902          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          if (g_ownbackstore)
1903          if (ownbackstore)          {
1904                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,                  if (g_Unobscured)
1905                            cx, cy, x, y);                  {
1906                            XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1907                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
1908                                      y);
1909                    }
1910                    else
1911                    {
1912                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1913                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
1914                                      y);
1915                    }
1916            }
1917            else
1918            {
1919                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1920            }
1921          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1922  }  }
1923    
# Line 1095  ui_memblt(uint8 opcode, Line 1927  ui_memblt(uint8 opcode,
1927            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1928  {  {
1929          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1930          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1931          if (ownbackstore)          if (g_ownbackstore)
1932                  XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy,                  XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1933          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1934  }  }
1935    
# Line 1115  ui_triblt(uint8 opcode, Line 1946  ui_triblt(uint8 opcode,
1946          {          {
1947                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1948                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1949                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1950                          break;                          break;
1951    
1952                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1953                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1954                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1955                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1956                          break;                          break;
1957    
1958                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
1959                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1960                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1961                          break;                          break;
1962    
1963                  default:                  default:
# Line 1146  ui_line(uint8 opcode, Line 1973  ui_line(uint8 opcode,
1973  {  {
1974          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1975          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
1976          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1977          if (ownbackstore)          if (g_ownbackstore)
1978                  XDrawLine(display, backstore, gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1979          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1980  }  }
1981    
# Line 1161  ui_rect( Line 1988  ui_rect(
1988          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
1989  }  }
1990    
1991    /* warning, this function only draws on wnd or backstore, not both */
1992  void  void
1993  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1994                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1995                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1996                int fgcolour)                int bgcolour, int fgcolour)
1997  {  {
1998          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
1999          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
2000    
2001          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(g_display, g_gc,
2002                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2003          XSetStipple(display, gc, (Pixmap) glyph);          XSetStipple(g_display, g_gc, (Pixmap) glyph);
2004          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(g_display, g_gc, x, y);
2005    
2006          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2007    
2008          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(g_display, g_gc, FillSolid);
2009  }  }
2010    
2011  #define DO_GLYPH(ttext,idx) \  #define DO_GLYPH(ttext,idx) \
2012  {\  {\
2013    glyph = cache_get_font (font, ttext[idx]);\    glyph = cache_get_font (font, ttext[idx]);\
2014    if (!(flags & TEXT2_IMPLICIT_X))\    if (!(flags & TEXT2_IMPLICIT_X))\
2015      {\
2016        xyoffset = ttext[++idx];\
2017        if ((xyoffset & 0x80))\
2018      {\      {\
2019        xyoffset = ttext[++idx];\        if (flags & TEXT2_VERTICAL)\
2020        if ((xyoffset & 0x80))\          y += ttext[idx+1] | (ttext[idx+2] << 8);\
         {\  
           if (flags & TEXT2_VERTICAL) \  
             y += ttext[++idx] | (ttext[++idx] << 8);\  
           else\  
             x += ttext[++idx] | (ttext[++idx] << 8);\  
         }\  
2021        else\        else\
2022          {\          x += ttext[idx+1] | (ttext[idx+2] << 8);\
2023            if (flags & TEXT2_VERTICAL) \        idx += 2;\
             y += xyoffset;\  
           else\  
             x += xyoffset;\  
         }\  
2024      }\      }\
2025    if (glyph != NULL)\      else\
2026      {\      {\
2027        ui_draw_glyph (mixmode, x + (short) glyph->offset,\        if (flags & TEXT2_VERTICAL)\
2028                       y + (short) glyph->baseline,\          y += xyoffset;\
2029                       glyph->width, glyph->height,\        else\
2030                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\          x += xyoffset;\
       if (flags & TEXT2_IMPLICIT_X)\  
         x += glyph->width;\  
2031      }\      }\
2032      }\
2033      if (glyph != NULL)\
2034      {\
2035        x1 = x + glyph->offset;\
2036        y1 = y + glyph->baseline;\
2037        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2038        XSetTSOrigin(g_display, g_gc, x1, y1);\
2039        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2040        if (flags & TEXT2_IMPLICIT_X)\
2041          x += glyph->width;\
2042      }\
2043  }  }
2044    
2045  void  void
2046  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
2047               int clipx, int clipy, int clipcx, int clipcy, int boxx,               int clipx, int clipy, int clipcx, int clipcy,
2048               int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
2049               int fgcolour, uint8 * text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
2050  {  {
2051          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2052          int i, j, xyoffset;          int i, j, xyoffset, x1, y1;
2053          DATABLOB *entry;          DATABLOB *entry;
2054    
2055          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
2056    
2057            /* Sometimes, the boxcx value is something really large, like
2058               32691. This makes XCopyArea fail with Xvnc. The code below
2059               is a quick fix. */
2060            if (boxx + boxcx > g_width)
2061                    boxcx = g_width - boxx;
2062    
2063          if (boxcx > 1)          if (boxcx > 1)
2064          {          {
2065                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2066          }          }
2067          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
2068          {          {
2069                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2070          }          }
2071    
2072            SET_FOREGROUND(fgcolour);
2073            SET_BACKGROUND(bgcolour);
2074            XSetFillStyle(g_display, g_gc, FillStippled);
2075    
2076          /* Paint text, character by character */          /* Paint text, character by character */
2077          for (i = 0; i < length;)          for (i = 0; i < length;)
2078          {          {
# Line 1240  ui_draw_text(uint8 font, uint8 flags, in Line 2080  ui_draw_text(uint8 font, uint8 flags, in
2080                  {                  {
2081                          case 0xff:                          case 0xff:
2082                                  if (i + 2 < length)                                  if (i + 2 < length)
2083                                          cache_put_text(text[i + 1], text,                                          cache_put_text(text[i + 1], text, text[i + 2]);
                                                        text[i + 2]);  
2084                                  else                                  else
2085                                  {                                  {
2086                                          error("this shouldn't be happening\n");                                          error("this shouldn't be happening\n");
2087                                          break;                                          exit(1);
2088                                  }                                  }
2089                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2090                                  length -= i + 3;                                  length -= i + 3;
# Line 1258  ui_draw_text(uint8 font, uint8 flags, in Line 2097  ui_draw_text(uint8 font, uint8 flags, in
2097                                  if (entry != NULL)                                  if (entry != NULL)
2098                                  {                                  {
2099                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] ==
2100                                               0)                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
                                             && (!(flags & TEXT2_IMPLICIT_X)))  
2101                                          {                                          {
2102                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2103                                                          y += text[i + 2];                                                          y += text[i + 2];
2104                                                  else                                                  else
2105                                                          x += text[i + 2];                                                          x += text[i + 2];
2106                                          }                                          }
                                         if (i + 2 < length)  
                                                 i += 3;  
                                         else  
                                                 i += 2;  
                                         length -= i;  
                                         /* this will move pointer from start to first character after FE command */  
                                         text = &(text[i]);  
                                         i = 0;  
2107                                          for (j = 0; j < entry->size; j++)                                          for (j = 0; j < entry->size; j++)
2108                                                  DO_GLYPH(((uint8 *) (entry->                                                  DO_GLYPH(((uint8 *) (entry->data)), j);
                                                                      data)),  
                                                          j);  
2109                                  }                                  }
2110                                    if (i + 2 < length)
2111                                            i += 3;
2112                                    else
2113                                            i += 2;
2114                                    length -= i;
2115                                    /* this will move pointer from start to first character after FE command */
2116                                    text = &(text[i]);
2117                                    i = 0;
2118                                  break;                                  break;
2119    
2120                          default:                          default:
# Line 1288  ui_draw_text(uint8 font, uint8 flags, in Line 2124  ui_draw_text(uint8 font, uint8 flags, in
2124                  }                  }
2125          }          }
2126    
2127            XSetFillStyle(g_display, g_gc, FillSolid);
2128    
2129            if (g_ownbackstore)
2130            {
2131                    if (boxcx > 1)
2132                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2133                                      boxy, boxcx, boxcy, boxx, boxy);
2134                    else
2135                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2136                                      clipy, clipcx, clipcy, clipx, clipy);
2137            }
2138  }  }
2139    
2140  void  void
# Line 1297  ui_desktop_save(uint32 offset, int x, in Line 2143  ui_desktop_save(uint32 offset, int x, in
2143          Pixmap pix;          Pixmap pix;
2144          XImage *image;          XImage *image;
2145    
2146          if (ownbackstore)          if (g_ownbackstore)
2147          {          {
2148                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
2149          }          }
2150          else          else
2151          {          {
2152                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2153                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                  XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
2154                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2155                                    ZPixmap);                  XFreePixmap(g_display, pix);
                 XFreePixmap(display, pix);  
2156          }          }
2157    
2158          offset *= bpp / 8;          offset *= g_bpp / 8;
2159          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
                           bpp / 8, (uint8 *) image->data);  
2160    
2161          XDestroyImage(image);          XDestroyImage(image);
2162  }  }
# Line 1324  ui_desktop_restore(uint32 offset, int x, Line 2167  ui_desktop_restore(uint32 offset, int x,
2167          XImage *image;          XImage *image;
2168          uint8 *data;          uint8 *data;
2169    
2170          offset *= bpp / 8;          offset *= g_bpp / 8;
2171          data = cache_get_desktop(offset, cx, cy, bpp / 8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2172          if (data == NULL)          if (data == NULL)
2173                  return;                  return;
2174    
2175          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2176                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
                              cx * bpp / 8);  
2177    
2178          if (ownbackstore)          if (g_ownbackstore)
2179          {          {
2180                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2181                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);                  XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2182          }          }
2183          else          else
2184          {          {
2185                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);                  XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2186          }          }
2187    
2188          XFree(image);          XFree(image);
2189  }  }
2190    
2191    /* these do nothing here but are used in uiports */
2192    void
2193    ui_begin_update(void)
2194    {
2195    }
2196    
2197    void
2198    ui_end_update(void)
2199    {
2200    }

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

  ViewVC Help
Powered by ViewVC 1.1.26