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

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

  ViewVC Help
Powered by ViewVC 1.1.26