/[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 603 by stargo, Sat Feb 7 18:47:06 2004 UTC revision 1049 by astrand, Wed Mar 1 13:54:19 2006 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- 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-2002     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 21  Line 21 
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23  #include <unistd.h>  #include <unistd.h>
24    #include <sys/time.h>
25  #include <time.h>  #include <time.h>
26  #include <errno.h>  #include <errno.h>
27  #include <strings.h>  #include <strings.h>
# Line 29  Line 30 
30    
31  extern int g_width;  extern int g_width;
32  extern int g_height;  extern int g_height;
33    extern int g_xpos;
34    extern int g_ypos;
35    extern int g_pos;
36  extern BOOL g_sendmotion;  extern BOOL g_sendmotion;
37  extern BOOL g_fullscreen;  extern BOOL g_fullscreen;
38  extern BOOL g_grab_keyboard;  extern BOOL g_grab_keyboard;
39  extern BOOL g_hide_decorations;  extern BOOL g_hide_decorations;
40  extern char g_title[];  extern char g_title[];
41  extern int g_server_bpp;  /* Color depth of the RDP session.
42       As of RDP 5.1, it may be 8, 15, 16 or 24. */
43    extern int g_server_depth;
44  extern int g_win_button_size;  extern int g_win_button_size;
45    
46  Display *g_display;  Display *g_display;
# Line 42  Time g_last_gesturetime; Line 48  Time g_last_gesturetime;
48  static int g_x_socket;  static int g_x_socket;
49  static Screen *g_screen;  static Screen *g_screen;
50  Window g_wnd;  Window g_wnd;
51    extern uint32 g_embed_wnd;
52  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
53    BOOL g_Unobscured;              /* used for screenblt */
54  static GC g_gc = NULL;  static GC g_gc = NULL;
55    static GC g_create_bitmap_gc = NULL;
56    static GC g_create_glyph_gc = NULL;
57  static Visual *g_visual;  static Visual *g_visual;
58    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
59       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
60       as far as we're concerned. */
61  static int g_depth;  static int g_depth;
62    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
63       This may be larger than g_depth, in which case some of the bits would
64       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
65  static int g_bpp;  static int g_bpp;
66  static XIM g_IM;  static XIM g_IM;
67  static XIC g_IC;  static XIC g_IC;
# Line 55  static HCURSOR g_null_cursor = NULL; Line 71  static HCURSOR g_null_cursor = NULL;
71  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
72  static BOOL g_focused;  static BOOL g_focused;
73  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
74    /* Indicates that:
75       1) visual has 15, 16 or 24 depth and the same color channel masks
76          as its RDP equivalent (implies X server is LE),
77       2) host is LE
78       This will trigger an optimization whose real value is questionable.
79    */
80    static BOOL g_compatible_arch;
81    /* Indicates whether RDP's bitmaps and our XImages have the same
82       binary format. If so, we can avoid an expensive translation.
83       Note that this can be true when g_compatible_arch is false,
84       e.g.:
85      
86         RDP(LE) <-> host(BE) <-> X-Server(LE)
87        
88       ('host' is the machine running rdesktop; the host simply memcpy's
89        so its endianess doesn't matter)
90     */
91    static BOOL g_no_translate_image = False;
92    
93  /* endianness */  /* endianness */
94  static BOOL g_host_be;  static BOOL g_host_be;
# Line 63  static int g_red_shift_r, g_blue_shift_r Line 97  static int g_red_shift_r, g_blue_shift_r
97  static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;  static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
98    
99  /* software backing store */  /* software backing store */
100  static BOOL g_ownbackstore;  extern BOOL g_ownbackstore;
101  static Pixmap g_backstore = 0;  static Pixmap g_backstore = 0;
102    
103  /* Moving in single app mode */  /* Moving in single app mode */
104  static BOOL g_moving_wnd;  static BOOL g_moving_wnd;
105  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
106  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
107    static BOOL g_using_full_workarea = False;
108    
109  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
110  extern int g_dsp_fd;  extern int g_dsp_fd;
# Line 82  extern BOOL g_rdpsnd; Line 117  extern BOOL g_rdpsnd;
117  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
118  typedef struct  typedef struct
119  {  {
120          uint32 flags;          unsigned long flags;
121          uint32 functions;          unsigned long functions;
122          uint32 decorations;          unsigned long decorations;
123          sint32 inputMode;          long inputMode;
124          uint32 status;          unsigned long status;
125  }  }
126  PropMotifWmHints;  PropMotifWmHints;
127    
# Line 111  PixelColour; Line 146  PixelColour;
146          XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
147  }  }
148    
149    #define FILL_POLYGON(p,np)\
150    { \
151            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
152            if (g_ownbackstore) \
153                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
154    }
155    
156    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
157    { \
158            switch (m) \
159            { \
160                    case 0: /* Outline */ \
161                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
162                            if (g_ownbackstore) \
163                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
164                            break; \
165                    case 1: /* Filled */ \
166                            XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
167                            if (g_ownbackstore) \
168                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
169                            break; \
170            } \
171    }
172    
173  /* colour maps */  /* colour maps */
174  BOOL g_owncolmap = False;  extern BOOL g_owncolmap;
175  static Colormap g_xcolmap;  static Colormap g_xcolmap;
176  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
177    
178  #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )  #define TRANSLATE(col)          ( g_server_depth != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
179  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
180  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
181    
# Line 164  mwm_hide_decorations(void) Line 223  mwm_hide_decorations(void)
223                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
224  }  }
225    
226  static PixelColour  #define SPLITCOLOUR15(colour, rv) \
227  split_colour15(uint32 colour)  { \
228  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
229          PixelColour rv;          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
230          rv.red = (colour & 0x7c00) >> 10;          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
         rv.red = (rv.red * 0xff) / 0x1f;  
         rv.green = (colour & 0x03e0) >> 5;  
         rv.green = (rv.green * 0xff) / 0x1f;  
         rv.blue = (colour & 0x1f);  
         rv.blue = (rv.blue * 0xff) / 0x1f;  
         return rv;  
 }  
   
 static PixelColour  
 split_colour16(uint32 colour)  
 {  
         PixelColour rv;  
         rv.red = (colour & 0xf800) >> 11;  
         rv.red = (rv.red * 0xff) / 0x1f;  
         rv.green = (colour & 0x07e0) >> 5;  
         rv.green = (rv.green * 0xff) / 0x3f;  
         rv.blue = (colour & 0x001f);  
         rv.blue = (rv.blue * 0xff) / 0x1f;  
         return rv;  
 }  
   
 static PixelColour  
 split_colour24(uint32 colour)  
 {  
         PixelColour rv;  
         rv.blue = (colour & 0xff0000) >> 16;  
         rv.green = (colour & 0xff00) >> 8;  
         rv.red = (colour & 0xff);  
         return rv;  
231  }  }
232    
233  static uint32  #define SPLITCOLOUR16(colour, rv) \
234  make_colour(PixelColour pc)  { \
235  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
236          return (((pc.red >> g_red_shift_r) << g_red_shift_l)          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
237                  | ((pc.green >> g_green_shift_r) << g_green_shift_l)          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
238                  | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l));  } \
239    
240    #define SPLITCOLOUR24(colour, rv) \
241    { \
242            rv.blue = (colour & 0xff0000) >> 16; \
243            rv.green = (colour & 0x00ff00) >> 8; \
244            rv.red = (colour & 0x0000ff); \
245  }  }
246    
247    #define MAKECOLOUR(pc) \
248            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
249                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
250                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
251    
252  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
253  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
254  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
255                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
256    
257    /* The following macros output the same octet sequences
258       on both BE and LE hosts: */
259    
260    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
261    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
262    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
263    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
264    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
265    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
266    
267  static uint32  static uint32
268  translate_colour(uint32 colour)  translate_colour(uint32 colour)
269  {  {
270          PixelColour pc;          PixelColour pc;
271          switch (g_server_bpp)          switch (g_server_depth)
272          {          {
273                  case 15:                  case 15:
274                          pc = split_colour15(colour);                          SPLITCOLOUR15(colour, pc);
275                          break;                          break;
276                  case 16:                  case 16:
277                          pc = split_colour16(colour);                          SPLITCOLOUR16(colour, pc);
278                          break;                          break;
279                  case 24:                  case 24:
280                          pc = split_colour24(colour);                          SPLITCOLOUR24(colour, pc);
281                            break;
282                    default:
283                            /* Avoid warning */
284                            pc.red = 0;
285                            pc.green = 0;
286                            pc.blue = 0;
287                          break;                          break;
288          }          }
289          return make_colour(pc);          return MAKECOLOUR(pc);
290  }  }
291    
292    /* indent is confused by UNROLL8 */
293    /* *INDENT-OFF* */
294    
295    /* repeat and unroll, similar to bitmap.c */
296    /* potentialy any of the following translate */
297    /* functions can use repeat but just doing */
298    /* the most common ones */
299    
300    #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
301    /* 2 byte output repeat */
302    #define REPEAT2(stm) \
303    { \
304            while (out <= end - 8 * 2) \
305                    UNROLL8(stm) \
306            while (out < end) \
307                    { stm } \
308    }
309    /* 3 byte output repeat */
310    #define REPEAT3(stm) \
311    { \
312            while (out <= end - 8 * 3) \
313                    UNROLL8(stm) \
314            while (out < end) \
315                    { stm } \
316    }
317    /* 4 byte output repeat */
318    #define REPEAT4(stm) \
319    { \
320            while (out <= end - 8 * 4) \
321                    UNROLL8(stm) \
322            while (out < end) \
323                    { stm } \
324    }
325    /* *INDENT-ON* */
326    
327  static void  static void
328  translate8to8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
329  {  {
330          while (out < end)          while (out < end)
331                  *(out++) = (uint8) g_colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
332  }  }
333    
334  static void  static void
335  translate8to16(uint8 * data, uint8 * out, uint8 * end)  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
336  {  {
337          uint16 value;          uint16 value;
338    
339          while (out < end)          if (g_compatible_arch)
340          {          {
341                  value = (uint16) g_colmap[*(data++)];                  /* *INDENT-OFF* */
342                    REPEAT2
343                  if (g_xserver_be)                  (
344                            *((uint16 *) out) = g_colmap[*(data++)];
345                            out += 2;
346                    )
347                    /* *INDENT-ON* */
348            }
349            else if (g_xserver_be)
350            {
351                    while (out < end)
352                  {                  {
353                          *(out++) = value >> 8;                          value = (uint16) g_colmap[*(data++)];
354                          *(out++) = value;                          BOUT16(out, value);
355                  }                  }
356                  else          }
357            else
358            {
359                    while (out < end)
360                  {                  {
361                          *(out++) = value;                          value = (uint16) g_colmap[*(data++)];
362                          *(out++) = value >> 8;                          LOUT16(out, value);
363                  }                  }
364          }          }
365  }  }
366    
367  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
368  static void  static void
369  translate8to24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
370  {  {
371          uint32 value;          uint32 value;
372    
373          while (out < end)          if (g_compatible_arch)
374          {          {
375                  value = g_colmap[*(data++)];                  while (out < end)
   
                 if (g_xserver_be)  
376                  {                  {
377                          *(out++) = value >> 16;                          value = g_colmap[*(data++)];
378                          *(out++) = value >> 8;                          BOUT24(out, value);
                         *(out++) = value;  
379                  }                  }
380                  else          }
381            else
382            {
383                    while (out < end)
384                  {                  {
385                          *(out++) = value;                          value = g_colmap[*(data++)];
386                          *(out++) = value >> 8;                          LOUT24(out, value);
                         *(out++) = value >> 16;  
387                  }                  }
388          }          }
389  }  }
390    
391  static void  static void
392  translate8to32(uint8 * data, uint8 * out, uint8 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
393  {  {
394          uint32 value;          uint32 value;
395    
396          while (out < end)          if (g_compatible_arch)
397          {          {
398                  value = g_colmap[*(data++)];                  /* *INDENT-OFF* */
399                    REPEAT4
400                  if (g_xserver_be)                  (
401                            *((uint32 *) out) = g_colmap[*(data++)];
402                            out += 4;
403                    )
404                    /* *INDENT-ON* */
405            }
406            else if (g_xserver_be)
407            {
408                    while (out < end)
409                  {                  {
410                          *(out++) = value >> 24;                          value = g_colmap[*(data++)];
411                          *(out++) = value >> 16;                          BOUT32(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value;  
412                  }                  }
413                  else          }
414            else
415            {
416                    while (out < end)
417                  {                  {
418                          *(out++) = value;                          value = g_colmap[*(data++)];
419                          *(out++) = value >> 8;                          LOUT32(out, value);
                         *(out++) = value >> 16;  
                         *(out++) = value >> 24;  
420                  }                  }
421          }          }
422  }  }
423    
424  static void  static void
425  translate15to16(uint16 * data, uint8 * out, uint8 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
426  {  {
427          uint16 pixel;          uint16 pixel;
428          uint16 value;          uint16 value;
429            PixelColour pc;
430    
431          while (out < end)          if (g_xserver_be)
432          {          {
433                  pixel = *(data++);                  while (out < end)
   
                 if (g_host_be)  
434                  {                  {
435                          BSWAP16(pixel);                          pixel = *(data++);
436                  }                          if (g_host_be)
437                            {
438                  value = make_colour(split_colour15(pixel));                                  BSWAP16(pixel);
439                            }
440                  if (g_xserver_be)                          SPLITCOLOUR15(pixel, pc);
441                  {                          value = MAKECOLOUR(pc);
442                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
443                  }                  }
444                  else          }
445            else
446            {
447                    while (out < end)
448                  {                  {
449                          *(out++) = value;                          pixel = *(data++);
450                          *(out++) = value >> 8;                          if (g_host_be)
451                            {
452                                    BSWAP16(pixel);
453                            }
454                            SPLITCOLOUR15(pixel, pc);
455                            value = MAKECOLOUR(pc);
456                            LOUT16(out, value);
457                  }                  }
458          }          }
459  }  }
460    
461  static void  static void
462  translate15to24(uint16 * data, uint8 * out, uint8 * end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
463  {  {
464          uint32 value;          uint32 value;
465          uint16 pixel;          uint16 pixel;
466            PixelColour pc;
467    
468          while (out < end)          if (g_compatible_arch)
469          {          {
470                  pixel = *(data++);                  /* *INDENT-OFF* */
471                    REPEAT3
472                  if (g_host_be)                  (
473                  {                          pixel = *(data++);
474                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
475                  }                          *(out++) = pc.blue;
476                            *(out++) = pc.green;
477                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
478                  if (g_xserver_be)                  )
479                    /* *INDENT-ON* */
480            }
481            else if (g_xserver_be)
482            {
483                    while (out < end)
484                  {                  {
485                          *(out++) = value >> 16;                          pixel = *(data++);
486                          *(out++) = value >> 8;                          if (g_host_be)
487                          *(out++) = value;                          {
488                                    BSWAP16(pixel);
489                            }
490                            SPLITCOLOUR15(pixel, pc);
491                            value = MAKECOLOUR(pc);
492                            BOUT24(out, value);
493                  }                  }
494                  else          }
495            else
496            {
497                    while (out < end)
498                  {                  {
499                          *(out++) = value;                          pixel = *(data++);
500                          *(out++) = value >> 8;                          if (g_host_be)
501                          *(out++) = value >> 16;                          {
502                                    BSWAP16(pixel);
503                            }
504                            SPLITCOLOUR15(pixel, pc);
505                            value = MAKECOLOUR(pc);
506                            LOUT24(out, value);
507                  }                  }
508          }          }
509  }  }
510    
511  static void  static void
512  translate15to32(uint16 * data, uint8 * out, uint8 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
513  {  {
514          uint16 pixel;          uint16 pixel;
515          uint32 value;          uint32 value;
516            PixelColour pc;
517    
518          while (out < end)          if (g_compatible_arch)
519          {          {
520                  pixel = *(data++);                  /* *INDENT-OFF* */
521                    REPEAT4
522                  if (g_host_be)                  (
523                  {                          pixel = *(data++);
524                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
525                  }                          *(out++) = pc.blue;
526                            *(out++) = pc.green;
527                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
528                            *(out++) = 0;
529                  if (g_xserver_be)                  )
530                    /* *INDENT-ON* */
531            }
532            else if (g_xserver_be)
533            {
534                    while (out < end)
535                  {                  {
536                          *(out++) = value >> 24;                          pixel = *(data++);
537                          *(out++) = value >> 16;                          if (g_host_be)
538                          *(out++) = value >> 8;                          {
539                          *(out++) = value;                                  BSWAP16(pixel);
540                            }
541                            SPLITCOLOUR15(pixel, pc);
542                            value = MAKECOLOUR(pc);
543                            BOUT32(out, value);
544                  }                  }
545                  else          }
546            else
547            {
548                    while (out < end)
549                  {                  {
550                          *(out++) = value;                          pixel = *(data++);
551                          *(out++) = value >> 8;                          if (g_host_be)
552                          *(out++) = value >> 16;                          {
553                          *(out++) = value >> 24;                                  BSWAP16(pixel);
554                            }
555                            SPLITCOLOUR15(pixel, pc);
556                            value = MAKECOLOUR(pc);
557                            LOUT32(out, value);
558                  }                  }
559          }          }
560  }  }
561    
562  static void  static void
563  translate16to16(uint16 * data, uint8 * out, uint8 * end)  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
564  {  {
565          uint16 pixel;          uint16 pixel;
566          uint16 value;          uint16 value;
567            PixelColour pc;
568    
569          while (out < end)          if (g_xserver_be)
570          {          {
                 pixel = *(data++);  
   
571                  if (g_host_be)                  if (g_host_be)
572                  {                  {
573                          BSWAP16(pixel);                          while (out < end)
574                            {
575                                    pixel = *(data++);
576                                    BSWAP16(pixel);
577                                    SPLITCOLOUR16(pixel, pc);
578                                    value = MAKECOLOUR(pc);
579                                    BOUT16(out, value);
580                            }
581                  }                  }
582                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
583                  {                  {
584                          *(out++) = value >> 8;                          while (out < end)
585                          *(out++) = value;                          {
586                                    pixel = *(data++);
587                                    SPLITCOLOUR16(pixel, pc);
588                                    value = MAKECOLOUR(pc);
589                                    BOUT16(out, value);
590                            }
591                    }
592            }
593            else
594            {
595                    if (g_host_be)
596                    {
597                            while (out < end)
598                            {
599                                    pixel = *(data++);
600                                    BSWAP16(pixel);
601                                    SPLITCOLOUR16(pixel, pc);
602                                    value = MAKECOLOUR(pc);
603                                    LOUT16(out, value);
604                            }
605                  }                  }
606                  else                  else
607                  {                  {
608                          *(out++) = value;                          while (out < end)
609                          *(out++) = value >> 8;                          {
610                                    pixel = *(data++);
611                                    SPLITCOLOUR16(pixel, pc);
612                                    value = MAKECOLOUR(pc);
613                                    LOUT16(out, value);
614                            }
615                  }                  }
616          }          }
617  }  }
618    
619  static void  static void
620  translate16to24(uint16 * data, uint8 * out, uint8 * end)  translate16to24(const uint16 * data, uint8 * out, uint8 * end)
621  {  {
622          uint32 value;          uint32 value;
623          uint16 pixel;          uint16 pixel;
624            PixelColour pc;
625    
626          while (out < end)          if (g_compatible_arch)
627            {
628                    /* *INDENT-OFF* */
629                    REPEAT3
630                    (
631                            pixel = *(data++);
632                            SPLITCOLOUR16(pixel, pc);
633                            *(out++) = pc.blue;
634                            *(out++) = pc.green;
635                            *(out++) = pc.red;
636                    )
637                    /* *INDENT-ON* */
638            }
639            else if (g_xserver_be)
640          {          {
                 pixel = *(data++);  
   
641                  if (g_host_be)                  if (g_host_be)
642                  {                  {
643                          BSWAP16(pixel);                          while (out < end)
644                            {
645                                    pixel = *(data++);
646                                    BSWAP16(pixel);
647                                    SPLITCOLOUR16(pixel, pc);
648                                    value = MAKECOLOUR(pc);
649                                    BOUT24(out, value);
650                            }
651                  }                  }
652                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
653                  {                  {
654                          *(out++) = value >> 16;                          while (out < end)
655                          *(out++) = value >> 8;                          {
656                          *(out++) = value;                                  pixel = *(data++);
657                                    SPLITCOLOUR16(pixel, pc);
658                                    value = MAKECOLOUR(pc);
659                                    BOUT24(out, value);
660                            }
661                    }
662            }
663            else
664            {
665                    if (g_host_be)
666                    {
667                            while (out < end)
668                            {
669                                    pixel = *(data++);
670                                    BSWAP16(pixel);
671                                    SPLITCOLOUR16(pixel, pc);
672                                    value = MAKECOLOUR(pc);
673                                    LOUT24(out, value);
674                            }
675                  }                  }
676                  else                  else
677                  {                  {
678                          *(out++) = value;                          while (out < end)
679                          *(out++) = value >> 8;                          {
680                          *(out++) = value >> 16;                                  pixel = *(data++);
681                                    SPLITCOLOUR16(pixel, pc);
682                                    value = MAKECOLOUR(pc);
683                                    LOUT24(out, value);
684                            }
685                  }                  }
686          }          }
687  }  }
688    
689  static void  static void
690  translate16to32(uint16 * data, uint8 * out, uint8 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
691  {  {
692          uint16 pixel;          uint16 pixel;
693          uint32 value;          uint32 value;
694            PixelColour pc;
695    
696          while (out < end)          if (g_compatible_arch)
697            {
698                    /* *INDENT-OFF* */
699                    REPEAT4
700                    (
701                            pixel = *(data++);
702                            SPLITCOLOUR16(pixel, pc);
703                            *(out++) = pc.blue;
704                            *(out++) = pc.green;
705                            *(out++) = pc.red;
706                            *(out++) = 0;
707                    )
708                    /* *INDENT-ON* */
709            }
710            else if (g_xserver_be)
711          {          {
                 pixel = *(data++);  
   
712                  if (g_host_be)                  if (g_host_be)
713                  {                  {
714                          BSWAP16(pixel);                          while (out < end)
715                            {
716                                    pixel = *(data++);
717                                    BSWAP16(pixel);
718                                    SPLITCOLOUR16(pixel, pc);
719                                    value = MAKECOLOUR(pc);
720                                    BOUT32(out, value);
721                            }
722                  }                  }
723                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
724                  {                  {
725                          *(out++) = value >> 24;                          while (out < end)
726                          *(out++) = value >> 16;                          {
727                          *(out++) = value >> 8;                                  pixel = *(data++);
728                          *(out++) = value;                                  SPLITCOLOUR16(pixel, pc);
729                                    value = MAKECOLOUR(pc);
730                                    BOUT32(out, value);
731                            }
732                    }
733            }
734            else
735            {
736                    if (g_host_be)
737                    {
738                            while (out < end)
739                            {
740                                    pixel = *(data++);
741                                    BSWAP16(pixel);
742                                    SPLITCOLOUR16(pixel, pc);
743                                    value = MAKECOLOUR(pc);
744                                    LOUT32(out, value);
745                            }
746                  }                  }
747                  else                  else
748                  {                  {
749                          *(out++) = value;                          while (out < end)
750                          *(out++) = value >> 8;                          {
751                          *(out++) = value >> 16;                                  pixel = *(data++);
752                          *(out++) = value >> 24;                                  SPLITCOLOUR16(pixel, pc);
753                                    value = MAKECOLOUR(pc);
754                                    LOUT32(out, value);
755                            }
756                  }                  }
757          }          }
758  }  }
759    
760  static void  static void
761  translate24to16(uint8 * data, uint8 * out, uint8 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
762  {  {
763          uint32 pixel = 0;          uint32 pixel = 0;
764          uint16 value;          uint16 value;
765            PixelColour pc;
766    
767          while (out < end)          while (out < end)
768          {          {
769                  pixel = *(data++) << 16;                  pixel = *(data++) << 16;
770                  pixel |= *(data++) << 8;                  pixel |= *(data++) << 8;
771                  pixel |= *(data++);                  pixel |= *(data++);
772                    SPLITCOLOUR24(pixel, pc);
773                  value = (uint16) make_colour(split_colour24(pixel));                  value = MAKECOLOUR(pc);
   
774                  if (g_xserver_be)                  if (g_xserver_be)
775                  {                  {
776                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
777                  }                  }
778                  else                  else
779                  {                  {
780                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
781                  }                  }
782          }          }
783  }  }
784    
785  static void  static void
786  translate24to24(uint8 * data, uint8 * out, uint8 * end)  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
787  {  {
788          uint32 pixel;          uint32 pixel;
789          uint32 value;          uint32 value;
790            PixelColour pc;
791    
792          while (out < end)          if (g_xserver_be)
793          {          {
794                  pixel = *(data++) << 16;                  while (out < end)
                 pixel |= *(data++) << 8;  
                 pixel |= *(data++);  
   
                 value = make_colour(split_colour24(pixel));  
   
                 if (g_xserver_be)  
795                  {                  {
796                          *(out++) = value >> 16;                          pixel = *(data++) << 16;
797                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
798                          *(out++) = value;                          pixel |= *(data++);
799                            SPLITCOLOUR24(pixel, pc);
800                            value = MAKECOLOUR(pc);
801                            BOUT24(out, value);
802                  }                  }
803                  else          }
804            else
805            {
806                    while (out < end)
807                  {                  {
808                          *(out++) = value;                          pixel = *(data++) << 16;
809                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
810                          *(out++) = value >> 16;                          pixel |= *(data++);
811                            SPLITCOLOUR24(pixel, pc);
812                            value = MAKECOLOUR(pc);
813                            LOUT24(out, value);
814                  }                  }
815          }          }
816  }  }
817    
818  static void  static void
819  translate24to32(uint8 * data, uint8 * out, uint8 * end)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
820  {  {
821          uint32 pixel;          uint32 pixel;
822          uint32 value;          uint32 value;
823            PixelColour pc;
824    
825          while (out < end)          if (g_compatible_arch)
826          {          {
827                  pixel = *(data++) << 16;                  /* *INDENT-OFF* */
828                  pixel |= *(data++) << 8;  #ifdef NEED_ALIGN
829                  pixel |= *(data++);                  REPEAT4
830                    (
831                  value = make_colour(split_colour24(pixel));                          *(out++) = *(data++);
832                            *(out++) = *(data++);
833                  if (g_xserver_be)                          *(out++) = *(data++);
834                            *(out++) = 0;
835                    )
836    #else
837                    REPEAT4
838                    (
839                     /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
840                     *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
841                     out += 4;
842                     data += 3;
843                    )
844    #endif
845                    /* *INDENT-ON* */
846            }
847            else if (g_xserver_be)
848            {
849                    while (out < end)
850                  {                  {
851                          *(out++) = value >> 24;                          pixel = *(data++) << 16;
852                          *(out++) = value >> 16;                          pixel |= *(data++) << 8;
853                          *(out++) = value >> 8;                          pixel |= *(data++);
854                          *(out++) = value;                          SPLITCOLOUR24(pixel, pc);
855                            value = MAKECOLOUR(pc);
856                            BOUT32(out, value);
857                  }                  }
858                  else          }
859            else
860            {
861                    while (out < end)
862                  {                  {
863                          *(out++) = value;                          pixel = *(data++) << 16;
864                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
865                          *(out++) = value >> 16;                          pixel |= *(data++);
866                          *(out++) = value >> 24;                          SPLITCOLOUR24(pixel, pc);
867                            value = MAKECOLOUR(pc);
868                            LOUT32(out, value);
869                  }                  }
870          }          }
871  }  }
# Line 592  translate24to32(uint8 * data, uint8 * ou Line 873  translate24to32(uint8 * data, uint8 * ou
873  static uint8 *  static uint8 *
874  translate_image(int width, int height, uint8 * data)  translate_image(int width, int height, uint8 * data)
875  {  {
876          int size = width * height * g_bpp / 8;          int size;
877          uint8 *out = (uint8 *) xmalloc(size);          uint8 *out;
878          uint8 *end = out + size;          uint8 *end;
879    
880          switch (g_server_bpp)          /*
881               If RDP depth and X Visual depths match,
882               and arch(endian) matches, no need to translate:
883               just return data.
884               Note: select_visual should've already ensured g_no_translate
885               is only set for compatible depths, but the RDP depth might've
886               changed during connection negotiations.
887             */
888            if (g_no_translate_image)
889            {
890                    if ((g_depth == 15 && g_server_depth == 15) ||
891                        (g_depth == 16 && g_server_depth == 16) ||
892                        (g_depth == 24 && g_server_depth == 24))
893                            return data;
894            }
895    
896            size = width * height * (g_bpp / 8);
897            out = (uint8 *) xmalloc(size);
898            end = out + size;
899    
900            switch (g_server_depth)
901          {          {
902                  case 24:                  case 24:
903                          switch (g_bpp)                          switch (g_bpp)
# Line 694  calculate_shifts(uint32 mask, int *shift Line 995  calculate_shifts(uint32 mask, int *shift
995          *shift_r = 8 - ffs(mask & ~(mask >> 1));          *shift_r = 8 - ffs(mask & ~(mask >> 1));
996  }  }
997    
998  BOOL  /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
999  ui_init(void)     calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1000     */
1001    static unsigned
1002    calculate_mask_weight(uint32 mask)
1003    {
1004            unsigned weight = 0;
1005            do
1006            {
1007                    weight += (mask & 1);
1008            }
1009            while (mask >>= 1);
1010            return weight;
1011    }
1012    
1013    static BOOL
1014    select_visual()
1015  {  {
         XVisualInfo vi;  
1016          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1017          uint16 test;          int pixmap_formats_count, visuals_count;
         int i, screen_num, nvisuals;  
1018          XVisualInfo *vmatches = NULL;          XVisualInfo *vmatches = NULL;
1019          XVisualInfo template;          XVisualInfo template;
1020          Bool TrueColorVisual = False;          int i;
1021            unsigned red_weight, blue_weight, green_weight;
1022    
1023          g_display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1024          if (g_display == NULL)  
1025            pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1026            if (pfm == NULL)
1027          {          {
1028                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1029                    XCloseDisplay(g_display);
1030                  return False;                  return False;
1031          }          }
1032    
1033          screen_num = DefaultScreen(g_display);          /* Search for best TrueColor visual */
         g_x_socket = ConnectionNumber(g_display);  
         g_screen = ScreenOfDisplay(g_display, screen_num);  
         g_depth = DefaultDepthOfScreen(g_screen);  
   
         /* Search for best TrueColor depth */  
1034          template.class = TrueColor;          template.class = TrueColor;
1035          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1036            g_visual = NULL;
1037            g_no_translate_image = False;
1038            g_compatible_arch = False;
1039            if (vmatches != NULL)
1040            {
1041                    for (i = 0; i < visuals_count; ++i)
1042                    {
1043                            XVisualInfo *visual_info = &vmatches[i];
1044    
1045                            /* Try to find a no-translation visual that'll
1046                               allow us to use RDP bitmaps directly as ZPixmaps. */
1047                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1048                                                   /* R5G5B5 */
1049                                                   (visual_info->red_mask == 0x7c00) &&
1050                                                   (visual_info->green_mask == 0x3e0) &&
1051                                                   (visual_info->blue_mask == 0x1f)) ||
1052                                                  ((visual_info->depth == 16) &&
1053                                                   /* R5G6B5 */
1054                                                   (visual_info->red_mask == 0xf800) &&
1055                                                   (visual_info->green_mask == 0x7e0) &&
1056                                                   (visual_info->blue_mask == 0x1f)) ||
1057                                                  ((visual_info->depth == 24) &&
1058                                                   /* R8G8B8 */
1059                                                   (visual_info->red_mask == 0xff0000) &&
1060                                                   (visual_info->green_mask == 0xff00) &&
1061                                                   (visual_info->blue_mask == 0xff))))
1062                            {
1063                                    g_visual = visual_info->visual;
1064                                    g_depth = visual_info->depth;
1065                                    g_compatible_arch = !g_host_be;
1066                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1067                                    if (g_no_translate_image)
1068                                            /* We found the best visual */
1069                                            break;
1070                            }
1071                            else
1072                            {
1073                                    g_compatible_arch = False;
1074                            }
1075    
1076          nvisuals--;                          if (visual_info->depth > 24)
1077          while (nvisuals >= 0)                          {
1078          {                                  /* Avoid 32-bit visuals and likes like the plague.
1079                  if ((vmatches + nvisuals)->depth > g_depth)                                     They're either untested or proven to work bad
1080                  {                                     (e.g. nvidia's Composite 32-bit visual).
1081                          g_depth = (vmatches + nvisuals)->depth;                                     Most implementation offer a 24-bit visual anyway. */
1082                                    continue;
1083                            }
1084    
1085                            /* Only care for visuals, for whose BPPs (not depths!)
1086                               we have a translateXtoY function. */
1087                            BOOL can_translate_to_bpp = False;
1088                            int j;
1089                            for (j = 0; j < pixmap_formats_count; ++j)
1090                            {
1091                                    if (pfm[j].depth == visual_info->depth)
1092                                    {
1093                                            if ((pfm[j].bits_per_pixel == 16) ||
1094                                                (pfm[j].bits_per_pixel == 24) ||
1095                                                (pfm[j].bits_per_pixel == 32))
1096                                            {
1097                                                    can_translate_to_bpp = True;
1098                                            }
1099                                            break;
1100                                    }
1101                            }
1102    
1103                            /* Prefer formats which have the most colour depth.
1104                               We're being truly aristocratic here, minding each
1105                               weight on its own. */
1106                            if (can_translate_to_bpp)
1107                            {
1108                                    unsigned vis_red_weight =
1109                                            calculate_mask_weight(visual_info->red_mask);
1110                                    unsigned vis_green_weight =
1111                                            calculate_mask_weight(visual_info->green_mask);
1112                                    unsigned vis_blue_weight =
1113                                            calculate_mask_weight(visual_info->blue_mask);
1114                                    if ((vis_red_weight >= red_weight)
1115                                        && (vis_green_weight >= green_weight)
1116                                        && (vis_blue_weight >= blue_weight))
1117                                    {
1118                                            red_weight = vis_red_weight;
1119                                            green_weight = vis_green_weight;
1120                                            blue_weight = vis_blue_weight;
1121                                            g_visual = visual_info->visual;
1122                                            g_depth = visual_info->depth;
1123                                    }
1124                            }
1125                  }                  }
1126                  nvisuals--;                  XFree(vmatches);
                 TrueColorVisual = True;  
1127          }          }
1128    
1129          if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))          if (g_visual != NULL)
1130          {          {
1131                  /* we use a colourmap, so the default visual should do */                  g_owncolmap = False;
1132                  g_visual = DefaultVisualOfScreen(g_screen);                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1133                  g_depth = DefaultDepthOfScreen(g_screen);                  calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1134                    calculate_shifts(g_visual->blue_mask, &g_blue_shift_r, &g_blue_shift_l);
                 /* Do not allocate colours on a TrueColor visual */  
                 if (g_visual->class == TrueColor)  
                 {  
                         g_owncolmap = False;  
                 }  
1135          }          }
1136          else          else
1137          {          {
1138                  /* need a truecolour visual */                  template.class = PseudoColor;
1139                  if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))                  template.depth = 8;
1140                  {                  template.colormap_size = 256;
1141                          error("The display does not support true colour - high colour support unavailable.\n");                  vmatches =
1142                            XGetVisualInfo(g_display,
1143                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1144                                           &template, &visuals_count);
1145                    if (vmatches == NULL)
1146                    {
1147                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1148                            XCloseDisplay(g_display);
1149                            XFree(pfm);
1150                          return False;                          return False;
1151                  }                  }
1152    
1153                  g_visual = vi.visual;                  /* we use a colourmap, so the default visual should do */
1154                  g_owncolmap = False;                  g_owncolmap = True;
1155                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);                  g_visual = vmatches[0].visual;
1156                  calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);                  g_depth = vmatches[0].depth;
                 calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);  
1157          }          }
1158    
1159          pfm = XListPixmapFormats(g_display, &i);          g_bpp = 0;
1160          if (pfm != NULL)          for (i = 0; i < pixmap_formats_count; ++i)
1161          {          {
1162                  /* Use maximum bpp for this depth - this is generally                  XPixmapFormatValues *pf = &pfm[i];
1163                     desirable, e.g. 24 bits->32 bits. */                  if (pf->depth == g_depth)
                 while (i--)  
1164                  {                  {
1165                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))                          g_bpp = pf->bits_per_pixel;
1166    
1167                            if (g_no_translate_image)
1168                          {                          {
1169                                  g_bpp = pfm[i].bits_per_pixel;                                  switch (g_server_depth)
1170                                    {
1171                                            case 15:
1172                                            case 16:
1173                                                    if (g_bpp != 16)
1174                                                            g_no_translate_image = False;
1175                                                    break;
1176                                            case 24:
1177                                                    /* Yes, this will force image translation
1178                                                       on most modern servers which use 32 bits
1179                                                       for R8G8B8. */
1180                                                    if (g_bpp != 24)
1181                                                            g_no_translate_image = False;
1182                                                    break;
1183                                            default:
1184                                                    g_no_translate_image = False;
1185                                                    break;
1186                                    }
1187                          }                          }
1188    
1189                            /* Pixmap formats list is a depth-to-bpp mapping --
1190                               there's just a single entry for every depth,
1191                               so we can safely break here */
1192                            break;
1193                  }                  }
                 XFree(pfm);  
1194          }          }
1195            XFree(pfm);
1196            pfm = NULL;
1197            return True;
1198    }
1199    
1200          if (g_bpp < 8)  BOOL
1201    ui_init(void)
1202    {
1203            int screen_num;
1204    
1205            g_display = XOpenDisplay(NULL);
1206            if (g_display == NULL)
1207          {          {
1208                  error("Less than 8 bpp not currently supported.\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
1209                  XCloseDisplay(g_display);                  return False;
1210            }
1211    
1212            {
1213                    uint16 endianess_test = 1;
1214                    g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1215            }
1216    
1217            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1218            screen_num = DefaultScreen(g_display);
1219            g_x_socket = ConnectionNumber(g_display);
1220            g_screen = ScreenOfDisplay(g_display, screen_num);
1221            g_depth = DefaultDepthOfScreen(g_screen);
1222    
1223            if (!select_visual())
1224                  return False;                  return False;
1225    
1226            if (g_no_translate_image)
1227            {
1228                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1229          }          }
1230    
1231            if (g_server_depth > g_bpp)
1232            {
1233                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1234                            g_server_depth, g_bpp);
1235            }
1236    
1237            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1238                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1239    
1240          if (!g_owncolmap)          if (!g_owncolmap)
1241          {          {
1242                  g_xcolmap =                  g_xcolmap =
1243                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1244                                          AllocNone);                                          AllocNone);
1245                  if (g_depth <= 8)                  if (g_depth <= 8)
1246                          warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");                          warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", g_depth);
1247          }          }
1248    
1249          if (DoesBackingStore(g_screen) != Always)          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1250            {
1251                    warning("External BackingStore not available. Using internal.\n");
1252                  g_ownbackstore = True;                  g_ownbackstore = True;
1253            }
         test = 1;  
         g_host_be = !(BOOL) (*(uint8 *) (&test));  
         g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);  
1254    
1255          /*          /*
1256           * Determine desktop size           * Determine desktop size
# Line 809  ui_init(void) Line 1263  ui_init(void)
1263          else if (g_width < 0)          else if (g_width < 0)
1264          {          {
1265                  /* Percent of screen */                  /* Percent of screen */
1266                    if (-g_width >= 100)
1267                            g_using_full_workarea = True;
1268                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1269                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1270          }          }
# Line 816  ui_init(void) Line 1272  ui_init(void)
1272          {          {
1273                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1274                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
1275                    g_using_full_workarea = True;
1276    
1277                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1278                  {                  {
# Line 842  ui_init(void) Line 1299  ui_init(void)
1299    
1300          xclip_init();          xclip_init();
1301    
1302          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
1303    
1304          return True;          return True;
1305  }  }
# Line 870  BOOL Line 1327  BOOL
1327  ui_create_window(void)  ui_create_window(void)
1328  {  {
1329          uint8 null_pointer_mask[1] = { 0x80 };          uint8 null_pointer_mask[1] = { 0x80 };
1330          uint8 null_pointer_data[4] = { 0x00, 0x00, 0x00, 0x00 };          uint8 null_pointer_data[24] = { 0x00 };
1331    
1332          XSetWindowAttributes attribs;          XSetWindowAttributes attribs;
1333          XClassHint *classhints;          XClassHint *classhints;
1334          XSizeHints *sizehints;          XSizeHints *sizehints;
# Line 881  ui_create_window(void) Line 1339  ui_create_window(void)
1339          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1340          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1341    
1342            /* Handle -x-y portion of geometry string */
1343            if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1344                    g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1345            if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1346                    g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1347    
1348          attribs.background_pixel = BlackPixelOfScreen(g_screen);          attribs.background_pixel = BlackPixelOfScreen(g_screen);
1349          attribs.border_pixel = WhitePixelOfScreen(g_screen);          attribs.border_pixel = WhitePixelOfScreen(g_screen);
1350          attribs.backing_store = g_ownbackstore ? NotUseful : Always;          attribs.backing_store = g_ownbackstore ? NotUseful : Always;
1351          attribs.override_redirect = g_fullscreen;          attribs.override_redirect = g_fullscreen;
1352          attribs.colormap = g_xcolmap;          attribs.colormap = g_xcolmap;
1353    
1354          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,          g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1355                                0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
1356                                CWBackPixel | CWBackingStore | CWOverrideRedirect |                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1357                                CWColormap | CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1358    
1359          if (g_gc == NULL)          if (g_gc == NULL)
1360                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1361    
1362            if (g_create_bitmap_gc == NULL)
1363                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1364    
1365          if ((g_ownbackstore) && (g_backstore == 0))          if ((g_ownbackstore) && (g_backstore == 0))
1366          {          {
1367                  g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);                  g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
# Line 921  ui_create_window(void) Line 1388  ui_create_window(void)
1388          if (sizehints)          if (sizehints)
1389          {          {
1390                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1391                    if (g_pos)
1392                            sizehints->flags |= PPosition;
1393                  sizehints->min_width = sizehints->max_width = g_width;                  sizehints->min_width = sizehints->max_width = g_width;
1394                  sizehints->min_height = sizehints->max_height = g_height;                  sizehints->min_height = sizehints->max_height = g_height;
1395                  XSetWMNormalHints(g_display, g_wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
1396                  XFree(sizehints);                  XFree(sizehints);
1397          }          }
1398    
1399            if (g_embed_wnd)
1400            {
1401                    XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1402            }
1403    
1404          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1405                  VisibilityChangeMask | FocusChangeMask;                  VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1406    
1407          if (g_sendmotion)          if (g_sendmotion)
1408                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
# Line 958  ui_create_window(void) Line 1432  ui_create_window(void)
1432                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1433          }          }
1434          while (xevent.type != VisibilityNotify);          while (xevent.type != VisibilityNotify);
1435            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1436    
1437          g_focused = False;          g_focused = False;
1438          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 975  ui_create_window(void) Line 1450  ui_create_window(void)
1450  }  }
1451    
1452  void  void
1453    ui_resize_window()
1454    {
1455            XSizeHints *sizehints;
1456            Pixmap bs;
1457    
1458            sizehints = XAllocSizeHints();
1459            if (sizehints)
1460            {
1461                    sizehints->flags = PMinSize | PMaxSize;
1462                    sizehints->min_width = sizehints->max_width = g_width;
1463                    sizehints->min_height = sizehints->max_height = g_height;
1464                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1465                    XFree(sizehints);
1466            }
1467    
1468            if (!(g_fullscreen || g_embed_wnd))
1469            {
1470                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1471            }
1472    
1473            /* create new backstore pixmap */
1474            if (g_backstore != 0)
1475            {
1476                    bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1477                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1478                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1479                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1480                    XFreePixmap(g_display, g_backstore);
1481                    g_backstore = bs;
1482            }
1483    }
1484    
1485    void
1486  ui_destroy_window(void)  ui_destroy_window(void)
1487  {  {
1488          if (g_IC != NULL)          if (g_IC != NULL)
# Line 1008  xwin_toggle_fullscreen(void) Line 1516  xwin_toggle_fullscreen(void)
1516          }          }
1517  }  }
1518    
1519  /* Process all events in Xlib queue  static void
1520    handle_button_event(XEvent xevent, BOOL down)
1521    {
1522            uint16 button, flags = 0;
1523            g_last_gesturetime = xevent.xbutton.time;
1524            button = xkeymap_translate_button(xevent.xbutton.button);
1525            if (button == 0)
1526                    return;
1527    
1528            if (down)
1529                    flags = MOUSE_FLAG_DOWN;
1530    
1531            /* Stop moving window when button is released, regardless of cursor position */
1532            if (g_moving_wnd && (xevent.type == ButtonRelease))
1533                    g_moving_wnd = False;
1534    
1535            /* If win_button_size is nonzero, enable single app mode */
1536            if (xevent.xbutton.y < g_win_button_size)
1537            {
1538                    /*  Check from right to left: */
1539                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1540                    {
1541                            /* The close button, continue */
1542                            ;
1543                    }
1544                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1545                    {
1546                            /* The maximize/restore button. Do not send to
1547                               server.  It might be a good idea to change the
1548                               cursor or give some other visible indication
1549                               that rdesktop inhibited this click */
1550                            if (xevent.type == ButtonPress)
1551                                    return;
1552                    }
1553                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1554                    {
1555                            /* The minimize button. Iconify window. */
1556                            if (xevent.type == ButtonRelease)
1557                            {
1558                                    /* Release the mouse button outside the minimize button, to prevent the
1559                                       actual minimazation to happen */
1560                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1561                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1562                                    return;
1563                            }
1564                    }
1565                    else if (xevent.xbutton.x <= g_win_button_size)
1566                    {
1567                            /* The system menu. Ignore. */
1568                            if (xevent.type == ButtonPress)
1569                                    return;
1570                    }
1571                    else
1572                    {
1573                            /* The title bar. */
1574                            if (xevent.type == ButtonPress)
1575                            {
1576                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1577                                    {
1578                                            g_moving_wnd = True;
1579                                            g_move_x_offset = xevent.xbutton.x;
1580                                            g_move_y_offset = xevent.xbutton.y;
1581                                    }
1582                                    return;
1583                            }
1584                    }
1585            }
1586    
1587            rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1588                           flags | button, xevent.xbutton.x, xevent.xbutton.y);
1589    }
1590    
1591    /* Process events in Xlib queue
1592     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1593  static int  static int
1594  xwin_process_events(void)  xwin_process_events(void)
1595  {  {
1596          XEvent xevent;          XEvent xevent;
1597          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1598          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1599          char str[256];          char str[256];
1600          Status status;          Status status;
1601            int events = 0;
1602    
1603          while (XPending(g_display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1604          {          {
1605                  XNextEvent(g_display, &xevent);                  XNextEvent(g_display, &xevent);
1606    
# Line 1031  xwin_process_events(void) Line 1610  xwin_process_events(void)
1610                          continue;                          continue;
1611                  }                  }
1612    
                 flags = 0;  
   
1613                  switch (xevent.type)                  switch (xevent.type)
1614                  {                  {
1615                            case VisibilityNotify:
1616                                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1617                                    break;
1618                          case ClientMessage:                          case ClientMessage:
1619                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
1620                                  if ((xevent.xclient.message_type == g_protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
# Line 1066  xwin_process_events(void) Line 1646  xwin_process_events(void)
1646                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1647                                  }                                  }
1648    
1649                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1650                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1651    
1652                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1653                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1654                                          break;                                          break;
1655    
1656                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1657                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, True, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 save_remote_modifiers(tr.scancode);  
                                 ensure_remote_modifiers(ev_time, tr);  
                                 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);  
                                 restore_remote_modifiers(ev_time, tr.scancode);  
   
1658                                  break;                                  break;
1659    
1660                          case KeyRelease:                          case KeyRelease:
# Line 1091  xwin_process_events(void) Line 1662  xwin_process_events(void)
1662                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
1663                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
1664    
1665                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1666                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1667    
1668                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1669                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1670                                          break;                                          break;
1671    
1672                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1673                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
1674                                  break;                                  break;
1675    
1676                          case ButtonPress:                          case ButtonPress:
1677                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
1678                                  /* fall through */                                  break;
1679    
1680                          case ButtonRelease:                          case ButtonRelease:
1681                                  g_last_gesturetime = xevent.xbutton.time;                                  handle_button_event(xevent, False);
                                 button = xkeymap_translate_button(xevent.xbutton.button);  
                                 if (button == 0)  
                                         break;  
   
                                 /* If win_button_size is nonzero, enable single app mode */  
                                 if (xevent.xbutton.y < g_win_button_size)  
                                 {  
                                         /* Stop moving window when button is released, regardless of cursor position */  
                                         if (g_moving_wnd && (xevent.type == ButtonRelease))  
                                                 g_moving_wnd = False;  
   
                                         /*  Check from right to left: */  
   
                                         if (xevent.xbutton.x >= g_width - g_win_button_size)  
                                         {  
                                                 /* The close button, continue */  
                                                 ;  
                                         }  
                                         else if (xevent.xbutton.x >=  
                                                  g_width - g_win_button_size * 2)  
                                         {  
                                                 /* The maximize/restore button. Do not send to  
                                                    server.  It might be a good idea to change the  
                                                    cursor or give some other visible indication  
                                                    that rdesktop inhibited this click */  
                                                 break;  
                                         }  
                                         else if (xevent.xbutton.x >=  
                                                  g_width - g_win_button_size * 3)  
                                         {  
                                                 /* The minimize button. Iconify window. */  
                                                 XIconifyWindow(g_display, g_wnd,  
                                                                DefaultScreen(g_display));  
                                                 break;  
                                         }  
                                         else if (xevent.xbutton.x <= g_win_button_size)  
                                         {  
                                                 /* The system menu. Ignore. */  
                                                 break;  
                                         }  
                                         else  
                                         {  
                                                 /* The title bar. */  
                                                 if ((xevent.type == ButtonPress) && !g_fullscreen  
                                                     && g_hide_decorations)  
                                                 {  
                                                         g_moving_wnd = True;  
                                                         g_move_x_offset = xevent.xbutton.x;  
                                                         g_move_y_offset = xevent.xbutton.y;  
                                                 }  
                                                 break;  
   
                                         }  
                                 }  
   
                                 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
                                                flags | button, xevent.xbutton.x, xevent.xbutton.y);  
1682                                  break;                                  break;
1683    
1684                          case MotionNotify:                          case MotionNotify:
# Line 1262  xwin_process_events(void) Line 1771  xwin_process_events(void)
1771                          case PropertyNotify:                          case PropertyNotify:
1772                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
1773                                  break;                                  break;
1774                            case MapNotify:
1775                                    rdp_send_client_window_status(1);
1776                                    break;
1777                            case UnmapNotify:
1778                                    rdp_send_client_window_status(0);
1779                                    break;
1780                  }                  }
1781          }          }
1782          /* Keep going */          /* Keep going */
# Line 1272  xwin_process_events(void) Line 1787  xwin_process_events(void)
1787  int  int
1788  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1789  {  {
1790          int n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;          int n;
1791          fd_set rfds, wfds;          fd_set rfds, wfds;
1792          struct timeval tv;          struct timeval tv;
1793          BOOL s_timeout = False;          BOOL s_timeout = False;
1794    
1795          while (True)          while (True)
1796          {          {
1797                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1798                  /* Process any events already waiting */                  /* Process any events already waiting */
1799                  if (!xwin_process_events())                  if (!xwin_process_events())
1800                          /* User quit */                          /* User quit */
# Line 1312  ui_select(int rdp_socket) Line 1828  ui_select(int rdp_socket)
1828                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
1829    
1830                          case 0:                          case 0:
1831                                  /* TODO: if tv.tv_sec just times out                                  /* Abort serial read calls */
1832                                   * we will segfault.                                  if (s_timeout)
1833                                   * FIXME:                                          rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
                                  */  
                                 //s_timeout = True;  
                                 //rdpdr_check_fds(&rfds, &wfds, (BOOL) True);  
1834                                  continue;                                  continue;
1835                  }                  }
1836    
# Line 1347  ui_create_bitmap(int width, int height, Line 1860  ui_create_bitmap(int width, int height,
1860          uint8 *tdata;          uint8 *tdata;
1861          int bitmap_pad;          int bitmap_pad;
1862    
1863          if (g_server_bpp == 8)          if (g_server_depth == 8)
1864          {          {
1865                  bitmap_pad = 8;                  bitmap_pad = 8;
1866          }          }
# Line 1364  ui_create_bitmap(int width, int height, Line 1877  ui_create_bitmap(int width, int height,
1877          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1878                               (char *) tdata, width, height, bitmap_pad, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
1879    
1880          XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);          XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
1881    
1882          XFree(image);          XFree(image);
1883          if (!g_owncolmap)          if (tdata != data)
1884                  xfree(tdata);                  xfree(tdata);
1885          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1886  }  }
# Line 1379  ui_paint_bitmap(int x, int y, int cx, in Line 1892  ui_paint_bitmap(int x, int y, int cx, in
1892          uint8 *tdata;          uint8 *tdata;
1893          int bitmap_pad;          int bitmap_pad;
1894    
1895          if (g_server_bpp == 8)          if (g_server_depth == 8)
1896          {          {
1897                  bitmap_pad = 8;                  bitmap_pad = 8;
1898          }          }
# Line 1406  ui_paint_bitmap(int x, int y, int cx, in Line 1919  ui_paint_bitmap(int x, int y, int cx, in
1919          }          }
1920    
1921          XFree(image);          XFree(image);
1922          if (!g_owncolmap)          if (tdata != data)
1923                  xfree(tdata);                  xfree(tdata);
1924  }  }
1925    
# Line 1422  ui_create_glyph(int width, int height, u Line 1935  ui_create_glyph(int width, int height, u
1935          XImage *image;          XImage *image;
1936          Pixmap bitmap;          Pixmap bitmap;
1937          int scanline;          int scanline;
         GC gc;  
1938    
1939          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1940    
1941          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1942          gc = XCreateGC(g_display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
1943                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1944    
1945          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1946                               width, height, 8, scanline);                               width, height, 8, scanline);
# Line 1435  ui_create_glyph(int width, int height, u Line 1948  ui_create_glyph(int width, int height, u
1948          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1949          XInitImage(image);          XInitImage(image);
1950    
1951          XPutImage(g_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);
1952    
1953          XFree(image);          XFree(image);
         XFreeGC(g_display, gc);  
1954          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1955  }  }
1956    
# Line 1730  ui_patblt(uint8 opcode, Line 2242  ui_patblt(uint8 opcode,
2242          {          {
2243                  case 0: /* Solid */                  case 0: /* Solid */
2244                          SET_FOREGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
2245                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2246                          break;                          break;
2247    
2248                  case 2: /* Hatch */                  case 2: /* Hatch */
# Line 1741  ui_patblt(uint8 opcode, Line 2253  ui_patblt(uint8 opcode,
2253                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2254                          XSetStipple(g_display, g_gc, fill);                          XSetStipple(g_display, g_gc, fill);
2255                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2256                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2257                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2258                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2259                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
# Line 1751  ui_patblt(uint8 opcode, Line 2263  ui_patblt(uint8 opcode,
2263                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
2264                                  ipattern[7 - i] = brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
2265                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
   
2266                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
2267                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
2268                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2269                          XSetStipple(g_display, g_gc, fill);                          XSetStipple(g_display, g_gc, fill);
2270                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2271                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
                         FILL_RECTANGLE(x, y, cx, cy);  
   
2272                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2273                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2274                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
# Line 1770  ui_patblt(uint8 opcode, Line 2279  ui_patblt(uint8 opcode,
2279          }          }
2280    
2281          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2282    
2283            if (g_ownbackstore)
2284                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2285  }  }
2286    
2287  void  void
# Line 1778  ui_screenblt(uint8 opcode, Line 2290  ui_screenblt(uint8 opcode,
2290               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
2291  {  {
2292          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
         XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);  
2293          if (g_ownbackstore)          if (g_ownbackstore)
2294                  XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);          {
2295                    if (g_Unobscured)
2296                    {
2297                            XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2298                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2299                                      y);
2300                    }
2301                    else
2302                    {
2303                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2304                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2305                                      y);
2306                    }
2307            }
2308            else
2309            {
2310                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2311            }
2312          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2313  }  }
2314    
# Line 1851  ui_rect( Line 2379  ui_rect(
2379          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2380  }  }
2381    
2382    void
2383    ui_polygon(uint8 opcode,
2384               /* mode */ uint8 fillmode,
2385               /* dest */ POINT * point, int npoints,
2386               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2387    {
2388            uint8 style, i, ipattern[8];
2389            Pixmap fill;
2390    
2391            SET_FUNCTION(opcode);
2392    
2393            switch (fillmode)
2394            {
2395                    case ALTERNATE:
2396                            XSetFillRule(g_display, g_gc, EvenOddRule);
2397                            break;
2398                    case WINDING:
2399                            XSetFillRule(g_display, g_gc, WindingRule);
2400                            break;
2401                    default:
2402                            unimpl("fill mode %d\n", fillmode);
2403            }
2404    
2405            if (brush)
2406                    style = brush->style;
2407            else
2408                    style = 0;
2409    
2410            switch (style)
2411            {
2412                    case 0: /* Solid */
2413                            SET_FOREGROUND(fgcolour);
2414                            FILL_POLYGON((XPoint *) point, npoints);
2415                            break;
2416    
2417                    case 2: /* Hatch */
2418                            fill = (Pixmap) ui_create_glyph(8, 8,
2419                                                            hatch_patterns + brush->pattern[0] * 8);
2420                            SET_FOREGROUND(fgcolour);
2421                            SET_BACKGROUND(bgcolour);
2422                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2423                            XSetStipple(g_display, g_gc, fill);
2424                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2425                            FILL_POLYGON((XPoint *) point, npoints);
2426                            XSetFillStyle(g_display, g_gc, FillSolid);
2427                            XSetTSOrigin(g_display, g_gc, 0, 0);
2428                            ui_destroy_glyph((HGLYPH) fill);
2429                            break;
2430    
2431                    case 3: /* Pattern */
2432                            for (i = 0; i != 8; i++)
2433                                    ipattern[7 - i] = brush->pattern[i];
2434                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2435                            SET_FOREGROUND(bgcolour);
2436                            SET_BACKGROUND(fgcolour);
2437                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2438                            XSetStipple(g_display, g_gc, fill);
2439                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2440                            FILL_POLYGON((XPoint *) point, npoints);
2441                            XSetFillStyle(g_display, g_gc, FillSolid);
2442                            XSetTSOrigin(g_display, g_gc, 0, 0);
2443                            ui_destroy_glyph((HGLYPH) fill);
2444                            break;
2445    
2446                    default:
2447                            unimpl("brush %d\n", brush->style);
2448            }
2449    
2450            RESET_FUNCTION(opcode);
2451    }
2452    
2453    void
2454    ui_polyline(uint8 opcode,
2455                /* dest */ POINT * points, int npoints,
2456                /* pen */ PEN * pen)
2457    {
2458            /* TODO: set join style */
2459            SET_FUNCTION(opcode);
2460            SET_FOREGROUND(pen->colour);
2461            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2462            if (g_ownbackstore)
2463                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2464                               CoordModePrevious);
2465            RESET_FUNCTION(opcode);
2466    }
2467    
2468    void
2469    ui_ellipse(uint8 opcode,
2470               /* mode */ uint8 fillmode,
2471               /* dest */ int x, int y, int cx, int cy,
2472               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2473    {
2474            uint8 style, i, ipattern[8];
2475            Pixmap fill;
2476    
2477            SET_FUNCTION(opcode);
2478    
2479            if (brush)
2480                    style = brush->style;
2481            else
2482                    style = 0;
2483    
2484            switch (style)
2485            {
2486                    case 0: /* Solid */
2487                            SET_FOREGROUND(fgcolour);
2488                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2489                            break;
2490    
2491                    case 2: /* Hatch */
2492                            fill = (Pixmap) ui_create_glyph(8, 8,
2493                                                            hatch_patterns + brush->pattern[0] * 8);
2494                            SET_FOREGROUND(fgcolour);
2495                            SET_BACKGROUND(bgcolour);
2496                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2497                            XSetStipple(g_display, g_gc, fill);
2498                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2499                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2500                            XSetFillStyle(g_display, g_gc, FillSolid);
2501                            XSetTSOrigin(g_display, g_gc, 0, 0);
2502                            ui_destroy_glyph((HGLYPH) fill);
2503                            break;
2504    
2505                    case 3: /* Pattern */
2506                            for (i = 0; i != 8; i++)
2507                                    ipattern[7 - i] = brush->pattern[i];
2508                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2509                            SET_FOREGROUND(bgcolour);
2510                            SET_BACKGROUND(fgcolour);
2511                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2512                            XSetStipple(g_display, g_gc, fill);
2513                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2514                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2515                            XSetFillStyle(g_display, g_gc, FillSolid);
2516                            XSetTSOrigin(g_display, g_gc, 0, 0);
2517                            ui_destroy_glyph((HGLYPH) fill);
2518                            break;
2519    
2520                    default:
2521                            unimpl("brush %d\n", brush->style);
2522            }
2523    
2524            RESET_FUNCTION(opcode);
2525    }
2526    
2527  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
2528  void  void
2529  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 1906  ui_draw_glyph(int mixmode, Line 2579  ui_draw_glyph(int mixmode,
2579  }  }
2580    
2581  void  void
2582  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,
2583               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2584               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2585               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2586  {  {
2587            /* TODO: use brush appropriately */
2588    
2589          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2590          int i, j, xyoffset, x1, y1;          int i, j, xyoffset, x1, y1;
2591          DATABLOB *entry;          DATABLOB *entry;
2592    
2593          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
2594    
2595            /* Sometimes, the boxcx value is something really large, like
2596               32691. This makes XCopyArea fail with Xvnc. The code below
2597               is a quick fix. */
2598            if (boxx + boxcx > g_width)
2599                    boxcx = g_width - boxx;
2600    
2601          if (boxcx > 1)          if (boxcx > 1)
2602          {          {
2603                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
# Line 1936  ui_draw_text(uint8 font, uint8 flags, in Line 2617  ui_draw_text(uint8 font, uint8 flags, in
2617                  switch (text[i])                  switch (text[i])
2618                  {                  {
2619                          case 0xff:                          case 0xff:
2620                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
2621                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
2622                                  {                                  {
2623                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
2624                                          exit(1);                                          for (j = 0; j < length; j++)
2625                                                    fprintf(stderr, "%02x ", text[j]);
2626                                            fprintf(stderr, "\n");
2627                                            i = length = 0;
2628                                            break;
2629                                  }                                  }
2630                                    cache_put_text(text[i + 1], text, text[i + 2]);
2631                                    i += 3;
2632                                    length -= i;
2633                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2634                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
2635                                  i = 0;                                  i = 0;
2636                                  break;                                  break;
2637    
2638                          case 0xfe:                          case 0xfe:
2639                                    /* At least one byte needs to follow */
2640                                    if (i + 2 > length)
2641                                    {
2642                                            warning("Skipping short 0xfe command:");
2643                                            for (j = 0; j < length; j++)
2644                                                    fprintf(stderr, "%02x ", text[j]);
2645                                            fprintf(stderr, "\n");
2646                                            i = length = 0;
2647                                            break;
2648                                    }
2649                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
2650                                  if (entry != NULL)                                  if (entry->data != NULL)
2651                                  {                                  {
2652                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
2653                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
2654                                          {                                          {
2655                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2656                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 2044  ui_desktop_restore(uint32 offset, int x, Line 2740  ui_desktop_restore(uint32 offset, int x,
2740    
2741          XFree(image);          XFree(image);
2742  }  }
2743    
2744    /* these do nothing here but are used in uiports */
2745    void
2746    ui_begin_update(void)
2747    {
2748    }
2749    
2750    void
2751    ui_end_update(void)
2752    {
2753    }

Legend:
Removed from v.603  
changed lines
  Added in v.1049

  ViewVC Help
Powered by ViewVC 1.1.26