/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

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

revision 28 by matty, Wed Jun 20 13:54:48 2001 UTC revision 823 by stargo, Mon Feb 28 23:30:00 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                            while (out < end)
666                            {
667                                    pixel = *(data++);
668                                    SPLITCOLOUR16(pixel, pc);
669                                    value = MAKECOLOUR(pc);
670                                    BOUT32(out, value);
671                            }
672                    }
673            }
674            else
675            {
676                    if (g_host_be)
677                    {
678                            while (out < end)
679                            {
680                                    pixel = *(data++);
681                                    BSWAP16(pixel);
682                                    SPLITCOLOUR16(pixel, pc);
683                                    value = MAKECOLOUR(pc);
684                                    LOUT32(out, value);
685                            }
686                    }
687                    else
688                    {
689                            while (out < end)
690                            {
691                                    pixel = *(data++);
692                                    SPLITCOLOUR16(pixel, pc);
693                                    value = MAKECOLOUR(pc);
694                                    LOUT32(out, value);
695                            }
696                    }
697            }
698    }
699    
700          if (last_rop2 != rop2)  static void
701    translate24to16(const uint8 * data, uint8 * out, uint8 * end)
702    {
703            uint32 pixel = 0;
704            uint16 value;
705            PixelColour pc;
706    
707            while (out < end)
708            {
709                    pixel = *(data++) << 16;
710                    pixel |= *(data++) << 8;
711                    pixel |= *(data++);
712                    SPLITCOLOUR24(pixel, pc);
713                    value = MAKECOLOUR(pc);
714                    if (g_xserver_be)
715                    {
716                            BOUT16(out, value);
717                    }
718                    else
719                    {
720                            LOUT16(out, value);
721                    }
722            }
723    }
724    
725    static void
726    translate24to24(const uint8 * data, uint8 * out, uint8 * end)
727    {
728            uint32 pixel;
729            uint32 value;
730            PixelColour pc;
731    
732            if (g_xserver_be)
733            {
734                    while (out < end)
735                    {
736                            pixel = *(data++) << 16;
737                            pixel |= *(data++) << 8;
738                            pixel |= *(data++);
739                            SPLITCOLOUR24(pixel, pc);
740                            value = MAKECOLOUR(pc);
741                            BOUT24(out, value);
742                    }
743            }
744            else
745          {          {
746                  XSetFunction(display, gc, rop2_map[rop2]);                  while (out < end)
747                  last_rop2 = rop2;                  {
748                            pixel = *(data++) << 16;
749                            pixel |= *(data++) << 8;
750                            pixel |= *(data++);
751                            SPLITCOLOUR24(pixel, pc);
752                            value = MAKECOLOUR(pc);
753                            LOUT24(out, value);
754                    }
755          }          }
756  }  }
757    
758  static void  static void
759  xwin_grab_keyboard()  translate24to32(const uint8 * data, uint8 * out, uint8 * end)
760  {  {
761          XGrabKeyboard(display, wnd, True, GrabModeAsync, GrabModeAsync,          uint32 pixel;
762                        CurrentTime);          uint32 value;
763            PixelColour pc;
764    
765            if (g_arch_match)
766            {
767                    /* *INDENT-OFF* */
768    #ifdef NEED_ALIGN
769                    REPEAT4
770                    (
771                            *(out++) = *(data++);
772                            *(out++) = *(data++);
773                            *(out++) = *(data++);
774                            *(out++) = 0;
775                    )
776    #else
777                    REPEAT4
778                    (
779                            *((uint32 *) out) = *((uint32 *) data);
780                            out += 4;
781                            data += 3;
782                    )
783    #endif
784                    /* *INDENT-ON* */
785            }
786            else if (g_xserver_be)
787            {
788                    while (out < end)
789                    {
790                            pixel = *(data++) << 16;
791                            pixel |= *(data++) << 8;
792                            pixel |= *(data++);
793                            SPLITCOLOUR24(pixel, pc);
794                            value = MAKECOLOUR(pc);
795                            BOUT32(out, value);
796                    }
797            }
798            else
799            {
800                    while (out < end)
801                    {
802                            pixel = *(data++) << 16;
803                            pixel |= *(data++) << 8;
804                            pixel |= *(data++);
805                            SPLITCOLOUR24(pixel, pc);
806                            value = MAKECOLOUR(pc);
807                            LOUT32(out, value);
808                    }
809            }
810    }
811    
812    static uint8 *
813    translate_image(int width, int height, uint8 * data)
814    {
815            int size;
816            uint8 *out;
817            uint8 *end;
818    
819            /* if server and xserver bpp match, */
820            /* and arch(endian) matches, no need to translate */
821            /* just return data */
822            if (g_arch_match)
823            {
824                    if (g_depth == 15 && g_server_bpp == 15)
825                            return data;
826                    if (g_depth == 16 && g_server_bpp == 16)
827                            return data;
828                    if (g_depth == 24 && g_bpp == 24 && g_server_bpp == 24)
829                            return data;
830            }
831    
832            size = width * height * (g_bpp / 8);
833            out = (uint8 *) xmalloc(size);
834            end = out + size;
835    
836            switch (g_server_bpp)
837            {
838                    case 24:
839                            switch (g_bpp)
840                            {
841                                    case 32:
842                                            translate24to32(data, out, end);
843                                            break;
844                                    case 24:
845                                            translate24to24(data, out, end);
846                                            break;
847                                    case 16:
848                                            translate24to16(data, out, end);
849                                            break;
850                            }
851                            break;
852                    case 16:
853                            switch (g_bpp)
854                            {
855                                    case 32:
856                                            translate16to32((uint16 *) data, out, end);
857                                            break;
858                                    case 24:
859                                            translate16to24((uint16 *) data, out, end);
860                                            break;
861                                    case 16:
862                                            translate16to16((uint16 *) data, out, end);
863                                            break;
864                            }
865                            break;
866                    case 15:
867                            switch (g_bpp)
868                            {
869                                    case 32:
870                                            translate15to32((uint16 *) data, out, end);
871                                            break;
872                                    case 24:
873                                            translate15to24((uint16 *) data, out, end);
874                                            break;
875                                    case 16:
876                                            translate15to16((uint16 *) data, out, end);
877                                            break;
878                            }
879                            break;
880                    case 8:
881                            switch (g_bpp)
882                            {
883                                    case 8:
884                                            translate8to8(data, out, end);
885                                            break;
886                                    case 16:
887                                            translate8to16(data, out, end);
888                                            break;
889                                    case 24:
890                                            translate8to24(data, out, end);
891                                            break;
892                                    case 32:
893                                            translate8to32(data, out, end);
894                                            break;
895                            }
896                            break;
897            }
898            return out;
899    }
900    
901    BOOL
902    get_key_state(unsigned int state, uint32 keysym)
903    {
904            int modifierpos, key, keysymMask = 0;
905            int offset;
906    
907            KeyCode keycode = XKeysymToKeycode(g_display, keysym);
908    
909            if (keycode == NoSymbol)
910                    return False;
911    
912            for (modifierpos = 0; modifierpos < 8; modifierpos++)
913            {
914                    offset = g_mod_map->max_keypermod * modifierpos;
915    
916                    for (key = 0; key < g_mod_map->max_keypermod; key++)
917                    {
918                            if (g_mod_map->modifiermap[offset + key] == keycode)
919                                    keysymMask |= 1 << modifierpos;
920                    }
921            }
922    
923            return (state & keysymMask) ? True : False;
924  }  }
925    
926  static void  static void
927  xwin_ungrab_keyboard()  calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
928  {  {
929          XUngrabKeyboard(display, CurrentTime);          *shift_l = ffs(mask) - 1;
930            mask >>= *shift_l;
931            *shift_r = 8 - ffs(mask & ~(mask >> 1));
932  }  }
933    
934  BOOL  BOOL
935  ui_create_window(char *title)  ui_init(void)
936  {  {
937          XSetWindowAttributes attribs;          XVisualInfo vi;
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
938          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
939          int count;          uint16 test;
940            int i, screen_num, nvisuals;
941            XVisualInfo *vmatches = NULL;
942            XVisualInfo template;
943            Bool TrueColorVisual = False;
944    
945          display = XOpenDisplay(NULL);          g_display = XOpenDisplay(NULL);
946          if (display == NULL)          if (g_display == NULL)
947          {          {
948                  ERROR("Failed to open display\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
949                  return False;                  return False;
950          }          }
951    
952          visual = DefaultVisual(display, DefaultScreen(display));          screen_num = DefaultScreen(g_display);
953          depth = DefaultDepth(display, DefaultScreen(display));          g_x_socket = ConnectionNumber(g_display);
954          pfm = XListPixmapFormats(display, &count);          g_screen = ScreenOfDisplay(g_display, screen_num);
955            g_depth = DefaultDepthOfScreen(g_screen);
956    
957            /* Search for best TrueColor depth */
958            template.class = TrueColor;
959            vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);
960    
961            nvisuals--;
962            while (nvisuals >= 0)
963            {
964                    if ((vmatches + nvisuals)->depth > g_depth)
965                    {
966                            g_depth = (vmatches + nvisuals)->depth;
967                    }
968                    nvisuals--;
969                    TrueColorVisual = True;
970            }
971    
972            test = 1;
973            g_host_be = !(BOOL) (*(uint8 *) (&test));
974            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
975    
976            if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))
977            {
978                    /* we use a colourmap, so the default visual should do */
979                    g_visual = DefaultVisualOfScreen(g_screen);
980                    g_depth = DefaultDepthOfScreen(g_screen);
981    
982                    /* Do not allocate colours on a TrueColor visual */
983                    if (g_visual->class == TrueColor)
984                    {
985                            g_owncolmap = False;
986                    }
987            }
988            else
989            {
990                    /* need a truecolour visual */
991                    if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))
992                    {
993                            error("The display does not support true colour - high colour support unavailable.\n");
994                            return False;
995                    }
996    
997                    g_visual = vi.visual;
998                    g_owncolmap = False;
999                    calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);
1000                    calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);
1001                    calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);
1002    
1003                    /* if RGB video and everything is little endian */
1004                    if ((vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask) &&
1005                        !g_xserver_be && !g_host_be)
1006                    {
1007                            if (g_depth <= 16 || (g_red_shift_l == 16 && g_green_shift_l == 8 &&
1008                                                  g_blue_shift_l == 0))
1009                            {
1010                                    g_arch_match = True;
1011                            }
1012                    }
1013    
1014                    if (g_arch_match)
1015                    {
1016                            DEBUG(("Architectures match, enabling little endian optimisations.\n"));
1017                    }
1018            }
1019    
1020            pfm = XListPixmapFormats(g_display, &i);
1021          if (pfm != NULL)          if (pfm != NULL)
1022          {          {
1023                  while (count--)                  /* Use maximum bpp for this depth - this is generally
1024                       desirable, e.g. 24 bits->32 bits. */
1025                    while (i--)
1026                  {                  {
1027                          if ((pfm + count)->depth == depth                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
                             && (pfm + count)->bits_per_pixel > bpp)  
1028                          {                          {
1029                                  bpp = (pfm + count)->bits_per_pixel;                                  g_bpp = pfm[i].bits_per_pixel;
1030                          }                          }
1031                  }                  }
1032                  XFree(pfm);                  XFree(pfm);
1033          }          }
1034    
1035          if (bpp < 8)          if (g_bpp < 8)
1036          {          {
1037                  ERROR("Less than 8 bpp not currently supported.\n");                  error("Less than 8 bpp not currently supported.\n");
1038                  XCloseDisplay(display);                  XCloseDisplay(g_display);
1039                  return False;                  return False;
1040          }          }
1041    
1042          width &= ~3; /* make width nicely divisible */          if (!g_owncolmap)
1043            {
1044                    g_xcolmap =
1045                            XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1046                                            AllocNone);
1047                    if (g_depth <= 8)
1048                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
1049            }
1050    
1051          attribs.background_pixel = BlackPixel(display, DefaultScreen(display));          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1052          attribs.backing_store = Always;          {
1053                    warning("External BackingStore not available, using internal\n");
1054                    g_ownbackstore = True;
1055            }
1056    
1057          if (fullscreen)          /*
1058             * Determine desktop size
1059             */
1060            if (g_fullscreen)
1061          {          {
1062                  attribs.override_redirect = True;                  g_width = WidthOfScreen(g_screen);
1063                  width = WidthOfScreen(DefaultScreenOfDisplay(display));                  g_height = HeightOfScreen(g_screen);
                 height = HeightOfScreen(DefaultScreenOfDisplay(display));  
                 XSetInputFocus(display, PointerRoot, RevertToPointerRoot,  
                                CurrentTime);  
1064          }          }
1065          else          else if (g_width < 0)
1066            {
1067                    /* Percent of screen */
1068                    g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1069                    g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1070            }
1071            else if (g_width == 0)
1072            {
1073                    /* Fetch geometry from _NET_WORKAREA */
1074                    uint32 x, y, cx, cy;
1075    
1076                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1077                    {
1078                            g_width = cx;
1079                            g_height = cy;
1080                    }
1081                    else
1082                    {
1083                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1084                            g_width = 800;
1085                            g_height = 600;
1086                    }
1087            }
1088    
1089            /* make sure width is a multiple of 4 */
1090            g_width = (g_width + 3) & ~3;
1091    
1092            g_mod_map = XGetModifierMapping(g_display);
1093    
1094            xkeymap_init();
1095    
1096            if (g_enable_compose)
1097                    g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1098    
1099            xclip_init();
1100    
1101            DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));
1102    
1103            return True;
1104    }
1105    
1106    void
1107    ui_deinit(void)
1108    {
1109            if (g_IM != NULL)
1110                    XCloseIM(g_IM);
1111    
1112            if (g_null_cursor != NULL)
1113                    ui_destroy_cursor(g_null_cursor);
1114    
1115            XFreeModifiermap(g_mod_map);
1116    
1117            if (g_ownbackstore)
1118                    XFreePixmap(g_display, g_backstore);
1119    
1120            XFreeGC(g_display, g_gc);
1121            XCloseDisplay(g_display);
1122            g_display = NULL;
1123    }
1124    
1125    BOOL
1126    ui_create_window(void)
1127    {
1128            uint8 null_pointer_mask[1] = { 0x80 };
1129            uint8 null_pointer_data[24] = { 0x00 };
1130    
1131            XSetWindowAttributes attribs;
1132            XClassHint *classhints;
1133            XSizeHints *sizehints;
1134            int wndwidth, wndheight;
1135            long input_mask, ic_input_mask;
1136            XEvent xevent;
1137    
1138            wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1139            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1140    
1141            attribs.background_pixel = BlackPixelOfScreen(g_screen);
1142            attribs.border_pixel = WhitePixelOfScreen(g_screen);
1143            attribs.backing_store = g_ownbackstore ? NotUseful : Always;
1144            attribs.override_redirect = g_fullscreen;
1145            attribs.colormap = g_xcolmap;
1146    
1147            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1148                                  wndheight, 0, g_depth, InputOutput, g_visual,
1149                                  CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1150                                  CWBorderPixel, &attribs);
1151    
1152            if (g_gc == NULL)
1153                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1154    
1155            if (g_create_bitmap_gc == NULL)
1156                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1157    
1158            if ((g_ownbackstore) && (g_backstore == 0))
1159          {          {
1160                  attribs.override_redirect = False;                  g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1161    
1162                    /* clear to prevent rubbish being exposed at startup */
1163                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1164                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
1165          }          }
1166    
1167          wnd = XCreateWindow(display, DefaultRootWindow(display),          XStoreName(g_display, g_wnd, g_title);
                             0, 0, width, height, 0, CopyFromParent,  
                             InputOutput, CopyFromParent,  
                             CWBackingStore | CWBackPixel | CWOverrideRedirect,  
                             &attribs);  
1168    
1169          XStoreName(display, wnd, title);          if (g_hide_decorations)
1170                    mwm_hide_decorations();
1171    
1172          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1173          if (classhints != NULL)          if (classhints != NULL)
   
1174          {          {
1175                  classhints->res_name = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
1176                  classhints->res_class = "rdesktop";                  XSetClassHint(g_display, g_wnd, classhints);
                 XSetClassHint(display, wnd, classhints);  
1177                  XFree(classhints);                  XFree(classhints);
1178          }          }
1179    
1180          sizehints = XAllocSizeHints();          sizehints = XAllocSizeHints();
1181          if (sizehints)          if (sizehints)
1182          {          {
1183                  sizehints->flags =                  sizehints->flags = PMinSize | PMaxSize;
1184                          PPosition | PSize | PMinSize | PMaxSize | PBaseSize;                  sizehints->min_width = sizehints->max_width = g_width;
1185                  sizehints->min_width = width;                  sizehints->min_height = sizehints->max_height = g_height;
1186                  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);  
1187                  XFree(sizehints);                  XFree(sizehints);
1188          }          }
1189    
1190          input_mask = KeyPressMask | KeyReleaseMask;          if (g_embed_wnd)
1191          input_mask |= ButtonPressMask | ButtonReleaseMask;          {
1192          if (motion)                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1193            }
1194    
1195            input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1196                    VisibilityChangeMask | FocusChangeMask;
1197    
1198            if (g_sendmotion)
1199                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
1200          if (grab_keyboard)          if (g_ownbackstore)
1201                  input_mask |= EnterWindowMask | LeaveWindowMask;                  input_mask |= ExposureMask;
1202            if (g_fullscreen || g_grab_keyboard)
1203                    input_mask |= EnterWindowMask;
1204            if (g_grab_keyboard)
1205                    input_mask |= LeaveWindowMask;
1206    
1207            if (g_IM != NULL)
1208            {
1209                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1210                                     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1211    
1212                    if ((g_IC != NULL)
1213                        && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1214                            input_mask |= ic_input_mask;
1215            }
1216    
1217            XSelectInput(g_display, g_wnd, input_mask);
1218            XMapWindow(g_display, g_wnd);
1219    
1220            /* wait for VisibilityNotify */
1221            do
1222            {
1223                    XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1224            }
1225            while (xevent.type != VisibilityNotify);
1226            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1227    
1228            g_focused = False;
1229            g_mouse_in_wnd = False;
1230    
1231            /* handle the WM_DELETE_WINDOW protocol */
1232            g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1233            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1234            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1235    
1236          XSelectInput(display, wnd, input_mask);          /* create invisible 1x1 cursor to be used as null cursor */
1237          gc = XCreateGC(display, wnd, 0, NULL);          if (g_null_cursor == NULL)
1238                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1239    
         XMapWindow(display, wnd);  
1240          return True;          return True;
1241  }  }
1242    
1243  void  void
1244  ui_destroy_window()  ui_resize_window()
1245  {  {
1246          XFreeGC(display, gc);          XSizeHints *sizehints;
1247          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;  
1248    
1249          if (display == NULL)          sizehints = XAllocSizeHints();
1250                  return;          if (sizehints)
1251            {
1252                    sizehints->flags = PMinSize | PMaxSize;
1253                    sizehints->min_width = sizehints->max_width = g_width;
1254                    sizehints->min_height = sizehints->max_height = g_height;
1255                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1256                    XFree(sizehints);
1257            }
1258    
1259            if (!(g_fullscreen || g_embed_wnd))
1260            {
1261                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1262            }
1263    
1264          while (XCheckWindowEvent(display, wnd, ~0, &event))          /* create new backstore pixmap */
1265            if (g_backstore != 0)
1266          {          {
1267                  ev_time = time(NULL);                  bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1268                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1269                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1270                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1271                    XFreePixmap(g_display, g_backstore);
1272                    g_backstore = bs;
1273            }
1274    }
1275    
1276    void
1277    ui_destroy_window(void)
1278    {
1279            if (g_IC != NULL)
1280                    XDestroyIC(g_IC);
1281    
1282            XDestroyWindow(g_display, g_wnd);
1283    }
1284    
1285    void
1286    xwin_toggle_fullscreen(void)
1287    {
1288            Pixmap contents = 0;
1289    
1290            if (!g_ownbackstore)
1291            {
1292                    /* need to save contents of window */
1293                    contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1294                    XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1295            }
1296    
1297            ui_destroy_window();
1298            g_fullscreen = !g_fullscreen;
1299            ui_create_window();
1300    
1301                  switch (event.type)          XDefineCursor(g_display, g_wnd, g_current_cursor);
1302    
1303            if (!g_ownbackstore)
1304            {
1305                    XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1306                    XFreePixmap(g_display, contents);
1307            }
1308    }
1309    
1310    /* Process all events in Xlib queue
1311       Returns 0 after user quit, 1 otherwise */
1312    static int
1313    xwin_process_events(void)
1314    {
1315            XEvent xevent;
1316            KeySym keysym;
1317            uint16 button, flags;
1318            uint32 ev_time;
1319            key_translation tr;
1320            char str[256];
1321            Status status;
1322    
1323            while (XPending(g_display) > 0)
1324            {
1325                    XNextEvent(g_display, &xevent);
1326    
1327                    if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1328                    {
1329                            DEBUG_KBD(("Filtering event\n"));
1330                            continue;
1331                    }
1332    
1333                    flags = 0;
1334    
1335                    switch (xevent.type)
1336                  {                  {
1337                            case VisibilityNotify:
1338                                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1339                                    break;
1340                            case ClientMessage:
1341                                    /* the window manager told us to quit */
1342                                    if ((xevent.xclient.message_type == g_protocol_atom)
1343                                        && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1344                                            /* Quit */
1345                                            return 0;
1346                                    break;
1347    
1348                          case KeyPress:                          case KeyPress:
1349                                  scancode = xwin_translate_key(event.xkey.keycode);                                  g_last_gesturetime = xevent.xkey.time;
1350                                  if (scancode == 0)                                  if (g_IC != NULL)
1351                                            /* Multi_key compatible version */
1352                                    {
1353                                            XmbLookupString(g_IC,
1354                                                            &xevent.xkey, str, sizeof(str), &keysym,
1355                                                            &status);
1356                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1357                                            {
1358                                                    error("XmbLookupString failed with status 0x%x\n",
1359                                                          status);
1360                                                    break;
1361                                            }
1362                                    }
1363                                    else
1364                                    {
1365                                            /* Plain old XLookupString */
1366                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1367                                            XLookupString((XKeyEvent *) & xevent,
1368                                                          str, sizeof(str), &keysym, NULL);
1369                                    }
1370    
1371                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1372                                               get_ksname(keysym)));
1373    
1374                                    ev_time = time(NULL);
1375                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1376                                            break;
1377    
1378                                    tr = xkeymap_translate_key(keysym,
1379                                                               xevent.xkey.keycode, xevent.xkey.state);
1380    
1381                                    if (tr.scancode == 0)
1382                                          break;                                          break;
1383    
1384                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  save_remote_modifiers(tr.scancode);
1385                                                 scancode, 0);                                  ensure_remote_modifiers(ev_time, tr);
1386                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1387                                    restore_remote_modifiers(ev_time, tr.scancode);
1388    
1389                                  break;                                  break;
1390    
1391                          case KeyRelease:                          case KeyRelease:
1392                                  scancode = xwin_translate_key(event.xkey.keycode);                                  g_last_gesturetime = xevent.xkey.time;
1393                                  if (scancode == 0)                                  XLookupString((XKeyEvent *) & xevent, str,
1394                                                  sizeof(str), &keysym, NULL);
1395    
1396                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1397                                               get_ksname(keysym)));
1398    
1399                                    ev_time = time(NULL);
1400                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1401                                          break;                                          break;
1402    
1403                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  tr = xkeymap_translate_key(keysym,
1404                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                             xevent.xkey.keycode, xevent.xkey.state);
                                                scancode, 0);  
                                 break;  
1405    
1406                          case ButtonPress:                                  if (tr.scancode == 0)
                                 button = xwin_translate_mouse(event.xbutton.button);  
                                 if (button == 0)  
1407                                          break;                                          break;
1408    
1409                                  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);  
1410                                  break;                                  break;
1411    
1412                            case ButtonPress:
1413                                    flags = MOUSE_FLAG_DOWN;
1414                                    /* fall through */
1415    
1416                          case ButtonRelease:                          case ButtonRelease:
1417                                  button = xwin_translate_mouse(event.xbutton.button);                                  g_last_gesturetime = xevent.xbutton.time;
1418                                    button = xkeymap_translate_button(xevent.xbutton.button);
1419                                  if (button == 0)                                  if (button == 0)
1420                                          break;                                          break;
1421    
1422                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
1423                                                 button,                                  if (xevent.xbutton.y < g_win_button_size)
1424                                                 event.xbutton.x,                                  {
1425                                                 event.xbutton.y);                                          /* Stop moving window when button is released, regardless of cursor position */
1426                                            if (g_moving_wnd && (xevent.type == ButtonRelease))
1427                                                    g_moving_wnd = False;
1428    
1429                                            /*  Check from right to left: */
1430    
1431                                            if (xevent.xbutton.x >= g_width - g_win_button_size)
1432                                            {
1433                                                    /* The close button, continue */
1434                                                    ;
1435                                            }
1436                                            else if (xevent.xbutton.x >=
1437                                                     g_width - g_win_button_size * 2)
1438                                            {
1439                                                    /* The maximize/restore button. Do not send to
1440                                                       server.  It might be a good idea to change the
1441                                                       cursor or give some other visible indication
1442                                                       that rdesktop inhibited this click */
1443                                                    break;
1444                                            }
1445                                            else if (xevent.xbutton.x >=
1446                                                     g_width - g_win_button_size * 3)
1447                                            {
1448                                                    /* The minimize button. Iconify window. */
1449                                                    XIconifyWindow(g_display, g_wnd,
1450                                                                   DefaultScreen(g_display));
1451                                                    break;
1452                                            }
1453                                            else if (xevent.xbutton.x <= g_win_button_size)
1454                                            {
1455                                                    /* The system menu. Ignore. */
1456                                                    break;
1457                                            }
1458                                            else
1459                                            {
1460                                                    /* The title bar. */
1461                                                    if ((xevent.type == ButtonPress) && !g_fullscreen
1462                                                        && g_hide_decorations)
1463                                                    {
1464                                                            g_moving_wnd = True;
1465                                                            g_move_x_offset = xevent.xbutton.x;
1466                                                            g_move_y_offset = xevent.xbutton.y;
1467                                                    }
1468                                                    break;
1469    
1470                                            }
1471                                    }
1472    
1473                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1474                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1475                                  break;                                  break;
1476    
1477                          case MotionNotify:                          case MotionNotify:
1478                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (g_moving_wnd)
1479                                                 MOUSE_FLAG_MOVE,                                  {
1480                                                 event.xmotion.x,                                          XMoveWindow(g_display, g_wnd,
1481                                                 event.xmotion.y);                                                      xevent.xmotion.x_root - g_move_x_offset,
1482                                                        xevent.xmotion.y_root - g_move_y_offset);
1483                                            break;
1484                                    }
1485    
1486                                    if (g_fullscreen && !g_focused)
1487                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1488                                                           CurrentTime);
1489                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1490                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1491                                    break;
1492    
1493                            case FocusIn:
1494                                    if (xevent.xfocus.mode == NotifyGrab)
1495                                            break;
1496                                    g_focused = True;
1497                                    reset_modifier_keys();
1498                                    if (g_grab_keyboard && g_mouse_in_wnd)
1499                                            XGrabKeyboard(g_display, g_wnd, True,
1500                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1501                                    break;
1502    
1503                            case FocusOut:
1504                                    if (xevent.xfocus.mode == NotifyUngrab)
1505                                            break;
1506                                    g_focused = False;
1507                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1508                                            XUngrabKeyboard(g_display, CurrentTime);
1509                                  break;                                  break;
1510    
1511                          case EnterNotify:                          case EnterNotify:
1512                                  if (grab_keyboard)                                  /* we only register for this event when in fullscreen mode */
1513                                          xwin_grab_keyboard();                                  /* or grab_keyboard */
1514                                    g_mouse_in_wnd = True;
1515                                    if (g_fullscreen)
1516                                    {
1517                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1518                                                           CurrentTime);
1519                                            break;
1520                                    }
1521                                    if (g_focused)
1522                                            XGrabKeyboard(g_display, g_wnd, True,
1523                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1524                                  break;                                  break;
1525    
1526                          case LeaveNotify:                          case LeaveNotify:
1527                                  if (grab_keyboard)                                  /* we only register for this event when grab_keyboard */
1528                                          xwin_ungrab_keyboard();                                  g_mouse_in_wnd = False;
1529                                    XUngrabKeyboard(g_display, CurrentTime);
1530                                    break;
1531    
1532                            case Expose:
1533                                    XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1534                                              xevent.xexpose.x, xevent.xexpose.y,
1535                                              xevent.xexpose.width,
1536                                              xevent.xexpose.height,
1537                                              xevent.xexpose.x, xevent.xexpose.y);
1538                                    break;
1539    
1540                            case MappingNotify:
1541                                    /* Refresh keyboard mapping if it has changed. This is important for
1542                                       Xvnc, since it allocates keycodes dynamically */
1543                                    if (xevent.xmapping.request == MappingKeyboard
1544                                        || xevent.xmapping.request == MappingModifier)
1545                                            XRefreshKeyboardMapping(&xevent.xmapping);
1546    
1547                                    if (xevent.xmapping.request == MappingModifier)
1548                                    {
1549                                            XFreeModifiermap(g_mod_map);
1550                                            g_mod_map = XGetModifierMapping(g_display);
1551                                    }
1552                                    break;
1553    
1554                                    /* clipboard stuff */
1555                            case SelectionNotify:
1556                                    xclip_handle_SelectionNotify(&xevent.xselection);
1557                                    break;
1558                            case SelectionRequest:
1559                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1560                                    break;
1561                            case SelectionClear:
1562                                    xclip_handle_SelectionClear();
1563                                    break;
1564                            case PropertyNotify:
1565                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1566                                  break;                                  break;
1567                  }                  }
1568          }          }
1569            /* Keep going */
1570            return 1;
1571    }
1572    
1573    /* Returns 0 after user quit, 1 otherwise */
1574    int
1575    ui_select(int rdp_socket)
1576    {
1577            int n;
1578            fd_set rfds, wfds;
1579            struct timeval tv;
1580            BOOL s_timeout = False;
1581    
1582            while (True)
1583            {
1584                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1585                    /* Process any events already waiting */
1586                    if (!xwin_process_events())
1587                            /* User quit */
1588                            return 0;
1589    
1590                    FD_ZERO(&rfds);
1591                    FD_ZERO(&wfds);
1592                    FD_SET(rdp_socket, &rfds);
1593                    FD_SET(g_x_socket, &rfds);
1594    
1595    #ifdef WITH_RDPSND
1596                    /* FIXME: there should be an API for registering fds */
1597                    if (g_dsp_busy)
1598                    {
1599                            FD_SET(g_dsp_fd, &wfds);
1600                            n = (g_dsp_fd > n) ? g_dsp_fd : n;
1601                    }
1602    #endif
1603                    /* default timeout */
1604                    tv.tv_sec = 60;
1605                    tv.tv_usec = 0;
1606    
1607                    /* add redirection handles */
1608                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1609    
1610                    n++;
1611    
1612                    switch (select(n, &rfds, &wfds, NULL, &tv))
1613                    {
1614                            case -1:
1615                                    error("select: %s\n", strerror(errno));
1616    
1617                            case 0:
1618                                    /* Abort serial read calls */
1619                                    if (s_timeout)
1620                                            rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1621                                    continue;
1622                    }
1623    
1624                    rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
1625    
1626                    if (FD_ISSET(rdp_socket, &rfds))
1627                            return 1;
1628    
1629    #ifdef WITH_RDPSND
1630                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1631                            wave_out_play();
1632    #endif
1633            }
1634  }  }
1635    
1636  void  void
1637  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
1638  {  {
1639          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1640  }  }
1641    
1642  HBITMAP  HBITMAP
1643  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1644  {  {
1645          XImage *image;          XImage *image;
1646          Pixmap bitmap;          Pixmap bitmap;
1647          uint8 *tdata;          uint8 *tdata;
1648          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);  
1649    
1650          xwin_set_function(ROP2_COPY);          if (g_server_bpp == 8)
1651          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          {
1652                    bitmap_pad = 8;
1653            }
1654            else
1655            {
1656                    bitmap_pad = g_bpp;
1657    
1658          XFree(image);                  if (g_bpp == 24)
1659          if (!private_colormap)                          bitmap_pad = 32;
1660                  xfree(tdata);          }
         return (HBITMAP) bitmap;  
 }  
1661    
1662  void          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1663  ui_paint_bitmap(int x, int y, int cx, int cy,          bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1664                  int width, int height, uint8 *data)          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1665  {                               (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);  
1666    
1667          xwin_set_function(ROP2_COPY);          XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
1668    
         /* Window */  
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
1669          XFree(image);          XFree(image);
1670          if (!private_colormap)          if (tdata != data)
1671                  xfree(tdata);                  xfree(tdata);
1672            return (HBITMAP) bitmap;
1673  }  }
1674    
1675  void  void
1676  ui_destroy_bitmap(HBITMAP bmp)  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1677  {  {
1678          XFreePixmap(display, (Pixmap) bmp);          XImage *image;
1679  }          uint8 *tdata;
1680            int bitmap_pad;
1681    
1682  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)  
1683          {          {
1684                  free(cdata);                  bitmap_pad = 8;
                 return NULL;  
1685          }          }
1686          i = (height - 1) * scanlinelen;          else
1687            {
1688                    bitmap_pad = g_bpp;
1689    
1690                    if (g_bpp == 24)
1691                            bitmap_pad = 32;
1692            }
1693    
1694            tdata = (g_owncolmap ? data : translate_image(width, height, data));
1695            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1696                                 (char *) tdata, width, height, bitmap_pad, 0);
1697    
1698          if (!screen_msbfirst)          if (g_ownbackstore)
1699          {          {
1700                  while (i >= 0)                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1701                  {                  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;  
                 }  
1702          }          }
1703          else          else
1704          {          {
1705                  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;  
                 }  
1706          }          }
1707    
1708            XFree(image);
1709          fg.red = 0;          if (tdata != data)
1710          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);  
1711  }  }
1712    
1713  void  void
1714  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_bitmap(HBITMAP bmp)
1715  {  {
1716          XFreeCursor(display, (Cursor) cursor);          XFreePixmap(g_display, (Pixmap) bmp);
1717  }  }
1718    
1719  HGLYPH  HGLYPH
1720  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1721  {  {
1722          XImage *image;          XImage *image;
1723          Pixmap bitmap;          Pixmap bitmap;
1724          int scanline;          int scanline;
         GC gc;  
1725    
1726          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1727    
1728          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1729          gc = XCreateGC(display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
1730                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1731    
1732          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1733                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1734          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1735          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1736          XInitImage(image);          XInitImage(image);
1737    
1738          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);  
1739    
1740            XFree(image);
1741          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1742  }  }
1743    
1744  void  void
1745  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1746  {  {
1747          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(g_display, (Pixmap) glyph);
1748  }  }
1749    
1750  HCOLOURMAP  HCURSOR
1751  ui_create_colourmap(COLOURMAP *colours)  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1752                     uint8 * andmask, uint8 * xormask)
1753  {  {
1754          if (!private_colormap)          HGLYPH maskglyph, cursorglyph;
1755            XColor bg, fg;
1756            Cursor xcursor;
1757            uint8 *cursor, *pcursor;
1758            uint8 *mask, *pmask;
1759            uint8 nextbit;
1760            int scanline, offset;
1761            int i, j;
1762    
1763            scanline = (width + 7) / 8;
1764            offset = scanline * height;
1765    
1766            cursor = (uint8 *) xmalloc(offset);
1767            memset(cursor, 0, offset);
1768    
1769            mask = (uint8 *) xmalloc(offset);
1770            memset(mask, 0, offset);
1771    
1772            /* approximate AND and XOR masks with a monochrome X pointer */
1773            for (i = 0; i < height; i++)
1774          {          {
1775                  COLOURENTRY *entry;                  offset -= scanline;
1776                  int i, ncolours = colours->ncolours;                  pcursor = &cursor[offset];
1777                  uint32 *nc = xmalloc(sizeof(*colmap) * ncolours);                  pmask = &mask[offset];
1778    
1779                    for (j = 0; j < scanline; j++)
1780                    {
1781                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1782                            {
1783                                    if (xormask[0] || xormask[1] || xormask[2])
1784                                    {
1785                                            *pcursor |= (~(*andmask) & nextbit);
1786                                            *pmask |= nextbit;
1787                                    }
1788                                    else
1789                                    {
1790                                            *pcursor |= ((*andmask) & nextbit);
1791                                            *pmask |= (~(*andmask) & nextbit);
1792                                    }
1793    
1794                                    xormask += 3;
1795                            }
1796    
1797                            andmask++;
1798                            pcursor++;
1799                            pmask++;
1800                    }
1801            }
1802    
1803            fg.red = fg.blue = fg.green = 0xffff;
1804            bg.red = bg.blue = bg.green = 0x0000;
1805            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1806    
1807            cursorglyph = ui_create_glyph(width, height, cursor);
1808            maskglyph = ui_create_glyph(width, height, mask);
1809    
1810            xcursor =
1811                    XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1812                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1813    
1814            ui_destroy_glyph(maskglyph);
1815            ui_destroy_glyph(cursorglyph);
1816            xfree(mask);
1817            xfree(cursor);
1818            return (HCURSOR) xcursor;
1819    }
1820    
1821    void
1822    ui_set_cursor(HCURSOR cursor)
1823    {
1824            g_current_cursor = (Cursor) cursor;
1825            XDefineCursor(g_display, g_wnd, g_current_cursor);
1826    }
1827    
1828    void
1829    ui_destroy_cursor(HCURSOR cursor)
1830    {
1831            XFreeCursor(g_display, (Cursor) cursor);
1832    }
1833    
1834    void
1835    ui_set_null_cursor(void)
1836    {
1837            ui_set_cursor(g_null_cursor);
1838    }
1839    
1840    #define MAKE_XCOLOR(xc,c) \
1841                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
1842                    (xc)->green = ((c)->green << 8) | (c)->green; \
1843                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1844                    (xc)->flags = DoRed | DoGreen | DoBlue;
1845    
1846    
1847    HCOLOURMAP
1848    ui_create_colourmap(COLOURMAP * colours)
1849    {
1850            COLOURENTRY *entry;
1851            int i, ncolours = colours->ncolours;
1852            if (!g_owncolmap)
1853            {
1854                    uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1855                    XColor xentry;
1856                    XColor xc_cache[256];
1857                    uint32 colour;
1858                    int colLookup = 256;
1859                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1860                  {                  {
                         XColor xc;  
1861                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1862                          xc.red = entry->red << 8;                          MAKE_XCOLOR(&xentry, entry);
1863                          xc.green = entry->green << 8;  
1864                          xc.blue = entry->blue << 8;                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1865                          XAllocColor(display,                          {
1866                                      DefaultColormap(display,                                  /* Allocation failed, find closest match. */
1867                                                      DefaultScreen(display)),                                  int j = 256;
1868                                      &xc);                                  int nMinDist = 3 * 256 * 256;
1869                          /* XXX Check return value */                                  long nDist = nMinDist;
1870                          nc[i] = xc.pixel;  
1871                                    /* only get the colors once */
1872                                    while (colLookup--)
1873                                    {
1874                                            xc_cache[colLookup].pixel = colLookup;
1875                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1876                                                    xc_cache[colLookup].blue = 0;
1877                                            xc_cache[colLookup].flags = 0;
1878                                            XQueryColor(g_display,
1879                                                        DefaultColormap(g_display,
1880                                                                        DefaultScreen(g_display)),
1881                                                        &xc_cache[colLookup]);
1882                                    }
1883                                    colLookup = 0;
1884    
1885                                    /* approximate the pixel */
1886                                    while (j--)
1887                                    {
1888                                            if (xc_cache[j].flags)
1889                                            {
1890                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1891                                                             (long) (xentry.red >> 8)) *
1892                                                            ((long) (xc_cache[j].red >> 8) -
1893                                                             (long) (xentry.red >> 8)) +
1894                                                            ((long) (xc_cache[j].green >> 8) -
1895                                                             (long) (xentry.green >> 8)) *
1896                                                            ((long) (xc_cache[j].green >> 8) -
1897                                                             (long) (xentry.green >> 8)) +
1898                                                            ((long) (xc_cache[j].blue >> 8) -
1899                                                             (long) (xentry.blue >> 8)) *
1900                                                            ((long) (xc_cache[j].blue >> 8) -
1901                                                             (long) (xentry.blue >> 8));
1902                                            }
1903                                            if (nDist < nMinDist)
1904                                            {
1905                                                    nMinDist = nDist;
1906                                                    xentry.pixel = j;
1907                                            }
1908                                    }
1909                            }
1910                            colour = xentry.pixel;
1911    
1912                            /* update our cache */
1913                            if (xentry.pixel < 256)
1914                            {
1915                                    xc_cache[xentry.pixel].red = xentry.red;
1916                                    xc_cache[xentry.pixel].green = xentry.green;
1917                                    xc_cache[xentry.pixel].blue = xentry.blue;
1918    
1919                            }
1920    
1921                            map[i] = colour;
1922                  }                  }
1923                  return nc;                  return map;
1924          }          }
1925          else          else
1926          {          {
                 COLOURENTRY *entry;  
1927                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
1928                  Colormap map;                  Colormap map;
1929                  int i, ncolours = colours->ncolours;  
1930                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1931                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1932                  {                  {
1933                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1934                          xentry = &xcolours[i];                          xentry = &xcolours[i];
   
1935                          xentry->pixel = i;                          xentry->pixel = i;
1936                          xentry->red = entry->red << 8;                          MAKE_XCOLOR(xentry, entry);
                         xentry->blue = entry->blue << 8;  
                         xentry->green = entry->green << 8;  
                         xentry->flags = DoRed | DoBlue | DoGreen;  
1937                  }                  }
1938    
1939                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1940                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
1941    
1942                  xfree(xcolours);                  xfree(xcolours);
1943                  return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
# Line 612  ui_create_colourmap(COLOURMAP *colours) Line 1947  ui_create_colourmap(COLOURMAP *colours)
1947  void  void
1948  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1949  {  {
1950          XFreeColormap(display, (Colormap) map);          if (!g_owncolmap)
1951                    xfree(map);
1952            else
1953                    XFreeColormap(g_display, (Colormap) map);
1954  }  }
1955    
1956  void  void
1957  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1958  {  {
1959            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  
1960          {          {
1961                  XSetWindowColormap(display, wnd, (Colormap) map);                  if (g_colmap)
1962                  if (fullscreen)                          xfree(g_colmap);
1963                          XInstallColormap(display, (Colormap) map);  
1964                    g_colmap = (uint32 *) map;
1965          }          }
1966            else
1967                    XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1968  }  }
1969    
1970  void  void
# Line 640  ui_set_clip(int x, int y, int cx, int cy Line 1976  ui_set_clip(int x, int y, int cx, int cy
1976          rect.y = y;          rect.y = y;
1977          rect.width = cx;          rect.width = cx;
1978          rect.height = cy;          rect.height = cy;
1979          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1980  }  }
1981    
1982  void  void
1983  ui_reset_clip()  ui_reset_clip(void)
1984  {  {
1985          XRectangle rect;          XRectangle rect;
1986    
1987          rect.x = 0;          rect.x = 0;
1988          rect.y = 0;          rect.y = 0;
1989          rect.width = width;          rect.width = g_width;
1990          rect.height = height;          rect.height = g_height;
1991          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1992  }  }
1993    
1994  void  void
1995  ui_bell()  ui_bell(void)
1996  {  {
1997          XBell(display, 0);          XBell(g_display, 0);
1998  }  }
1999    
2000  void  void
2001  ui_destblt(uint8 opcode,  ui_destblt(uint8 opcode,
2002             /* dest */ int x, int y, int cx, int cy)             /* dest */ int x, int y, int cx, int cy)
2003  {  {
2004          xwin_set_function(opcode);          SET_FUNCTION(opcode);
2005            FILL_RECTANGLE(x, y, cx, cy);
2006          XFillRectangle(display, wnd, gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
2007  }  }
2008    
2009    static uint8 hatch_patterns[] = {
2010            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
2011            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
2012            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
2013            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
2014            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
2015            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
2016    };
2017    
2018  void  void
2019  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
2020            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2021            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2022  {  {
         Display *dpy = display;  
2023          Pixmap fill;          Pixmap fill;
2024          uint8 i, ipattern[8];          uint8 i, ipattern[8];
2025    
2026          xwin_set_function(opcode);          SET_FUNCTION(opcode);
2027    
2028          switch (brush->style)          switch (brush->style)
2029          {          {
2030                  case 0: /* Solid */                  case 0: /* Solid */
2031                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_FOREGROUND(fgcolour);
2032                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2033                            break;
2034    
2035                    case 2: /* Hatch */
2036                            fill = (Pixmap) ui_create_glyph(8, 8,
2037                                                            hatch_patterns + brush->pattern[0] * 8);
2038                            SET_FOREGROUND(fgcolour);
2039                            SET_BACKGROUND(bgcolour);
2040                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2041                            XSetStipple(g_display, g_gc, fill);
2042                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2043                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2044                            XSetFillStyle(g_display, g_gc, FillSolid);
2045                            XSetTSOrigin(g_display, g_gc, 0, 0);
2046                            ui_destroy_glyph((HGLYPH) fill);
2047                          break;                          break;
2048    
2049                  case 3: /* Pattern */                  case 3: /* Pattern */
2050                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
2051                                  ipattern[i] = ~brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
2052                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2053                            SET_FOREGROUND(bgcolour);
2054                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_BACKGROUND(fgcolour);
2055                          XSetBackground(dpy, gc, Ctrans(bgcolour));                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2056                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                          XSetStipple(g_display, g_gc, fill);
2057                          XSetStipple(dpy, gc, fill);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2058                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2059                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          XSetFillStyle(g_display, g_gc, FillSolid);
2060                            XSetTSOrigin(g_display, g_gc, 0, 0);
                         XSetFillStyle(dpy, gc, FillSolid);  
2061                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
2062                          break;                          break;
2063    
2064                  default:                  default:
2065                          NOTIMP("brush %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
2066          }          }
2067    
2068            RESET_FUNCTION(opcode);
2069    
2070            if (g_ownbackstore)
2071                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2072  }  }
2073    
2074  void  void
# Line 714  ui_screenblt(uint8 opcode, Line 2076  ui_screenblt(uint8 opcode,
2076               /* dest */ int x, int y, int cx, int cy,               /* dest */ int x, int y, int cx, int cy,
2077               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
2078  {  {
2079          xwin_set_function(opcode);          SET_FUNCTION(opcode);
2080            if (g_ownbackstore)
2081          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          {
2082                    if (g_Unobscured)
2083                    {
2084                            XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2085                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2086                                      y);
2087                    }
2088                    else
2089                    {
2090                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2091                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2092                                      y);
2093                    }
2094            }
2095            else
2096            {
2097                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2098            }
2099            RESET_FUNCTION(opcode);
2100  }  }
2101    
2102  void  void
# Line 724  ui_memblt(uint8 opcode, Line 2104  ui_memblt(uint8 opcode,
2104            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2105            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
2106  {  {
2107          xwin_set_function(opcode);          SET_FUNCTION(opcode);
2108            XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2109          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          if (g_ownbackstore)
2110                    XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2111            RESET_FUNCTION(opcode);
2112  }  }
2113    
2114  void  void
2115  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
2116            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2117            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
2118            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2119  {  {
2120          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
2121             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 2124  ui_triblt(uint8 opcode,
2124          {          {
2125                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
2126                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
2127                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2128                          break;                          break;
2129    
2130                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
2131                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2132                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
2133                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2134                          break;                          break;
2135    
2136                  case 0xc0:                  case 0xc0:      /* PSa */
2137                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2138                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
2139                          break;                          break;
2140    
2141                  default:                  default:
2142                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
2143                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2144          }          }
2145  }  }
# Line 769  ui_triblt(uint8 opcode, Line 2147  ui_triblt(uint8 opcode,
2147  void  void
2148  ui_line(uint8 opcode,  ui_line(uint8 opcode,
2149          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
2150          /* pen */ PEN *pen)          /* pen */ PEN * pen)
2151  {  {
2152          xwin_set_function(opcode);          SET_FUNCTION(opcode);
2153            SET_FOREGROUND(pen->colour);
2154          XSetForeground(display, gc, Ctrans(pen->colour));          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2155          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          if (g_ownbackstore)
2156                    XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2157            RESET_FUNCTION(opcode);
2158  }  }
2159    
2160  void  void
# Line 782  ui_rect( Line 2162  ui_rect(
2162                 /* dest */ int x, int y, int cx, int cy,                 /* dest */ int x, int y, int cx, int cy,
2163                 /* brush */ int colour)                 /* brush */ int colour)
2164  {  {
2165          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(colour);
2166            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(display, gc, Ctrans(colour));  
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
2167  }  }
2168    
2169    /* warning, this function only draws on wnd or backstore, not both */
2170  void  void
2171  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
2172                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
2173                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
2174                int fgcolour)                int bgcolour, int fgcolour)
2175  {  {
2176          Pixmap pixmap = (Pixmap) glyph;          SET_FOREGROUND(fgcolour);
2177            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;  
2178    
2179                  default:          XSetFillStyle(g_display, g_gc,
2180                          NOTIMP("mix %d\n", mixmode);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2181          }          XSetStipple(g_display, g_gc, (Pixmap) glyph);
2182            XSetTSOrigin(g_display, g_gc, x, y);
2183    
2184            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2185    
2186            XSetFillStyle(g_display, g_gc, FillSolid);
2187    }
2188    
2189    #define DO_GLYPH(ttext,idx) \
2190    {\
2191      glyph = cache_get_font (font, ttext[idx]);\
2192      if (!(flags & TEXT2_IMPLICIT_X))\
2193      {\
2194        xyoffset = ttext[++idx];\
2195        if ((xyoffset & 0x80))\
2196        {\
2197          if (flags & TEXT2_VERTICAL)\
2198            y += ttext[idx+1] | (ttext[idx+2] << 8);\
2199          else\
2200            x += ttext[idx+1] | (ttext[idx+2] << 8);\
2201          idx += 2;\
2202        }\
2203        else\
2204        {\
2205          if (flags & TEXT2_VERTICAL)\
2206            y += xyoffset;\
2207          else\
2208            x += xyoffset;\
2209        }\
2210      }\
2211      if (glyph != NULL)\
2212      {\
2213        x1 = x + glyph->offset;\
2214        y1 = y + glyph->baseline;\
2215        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2216        XSetTSOrigin(g_display, g_gc, x1, y1);\
2217        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2218        if (flags & TEXT2_IMPLICIT_X)\
2219          x += glyph->width;\
2220      }\
2221  }  }
2222    
2223  void  void
2224  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,
2225               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2226               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
2227               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
2228  {  {
2229          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2230          int i, xyoffset;          int i, j, xyoffset, x1, y1;
2231            DATABLOB *entry;
2232    
2233          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(bgcolour);
2234          XSetForeground(display, gc, Ctrans(bgcolour));  
2235            /* Sometimes, the boxcx value is something really large, like
2236               32691. This makes XCopyArea fail with Xvnc. The code below
2237               is a quick fix. */
2238            if (boxx + boxcx > g_width)
2239                    boxcx = g_width - boxx;
2240    
2241          if (boxcx > 1)          if (boxcx > 1)
2242                  XFillRectangle(display, wnd, gc, boxx, boxy, boxcx, boxcy);          {
2243                    FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2244            }
2245          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++)  
2246          {          {
2247                  glyph = cache_get_font(font, text[i]);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2248            }
2249    
2250                  if (!(flags & TEXT2_IMPLICIT_X))          SET_FOREGROUND(fgcolour);
2251            SET_BACKGROUND(bgcolour);
2252            XSetFillStyle(g_display, g_gc, FillStippled);
2253    
2254            /* Paint text, character by character */
2255            for (i = 0; i < length;)
2256            {
2257                    switch (text[i])
2258                  {                  {
2259                          xyoffset = text[++i];                          case 0xff:
2260                          if ((xyoffset & 0x80))                                  if (i + 2 < length)
2261                          {                                          cache_put_text(text[i + 1], text, text[i + 2]);
                                 if (flags & 0x04)       /* vertical text */  
                                         y += text[++i] | (text[++i] << 8);  
2262                                  else                                  else
2263                                          x += text[++i] | (text[++i] << 8);                                  {
2264                          }                                          error("this shouldn't be happening\n");
2265                          else                                          exit(1);
2266                          {                                  }
2267                                  if (flags & 0x04)       /* vertical text */                                  /* this will move pointer from start to first character after FF command */
2268                                          y += xyoffset;                                  length -= i + 3;
2269                                    text = &(text[i + 3]);
2270                                    i = 0;
2271                                    break;
2272    
2273                            case 0xfe:
2274                                    entry = cache_get_text(text[i + 1]);
2275                                    if (entry != NULL)
2276                                    {
2277                                            if ((((uint8 *) (entry->data))[1] ==
2278                                                 0) && (!(flags & TEXT2_IMPLICIT_X)))
2279                                            {
2280                                                    if (flags & TEXT2_VERTICAL)
2281                                                            y += text[i + 2];
2282                                                    else
2283                                                            x += text[i + 2];
2284                                            }
2285                                            for (j = 0; j < entry->size; j++)
2286                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
2287                                    }
2288                                    if (i + 2 < length)
2289                                            i += 3;
2290                                  else                                  else
2291                                          x += xyoffset;                                          i += 2;
2292                          }                                  length -= i;
2293                                    /* this will move pointer from start to first character after FE command */
2294                                    text = &(text[i]);
2295                                    i = 0;
2296                                    break;
2297    
2298                            default:
2299                                    DO_GLYPH(text, i);
2300                                    i++;
2301                                    break;
2302                  }                  }
2303                  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);  
2304    
2305                          if (flags & TEXT2_IMPLICIT_X)          XSetFillStyle(g_display, g_gc, FillSolid);
2306                                  x += glyph->width;  
2307                  }          if (g_ownbackstore)
2308            {
2309                    if (boxcx > 1)
2310                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2311                                      boxy, boxcx, boxcy, boxx, boxy);
2312                    else
2313                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2314                                      clipy, clipcx, clipcy, clipx, clipy);
2315          }          }
2316  }  }
2317    
# Line 887  ui_desktop_save(uint32 offset, int x, in Line 2321  ui_desktop_save(uint32 offset, int x, in
2321          Pixmap pix;          Pixmap pix;
2322          XImage *image;          XImage *image;
2323    
2324          pix = XCreatePixmap(display, wnd, cx, cy, depth);          if (g_ownbackstore)
2325          xwin_set_function(ROP2_COPY);          {
2326                    image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
2327          XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);          }
2328          image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);          else
2329            {
2330                    pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2331                    XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
2332                    image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2333                    XFreePixmap(g_display, pix);
2334            }
2335    
2336          offset *= bpp/8;          offset *= g_bpp / 8;
2337          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);  
2338    
2339          XDestroyImage(image);          XDestroyImage(image);
         XFreePixmap(display, pix);  
2340  }  }
2341    
2342  void  void
# Line 907  ui_desktop_restore(uint32 offset, int x, Line 2345  ui_desktop_restore(uint32 offset, int x,
2345          XImage *image;          XImage *image;
2346          uint8 *data;          uint8 *data;
2347    
2348          offset *= bpp/8;          offset *= g_bpp / 8;
2349          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2350          if (data == NULL)          if (data == NULL)
2351                  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  
2352    
2353  static uint8 *          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2354  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;)}  
                 }  
         }  
2355    
2356  #else /* bigendian-compiled */          if (g_ownbackstore)
         if (screen_msbfirst)  
2357          {          {
2358                  /* big-endian screen */                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2359                  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;)}  
                 }  
2360          }          }
2361          else          else
2362          {          {
2363                  /* 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;)}  
                 }  
2364          }          }
 #endif  
2365    
2366          return d2;          XFree(image);
2367    }
2368    
2369    /* these do nothing here but are used in uiports */
2370    void
2371    ui_begin_update(void)
2372    {
2373    }
2374    
2375    void
2376    ui_end_update(void)
2377    {
2378  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26