/[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 1042 by astrand, Tue Jan 24 12:40:24 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 the visual is has 15, 16 or 24 depth
75       and the same color channel masks as its RDP equivalent. */
76    static BOOL g_compatible_depth;
77    /* Indicates whether RDP's bitmaps and our XImages have the same
78       binary format. If so, we can avoid an expensive translation.
79       If this is True, so is g_compatible_depth. */
80    static BOOL g_no_translate_image = False;
81    
82  /* endianness */  /* endianness */
83  static BOOL g_host_be;  static BOOL g_host_be;
# Line 63  static int g_red_shift_r, g_blue_shift_r Line 86  static int g_red_shift_r, g_blue_shift_r
86  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;
87    
88  /* software backing store */  /* software backing store */
89  static BOOL g_ownbackstore;  extern BOOL g_ownbackstore;
90  static Pixmap g_backstore = 0;  static Pixmap g_backstore = 0;
91    
92  /* Moving in single app mode */  /* Moving in single app mode */
93  static BOOL g_moving_wnd;  static BOOL g_moving_wnd;
94  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
95  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
96    static BOOL g_using_full_workarea = False;
97    
98  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
99  extern int g_dsp_fd;  extern int g_dsp_fd;
# Line 82  extern BOOL g_rdpsnd; Line 106  extern BOOL g_rdpsnd;
106  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
107  typedef struct  typedef struct
108  {  {
109          uint32 flags;          unsigned long flags;
110          uint32 functions;          unsigned long functions;
111          uint32 decorations;          unsigned long decorations;
112          sint32 inputMode;          long inputMode;
113          uint32 status;          unsigned long status;
114  }  }
115  PropMotifWmHints;  PropMotifWmHints;
116    
# Line 111  PixelColour; Line 135  PixelColour;
135          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); \
136  }  }
137    
138    #define FILL_POLYGON(p,np)\
139    { \
140            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
141            if (g_ownbackstore) \
142                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
143    }
144    
145    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
146    { \
147            switch (m) \
148            { \
149                    case 0: /* Outline */ \
150                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
151                            if (g_ownbackstore) \
152                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
153                            break; \
154                    case 1: /* Filled */ \
155                            XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
156                            if (g_ownbackstore) \
157                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
158                            break; \
159            } \
160    }
161    
162  /* colour maps */  /* colour maps */
163  BOOL g_owncolmap = False;  extern BOOL g_owncolmap;
164  static Colormap g_xcolmap;  static Colormap g_xcolmap;
165  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
166    
167  #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] )
168  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
169  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
170    
# Line 164  mwm_hide_decorations(void) Line 212  mwm_hide_decorations(void)
212                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
213  }  }
214    
215  static PixelColour  #define SPLITCOLOUR15(colour, rv) \
216  split_colour15(uint32 colour)  { \
217  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
218          PixelColour rv;          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
219          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;  
220  }  }
221    
222  static uint32  #define SPLITCOLOUR16(colour, rv) \
223  make_colour(PixelColour pc)  { \
224  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
225          return (((pc.red >> g_red_shift_r) << g_red_shift_l)          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
226                  | ((pc.green >> g_green_shift_r) << g_green_shift_l)          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
227                  | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l));  } \
228    
229    #define SPLITCOLOUR24(colour, rv) \
230    { \
231            rv.blue = (colour & 0xff0000) >> 16; \
232            rv.green = (colour & 0x00ff00) >> 8; \
233            rv.red = (colour & 0x0000ff); \
234  }  }
235    
236    #define MAKECOLOUR(pc) \
237            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
238                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
239                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
240    
241  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
242  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
243  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
244                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
245    
246    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
247    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
248    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
249    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
250    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
251    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
252    
253  static uint32  static uint32
254  translate_colour(uint32 colour)  translate_colour(uint32 colour)
255  {  {
256          PixelColour pc;          PixelColour pc;
257          switch (g_server_bpp)          switch (g_server_depth)
258          {          {
259                  case 15:                  case 15:
260                          pc = split_colour15(colour);                          SPLITCOLOUR15(colour, pc);
261                          break;                          break;
262                  case 16:                  case 16:
263                          pc = split_colour16(colour);                          SPLITCOLOUR16(colour, pc);
264                          break;                          break;
265                  case 24:                  case 24:
266                          pc = split_colour24(colour);                          SPLITCOLOUR24(colour, pc);
267                            break;
268                    default:
269                            /* Avoid warning */
270                            pc.red = 0;
271                            pc.green = 0;
272                            pc.blue = 0;
273                          break;                          break;
274          }          }
275          return make_colour(pc);          return MAKECOLOUR(pc);
276  }  }
277    
278    /* indent is confused by UNROLL8 */
279    /* *INDENT-OFF* */
280    
281    /* repeat and unroll, similar to bitmap.c */
282    /* potentialy any of the following translate */
283    /* functions can use repeat but just doing */
284    /* the most common ones */
285    
286    #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
287    /* 2 byte output repeat */
288    #define REPEAT2(stm) \
289    { \
290            while (out <= end - 8 * 2) \
291                    UNROLL8(stm) \
292            while (out < end) \
293                    { stm } \
294    }
295    /* 3 byte output repeat */
296    #define REPEAT3(stm) \
297    { \
298            while (out <= end - 8 * 3) \
299                    UNROLL8(stm) \
300            while (out < end) \
301                    { stm } \
302    }
303    /* 4 byte output repeat */
304    #define REPEAT4(stm) \
305    { \
306            while (out <= end - 8 * 4) \
307                    UNROLL8(stm) \
308            while (out < end) \
309                    { stm } \
310    }
311    /* *INDENT-ON* */
312    
313  static void  static void
314  translate8to8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
315  {  {
316          while (out < end)          while (out < end)
317                  *(out++) = (uint8) g_colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
318  }  }
319    
320  static void  static void
321  translate8to16(uint8 * data, uint8 * out, uint8 * end)  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
322  {  {
323          uint16 value;          uint16 value;
324    
325          while (out < end)          if (g_compatible_depth)
326          {          {
327                  value = (uint16) g_colmap[*(data++)];                  /* *INDENT-OFF* */
328                    REPEAT2
329                  if (g_xserver_be)                  (
330                            *((uint16 *) out) = g_colmap[*(data++)];
331                            out += 2;
332                    )
333                    /* *INDENT-ON* */
334            }
335            else if (g_xserver_be)
336            {
337                    while (out < end)
338                  {                  {
339                          *(out++) = value >> 8;                          value = (uint16) g_colmap[*(data++)];
340                          *(out++) = value;                          BOUT16(out, value);
341                  }                  }
342                  else          }
343            else
344            {
345                    while (out < end)
346                  {                  {
347                          *(out++) = value;                          value = (uint16) g_colmap[*(data++)];
348                          *(out++) = value >> 8;                          LOUT16(out, value);
349                  }                  }
350          }          }
351  }  }
352    
353  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
354  static void  static void
355  translate8to24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
356  {  {
357          uint32 value;          uint32 value;
358    
359          while (out < end)          if (g_compatible_depth)
360          {          {
361                  value = g_colmap[*(data++)];                  while (out < end)
   
                 if (g_xserver_be)  
362                  {                  {
363                          *(out++) = value >> 16;                          value = g_colmap[*(data++)];
364                          *(out++) = value >> 8;                          BOUT24(out, value);
                         *(out++) = value;  
365                  }                  }
366                  else          }
367            else
368            {
369                    while (out < end)
370                  {                  {
371                          *(out++) = value;                          value = g_colmap[*(data++)];
372                          *(out++) = value >> 8;                          LOUT24(out, value);
                         *(out++) = value >> 16;  
373                  }                  }
374          }          }
375  }  }
376    
377  static void  static void
378  translate8to32(uint8 * data, uint8 * out, uint8 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
379  {  {
380          uint32 value;          uint32 value;
381    
382          while (out < end)          if (g_compatible_depth)
383          {          {
384                  value = g_colmap[*(data++)];                  /* *INDENT-OFF* */
385                    REPEAT4
386                  if (g_xserver_be)                  (
387                            *((uint32 *) out) = g_colmap[*(data++)];
388                            out += 4;
389                    )
390                    /* *INDENT-ON* */
391            }
392            else if (g_xserver_be)
393            {
394                    while (out < end)
395                  {                  {
396                          *(out++) = value >> 24;                          value = g_colmap[*(data++)];
397                          *(out++) = value >> 16;                          BOUT32(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value;  
398                  }                  }
399                  else          }
400            else
401            {
402                    while (out < end)
403                  {                  {
404                          *(out++) = value;                          value = g_colmap[*(data++)];
405                          *(out++) = value >> 8;                          LOUT32(out, value);
                         *(out++) = value >> 16;  
                         *(out++) = value >> 24;  
406                  }                  }
407          }          }
408  }  }
409    
410  static void  static void
411  translate15to16(uint16 * data, uint8 * out, uint8 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
412  {  {
413          uint16 pixel;          uint16 pixel;
414          uint16 value;          uint16 value;
415            PixelColour pc;
416    
417          while (out < end)          if (g_xserver_be)
418          {          {
419                  pixel = *(data++);                  while (out < end)
   
                 if (g_host_be)  
                 {  
                         BSWAP16(pixel);  
                 }  
   
                 value = make_colour(split_colour15(pixel));  
   
                 if (g_xserver_be)  
420                  {                  {
421                          *(out++) = value >> 8;                          pixel = *(data++);
422                          *(out++) = value;                          if (g_host_be)
423                            {
424                                    BSWAP16(pixel);
425                            }
426                            SPLITCOLOUR15(pixel, pc);
427                            value = MAKECOLOUR(pc);
428                            BOUT16(out, value);
429                  }                  }
430                  else          }
431            else
432            {
433                    while (out < end)
434                  {                  {
435                          *(out++) = value;                          pixel = *(data++);
436                          *(out++) = value >> 8;                          if (g_host_be)
437                            {
438                                    BSWAP16(pixel);
439                            }
440                            SPLITCOLOUR15(pixel, pc);
441                            value = MAKECOLOUR(pc);
442                            LOUT16(out, value);
443                  }                  }
444          }          }
445  }  }
446    
447  static void  static void
448  translate15to24(uint16 * data, uint8 * out, uint8 * end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
449  {  {
450          uint32 value;          uint32 value;
451          uint16 pixel;          uint16 pixel;
452            PixelColour pc;
453    
454          while (out < end)          if (g_compatible_depth)
455          {          {
456                  pixel = *(data++);                  /* *INDENT-OFF* */
457                    REPEAT3
458                  if (g_host_be)                  (
459                  {                          pixel = *(data++);
460                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
461                  }                          *(out++) = pc.blue;
462                            *(out++) = pc.green;
463                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
464                  if (g_xserver_be)                  )
465                    /* *INDENT-ON* */
466            }
467            else if (g_xserver_be)
468            {
469                    while (out < end)
470                  {                  {
471                          *(out++) = value >> 16;                          pixel = *(data++);
472                          *(out++) = value >> 8;                          if (g_host_be)
473                          *(out++) = value;                          {
474                                    BSWAP16(pixel);
475                            }
476                            SPLITCOLOUR15(pixel, pc);
477                            value = MAKECOLOUR(pc);
478                            BOUT24(out, value);
479                  }                  }
480                  else          }
481            else
482            {
483                    while (out < end)
484                  {                  {
485                          *(out++) = value;                          pixel = *(data++);
486                          *(out++) = value >> 8;                          if (g_host_be)
487                          *(out++) = value >> 16;                          {
488                                    BSWAP16(pixel);
489                            }
490                            SPLITCOLOUR15(pixel, pc);
491                            value = MAKECOLOUR(pc);
492                            LOUT24(out, value);
493                  }                  }
494          }          }
495  }  }
496    
497  static void  static void
498  translate15to32(uint16 * data, uint8 * out, uint8 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
499  {  {
500          uint16 pixel;          uint16 pixel;
501          uint32 value;          uint32 value;
502            PixelColour pc;
503    
504          while (out < end)          if (g_compatible_depth)
505          {          {
506                  pixel = *(data++);                  /* *INDENT-OFF* */
507                    REPEAT4
508                  if (g_host_be)                  (
509                  {                          pixel = *(data++);
510                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
511                  }                          *(out++) = pc.blue;
512                            *(out++) = pc.green;
513                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
514                            *(out++) = 0;
515                  if (g_xserver_be)                  )
516                    /* *INDENT-ON* */
517            }
518            else if (g_xserver_be)
519            {
520                    while (out < end)
521                  {                  {
522                          *(out++) = value >> 24;                          pixel = *(data++);
523                          *(out++) = value >> 16;                          if (g_host_be)
524                          *(out++) = value >> 8;                          {
525                          *(out++) = value;                                  BSWAP16(pixel);
526                            }
527                            SPLITCOLOUR15(pixel, pc);
528                            value = MAKECOLOUR(pc);
529                            BOUT32(out, value);
530                  }                  }
531                  else          }
532            else
533            {
534                    while (out < end)
535                  {                  {
536                          *(out++) = value;                          pixel = *(data++);
537                          *(out++) = value >> 8;                          if (g_host_be)
538                          *(out++) = value >> 16;                          {
539                          *(out++) = value >> 24;                                  BSWAP16(pixel);
540                            }
541                            SPLITCOLOUR15(pixel, pc);
542                            value = MAKECOLOUR(pc);
543                            LOUT32(out, value);
544                  }                  }
545          }          }
546  }  }
547    
548  static void  static void
549  translate16to16(uint16 * data, uint8 * out, uint8 * end)  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
550  {  {
551          uint16 pixel;          uint16 pixel;
552          uint16 value;          uint16 value;
553            PixelColour pc;
554    
555          while (out < end)          if (g_xserver_be)
556          {          {
                 pixel = *(data++);  
   
557                  if (g_host_be)                  if (g_host_be)
558                  {                  {
559                          BSWAP16(pixel);                          while (out < end)
560                            {
561                                    pixel = *(data++);
562                                    BSWAP16(pixel);
563                                    SPLITCOLOUR16(pixel, pc);
564                                    value = MAKECOLOUR(pc);
565                                    BOUT16(out, value);
566                            }
567                  }                  }
568                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
569                  {                  {
570                          *(out++) = value >> 8;                          while (out < end)
571                          *(out++) = value;                          {
572                                    pixel = *(data++);
573                                    SPLITCOLOUR16(pixel, pc);
574                                    value = MAKECOLOUR(pc);
575                                    BOUT16(out, value);
576                            }
577                    }
578            }
579            else
580            {
581                    if (g_host_be)
582                    {
583                            while (out < end)
584                            {
585                                    pixel = *(data++);
586                                    BSWAP16(pixel);
587                                    SPLITCOLOUR16(pixel, pc);
588                                    value = MAKECOLOUR(pc);
589                                    LOUT16(out, value);
590                            }
591                  }                  }
592                  else                  else
593                  {                  {
594                          *(out++) = value;                          while (out < end)
595                          *(out++) = value >> 8;                          {
596                                    pixel = *(data++);
597                                    SPLITCOLOUR16(pixel, pc);
598                                    value = MAKECOLOUR(pc);
599                                    LOUT16(out, value);
600                            }
601                  }                  }
602          }          }
603  }  }
604    
605  static void  static void
606  translate16to24(uint16 * data, uint8 * out, uint8 * end)  translate16to24(const uint16 * data, uint8 * out, uint8 * end)
607  {  {
608          uint32 value;          uint32 value;
609          uint16 pixel;          uint16 pixel;
610            PixelColour pc;
611    
612          while (out < end)          if (g_compatible_depth)
613            {
614                    /* *INDENT-OFF* */
615                    REPEAT3
616                    (
617                            pixel = *(data++);
618                            SPLITCOLOUR16(pixel, pc);
619                            *(out++) = pc.blue;
620                            *(out++) = pc.green;
621                            *(out++) = pc.red;
622                    )
623                    /* *INDENT-ON* */
624            }
625            else if (g_xserver_be)
626          {          {
                 pixel = *(data++);  
   
627                  if (g_host_be)                  if (g_host_be)
628                  {                  {
629                          BSWAP16(pixel);                          while (out < end)
630                            {
631                                    pixel = *(data++);
632                                    BSWAP16(pixel);
633                                    SPLITCOLOUR16(pixel, pc);
634                                    value = MAKECOLOUR(pc);
635                                    BOUT24(out, value);
636                            }
637                    }
638                    else
639                    {
640                            while (out < end)
641                            {
642                                    pixel = *(data++);
643                                    SPLITCOLOUR16(pixel, pc);
644                                    value = MAKECOLOUR(pc);
645                                    BOUT24(out, value);
646                            }
647                  }                  }
648            }
649                  value = make_colour(split_colour16(pixel));          else
650            {
651                  if (g_xserver_be)                  if (g_host_be)
652                  {                  {
653                          *(out++) = value >> 16;                          while (out < end)
654                          *(out++) = value >> 8;                          {
655                          *(out++) = value;                                  pixel = *(data++);
656                                    BSWAP16(pixel);
657                                    SPLITCOLOUR16(pixel, pc);
658                                    value = MAKECOLOUR(pc);
659                                    LOUT24(out, value);
660                            }
661                  }                  }
662                  else                  else
663                  {                  {
664                          *(out++) = value;                          while (out < end)
665                          *(out++) = value >> 8;                          {
666                          *(out++) = value >> 16;                                  pixel = *(data++);
667                                    SPLITCOLOUR16(pixel, pc);
668                                    value = MAKECOLOUR(pc);
669                                    LOUT24(out, value);
670                            }
671                  }                  }
672          }          }
673  }  }
674    
675  static void  static void
676  translate16to32(uint16 * data, uint8 * out, uint8 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
677  {  {
678          uint16 pixel;          uint16 pixel;
679          uint32 value;          uint32 value;
680            PixelColour pc;
681    
682          while (out < end)          if (g_compatible_depth)
683            {
684                    /* *INDENT-OFF* */
685                    REPEAT4
686                    (
687                            pixel = *(data++);
688                            SPLITCOLOUR16(pixel, pc);
689                            *(out++) = pc.blue;
690                            *(out++) = pc.green;
691                            *(out++) = pc.red;
692                            *(out++) = 0;
693                    )
694                    /* *INDENT-ON* */
695            }
696            else if (g_xserver_be)
697          {          {
                 pixel = *(data++);  
   
698                  if (g_host_be)                  if (g_host_be)
699                  {                  {
700                          BSWAP16(pixel);                          while (out < end)
701                            {
702                                    pixel = *(data++);
703                                    BSWAP16(pixel);
704                                    SPLITCOLOUR16(pixel, pc);
705                                    value = MAKECOLOUR(pc);
706                                    BOUT32(out, value);
707                            }
708                  }                  }
709                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
710                  {                  {
711                          *(out++) = value >> 24;                          while (out < end)
712                          *(out++) = value >> 16;                          {
713                          *(out++) = value >> 8;                                  pixel = *(data++);
714                          *(out++) = value;                                  SPLITCOLOUR16(pixel, pc);
715                                    value = MAKECOLOUR(pc);
716                                    BOUT32(out, value);
717                            }
718                    }
719            }
720            else
721            {
722                    if (g_host_be)
723                    {
724                            while (out < end)
725                            {
726                                    pixel = *(data++);
727                                    BSWAP16(pixel);
728                                    SPLITCOLOUR16(pixel, pc);
729                                    value = MAKECOLOUR(pc);
730                                    LOUT32(out, value);
731                            }
732                  }                  }
733                  else                  else
734                  {                  {
735                          *(out++) = value;                          while (out < end)
736                          *(out++) = value >> 8;                          {
737                          *(out++) = value >> 16;                                  pixel = *(data++);
738                          *(out++) = value >> 24;                                  SPLITCOLOUR16(pixel, pc);
739                                    value = MAKECOLOUR(pc);
740                                    LOUT32(out, value);
741                            }
742                  }                  }
743          }          }
744  }  }
745    
746  static void  static void
747  translate24to16(uint8 * data, uint8 * out, uint8 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
748  {  {
749          uint32 pixel = 0;          uint32 pixel = 0;
750          uint16 value;          uint16 value;
751            PixelColour pc;
752    
753          while (out < end)          while (out < end)
754          {          {
755                  pixel = *(data++) << 16;                  pixel = *(data++) << 16;
756                  pixel |= *(data++) << 8;                  pixel |= *(data++) << 8;
757                  pixel |= *(data++);                  pixel |= *(data++);
758                    SPLITCOLOUR24(pixel, pc);
759                  value = (uint16) make_colour(split_colour24(pixel));                  value = MAKECOLOUR(pc);
   
760                  if (g_xserver_be)                  if (g_xserver_be)
761                  {                  {
762                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
763                  }                  }
764                  else                  else
765                  {                  {
766                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
767                  }                  }
768          }          }
769  }  }
770    
771  static void  static void
772  translate24to24(uint8 * data, uint8 * out, uint8 * end)  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
773  {  {
774          uint32 pixel;          uint32 pixel;
775          uint32 value;          uint32 value;
776            PixelColour pc;
777    
778          while (out < end)          if (g_xserver_be)
779          {          {
780                  pixel = *(data++) << 16;                  while (out < end)
                 pixel |= *(data++) << 8;  
                 pixel |= *(data++);  
   
                 value = make_colour(split_colour24(pixel));  
   
                 if (g_xserver_be)  
781                  {                  {
782                          *(out++) = value >> 16;                          pixel = *(data++) << 16;
783                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
784                          *(out++) = value;                          pixel |= *(data++);
785                            SPLITCOLOUR24(pixel, pc);
786                            value = MAKECOLOUR(pc);
787                            BOUT24(out, value);
788                  }                  }
789                  else          }
790            else
791            {
792                    while (out < end)
793                  {                  {
794                          *(out++) = value;                          pixel = *(data++) << 16;
795                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
796                          *(out++) = value >> 16;                          pixel |= *(data++);
797                            SPLITCOLOUR24(pixel, pc);
798                            value = MAKECOLOUR(pc);
799                            LOUT24(out, value);
800                  }                  }
801          }          }
802  }  }
803    
804  static void  static void
805  translate24to32(uint8 * data, uint8 * out, uint8 * end)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
806  {  {
807          uint32 pixel;          uint32 pixel;
808          uint32 value;          uint32 value;
809            PixelColour pc;
810    
811          while (out < end)          if (g_compatible_depth)
812          {          {
813                  pixel = *(data++) << 16;                  /* *INDENT-OFF* */
814                  pixel |= *(data++) << 8;  #ifdef NEED_ALIGN
815                  pixel |= *(data++);                  REPEAT4
816                    (
817                  value = make_colour(split_colour24(pixel));                          *(out++) = *(data++);
818                            *(out++) = *(data++);
819                  if (g_xserver_be)                          *(out++) = *(data++);
820                            *(out++) = 0;
821                    )
822    #else
823                    REPEAT4
824                    (
825                     /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
826                     *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
827                     out += 4;
828                     data += 3;
829                    )
830    #endif
831                    /* *INDENT-ON* */
832            }
833            else if (g_xserver_be)
834            {
835                    while (out < end)
836                  {                  {
837                          *(out++) = value >> 24;                          pixel = *(data++) << 16;
838                          *(out++) = value >> 16;                          pixel |= *(data++) << 8;
839                          *(out++) = value >> 8;                          pixel |= *(data++);
840                          *(out++) = value;                          SPLITCOLOUR24(pixel, pc);
841                            value = MAKECOLOUR(pc);
842                            BOUT32(out, value);
843                  }                  }
844                  else          }
845            else
846            {
847                    while (out < end)
848                  {                  {
849                          *(out++) = value;                          pixel = *(data++) << 16;
850                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
851                          *(out++) = value >> 16;                          pixel |= *(data++);
852                          *(out++) = value >> 24;                          SPLITCOLOUR24(pixel, pc);
853                            value = MAKECOLOUR(pc);
854                            LOUT32(out, value);
855                  }                  }
856          }          }
857  }  }
# Line 592  translate24to32(uint8 * data, uint8 * ou Line 859  translate24to32(uint8 * data, uint8 * ou
859  static uint8 *  static uint8 *
860  translate_image(int width, int height, uint8 * data)  translate_image(int width, int height, uint8 * data)
861  {  {
862          int size = width * height * g_bpp / 8;          int size;
863          uint8 *out = (uint8 *) xmalloc(size);          uint8 *out;
864          uint8 *end = out + size;          uint8 *end;
865    
866            /*
867               If RDP depth and X Visual depths match,
868               and arch(endian) matches, no need to translate:
869               just return data.
870               Note: select_visual should've already ensured g_no_translate
871               is only set for compatible depths, but the RDP depth might've
872               changed during connection negotiations.
873             */
874            if (g_no_translate_image)
875            {
876                    if ((g_depth == 15 && g_server_depth == 15) ||
877                        (g_depth == 16 && g_server_depth == 16) ||
878                        (g_depth == 24 && g_server_depth == 24))
879                            return data;
880            }
881    
882            size = width * height * (g_bpp / 8);
883            out = (uint8 *) xmalloc(size);
884            end = out + size;
885    
886          switch (g_server_bpp)          switch (g_server_depth)
887          {          {
888                  case 24:                  case 24:
889                          switch (g_bpp)                          switch (g_bpp)
# Line 694  calculate_shifts(uint32 mask, int *shift Line 981  calculate_shifts(uint32 mask, int *shift
981          *shift_r = 8 - ffs(mask & ~(mask >> 1));          *shift_r = 8 - ffs(mask & ~(mask >> 1));
982  }  }
983    
984  BOOL  /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
985  ui_init(void)     calculates the bits-per-pixel of this channel (a.k.a. colour weight).
986     */
987    static unsigned
988    calculate_mask_weight(uint32 mask)
989    {
990            unsigned weight = 0;
991            do
992            {
993                    weight += (mask & 1);
994            }
995            while (mask >>= 1);
996            return weight;
997    }
998    
999    static BOOL
1000    select_visual()
1001  {  {
         XVisualInfo vi;  
1002          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1003          uint16 test;          int pixmap_formats_count, visuals_count;
         int i, screen_num, nvisuals;  
1004          XVisualInfo *vmatches = NULL;          XVisualInfo *vmatches = NULL;
1005          XVisualInfo template;          XVisualInfo template;
1006          Bool TrueColorVisual = False;          int i;
1007            unsigned red_weight, blue_weight, green_weight;
1008    
1009          g_display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1010          if (g_display == NULL)  
1011            pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1012            if (pfm == NULL)
1013          {          {
1014                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1015                    XCloseDisplay(g_display);
1016                  return False;                  return False;
1017          }          }
1018    
1019          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 */  
1020          template.class = TrueColor;          template.class = TrueColor;
1021          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1022            g_visual = NULL;
1023            g_no_translate_image = False;
1024            g_compatible_depth = False;
1025            if (vmatches != NULL)
1026            {
1027                    for (i = 0; i < visuals_count; ++i)
1028                    {
1029                            XVisualInfo *visual_info = &vmatches[i];
1030    
1031                            /* Try to find a no-translation visual that'll
1032                               allow us to use RDP bitmaps directly as ZPixmaps. */
1033                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1034                                                   /* R5G5B5 */
1035                                                   (visual_info->red_mask == 0x7c00) &&
1036                                                   (visual_info->green_mask == 0x3e0) &&
1037                                                   (visual_info->blue_mask == 0x1f)) ||
1038                                                  ((visual_info->depth == 16) &&
1039                                                   /* R5G6B5 */
1040                                                   (visual_info->red_mask == 0xf800) &&
1041                                                   (visual_info->green_mask == 0x7e0) &&
1042                                                   (visual_info->blue_mask == 0x1f)) ||
1043                                                  ((visual_info->depth == 24) &&
1044                                                   /* R8G8B8 */
1045                                                   (visual_info->red_mask == 0xff0000) &&
1046                                                   (visual_info->green_mask == 0xff00) &&
1047                                                   (visual_info->blue_mask == 0xff))))
1048                            {
1049                                    g_visual = visual_info->visual;
1050                                    g_depth = visual_info->depth;
1051                                    g_compatible_depth = True;
1052                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1053                                    if (g_no_translate_image)
1054                                            /* We found the best visual */
1055                                            break;
1056                            }
1057                            else
1058                            {
1059                                    g_compatible_depth = False;
1060                            }
1061    
1062          nvisuals--;                          if (visual_info->depth > 24)
1063          while (nvisuals >= 0)                          {
1064          {                                  /* Avoid 32-bit visuals and likes like the plague.
1065                  if ((vmatches + nvisuals)->depth > g_depth)                                     They're either untested or proven to work bad
1066                  {                                     (e.g. nvidia's Composite 32-bit visual).
1067                          g_depth = (vmatches + nvisuals)->depth;                                     Most implementation offer a 24-bit visual anyway. */
1068                                    continue;
1069                            }
1070    
1071                            /* Only care for visuals, for whose BPPs (not depths!)
1072                               we have a translateXtoY function. */
1073                            BOOL can_translate_to_bpp = False;
1074                            int j;
1075                            for (j = 0; j < pixmap_formats_count; ++j)
1076                            {
1077                                    if (pfm[j].depth == visual_info->depth)
1078                                    {
1079                                            if ((pfm[j].bits_per_pixel == 16) ||
1080                                                (pfm[j].bits_per_pixel == 24) ||
1081                                                (pfm[j].bits_per_pixel == 32))
1082                                            {
1083                                                    can_translate_to_bpp = True;
1084                                            }
1085                                            break;
1086                                    }
1087                            }
1088    
1089                            /* Prefer formats which have the most colour depth.
1090                               We're being truly aristocratic here, minding each
1091                               weight on its own. */
1092                            if (can_translate_to_bpp)
1093                            {
1094                                    unsigned vis_red_weight =
1095                                            calculate_mask_weight(visual_info->red_mask);
1096                                    unsigned vis_green_weight =
1097                                            calculate_mask_weight(visual_info->green_mask);
1098                                    unsigned vis_blue_weight =
1099                                            calculate_mask_weight(visual_info->blue_mask);
1100                                    if ((vis_red_weight >= red_weight)
1101                                        && (vis_green_weight >= green_weight)
1102                                        && (vis_blue_weight >= blue_weight))
1103                                    {
1104                                            red_weight = vis_red_weight;
1105                                            green_weight = vis_green_weight;
1106                                            blue_weight = vis_blue_weight;
1107                                            g_visual = visual_info->visual;
1108                                            g_depth = visual_info->depth;
1109                                    }
1110                            }
1111                  }                  }
1112                  nvisuals--;                  XFree(vmatches);
                 TrueColorVisual = True;  
1113          }          }
1114    
1115          if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))          if (g_visual != NULL)
1116          {          {
1117                  /* we use a colourmap, so the default visual should do */                  g_owncolmap = False;
1118                  g_visual = DefaultVisualOfScreen(g_screen);                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1119                  g_depth = DefaultDepthOfScreen(g_screen);                  calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1120                    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;  
                 }  
1121          }          }
1122          else          else
1123          {          {
1124                  /* need a truecolour visual */                  template.class = PseudoColor;
1125                  if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))                  template.depth = 8;
1126                  {                  template.colormap_size = 256;
1127                          error("The display does not support true colour - high colour support unavailable.\n");                  vmatches =
1128                            XGetVisualInfo(g_display,
1129                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1130                                           &template, &visuals_count);
1131                    if (vmatches == NULL)
1132                    {
1133                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1134                            XCloseDisplay(g_display);
1135                            XFree(pfm);
1136                          return False;                          return False;
1137                  }                  }
1138    
1139                  g_visual = vi.visual;                  /* we use a colourmap, so the default visual should do */
1140                  g_owncolmap = False;                  g_owncolmap = True;
1141                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);                  g_visual = vmatches[0].visual;
1142                  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);  
1143          }          }
1144    
1145          pfm = XListPixmapFormats(g_display, &i);          g_bpp = 0;
1146          if (pfm != NULL)          for (i = 0; i < pixmap_formats_count; ++i)
1147          {          {
1148                  /* Use maximum bpp for this depth - this is generally                  XPixmapFormatValues *pf = &pfm[i];
1149                     desirable, e.g. 24 bits->32 bits. */                  if (pf->depth == g_depth)
                 while (i--)  
1150                  {                  {
1151                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))                          g_bpp = pf->bits_per_pixel;
1152    
1153                            if (g_no_translate_image)
1154                          {                          {
1155                                  g_bpp = pfm[i].bits_per_pixel;                                  switch (g_server_depth)
1156                                    {
1157                                            case 15:
1158                                            case 16:
1159                                                    if (g_bpp != 16)
1160                                                            g_no_translate_image = False;
1161                                                    break;
1162                                            case 24:
1163                                                    /* Yes, this will force image translation
1164                                                       on most modern servers which use 32 bits
1165                                                       for R8G8B8. */
1166                                                    if (g_bpp != 24)
1167                                                            g_no_translate_image = False;
1168                                                    break;
1169                                            default:
1170                                                    g_no_translate_image = False;
1171                                                    break;
1172                                    }
1173                          }                          }
1174    
1175                            /* Pixmap formats list is a depth-to-bpp mapping --
1176                               there's just a single entry for every depth,
1177                               so we can safely break here */
1178                            break;
1179                  }                  }
                 XFree(pfm);  
1180          }          }
1181            XFree(pfm);
1182            pfm = NULL;
1183            return True;
1184    }
1185    
1186    BOOL
1187    ui_init(void)
1188    {
1189            int screen_num;
1190    
1191          if (g_bpp < 8)          g_display = XOpenDisplay(NULL);
1192            if (g_display == NULL)
1193          {          {
1194                  error("Less than 8 bpp not currently supported.\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
1195                  XCloseDisplay(g_display);                  return False;
1196            }
1197    
1198            {
1199                    uint16 endianess_test = 1;
1200                    g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1201            }
1202    
1203            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1204            screen_num = DefaultScreen(g_display);
1205            g_x_socket = ConnectionNumber(g_display);
1206            g_screen = ScreenOfDisplay(g_display, screen_num);
1207            g_depth = DefaultDepthOfScreen(g_screen);
1208    
1209            if (!select_visual())
1210                  return False;                  return False;
1211    
1212            if (g_no_translate_image)
1213            {
1214                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1215            }
1216    
1217            if (g_server_depth > g_bpp)
1218            {
1219                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1220                            g_server_depth, g_bpp);
1221          }          }
1222    
1223            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1224                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1225    
1226          if (!g_owncolmap)          if (!g_owncolmap)
1227          {          {
1228                  g_xcolmap =                  g_xcolmap =
1229                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1230                                          AllocNone);                                          AllocNone);
1231                  if (g_depth <= 8)                  if (g_depth <= 8)
1232                          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);
1233          }          }
1234    
1235          if (DoesBackingStore(g_screen) != Always)          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1236            {
1237                    warning("External BackingStore not available. Using internal.\n");
1238                  g_ownbackstore = True;                  g_ownbackstore = True;
1239            }
         test = 1;  
         g_host_be = !(BOOL) (*(uint8 *) (&test));  
         g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);  
1240    
1241          /*          /*
1242           * Determine desktop size           * Determine desktop size
# Line 809  ui_init(void) Line 1249  ui_init(void)
1249          else if (g_width < 0)          else if (g_width < 0)
1250          {          {
1251                  /* Percent of screen */                  /* Percent of screen */
1252                    if (-g_width >= 100)
1253                            g_using_full_workarea = True;
1254                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1255                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1256          }          }
# Line 816  ui_init(void) Line 1258  ui_init(void)
1258          {          {
1259                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1260                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
1261                    g_using_full_workarea = True;
1262    
1263                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1264                  {                  {
# Line 842  ui_init(void) Line 1285  ui_init(void)
1285    
1286          xclip_init();          xclip_init();
1287    
1288          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));
1289    
1290          return True;          return True;
1291  }  }
# Line 870  BOOL Line 1313  BOOL
1313  ui_create_window(void)  ui_create_window(void)
1314  {  {
1315          uint8 null_pointer_mask[1] = { 0x80 };          uint8 null_pointer_mask[1] = { 0x80 };
1316          uint8 null_pointer_data[4] = { 0x00, 0x00, 0x00, 0x00 };          uint8 null_pointer_data[24] = { 0x00 };
1317    
1318          XSetWindowAttributes attribs;          XSetWindowAttributes attribs;
1319          XClassHint *classhints;          XClassHint *classhints;
1320          XSizeHints *sizehints;          XSizeHints *sizehints;
# Line 881  ui_create_window(void) Line 1325  ui_create_window(void)
1325          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1326          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1327    
1328            /* Handle -x-y portion of geometry string */
1329            if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1330                    g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1331            if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1332                    g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1333    
1334          attribs.background_pixel = BlackPixelOfScreen(g_screen);          attribs.background_pixel = BlackPixelOfScreen(g_screen);
1335          attribs.border_pixel = WhitePixelOfScreen(g_screen);          attribs.border_pixel = WhitePixelOfScreen(g_screen);
1336          attribs.backing_store = g_ownbackstore ? NotUseful : Always;          attribs.backing_store = g_ownbackstore ? NotUseful : Always;
1337          attribs.override_redirect = g_fullscreen;          attribs.override_redirect = g_fullscreen;
1338          attribs.colormap = g_xcolmap;          attribs.colormap = g_xcolmap;
1339    
1340          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,
1341                                0, g_depth, InputOutput, g_visual,                                wndheight, 0, g_depth, InputOutput, g_visual,
1342                                CWBackPixel | CWBackingStore | CWOverrideRedirect |                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1343                                CWColormap | CWBorderPixel, &attribs);                                CWBorderPixel, &attribs);
1344    
1345          if (g_gc == NULL)          if (g_gc == NULL)
1346                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);                  g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1347    
1348            if (g_create_bitmap_gc == NULL)
1349                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1350    
1351          if ((g_ownbackstore) && (g_backstore == 0))          if ((g_ownbackstore) && (g_backstore == 0))
1352          {          {
1353                  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 1374  ui_create_window(void)
1374          if (sizehints)          if (sizehints)
1375          {          {
1376                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1377                    if (g_pos)
1378                            sizehints->flags |= PPosition;
1379                  sizehints->min_width = sizehints->max_width = g_width;                  sizehints->min_width = sizehints->max_width = g_width;
1380                  sizehints->min_height = sizehints->max_height = g_height;                  sizehints->min_height = sizehints->max_height = g_height;
1381                  XSetWMNormalHints(g_display, g_wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
1382                  XFree(sizehints);                  XFree(sizehints);
1383          }          }
1384    
1385            if (g_embed_wnd)
1386            {
1387                    XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1388            }
1389    
1390          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1391                  VisibilityChangeMask | FocusChangeMask;                  VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1392    
1393          if (g_sendmotion)          if (g_sendmotion)
1394                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
# Line 958  ui_create_window(void) Line 1418  ui_create_window(void)
1418                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1419          }          }
1420          while (xevent.type != VisibilityNotify);          while (xevent.type != VisibilityNotify);
1421            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1422    
1423          g_focused = False;          g_focused = False;
1424          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 975  ui_create_window(void) Line 1436  ui_create_window(void)
1436  }  }
1437    
1438  void  void
1439    ui_resize_window()
1440    {
1441            XSizeHints *sizehints;
1442            Pixmap bs;
1443    
1444            sizehints = XAllocSizeHints();
1445            if (sizehints)
1446            {
1447                    sizehints->flags = PMinSize | PMaxSize;
1448                    sizehints->min_width = sizehints->max_width = g_width;
1449                    sizehints->min_height = sizehints->max_height = g_height;
1450                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1451                    XFree(sizehints);
1452            }
1453    
1454            if (!(g_fullscreen || g_embed_wnd))
1455            {
1456                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1457            }
1458    
1459            /* create new backstore pixmap */
1460            if (g_backstore != 0)
1461            {
1462                    bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1463                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1464                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1465                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1466                    XFreePixmap(g_display, g_backstore);
1467                    g_backstore = bs;
1468            }
1469    }
1470    
1471    void
1472  ui_destroy_window(void)  ui_destroy_window(void)
1473  {  {
1474          if (g_IC != NULL)          if (g_IC != NULL)
# Line 1008  xwin_toggle_fullscreen(void) Line 1502  xwin_toggle_fullscreen(void)
1502          }          }
1503  }  }
1504    
1505  /* Process all events in Xlib queue  static void
1506    handle_button_event(XEvent xevent, BOOL down)
1507    {
1508            uint16 button, flags = 0;
1509            g_last_gesturetime = xevent.xbutton.time;
1510            button = xkeymap_translate_button(xevent.xbutton.button);
1511            if (button == 0)
1512                    return;
1513    
1514            if (down)
1515                    flags = MOUSE_FLAG_DOWN;
1516    
1517            /* Stop moving window when button is released, regardless of cursor position */
1518            if (g_moving_wnd && (xevent.type == ButtonRelease))
1519                    g_moving_wnd = False;
1520    
1521            /* If win_button_size is nonzero, enable single app mode */
1522            if (xevent.xbutton.y < g_win_button_size)
1523            {
1524                    /*  Check from right to left: */
1525                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1526                    {
1527                            /* The close button, continue */
1528                            ;
1529                    }
1530                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1531                    {
1532                            /* The maximize/restore button. Do not send to
1533                               server.  It might be a good idea to change the
1534                               cursor or give some other visible indication
1535                               that rdesktop inhibited this click */
1536                            if (xevent.type == ButtonPress)
1537                                    return;
1538                    }
1539                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1540                    {
1541                            /* The minimize button. Iconify window. */
1542                            if (xevent.type == ButtonRelease)
1543                            {
1544                                    /* Release the mouse button outside the minimize button, to prevent the
1545                                       actual minimazation to happen */
1546                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1547                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1548                                    return;
1549                            }
1550                    }
1551                    else if (xevent.xbutton.x <= g_win_button_size)
1552                    {
1553                            /* The system menu. Ignore. */
1554                            if (xevent.type == ButtonPress)
1555                                    return;
1556                    }
1557                    else
1558                    {
1559                            /* The title bar. */
1560                            if (xevent.type == ButtonPress)
1561                            {
1562                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1563                                    {
1564                                            g_moving_wnd = True;
1565                                            g_move_x_offset = xevent.xbutton.x;
1566                                            g_move_y_offset = xevent.xbutton.y;
1567                                    }
1568                                    return;
1569                            }
1570                    }
1571            }
1572    
1573            rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1574                           flags | button, xevent.xbutton.x, xevent.xbutton.y);
1575    }
1576    
1577    /* Process events in Xlib queue
1578     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1579  static int  static int
1580  xwin_process_events(void)  xwin_process_events(void)
1581  {  {
1582          XEvent xevent;          XEvent xevent;
1583          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1584          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1585          char str[256];          char str[256];
1586          Status status;          Status status;
1587            int events = 0;
1588    
1589          while (XPending(g_display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1590          {          {
1591                  XNextEvent(g_display, &xevent);                  XNextEvent(g_display, &xevent);
1592    
# Line 1031  xwin_process_events(void) Line 1596  xwin_process_events(void)
1596                          continue;                          continue;
1597                  }                  }
1598    
                 flags = 0;  
   
1599                  switch (xevent.type)                  switch (xevent.type)
1600                  {                  {
1601                            case VisibilityNotify:
1602                                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1603                                    break;
1604                          case ClientMessage:                          case ClientMessage:
1605                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
1606                                  if ((xevent.xclient.message_type == g_protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
# Line 1066  xwin_process_events(void) Line 1632  xwin_process_events(void)
1632                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1633                                  }                                  }
1634    
1635                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1636                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1637    
1638                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1639                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1640                                          break;                                          break;
1641    
1642                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1643                                                             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);  
   
1644                                  break;                                  break;
1645    
1646                          case KeyRelease:                          case KeyRelease:
# Line 1091  xwin_process_events(void) Line 1648  xwin_process_events(void)
1648                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
1649                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
1650    
1651                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1652                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1653    
1654                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1655                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1656                                          break;                                          break;
1657    
1658                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1659                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
1660                                  break;                                  break;
1661    
1662                          case ButtonPress:                          case ButtonPress:
1663                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
1664                                  /* fall through */                                  break;
1665    
1666                          case ButtonRelease:                          case ButtonRelease:
1667                                  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);  
1668                                  break;                                  break;
1669    
1670                          case MotionNotify:                          case MotionNotify:
# Line 1262  xwin_process_events(void) Line 1757  xwin_process_events(void)
1757                          case PropertyNotify:                          case PropertyNotify:
1758                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
1759                                  break;                                  break;
1760                            case MapNotify:
1761                                    rdp_send_client_window_status(1);
1762                                    break;
1763                            case UnmapNotify:
1764                                    rdp_send_client_window_status(0);
1765                                    break;
1766                  }                  }
1767          }          }
1768          /* Keep going */          /* Keep going */
# Line 1272  xwin_process_events(void) Line 1773  xwin_process_events(void)
1773  int  int
1774  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1775  {  {
1776          int n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;          int n;
1777          fd_set rfds, wfds;          fd_set rfds, wfds;
1778          struct timeval tv;          struct timeval tv;
1779          BOOL s_timeout = False;          BOOL s_timeout = False;
1780    
1781          while (True)          while (True)
1782          {          {
1783                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1784                  /* Process any events already waiting */                  /* Process any events already waiting */
1785                  if (!xwin_process_events())                  if (!xwin_process_events())
1786                          /* User quit */                          /* User quit */
# Line 1312  ui_select(int rdp_socket) Line 1814  ui_select(int rdp_socket)
1814                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
1815    
1816                          case 0:                          case 0:
1817                                  /* TODO: if tv.tv_sec just times out                                  /* Abort serial read calls */
1818                                   * we will segfault.                                  if (s_timeout)
1819                                   * FIXME:                                          rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
                                  */  
                                 //s_timeout = True;  
                                 //rdpdr_check_fds(&rfds, &wfds, (BOOL) True);  
1820                                  continue;                                  continue;
1821                  }                  }
1822    
# Line 1347  ui_create_bitmap(int width, int height, Line 1846  ui_create_bitmap(int width, int height,
1846          uint8 *tdata;          uint8 *tdata;
1847          int bitmap_pad;          int bitmap_pad;
1848    
1849          if (g_server_bpp == 8)          if (g_server_depth == 8)
1850          {          {
1851                  bitmap_pad = 8;                  bitmap_pad = 8;
1852          }          }
# Line 1364  ui_create_bitmap(int width, int height, Line 1863  ui_create_bitmap(int width, int height,
1863          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1864                               (char *) tdata, width, height, bitmap_pad, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
1865    
1866          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);
1867    
1868          XFree(image);          XFree(image);
1869          if (!g_owncolmap)          if (tdata != data)
1870                  xfree(tdata);                  xfree(tdata);
1871          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1872  }  }
# Line 1379  ui_paint_bitmap(int x, int y, int cx, in Line 1878  ui_paint_bitmap(int x, int y, int cx, in
1878          uint8 *tdata;          uint8 *tdata;
1879          int bitmap_pad;          int bitmap_pad;
1880    
1881          if (g_server_bpp == 8)          if (g_server_depth == 8)
1882          {          {
1883                  bitmap_pad = 8;                  bitmap_pad = 8;
1884          }          }
# Line 1406  ui_paint_bitmap(int x, int y, int cx, in Line 1905  ui_paint_bitmap(int x, int y, int cx, in
1905          }          }
1906    
1907          XFree(image);          XFree(image);
1908          if (!g_owncolmap)          if (tdata != data)
1909                  xfree(tdata);                  xfree(tdata);
1910  }  }
1911    
# Line 1422  ui_create_glyph(int width, int height, u Line 1921  ui_create_glyph(int width, int height, u
1921          XImage *image;          XImage *image;
1922          Pixmap bitmap;          Pixmap bitmap;
1923          int scanline;          int scanline;
         GC gc;  
1924    
1925          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1926    
1927          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1928          gc = XCreateGC(g_display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
1929                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1930    
1931          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1932                               width, height, 8, scanline);                               width, height, 8, scanline);
# Line 1435  ui_create_glyph(int width, int height, u Line 1934  ui_create_glyph(int width, int height, u
1934          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1935          XInitImage(image);          XInitImage(image);
1936    
1937          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);
1938    
1939          XFree(image);          XFree(image);
         XFreeGC(g_display, gc);  
1940          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1941  }  }
1942    
# Line 1730  ui_patblt(uint8 opcode, Line 2228  ui_patblt(uint8 opcode,
2228          {          {
2229                  case 0: /* Solid */                  case 0: /* Solid */
2230                          SET_FOREGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
2231                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2232                          break;                          break;
2233    
2234                  case 2: /* Hatch */                  case 2: /* Hatch */
# Line 1741  ui_patblt(uint8 opcode, Line 2239  ui_patblt(uint8 opcode,
2239                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2240                          XSetStipple(g_display, g_gc, fill);                          XSetStipple(g_display, g_gc, fill);
2241                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2242                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2243                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2244                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2245                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
# Line 1751  ui_patblt(uint8 opcode, Line 2249  ui_patblt(uint8 opcode,
2249                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
2250                                  ipattern[7 - i] = brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
2251                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
   
2252                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
2253                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
2254                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2255                          XSetStipple(g_display, g_gc, fill);                          XSetStipple(g_display, g_gc, fill);
2256                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2257                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
                         FILL_RECTANGLE(x, y, cx, cy);  
   
2258                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2259                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2260                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
# Line 1770  ui_patblt(uint8 opcode, Line 2265  ui_patblt(uint8 opcode,
2265          }          }
2266    
2267          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2268    
2269            if (g_ownbackstore)
2270                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2271  }  }
2272    
2273  void  void
# Line 1778  ui_screenblt(uint8 opcode, Line 2276  ui_screenblt(uint8 opcode,
2276               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
2277  {  {
2278          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
         XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);  
2279          if (g_ownbackstore)          if (g_ownbackstore)
2280                  XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);          {
2281                    if (g_Unobscured)
2282                    {
2283                            XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2284                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2285                                      y);
2286                    }
2287                    else
2288                    {
2289                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2290                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2291                                      y);
2292                    }
2293            }
2294            else
2295            {
2296                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2297            }
2298          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2299  }  }
2300    
# Line 1851  ui_rect( Line 2365  ui_rect(
2365          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2366  }  }
2367    
2368    void
2369    ui_polygon(uint8 opcode,
2370               /* mode */ uint8 fillmode,
2371               /* dest */ POINT * point, int npoints,
2372               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2373    {
2374            uint8 style, i, ipattern[8];
2375            Pixmap fill;
2376    
2377            SET_FUNCTION(opcode);
2378    
2379            switch (fillmode)
2380            {
2381                    case ALTERNATE:
2382                            XSetFillRule(g_display, g_gc, EvenOddRule);
2383                            break;
2384                    case WINDING:
2385                            XSetFillRule(g_display, g_gc, WindingRule);
2386                            break;
2387                    default:
2388                            unimpl("fill mode %d\n", fillmode);
2389            }
2390    
2391            if (brush)
2392                    style = brush->style;
2393            else
2394                    style = 0;
2395    
2396            switch (style)
2397            {
2398                    case 0: /* Solid */
2399                            SET_FOREGROUND(fgcolour);
2400                            FILL_POLYGON((XPoint *) point, npoints);
2401                            break;
2402    
2403                    case 2: /* Hatch */
2404                            fill = (Pixmap) ui_create_glyph(8, 8,
2405                                                            hatch_patterns + brush->pattern[0] * 8);
2406                            SET_FOREGROUND(fgcolour);
2407                            SET_BACKGROUND(bgcolour);
2408                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2409                            XSetStipple(g_display, g_gc, fill);
2410                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2411                            FILL_POLYGON((XPoint *) point, npoints);
2412                            XSetFillStyle(g_display, g_gc, FillSolid);
2413                            XSetTSOrigin(g_display, g_gc, 0, 0);
2414                            ui_destroy_glyph((HGLYPH) fill);
2415                            break;
2416    
2417                    case 3: /* Pattern */
2418                            for (i = 0; i != 8; i++)
2419                                    ipattern[7 - i] = brush->pattern[i];
2420                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2421                            SET_FOREGROUND(bgcolour);
2422                            SET_BACKGROUND(fgcolour);
2423                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2424                            XSetStipple(g_display, g_gc, fill);
2425                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2426                            FILL_POLYGON((XPoint *) point, npoints);
2427                            XSetFillStyle(g_display, g_gc, FillSolid);
2428                            XSetTSOrigin(g_display, g_gc, 0, 0);
2429                            ui_destroy_glyph((HGLYPH) fill);
2430                            break;
2431    
2432                    default:
2433                            unimpl("brush %d\n", brush->style);
2434            }
2435    
2436            RESET_FUNCTION(opcode);
2437    }
2438    
2439    void
2440    ui_polyline(uint8 opcode,
2441                /* dest */ POINT * points, int npoints,
2442                /* pen */ PEN * pen)
2443    {
2444            /* TODO: set join style */
2445            SET_FUNCTION(opcode);
2446            SET_FOREGROUND(pen->colour);
2447            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2448            if (g_ownbackstore)
2449                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2450                               CoordModePrevious);
2451            RESET_FUNCTION(opcode);
2452    }
2453    
2454    void
2455    ui_ellipse(uint8 opcode,
2456               /* mode */ uint8 fillmode,
2457               /* dest */ int x, int y, int cx, int cy,
2458               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2459    {
2460            uint8 style, i, ipattern[8];
2461            Pixmap fill;
2462    
2463            SET_FUNCTION(opcode);
2464    
2465            if (brush)
2466                    style = brush->style;
2467            else
2468                    style = 0;
2469    
2470            switch (style)
2471            {
2472                    case 0: /* Solid */
2473                            SET_FOREGROUND(fgcolour);
2474                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2475                            break;
2476    
2477                    case 2: /* Hatch */
2478                            fill = (Pixmap) ui_create_glyph(8, 8,
2479                                                            hatch_patterns + brush->pattern[0] * 8);
2480                            SET_FOREGROUND(fgcolour);
2481                            SET_BACKGROUND(bgcolour);
2482                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2483                            XSetStipple(g_display, g_gc, fill);
2484                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2485                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2486                            XSetFillStyle(g_display, g_gc, FillSolid);
2487                            XSetTSOrigin(g_display, g_gc, 0, 0);
2488                            ui_destroy_glyph((HGLYPH) fill);
2489                            break;
2490    
2491                    case 3: /* Pattern */
2492                            for (i = 0; i != 8; i++)
2493                                    ipattern[7 - i] = brush->pattern[i];
2494                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2495                            SET_FOREGROUND(bgcolour);
2496                            SET_BACKGROUND(fgcolour);
2497                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2498                            XSetStipple(g_display, g_gc, fill);
2499                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2500                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2501                            XSetFillStyle(g_display, g_gc, FillSolid);
2502                            XSetTSOrigin(g_display, g_gc, 0, 0);
2503                            ui_destroy_glyph((HGLYPH) fill);
2504                            break;
2505    
2506                    default:
2507                            unimpl("brush %d\n", brush->style);
2508            }
2509    
2510            RESET_FUNCTION(opcode);
2511    }
2512    
2513  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
2514  void  void
2515  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 1906  ui_draw_glyph(int mixmode, Line 2565  ui_draw_glyph(int mixmode,
2565  }  }
2566    
2567  void  void
2568  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,
2569               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2570               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2571               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2572  {  {
2573            /* TODO: use brush appropriately */
2574    
2575          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2576          int i, j, xyoffset, x1, y1;          int i, j, xyoffset, x1, y1;
2577          DATABLOB *entry;          DATABLOB *entry;
2578    
2579          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
2580    
2581            /* Sometimes, the boxcx value is something really large, like
2582               32691. This makes XCopyArea fail with Xvnc. The code below
2583               is a quick fix. */
2584            if (boxx + boxcx > g_width)
2585                    boxcx = g_width - boxx;
2586    
2587          if (boxcx > 1)          if (boxcx > 1)
2588          {          {
2589                  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 2603  ui_draw_text(uint8 font, uint8 flags, in
2603                  switch (text[i])                  switch (text[i])
2604                  {                  {
2605                          case 0xff:                          case 0xff:
2606                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
2607                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
2608                                  {                                  {
2609                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
2610                                          exit(1);                                          for (j = 0; j < length; j++)
2611                                                    fprintf(stderr, "%02x ", text[j]);
2612                                            fprintf(stderr, "\n");
2613                                            i = length = 0;
2614                                            break;
2615                                  }                                  }
2616                                    cache_put_text(text[i + 1], text, text[i + 2]);
2617                                    i += 3;
2618                                    length -= i;
2619                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2620                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
2621                                  i = 0;                                  i = 0;
2622                                  break;                                  break;
2623    
2624                          case 0xfe:                          case 0xfe:
2625                                    /* At least one byte needs to follow */
2626                                    if (i + 2 > length)
2627                                    {
2628                                            warning("Skipping short 0xfe command:");
2629                                            for (j = 0; j < length; j++)
2630                                                    fprintf(stderr, "%02x ", text[j]);
2631                                            fprintf(stderr, "\n");
2632                                            i = length = 0;
2633                                            break;
2634                                    }
2635                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
2636                                  if (entry != NULL)                                  if (entry->data != NULL)
2637                                  {                                  {
2638                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
2639                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
2640                                          {                                          {
2641                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2642                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 2044  ui_desktop_restore(uint32 offset, int x, Line 2726  ui_desktop_restore(uint32 offset, int x,
2726    
2727          XFree(image);          XFree(image);
2728  }  }
2729    
2730    /* these do nothing here but are used in uiports */
2731    void
2732    ui_begin_update(void)
2733    {
2734    }
2735    
2736    void
2737    ui_end_update(void)
2738    {
2739    }

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

  ViewVC Help
Powered by ViewVC 1.1.26