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

Legend:
Removed from v.7  
changed lines
  Added in v.801

  ViewVC Help
Powered by ViewVC 1.1.26