/[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 536 by matthewc, Fri Oct 31 04:29:57 2003 UTC revision 1041 by astrand, Tue Jan 24 12:25:49 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 20  Line 20 
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23    #include <unistd.h>
24    #include <sys/time.h>
25  #include <time.h>  #include <time.h>
26  #include <errno.h>  #include <errno.h>
27    #include <strings.h>
28  #include "rdesktop.h"  #include "rdesktop.h"
29  #include "xproto.h"  #include "xproto.h"
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;
# Line 40  Time g_last_gesturetime; Line 46  Time g_last_gesturetime;
46  static int g_x_socket;  static int g_x_socket;
47  static Screen *g_screen;  static Screen *g_screen;
48  Window g_wnd;  Window g_wnd;
49    extern uint32 g_embed_wnd;
50  BOOL g_enable_compose = False;  BOOL g_enable_compose = False;
51  static GC g_gc;  BOOL g_Unobscured;              /* used for screenblt */
52    static GC g_gc = NULL;
53    static GC g_create_bitmap_gc = NULL;
54    static GC g_create_glyph_gc = NULL;
55  static Visual *g_visual;  static Visual *g_visual;
56  static int g_depth;  static int g_depth;
57  static int g_bpp;  static int g_bpp;
# Line 49  static XIM g_IM; Line 59  static XIM g_IM;
59  static XIC g_IC;  static XIC g_IC;
60  static XModifierKeymap *g_mod_map;  static XModifierKeymap *g_mod_map;
61  static Cursor g_current_cursor;  static Cursor g_current_cursor;
62  static HCURSOR g_null_cursor;  static HCURSOR g_null_cursor = NULL;
63  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
64  static BOOL g_focused;  static BOOL g_focused;
65  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
66    static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */
67    
68  /* endianness */  /* endianness */
69  static BOOL g_host_be;  static BOOL g_host_be;
# Line 61  static int g_red_shift_r, g_blue_shift_r Line 72  static int g_red_shift_r, g_blue_shift_r
72  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;
73    
74  /* software backing store */  /* software backing store */
75  static BOOL g_ownbackstore;  extern BOOL g_ownbackstore;
76  static Pixmap g_backstore;  static Pixmap g_backstore = 0;
77    
78  /* Moving in single app mode */  /* Moving in single app mode */
79  static BOOL g_moving_wnd;  static BOOL g_moving_wnd;
80  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
81  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
82    static BOOL g_using_full_workarea = False;
83    
84  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
85  extern int g_dsp_fd;  extern int g_dsp_fd;
# Line 80  extern BOOL g_rdpsnd; Line 92  extern BOOL g_rdpsnd;
92  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
93  typedef struct  typedef struct
94  {  {
95          uint32 flags;          unsigned long flags;
96          uint32 functions;          unsigned long functions;
97          uint32 decorations;          unsigned long decorations;
98          sint32 inputMode;          long inputMode;
99          uint32 status;          unsigned long status;
100  }  }
101  PropMotifWmHints;  PropMotifWmHints;
102    
# Line 109  PixelColour; Line 121  PixelColour;
121          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); \
122  }  }
123    
124    #define FILL_POLYGON(p,np)\
125    { \
126            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
127            if (g_ownbackstore) \
128                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
129    }
130    
131    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
132    { \
133            switch (m) \
134            { \
135                    case 0: /* Outline */ \
136                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
137                            if (g_ownbackstore) \
138                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
139                            break; \
140                    case 1: /* Filled */ \
141                            XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
142                            if (g_ownbackstore) \
143                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
144                            break; \
145            } \
146    }
147    
148  /* colour maps */  /* colour maps */
149  BOOL g_owncolmap = False;  extern BOOL g_owncolmap;
150  static Colormap g_xcolmap;  static Colormap g_xcolmap;
151  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
152    
# Line 162  mwm_hide_decorations(void) Line 198  mwm_hide_decorations(void)
198                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
199  }  }
200    
201  static PixelColour  #define SPLITCOLOUR15(colour, rv) \
202  split_colour15(uint32 colour)  { \
203  {          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
204          PixelColour rv;          rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
205          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;  
206  }  }
207    
208  static uint32  #define SPLITCOLOUR16(colour, rv) \
209  make_colour(PixelColour pc)  { \
210  {          rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
211          return (((pc.red >> g_red_shift_r) << g_red_shift_l)          rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
212                  | ((pc.green >> g_green_shift_r) << g_green_shift_l)          rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
213                  | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l));  } \
214    
215    #define SPLITCOLOUR24(colour, rv) \
216    { \
217            rv.blue = (colour & 0xff0000) >> 16; \
218            rv.green = (colour & 0x00ff00) >> 8; \
219            rv.red = (colour & 0x0000ff); \
220  }  }
221    
222    #define MAKECOLOUR(pc) \
223            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
224                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
225                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
226    
227  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
228  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
229  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
230                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
231    
232    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
233    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
234    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
235    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
236    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
237    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
238    
239  static uint32  static uint32
240  translate_colour(uint32 colour)  translate_colour(uint32 colour)
241  {  {
# Line 218  translate_colour(uint32 colour) Line 243  translate_colour(uint32 colour)
243          switch (g_server_bpp)          switch (g_server_bpp)
244          {          {
245                  case 15:                  case 15:
246                          pc = split_colour15(colour);                          SPLITCOLOUR15(colour, pc);
247                          break;                          break;
248                  case 16:                  case 16:
249                          pc = split_colour16(colour);                          SPLITCOLOUR16(colour, pc);
250                          break;                          break;
251                  case 24:                  case 24:
252                          pc = split_colour24(colour);                          SPLITCOLOUR24(colour, pc);
253                          break;                          break;
254          }          }
255          return make_colour(pc);          return MAKECOLOUR(pc);
256  }  }
257    
258    /* indent is confused by UNROLL8 */
259    /* *INDENT-OFF* */
260    
261    /* repeat and unroll, similar to bitmap.c */
262    /* potentialy any of the following translate */
263    /* functions can use repeat but just doing */
264    /* the most common ones */
265    
266    #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
267    /* 2 byte output repeat */
268    #define REPEAT2(stm) \
269    { \
270            while (out <= end - 8 * 2) \
271                    UNROLL8(stm) \
272            while (out < end) \
273                    { stm } \
274    }
275    /* 3 byte output repeat */
276    #define REPEAT3(stm) \
277    { \
278            while (out <= end - 8 * 3) \
279                    UNROLL8(stm) \
280            while (out < end) \
281                    { stm } \
282    }
283    /* 4 byte output repeat */
284    #define REPEAT4(stm) \
285    { \
286            while (out <= end - 8 * 4) \
287                    UNROLL8(stm) \
288            while (out < end) \
289                    { stm } \
290    }
291    /* *INDENT-ON* */
292    
293  static void  static void
294  translate8to8(uint8 * data, uint8 * out, uint8 * end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
295  {  {
296          while (out < end)          while (out < end)
297                  *(out++) = (uint8) g_colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
298  }  }
299    
300  static void  static void
301  translate8to16(uint8 * data, uint8 * out, uint8 * end)  translate8to16(const uint8 * data, uint8 * out, uint8 * end)
302  {  {
303          uint16 value;          uint16 value;
304    
305          while (out < end)          if (g_arch_match)
306          {          {
307                  value = (uint16) g_colmap[*(data++)];                  /* *INDENT-OFF* */
308                    REPEAT2
309                  if (g_xserver_be)                  (
310                            *((uint16 *) out) = g_colmap[*(data++)];
311                            out += 2;
312                    )
313                    /* *INDENT-ON* */
314            }
315            else if (g_xserver_be)
316            {
317                    while (out < end)
318                  {                  {
319                          *(out++) = value >> 8;                          value = (uint16) g_colmap[*(data++)];
320                          *(out++) = value;                          BOUT16(out, value);
321                  }                  }
322                  else          }
323            else
324            {
325                    while (out < end)
326                  {                  {
327                          *(out++) = value;                          value = (uint16) g_colmap[*(data++)];
328                          *(out++) = value >> 8;                          LOUT16(out, value);
329                  }                  }
330          }          }
331  }  }
332    
333  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
334  static void  static void
335  translate8to24(uint8 * data, uint8 * out, uint8 * end)  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
336  {  {
337          uint32 value;          uint32 value;
338    
339          while (out < end)          if (g_xserver_be)
340          {          {
341                  value = g_colmap[*(data++)];                  while (out < end)
   
                 if (g_xserver_be)  
342                  {                  {
343                          *(out++) = value >> 16;                          value = g_colmap[*(data++)];
344                          *(out++) = value >> 8;                          BOUT24(out, value);
                         *(out++) = value;  
345                  }                  }
346                  else          }
347            else
348            {
349                    while (out < end)
350                  {                  {
351                          *(out++) = value;                          value = g_colmap[*(data++)];
352                          *(out++) = value >> 8;                          LOUT24(out, value);
                         *(out++) = value >> 16;  
353                  }                  }
354          }          }
355  }  }
356    
357  static void  static void
358  translate8to32(uint8 * data, uint8 * out, uint8 * end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
359  {  {
360          uint32 value;          uint32 value;
361    
362          while (out < end)          if (g_arch_match)
363          {          {
364                  value = g_colmap[*(data++)];                  /* *INDENT-OFF* */
365                    REPEAT4
366                  if (g_xserver_be)                  (
367                            *((uint32 *) out) = g_colmap[*(data++)];
368                            out += 4;
369                    )
370                    /* *INDENT-ON* */
371            }
372            else if (g_xserver_be)
373            {
374                    while (out < end)
375                  {                  {
376                          *(out++) = value >> 24;                          value = g_colmap[*(data++)];
377                          *(out++) = value >> 16;                          BOUT32(out, value);
                         *(out++) = value >> 8;  
                         *(out++) = value;  
378                  }                  }
379                  else          }
380            else
381            {
382                    while (out < end)
383                  {                  {
384                          *(out++) = value;                          value = g_colmap[*(data++)];
385                          *(out++) = value >> 8;                          LOUT32(out, value);
                         *(out++) = value >> 16;  
                         *(out++) = value >> 24;  
386                  }                  }
387          }          }
388  }  }
389    
 /* todo the remaining translate function might need some big endian check ?? */  
   
390  static void  static void
391  translate15to16(uint16 * data, uint8 * out, uint8 * end)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
392  {  {
393          uint16 pixel;          uint16 pixel;
394          uint16 value;          uint16 value;
395            PixelColour pc;
396    
397          while (out < end)          if (g_xserver_be)
398          {          {
399                  pixel = *(data++);                  while (out < end)
   
                 if (g_host_be)  
                 {  
                         BSWAP16(pixel);  
                 }  
   
                 value = make_colour(split_colour15(pixel));  
   
                 if (g_xserver_be)  
400                  {                  {
401                          *(out++) = value >> 8;                          pixel = *(data++);
402                          *(out++) = value;                          if (g_host_be)
403                            {
404                                    BSWAP16(pixel);
405                            }
406                            SPLITCOLOUR15(pixel, pc);
407                            value = MAKECOLOUR(pc);
408                            BOUT16(out, value);
409                  }                  }
410                  else          }
411            else
412            {
413                    while (out < end)
414                  {                  {
415                          *(out++) = value;                          pixel = *(data++);
416                          *(out++) = value >> 8;                          if (g_host_be)
417                            {
418                                    BSWAP16(pixel);
419                            }
420                            SPLITCOLOUR15(pixel, pc);
421                            value = MAKECOLOUR(pc);
422                            LOUT16(out, value);
423                  }                  }
424          }          }
425  }  }
426    
427  static void  static void
428  translate15to24(uint16 * data, uint8 * out, uint8 * end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
429  {  {
430          uint32 value;          uint32 value;
431          uint16 pixel;          uint16 pixel;
432            PixelColour pc;
433    
434          while (out < end)          if (g_arch_match)
435          {          {
436                  pixel = *(data++);                  /* *INDENT-OFF* */
437                    REPEAT3
438                  if (g_host_be)                  (
439                  {                          pixel = *(data++);
440                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
441                  }                          *(out++) = pc.blue;
442                            *(out++) = pc.green;
443                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
444                  if (g_xserver_be)                  )
445                    /* *INDENT-ON* */
446            }
447            else if (g_xserver_be)
448            {
449                    while (out < end)
450                  {                  {
451                          *(out++) = value >> 16;                          pixel = *(data++);
452                          *(out++) = value >> 8;                          if (g_host_be)
453                          *(out++) = value;                          {
454                                    BSWAP16(pixel);
455                            }
456                            SPLITCOLOUR15(pixel, pc);
457                            value = MAKECOLOUR(pc);
458                            BOUT24(out, value);
459                  }                  }
460                  else          }
461            else
462            {
463                    while (out < end)
464                  {                  {
465                          *(out++) = value;                          pixel = *(data++);
466                          *(out++) = value >> 8;                          if (g_host_be)
467                          *(out++) = value >> 16;                          {
468                                    BSWAP16(pixel);
469                            }
470                            SPLITCOLOUR15(pixel, pc);
471                            value = MAKECOLOUR(pc);
472                            LOUT24(out, value);
473                  }                  }
474          }          }
475  }  }
476    
477  static void  static void
478  translate15to32(uint16 * data, uint8 * out, uint8 * end)  translate15to32(const uint16 * data, uint8 * out, uint8 * end)
479  {  {
480          uint16 pixel;          uint16 pixel;
481          uint32 value;          uint32 value;
482            PixelColour pc;
483    
484          while (out < end)          if (g_arch_match)
485          {          {
486                  pixel = *(data++);                  /* *INDENT-OFF* */
487                    REPEAT4
488                  if (g_host_be)                  (
489                  {                          pixel = *(data++);
490                          BSWAP16(pixel);                          SPLITCOLOUR15(pixel, pc);
491                  }                          *(out++) = pc.blue;
492                            *(out++) = pc.green;
493                  value = make_colour(split_colour15(pixel));                          *(out++) = pc.red;
494                            *(out++) = 0;
495                  if (g_xserver_be)                  )
496                    /* *INDENT-ON* */
497            }
498            else if (g_xserver_be)
499            {
500                    while (out < end)
501                  {                  {
502                          *(out++) = value >> 24;                          pixel = *(data++);
503                          *(out++) = value >> 16;                          if (g_host_be)
504                          *(out++) = value >> 8;                          {
505                          *(out++) = value;                                  BSWAP16(pixel);
506                            }
507                            SPLITCOLOUR15(pixel, pc);
508                            value = MAKECOLOUR(pc);
509                            BOUT32(out, value);
510                  }                  }
511                  else          }
512            else
513            {
514                    while (out < end)
515                  {                  {
516                          *(out++) = value;                          pixel = *(data++);
517                          *(out++) = value >> 8;                          if (g_host_be)
518                          *(out++) = value >> 16;                          {
519                          *(out++) = value >> 24;                                  BSWAP16(pixel);
520                            }
521                            SPLITCOLOUR15(pixel, pc);
522                            value = MAKECOLOUR(pc);
523                            LOUT32(out, value);
524                  }                  }
525          }          }
526  }  }
527    
528  static void  static void
529  translate16to16(uint16 * data, uint8 * out, uint8 * end)  translate16to16(const uint16 * data, uint8 * out, uint8 * end)
530  {  {
531          uint16 pixel;          uint16 pixel;
532          uint16 value;          uint16 value;
533            PixelColour pc;
534    
535          while (out < end)          if (g_xserver_be)
536          {          {
                 pixel = *(data++);  
   
537                  if (g_host_be)                  if (g_host_be)
538                  {                  {
539                          BSWAP16(pixel);                          while (out < end)
540                            {
541                                    pixel = *(data++);
542                                    BSWAP16(pixel);
543                                    SPLITCOLOUR16(pixel, pc);
544                                    value = MAKECOLOUR(pc);
545                                    BOUT16(out, value);
546                            }
547                  }                  }
548                    else
                 value = make_colour(split_colour16(pixel));  
   
                 if (g_xserver_be)  
549                  {                  {
550                          *(out++) = value >> 8;                          while (out < end)
551                          *(out++) = value;                          {
552                                    pixel = *(data++);
553                                    SPLITCOLOUR16(pixel, pc);
554                                    value = MAKECOLOUR(pc);
555                                    BOUT16(out, value);
556                            }
557                    }
558            }
559            else
560            {
561                    if (g_host_be)
562                    {
563                            while (out < end)
564                            {
565                                    pixel = *(data++);
566                                    BSWAP16(pixel);
567                                    SPLITCOLOUR16(pixel, pc);
568                                    value = MAKECOLOUR(pc);
569                                    LOUT16(out, value);
570                            }
571                  }                  }
572                  else                  else
573                  {                  {
574                          *(out++) = value;                          while (out < end)
575                          *(out++) = value >> 8;                          {
576                                    pixel = *(data++);
577                                    SPLITCOLOUR16(pixel, pc);
578                                    value = MAKECOLOUR(pc);
579                                    LOUT16(out, value);
580                            }
581                  }                  }
582          }          }
583  }  }
584    
585  static void  static void
586  translate16to24(uint16 * data, uint8 * out, uint8 * end)  translate16to24(const uint16 * data, uint8 * out, uint8 * end)
587  {  {
588          uint32 value;          uint32 value;
589          uint16 pixel;          uint16 pixel;
590            PixelColour pc;
591    
592          while (out < end)          if (g_arch_match)
593            {
594                    /* *INDENT-OFF* */
595                    REPEAT3
596                    (
597                            pixel = *(data++);
598                            SPLITCOLOUR16(pixel, pc);
599                            *(out++) = pc.blue;
600                            *(out++) = pc.green;
601                            *(out++) = pc.red;
602                    )
603                    /* *INDENT-ON* */
604            }
605            else if (g_xserver_be)
606          {          {
                 pixel = *(data++);  
   
607                  if (g_host_be)                  if (g_host_be)
608                  {                  {
609                          BSWAP16(pixel);                          while (out < end)
610                            {
611                                    pixel = *(data++);
612                                    BSWAP16(pixel);
613                                    SPLITCOLOUR16(pixel, pc);
614                                    value = MAKECOLOUR(pc);
615                                    BOUT24(out, value);
616                            }
617                  }                  }
618                    else
619                  value = make_colour(split_colour16(pixel));                  {
620                            while (out < end)
621                  if (g_xserver_be)                          {
622                                    pixel = *(data++);
623                                    SPLITCOLOUR16(pixel, pc);
624                                    value = MAKECOLOUR(pc);
625                                    BOUT24(out, value);
626                            }
627                    }
628            }
629            else
630            {
631                    if (g_host_be)
632                  {                  {
633                          *(out++) = value >> 16;                          while (out < end)
634                          *(out++) = value >> 8;                          {
635                          *(out++) = value;                                  pixel = *(data++);
636                                    BSWAP16(pixel);
637                                    SPLITCOLOUR16(pixel, pc);
638                                    value = MAKECOLOUR(pc);
639                                    LOUT24(out, value);
640                            }
641                  }                  }
642                  else                  else
643                  {                  {
644                          *(out++) = value;                          while (out < end)
645                          *(out++) = value >> 8;                          {
646                          *(out++) = value >> 16;                                  pixel = *(data++);
647                                    SPLITCOLOUR16(pixel, pc);
648                                    value = MAKECOLOUR(pc);
649                                    LOUT24(out, value);
650                            }
651                  }                  }
652          }          }
653  }  }
654    
655  static void  static void
656  translate16to32(uint16 * data, uint8 * out, uint8 * end)  translate16to32(const uint16 * data, uint8 * out, uint8 * end)
657  {  {
658          uint16 pixel;          uint16 pixel;
659          uint32 value;          uint32 value;
660            PixelColour pc;
661    
662          while (out < end)          if (g_arch_match)
663            {
664                    /* *INDENT-OFF* */
665                    REPEAT4
666                    (
667                            pixel = *(data++);
668                            SPLITCOLOUR16(pixel, pc);
669                            *(out++) = pc.blue;
670                            *(out++) = pc.green;
671                            *(out++) = pc.red;
672                            *(out++) = 0;
673                    )
674                    /* *INDENT-ON* */
675            }
676            else if (g_xserver_be)
677          {          {
                 pixel = *(data++);  
   
678                  if (g_host_be)                  if (g_host_be)
679                  {                  {
680                          BSWAP16(pixel);                          while (out < end)
681                            {
682                                    pixel = *(data++);
683                                    BSWAP16(pixel);
684                                    SPLITCOLOUR16(pixel, pc);
685                                    value = MAKECOLOUR(pc);
686                                    BOUT32(out, value);
687                            }
688                  }                  }
689                    else
690                  value = make_colour(split_colour16(pixel));                  {
691                            while (out < end)
692                  if (g_xserver_be)                          {
693                                    pixel = *(data++);
694                                    SPLITCOLOUR16(pixel, pc);
695                                    value = MAKECOLOUR(pc);
696                                    BOUT32(out, value);
697                            }
698                    }
699            }
700            else
701            {
702                    if (g_host_be)
703                  {                  {
704                          *(out++) = value >> 24;                          while (out < end)
705                          *(out++) = value >> 16;                          {
706                          *(out++) = value >> 8;                                  pixel = *(data++);
707                          *(out++) = value;                                  BSWAP16(pixel);
708                                    SPLITCOLOUR16(pixel, pc);
709                                    value = MAKECOLOUR(pc);
710                                    LOUT32(out, value);
711                            }
712                  }                  }
713                  else                  else
714                  {                  {
715                          *(out++) = value;                          while (out < end)
716                          *(out++) = value >> 8;                          {
717                          *(out++) = value >> 16;                                  pixel = *(data++);
718                          *(out++) = value >> 24;                                  SPLITCOLOUR16(pixel, pc);
719                                    value = MAKECOLOUR(pc);
720                                    LOUT32(out, value);
721                            }
722                  }                  }
723          }          }
724  }  }
725    
726  static void  static void
727  translate24to16(uint8 * data, uint8 * out, uint8 * end)  translate24to16(const uint8 * data, uint8 * out, uint8 * end)
728  {  {
729          uint32 pixel = 0;          uint32 pixel = 0;
730          uint16 value;          uint16 value;
731            PixelColour pc;
732    
733          while (out < end)          while (out < end)
734          {          {
735                  pixel = *(data++) << 16;                  pixel = *(data++) << 16;
736                  pixel |= *(data++) << 8;                  pixel |= *(data++) << 8;
737                  pixel |= *(data++);                  pixel |= *(data++);
738                    SPLITCOLOUR24(pixel, pc);
739                  value = (uint16) make_colour(split_colour24(pixel));                  value = MAKECOLOUR(pc);
   
740                  if (g_xserver_be)                  if (g_xserver_be)
741                  {                  {
742                          *(out++) = value >> 8;                          BOUT16(out, value);
                         *(out++) = value;  
743                  }                  }
744                  else                  else
745                  {                  {
746                          *(out++) = value;                          LOUT16(out, value);
                         *(out++) = value >> 8;  
747                  }                  }
748          }          }
749  }  }
750    
751  static void  static void
752  translate24to24(uint8 * data, uint8 * out, uint8 * end)  translate24to24(const uint8 * data, uint8 * out, uint8 * end)
753  {  {
754          uint32 pixel;          uint32 pixel;
755          uint32 value;          uint32 value;
756            PixelColour pc;
757    
758          while (out < end)          if (g_xserver_be)
759          {          {
760                  pixel = *(data++) << 16;                  while (out < end)
                 pixel |= *(data++) << 8;  
                 pixel |= *(data++);  
   
                 value = make_colour(split_colour24(pixel));  
                   
                 if (g_xserver_be)  
761                  {                  {
762                          *(out++) = value >> 16;                          pixel = *(data++) << 16;
763                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
764                          *(out++) = value;                          pixel |= *(data++);
765                            SPLITCOLOUR24(pixel, pc);
766                            value = MAKECOLOUR(pc);
767                            BOUT24(out, value);
768                  }                  }
769                  else          }
770            else
771            {
772                    while (out < end)
773                  {                  {
774                          *(out++) = value;                          pixel = *(data++) << 16;
775                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
776                          *(out++) = value >> 16;                          pixel |= *(data++);
777                            SPLITCOLOUR24(pixel, pc);
778                            value = MAKECOLOUR(pc);
779                            LOUT24(out, value);
780                  }                  }
781          }          }
782  }  }
783    
784  static void  static void
785  translate24to32(uint8 * data, uint8 * out, uint8 * end)  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
786  {  {
787          uint32 pixel;          uint32 pixel;
788          uint32 value;          uint32 value;
789            PixelColour pc;
790    
791          while (out < end)          if (g_arch_match)
792          {          {
793                  pixel = *(data++) << 16;                  /* *INDENT-OFF* */
794                  pixel |= *(data++) << 8;  #ifdef NEED_ALIGN
795                  pixel |= *(data++);                  REPEAT4
796                    (
797                  value = make_colour(split_colour24(pixel));                          *(out++) = *(data++);
798                            *(out++) = *(data++);
799                  if (g_xserver_be)                          *(out++) = *(data++);
800                            *(out++) = 0;
801                    )
802    #else
803                    REPEAT4
804                    (
805                     /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
806                     *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
807                     out += 4;
808                     data += 3;
809                    )
810    #endif
811                    /* *INDENT-ON* */
812            }
813            else if (g_xserver_be)
814            {
815                    while (out < end)
816                  {                  {
817                          *(out++) = value >> 24;                          pixel = *(data++) << 16;
818                          *(out++) = value >> 16;                          pixel |= *(data++) << 8;
819                          *(out++) = value >> 8;                          pixel |= *(data++);
820                          *(out++) = value;                          SPLITCOLOUR24(pixel, pc);
821                            value = MAKECOLOUR(pc);
822                            BOUT32(out, value);
823                  }                  }
824                  else          }
825            else
826            {
827                    while (out < end)
828                  {                  {
829                          *(out++) = value;                          pixel = *(data++) << 16;
830                          *(out++) = value >> 8;                          pixel |= *(data++) << 8;
831                          *(out++) = value >> 16;                          pixel |= *(data++);
832                          *(out++) = value >> 24;                          SPLITCOLOUR24(pixel, pc);
833                            value = MAKECOLOUR(pc);
834                            LOUT32(out, value);
835                  }                  }
836          }          }
837  }  }
# Line 592  translate24to32(uint8 * data, uint8 * ou Line 839  translate24to32(uint8 * data, uint8 * ou
839  static uint8 *  static uint8 *
840  translate_image(int width, int height, uint8 * data)  translate_image(int width, int height, uint8 * data)
841  {  {
842          int size = width * height * g_bpp / 8;          int size;
843          uint8 *out = (uint8 *) xmalloc(size);          uint8 *out;
844          uint8 *end = out + size;          uint8 *end;
845    
846            /* if server and xserver bpp match, */
847            /* and arch(endian) matches, no need to translate */
848            /* just return data */
849            if (g_arch_match)
850            {
851                    if (g_depth == 15 && g_server_bpp == 15)
852                            return data;
853                    if (g_depth == 16 && g_server_bpp == 16)
854                            return data;
855                    if (g_depth == 24 && g_bpp == 24 && g_server_bpp == 24)
856                            return data;
857            }
858    
859            size = width * height * (g_bpp / 8);
860            out = (uint8 *) xmalloc(size);
861            end = out + size;
862    
863          switch (g_server_bpp)          switch (g_server_bpp)
864          {          {
# Line 700  ui_init(void) Line 964  ui_init(void)
964          XVisualInfo vi;          XVisualInfo vi;
965          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
966          uint16 test;          uint16 test;
967          int i, screen_num;          int i, screen_num, nvisuals;
968            XVisualInfo *vmatches = NULL;
969            XVisualInfo template;
970            Bool TrueColorVisual = False;
971    
972          g_display = XOpenDisplay(NULL);          g_display = XOpenDisplay(NULL);
973          if (g_display == NULL)          if (g_display == NULL)
# Line 714  ui_init(void) Line 981  ui_init(void)
981          g_screen = ScreenOfDisplay(g_display, screen_num);          g_screen = ScreenOfDisplay(g_display, screen_num);
982          g_depth = DefaultDepthOfScreen(g_screen);          g_depth = DefaultDepthOfScreen(g_screen);
983    
984          if (g_server_bpp == 8)          /* Search for best TrueColor depth */
985            template.class = TrueColor;
986            vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);
987    
988            nvisuals--;
989            while (nvisuals >= 0)
990            {
991                    if ((vmatches + nvisuals)->depth > g_depth)
992                    {
993                            g_depth = (vmatches + nvisuals)->depth;
994                    }
995                    nvisuals--;
996                    TrueColorVisual = True;
997            }
998    
999            test = 1;
1000            g_host_be = !(BOOL) (*(uint8 *) (&test));
1001            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1002    
1003            if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))
1004          {          {
1005                  /* we use a colourmap, so any visual should do */                  /* we use a colourmap, so the default visual should do */
1006                  g_visual = DefaultVisualOfScreen(g_screen);                  g_visual = DefaultVisualOfScreen(g_screen);
1007                    g_depth = DefaultDepthOfScreen(g_screen);
1008    
1009                    /* Do not allocate colours on a TrueColor visual */
1010                    if (g_visual->class == TrueColor)
1011                    {
1012                            g_owncolmap = False;
1013                    }
1014          }          }
1015          else          else
1016          {          {
# Line 733  ui_init(void) Line 1026  ui_init(void)
1026                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);
1027                  calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);                  calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);
1028                  calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);                  calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);
1029    
1030                    /* if RGB video and everything is little endian */
1031                    if ((vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask) &&
1032                        !g_xserver_be && !g_host_be)
1033                    {
1034                            if (g_depth <= 16 || (g_red_shift_l == 16 && g_green_shift_l == 8 &&
1035                                                  g_blue_shift_l == 0))
1036                            {
1037                                    g_arch_match = True;
1038                            }
1039                    }
1040    
1041                    if (g_arch_match)
1042                    {
1043                            DEBUG(("Architectures match, enabling little endian optimisations.\n"));
1044                    }
1045          }          }
1046    
1047          pfm = XListPixmapFormats(g_display, &i);          pfm = XListPixmapFormats(g_display, &i);
# Line 759  ui_init(void) Line 1068  ui_init(void)
1068    
1069          if (!g_owncolmap)          if (!g_owncolmap)
1070          {          {
1071                  g_xcolmap = DefaultColormapOfScreen(g_screen);                  g_xcolmap =
1072                            XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1073                                            AllocNone);
1074                  if (g_depth <= 8)                  if (g_depth <= 8)
1075                          warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");                          warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
1076          }          }
1077    
1078          g_gc = XCreateGC(g_display, RootWindowOfScreen(g_screen), 0, NULL);          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1079            {
1080          if (DoesBackingStore(g_screen) != Always)                  warning("External BackingStore not available, using internal\n");
1081                  g_ownbackstore = True;                  g_ownbackstore = True;
1082            }
         test = 1;  
         g_host_be = !(BOOL) (*(uint8 *) (&test));  
         g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);  
1083    
1084          /*          /*
1085           * Determine desktop size           * Determine desktop size
1086           */           */
1087          if (g_width < 0)          if (g_fullscreen)
1088            {
1089                    g_width = WidthOfScreen(g_screen);
1090                    g_height = HeightOfScreen(g_screen);
1091            }
1092            else if (g_width < 0)
1093          {          {
1094                  /* Percent of screen */                  /* Percent of screen */
1095                    if (-g_width >= 100)
1096                            g_using_full_workarea = True;
1097                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1098                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1099          }          }
# Line 786  ui_init(void) Line 1101  ui_init(void)
1101          {          {
1102                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1103                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
1104                    g_using_full_workarea = True;
1105    
1106                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1107                  {                  {
# Line 799  ui_init(void) Line 1115  ui_init(void)
1115                          g_height = 600;                          g_height = 600;
1116                  }                  }
1117          }          }
         else if (g_fullscreen)  
         {  
                 g_width = WidthOfScreen(g_screen);  
                 g_height = HeightOfScreen(g_screen);  
         }  
1118    
1119          /* make sure width is a multiple of 4 */          /* make sure width is a multiple of 4 */
1120          g_width = (g_width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1121    
         if (g_ownbackstore)  
         {  
                 g_backstore =  
                         XCreatePixmap(g_display, RootWindowOfScreen(g_screen), g_width, g_height,  
                                       g_depth);  
   
                 /* clear to prevent rubbish being exposed at startup */  
                 XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));  
                 XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);  
         }  
   
1122          g_mod_map = XGetModifierMapping(g_display);          g_mod_map = XGetModifierMapping(g_display);
1123    
1124          xkeymap_init();          xkeymap_init();
# Line 839  ui_deinit(void) Line 1139  ui_deinit(void)
1139          if (g_IM != NULL)          if (g_IM != NULL)
1140                  XCloseIM(g_IM);                  XCloseIM(g_IM);
1141    
1142            if (g_null_cursor != NULL)
1143                    ui_destroy_cursor(g_null_cursor);
1144    
1145          XFreeModifiermap(g_mod_map);          XFreeModifiermap(g_mod_map);
1146    
1147          if (g_ownbackstore)          if (g_ownbackstore)
# Line 853  BOOL Line 1156  BOOL
1156  ui_create_window(void)  ui_create_window(void)
1157  {  {
1158          uint8 null_pointer_mask[1] = { 0x80 };          uint8 null_pointer_mask[1] = { 0x80 };
1159          uint8 null_pointer_data[4] = { 0x00, 0x00, 0x00, 0x00 };          uint8 null_pointer_data[24] = { 0x00 };
1160    
1161          XSetWindowAttributes attribs;          XSetWindowAttributes attribs;
1162          XClassHint *classhints;          XClassHint *classhints;
1163          XSizeHints *sizehints;          XSizeHints *sizehints;
# Line 864  ui_create_window(void) Line 1168  ui_create_window(void)
1168          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1169          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1170    
1171            /* Handle -x-y portion of geometry string */
1172            if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1173                    g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1174            if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1175                    g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1176    
1177          attribs.background_pixel = BlackPixelOfScreen(g_screen);          attribs.background_pixel = BlackPixelOfScreen(g_screen);
1178            attribs.border_pixel = WhitePixelOfScreen(g_screen);
1179          attribs.backing_store = g_ownbackstore ? NotUseful : Always;          attribs.backing_store = g_ownbackstore ? NotUseful : Always;
1180          attribs.override_redirect = g_fullscreen;          attribs.override_redirect = g_fullscreen;
1181            attribs.colormap = g_xcolmap;
1182    
1183          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,
1184                                0, CopyFromParent, InputOutput, CopyFromParent,                                wndheight, 0, g_depth, InputOutput, g_visual,
1185                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);                                CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1186                                  CWBorderPixel, &attribs);
1187    
1188            if (g_gc == NULL)
1189                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1190    
1191            if (g_create_bitmap_gc == NULL)
1192                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1193    
1194            if ((g_ownbackstore) && (g_backstore == 0))
1195            {
1196                    g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1197    
1198                    /* clear to prevent rubbish being exposed at startup */
1199                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1200                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
1201            }
1202    
1203          XStoreName(g_display, g_wnd, g_title);          XStoreName(g_display, g_wnd, g_title);
1204    
# Line 889  ui_create_window(void) Line 1217  ui_create_window(void)
1217          if (sizehints)          if (sizehints)
1218          {          {
1219                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1220                    if (g_pos)
1221                            sizehints->flags |= PPosition;
1222                  sizehints->min_width = sizehints->max_width = g_width;                  sizehints->min_width = sizehints->max_width = g_width;
1223                  sizehints->min_height = sizehints->max_height = g_height;                  sizehints->min_height = sizehints->max_height = g_height;
1224                  XSetWMNormalHints(g_display, g_wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
1225                  XFree(sizehints);                  XFree(sizehints);
1226          }          }
1227    
1228            if (g_embed_wnd)
1229            {
1230                    XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1231            }
1232    
1233          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1234                  VisibilityChangeMask | FocusChangeMask;                  VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1235    
1236          if (g_sendmotion)          if (g_sendmotion)
1237                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
# Line 926  ui_create_window(void) Line 1261  ui_create_window(void)
1261                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);                  XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1262          }          }
1263          while (xevent.type != VisibilityNotify);          while (xevent.type != VisibilityNotify);
1264            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1265    
1266          g_focused = False;          g_focused = False;
1267          g_mouse_in_wnd = False;          g_mouse_in_wnd = False;
# Line 936  ui_create_window(void) Line 1272  ui_create_window(void)
1272          XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);          XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1273    
1274          /* create invisible 1x1 cursor to be used as null cursor */          /* create invisible 1x1 cursor to be used as null cursor */
1275          g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);          if (g_null_cursor == NULL)
1276                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1277    
1278          return True;          return True;
1279  }  }
1280    
1281  void  void
1282  ui_destroy_window(void)  ui_resize_window()
1283  {  {
1284          ui_destroy_cursor(g_null_cursor);          XSizeHints *sizehints;
1285            Pixmap bs;
1286    
1287            sizehints = XAllocSizeHints();
1288            if (sizehints)
1289            {
1290                    sizehints->flags = PMinSize | PMaxSize;
1291                    sizehints->min_width = sizehints->max_width = g_width;
1292                    sizehints->min_height = sizehints->max_height = g_height;
1293                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1294                    XFree(sizehints);
1295            }
1296    
1297            if (!(g_fullscreen || g_embed_wnd))
1298            {
1299                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1300            }
1301    
1302            /* create new backstore pixmap */
1303            if (g_backstore != 0)
1304            {
1305                    bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1306                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1307                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1308                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1309                    XFreePixmap(g_display, g_backstore);
1310                    g_backstore = bs;
1311            }
1312    }
1313    
1314    void
1315    ui_destroy_window(void)
1316    {
1317          if (g_IC != NULL)          if (g_IC != NULL)
1318                  XDestroyIC(g_IC);                  XDestroyIC(g_IC);
1319    
# Line 977  xwin_toggle_fullscreen(void) Line 1345  xwin_toggle_fullscreen(void)
1345          }          }
1346  }  }
1347    
1348  /* Process all events in Xlib queue  static void
1349    handle_button_event(XEvent xevent, BOOL down)
1350    {
1351            uint16 button, flags = 0;
1352            g_last_gesturetime = xevent.xbutton.time;
1353            button = xkeymap_translate_button(xevent.xbutton.button);
1354            if (button == 0)
1355                    return;
1356    
1357            if (down)
1358                    flags = MOUSE_FLAG_DOWN;
1359    
1360            /* Stop moving window when button is released, regardless of cursor position */
1361            if (g_moving_wnd && (xevent.type == ButtonRelease))
1362                    g_moving_wnd = False;
1363    
1364            /* If win_button_size is nonzero, enable single app mode */
1365            if (xevent.xbutton.y < g_win_button_size)
1366            {
1367                    /*  Check from right to left: */
1368                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1369                    {
1370                            /* The close button, continue */
1371                            ;
1372                    }
1373                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1374                    {
1375                            /* The maximize/restore button. Do not send to
1376                               server.  It might be a good idea to change the
1377                               cursor or give some other visible indication
1378                               that rdesktop inhibited this click */
1379                            if (xevent.type == ButtonPress)
1380                                    return;
1381                    }
1382                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1383                    {
1384                            /* The minimize button. Iconify window. */
1385                            if (xevent.type == ButtonRelease)
1386                            {
1387                                    /* Release the mouse button outside the minimize button, to prevent the
1388                                       actual minimazation to happen */
1389                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1390                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1391                                    return;
1392                            }
1393                    }
1394                    else if (xevent.xbutton.x <= g_win_button_size)
1395                    {
1396                            /* The system menu. Ignore. */
1397                            if (xevent.type == ButtonPress)
1398                                    return;
1399                    }
1400                    else
1401                    {
1402                            /* The title bar. */
1403                            if (xevent.type == ButtonPress)
1404                            {
1405                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1406                                    {
1407                                            g_moving_wnd = True;
1408                                            g_move_x_offset = xevent.xbutton.x;
1409                                            g_move_y_offset = xevent.xbutton.y;
1410                                    }
1411                                    return;
1412                            }
1413                    }
1414            }
1415    
1416            rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1417                           flags | button, xevent.xbutton.x, xevent.xbutton.y);
1418    }
1419    
1420    /* Process events in Xlib queue
1421     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1422  static int  static int
1423  xwin_process_events(void)  xwin_process_events(void)
1424  {  {
1425          XEvent xevent;          XEvent xevent;
1426          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1427          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1428          char str[256];          char str[256];
1429          Status status;          Status status;
1430          unsigned int state;          int events = 0;
         Window wdummy;  
         int dummy;  
1431    
1432          while (XPending(g_display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1433          {          {
1434                  XNextEvent(g_display, &xevent);                  XNextEvent(g_display, &xevent);
1435    
# Line 1003  xwin_process_events(void) Line 1439  xwin_process_events(void)
1439                          continue;                          continue;
1440                  }                  }
1441    
                 flags = 0;  
   
1442                  switch (xevent.type)                  switch (xevent.type)
1443                  {                  {
1444                            case VisibilityNotify:
1445                                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1446                                    break;
1447                          case ClientMessage:                          case ClientMessage:
1448                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
1449                                  if ((xevent.xclient.message_type == g_protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
# Line 1038  xwin_process_events(void) Line 1475  xwin_process_events(void)
1475                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1476                                  }                                  }
1477    
1478                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1479                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1480    
1481                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1482                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1483                                          break;                                          break;
1484    
1485                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1486                                                             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);  
   
1487                                  break;                                  break;
1488    
1489                          case KeyRelease:                          case KeyRelease:
# Line 1063  xwin_process_events(void) Line 1491  xwin_process_events(void)
1491                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
1492                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
1493    
1494                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1495                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1496    
1497                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1498                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1499                                          break;                                          break;
1500    
1501                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1502                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
1503                                  break;                                  break;
1504    
1505                          case ButtonPress:                          case ButtonPress:
1506                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
1507                                  /* fall through */                                  break;
1508    
1509                          case ButtonRelease:                          case ButtonRelease:
1510                                  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);  
1511                                  break;                                  break;
1512    
1513                          case MotionNotify:                          case MotionNotify:
# Line 1164  xwin_process_events(void) Line 1530  xwin_process_events(void)
1530                                  if (xevent.xfocus.mode == NotifyGrab)                                  if (xevent.xfocus.mode == NotifyGrab)
1531                                          break;                                          break;
1532                                  g_focused = True;                                  g_focused = True;
1533                                  XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy,                                  reset_modifier_keys();
                                               &dummy, &dummy, &state);  
                                 reset_modifier_keys(state);  
1534                                  if (g_grab_keyboard && g_mouse_in_wnd)                                  if (g_grab_keyboard && g_mouse_in_wnd)
1535                                          XGrabKeyboard(g_display, g_wnd, True,                                          XGrabKeyboard(g_display, g_wnd, True,
1536                                                        GrabModeAsync, GrabModeAsync, CurrentTime);                                                        GrabModeAsync, GrabModeAsync, CurrentTime);
# Line 1236  xwin_process_events(void) Line 1600  xwin_process_events(void)
1600                          case PropertyNotify:                          case PropertyNotify:
1601                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
1602                                  break;                                  break;
1603                            case MapNotify:
1604                                    rdp_send_client_window_status(1);
1605                                    break;
1606                            case UnmapNotify:
1607                                    rdp_send_client_window_status(0);
1608                                    break;
1609                  }                  }
1610          }          }
1611          /* Keep going */          /* Keep going */
# Line 1246  xwin_process_events(void) Line 1616  xwin_process_events(void)
1616  int  int
1617  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1618  {  {
1619          int n = (rdp_socket > g_x_socket) ? rdp_socket + 1 : g_x_socket + 1;          int n;
1620          fd_set rfds, wfds;          fd_set rfds, wfds;
1621            struct timeval tv;
1622            BOOL s_timeout = False;
1623    
1624          while (True)          while (True)
1625          {          {
1626                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1627                  /* Process any events already waiting */                  /* Process any events already waiting */
1628                  if (!xwin_process_events())                  if (!xwin_process_events())
1629                          /* User quit */                          /* User quit */
# Line 1266  ui_select(int rdp_socket) Line 1639  ui_select(int rdp_socket)
1639                  if (g_dsp_busy)                  if (g_dsp_busy)
1640                  {                  {
1641                          FD_SET(g_dsp_fd, &wfds);                          FD_SET(g_dsp_fd, &wfds);
1642                          n = (g_dsp_fd + 1 > n) ? g_dsp_fd + 1 : n;                          n = (g_dsp_fd > n) ? g_dsp_fd : n;
1643                  }                  }
1644  #endif  #endif
1645                    /* default timeout */
1646                    tv.tv_sec = 60;
1647                    tv.tv_usec = 0;
1648    
1649                    /* add redirection handles */
1650                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1651    
1652                  switch (select(n, &rfds, &wfds, NULL, NULL))                  n++;
1653    
1654                    switch (select(n, &rfds, &wfds, NULL, &tv))
1655                  {                  {
1656                          case -1:                          case -1:
1657                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
1658    
1659                          case 0:                          case 0:
1660                                    /* Abort serial read calls */
1661                                    if (s_timeout)
1662                                            rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1663                                  continue;                                  continue;
1664                  }                  }
1665    
1666                    rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
1667    
1668                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1669                          return 1;                          return 1;
1670    
# Line 1320  ui_create_bitmap(int width, int height, Line 1706  ui_create_bitmap(int width, int height,
1706          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1707                               (char *) tdata, width, height, bitmap_pad, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
1708    
1709          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);
1710    
1711          XFree(image);          XFree(image);
1712          if (!g_owncolmap)          if (tdata != data)
1713                  xfree(tdata);                  xfree(tdata);
1714          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1715  }  }
# Line 1362  ui_paint_bitmap(int x, int y, int cx, in Line 1748  ui_paint_bitmap(int x, int y, int cx, in
1748          }          }
1749    
1750          XFree(image);          XFree(image);
1751          if (!g_owncolmap)          if (tdata != data)
1752                  xfree(tdata);                  xfree(tdata);
1753  }  }
1754    
# Line 1378  ui_create_glyph(int width, int height, u Line 1764  ui_create_glyph(int width, int height, u
1764          XImage *image;          XImage *image;
1765          Pixmap bitmap;          Pixmap bitmap;
1766          int scanline;          int scanline;
         GC gc;  
1767    
1768          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1769    
1770          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1771          gc = XCreateGC(g_display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
1772                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1773    
1774          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1775                               width, height, 8, scanline);                               width, height, 8, scanline);
# Line 1391  ui_create_glyph(int width, int height, u Line 1777  ui_create_glyph(int width, int height, u
1777          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1778          XInitImage(image);          XInitImage(image);
1779    
1780          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);
1781    
1782          XFree(image);          XFree(image);
         XFreeGC(g_display, gc);  
1783          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1784  }  }
1785    
# Line 1686  ui_patblt(uint8 opcode, Line 2071  ui_patblt(uint8 opcode,
2071          {          {
2072                  case 0: /* Solid */                  case 0: /* Solid */
2073                          SET_FOREGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
2074                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2075                          break;                          break;
2076    
2077                  case 2: /* Hatch */                  case 2: /* Hatch */
# Line 1697  ui_patblt(uint8 opcode, Line 2082  ui_patblt(uint8 opcode,
2082                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2083                          XSetStipple(g_display, g_gc, fill);                          XSetStipple(g_display, g_gc, fill);
2084                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2085                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2086                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2087                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2088                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
# Line 1707  ui_patblt(uint8 opcode, Line 2092  ui_patblt(uint8 opcode,
2092                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
2093                                  ipattern[7 - i] = brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
2094                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
   
2095                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
2096                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
2097                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2098                          XSetStipple(g_display, g_gc, fill);                          XSetStipple(g_display, g_gc, fill);
2099                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2100                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
                         FILL_RECTANGLE(x, y, cx, cy);  
   
2101                          XSetFillStyle(g_display, g_gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
2102                          XSetTSOrigin(g_display, g_gc, 0, 0);                          XSetTSOrigin(g_display, g_gc, 0, 0);
2103                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
# Line 1726  ui_patblt(uint8 opcode, Line 2108  ui_patblt(uint8 opcode,
2108          }          }
2109    
2110          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2111    
2112            if (g_ownbackstore)
2113                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2114  }  }
2115    
2116  void  void
# Line 1734  ui_screenblt(uint8 opcode, Line 2119  ui_screenblt(uint8 opcode,
2119               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
2120  {  {
2121          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
         XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);  
2122          if (g_ownbackstore)          if (g_ownbackstore)
2123                  XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);          {
2124                    if (g_Unobscured)
2125                    {
2126                            XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2127                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2128                                      y);
2129                    }
2130                    else
2131                    {
2132                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2133                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2134                                      y);
2135                    }
2136            }
2137            else
2138            {
2139                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2140            }
2141          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2142  }  }
2143    
# Line 1807  ui_rect( Line 2208  ui_rect(
2208          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2209  }  }
2210    
2211    void
2212    ui_polygon(uint8 opcode,
2213               /* mode */ uint8 fillmode,
2214               /* dest */ POINT * point, int npoints,
2215               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2216    {
2217            uint8 style, i, ipattern[8];
2218            Pixmap fill;
2219    
2220            SET_FUNCTION(opcode);
2221    
2222            switch (fillmode)
2223            {
2224                    case ALTERNATE:
2225                            XSetFillRule(g_display, g_gc, EvenOddRule);
2226                            break;
2227                    case WINDING:
2228                            XSetFillRule(g_display, g_gc, WindingRule);
2229                            break;
2230                    default:
2231                            unimpl("fill mode %d\n", fillmode);
2232            }
2233    
2234            if (brush)
2235                    style = brush->style;
2236            else
2237                    style = 0;
2238    
2239            switch (style)
2240            {
2241                    case 0: /* Solid */
2242                            SET_FOREGROUND(fgcolour);
2243                            FILL_POLYGON((XPoint *) point, npoints);
2244                            break;
2245    
2246                    case 2: /* Hatch */
2247                            fill = (Pixmap) ui_create_glyph(8, 8,
2248                                                            hatch_patterns + brush->pattern[0] * 8);
2249                            SET_FOREGROUND(fgcolour);
2250                            SET_BACKGROUND(bgcolour);
2251                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2252                            XSetStipple(g_display, g_gc, fill);
2253                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2254                            FILL_POLYGON((XPoint *) point, npoints);
2255                            XSetFillStyle(g_display, g_gc, FillSolid);
2256                            XSetTSOrigin(g_display, g_gc, 0, 0);
2257                            ui_destroy_glyph((HGLYPH) fill);
2258                            break;
2259    
2260                    case 3: /* Pattern */
2261                            for (i = 0; i != 8; i++)
2262                                    ipattern[7 - i] = brush->pattern[i];
2263                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2264                            SET_FOREGROUND(bgcolour);
2265                            SET_BACKGROUND(fgcolour);
2266                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2267                            XSetStipple(g_display, g_gc, fill);
2268                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2269                            FILL_POLYGON((XPoint *) point, npoints);
2270                            XSetFillStyle(g_display, g_gc, FillSolid);
2271                            XSetTSOrigin(g_display, g_gc, 0, 0);
2272                            ui_destroy_glyph((HGLYPH) fill);
2273                            break;
2274    
2275                    default:
2276                            unimpl("brush %d\n", brush->style);
2277            }
2278    
2279            RESET_FUNCTION(opcode);
2280    }
2281    
2282    void
2283    ui_polyline(uint8 opcode,
2284                /* dest */ POINT * points, int npoints,
2285                /* pen */ PEN * pen)
2286    {
2287            /* TODO: set join style */
2288            SET_FUNCTION(opcode);
2289            SET_FOREGROUND(pen->colour);
2290            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2291            if (g_ownbackstore)
2292                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2293                               CoordModePrevious);
2294            RESET_FUNCTION(opcode);
2295    }
2296    
2297    void
2298    ui_ellipse(uint8 opcode,
2299               /* mode */ uint8 fillmode,
2300               /* dest */ int x, int y, int cx, int cy,
2301               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2302    {
2303            uint8 style, i, ipattern[8];
2304            Pixmap fill;
2305    
2306            SET_FUNCTION(opcode);
2307    
2308            if (brush)
2309                    style = brush->style;
2310            else
2311                    style = 0;
2312    
2313            switch (style)
2314            {
2315                    case 0: /* Solid */
2316                            SET_FOREGROUND(fgcolour);
2317                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2318                            break;
2319    
2320                    case 2: /* Hatch */
2321                            fill = (Pixmap) ui_create_glyph(8, 8,
2322                                                            hatch_patterns + brush->pattern[0] * 8);
2323                            SET_FOREGROUND(fgcolour);
2324                            SET_BACKGROUND(bgcolour);
2325                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2326                            XSetStipple(g_display, g_gc, fill);
2327                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2328                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2329                            XSetFillStyle(g_display, g_gc, FillSolid);
2330                            XSetTSOrigin(g_display, g_gc, 0, 0);
2331                            ui_destroy_glyph((HGLYPH) fill);
2332                            break;
2333    
2334                    case 3: /* Pattern */
2335                            for (i = 0; i != 8; i++)
2336                                    ipattern[7 - i] = brush->pattern[i];
2337                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2338                            SET_FOREGROUND(bgcolour);
2339                            SET_BACKGROUND(fgcolour);
2340                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2341                            XSetStipple(g_display, g_gc, fill);
2342                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2343                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2344                            XSetFillStyle(g_display, g_gc, FillSolid);
2345                            XSetTSOrigin(g_display, g_gc, 0, 0);
2346                            ui_destroy_glyph((HGLYPH) fill);
2347                            break;
2348    
2349                    default:
2350                            unimpl("brush %d\n", brush->style);
2351            }
2352    
2353            RESET_FUNCTION(opcode);
2354    }
2355    
2356  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
2357  void  void
2358  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 1831  ui_draw_glyph(int mixmode, Line 2377  ui_draw_glyph(int mixmode,
2377  {\  {\
2378    glyph = cache_get_font (font, ttext[idx]);\    glyph = cache_get_font (font, ttext[idx]);\
2379    if (!(flags & TEXT2_IMPLICIT_X))\    if (!(flags & TEXT2_IMPLICIT_X))\
2380      {\
2381        xyoffset = ttext[++idx];\
2382        if ((xyoffset & 0x80))\
2383      {\      {\
2384        xyoffset = ttext[++idx];\        if (flags & TEXT2_VERTICAL)\
2385        if ((xyoffset & 0x80))\          y += ttext[idx+1] | (ttext[idx+2] << 8);\
         {\  
           if (flags & TEXT2_VERTICAL) \  
             y += ttext[idx+1] | (ttext[idx+2] << 8);\  
           else\  
             x += ttext[idx+1] | (ttext[idx+2] << 8);\  
           idx += 2;\  
         }\  
2386        else\        else\
2387          {\          x += ttext[idx+1] | (ttext[idx+2] << 8);\
2388            if (flags & TEXT2_VERTICAL) \        idx += 2;\
             y += xyoffset;\  
           else\  
             x += xyoffset;\  
         }\  
2389      }\      }\
2390    if (glyph != NULL)\      else\
2391      {\      {\
2392        ui_draw_glyph (mixmode, x + glyph->offset,\        if (flags & TEXT2_VERTICAL)\
2393                       y + glyph->baseline,\          y += xyoffset;\
2394                       glyph->width, glyph->height,\        else\
2395                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\          x += xyoffset;\
       if (flags & TEXT2_IMPLICIT_X)\  
         x += glyph->width;\  
2396      }\      }\
2397      }\
2398      if (glyph != NULL)\
2399      {\
2400        x1 = x + glyph->offset;\
2401        y1 = y + glyph->baseline;\
2402        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2403        XSetTSOrigin(g_display, g_gc, x1, y1);\
2404        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2405        if (flags & TEXT2_IMPLICIT_X)\
2406          x += glyph->width;\
2407      }\
2408  }  }
2409    
2410  void  void
2411  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,
2412               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2413               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2414               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2415  {  {
2416            /* TODO: use brush appropriately */
2417    
2418          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2419          int i, j, xyoffset;          int i, j, xyoffset, x1, y1;
2420          DATABLOB *entry;          DATABLOB *entry;
2421    
2422          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
2423    
2424            /* Sometimes, the boxcx value is something really large, like
2425               32691. This makes XCopyArea fail with Xvnc. The code below
2426               is a quick fix. */
2427            if (boxx + boxcx > g_width)
2428                    boxcx = g_width - boxx;
2429    
2430          if (boxcx > 1)          if (boxcx > 1)
2431          {          {
2432                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
# Line 1881  ui_draw_text(uint8 font, uint8 flags, in Line 2436  ui_draw_text(uint8 font, uint8 flags, in
2436                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2437          }          }
2438    
2439            SET_FOREGROUND(fgcolour);
2440            SET_BACKGROUND(bgcolour);
2441            XSetFillStyle(g_display, g_gc, FillStippled);
2442    
2443          /* Paint text, character by character */          /* Paint text, character by character */
2444          for (i = 0; i < length;)          for (i = 0; i < length;)
2445          {          {
2446                  switch (text[i])                  switch (text[i])
2447                  {                  {
2448                          case 0xff:                          case 0xff:
2449                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
2450                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
2451                                  {                                  {
2452                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
2453                                          exit(1);                                          for (j = 0; j < length; j++)
2454                                                    fprintf(stderr, "%02x ", text[j]);
2455                                            fprintf(stderr, "\n");
2456                                            i = length = 0;
2457                                            break;
2458                                  }                                  }
2459                                    cache_put_text(text[i + 1], text, text[i + 2]);
2460                                    i += 3;
2461                                    length -= i;
2462                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2463                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
2464                                  i = 0;                                  i = 0;
2465                                  break;                                  break;
2466    
2467                          case 0xfe:                          case 0xfe:
2468                                    /* At least one byte needs to follow */
2469                                    if (i + 2 > length)
2470                                    {
2471                                            warning("Skipping short 0xfe command:");
2472                                            for (j = 0; j < length; j++)
2473                                                    fprintf(stderr, "%02x ", text[j]);
2474                                            fprintf(stderr, "\n");
2475                                            i = length = 0;
2476                                            break;
2477                                    }
2478                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
2479                                  if (entry != NULL)                                  if (entry->data != NULL)
2480                                  {                                  {
2481                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
2482                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
2483                                          {                                          {
2484                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2485                                                          y += text[i + 2];                                                          y += text[i + 2];
# Line 1931  ui_draw_text(uint8 font, uint8 flags, in Line 2505  ui_draw_text(uint8 font, uint8 flags, in
2505                                  break;                                  break;
2506                  }                  }
2507          }          }
2508    
2509            XSetFillStyle(g_display, g_gc, FillSolid);
2510    
2511          if (g_ownbackstore)          if (g_ownbackstore)
2512          {          {
2513                  if (boxcx > 1)                  if (boxcx > 1)
# Line 1992  ui_desktop_restore(uint32 offset, int x, Line 2569  ui_desktop_restore(uint32 offset, int x,
2569    
2570          XFree(image);          XFree(image);
2571  }  }
2572    
2573    /* these do nothing here but are used in uiports */
2574    void
2575    ui_begin_update(void)
2576    {
2577    }
2578    
2579    void
2580    ui_end_update(void)
2581    {
2582    }

Legend:
Removed from v.536  
changed lines
  Added in v.1041

  ViewVC Help
Powered by ViewVC 1.1.26