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

Legend:
Removed from v.6  
changed lines
  Added in v.677

  ViewVC Help
Powered by ViewVC 1.1.26