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

Legend:
Removed from v.208  
changed lines
  Added in v.905

  ViewVC Help
Powered by ViewVC 1.1.26