/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

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

  ViewVC Help
Powered by ViewVC 1.1.26