/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

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

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

Legend:
Removed from v.157  
changed lines
  Added in v.867

  ViewVC Help
Powered by ViewVC 1.1.26