/[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 753 by stargo, Mon Aug 23 11:13:50 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 BOOL g_sendmotion;
34    extern BOOL g_fullscreen;
35    extern BOOL g_grab_keyboard;
36    extern BOOL g_hide_decorations;
37    extern char g_title[];
38    extern int g_server_bpp;
39    extern int g_win_button_size;
40    
41    Display *g_display;
42    Time g_last_gesturetime;
43    static int g_x_socket;
44    static Screen *g_screen;
45    Window g_wnd;
46    extern uint32 g_embed_wnd;
47    BOOL g_enable_compose = False;
48    BOOL g_Unobscured;              /* used for screenblt */
49    static GC g_gc = NULL;
50    static GC g_create_bitmap_gc = NULL;
51    static GC g_create_glyph_gc = NULL;
52    static Visual *g_visual;
53    static int g_depth;
54    static int g_bpp;
55    static XIM g_IM;
56    static XIC g_IC;
57    static XModifierKeymap *g_mod_map;
58    static Cursor g_current_cursor;
59    static HCURSOR g_null_cursor = NULL;
60    static Atom g_protocol_atom, g_kill_atom;
61    static BOOL g_focused;
62    static BOOL g_mouse_in_wnd;
63    static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */
64    
65    /* endianness */
66    static BOOL g_host_be;
67    static BOOL g_xserver_be;
68    static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
69    static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
70    
71    /* software backing store */
72    extern BOOL g_ownbackstore;
73    static Pixmap g_backstore = 0;
74    
75    /* Moving in single app mode */
76    static BOOL g_moving_wnd;
77    static int g_move_x_offset = 0;
78    static int g_move_y_offset = 0;
79    
80    #ifdef WITH_RDPSND
81    extern int g_dsp_fd;
82    extern BOOL g_dsp_busy;
83    extern BOOL g_rdpsnd;
84    #endif
85    
86    /* MWM decorations */
87    #define MWM_HINTS_DECORATIONS   (1L << 1)
88    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
89    typedef struct
90    {
91            uint32 flags;
92            uint32 functions;
93            uint32 decorations;
94            sint32 inputMode;
95            uint32 status;
96    }
97    PropMotifWmHints;
98    
99    typedef struct
100    {
101            uint32 red;
102            uint32 green;
103            uint32 blue;
104    }
105    PixelColour;
106    
107    
108    #define FILL_RECTANGLE(x,y,cx,cy)\
109    { \
110            XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
111            if (g_ownbackstore) \
112                    XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
113    }
114    
115    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
116    { \
117            XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
118    }
119    
120    /* colour maps */
121    extern BOOL g_owncolmap;
122    static Colormap g_xcolmap;
123    static uint32 *g_colmap = NULL;
124    
125    #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
126    #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
127    #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
128    
129    static int rop2_map[] = {
130            GXclear,                /* 0 */
131            GXnor,                  /* DPon */
132            GXandInverted,          /* DPna */
133            GXcopyInverted,         /* Pn */
134            GXandReverse,           /* PDna */
135            GXinvert,               /* Dn */
136            GXxor,                  /* DPx */
137            GXnand,                 /* DPan */
138            GXand,                  /* DPa */
139            GXequiv,                /* DPxn */
140            GXnoop,                 /* D */
141            GXorInverted,           /* DPno */
142            GXcopy,                 /* P */
143            GXorReverse,            /* PDno */
144            GXor,                   /* DPo */
145            GXset                   /* 1 */
146    };
147    
148    #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
149    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
150    
151    static void
152    mwm_hide_decorations(void)
153    {
154            PropMotifWmHints motif_hints;
155            Atom hintsatom;
156    
157            /* setup the property */
158            motif_hints.flags = MWM_HINTS_DECORATIONS;
159            motif_hints.decorations = 0;
160    
161            /* get the atom for the property */
162            hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
163            if (!hintsatom)
164            {
165                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
166                    return;
167            }
168    
169            XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
170                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
171    }
172    
173    static PixelColour
174    split_colour15(uint32 colour)
175    {
176            PixelColour rv;
177            rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7);
178            rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7);
179            rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7);
180            return rv;
181    }
182    
183    static PixelColour
184    split_colour16(uint32 colour)
185    {
186            PixelColour rv;
187            rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7);
188            rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3);
189            rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7);
190            return rv;
191    }
192    
193    static PixelColour
194    split_colour24(uint32 colour)
195    {
196            PixelColour rv;
197            rv.blue = (colour & 0xff0000) >> 16;
198            rv.green = (colour & 0x00ff00) >> 8;
199            rv.red = (colour & 0x0000ff);
200            return rv;
201    }
202    
203    static uint32
204    make_colour(PixelColour pc)
205    {
206            return (((pc.red >> g_red_shift_r) << g_red_shift_l)
207                    | ((pc.green >> g_green_shift_r) << g_green_shift_l)
208                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l));
209    }
210    
211    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
212    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
213    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
214                            x = (x << 16) | (x >> 16); }
215    
216    static uint32
217    translate_colour(uint32 colour)
218    {
219            PixelColour pc;
220            switch (g_server_bpp)
221            {
222                    case 15:
223                            pc = split_colour15(colour);
224                            break;
225                    case 16:
226                            pc = split_colour16(colour);
227                            break;
228                    case 24:
229                            pc = split_colour24(colour);
230                            break;
231            }
232            return make_colour(pc);
233    }
234    
235    /* indent is confused by UNROLL8 */
236    /* *INDENT-OFF* */
237    
238    /* repeat and unroll, similar to bitmap.c */
239    /* potentialy any of the following translate */
240    /* functions can use repeat but just doing */
241    /* the most common ones */
242    
243    #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
244    /* 2 byte output repeat */
245    #define REPEAT2(stm) \
246    { \
247            while (out <= end - 8 * 2) \
248                    UNROLL8(stm) \
249            while (out < end) \
250                    { stm } \
251    }
252    /* 4 byte output repeat */
253    #define REPEAT4(stm) \
254    { \
255            while (out <= end - 8 * 4) \
256                    UNROLL8(stm) \
257            while (out < end) \
258                    { stm } \
259    }
260    
261    static void
262    translate8to8(uint8 * data, uint8 * out, uint8 * end)
263    {
264            while (out < end)
265                    *(out++) = (uint8) g_colmap[*(data++)];
266    }
267    
268    static void
269    translate8to16(uint8 * data, uint8 * out, uint8 * end)
270    {
271            uint16 value;
272    
273            if (g_arch_match)
274            {
275                    REPEAT2
276                    (
277                            *((uint16 *) out) = g_colmap[*(data++)];
278                            out += 2;
279                    )
280            }
281            else if (g_xserver_be)
282            {
283                    while (out < end)
284                    {
285                            value = (uint16) g_colmap[*(data++)];
286                            *(out++) = value >> 8;
287                            *(out++) = value;
288                    }
289            }
290            else
291            {
292                    while (out < end)
293                    {
294                            value = (uint16) g_colmap[*(data++)];
295                            *(out++) = value;
296                            *(out++) = value >> 8;
297                    }
298            }
299    }
300    
301    /* little endian - conversion happens when colourmap is built */
302    static void
303    translate8to24(uint8 * data, uint8 * out, uint8 * end)
304    {
305            uint32 value;
306    
307            if (g_xserver_be)
308            {
309                    while (out < end)
310                    {
311                            value = g_colmap[*(data++)];
312                            *(out++) = value >> 16;
313                            *(out++) = value >> 8;
314                            *(out++) = value;
315                    }
316            }
317            else
318            {
319                    while (out < end)
320                    {
321                            value = g_colmap[*(data++)];
322                            *(out++) = value;
323                            *(out++) = value >> 8;
324                            *(out++) = value >> 16;
325                    }
326            }
327    }
328    
329    static void
330    translate8to32(uint8 * data, uint8 * out, uint8 * end)
331    {
332            uint32 value;
333    
334            if (g_arch_match)
335            {
336                    REPEAT4
337                    (
338                            *((uint32 *) out) = g_colmap[*(data++)];
339                            out += 4;
340                    )
341            }
342            else if (g_xserver_be)
343            {
344                    while (out < end)
345                    {
346                            value = g_colmap[*(data++)];
347                            *(out++) = value >> 24;
348                            *(out++) = value >> 16;
349                            *(out++) = value >> 8;
350                            *(out++) = value;
351                    }
352            }
353            else
354            {
355                    while (out < end)
356                    {
357                            value = g_colmap[*(data++)];
358                            *(out++) = value;
359                            *(out++) = value >> 8;
360                            *(out++) = value >> 16;
361                            *(out++) = value >> 24;
362                    }
363            }
364    }
365    
366    /* *INDENT-ON* */
367    
368    static void
369    translate15to16(uint16 * data, uint8 * out, uint8 * end)
370    {
371            uint16 pixel;
372            uint16 value;
373    
374            while (out < end)
375            {
376                    pixel = *(data++);
377    
378                    if (g_host_be)
379                    {
380                            BSWAP16(pixel);
381                    }
382    
383                    value = make_colour(split_colour15(pixel));
384    
385                    if (g_xserver_be)
386                    {
387                            *(out++) = value >> 8;
388                            *(out++) = value;
389                    }
390                    else
391                    {
392                            *(out++) = value;
393                            *(out++) = value >> 8;
394                    }
395            }
396    }
397    
398    static void
399    translate15to24(uint16 * data, uint8 * out, uint8 * end)
400    {
401            uint32 value;
402            uint16 pixel;
403    
404            while (out < end)
405            {
406                    pixel = *(data++);
407    
408                    if (g_host_be)
409                    {
410                            BSWAP16(pixel);
411                    }
412    
413                    value = make_colour(split_colour15(pixel));
414                    if (g_xserver_be)
415                    {
416                            *(out++) = value >> 16;
417                            *(out++) = value >> 8;
418                            *(out++) = value;
419                    }
420                    else
421                    {
422                            *(out++) = value;
423                            *(out++) = value >> 8;
424                            *(out++) = value >> 16;
425                    }
426            }
427    }
428    
429    static void
430    translate15to32(uint16 * data, uint8 * out, uint8 * end)
431    {
432            uint16 pixel;
433            uint32 value;
434    
435            while (out < end)
436            {
437                    pixel = *(data++);
438    
439                    if (g_host_be)
440                    {
441                            BSWAP16(pixel);
442                    }
443    
444                    value = make_colour(split_colour15(pixel));
445    
446                    if (g_xserver_be)
447                    {
448                            *(out++) = value >> 24;
449                            *(out++) = value >> 16;
450                            *(out++) = value >> 8;
451                            *(out++) = value;
452                    }
453                    else
454                    {
455                            *(out++) = value;
456                            *(out++) = value >> 8;
457                            *(out++) = value >> 16;
458                            *(out++) = value >> 24;
459                    }
460            }
461    }
462    
463    static void
464    translate16to16(uint16 * data, uint8 * out, uint8 * end)
465    {
466            uint16 pixel;
467            uint16 value;
468    
469            while (out < end)
470            {
471                    pixel = *(data++);
472    
473                    if (g_host_be)
474                    {
475                            BSWAP16(pixel);
476                    }
477    
478                    value = make_colour(split_colour16(pixel));
479    
480                    if (g_xserver_be)
481                    {
482                            *(out++) = value >> 8;
483                            *(out++) = value;
484                    }
485                    else
486                    {
487                            *(out++) = value;
488                            *(out++) = value >> 8;
489                    }
490            }
491    }
492    
493    static void
494    translate16to24(uint16 * data, uint8 * out, uint8 * end)
495    {
496            uint32 value;
497            uint16 pixel;
498    
499            while (out < end)
500            {
501                    pixel = *(data++);
502    
503                    if (g_host_be)
504                    {
505                            BSWAP16(pixel);
506                    }
507    
508                    value = make_colour(split_colour16(pixel));
509    
510                    if (g_xserver_be)
511                    {
512                            *(out++) = value >> 16;
513                            *(out++) = value >> 8;
514                            *(out++) = value;
515                    }
516                    else
517                    {
518                            *(out++) = value;
519                            *(out++) = value >> 8;
520                            *(out++) = value >> 16;
521                    }
522            }
523    }
524    
525    static void
526    translate16to32(uint16 * data, uint8 * out, uint8 * end)
527    {
528            uint16 pixel;
529            uint32 value;
530    
531            while (out < end)
532            {
533                    pixel = *(data++);
534    
535                    if (g_host_be)
536                    {
537                            BSWAP16(pixel);
538                    }
539    
540                    value = make_colour(split_colour16(pixel));
541    
542                    if (g_xserver_be)
543                    {
544                            *(out++) = value >> 24;
545                            *(out++) = value >> 16;
546                            *(out++) = value >> 8;
547                            *(out++) = value;
548                    }
549                    else
550                    {
551                            *(out++) = value;
552                            *(out++) = value >> 8;
553                            *(out++) = value >> 16;
554                            *(out++) = value >> 24;
555                    }
556            }
557    }
558    
559    static void
560    translate24to16(uint8 * data, uint8 * out, uint8 * end)
561    {
562            uint32 pixel = 0;
563            uint16 value;
564            while (out < end)
565            {
566                    pixel = *(data++) << 16;
567                    pixel |= *(data++) << 8;
568                    pixel |= *(data++);
569    
570                    value = (uint16) make_colour(split_colour24(pixel));
571    
572                    if (g_xserver_be)
573                    {
574                            *(out++) = value >> 8;
575                            *(out++) = value;
576                    }
577                    else
578                    {
579                            *(out++) = value;
580                            *(out++) = value >> 8;
581                    }
582            }
583    }
584    
585    static void
586    translate24to24(uint8 * data, uint8 * out, uint8 * end)
587    {
588            uint32 pixel;
589            uint32 value;
590    
591            while (out < end)
592            {
593                    pixel = *(data++) << 16;
594                    pixel |= *(data++) << 8;
595                    pixel |= *(data++);
596    
597                    value = make_colour(split_colour24(pixel));
598    
599                    if (g_xserver_be)
600                    {
601                            *(out++) = value >> 16;
602                            *(out++) = value >> 8;
603                            *(out++) = value;
604                    }
605                    else
606                    {
607                            *(out++) = value;
608                            *(out++) = value >> 8;
609                            *(out++) = value >> 16;
610                    }
611            }
612    }
613    
614    static void
615    translate24to32(uint8 * data, uint8 * out, uint8 * end)
616    {
617            uint32 pixel;
618            uint32 value;
619    
620            while (out < end)
621            {
622                    pixel = *(data++) << 16;
623                    pixel |= *(data++) << 8;
624                    pixel |= *(data++);
625    
626                    value = make_colour(split_colour24(pixel));
627    
628                    if (g_xserver_be)
629                    {
630                            *(out++) = value >> 24;
631                            *(out++) = value >> 16;
632                            *(out++) = value >> 8;
633                            *(out++) = value;
634                    }
635                    else
636                    {
637                            *(out++) = value;
638                            *(out++) = value >> 8;
639                            *(out++) = value >> 16;
640                            *(out++) = value >> 24;
641                    }
642            }
643    }
644    
645    static uint8 *
646    translate_image(int width, int height, uint8 * data)
647    {
648            int size;
649            uint8 *out;
650            uint8 *end;
651    
652            /* if server and xserver bpp match, */
653            /* and arch(endian) matches, no need to translate */
654            /* just return data */
655            if (g_arch_match)
656            {
657                    if (g_depth == 15 && g_server_bpp == 15)
658                            return data;
659                    if (g_depth == 16 && g_server_bpp == 16)
660                            return data;
661            }
662    
663            size = width * height * (g_bpp / 8);
664            out = (uint8 *) xmalloc(size);
665            end = out + size;
666    
667            switch (g_server_bpp)
668            {
669                    case 24:
670                            switch (g_bpp)
671                            {
672                                    case 32:
673                                            translate24to32(data, out, end);
674                                            break;
675                                    case 24:
676                                            translate24to24(data, out, end);
677                                            break;
678                                    case 16:
679                                            translate24to16(data, out, end);
680                                            break;
681                            }
682                            break;
683                    case 16:
684                            switch (g_bpp)
685                            {
686                                    case 32:
687                                            translate16to32((uint16 *) data, out, end);
688                                            break;
689                                    case 24:
690                                            translate16to24((uint16 *) data, out, end);
691                                            break;
692                                    case 16:
693                                            translate16to16((uint16 *) data, out, end);
694                                            break;
695                            }
696                            break;
697                    case 15:
698                            switch (g_bpp)
699                            {
700                                    case 32:
701                                            translate15to32((uint16 *) data, out, end);
702                                            break;
703                                    case 24:
704                                            translate15to24((uint16 *) data, out, end);
705                                            break;
706                                    case 16:
707                                            translate15to16((uint16 *) data, out, end);
708                                            break;
709                            }
710                            break;
711                    case 8:
712                            switch (g_bpp)
713                            {
714                                    case 8:
715                                            translate8to8(data, out, end);
716                                            break;
717                                    case 16:
718                                            translate8to16(data, out, end);
719                                            break;
720                                    case 24:
721                                            translate8to24(data, out, end);
722                                            break;
723                                    case 32:
724                                            translate8to32(data, out, end);
725                                            break;
726                            }
727                            break;
728            }
729            return out;
730    }
731    
732    BOOL
733    get_key_state(unsigned int state, uint32 keysym)
734    {
735            int modifierpos, key, keysymMask = 0;
736            int offset;
737    
738            KeyCode keycode = XKeysymToKeycode(g_display, keysym);
739    
740            if (keycode == NoSymbol)
741                    return False;
742    
743            for (modifierpos = 0; modifierpos < 8; modifierpos++)
744            {
745                    offset = g_mod_map->max_keypermod * modifierpos;
746    
747                    for (key = 0; key < g_mod_map->max_keypermod; key++)
748                    {
749                            if (g_mod_map->modifiermap[offset + key] == keycode)
750                                    keysymMask |= 1 << modifierpos;
751                    }
752            }
753    
754            return (state & keysymMask) ? True : False;
755    }
756    
757    static void
758    calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
759    {
760            *shift_l = ffs(mask) - 1;
761            mask >>= *shift_l;
762            *shift_r = 8 - ffs(mask & ~(mask >> 1));
763    }
764    
765    BOOL
766    ui_init(void)
767    {
768            XVisualInfo vi;
769            XPixmapFormatValues *pfm;
770            uint16 test;
771            int i, screen_num, nvisuals;
772            XVisualInfo *vmatches = NULL;
773            XVisualInfo template;
774            Bool TrueColorVisual = False;
775    
776            g_display = XOpenDisplay(NULL);
777            if (g_display == NULL)
778            {
779                    error("Failed to open display: %s\n", XDisplayName(NULL));
780                    return False;
781            }
782    
783            screen_num = DefaultScreen(g_display);
784            g_x_socket = ConnectionNumber(g_display);
785            g_screen = ScreenOfDisplay(g_display, screen_num);
786            g_depth = DefaultDepthOfScreen(g_screen);
787    
788            /* Search for best TrueColor depth */
789            template.class = TrueColor;
790            vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);
791    
792            nvisuals--;
793            while (nvisuals >= 0)
794            {
795                    if ((vmatches + nvisuals)->depth > g_depth)
796                    {
797                            g_depth = (vmatches + nvisuals)->depth;
798                    }
799                    nvisuals--;
800                    TrueColorVisual = True;
801            }
802    
803            test = 1;
804            g_host_be = !(BOOL) (*(uint8 *) (&test));
805            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
806    
807            if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))
808            {
809                    /* we use a colourmap, so the default visual should do */
810                    g_visual = DefaultVisualOfScreen(g_screen);
811                    g_depth = DefaultDepthOfScreen(g_screen);
812    
813                    /* Do not allocate colours on a TrueColor visual */
814                    if (g_visual->class == TrueColor)
815                    {
816                            g_owncolmap = False;
817                    }
818            }
819            else
820            {
821                    /* need a truecolour visual */
822                    if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))
823                    {
824                            error("The display does not support true colour - high colour support unavailable.\n");
825                            return False;
826                    }
827    
828                    g_visual = vi.visual;
829                    g_owncolmap = False;
830                    calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);
831                    calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);
832                    calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);
833    
834                    /* if RGB video and averything is little endian */
835                    if (vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask)
836                            if (!g_xserver_be && !g_host_be)
837                                    g_arch_match = True;
838            }
839    
840            pfm = XListPixmapFormats(g_display, &i);
841            if (pfm != NULL)
842            {
843                    /* Use maximum bpp for this depth - this is generally
844                       desirable, e.g. 24 bits->32 bits. */
845                    while (i--)
846                    {
847                            if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
848                            {
849                                    g_bpp = pfm[i].bits_per_pixel;
850                            }
851                    }
852                    XFree(pfm);
853            }
854    
855            if (g_bpp < 8)
856            {
857                    error("Less than 8 bpp not currently supported.\n");
858                    XCloseDisplay(g_display);
859                    return False;
860            }
861    
862            if (!g_owncolmap)
863            {
864                    g_xcolmap =
865                            XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
866                                            AllocNone);
867                    if (g_depth <= 8)
868                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
869            }
870    
871            if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
872            {
873                    warning("External BackingStore not available, using internal\n");
874                    g_ownbackstore = True;
875            }
876    
877            /*
878             * Determine desktop size
879             */
880            if (g_fullscreen)
881            {
882                    g_width = WidthOfScreen(g_screen);
883                    g_height = HeightOfScreen(g_screen);
884            }
885            else if (g_width < 0)
886            {
887                    /* Percent of screen */
888                    g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
889                    g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
890            }
891            else if (g_width == 0)
892            {
893                    /* Fetch geometry from _NET_WORKAREA */
894                    uint32 x, y, cx, cy;
895    
896                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
897                    {
898                            g_width = cx;
899                            g_height = cy;
900                    }
901                    else
902                    {
903                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
904                            g_width = 800;
905                            g_height = 600;
906                    }
907            }
908    
909            /* make sure width is a multiple of 4 */
910            g_width = (g_width + 3) & ~3;
911    
912            g_mod_map = XGetModifierMapping(g_display);
913    
914            xkeymap_init();
915    
916            if (g_enable_compose)
917                    g_IM = XOpenIM(g_display, NULL, NULL, NULL);
918    
919            xclip_init();
920    
921            DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));
922    
923            return True;
924    }
925    
926    void
927    ui_deinit(void)
928    {
929            if (g_IM != NULL)
930                    XCloseIM(g_IM);
931    
932            if (g_null_cursor != NULL)
933                    ui_destroy_cursor(g_null_cursor);
934    
935            XFreeModifiermap(g_mod_map);
936    
937            if (g_ownbackstore)
938                    XFreePixmap(g_display, g_backstore);
939    
940            XFreeGC(g_display, g_gc);
941            XCloseDisplay(g_display);
942            g_display = NULL;
943    }
944    
945    BOOL
946    ui_create_window(void)
947    {
948            uint8 null_pointer_mask[1] = { 0x80 };
949            uint8 null_pointer_data[4] = { 0x00, 0x00, 0x00, 0x00 };
950            XSetWindowAttributes attribs;
951            XClassHint *classhints;
952            XSizeHints *sizehints;
953            int wndwidth, wndheight;
954            long input_mask, ic_input_mask;
955            XEvent xevent;
956    
957            wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
958            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
959    
960            attribs.background_pixel = BlackPixelOfScreen(g_screen);
961            attribs.border_pixel = WhitePixelOfScreen(g_screen);
962            attribs.backing_store = g_ownbackstore ? NotUseful : Always;
963            attribs.override_redirect = g_fullscreen;
964            attribs.colormap = g_xcolmap;
965    
966            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
967                                  0, g_depth, InputOutput, g_visual,
968                                  CWBackPixel | CWBackingStore | CWOverrideRedirect |
969                                  CWColormap | CWBorderPixel, &attribs);
970    
971            if (g_gc == NULL)
972                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
973    
974            if (g_create_bitmap_gc == NULL)
975                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
976    
977            if ((g_ownbackstore) && (g_backstore == 0))
978            {
979                    g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
980    
981                    /* clear to prevent rubbish being exposed at startup */
982                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
983                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
984            }
985    
986            XStoreName(g_display, g_wnd, g_title);
987    
988            if (g_hide_decorations)
989                    mwm_hide_decorations();
990    
991            classhints = XAllocClassHint();
992            if (classhints != NULL)
993            {
994                    classhints->res_name = classhints->res_class = "rdesktop";
995                    XSetClassHint(g_display, g_wnd, classhints);
996                    XFree(classhints);
997            }
998    
999            sizehints = XAllocSizeHints();
1000            if (sizehints)
1001            {
1002                    sizehints->flags = PMinSize | PMaxSize;
1003                    sizehints->min_width = sizehints->max_width = g_width;
1004                    sizehints->min_height = sizehints->max_height = g_height;
1005                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1006                    XFree(sizehints);
1007            }
1008    
1009            if (g_embed_wnd)
1010            {
1011                    XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1012            }
1013    
1014            input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1015                    VisibilityChangeMask | FocusChangeMask;
1016    
1017            if (g_sendmotion)
1018                    input_mask |= PointerMotionMask;
1019            if (g_ownbackstore)
1020                    input_mask |= ExposureMask;
1021            if (g_fullscreen || g_grab_keyboard)
1022                    input_mask |= EnterWindowMask;
1023            if (g_grab_keyboard)
1024                    input_mask |= LeaveWindowMask;
1025    
1026            if (g_IM != NULL)
1027            {
1028                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1029                                     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1030    
1031                    if ((g_IC != NULL)
1032                        && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1033                            input_mask |= ic_input_mask;
1034            }
1035    
1036            XSelectInput(g_display, g_wnd, input_mask);
1037            XMapWindow(g_display, g_wnd);
1038    
1039            /* wait for VisibilityNotify */
1040            do
1041            {
1042                    XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1043            }
1044            while (xevent.type != VisibilityNotify);
1045            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1046    
1047            g_focused = False;
1048            g_mouse_in_wnd = False;
1049    
1050            /* handle the WM_DELETE_WINDOW protocol */
1051            g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1052            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1053            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1054    
1055            /* create invisible 1x1 cursor to be used as null cursor */
1056            if (g_null_cursor == NULL)
1057                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1058    
1059            return True;
1060    }
1061    
1062    void
1063    ui_resize_window()
1064    {
1065            XSizeHints *sizehints;
1066            Pixmap bs;
1067    
1068            sizehints = XAllocSizeHints();
1069            if (sizehints)
1070            {
1071                    sizehints->flags = PMinSize | PMaxSize;
1072                    sizehints->min_width = sizehints->max_width = g_width;
1073                    sizehints->min_height = sizehints->max_height = g_height;
1074                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1075                    XFree(sizehints);
1076            }
1077    
1078            if (!(g_fullscreen || g_embed_wnd))
1079            {
1080                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1081            }
1082    
1083            /* create new backstore pixmap */
1084            if (g_backstore != 0)
1085            {
1086                    bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1087                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1088                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1089                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1090                    XFreePixmap(g_display, g_backstore);
1091                    g_backstore = bs;
1092            }
1093    }
1094    
1095    void
1096    ui_destroy_window(void)
1097    {
1098            if (g_IC != NULL)
1099                    XDestroyIC(g_IC);
1100    
1101            XDestroyWindow(g_display, g_wnd);
1102    }
1103    
1104    void
1105    xwin_toggle_fullscreen(void)
1106    {
1107            Pixmap contents = 0;
1108    
1109            if (!g_ownbackstore)
1110            {
1111                    /* need to save contents of window */
1112                    contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1113                    XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1114            }
1115    
1116            ui_destroy_window();
1117            g_fullscreen = !g_fullscreen;
1118            ui_create_window();
1119    
1120            XDefineCursor(g_display, g_wnd, g_current_cursor);
1121    
1122            if (!g_ownbackstore)
1123            {
1124                    XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1125                    XFreePixmap(g_display, contents);
1126            }
1127    }
1128    
1129    /* Process all events in Xlib queue
1130       Returns 0 after user quit, 1 otherwise */
1131    static int
1132    xwin_process_events(void)
1133    {
1134            XEvent xevent;
1135            KeySym keysym;
1136            uint16 button, flags;
1137            uint32 ev_time;
1138            key_translation tr;
1139            char str[256];
1140            Status status;
1141    
1142            while (XPending(g_display) > 0)
1143            {
1144                    XNextEvent(g_display, &xevent);
1145    
1146                    if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1147                    {
1148                            DEBUG_KBD(("Filtering event\n"));
1149                            continue;
1150                    }
1151    
1152                    flags = 0;
1153    
1154                    switch (xevent.type)
1155                    {
1156                            case VisibilityNotify:
1157                                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1158                                    break;
1159                            case ClientMessage:
1160                                    /* the window manager told us to quit */
1161                                    if ((xevent.xclient.message_type == g_protocol_atom)
1162                                        && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1163                                            /* Quit */
1164                                            return 0;
1165                                    break;
1166    
1167                            case KeyPress:
1168                                    g_last_gesturetime = xevent.xkey.time;
1169                                    if (g_IC != NULL)
1170                                            /* Multi_key compatible version */
1171                                    {
1172                                            XmbLookupString(g_IC,
1173                                                            &xevent.xkey, str, sizeof(str), &keysym,
1174                                                            &status);
1175                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1176                                            {
1177                                                    error("XmbLookupString failed with status 0x%x\n",
1178                                                          status);
1179                                                    break;
1180                                            }
1181                                    }
1182                                    else
1183                                    {
1184                                            /* Plain old XLookupString */
1185                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1186                                            XLookupString((XKeyEvent *) & xevent,
1187                                                          str, sizeof(str), &keysym, NULL);
1188                                    }
1189    
1190                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1191                                               get_ksname(keysym)));
1192    
1193                                    ev_time = time(NULL);
1194                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1195                                            break;
1196    
1197                                    tr = xkeymap_translate_key(keysym,
1198                                                               xevent.xkey.keycode, xevent.xkey.state);
1199    
1200                                    if (tr.scancode == 0)
1201                                            break;
1202    
1203                                    save_remote_modifiers(tr.scancode);
1204                                    ensure_remote_modifiers(ev_time, tr);
1205                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1206                                    restore_remote_modifiers(ev_time, tr.scancode);
1207    
1208                                    break;
1209    
1210                            case KeyRelease:
1211                                    g_last_gesturetime = xevent.xkey.time;
1212                                    XLookupString((XKeyEvent *) & xevent, str,
1213                                                  sizeof(str), &keysym, NULL);
1214    
1215                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1216                                               get_ksname(keysym)));
1217    
1218                                    ev_time = time(NULL);
1219                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1220                                            break;
1221    
1222                                    tr = xkeymap_translate_key(keysym,
1223                                                               xevent.xkey.keycode, xevent.xkey.state);
1224    
1225                                    if (tr.scancode == 0)
1226                                            break;
1227    
1228                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
1229                                    break;
1230    
1231                            case ButtonPress:
1232                                    flags = MOUSE_FLAG_DOWN;
1233                                    /* fall through */
1234    
1235                            case ButtonRelease:
1236                                    g_last_gesturetime = xevent.xbutton.time;
1237                                    button = xkeymap_translate_button(xevent.xbutton.button);
1238                                    if (button == 0)
1239                                            break;
1240    
1241                                    /* If win_button_size is nonzero, enable single app mode */
1242                                    if (xevent.xbutton.y < g_win_button_size)
1243                                    {
1244                                            /* Stop moving window when button is released, regardless of cursor position */
1245                                            if (g_moving_wnd && (xevent.type == ButtonRelease))
1246                                                    g_moving_wnd = False;
1247    
1248                                            /*  Check from right to left: */
1249    
1250                                            if (xevent.xbutton.x >= g_width - g_win_button_size)
1251                                            {
1252                                                    /* The close button, continue */
1253                                                    ;
1254                                            }
1255                                            else if (xevent.xbutton.x >=
1256                                                     g_width - g_win_button_size * 2)
1257                                            {
1258                                                    /* The maximize/restore button. Do not send to
1259                                                       server.  It might be a good idea to change the
1260                                                       cursor or give some other visible indication
1261                                                       that rdesktop inhibited this click */
1262                                                    break;
1263                                            }
1264                                            else if (xevent.xbutton.x >=
1265                                                     g_width - g_win_button_size * 3)
1266                                            {
1267                                                    /* The minimize button. Iconify window. */
1268                                                    XIconifyWindow(g_display, g_wnd,
1269                                                                   DefaultScreen(g_display));
1270                                                    break;
1271                                            }
1272                                            else if (xevent.xbutton.x <= g_win_button_size)
1273                                            {
1274                                                    /* The system menu. Ignore. */
1275                                                    break;
1276                                            }
1277                                            else
1278                                            {
1279                                                    /* The title bar. */
1280                                                    if ((xevent.type == ButtonPress) && !g_fullscreen
1281                                                        && g_hide_decorations)
1282                                                    {
1283                                                            g_moving_wnd = True;
1284                                                            g_move_x_offset = xevent.xbutton.x;
1285                                                            g_move_y_offset = xevent.xbutton.y;
1286                                                    }
1287                                                    break;
1288    
1289                                            }
1290                                    }
1291    
1292                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1293                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1294                                    break;
1295    
1296                            case MotionNotify:
1297                                    if (g_moving_wnd)
1298                                    {
1299                                            XMoveWindow(g_display, g_wnd,
1300                                                        xevent.xmotion.x_root - g_move_x_offset,
1301                                                        xevent.xmotion.y_root - g_move_y_offset);
1302                                            break;
1303                                    }
1304    
1305                                    if (g_fullscreen && !g_focused)
1306                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1307                                                           CurrentTime);
1308                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1309                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1310                                    break;
1311    
1312                            case FocusIn:
1313                                    if (xevent.xfocus.mode == NotifyGrab)
1314                                            break;
1315                                    g_focused = True;
1316                                    reset_modifier_keys();
1317                                    if (g_grab_keyboard && g_mouse_in_wnd)
1318                                            XGrabKeyboard(g_display, g_wnd, True,
1319                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1320                                    break;
1321    
1322                            case FocusOut:
1323                                    if (xevent.xfocus.mode == NotifyUngrab)
1324                                            break;
1325                                    g_focused = False;
1326                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1327                                            XUngrabKeyboard(g_display, CurrentTime);
1328                                    break;
1329    
1330                            case EnterNotify:
1331                                    /* we only register for this event when in fullscreen mode */
1332                                    /* or grab_keyboard */
1333                                    g_mouse_in_wnd = True;
1334                                    if (g_fullscreen)
1335                                    {
1336                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1337                                                           CurrentTime);
1338                                            break;
1339                                    }
1340                                    if (g_focused)
1341                                            XGrabKeyboard(g_display, g_wnd, True,
1342                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1343                                    break;
1344    
1345                            case LeaveNotify:
1346                                    /* we only register for this event when grab_keyboard */
1347                                    g_mouse_in_wnd = False;
1348                                    XUngrabKeyboard(g_display, CurrentTime);
1349                                    break;
1350    
1351                            case Expose:
1352                                    XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1353                                              xevent.xexpose.x, xevent.xexpose.y,
1354                                              xevent.xexpose.width,
1355                                              xevent.xexpose.height,
1356                                              xevent.xexpose.x, xevent.xexpose.y);
1357                                    break;
1358    
1359                            case MappingNotify:
1360                                    /* Refresh keyboard mapping if it has changed. This is important for
1361                                       Xvnc, since it allocates keycodes dynamically */
1362                                    if (xevent.xmapping.request == MappingKeyboard
1363                                        || xevent.xmapping.request == MappingModifier)
1364                                            XRefreshKeyboardMapping(&xevent.xmapping);
1365    
1366                                    if (xevent.xmapping.request == MappingModifier)
1367                                    {
1368                                            XFreeModifiermap(g_mod_map);
1369                                            g_mod_map = XGetModifierMapping(g_display);
1370                                    }
1371                                    break;
1372    
1373                                    /* clipboard stuff */
1374                            case SelectionNotify:
1375                                    xclip_handle_SelectionNotify(&xevent.xselection);
1376                                    break;
1377                            case SelectionRequest:
1378                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1379                                    break;
1380                            case SelectionClear:
1381                                    xclip_handle_SelectionClear();
1382                                    break;
1383                            case PropertyNotify:
1384                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1385                                    break;
1386                    }
1387            }
1388            /* Keep going */
1389            return 1;
1390    }
1391    
1392  HWINDOW ui_create_window(int width, int height)  /* Returns 0 after user quit, 1 otherwise */
1393    int
1394    ui_select(int rdp_socket)
1395  {  {
1396          struct window *wnd;          int n;
1397          Display *display;          fd_set rfds, wfds;
1398          Window window;          struct timeval tv;
1399          int black;          BOOL s_timeout = False;
1400          GC gc;  
1401            while (True)
1402            {
1403                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1404                    /* Process any events already waiting */
1405                    if (!xwin_process_events())
1406                            /* User quit */
1407                            return 0;
1408    
1409                    FD_ZERO(&rfds);
1410                    FD_ZERO(&wfds);
1411                    FD_SET(rdp_socket, &rfds);
1412                    FD_SET(g_x_socket, &rfds);
1413    
1414    #ifdef WITH_RDPSND
1415                    /* FIXME: there should be an API for registering fds */
1416                    if (g_dsp_busy)
1417                    {
1418                            FD_SET(g_dsp_fd, &wfds);
1419                            n = (g_dsp_fd > n) ? g_dsp_fd : n;
1420                    }
1421    #endif
1422                    /* default timeout */
1423                    tv.tv_sec = 60;
1424                    tv.tv_usec = 0;
1425    
1426                    /* add redirection handles */
1427                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1428    
1429                    n++;
1430    
1431                    switch (select(n, &rfds, &wfds, NULL, &tv))
1432                    {
1433                            case -1:
1434                                    error("select: %s\n", strerror(errno));
1435    
1436                            case 0:
1437                                    /* TODO: if tv.tv_sec just times out
1438                                     * we will segfault.
1439                                     * FIXME:
1440                                     */
1441                                    //s_timeout = True;
1442                                    //rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1443                                    continue;
1444                    }
1445    
1446                    rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
1447    
1448    #ifdef WITH_RDPSND
1449                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1450                            wave_out_play();
1451    #endif
1452    
1453                    if (FD_ISSET(rdp_socket, &rfds))
1454                            return 1;
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.753

  ViewVC Help
Powered by ViewVC 1.1.26