/[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 52 by n-ki, Fri Apr 26 08:22:39 2002 UTC revision 725 by jsorg71, Sun Jun 27 17:51:54 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 key_modifier_state = 0;  
 static unsigned int key_down_state = 0;  
   
 #define DShift1Mask   (1<<0)  
 #define DShift2Mask   (1<<1)  
 #define DControl1Mask (1<<2)  
 #define DControl2Mask (1<<3)  
 #define DMod1Mask     (1<<4)  
 #define DMod2Mask     (1<<5)  
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 96  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    /* repeat and unroll, similar to bitmap.c */
239    /* potentialy any of the following translate */
240    /* functions can use repeat but just doing */
241    /* the most common ones */
242    
243  void xwin_release_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode);  #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
244  void xwin_press_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode);  /* 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;
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;          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++);
534                          if (host_be != xserver_be)  
535                                  BSWAP16(colour);                  if (g_host_be)
536                          break;                  {
537                            BSWAP16(pixel);
538                    }
539    
540                    value = make_colour(split_colour16(pixel));
541    
542                    if (g_xserver_be)
543                    {
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    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    static void
586    translate24to24(uint8 * data, uint8 * out, uint8 * end)
587    {
588            uint32 pixel;
589            uint32 value;
590    
591            while (out < end)
592            {
593                    pixel = *(data++) << 16;
594                    pixel |= *(data++) << 8;
595                    pixel |= *(data++);
596    
597                    value = make_colour(split_colour24(pixel));
598    
599                    if (g_xserver_be)
600                    {
601                            *(out++) = value >> 16;
602                            *(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                    pixel = *(data++) << 16;
623                    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            switch (g_server_bpp)
668            {
669                  case 24:                  case 24:
670                          if (xserver_be)                          switch (g_bpp)
671                                  BSWAP24(colour);                          {
672                                    case 32:
673                                            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 16:
684                  case 32:                          switch (g_bpp)
685                          if (host_be != xserver_be)                          {
686                                  BSWAP32(colour);                                  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;
697                    case 15:
698                            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;
711                    case 8:
712                            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          return colour;          KeyCode keycode = XKeysymToKeycode(g_display, keysym);
739    
740            if (keycode == NoSymbol)
741                    return False;
742    
743            for (modifierpos = 0; modifierpos < 8; modifierpos++)
744            {
745                    offset = g_mod_map->max_keypermod * modifierpos;
746    
747                    for (key = 0; key < g_mod_map->max_keypermod; key++)
748                    {
749                            if (g_mod_map->modifiermap[offset + key] == keycode)
750                                    keysymMask |= 1 << modifierpos;
751                    }
752            }
753    
754            return (state & keysymMask) ? True : False;
755    }
756    
757    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  BOOL
766  ui_create_window(char *title)  ui_init(void)
767  {  {
768          XSetWindowAttributes attribs;          XVisualInfo vi;
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
769          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
         Screen *screen;  
770          uint16 test;          uint16 test;
771          int i;          int i, screen_num, nvisuals;
772                    XVisualInfo *vmatches = NULL;
773          int xkb_minor, xkb_major;          XVisualInfo template;
774          int xkb_event, xkb_error, xkb_reason;          Bool TrueColorVisual = False;
775    
776          /* compare compiletime libs with runtime libs. */          g_display = XOpenDisplay(NULL);
777          xkb_major = XkbMajorVersion;          if (g_display == NULL)
         xkb_minor = XkbMinorVersion;  
         if( XkbLibraryVersion( &xkb_major, &xkb_minor ) == False )  
778          {          {
779                  error("please re-compile rdesktop\ncompile time version of xkb is not compatible with\nyour runtime version of the library\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
780                  return False;                  return False;
781          }          }
782    
783            screen_num = DefaultScreen(g_display);
784            g_x_socket = ConnectionNumber(g_display);
785            g_screen = ScreenOfDisplay(g_display, screen_num);
786            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          /* XKB is the 'new' keyboard handler in x.. ( the xkb code in Xfree86 originates from SGI, years 1993 and 1995 from what I could tell. )          nvisuals--;
793           * it makes it possible for people with disabilities to use rdesktop, stickykeys, bouncekeys etc. VERY MUCH useful.          while (nvisuals >= 0)
          * XFree86 has had support for it since it's earliest incarnation. I believe it is a reasonable dependency.  
          */  
         display = XkbOpenDisplay( NULL, &xkb_event, &xkb_error, &xkb_major, &xkb_minor, &xkb_reason );  
         switch(xkb_reason)  
794          {          {
795                  case XkbOD_BadLibraryVersion:                  if ((vmatches + nvisuals)->depth > g_depth)
796                          error("XkbOD_BadLibraryVersion: XKB extensions in server and the library rdesktop is linked against aren't compatible with each other.\n");                  {
797                          break;                          g_depth = (vmatches + nvisuals)->depth;
798                  case XkbOD_ConnectionRefused:                  }
799                          error("XkbOD_ConnectionRefused\n");                  nvisuals--;
800                          break;                  TrueColorVisual = True;
                 case XkbOD_BadServerVersion:  
                         error("XkbOD_BadServerVersion\n");  
                         break;  
                 case XkbOD_NonXkbServer:  
                         error("XkbOD_NonXkbServer: XKB extension not present in server\nupdate your X server.\n");  
                         break;  
                 case XkbOD_Success:  
                         DEBUG("XkbOD_Success: Connection established with display\n");  
                         break;  
801          }          }
802    
803          if (display == NULL)          test = 1;
804            g_host_be = !(BOOL) (*(uint8 *) (&test));
805            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
806    
807            if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))
808          {          {
809                  error("Failed to open display\n");                  /* we use a colourmap, so the default visual should do */
810                  return False;                  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          x_socket = ConnectionNumber(display);          pfm = XListPixmapFormats(g_display, &i);
         screen = DefaultScreenOfDisplay(display);  
         visual = DefaultVisualOfScreen(screen);  
         depth = DefaultDepthOfScreen(screen);  
           
         pfm = XListPixmapFormats(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                    /* 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                  attribs.override_redirect = False;                  /* 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          width = (width + 3) & ~3; /* make width a multiple of 32 bits */          /* 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            if (g_null_cursor != NULL)
933                    ui_destroy_cursor(g_null_cursor);
934    
935            XFreeModifiermap(g_mod_map);
936    
937            if (g_ownbackstore)
938                    XFreePixmap(g_display, g_backstore);
939    
940            XFreeGC(g_display, g_gc);
941            XCloseDisplay(g_display);
942            g_display = NULL;
943    }
944    
945    BOOL
946    ui_create_window(void)
947    {
948            uint8 null_pointer_mask[1] = { 0x80 };
949            uint8 null_pointer_data[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          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          if ((g_ownbackstore) && (g_backstore == 0))
978                              0, 0, width, height, 0, CopyFromParent,          {
979                              InputOutput, CopyFromParent,                  g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
980                              CWBackingStore | CWBackPixel | CWOverrideRedirect,  
981                              &attribs);                  /* 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(display, wnd, title);          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 328  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 | KeymapStateMask;  
         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          if (ownbackstore)                                   XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
                 backstore = XCreatePixmap(display, wnd, width, height, depth);  
1030    
1031          XMapWindow(display, wnd);                  if ((g_IC != NULL)
1032                        && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1033                            input_mask |= ic_input_mask;
1034            }
1035    
1036          /* TODO: error texts... make them friendly. */          XSelectInput(g_display, g_wnd, input_mask);
1037          xkb = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);          XMapWindow(g_display, g_wnd);
         if ((int)xkb == BadAlloc || xkb == NULL)  
         {  
                         error( "XkbGetKeyboard failed.\n");  
                         exit(0);  
         }  
1038    
1039          /* TODO: error texts... make them friendly. */          /* wait for VisibilityNotify */
1040          if( XkbSelectEvents(display, xkb->device_spec, XkbAllEventsMask, XkbAllEventsMask) == False )          do
1041          {          {
1042                          error( "XkbSelectEvents failed.\n");                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);
                         exit(0);  
1043          }          }
1044            while (xevent.type != VisibilityNotify);
1045            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1046    
1047            g_focused = False;
1048            g_mouse_in_wnd = False;
1049    
1050            /* handle the WM_DELETE_WINDOW protocol */
1051            g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1052            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1053            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1054    
1055            /* 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  ui_destroy_window()  ui_resize_window()
1064  {  {
1065          if( xkb != NULL )          XSizeHints *sizehints;
1066                  XkbFreeKeyboard(xkb, XkbAllControlsMask, True);          Pixmap bs;
1067    
1068            sizehints = XAllocSizeHints();
1069            if (sizehints)
1070            {
1071                    sizehints->flags = PMinSize | PMaxSize;
1072                    sizehints->min_width = sizehints->max_width = g_width;
1073                    sizehints->min_height = sizehints->max_height = g_height;
1074                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1075                    XFree(sizehints);
1076            }
1077    
1078          if (ownbackstore)          if (!(g_fullscreen || g_embed_wnd))
1079                  XFreePixmap(display, backstore);          {
1080                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1081            }
1082    
1083          XFreeGC(display, gc);          /* create new backstore pixmap */
1084          XDestroyWindow(display, wnd);          if (g_backstore != 0)
1085          XCloseDisplay(display);          {
1086          display = NULL;                  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  static void  void
1096  xwin_process_events()  ui_destroy_window(void)
1097    {
1098            if (g_IC != NULL)
1099                    XDestroyIC(g_IC);
1100    
1101            XDestroyWindow(g_display, g_wnd);
1102    }
1103    
1104    void
1105    xwin_toggle_fullscreen(void)
1106  {  {
1107          XkbEvent xkbevent;          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    /* Process all events in Xlib queue
1130       Returns 0 after user quit, 1 otherwise */
1131    static int
1132    xwin_process_events(void)
1133    {
1134            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          if (display == NULL)          Status status;
                 return;  
1141    
1142          while (XCheckMaskEvent(display, ~0, &xkbevent.core))          while (XPending(g_display) > 0)
1143          {          {
1144                  ev_time = time(NULL);                  XNextEvent(g_display, &xevent);
1145    
1146                    if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1147                    {
1148                            DEBUG_KBD(("Filtering event\n"));
1149                            continue;
1150                    }
1151    
1152                  flags = 0;                  flags = 0;
1153    
1154                  switch (xkbevent.type)                  switch (xevent.type)
1155                  {                  {
1156                          case KeymapNotify:                          case VisibilityNotify:
1157                                  /* TODO:                                  g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1158                                   * read modifier status at focus in, and update the local masks, and the other end as well..                                  break;
1159                                   * if not, we may get out of sync.                          case ClientMessage:
1160                                   * xkbevent.core.xkeymap.key_vector                                  /* the window manager told us to quit */
1161                                   * char key_vector[32];                                  if ((xevent.xclient.message_type == g_protocol_atom)
1162                                   */                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1163                                            /* Quit */
1164                                            return 0;
1165                                  break;                                  break;
   
                         case KeyRelease:  
                                 flags = KBD_FLAG_DOWN | KBD_FLAG_UP;  
                                 /* fall through */  
1166    
1167                          case KeyPress:                          case KeyPress:
1168                                  if( XkbTranslateKeyCode(xkb, xkbevent.core.xkey.keycode, xkbevent.core.xkey.state, &tmpmods, &keysym) == False )                                  g_last_gesturetime = xevent.xkey.time;
1169                                    if (g_IC != NULL)
1170                                            /* Multi_key compatible version */
1171                                    {
1172                                            XmbLookupString(g_IC,
1173                                                            &xevent.xkey, str, sizeof(str), &keysym,
1174                                                            &status);
1175                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1176                                            {
1177                                                    error("XmbLookupString failed with status 0x%x\n",
1178                                                          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                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1191                                               get_ksname(keysym)));
1192    
1193                                    ev_time = time(NULL);
1194                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1195                                          break;                                          break;
                                 scancode = xkeymap_translate_key(keysym, xkbevent.core.xkey.keycode, &flags);  
1196    
1197                                  if (scancode == 0 )                                  tr = xkeymap_translate_key(keysym,
1198                                                               xevent.xkey.keycode, xevent.xkey.state);
1199    
1200                                    if (tr.scancode == 0)
1201                                          break;                                          break;
1202    
1203                                  /* keep track of the modifiers -- needed for stickykeys... */                                  save_remote_modifiers(tr.scancode);
1204                                  if( xkbevent.type == KeyPress )                                  ensure_remote_modifiers(ev_time, tr);
1205                                          xwin_press_modifiers( &xkbevent.core.xkey, ev_time, scancode );                                  rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1206                                    restore_remote_modifiers(ev_time, tr.scancode);
1207    
1208                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, flags, scancode, 0);                                  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( xkbevent.type == KeyRelease )                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1216                                          xwin_release_modifiers( &xkbevent.core.xkey, ev_time, scancode );                                             get_ksname(keysym)));
1217    
1218                                    ev_time = time(NULL);
1219                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1220                                            break;
1221    
1222                                    tr = xkeymap_translate_key(keysym,
1223                                                               xevent.xkey.keycode, xevent.xkey.state);
1224    
1225                                    if (tr.scancode == 0)
1226                                            break;
1227    
1228                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
1229                                  break;                                  break;
1230    
1231                          case ButtonPress:                          case ButtonPress:
# Line 444  xwin_process_events() Line 1233  xwin_process_events()
1233                                  /* fall through */                                  /* fall through */
1234    
1235                          case ButtonRelease:                          case ButtonRelease:
1236                                  button = xkeymap_translate_button(xkbevent.core.xbutton.button);                                  g_last_gesturetime = xevent.xbutton.time;
1237                                    button = xkeymap_translate_button(xevent.xbutton.button);
1238                                  if (button == 0)                                  if (button == 0)
1239                                          break;                                          break;
1240    
1241                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
1242                                                 flags | button,                                  if (xevent.xbutton.y < g_win_button_size)
1243                                                 xkbevent.core.xbutton.x,                                  {
1244                                                 xkbevent.core.xbutton.y);                                          /* 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                                            /*  Check from right to left: */
1249    
1250                                            if (xevent.xbutton.x >= g_width - g_win_button_size)
1251                                            {
1252                                                    /* The close button, continue */
1253                                                    ;
1254                                            }
1255                                            else if (xevent.xbutton.x >=
1256                                                     g_width - g_win_button_size * 2)
1257                                            {
1258                                                    /* The maximize/restore button. Do not send to
1259                                                       server.  It might be a good idea to change the
1260                                                       cursor or give some other visible indication
1261                                                       that rdesktop inhibited this click */
1262                                                    break;
1263                                            }
1264                                            else if (xevent.xbutton.x >=
1265                                                     g_width - g_win_button_size * 3)
1266                                            {
1267                                                    /* The minimize button. Iconify window. */
1268                                                    XIconifyWindow(g_display, g_wnd,
1269                                                                   DefaultScreen(g_display));
1270                                                    break;
1271                                            }
1272                                            else if (xevent.xbutton.x <= g_win_button_size)
1273                                            {
1274                                                    /* The system menu. Ignore. */
1275                                                    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                                            }
1290                                    }
1291    
1292                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1293                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1294                                  break;                                  break;
1295    
1296                          case MotionNotify:                          case MotionNotify:
1297                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (g_moving_wnd)
1298                                                 MOUSE_FLAG_MOVE,                                  {
1299                                                 xkbevent.core.xmotion.x,                                          XMoveWindow(g_display, g_wnd,
1300                                                 xkbevent.core.xmotion.y);                                                      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                            case FocusIn:
1313                                    if (xevent.xfocus.mode == NotifyGrab)
1314                                            break;
1315                                    g_focused = True;
1316                                    reset_modifier_keys();
1317                                    if (g_grab_keyboard && g_mouse_in_wnd)
1318                                            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;                                  break;
1329    
1330                          case EnterNotify:                          case EnterNotify:
1331                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,                                  /* we only register for this event when in fullscreen mode */
1332                                                GrabModeAsync, CurrentTime);                                  /* or grab_keyboard */
1333                                    g_mouse_in_wnd = True;
1334                                    if (g_fullscreen)
1335                                    {
1336                                            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;                                  break;
1344    
1345                          case LeaveNotify:                          case LeaveNotify:
1346                                  XUngrabKeyboard(display, CurrentTime);                                  /* we only register for this event when grab_keyboard */
1347                                    g_mouse_in_wnd = False;
1348                                    XUngrabKeyboard(g_display, CurrentTime);
1349                                  break;                                  break;
1350    
1351                          case Expose:                          case Expose:
1352                                  XCopyArea(display, backstore, wnd, gc,                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1353                                            xkbevent.core.xexpose.x, xkbevent.core.xexpose.y,                                            xevent.xexpose.x, xevent.xexpose.y,
1354                                            xkbevent.core.xexpose.width, xkbevent.core.xexpose.height,                                            xevent.xexpose.width,
1355                                            xkbevent.core.xexpose.x, xkbevent.core.xexpose.y);                                            xevent.xexpose.height,
1356                                              xevent.xexpose.x, xevent.xexpose.y);
1357                                  break;                                  break;
                 }  
         }  
 }  
   
 void  
 xwin_release_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode)  
 {  
         switch (scancode) {  
         case 0x2a:  
                 key_down_state &= ~DShift1Mask;  
                 break;  
         case 0x36:  
                 key_down_state &= ~DShift2Mask;  
                 break;  
         case 0x1d:  
                 key_down_state &= ~DControl1Mask;  
                 break;  
         case 0x9d:  
                 key_down_state &= ~DControl2Mask;  
                 break;  
         case 0x38:  
                 key_down_state &= ~DMod1Mask;  
                 break;  
         case 0xb8:  
                 key_down_state &= ~DMod2Mask;  
                 break;  
         }  
   
         if( !(ShiftMask & ev->state) && (key_down_state & DShift1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a, 0);  
                 key_down_state &= ~DShift1Mask;  
   
         }  
   
         if( !(ControlMask & ev->state) && (key_down_state & DControl1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d, 0);  
                 key_down_state &= ~DControl1Mask;  
   
         }  
           
         if( !(Mod1Mask & ev->state) && (key_down_state & DMod1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38, 0);  
                 key_down_state &= ~DMod1Mask;  
   
         }  
           
         if( !(Mod2Mask & ev->state) && (key_down_state & DMod2Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8, 0);  
                 key_down_state &= ~DMod2Mask;  
         }  
 }  
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  void                                  if (xevent.xmapping.request == MappingModifier)
1367  xwin_press_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode)                                  {
1368  {                                          XFreeModifiermap(g_mod_map);
1369          key_modifier_state = ev->state;                                          g_mod_map = XGetModifierMapping(g_display);
1370                                    }
1371          switch (scancode) {                                  break;
         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;  
         }  
   
         if( (ShiftMask & ev->state) && !((key_down_state & DShift1Mask) || (key_down_state & DShift2Mask)))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x2a, 0);  
                 key_down_state |= DShift1Mask;  
   
         }  
   
         if( (ControlMask & ev->state) && !((key_down_state & DControl1Mask) || (key_down_state & DControl2Mask)))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x1d, 0);  
                 key_down_state |= DControl1Mask;  
   
         }  
   
         if( (Mod1Mask & ev->state) && !(key_down_state & DMod1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x38, 0);  
                 key_down_state |= DMod1Mask;  
   
         }  
   
         if( (Mod2Mask & ev->state) && !(key_down_state & DMod2Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0xb8, 0);  
                 key_down_state |= DMod2Mask;  
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          XFlush(display);          BOOL s_timeout = False;
   
         FD_ZERO(&rfds);  
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                  FD_SET(x_socket, &rfds);                  FD_SET(g_x_socket, &rfds);
1413    
1414                  switch (select(n, &rfds, NULL, NULL, NULL))  #ifdef WITH_RDPSND
1415                    /* FIXME: there should be an API for registering fds */
1416                    if (g_dsp_busy)
1417                    {
1418                            FD_SET(g_dsp_fd, &wfds);
1419                            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, &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
1465  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1466  {  {
1467          XImage *image;          XImage *image;
1468          Pixmap bitmap;          Pixmap bitmap;
1469          uint8 *tdata;          uint8 *tdata;
1470            int bitmap_pad;
1471    
1472          tdata = (owncolmap ? data : translate_image(width, height, data));          if (g_server_bpp == 8)
1473          bitmap = XCreatePixmap(display, wnd, width, height, depth);          {
1474          image = XCreateImage(display, visual, depth, ZPixmap,                  bitmap_pad = 8;
1475                               0, tdata, width, height, 8, 0);          }
1476            else
1477            {
1478                    bitmap_pad = g_bpp;
1479    
1480                    if (g_bpp == 24)
1481                            bitmap_pad = 32;
1482            }
1483    
1484            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(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          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          tdata = (owncolmap ? data : translate_image(width, height, data));          if (g_server_bpp == 8)
1505          image = XCreateImage(display, visual, depth, ZPixmap,          {
1506                               0, tdata, width, height, 8, 0);                  bitmap_pad = 8;
1507            }
1508            else
1509            {
1510                    bitmap_pad = g_bpp;
1511    
1512          if (ownbackstore)                  if (g_bpp == 24)
1513                            bitmap_pad = 32;
1514            }
1515    
1516            tdata = (g_owncolmap ? data : translate_image(width, height, data));
1517            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1518                                 (char *) tdata, width, height, bitmap_pad, 0);
1519    
1520            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
1542  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1543  {  {
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);
1563          XFreeGC(display, gc);          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 727  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 770  ui_create_cursor(unsigned int x, unsigne Line 1628  ui_create_cursor(unsigned int x, unsigne
1628    
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);
1638          xfree(mask);          xfree(mask);
1639          xfree(cursor);          xfree(cursor);
1640          return (HCURSOR)xcursor;          return (HCURSOR) xcursor;
1641  }  }
1642    
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 799  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)
         if (owncolmap)  
1675          {          {
1676                  XColor *xcolours, *xentry;                  uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1677                  Colormap map;                  XColor xentry;
1678                    XColor xc_cache[256];
1679                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  uint32 colour;
1680                    int colLookup = 256;
1681                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1682                  {                  {
1683                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1684                          xentry = &xcolours[i];                          MAKE_XCOLOR(&xentry, entry);
                         xentry->pixel = i;  
                         MAKE_XCOLOR(xentry, entry);  
                 }  
1685    
1686                  map = XCreateColormap(display, wnd, visual, AllocAll);                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1687                  XStoreColors(display, map, xcolours, ncolours);                          {
1688                                    /* Allocation failed, find closest match. */
1689                                    int j = 256;
1690                                    int nMinDist = 3 * 256 * 256;
1691                                    long nDist = nMinDist;
1692    
1693                  xfree(xcolours);                                  /* only get the colors once */
1694                  return (HCOLOURMAP)map;                                  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          else
1748          {          {
1749                  uint32 *map = xmalloc(sizeof(*colmap) * ncolours);                  XColor *xcolours, *xentry;
1750                  XColor xentry;                  Colormap map;
                 uint32 colour;  
1751    
1752                    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];
1756                          MAKE_XCOLOR(&xentry, entry);                          xentry = &xcolours[i];
1757                            xentry->pixel = i;
1758                          if (XAllocColor(display, xcolmap, &xentry) != 0)                          MAKE_XCOLOR(xentry, entry);
                                 colour = xentry.pixel;  
                         else  
                                 colour = white;  
   
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
1759                  }                  }
1760    
1761                  return map;                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1762                    XStoreColors(g_display, map, xcolours, ncolours);
1763    
1764                    xfree(xcolours);
1765                    return (HCOLOURMAP) map;
1766          }          }
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 876  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 906  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,
1843            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1844  {  {
1845          Pixmap fill;          Pixmap fill;
1846            uint8 i, ipattern[8];
1847    
1848          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1849    
# Line 919  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;                          break;
1856    
1857                  case 3: /* Pattern */                  case 2: /* Hatch */
1858                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);                          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;
1870    
1871                    case 3: /* Pattern */
1872                            for (i = 0; i != 8; i++)
1873                                    ipattern[7 - i] = brush->pattern[i];
1874                            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, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1880                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1881                          FILL_RECTANGLE(x, y, cx, cy);                          XSetFillStyle(g_display, g_gc, FillSolid);
1882                            XSetTSOrigin(g_display, g_gc, 0, 0);
1883                          XSetFillStyle(display, gc, FillSolid);                          ui_destroy_glyph((HGLYPH) fill);
                         ui_destroy_glyph((HGLYPH)fill);  
1884                          break;                          break;
1885    
1886                  default:                  default:
# Line 942  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 950  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 963  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 974  void Line 1937  void
1937  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1938            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1939            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1940            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1941  {  {
1942          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1943             comes up with a more efficient way of doing it I am using cases. */             comes up with a more efficient way of doing it I am using cases. */
# Line 983  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 1010  ui_triblt(uint8 opcode, Line 1969  ui_triblt(uint8 opcode,
1969  void  void
1970  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1971          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1972          /* pen */ PEN *pen)          /* pen */ PEN * pen)
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 1029  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                  switch (text[i]) {          {
2079                  case 0xff:                  switch (text[i])
2080                          if (i + 2 < length)                  {
2081                                  cache_put_text(text[i + 1], text, text[i + 2]);                          case 0xff:
2082                          else {                                  if (i + 2 < length)
2083                                  error("this shouldn't be happening\n");                                          cache_put_text(text[i + 1], text, text[i + 2]);
2084                                    else
2085                                    {
2086                                            error("this shouldn't be happening\n");
2087                                            exit(1);
2088                                    }
2089                                    /* this will move pointer from start to first character after FF command */
2090                                    length -= i + 3;
2091                                    text = &(text[i + 3]);
2092                                    i = 0;
2093                                  break;                                  break;
                         }  
                         /* this will move pointer from start to first character after FF command */  
                         length -= i + 3;  
                         text = &(text[i + 3]);  
                         i = 0;  
                         break;  
2094    
2095                  case 0xfe:                          case 0xfe:
2096                          entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
2097                          if (entry != NULL) {                                  if (entry != NULL)
2098                                  if ((((uint8 *) (entry->data))[1] == 0)                                  {
2099                                      && (!(flags & TEXT2_IMPLICIT_X))) {                                          if ((((uint8 *) (entry->data))[1] ==
2100                                          if (flags & TEXT2_VERTICAL)                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
2101                                                  y += text[i + 2];                                          {
2102                                          else                                                  if (flags & TEXT2_VERTICAL)
2103                                                  x += text[i + 2];                                                          y += text[i + 2];
2104                                                    else
2105                                                            x += text[i + 2];
2106                                            }
2107                                            for (j = 0; j < entry->size; j++)
2108                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
2109                                  }                                  }
2110                                  if (i + 2 < length)                                  if (i + 2 < length)
2111                                          i += 3;                                          i += 3;
2112                                  else                                  else
2113                                          i += 2;                                          i += 2;
2114                                  length -= i;                                  length -= i;
2115                                  /* this will move pointer from start to first character after FE command */                                  /* this will move pointer from start to first character after FE command */
2116                                  text = &(text[i]);                                  text = &(text[i]);
2117                                  i = 0;                                  i = 0;
2118                                  for (j = 0; j < entry->size; j++)                                  break;
                                         DO_GLYPH(((uint8 *) (entry->data)), j);  
                         }  
                         break;  
2119    
2120                  default:                          default:
2121                          DO_GLYPH(text, i);                                  DO_GLYPH(text, i);
2122                          i++;                                  i++;
2123                          break;                                  break;
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 1156  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 1183  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.52  
changed lines
  Added in v.725

  ViewVC Help
Powered by ViewVC 1.1.26