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

Legend:
Removed from v.12  
changed lines
  Added in v.844

  ViewVC Help
Powered by ViewVC 1.1.26