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

Legend:
Removed from v.54  
changed lines
  Added in v.688

  ViewVC Help
Powered by ViewVC 1.1.26