/[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 36 by matty, Sat Sep 15 14:30:46 2001 UTC revision 988 by astrand, Thu Aug 25 20:27:45 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-Windows     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2001     Copyright (C) Matthew Chapman 1999-2005
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# 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 int g_pos;
36  static Display *display;  extern BOOL g_sendmotion;
37  static int x_socket;  extern BOOL g_fullscreen;
38  static Window wnd;  extern BOOL g_grab_keyboard;
39  static GC gc;  extern BOOL g_hide_decorations;
40  static Visual *visual;  extern char g_title[];
41  static int depth;  extern int g_server_bpp;
42  static int bpp;  extern int g_win_button_size;
43    
44    Display *g_display;
45    Time g_last_gesturetime;
46    static int g_x_socket;
47    static Screen *g_screen;
48    Window g_wnd;
49    extern uint32 g_embed_wnd;
50    BOOL g_enable_compose = False;
51    BOOL g_Unobscured;              /* used for screenblt */
52    static GC g_gc = NULL;
53    static GC g_create_bitmap_gc = NULL;
54    static GC g_create_glyph_gc = NULL;
55    static Visual *g_visual;
56    static int g_depth;
57    static int g_bpp;
58    static XIM g_IM;
59    static XIC g_IC;
60    static XModifierKeymap *g_mod_map;
61    static Cursor g_current_cursor;
62    static HCURSOR g_null_cursor = NULL;
63    static Atom g_protocol_atom, g_kill_atom;
64    static BOOL g_focused;
65    static BOOL g_mouse_in_wnd;
66    static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */
67    
68  /* endianness */  /* endianness */
69  static BOOL host_be;  static BOOL g_host_be;
70  static BOOL xserver_be;  static BOOL g_xserver_be;
71    static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
72    static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
73    
74  /* software backing store */  /* software backing store */
75  static BOOL ownbackstore;  extern BOOL g_ownbackstore;
76  static Pixmap backstore;  static Pixmap g_backstore = 0;
77    
78    /* Moving in single app mode */
79    static BOOL g_moving_wnd;
80    static int g_move_x_offset = 0;
81    static int g_move_y_offset = 0;
82    
83    #ifdef WITH_RDPSND
84    extern int g_dsp_fd;
85    extern BOOL g_dsp_busy;
86    extern BOOL g_rdpsnd;
87    #endif
88    
89    /* MWM decorations */
90    #define MWM_HINTS_DECORATIONS   (1L << 1)
91    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
92    typedef struct
93    {
94            uint32 flags;
95            uint32 functions;
96            uint32 decorations;
97            sint32 inputMode;
98            uint32 status;
99    }
100    PropMotifWmHints;
101    
102    typedef struct
103    {
104            uint32 red;
105            uint32 green;
106            uint32 blue;
107    }
108    PixelColour;
109    
110    
111  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
112  { \  { \
113          XFillRectangle(display, wnd, gc, x, y, cx, cy); \          XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
114          if (ownbackstore) \          if (g_ownbackstore) \
115                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \                  XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
116    }
117    
118    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
119    { \
120            XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
121    }
122    
123    #define FILL_POLYGON(p,np)\
124    { \
125            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
126            if (g_ownbackstore) \
127                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
128    }
129    
130    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
131    { \
132            switch (m) \
133            { \
134                    case 0: /* Outline */ \
135                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
136                            if (g_ownbackstore) \
137                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
138                            break; \
139                    case 1: /* Filled */ \
140                            XFillArc(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, \
141                                     cx, cy, 0, 360*64); \
142                            if (g_ownbackstore) \
143                                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y); \
144                            break; \
145            } \
146  }  }
147    
148  /* colour maps */  /* colour maps */
149  static BOOL owncolmap;  extern BOOL g_owncolmap;
150  static Colormap xcolmap;  static Colormap g_xcolmap;
151  static uint32 white;  static uint32 *g_colmap = NULL;
152  static uint32 *colmap;  
153    #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
154  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
155  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
 #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  
156    
157  static int rop2_map[] = {  static int rop2_map[] = {
158          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 81  static int rop2_map[] = { Line 173  static int rop2_map[] = {
173          GXset                   /* 1 */          GXset                   /* 1 */
174  };  };
175    
176  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
177  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
178    
179  static void  static void
180  translate8(uint8 *data, uint8 *out, uint8 *end)  mwm_hide_decorations(void)
181  {  {
182          while (out < end)          PropMotifWmHints motif_hints;
183                  *(out++) = (uint8)colmap[*(data++)];          Atom hintsatom;
184    
185            /* setup the property */
186            motif_hints.flags = MWM_HINTS_DECORATIONS;
187            motif_hints.decorations = 0;
188    
189            /* get the atom for the property */
190            hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
191            if (!hintsatom)
192            {
193                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
194                    return;
195            }
196    
197            XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
198                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
199    }
200    
201    #define SPLITCOLOUR15(colour, rv) \
202    { \
203            rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
204            rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
205            rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
206    }
207    
208    #define SPLITCOLOUR16(colour, rv) \
209    { \
210            rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
211            rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
212            rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
213    } \
214    
215    #define SPLITCOLOUR24(colour, rv) \
216    { \
217            rv.blue = (colour & 0xff0000) >> 16; \
218            rv.green = (colour & 0x00ff00) >> 8; \
219            rv.red = (colour & 0x0000ff); \
220    }
221    
222    #define MAKECOLOUR(pc) \
223            ((pc.red >> g_red_shift_r) << g_red_shift_l) \
224                    | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
225                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
226    
227    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
228    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
229    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
230                            x = (x << 16) | (x >> 16); }
231    
232    #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
233    #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
234    #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
235    #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
236    #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
237    #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
238    
239    static uint32
240    translate_colour(uint32 colour)
241    {
242            PixelColour pc;
243            switch (g_server_bpp)
244            {
245                    case 15:
246                            SPLITCOLOUR15(colour, pc);
247                            break;
248                    case 16:
249                            SPLITCOLOUR16(colour, pc);
250                            break;
251                    case 24:
252                            SPLITCOLOUR24(colour, pc);
253                            break;
254            }
255            return MAKECOLOUR(pc);
256    }
257    
258    /* indent is confused by UNROLL8 */
259    /* *INDENT-OFF* */
260    
261    /* repeat and unroll, similar to bitmap.c */
262    /* potentialy any of the following translate */
263    /* functions can use repeat but just doing */
264    /* the most common ones */
265    
266    #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
267    /* 2 byte output repeat */
268    #define REPEAT2(stm) \
269    { \
270            while (out <= end - 8 * 2) \
271                    UNROLL8(stm) \
272            while (out < end) \
273                    { stm } \
274    }
275    /* 3 byte output repeat */
276    #define REPEAT3(stm) \
277    { \
278            while (out <= end - 8 * 3) \
279                    UNROLL8(stm) \
280            while (out < end) \
281                    { stm } \
282    }
283    /* 4 byte output repeat */
284    #define REPEAT4(stm) \
285    { \
286            while (out <= end - 8 * 4) \
287                    UNROLL8(stm) \
288            while (out < end) \
289                    { stm } \
290  }  }
291    /* *INDENT-ON* */
292    
293  static void  static void
294  translate16(uint8 *data, uint16 *out, uint16 *end)  translate8to8(const uint8 * data, uint8 * out, uint8 * end)
295  {  {
296          while (out < end)          while (out < end)
297                  *(out++) = (uint16)colmap[*(data++)];                  *(out++) = (uint8) g_colmap[*(data++)];
298    }
299    
300    static void
301    translate8to16(const uint8 * data, uint8 * out, uint8 * end)
302    {
303            uint16 value;
304    
305            if (g_arch_match)
306            {
307                    /* *INDENT-OFF* */
308                    REPEAT2
309                    (
310                            *((uint16 *) out) = g_colmap[*(data++)];
311                            out += 2;
312                    )
313                    /* *INDENT-ON* */
314            }
315            else if (g_xserver_be)
316            {
317                    while (out < end)
318                    {
319                            value = (uint16) g_colmap[*(data++)];
320                            BOUT16(out, value);
321                    }
322            }
323            else
324            {
325                    while (out < end)
326                    {
327                            value = (uint16) g_colmap[*(data++)];
328                            LOUT16(out, value);
329                    }
330            }
331  }  }
332    
333  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
334  static void  static void
335  translate24(uint8 *data, uint8 *out, uint8 *end)  translate8to24(const uint8 * data, uint8 * out, uint8 * end)
336  {  {
337          uint32 value;          uint32 value;
338    
339          while (out < end)          if (g_xserver_be)
340            {
341                    while (out < end)
342                    {
343                            value = g_colmap[*(data++)];
344                            BOUT24(out, value);
345                    }
346            }
347            else
348          {          {
349                  value = colmap[*(data++)];                  while (out < end)
350                  *(out++) = value;                  {
351                  *(out++) = value >> 8;                          value = g_colmap[*(data++)];
352                  *(out++) = value >> 16;                          LOUT24(out, value);
353                    }
354          }          }
355  }  }
356    
357  static void  static void
358  translate32(uint8 *data, uint32 *out, uint32 *end)  translate8to32(const uint8 * data, uint8 * out, uint8 * end)
359  {  {
360          while (out < end)          uint32 value;
361                  *(out++) = colmap[*(data++)];  
362            if (g_arch_match)
363            {
364                    /* *INDENT-OFF* */
365                    REPEAT4
366                    (
367                            *((uint32 *) out) = g_colmap[*(data++)];
368                            out += 4;
369                    )
370                    /* *INDENT-ON* */
371            }
372            else if (g_xserver_be)
373            {
374                    while (out < end)
375                    {
376                            value = g_colmap[*(data++)];
377                            BOUT32(out, value);
378                    }
379            }
380            else
381            {
382                    while (out < end)
383                    {
384                            value = g_colmap[*(data++)];
385                            LOUT32(out, value);
386                    }
387            }
388  }  }
389    
390  static uint8 *  static void
391  translate_image(int width, int height, uint8 *data)  translate15to16(const uint16 * data, uint8 * out, uint8 * end)
392  {  {
393          int size = width * height * bpp/8;          uint16 pixel;
394          uint8 *out = xmalloc(size);          uint16 value;
395          uint8 *end = out + size;          PixelColour pc;
396    
397          switch (bpp)          if (g_xserver_be)
398          {          {
399                  case 8:                  while (out < end)
400                          translate8(data, out, end);                  {
401                          break;                          pixel = *(data++);
402                            if (g_host_be)
403                            {
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;                          break;
906                    case 8:
907                            switch (g_bpp)
908                            {
909                                    case 8:
910                                            translate8to8(data, out, end);
911                                            break;
912                                    case 16:
913                                            translate8to16(data, out, end);
914                                            break;
915                                    case 24:
916                                            translate8to24(data, out, end);
917                                            break;
918                                    case 32:
919                                            translate8to32(data, out, end);
920                                            break;
921                            }
922                            break;
923            }
924            return out;
925    }
926    
927    BOOL
928    get_key_state(unsigned int state, uint32 keysym)
929    {
930            int modifierpos, key, keysymMask = 0;
931            int offset;
932    
933            KeyCode keycode = XKeysymToKeycode(g_display, keysym);
934    
935            if (keycode == NoSymbol)
936                    return False;
937    
938            for (modifierpos = 0; modifierpos < 8; modifierpos++)
939            {
940                    offset = g_mod_map->max_keypermod * modifierpos;
941    
942                    for (key = 0; key < g_mod_map->max_keypermod; key++)
943                    {
944                            if (g_mod_map->modifiermap[offset + key] == keycode)
945                                    keysymMask |= 1 << modifierpos;
946                    }
947          }          }
948    
949          return colour;          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_create_window(char *title)  ui_init(void)
962  {  {
963          XSetWindowAttributes attribs;          XVisualInfo vi;
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
964          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
         Screen *screen;  
965          uint16 test;          uint16 test;
966          int i;          int i, screen_num, nvisuals;
967            XVisualInfo *vmatches = NULL;
968            XVisualInfo template;
969            Bool TrueColorVisual = False;
970    
971          display = XOpenDisplay(NULL);          g_display = XOpenDisplay(NULL);
972          if (display == NULL)          if (g_display == NULL)
973          {          {
974                  error("Failed to open display\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
975                  return False;                  return False;
976          }          }
977    
978          x_socket = ConnectionNumber(display);          screen_num = DefaultScreen(g_display);
979          screen = DefaultScreenOfDisplay(display);          g_x_socket = ConnectionNumber(g_display);
980          visual = DefaultVisualOfScreen(screen);          g_screen = ScreenOfDisplay(g_display, screen_num);
981          depth = DefaultDepthOfScreen(screen);          g_depth = DefaultDepthOfScreen(g_screen);
982    
983            /* Search for best TrueColor depth */
984            template.class = TrueColor;
985            vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);
986    
987            nvisuals--;
988            while (nvisuals >= 0)
989            {
990                    if ((vmatches + nvisuals)->depth > g_depth)
991                    {
992                            g_depth = (vmatches + nvisuals)->depth;
993                    }
994                    nvisuals--;
995                    TrueColorVisual = True;
996            }
997    
998            test = 1;
999            g_host_be = !(BOOL) (*(uint8 *) (&test));
1000            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1001    
1002            if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))
1003            {
1004                    /* we use a colourmap, so the default visual should do */
1005                    g_visual = DefaultVisualOfScreen(g_screen);
1006                    g_depth = DefaultDepthOfScreen(g_screen);
1007    
1008                    /* Do not allocate colours on a TrueColor visual */
1009                    if (g_visual->class == TrueColor)
1010                    {
1011                            g_owncolmap = False;
1012                    }
1013            }
1014            else
1015            {
1016                    /* need a truecolour visual */
1017                    if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))
1018                    {
1019                            error("The display does not support true colour - high colour support unavailable.\n");
1020                            return False;
1021                    }
1022    
1023                    g_visual = vi.visual;
1024                    g_owncolmap = False;
1025                    calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);
1026                    calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);
1027                    calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);
1028    
1029                    /* if RGB video and everything is little endian */
1030                    if ((vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask) &&
1031                        !g_xserver_be && !g_host_be)
1032                    {
1033                            if (g_depth <= 16 || (g_red_shift_l == 16 && g_green_shift_l == 8 &&
1034                                                  g_blue_shift_l == 0))
1035                            {
1036                                    g_arch_match = True;
1037                            }
1038                    }
1039    
1040                    if (g_arch_match)
1041                    {
1042                            DEBUG(("Architectures match, enabling little endian optimisations.\n"));
1043                    }
1044            }
1045    
1046          pfm = XListPixmapFormats(display, &i);          pfm = XListPixmapFormats(g_display, &i);
1047          if (pfm != NULL)          if (pfm != NULL)
1048          {          {
1049                  /* Use maximum bpp for this depth - this is generally                  /* Use maximum bpp for this depth - this is generally
1050                     desirable, e.g. 24 bits->32 bits. */                     desirable, e.g. 24 bits->32 bits. */
1051                  while (i--)                  while (i--)
1052                  {                  {
1053                          if ((pfm[i].depth == depth)                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
                             && (pfm[i].bits_per_pixel > bpp))  
1054                          {                          {
1055                                  bpp = pfm[i].bits_per_pixel;                                  g_bpp = pfm[i].bits_per_pixel;
1056                          }                          }
1057                  }                  }
1058                  XFree(pfm);                  XFree(pfm);
1059          }          }
1060    
1061          if (bpp < 8)          if (g_bpp < 8)
1062          {          {
1063                  error("Less than 8 bpp not currently supported.\n");                  error("Less than 8 bpp not currently supported.\n");
1064                  XCloseDisplay(display);                  XCloseDisplay(g_display);
1065                  return False;                  return False;
1066          }          }
1067    
1068          if (depth <= 8)          if (!g_owncolmap)
1069                  owncolmap = True;          {
1070          else                  g_xcolmap =
1071                  xcolmap = DefaultColormapOfScreen(screen);                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1072                                            AllocNone);
1073          test = 1;                  if (g_depth <= 8)
1074          host_be = !(BOOL)(*(uint8 *)(&test));                          warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
1075          xserver_be = (ImageByteOrder(display) == MSBFirst);          }
   
         white = WhitePixelOfScreen(screen);  
         attribs.background_pixel = BlackPixelOfScreen(screen);  
         attribs.backing_store = DoesBackingStore(screen);  
1076    
1077          if (attribs.backing_store == NotUseful)          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1078                  ownbackstore = True;          {
1079                    warning("External BackingStore not available, using internal\n");
1080                    g_ownbackstore = True;
1081            }
1082    
1083          if (fullscreen)          /*
1084             * Determine desktop size
1085             */
1086            if (g_fullscreen)
1087          {          {
1088                  attribs.override_redirect = True;                  g_width = WidthOfScreen(g_screen);
1089                  width = WidthOfScreen(screen);                  g_height = HeightOfScreen(g_screen);
                 height = HeightOfScreen(screen);  
1090          }          }
1091          else          else if (g_width < 0)
1092          {          {
1093                  attribs.override_redirect = False;                  /* Percent of screen */
1094                    g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1095                    g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1096          }          }
1097            else if (g_width == 0)
1098            {
1099                    /* Fetch geometry from _NET_WORKAREA */
1100                    uint32 x, y, cx, cy;
1101    
1102                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1103                    {
1104                            g_width = cx;
1105                            g_height = cy;
1106                    }
1107                    else
1108                    {
1109                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1110                            g_width = 800;
1111                            g_height = 600;
1112                    }
1113            }
1114    
1115            /* make sure width is a multiple of 4 */
1116            g_width = (g_width + 3) & ~3;
1117    
1118            g_mod_map = XGetModifierMapping(g_display);
1119    
1120            xkeymap_init();
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;
1130    }
1131    
1132    void
1133    ui_deinit(void)
1134    {
1135            if (g_IM != NULL)
1136                    XCloseIM(g_IM);
1137    
1138            if (g_null_cursor != NULL)
1139                    ui_destroy_cursor(g_null_cursor);
1140    
1141            XFreeModifiermap(g_mod_map);
1142    
1143            if (g_ownbackstore)
1144                    XFreePixmap(g_display, g_backstore);
1145    
1146            XFreeGC(g_display, g_gc);
1147            XCloseDisplay(g_display);
1148            g_display = NULL;
1149    }
1150    
1151    BOOL
1152    ui_create_window(void)
1153    {
1154            uint8 null_pointer_mask[1] = { 0x80 };
1155            uint8 null_pointer_data[24] = { 0x00 };
1156    
1157            XSetWindowAttributes attribs;
1158            XClassHint *classhints;
1159            XSizeHints *sizehints;
1160            int wndwidth, wndheight;
1161            long input_mask, ic_input_mask;
1162            XEvent xevent;
1163    
1164          width = (width + 3) & ~3; /* make width a multiple of 32 bits */          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1165            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1166    
1167          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          /* Handle -x-y portion of geometry string */
1168                              0, 0, width, height, 0, CopyFromParent,          if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1169                              InputOutput, CopyFromParent,                  g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1170                              CWBackingStore | CWBackPixel | CWOverrideRedirect,          if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1171                              &attribs);                  g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1172    
1173          XStoreName(display, wnd, title);          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            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 274  ui_create_window(char *title) Line 1213  ui_create_window(char *title)
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          input_mask = KeyPressMask | KeyReleaseMask          if (g_embed_wnd)
1225                          | ButtonPressMask | ButtonReleaseMask          {
1226                          | EnterWindowMask | LeaveWindowMask;                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1227            }
1228    
1229          if (sendmotion)          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1230                  input_mask |= PointerMotionMask;                  VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1231    
1232          if (ownbackstore)          if (g_sendmotion)
1233                    input_mask |= PointerMotionMask;
1234            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 (g_IM != NULL)
1242            {
1243                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1244                                     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1245    
1246          XSelectInput(display, wnd, input_mask);                  if ((g_IC != NULL)
1247          gc = XCreateGC(display, wnd, 0, NULL);                      && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1248                            input_mask |= ic_input_mask;
1249            }
1250    
1251          if (ownbackstore)          XSelectInput(g_display, g_wnd, input_mask);
1252                  backstore = XCreatePixmap(display, wnd, width, height, depth);          XMapWindow(g_display, g_wnd);
1253    
1254            /* wait for VisibilityNotify */
1255            do
1256            {
1257                    XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1258            }
1259            while (xevent.type != VisibilityNotify);
1260            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1261    
1262            g_focused = False;
1263            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    
         XMapWindow(display, wnd);  
1274          return True;          return True;
1275  }  }
1276    
1277  void  void
1278  ui_destroy_window()  ui_resize_window()
1279  {  {
1280          if (ownbackstore)          XSizeHints *sizehints;
1281                  XFreePixmap(display, backstore);          Pixmap bs;
1282    
1283          XFreeGC(display, gc);          sizehints = XAllocSizeHints();
1284          XDestroyWindow(display, wnd);          if (sizehints)
1285          XCloseDisplay(display);          {
1286          display = NULL;                  sizehints->flags = PMinSize | PMaxSize;
1287  }                  sizehints->min_width = sizehints->max_width = g_width;
1288                    sizehints->min_height = sizehints->max_height = g_height;
1289  static uint8                  XSetWMNormalHints(g_display, g_wnd, sizehints);
1290  xwin_translate_key(unsigned long key)                  XFree(sizehints);
 {  
         DEBUG(("KEY(code=0x%lx)\n", key));  
   
         if ((key > 8) && (key <= 0x60))  
                 return (key - 8);  
   
         switch (key)  
         {  
                 case 0x61:      /* home */  
                         return 0x47 | 0x80;  
                 case 0x62:      /* up arrow */  
                         return 0x48 | 0x80;  
                 case 0x63:      /* page up */  
                         return 0x49 | 0x80;  
                 case 0x64:      /* left arrow */  
                         return 0x4b | 0x80;  
                 case 0x66:      /* right arrow */  
                         return 0x4d | 0x80;  
                 case 0x67:      /* end */  
                         return 0x4f | 0x80;  
                 case 0x68:      /* down arrow */  
                         return 0x50 | 0x80;  
                 case 0x69:      /* page down */  
                         return 0x51 | 0x80;  
                 case 0x6a:      /* insert */  
                         return 0x52 | 0x80;  
                 case 0x6b:      /* delete */  
                         return 0x53 | 0x80;  
                 case 0x6c:      /* keypad enter */  
                         return 0x1c | 0x80;  
                 case 0x6d:      /* right ctrl */  
                         return 0x1d | 0x80;  
                 case 0x6f:      /* ctrl - print screen */  
                         return 0x37 | 0x80;  
                 case 0x70:      /* keypad '/' */  
                         return 0x35 | 0x80;  
                 case 0x71:      /* right alt */  
                         return 0x38 | 0x80;  
                 case 0x72:      /* ctrl break */  
                         return 0x46 | 0x80;  
                 case 0x73:      /* left window key */  
                         return 0xff;    /* real scancode is 5b */  
                 case 0x74:      /* right window key */  
                         return 0xff;    /* real scancode is 5c */  
                 case 0x75:      /* menu key */  
                         return 0x5d | 0x80;  
         }  
   
         return 0;  
 }  
   
 static uint16  
 xwin_translate_mouse(unsigned long button)  
 {  
         switch (button)  
         {  
                 case Button1:   /* left */  
                         return MOUSE_FLAG_BUTTON1;  
                 case Button2:   /* middle */  
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3:   /* right */  
                         return MOUSE_FLAG_BUTTON2;  
1291          }          }
1292    
1293          return 0;          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  static void  void
1311  xwin_process_events()  ui_destroy_window(void)
1312  {  {
1313          XEvent event;          if (g_IC != NULL)
1314          uint8 scancode;                  XDestroyIC(g_IC);
1315          uint16 button;  
1316          uint32 ev_time;          XDestroyWindow(g_display, g_wnd);
1317    }
1318    
1319    void
1320    xwin_toggle_fullscreen(void)
1321    {
1322            Pixmap contents = 0;
1323    
1324            if (!g_ownbackstore)
1325            {
1326                    /* need to save contents of window */
1327                    contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1328                    XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1329            }
1330    
1331            ui_destroy_window();
1332            g_fullscreen = !g_fullscreen;
1333            ui_create_window();
1334    
1335          if (display == NULL)          XDefineCursor(g_display, g_wnd, g_current_cursor);
1336    
1337            if (!g_ownbackstore)
1338            {
1339                    XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1340                    XFreePixmap(g_display, contents);
1341            }
1342    }
1343    
1344    static void
1345    handle_button_event(XEvent xevent, BOOL down)
1346    {
1347            uint16 button, flags = 0;
1348            g_last_gesturetime = xevent.xbutton.time;
1349            button = xkeymap_translate_button(xevent.xbutton.button);
1350            if (button == 0)
1351                  return;                  return;
1352    
1353          while (XCheckWindowEvent(display, wnd, ~0, &event))          if (down)
1354                    flags = MOUSE_FLAG_DOWN;
1355    
1356            /* Stop moving window when button is released, regardless of cursor position */
1357            if (g_moving_wnd && (xevent.type == ButtonRelease))
1358                    g_moving_wnd = False;
1359    
1360            /* If win_button_size is nonzero, enable single app mode */
1361            if (xevent.xbutton.y < g_win_button_size)
1362          {          {
1363                  ev_time = time(NULL);                  /*  Check from right to left: */
1364                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1365                    {
1366                            /* The close button, continue */
1367                            ;
1368                    }
1369                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1370                    {
1371                            /* The maximize/restore button. Do not send to
1372                               server.  It might be a good idea to change the
1373                               cursor or give some other visible indication
1374                               that rdesktop inhibited this click */
1375                            if (xevent.type == ButtonPress)
1376                                    return;
1377                    }
1378                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1379                    {
1380                            /* The minimize button. Iconify window. */
1381                            if (xevent.type == ButtonRelease)
1382                            {
1383                                    /* Release the mouse button outside the minimize button, to prevent the
1384                                       actual minimazation to happen */
1385                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1386                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1387                                    return;
1388                            }
1389                    }
1390                    else if (xevent.xbutton.x <= g_win_button_size)
1391                    {
1392                            /* The system menu. Ignore. */
1393                            if (xevent.type == ButtonPress)
1394                                    return;
1395                    }
1396                    else
1397                    {
1398                            /* The title bar. */
1399                            if (xevent.type == ButtonPress)
1400                            {
1401                                    if (!g_fullscreen && g_hide_decorations)
1402                                    {
1403                                            g_moving_wnd = True;
1404                                            g_move_x_offset = xevent.xbutton.x;
1405                                            g_move_y_offset = xevent.xbutton.y;
1406                                    }
1407                                    return;
1408                            }
1409                    }
1410            }
1411    
1412            rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1413                           flags | button, xevent.xbutton.x, xevent.xbutton.y);
1414    }
1415    
1416    /* Process events in Xlib queue
1417       Returns 0 after user quit, 1 otherwise */
1418    static int
1419    xwin_process_events(void)
1420    {
1421            XEvent xevent;
1422            KeySym keysym;
1423            uint32 ev_time;
1424            char str[256];
1425            Status status;
1426            int events = 0;
1427    
1428            while ((XPending(g_display) > 0) && events++ < 20)
1429            {
1430                    XNextEvent(g_display, &xevent);
1431    
1432                    if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1433                    {
1434                            DEBUG_KBD(("Filtering event\n"));
1435                            continue;
1436                    }
1437    
1438                  switch (event.type)                  switch (xevent.type)
1439                  {                  {
1440                            case VisibilityNotify:
1441                                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1442                                    break;
1443                            case ClientMessage:
1444                                    /* the window manager told us to quit */
1445                                    if ((xevent.xclient.message_type == g_protocol_atom)
1446                                        && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1447                                            /* Quit */
1448                                            return 0;
1449                                    break;
1450    
1451                          case KeyPress:                          case KeyPress:
1452                                  scancode = xwin_translate_key(event.xkey.keycode);                                  g_last_gesturetime = xevent.xkey.time;
1453                                  if (scancode == 0)                                  if (g_IC != NULL)
1454                                            /* Multi_key compatible version */
1455                                    {
1456                                            XmbLookupString(g_IC,
1457                                                            &xevent.xkey, str, sizeof(str), &keysym,
1458                                                            &status);
1459                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1460                                            {
1461                                                    error("XmbLookupString failed with status 0x%x\n",
1462                                                          status);
1463                                                    break;
1464                                            }
1465                                    }
1466                                    else
1467                                    {
1468                                            /* Plain old XLookupString */
1469                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1470                                            XLookupString((XKeyEvent *) & xevent,
1471                                                          str, sizeof(str), &keysym, NULL);
1472                                    }
1473    
1474                                    DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1475                                               get_ksname(keysym)));
1476    
1477                                    ev_time = time(NULL);
1478                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1479                                          break;                                          break;
1480    
1481                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1482                                                 scancode, 0);                                                    ev_time, True, 0);
1483                                  break;                                  break;
1484    
1485                          case KeyRelease:                          case KeyRelease:
1486                                  scancode = xwin_translate_key(event.xkey.keycode);                                  g_last_gesturetime = xevent.xkey.time;
1487                                  if (scancode == 0)                                  XLookupString((XKeyEvent *) & xevent, str,
1488                                                  sizeof(str), &keysym, NULL);
1489    
1490                                    DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1491                                               get_ksname(keysym)));
1492    
1493                                    ev_time = time(NULL);
1494                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1495                                          break;                                          break;
1496    
1497                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1498                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                    ev_time, False, 0);
                                                scancode, 0);  
1499                                  break;                                  break;
1500    
1501                          case ButtonPress:                          case ButtonPress:
1502                                  button = xwin_translate_mouse(event.xbutton.button);                                  handle_button_event(xevent, True);
                                 if (button == 0)  
                                         break;  
   
                                 rdp_send_input(ev_time, RDP_INPUT_MOUSE,  
                                                button | MOUSE_FLAG_DOWN,  
                                                event.xbutton.x,  
                                                event.xbutton.y);  
1503                                  break;                                  break;
1504    
1505                          case ButtonRelease:                          case ButtonRelease:
1506                                  button = xwin_translate_mouse(event.xbutton.button);                                  handle_button_event(xevent, False);
1507                                  if (button == 0)                                  break;
1508    
1509                            case MotionNotify:
1510                                    if (g_moving_wnd)
1511                                    {
1512                                            XMoveWindow(g_display, g_wnd,
1513                                                        xevent.xmotion.x_root - g_move_x_offset,
1514                                                        xevent.xmotion.y_root - g_move_y_offset);
1515                                          break;                                          break;
1516                                    }
1517    
1518                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (g_fullscreen && !g_focused)
1519                                                 button,                                          XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1520                                                 event.xbutton.x,                                                         CurrentTime);
1521                                                 event.xbutton.y);                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1522                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1523                                  break;                                  break;
1524    
1525                          case MotionNotify:                          case FocusIn:
1526                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (xevent.xfocus.mode == NotifyGrab)
1527                                                 MOUSE_FLAG_MOVE,                                          break;
1528                                                 event.xmotion.x,                                  g_focused = True;
1529                                                 event.xmotion.y);                                  reset_modifier_keys();
1530                                    if (g_grab_keyboard && g_mouse_in_wnd)
1531                                            XGrabKeyboard(g_display, g_wnd, True,
1532                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1533                                    break;
1534    
1535                            case FocusOut:
1536                                    if (xevent.xfocus.mode == NotifyUngrab)
1537                                            break;
1538                                    g_focused = False;
1539                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1540                                            XUngrabKeyboard(g_display, CurrentTime);
1541                                  break;                                  break;
1542    
1543                          case EnterNotify:                          case EnterNotify:
1544                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,                                  /* we only register for this event when in fullscreen mode */
1545                                                GrabModeAsync, CurrentTime);                                  /* or grab_keyboard */
1546                                    g_mouse_in_wnd = True;
1547                                    if (g_fullscreen)
1548                                    {
1549                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1550                                                           CurrentTime);
1551                                            break;
1552                                    }
1553                                    if (g_focused)
1554                                            XGrabKeyboard(g_display, g_wnd, True,
1555                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1556                                  break;                                  break;
1557    
1558                          case LeaveNotify:                          case LeaveNotify:
1559                                  XUngrabKeyboard(display, CurrentTime);                                  /* we only register for this event when grab_keyboard */
1560                                    g_mouse_in_wnd = False;
1561                                    XUngrabKeyboard(g_display, CurrentTime);
1562                                  break;                                  break;
1563    
1564                          case Expose:                          case Expose:
1565                                  XCopyArea(display, backstore, wnd, gc,                                  XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1566                                            event.xexpose.x, event.xexpose.y,                                            xevent.xexpose.x, xevent.xexpose.y,
1567                                            event.xexpose.width, event.xexpose.height,                                            xevent.xexpose.width,
1568                                            event.xexpose.x, event.xexpose.y);                                            xevent.xexpose.height,
1569                                              xevent.xexpose.x, xevent.xexpose.y);
1570                                    break;
1571    
1572                            case MappingNotify:
1573                                    /* Refresh keyboard mapping if it has changed. This is important for
1574                                       Xvnc, since it allocates keycodes dynamically */
1575                                    if (xevent.xmapping.request == MappingKeyboard
1576                                        || xevent.xmapping.request == MappingModifier)
1577                                            XRefreshKeyboardMapping(&xevent.xmapping);
1578    
1579                                    if (xevent.xmapping.request == MappingModifier)
1580                                    {
1581                                            XFreeModifiermap(g_mod_map);
1582                                            g_mod_map = XGetModifierMapping(g_display);
1583                                    }
1584                                    break;
1585    
1586                                    /* clipboard stuff */
1587                            case SelectionNotify:
1588                                    xclip_handle_SelectionNotify(&xevent.xselection);
1589                                    break;
1590                            case SelectionRequest:
1591                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1592                                    break;
1593                            case SelectionClear:
1594                                    xclip_handle_SelectionClear();
1595                                    break;
1596                            case PropertyNotify:
1597                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1598                                    break;
1599                            case MapNotify:
1600                                    rdp_send_client_window_status(1);
1601                                    break;
1602                            case UnmapNotify:
1603                                    rdp_send_client_window_status(0);
1604                                  break;                                  break;
1605                  }                  }
1606          }          }
1607            /* Keep going */
1608            return 1;
1609  }  }
1610    
1611  void  /* Returns 0 after user quit, 1 otherwise */
1612    int
1613  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1614  {  {
1615          int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;          int n;
1616          fd_set rfds;          fd_set rfds, wfds;
1617            struct timeval tv;
1618          XFlush(display);          BOOL s_timeout = False;
   
         FD_ZERO(&rfds);  
1619    
1620          while (True)          while (True)
1621          {          {
1622                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1623                    /* Process any events already waiting */
1624                    if (!xwin_process_events())
1625                            /* User quit */
1626                            return 0;
1627    
1628                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
1629                    FD_ZERO(&wfds);
1630                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
1631                  FD_SET(x_socket, &rfds);                  FD_SET(g_x_socket, &rfds);
1632    
1633    #ifdef WITH_RDPSND
1634                    /* FIXME: there should be an API for registering fds */
1635                    if (g_dsp_busy)
1636                    {
1637                            FD_SET(g_dsp_fd, &wfds);
1638                            n = (g_dsp_fd > n) ? g_dsp_fd : n;
1639                    }
1640    #endif
1641                    /* default timeout */
1642                    tv.tv_sec = 60;
1643                    tv.tv_usec = 0;
1644    
1645                    /* add redirection handles */
1646                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1647    
1648                    n++;
1649    
1650                  switch (select(n, &rfds, NULL, NULL, NULL))                  switch (select(n, &rfds, &wfds, NULL, &tv))
1651                  {                  {
1652                          case -1:                          case -1:
1653                                  error("select: %s\n", strerror(errno));                                  error("select: %s\n", strerror(errno));
1654    
1655                          case 0:                          case 0:
1656                                    /* Abort serial read calls */
1657                                    if (s_timeout)
1658                                            rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1659                                  continue;                                  continue;
1660                  }                  }
1661    
1662                  if (FD_ISSET(x_socket, &rfds))                  rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
                         xwin_process_events();  
1663    
1664                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1665                          return;                          return 1;
1666    
1667    #ifdef WITH_RDPSND
1668                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1669                            wave_out_play();
1670    #endif
1671          }          }
1672  }  }
1673    
1674  void  void
1675  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
1676  {  {
1677          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1678  }  }
1679    
1680  HBITMAP  HBITMAP
1681  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1682  {  {
1683          XImage *image;          XImage *image;
1684          Pixmap bitmap;          Pixmap bitmap;
1685          uint8 *tdata;          uint8 *tdata;
1686            int bitmap_pad;
1687    
1688          tdata = (owncolmap ? data : translate_image(width, height, data));          if (g_server_bpp == 8)
1689          bitmap = XCreatePixmap(display, wnd, width, height, depth);          {
1690          image = XCreateImage(display, visual, depth, ZPixmap,                  bitmap_pad = 8;
1691                               0, tdata, width, height, 8, 0);          }
1692            else
1693            {
1694                    bitmap_pad = g_bpp;
1695    
1696          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);                  if (g_bpp == 24)
1697                            bitmap_pad = 32;
1698            }
1699    
1700            tdata = (g_owncolmap ? data : translate_image(width, height, data));
1701            bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1702            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1703                                 (char *) tdata, width, height, bitmap_pad, 0);
1704    
1705            XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
1706    
1707          XFree(image);          XFree(image);
1708          if (!owncolmap)          if (tdata != data)
1709                  xfree(tdata);                  xfree(tdata);
1710          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1711  }  }
1712    
1713  void  void
1714  ui_paint_bitmap(int x, int y, int cx, int cy,  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
                 int width, int height, uint8 *data)  
1715  {  {
1716          XImage *image;          XImage *image;
1717          uint8 *tdata;          uint8 *tdata;
1718            int bitmap_pad;
1719    
1720            if (g_server_bpp == 8)
1721            {
1722                    bitmap_pad = 8;
1723            }
1724            else
1725            {
1726                    bitmap_pad = g_bpp;
1727    
1728                    if (g_bpp == 24)
1729                            bitmap_pad = 32;
1730            }
1731    
1732          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1733          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1734                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, bitmap_pad, 0);
1735    
1736          if (ownbackstore)          if (g_ownbackstore)
1737          {          {
1738                  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);
1739                  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);
1740          }          }
1741          else          else
1742          {          {
1743                  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);
1744          }          }
1745    
1746          XFree(image);          XFree(image);
1747          if (!owncolmap)          if (tdata != data)
1748                  xfree(tdata);                  xfree(tdata);
1749  }  }
1750    
1751  void  void
1752  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1753  {  {
1754          XFreePixmap(display, (Pixmap)bmp);          XFreePixmap(g_display, (Pixmap) bmp);
1755  }  }
1756    
1757  HGLYPH  HGLYPH
1758  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1759  {  {
1760          XImage *image;          XImage *image;
1761          Pixmap bitmap;          Pixmap bitmap;
1762          int scanline;          int scanline;
         GC gc;  
1763    
1764          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1765    
1766          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1767          gc = XCreateGC(display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
1768                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1769    
1770          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1771                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1772          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1773          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1774          XInitImage(image);          XInitImage(image);
1775    
1776          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);
1777    
1778          XFree(image);          XFree(image);
1779          XFreeGC(display, gc);          return (HGLYPH) bitmap;
         return (HGLYPH)bitmap;  
1780  }  }
1781    
1782  void  void
1783  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1784  {  {
1785          XFreePixmap(display, (Pixmap)glyph);          XFreePixmap(g_display, (Pixmap) glyph);
1786  }  }
1787    
1788  HCURSOR  HCURSOR
1789  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1790                   int height, uint8 *andmask, uint8 *xormask)                   uint8 * andmask, uint8 * xormask)
1791  {  {
1792          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
1793          XColor bg, fg;          XColor bg, fg;
# Line 604  ui_create_cursor(unsigned int x, unsigne Line 1801  ui_create_cursor(unsigned int x, unsigne
1801          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1802          offset = scanline * height;          offset = scanline * height;
1803    
1804          cursor = xmalloc(offset);          cursor = (uint8 *) xmalloc(offset);
1805          memset(cursor, 0, offset);          memset(cursor, 0, offset);
1806    
1807          mask = xmalloc(offset);          mask = (uint8 *) xmalloc(offset);
1808          memset(mask, 0, offset);          memset(mask, 0, offset);
1809    
1810          /* approximate AND and XOR masks with a monochrome X pointer */          /* approximate AND and XOR masks with a monochrome X pointer */
# Line 647  ui_create_cursor(unsigned int x, unsigne Line 1844  ui_create_cursor(unsigned int x, unsigne
1844    
1845          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
1846          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
1847            
1848          xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,          xcursor =
1849                                  (Pixmap)maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1850                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1851    
1852          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
1853          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
1854          xfree(mask);          xfree(mask);
1855          xfree(cursor);          xfree(cursor);
1856          return (HCURSOR)xcursor;          return (HCURSOR) xcursor;
1857  }  }
1858    
1859  void  void
1860  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
1861  {  {
1862          XDefineCursor(display, wnd, (Cursor)cursor);          g_current_cursor = (Cursor) cursor;
1863            XDefineCursor(g_display, g_wnd, g_current_cursor);
1864  }  }
1865    
1866  void  void
1867  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
1868  {  {
1869          XFreeCursor(display, (Cursor)cursor);          XFreeCursor(g_display, (Cursor) cursor);
1870    }
1871    
1872    void
1873    ui_set_null_cursor(void)
1874    {
1875            ui_set_cursor(g_null_cursor);
1876  }  }
1877    
1878  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 676  ui_destroy_cursor(HCURSOR cursor) Line 1881  ui_destroy_cursor(HCURSOR cursor)
1881                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1882                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
1883    
1884    
1885  HCOLOURMAP  HCOLOURMAP
1886  ui_create_colourmap(COLOURMAP *colours)  ui_create_colourmap(COLOURMAP * colours)
1887  {  {
1888          COLOURENTRY *entry;          COLOURENTRY *entry;
1889          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1890            if (!g_owncolmap)
         if (owncolmap)  
1891          {          {
1892                  XColor *xcolours, *xentry;                  uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1893                  Colormap map;                  XColor xentry;
1894                    XColor xc_cache[256];
1895                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  uint32 colour;
1896                    int colLookup = 256;
1897                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1898                  {                  {
1899                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1900                          xentry = &xcolours[i];                          MAKE_XCOLOR(&xentry, entry);
                         xentry->pixel = i;  
                         MAKE_XCOLOR(xentry, entry);  
                 }  
1901    
1902                  map = XCreateColormap(display, wnd, visual, AllocAll);                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1903                  XStoreColors(display, map, xcolours, ncolours);                          {
1904                                    /* Allocation failed, find closest match. */
1905                                    int j = 256;
1906                                    int nMinDist = 3 * 256 * 256;
1907                                    long nDist = nMinDist;
1908    
1909                  xfree(xcolours);                                  /* only get the colors once */
1910                  return (HCOLOURMAP)map;                                  while (colLookup--)
1911                                    {
1912                                            xc_cache[colLookup].pixel = colLookup;
1913                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1914                                                    xc_cache[colLookup].blue = 0;
1915                                            xc_cache[colLookup].flags = 0;
1916                                            XQueryColor(g_display,
1917                                                        DefaultColormap(g_display,
1918                                                                        DefaultScreen(g_display)),
1919                                                        &xc_cache[colLookup]);
1920                                    }
1921                                    colLookup = 0;
1922    
1923                                    /* approximate the pixel */
1924                                    while (j--)
1925                                    {
1926                                            if (xc_cache[j].flags)
1927                                            {
1928                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1929                                                             (long) (xentry.red >> 8)) *
1930                                                            ((long) (xc_cache[j].red >> 8) -
1931                                                             (long) (xentry.red >> 8)) +
1932                                                            ((long) (xc_cache[j].green >> 8) -
1933                                                             (long) (xentry.green >> 8)) *
1934                                                            ((long) (xc_cache[j].green >> 8) -
1935                                                             (long) (xentry.green >> 8)) +
1936                                                            ((long) (xc_cache[j].blue >> 8) -
1937                                                             (long) (xentry.blue >> 8)) *
1938                                                            ((long) (xc_cache[j].blue >> 8) -
1939                                                             (long) (xentry.blue >> 8));
1940                                            }
1941                                            if (nDist < nMinDist)
1942                                            {
1943                                                    nMinDist = nDist;
1944                                                    xentry.pixel = j;
1945                                            }
1946                                    }
1947                            }
1948                            colour = xentry.pixel;
1949    
1950                            /* update our cache */
1951                            if (xentry.pixel < 256)
1952                            {
1953                                    xc_cache[xentry.pixel].red = xentry.red;
1954                                    xc_cache[xentry.pixel].green = xentry.green;
1955                                    xc_cache[xentry.pixel].blue = xentry.blue;
1956    
1957                            }
1958    
1959                            map[i] = colour;
1960                    }
1961                    return map;
1962          }          }
1963          else          else
1964          {          {
1965                  uint32 *map = xmalloc(sizeof(*colmap) * ncolours);                  XColor *xcolours, *xentry;
1966                  XColor xentry;                  Colormap map;
                 uint32 colour;  
1967    
1968                    xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1969                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1970                  {                  {
1971                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1972                          MAKE_XCOLOR(&xentry, entry);                          xentry = &xcolours[i];
1973                            xentry->pixel = i;
1974                          if (XAllocColor(display, xcolmap, &xentry) != 0)                          MAKE_XCOLOR(xentry, entry);
                                 colour = xentry.pixel;  
                         else  
                                 colour = white;  
   
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
1975                  }                  }
1976    
1977                  return map;                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1978                    XStoreColors(g_display, map, xcolours, ncolours);
1979    
1980                    xfree(xcolours);
1981                    return (HCOLOURMAP) map;
1982          }          }
1983  }  }
1984    
1985  void  void
1986  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1987  {  {
1988          if (owncolmap)          if (!g_owncolmap)
                 XFreeColormap(display, (Colormap)map);  
         else  
1989                  xfree(map);                  xfree(map);
1990            else
1991                    XFreeColormap(g_display, (Colormap) map);
1992  }  }
1993    
1994  void  void
1995  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1996  {  {
1997          if (owncolmap)          if (!g_owncolmap)
1998                  XSetWindowColormap(display, wnd, (Colormap)map);          {
1999                    if (g_colmap)
2000                            xfree(g_colmap);
2001    
2002                    g_colmap = (uint32 *) map;
2003            }
2004          else          else
2005                  colmap = map;                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2006  }  }
2007    
2008  void  void
# Line 753  ui_set_clip(int x, int y, int cx, int cy Line 2014  ui_set_clip(int x, int y, int cx, int cy
2014          rect.y = y;          rect.y = y;
2015          rect.width = cx;          rect.width = cx;
2016          rect.height = cy;          rect.height = cy;
2017          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
2018  }  }
2019    
2020  void  void
2021  ui_reset_clip()  ui_reset_clip(void)
2022  {  {
2023          XRectangle rect;          XRectangle rect;
2024    
2025          rect.x = 0;          rect.x = 0;
2026          rect.y = 0;          rect.y = 0;
2027          rect.width = width;          rect.width = g_width;
2028          rect.height = height;          rect.height = g_height;
2029          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
2030  }  }
2031    
2032  void  void
2033  ui_bell()  ui_bell(void)
2034  {  {
2035          XBell(display, 0);          XBell(g_display, 0);
2036  }  }
2037    
2038  void  void
# Line 783  ui_destblt(uint8 opcode, Line 2044  ui_destblt(uint8 opcode,
2044          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2045  }  }
2046    
2047    static uint8 hatch_patterns[] = {
2048            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
2049            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
2050            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
2051            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
2052            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
2053            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
2054    };
2055    
2056  void  void
2057  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
2058            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2059            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2060  {  {
2061          Pixmap fill;          Pixmap fill;
2062            uint8 i, ipattern[8];
2063    
2064          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2065    
# Line 796  ui_patblt(uint8 opcode, Line 2067  ui_patblt(uint8 opcode,
2067          {          {
2068                  case 0: /* Solid */                  case 0: /* Solid */
2069                          SET_FOREGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
2070                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2071                          break;                          break;
2072    
2073                  case 3: /* Pattern */                  case 2: /* Hatch */
2074                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);                          fill = (Pixmap) ui_create_glyph(8, 8,
2075                                                            hatch_patterns + brush->pattern[0] * 8);
2076                            SET_FOREGROUND(fgcolour);
2077                            SET_BACKGROUND(bgcolour);
2078                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2079                            XSetStipple(g_display, g_gc, fill);
2080                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2081                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2082                            XSetFillStyle(g_display, g_gc, FillSolid);
2083                            XSetTSOrigin(g_display, g_gc, 0, 0);
2084                            ui_destroy_glyph((HGLYPH) fill);
2085                            break;
2086    
2087                    case 3: /* Pattern */
2088                            for (i = 0; i != 8; i++)
2089                                    ipattern[7 - i] = brush->pattern[i];
2090                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2091                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
2092                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
2093                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2094                          XSetStipple(display, gc, fill);                          XSetStipple(g_display, g_gc, fill);
2095                          XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2096                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2097                          FILL_RECTANGLE(x, y, cx, cy);                          XSetFillStyle(g_display, g_gc, FillSolid);
2098                            XSetTSOrigin(g_display, g_gc, 0, 0);
2099                          XSetFillStyle(display, gc, FillSolid);                          ui_destroy_glyph((HGLYPH) fill);
                         ui_destroy_glyph((HGLYPH)fill);  
2100                          break;                          break;
2101    
2102                  default:                  default:
# Line 819  ui_patblt(uint8 opcode, Line 2104  ui_patblt(uint8 opcode,
2104          }          }
2105    
2106          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2107    
2108            if (g_ownbackstore)
2109                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2110  }  }
2111    
2112  void  void
# Line 827  ui_screenblt(uint8 opcode, Line 2115  ui_screenblt(uint8 opcode,
2115               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
2116  {  {
2117          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2118          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          if (g_ownbackstore)
2119          if (ownbackstore)          {
2120                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,                  if (g_Unobscured)
2121                            cx, cy, x, y);                  {
2122                            XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2123                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2124                                      y);
2125                    }
2126                    else
2127                    {
2128                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2129                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2130                                      y);
2131                    }
2132            }
2133            else
2134            {
2135                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2136            }
2137          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2138  }  }
2139    
# Line 840  ui_memblt(uint8 opcode, Line 2143  ui_memblt(uint8 opcode,
2143            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
2144  {  {
2145          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2146          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);
2147          if (ownbackstore)          if (g_ownbackstore)
2148                  XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,                  XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
2149          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2150  }  }
2151    
# Line 851  void Line 2153  void
2153  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
2154            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2155            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
2156            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2157  {  {
2158          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
2159             comes up with a more efficient way of doing it I am using cases. */             comes up with a more efficient way of doing it I am using cases. */
# Line 860  ui_triblt(uint8 opcode, Line 2162  ui_triblt(uint8 opcode,
2162          {          {
2163                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
2164                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
2165                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2166                          break;                          break;
2167    
2168                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
2169                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2170                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
2171                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2172                          break;                          break;
2173    
2174                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
2175                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2176                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
2177                          break;                          break;
2178    
2179                  default:                  default:
# Line 887  ui_triblt(uint8 opcode, Line 2185  ui_triblt(uint8 opcode,
2185  void  void
2186  ui_line(uint8 opcode,  ui_line(uint8 opcode,
2187          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
2188          /* pen */ PEN *pen)          /* pen */ PEN * pen)
2189  {  {
2190          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2191          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2192          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2193          if (ownbackstore)          if (g_ownbackstore)
2194                  XDrawLine(display, backstore, gc, startx, starty, endx, endy);                  XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2195          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2196  }  }
2197    
# Line 907  ui_rect( Line 2205  ui_rect(
2205  }  }
2206    
2207  void  void
2208    ui_polygon(uint8 opcode,
2209               /* mode */ uint8 fillmode,
2210               /* dest */ POINT * point, int npoints,
2211               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2212    {
2213            uint8 style, i, ipattern[8];
2214            Pixmap fill;
2215    
2216            SET_FUNCTION(opcode);
2217    
2218            switch (fillmode)
2219            {
2220                    case ALTERNATE:
2221                            XSetFillRule(g_display, g_gc, EvenOddRule);
2222                            break;
2223                    case WINDING:
2224                            XSetFillRule(g_display, g_gc, WindingRule);
2225                            break;
2226                    default:
2227                            unimpl("fill mode %d\n", fillmode);
2228            }
2229    
2230            if (brush)
2231                    style = brush->style;
2232            else
2233                    style = 0;
2234    
2235            switch (style)
2236            {
2237                    case 0: /* Solid */
2238                            SET_FOREGROUND(fgcolour);
2239                            FILL_POLYGON((XPoint *) point, npoints);
2240                            break;
2241    
2242                    case 2: /* Hatch */
2243                            fill = (Pixmap) ui_create_glyph(8, 8,
2244                                                            hatch_patterns + brush->pattern[0] * 8);
2245                            SET_FOREGROUND(fgcolour);
2246                            SET_BACKGROUND(bgcolour);
2247                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2248                            XSetStipple(g_display, g_gc, fill);
2249                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2250                            FILL_POLYGON((XPoint *) point, npoints);
2251                            XSetFillStyle(g_display, g_gc, FillSolid);
2252                            XSetTSOrigin(g_display, g_gc, 0, 0);
2253                            ui_destroy_glyph((HGLYPH) fill);
2254                            break;
2255    
2256                    case 3: /* Pattern */
2257                            for (i = 0; i != 8; i++)
2258                                    ipattern[7 - i] = brush->pattern[i];
2259                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2260                            SET_FOREGROUND(bgcolour);
2261                            SET_BACKGROUND(fgcolour);
2262                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2263                            XSetStipple(g_display, g_gc, fill);
2264                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2265                            FILL_POLYGON((XPoint *) point, npoints);
2266                            XSetFillStyle(g_display, g_gc, FillSolid);
2267                            XSetTSOrigin(g_display, g_gc, 0, 0);
2268                            ui_destroy_glyph((HGLYPH) fill);
2269                            break;
2270    
2271                    default:
2272                            unimpl("brush %d\n", brush->style);
2273            }
2274    
2275            RESET_FUNCTION(opcode);
2276    }
2277    
2278    void
2279    ui_polyline(uint8 opcode,
2280                /* dest */ POINT * points, int npoints,
2281                /* pen */ PEN * pen)
2282    {
2283            /* TODO: set join style */
2284            SET_FUNCTION(opcode);
2285            SET_FOREGROUND(pen->colour);
2286            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2287            if (g_ownbackstore)
2288                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2289                               CoordModePrevious);
2290            RESET_FUNCTION(opcode);
2291    }
2292    
2293    void
2294    ui_ellipse(uint8 opcode,
2295               /* mode */ uint8 fillmode,
2296               /* dest */ int x, int y, int cx, int cy,
2297               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2298    {
2299            uint8 style, i, ipattern[8];
2300            Pixmap fill;
2301    
2302            SET_FUNCTION(opcode);
2303    
2304            if (brush)
2305                    style = brush->style;
2306            else
2307                    style = 0;
2308    
2309            switch (style)
2310            {
2311                    case 0: /* Solid */
2312                            SET_FOREGROUND(fgcolour);
2313                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2314                            break;
2315    
2316                    case 2: /* Hatch */
2317                            fill = (Pixmap) ui_create_glyph(8, 8,
2318                                                            hatch_patterns + brush->pattern[0] * 8);
2319                            SET_FOREGROUND(fgcolour);
2320                            SET_BACKGROUND(bgcolour);
2321                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2322                            XSetStipple(g_display, g_gc, fill);
2323                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2324                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2325                            XSetFillStyle(g_display, g_gc, FillSolid);
2326                            XSetTSOrigin(g_display, g_gc, 0, 0);
2327                            ui_destroy_glyph((HGLYPH) fill);
2328                            break;
2329    
2330                    case 3: /* Pattern */
2331                            for (i = 0; i != 8; i++)
2332                                    ipattern[7 - i] = brush->pattern[i];
2333                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2334                            SET_FOREGROUND(bgcolour);
2335                            SET_BACKGROUND(fgcolour);
2336                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2337                            XSetStipple(g_display, g_gc, fill);
2338                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2339                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2340                            XSetFillStyle(g_display, g_gc, FillSolid);
2341                            XSetTSOrigin(g_display, g_gc, 0, 0);
2342                            ui_destroy_glyph((HGLYPH) fill);
2343                            break;
2344    
2345                    default:
2346                            unimpl("brush %d\n", brush->style);
2347            }
2348    
2349            RESET_FUNCTION(opcode);
2350    }
2351    
2352    /* warning, this function only draws on wnd or backstore, not both */
2353    void
2354  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
2355                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
2356                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
2357                int fgcolour)                int bgcolour, int fgcolour)
2358  {  {
2359          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
2360          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
2361    
2362          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(g_display, g_gc,
2363                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2364          XSetStipple(display, gc, (Pixmap)glyph);          XSetStipple(g_display, g_gc, (Pixmap) glyph);
2365          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(g_display, g_gc, x, y);
2366    
2367          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2368    
2369          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(g_display, g_gc, FillSolid);
2370    }
2371    
2372    #define DO_GLYPH(ttext,idx) \
2373    {\
2374      glyph = cache_get_font (font, ttext[idx]);\
2375      if (!(flags & TEXT2_IMPLICIT_X))\
2376      {\
2377        xyoffset = ttext[++idx];\
2378        if ((xyoffset & 0x80))\
2379        {\
2380          if (flags & TEXT2_VERTICAL)\
2381            y += ttext[idx+1] | (ttext[idx+2] << 8);\
2382          else\
2383            x += ttext[idx+1] | (ttext[idx+2] << 8);\
2384          idx += 2;\
2385        }\
2386        else\
2387        {\
2388          if (flags & TEXT2_VERTICAL)\
2389            y += xyoffset;\
2390          else\
2391            x += xyoffset;\
2392        }\
2393      }\
2394      if (glyph != NULL)\
2395      {\
2396        x1 = x + glyph->offset;\
2397        y1 = y + glyph->baseline;\
2398        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2399        XSetTSOrigin(g_display, g_gc, x1, y1);\
2400        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2401        if (flags & TEXT2_IMPLICIT_X)\
2402          x += glyph->width;\
2403      }\
2404  }  }
2405    
2406  void  void
2407  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,
2408               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2409               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2410               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2411  {  {
2412            /* TODO: use brush appropriately */
2413    
2414          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2415          int i, offset;          int i, j, xyoffset, x1, y1;
2416            DATABLOB *entry;
2417    
2418          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
2419    
2420            /* Sometimes, the boxcx value is something really large, like
2421               32691. This makes XCopyArea fail with Xvnc. The code below
2422               is a quick fix. */
2423            if (boxx + boxcx > g_width)
2424                    boxcx = g_width - boxx;
2425    
2426          if (boxcx > 1)          if (boxcx > 1)
2427          {          {
2428                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2429          }          }
2430          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
2431          {          {
2432                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2433          }          }
2434    
2435            SET_FOREGROUND(fgcolour);
2436            SET_BACKGROUND(bgcolour);
2437            XSetFillStyle(g_display, g_gc, FillStippled);
2438    
2439          /* Paint text, character by character */          /* Paint text, character by character */
2440          for (i = 0; i < length; i++)          for (i = 0; i < length;)
2441          {          {
2442                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
2443                  {                  {
2444                          offset = text[++i];                          case 0xff:
2445                          if (offset & 0x80)                                  if (i + 2 < length)
2446                                  offset = ((offset & 0x7f) << 8) | text[++i];                                          cache_put_text(text[i + 1], text, text[i + 2]);
2447                                    else
2448                                    {
2449                                            error("this shouldn't be happening\n");
2450                                            exit(1);
2451                                    }
2452                                    /* this will move pointer from start to first character after FF command */
2453                                    length -= i + 3;
2454                                    text = &(text[i + 3]);
2455                                    i = 0;
2456                                    break;
2457    
2458                          if (flags & TEXT2_VERTICAL)                          case 0xfe:
2459                                  y += offset;                                  entry = cache_get_text(text[i + 1]);
2460                          else                                  if (entry != NULL)
2461                                  x += offset;                                  {
2462                                            if ((((uint8 *) (entry->data))[1] ==
2463                                                 0) && (!(flags & TEXT2_IMPLICIT_X)))
2464                                            {
2465                                                    if (flags & TEXT2_VERTICAL)
2466                                                            y += text[i + 2];
2467                                                    else
2468                                                            x += text[i + 2];
2469                                            }
2470                                            for (j = 0; j < entry->size; j++)
2471                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
2472                                    }
2473                                    if (i + 2 < length)
2474                                            i += 3;
2475                                    else
2476                                            i += 2;
2477                                    length -= i;
2478                                    /* this will move pointer from start to first character after FE command */
2479                                    text = &(text[i]);
2480                                    i = 0;
2481                                    break;
2482    
2483                            default:
2484                                    DO_GLYPH(text, i);
2485                                    i++;
2486                                    break;
2487                  }                  }
2488            }
2489    
2490                  if (glyph != NULL)          XSetFillStyle(g_display, g_gc, FillSolid);
                 {  
                         ui_draw_glyph(mixmode, x + (short) glyph->offset,  
                                       y + (short) glyph->baseline,  
                                       glyph->width, glyph->height,  
                                       glyph->pixmap, 0, 0,  
                                       bgcolour, fgcolour);  
2491    
2492                          if (flags & TEXT2_IMPLICIT_X)          if (g_ownbackstore)
2493                                  x += glyph->width;          {
2494                  }                  if (boxcx > 1)
2495                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2496                                      boxy, boxcx, boxcy, boxx, boxy);
2497                    else
2498                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2499                                      clipy, clipcx, clipcy, clipx, clipy);
2500          }          }
2501  }  }
2502    
# Line 982  ui_desktop_save(uint32 offset, int x, in Line 2506  ui_desktop_save(uint32 offset, int x, in
2506          Pixmap pix;          Pixmap pix;
2507          XImage *image;          XImage *image;
2508    
2509          if (ownbackstore)          if (g_ownbackstore)
2510          {          {
2511                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
2512          }          }
2513          else          else
2514          {          {
2515                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2516                  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);
2517                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,                  image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2518                                    ZPixmap);                  XFreePixmap(g_display, pix);
                 XFreePixmap(display, pix);  
2519          }          }
2520    
2521          offset *= bpp/8;          offset *= g_bpp / 8;
2522          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
                           bpp/8, (uint8 *)image->data);  
2523    
2524          XDestroyImage(image);          XDestroyImage(image);
2525  }  }
# Line 1009  ui_desktop_restore(uint32 offset, int x, Line 2530  ui_desktop_restore(uint32 offset, int x,
2530          XImage *image;          XImage *image;
2531          uint8 *data;          uint8 *data;
2532    
2533          offset *= bpp/8;          offset *= g_bpp / 8;
2534          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2535          if (data == NULL)          if (data == NULL)
2536                  return;                  return;
2537    
2538          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2539                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
                              cx * bpp/8);  
2540    
2541          if (ownbackstore)          if (g_ownbackstore)
2542          {          {
2543                  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);
2544                  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);
2545          }          }
2546          else          else
2547          {          {
2548                  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);
2549          }          }
2550    
2551          XFree(image);          XFree(image);
2552  }  }
2553    
2554    /* these do nothing here but are used in uiports */
2555    void
2556    ui_begin_update(void)
2557    {
2558    }
2559    
2560    void
2561    ui_end_update(void)
2562    {
2563    }

Legend:
Removed from v.36  
changed lines
  Added in v.988

  ViewVC Help
Powered by ViewVC 1.1.26