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

Legend:
Removed from v.28  
changed lines
  Added in v.822

  ViewVC Help
Powered by ViewVC 1.1.26