/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26