/[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 9 by matty, Tue Jul 25 12:34:29 2000 UTC revision 448 by astrand, Wed Aug 27 08:21:53 2003 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 <time.h>
24    #include <errno.h>
25    #include "rdesktop.h"
26    #include "xproto.h"
27    
28    extern int g_width;
29    extern int g_height;
30    extern BOOL g_sendmotion;
31    extern BOOL g_fullscreen;
32    extern BOOL grab_keyboard;
33    extern BOOL hide_decorations;
34    extern char title[];
35    extern int g_server_bpp;
36    extern int win_button_size;
37    BOOL g_enable_compose = False;
38    BOOL g_focused;
39    BOOL g_mouse_in_wnd;
40    
41    Display *display;
42    Time last_gesturetime;
43    static int x_socket;
44    static Screen *screen;
45    Window wnd;
46    static GC gc;
47    static Visual *visual;
48    static int depth;
49    static int bpp;
50    static XIM IM;
51    static XIC IC;
52    static XModifierKeymap *mod_map;
53    static Cursor current_cursor;
54    static Atom protocol_atom, kill_atom;
55    
56    /* endianness */
57    static BOOL host_be;
58    static BOOL xserver_be;
59    
60    /* software backing store */
61    static BOOL ownbackstore;
62    static Pixmap backstore;
63    
64    /* Moving in single app mode */
65    static BOOL moving_wnd;
66    static int move_x_offset = 0;
67    static int move_y_offset = 0;
68    
69    /* MWM decorations */
70    #define MWM_HINTS_DECORATIONS   (1L << 1)
71    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
72    typedef struct
73    {
74            uint32 flags;
75            uint32 functions;
76            uint32 decorations;
77            sint32 inputMode;
78            uint32 status;
79    }
80    PropMotifWmHints;
81    
82    typedef struct
83    {
84            uint32 red;
85            uint32 green;
86            uint32 blue;
87    }
88    PixelColour;
89    
90    
91    #define FILL_RECTANGLE(x,y,cx,cy)\
92    { \
93            XFillRectangle(display, wnd, gc, x, y, cx, cy); \
94            if (ownbackstore) \
95                    XFillRectangle(display, backstore, gc, x, y, cx, cy); \
96    }
97    
98    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
99    { \
100            XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \
101    }
102    
103    /* colour maps */
104    BOOL owncolmap = False;
105    static Colormap xcolmap;
106    static uint32 *colmap = NULL;
107    
108    #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : owncolmap ? col : translate_colour(colmap[col]) )
109    #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
110    #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
111    
112    static int rop2_map[] = {
113            GXclear,                /* 0 */
114            GXnor,                  /* DPon */
115            GXandInverted,          /* DPna */
116            GXcopyInverted,         /* Pn */
117            GXandReverse,           /* PDna */
118            GXinvert,               /* Dn */
119            GXxor,                  /* DPx */
120            GXnand,                 /* DPan */
121            GXand,                  /* DPa */
122            GXequiv,                /* DPxn */
123            GXnoop,                 /* D */
124            GXorInverted,           /* DPno */
125            GXcopy,                 /* P */
126            GXorReverse,            /* PDno */
127            GXor,                   /* DPo */
128            GXset                   /* 1 */
129    };
130    
131    #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
132    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
133    
134  HWINDOW ui_create_window(HCONN conn, int width, int height)  static void
135    mwm_hide_decorations(void)
136  {  {
137          struct window *wnd;          PropMotifWmHints motif_hints;
138          XSetWindowAttributes attribs;          Atom hintsatom;
         Display *display;  
         Visual *visual;  
         Window window;  
         int black;  
         GC gc;  
139    
140          display = XOpenDisplay(NULL);          /* setup the property */
141          if (display == NULL)          motif_hints.flags = MWM_HINTS_DECORATIONS;
142                  return NULL;          motif_hints.decorations = 0;
143    
144            /* get the atom for the property */
145            hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
146            if (!hintsatom)
147            {
148                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
149                    return;
150            }
151    
152          visual = DefaultVisual(display, DefaultScreen(display));          XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
153          black = BlackPixel(display, DefaultScreen(display));                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
154    }
155    
156          attribs.background_pixel = black;  static PixelColour
157          attribs.backing_store = Always;  split_colour15(uint32 colour)
158          window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,  {
159                          width, height, 0, 8, InputOutput, visual,          PixelColour rv;
160                          CWBackingStore | CWBackPixel, &attribs);          rv.red = (colour & 0x7c00) >> 10;
161            rv.red = (rv.red * 0xff) / 0x1f;
162            rv.green = (colour & 0x03e0) >> 5;
163            rv.green = (rv.green * 0xff) / 0x1f;
164            rv.blue = (colour & 0x1f);
165            rv.blue = (rv.blue * 0xff) / 0x1f;
166            return rv;
167    }
168    
169          XStoreName(display, window, "rdesktop");  static PixelColour
170          XMapWindow(display, window);  split_colour16(uint32 colour)
171          XSelectInput(display, window, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);  {
172          XSync(display, True);          PixelColour rv;
173            rv.red = (colour & 0xf800) >> 11;
174            rv.red = (rv.red * 0xff) / 0x1f;
175            rv.green = (colour & 0x07e0) >> 5;
176            rv.green = (rv.green * 0xff) / 0x3f;
177            rv.blue = (colour & 0x001f);
178            rv.blue = (rv.blue * 0xff) / 0x1f;
179            return rv;
180    }
181    
182          gc = XCreateGC(display, window, 0, NULL);  static PixelColour
183    split_colour24(uint32 colour)
184    {
185            PixelColour rv;
186            rv.blue = (colour & 0xff0000) >> 16;
187            rv.green = (colour & 0xff00) >> 8;
188            rv.red = (colour & 0xff);
189            return rv;
190    }
191    
192          wnd = xmalloc(sizeof(struct window));  static uint32
193          wnd->conn = conn;  make_colour16(PixelColour pc)
194          wnd->width = width;  {
195          wnd->height = height;          pc.red = (pc.red * 0x1f) / 0xff;
196          wnd->display = display;          pc.green = (pc.green * 0x3f) / 0xff;
197          wnd->wnd = window;          pc.blue = (pc.blue * 0x1f) / 0xff;
198          wnd->gc = gc;          return (pc.red << 11) | (pc.green << 5) | pc.blue;
199          wnd->visual = visual;  }
200    
201          return wnd;  static uint32
202    make_colour24(PixelColour pc)
203    {
204            return (pc.red << 16) | (pc.green << 8) | pc.blue;
205  }  }
206    
207  void ui_destroy_window(HWINDOW wnd)  static uint32
208    make_colour32(PixelColour pc)
209  {  {
210          XFreeGC(wnd->display, wnd->gc);          return (pc.red << 16) | (pc.green << 8) | pc.blue;
         XDestroyWindow(wnd->display, wnd->wnd);  
         XCloseDisplay(wnd->display);  
211  }  }
212    
213  static uint8 xwin_translate_key(unsigned long key)  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
214    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
215    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
216                            x = (x << 16) | (x >> 16); }
217    
218    static uint32
219    translate_colour(uint32 colour)
220  {  {
221          DEBUG("KEY(code=0x%lx)\n", key);          switch (g_server_bpp)
222            {
223                    case 15:
224                            switch (bpp)
225                            {
226                                    case 16:
227                                            colour = make_colour16(split_colour15(colour));
228                                            break;
229                                    case 24:
230                                            colour = make_colour24(split_colour15(colour));
231                                            break;
232                                    case 32:
233                                            colour = make_colour32(split_colour15(colour));
234                                            break;
235                            }
236                            break;
237                    case 16:
238                            switch (bpp)
239                            {
240                                    case 16:
241                                            break;
242                                    case 24:
243                                            colour = make_colour24(split_colour16(colour));
244                                            break;
245                                    case 32:
246                                            colour = make_colour32(split_colour16(colour));
247                                            break;
248                            }
249                            break;
250                    case 24:
251                            switch (bpp)
252                            {
253                                    case 16:
254                                            colour = make_colour16(split_colour24(colour));
255                                            break;
256                                    case 24:
257                                            break;
258                                    case 32:
259                                            colour = make_colour32(split_colour24(colour));
260                                            break;
261                            }
262                            break;
263            }
264            switch (bpp)
265            {
266                    case 16:
267                            if (host_be != xserver_be)
268                                    BSWAP16(colour);
269                            break;
270    
271                    case 24:
272                            if (xserver_be)
273                                    BSWAP24(colour);
274                            break;
275    
276          if ((key > 8) && (key <= 0x60))                  case 32:
277                  return (key - 8);                          if (host_be != xserver_be)
278                                    BSWAP32(colour);
279                            break;
280            }
281    
282            return colour;
283    }
284    
285          switch (key)  static void
286    translate8to8(uint8 * data, uint8 * out, uint8 * end)
287    {
288            while (out < end)
289                    *(out++) = (uint8) colmap[*(data++)];
290    }
291    
292    static void
293    translate8to16(uint8 * data, uint16 * out, uint16 * end)
294    {
295            while (out < end)
296                    *(out++) = (uint16) colmap[*(data++)];
297    }
298    
299    /* little endian - conversion happens when colourmap is built */
300    static void
301    translate8to24(uint8 * data, uint8 * out, uint8 * end)
302    {
303            uint32 value;
304    
305            while (out < end)
306          {          {
307                  case 0x62: /* left arrow */                  value = colmap[*(data++)];
308                          return 0x48;                  *(out++) = value;
309                  case 0x64: /* up arrow */                  *(out++) = value >> 8;
310                          return 0x4b;                  *(out++) = value >> 16;
                 case 0x66: /* down arrow */  
                         return 0x4d;  
                 case 0x68: /* right arrow */  
                         return 0x50;  
                 case 0x73: /* Windows key */  
                         DEBUG("CHECKPOINT\n");  
311          }          }
312    }
313    
314    static void
315    translate8to32(uint8 * data, uint32 * out, uint32 * end)
316    {
317            while (out < end)
318                    *(out++) = colmap[*(data++)];
319    }
320    
321    /* todo the remaining translate function might need some big endian check ?? */
322    
323          return 0;  static void
324    translate15to16(uint16 * data, uint16 * out, uint16 * end)
325    {
326            while (out < end)
327                    *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
328  }  }
329    
330  static uint16 xwin_translate_mouse(unsigned long button)  static void
331    translate15to24(uint16 * data, uint8 * out, uint8 * end)
332  {  {
333          switch (button)          uint32 value;
334    
335            while (out < end)
336          {          {
337                  case Button1: /* left */                  value = make_colour24(split_colour15(*(data++)));
338                          return MOUSE_FLAG_BUTTON1;                  *(out++) = value;
339                  case Button2: /* middle */                  *(out++) = value >> 8;
340                          return MOUSE_FLAG_BUTTON3;                  *(out++) = value >> 16;
                 case Button3: /* right */  
                         return MOUSE_FLAG_BUTTON2;  
341          }          }
342    }
343    
344          return 0;  static void
345    translate15to32(uint16 * data, uint32 * out, uint32 * end)
346    {
347            while (out < end)
348                    *(out++) = make_colour32(split_colour15(*(data++)));
349  }  }
350    
351  void ui_process_events(HWINDOW wnd, HCONN conn)  static void
352    translate16to16(uint16 * data, uint16 * out, uint16 * end)
353  {  {
354          XEvent event;          while (out < end)
355          uint8 scancode;                  *(out++) = (uint16) (*(data++));
356          uint16 button;  }
357    
         if (wnd == NULL)  
                 return;  
358    
359          while (XCheckWindowEvent(wnd->display, wnd->wnd, 0xffffffff, &event))  static void
360    translate16to24(uint16 * data, uint8 * out, uint8 * end)
361    {
362            uint32 value;
363    
364            while (out < end)
365            {
366                    value = make_colour24(split_colour16(*(data++)));
367                    *(out++) = value;
368                    *(out++) = value >> 8;
369                    *(out++) = value >> 16;
370            }
371    }
372    
373    static void
374    translate16to32(uint16 * data, uint32 * out, uint32 * end)
375    {
376            while (out < end)
377                    *(out++) = make_colour32(split_colour16(*(data++)));
378    }
379    
380    static void
381    translate24to16(uint8 * data, uint16 * out, uint16 * end)
382    {
383            uint32 pixel = 0;
384            while (out < end)
385            {
386                    pixel = *(data++) << 16;
387                    pixel |= *(data++) << 8;
388                    pixel |= *(data++);
389                    *(out++) = (uint16) make_colour16(split_colour24(pixel));
390            }
391    }
392    
393    static void
394    translate24to24(uint8 * data, uint8 * out, uint8 * end)
395    {
396            while (out < end)
397            {
398                    *(out++) = (*(data++));
399            }
400    }
401    
402    static void
403    translate24to32(uint8 * data, uint32 * out, uint32 * end)
404    {
405            uint32 pixel = 0;
406            while (out < end)
407            {
408                    pixel = *(data++);
409                    pixel |= *(data++) << 8;
410                    pixel |= *(data++) << 16;
411                    *(out++) = pixel;
412            }
413    }
414    
415    static uint8 *
416    translate_image(int width, int height, uint8 * data)
417    {
418            int size = width * height * bpp / 8;
419            uint8 *out = (uint8 *) xmalloc(size);
420            uint8 *end = out + size;
421    
422            switch (g_server_bpp)
423            {
424                    case 24:
425                            switch (bpp)
426                            {
427                                    case 32:
428                                            translate24to32(data, (uint32 *) out, (uint32 *) end);
429                                            break;
430                                    case 24:
431                                            translate24to24(data, out, end);
432                                            break;
433                                    case 16:
434                                            translate24to16(data, (uint16 *) out, (uint16 *) end);
435                                            break;
436                            }
437                            break;
438                    case 16:
439                            switch (bpp)
440                            {
441                                    case 32:
442                                            translate16to32((uint16 *) data, (uint32 *) out,
443                                                            (uint32 *) end);
444                                            break;
445                                    case 24:
446                                            translate16to24((uint16 *) data, out, end);
447                                            break;
448                                    case 16:
449                                            translate16to16((uint16 *) data, (uint16 *) out,
450                                                            (uint16 *) end);
451                                            break;
452                            }
453                            break;
454                    case 15:
455                            switch (bpp)
456                            {
457                                    case 32:
458                                            translate15to32((uint16 *) data, (uint32 *) out,
459                                                            (uint32 *) end);
460                                            break;
461                                    case 24:
462                                            translate15to24((uint16 *) data, out, end);
463                                            break;
464                                    case 16:
465                                            translate15to16((uint16 *) data, (uint16 *) out,
466                                                            (uint16 *) end);
467                                            break;
468                            }
469                            break;
470                    case 8:
471                            switch (bpp)
472                            {
473                                    case 8:
474                                            translate8to8(data, out, end);
475                                            break;
476                                    case 16:
477                                            translate8to16(data, (uint16 *) out, (uint16 *) end);
478                                            break;
479                                    case 24:
480                                            translate8to24(data, out, end);
481                                            break;
482                                    case 32:
483                                            translate8to32(data, (uint32 *) out, (uint32 *) end);
484                                            break;
485                            }
486                            break;
487            }
488            return out;
489    }
490    
491    BOOL
492    get_key_state(unsigned int state, uint32 keysym)
493    {
494            int modifierpos, key, keysymMask = 0;
495            int offset;
496    
497            KeyCode keycode = XKeysymToKeycode(display, keysym);
498    
499            if (keycode == NoSymbol)
500                    return False;
501    
502            for (modifierpos = 0; modifierpos < 8; modifierpos++)
503            {
504                    offset = mod_map->max_keypermod * modifierpos;
505    
506                    for (key = 0; key < mod_map->max_keypermod; key++)
507                    {
508                            if (mod_map->modifiermap[offset + key] == keycode)
509                                    keysymMask |= 1 << modifierpos;
510                    }
511            }
512    
513            return (state & keysymMask) ? True : False;
514    }
515    
516    BOOL
517    ui_init(void)
518    {
519            XPixmapFormatValues *pfm;
520            uint16 test;
521            int i;
522    
523            display = XOpenDisplay(NULL);
524            if (display == NULL)
525            {
526                    error("Failed to open display: %s\n", XDisplayName(NULL));
527                    return False;
528            }
529    
530            x_socket = ConnectionNumber(display);
531            screen = DefaultScreenOfDisplay(display);
532            visual = DefaultVisualOfScreen(screen);
533            depth = DefaultDepthOfScreen(screen);
534    
535            pfm = XListPixmapFormats(display, &i);
536            if (pfm != NULL)
537            {
538                    /* Use maximum bpp for this depth - this is generally
539                       desirable, e.g. 24 bits->32 bits. */
540                    while (i--)
541                    {
542                            if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
543                            {
544                                    bpp = pfm[i].bits_per_pixel;
545                            }
546                    }
547                    XFree(pfm);
548            }
549    
550            if (bpp < 8)
551            {
552                    error("Less than 8 bpp not currently supported.\n");
553                    XCloseDisplay(display);
554                    return False;
555            }
556    
557            if (owncolmap != True)
558            {
559                    xcolmap = DefaultColormapOfScreen(screen);
560                    if (depth <= 8)
561                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
562            }
563    
564            gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
565    
566            if (DoesBackingStore(screen) != Always)
567                    ownbackstore = True;
568    
569            test = 1;
570            host_be = !(BOOL) (*(uint8 *) (&test));
571            xserver_be = (ImageByteOrder(display) == MSBFirst);
572    
573            if ((g_width == 0) || (g_height == 0))
574            {
575                    /* Fetch geometry from _NET_WORKAREA */
576                    uint32 x, y, cx, cy;
577    
578                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
579                    {
580                            g_width = cx;
581                            g_height = cy;
582                    }
583                    else
584                    {
585                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
586                            g_width = 800;
587                            g_height = 600;
588                    }
589            }
590    
591            if (g_fullscreen)
592            {
593                    g_width = WidthOfScreen(screen);
594                    g_height = HeightOfScreen(screen);
595            }
596    
597            /* make sure width is a multiple of 4 */
598            g_width = (g_width + 3) & ~3;
599    
600            if (ownbackstore)
601            {
602                    backstore =
603                            XCreatePixmap(display, RootWindowOfScreen(screen), g_width, g_height,
604                                          depth);
605    
606                    /* clear to prevent rubbish being exposed at startup */
607                    XSetForeground(display, gc, BlackPixelOfScreen(screen));
608                    XFillRectangle(display, backstore, gc, 0, 0, g_width, g_height);
609            }
610    
611            mod_map = XGetModifierMapping(display);
612    
613            if (g_enable_compose)
614                    IM = XOpenIM(display, NULL, NULL, NULL);
615    
616            xkeymap_init();
617            xclip_init();
618    
619            /* todo take this out when high colour is done */
620            printf("server bpp %d client bpp %d depth %d\n", g_server_bpp, bpp, depth);
621    
622            return True;
623    }
624    
625    void
626    ui_deinit(void)
627    {
628            if (IM != NULL)
629                    XCloseIM(IM);
630    
631            XFreeModifiermap(mod_map);
632    
633            if (ownbackstore)
634                    XFreePixmap(display, backstore);
635    
636            XFreeGC(display, gc);
637            XCloseDisplay(display);
638            display = NULL;
639    }
640    
641    BOOL
642    ui_create_window(void)
643    {
644            XSetWindowAttributes attribs;
645            XClassHint *classhints;
646            XSizeHints *sizehints;
647            int wndwidth, wndheight;
648            long input_mask, ic_input_mask;
649            XEvent xevent;
650    
651            wndwidth = g_fullscreen ? WidthOfScreen(screen) : g_width;
652            wndheight = g_fullscreen ? HeightOfScreen(screen) : g_height;
653    
654            attribs.background_pixel = BlackPixelOfScreen(screen);
655            attribs.backing_store = ownbackstore ? NotUseful : Always;
656            attribs.override_redirect = g_fullscreen;
657    
658            wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
659                                0, CopyFromParent, InputOutput, CopyFromParent,
660                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
661    
662            XStoreName(display, wnd, title);
663    
664            if (hide_decorations)
665                    mwm_hide_decorations();
666    
667            classhints = XAllocClassHint();
668            if (classhints != NULL)
669            {
670                    classhints->res_name = classhints->res_class = "rdesktop";
671                    XSetClassHint(display, wnd, classhints);
672                    XFree(classhints);
673            }
674    
675            sizehints = XAllocSizeHints();
676            if (sizehints)
677            {
678                    sizehints->flags = PMinSize | PMaxSize;
679                    sizehints->min_width = sizehints->max_width = g_width;
680                    sizehints->min_height = sizehints->max_height = g_height;
681                    XSetWMNormalHints(display, wnd, sizehints);
682                    XFree(sizehints);
683            }
684    
685            input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
686                    VisibilityChangeMask | FocusChangeMask;
687    
688            if (g_sendmotion)
689                    input_mask |= PointerMotionMask;
690            if (ownbackstore)
691                    input_mask |= ExposureMask;
692            if (g_fullscreen || grab_keyboard)
693                    input_mask |= EnterWindowMask;
694            if (grab_keyboard)
695                    input_mask |= LeaveWindowMask;
696    
697            if (IM != NULL)
698            {
699                    IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
700                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
701    
702                    if ((IC != NULL)
703                        && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
704                            input_mask |= ic_input_mask;
705            }
706    
707            XSelectInput(display, wnd, input_mask);
708            XMapWindow(display, wnd);
709    
710            /* wait for VisibilityNotify */
711            do
712          {          {
713                  switch (event.type)                  XMaskEvent(display, VisibilityChangeMask, &xevent);
714            }
715            while (xevent.type != VisibilityNotify);
716    
717            g_focused = False;
718            g_mouse_in_wnd = False;
719    
720            /* handle the WM_DELETE_WINDOW protocol */
721            protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
722            kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
723            XSetWMProtocols(display, wnd, &kill_atom, 1);
724    
725            return True;
726    }
727    
728    void
729    ui_destroy_window(void)
730    {
731            if (IC != NULL)
732                    XDestroyIC(IC);
733    
734            XDestroyWindow(display, wnd);
735    }
736    
737    void
738    xwin_toggle_fullscreen(void)
739    {
740            Pixmap contents = 0;
741    
742            if (!ownbackstore)
743            {
744                    /* need to save contents of window */
745                    contents = XCreatePixmap(display, wnd, g_width, g_height, depth);
746                    XCopyArea(display, wnd, contents, gc, 0, 0, g_width, g_height, 0, 0);
747            }
748    
749            ui_destroy_window();
750            g_fullscreen = !g_fullscreen;
751            ui_create_window();
752    
753            XDefineCursor(display, wnd, current_cursor);
754    
755            if (!ownbackstore)
756            {
757                    XCopyArea(display, contents, wnd, gc, 0, 0, g_width, g_height, 0, 0);
758                    XFreePixmap(display, contents);
759            }
760    }
761    
762    /* Process all events in Xlib queue
763       Returns 0 after user quit, 1 otherwise */
764    static int
765    xwin_process_events(void)
766    {
767            XEvent xevent;
768            KeySym keysym;
769            uint16 button, flags;
770            uint32 ev_time;
771            key_translation tr;
772            char str[256];
773            Status status;
774            unsigned int state;
775            Window wdummy;
776            int dummy;
777    
778            while (XPending(display) > 0)
779            {
780                    XNextEvent(display, &xevent);
781    
782                    if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
783                  {                  {
784                            DEBUG_KBD(("Filtering event\n"));
785                            continue;
786                    }
787    
788                    flags = 0;
789    
790                    switch (xevent.type)
791                    {
792                            case ClientMessage:
793                                    /* the window manager told us to quit */
794                                    if ((xevent.xclient.message_type == protocol_atom)
795                                        && ((Atom) xevent.xclient.data.l[0] == kill_atom))
796                                            /* Quit */
797                                            return 0;
798                                    break;
799    
800                          case KeyPress:                          case KeyPress:
801                                  scancode = xwin_translate_key(event.xkey.keycode);                                  last_gesturetime = xevent.xkey.time;
802                                  if (scancode == 0)                                  if (IC != NULL)
803                                            /* Multi_key compatible version */
804                                    {
805                                            XmbLookupString(IC,
806                                                            &xevent.xkey, str, sizeof(str), &keysym,
807                                                            &status);
808                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
809                                            {
810                                                    error("XmbLookupString failed with status 0x%x\n",
811                                                          status);
812                                                    break;
813                                            }
814                                    }
815                                    else
816                                    {
817                                            /* Plain old XLookupString */
818                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
819                                            XLookupString((XKeyEvent *) & xevent,
820                                                          str, sizeof(str), &keysym, NULL);
821                                    }
822    
823                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
824                                               get_ksname(keysym)));
825    
826                                    ev_time = time(NULL);
827                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
828                                            break;
829    
830                                    tr = xkeymap_translate_key(keysym,
831                                                               xevent.xkey.keycode, xevent.xkey.state);
832    
833                                    if (tr.scancode == 0)
834                                          break;                                          break;
835    
836                                  rdp_send_input(conn, RDP_INPUT_SCANCODE, 0,                                  ensure_remote_modifiers(ev_time, tr);
837                                                  scancode, 0);  
838                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
839                                  break;                                  break;
840    
841                          case KeyRelease:                          case KeyRelease:
842                                  scancode = xwin_translate_key(event.xkey.keycode);                                  last_gesturetime = xevent.xkey.time;
843                                  if (scancode == 0)                                  XLookupString((XKeyEvent *) & xevent, str,
844                                                  sizeof(str), &keysym, NULL);
845    
846                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
847                                               get_ksname(keysym)));
848    
849                                    ev_time = time(NULL);
850                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
851                                            break;
852    
853                                    tr = xkeymap_translate_key(keysym,
854                                                               xevent.xkey.keycode, xevent.xkey.state);
855    
856                                    if (tr.scancode == 0)
857                                          break;                                          break;
858    
859                                  rdp_send_input(conn, RDP_INPUT_SCANCODE,                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,  
                                                 scancode, 0);  
860                                  break;                                  break;
861    
862                          case ButtonPress:                          case ButtonPress:
863                                  button = xwin_translate_mouse(event.xbutton.button);                                  flags = MOUSE_FLAG_DOWN;
864                                    /* fall through */
865    
866                            case ButtonRelease:
867                                    last_gesturetime = xevent.xbutton.time;
868                                    button = xkeymap_translate_button(xevent.xbutton.button);
869                                  if (button == 0)                                  if (button == 0)
870                                          break;                                          break;
871    
872                                  rdp_send_input(conn, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
873                                                  button | MOUSE_FLAG_DOWN,                                  if (xevent.xbutton.y < win_button_size)
874                                                  event.xbutton.x,                                  {
875                                                  event.xbutton.y);                                          /* Stop moving window when button is released, regardless of cursor position */
876                                            if (moving_wnd && (xevent.type == ButtonRelease))
877                                                    moving_wnd = False;
878    
879                                            /*  Check from right to left: */
880    
881                                            if (xevent.xbutton.x >= g_width - win_button_size)
882                                            {
883                                                    /* The close button, continue */
884                                                    ;
885                                            }
886                                            else if (xevent.xbutton.x >= g_width - win_button_size * 2)
887                                            {
888                                                    /* The maximize/restore button. Do not send to
889                                                       server.  It might be a good idea to change the
890                                                       cursor or give some other visible indication
891                                                       that rdesktop inhibited this click */
892                                                    break;
893                                            }
894                                            else if (xevent.xbutton.x >= g_width - win_button_size * 3)
895                                            {
896                                                    /* The minimize button. Iconify window. */
897                                                    XIconifyWindow(display, wnd,
898                                                                   DefaultScreen(display));
899                                                    break;
900                                            }
901                                            else if (xevent.xbutton.x <= win_button_size)
902                                            {
903                                                    /* The system menu. Ignore. */
904                                                    break;
905                                            }
906                                            else
907                                            {
908                                                    /* The title bar. */
909                                                    if ((xevent.type == ButtonPress) && !g_fullscreen
910                                                        && hide_decorations)
911                                                    {
912                                                            moving_wnd = True;
913                                                            move_x_offset = xevent.xbutton.x;
914                                                            move_y_offset = xevent.xbutton.y;
915                                                    }
916                                                    break;
917    
918                                            }
919                                    }
920    
921                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
922                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
923                                  break;                                  break;
924    
925                          case ButtonRelease:                          case MotionNotify:
926                                  button = xwin_translate_mouse(event.xbutton.button);                                  if (moving_wnd)
927                                  if (button == 0)                                  {
928                                            XMoveWindow(display, wnd,
929                                                        xevent.xmotion.x_root - move_x_offset,
930                                                        xevent.xmotion.y_root - move_y_offset);
931                                          break;                                          break;
932                                    }
933    
934                                  rdp_send_input(conn, RDP_INPUT_MOUSE,                                  if (g_fullscreen && !g_focused)
935                                                  button,                                          XSetInputFocus(display, wnd, RevertToPointerRoot,
936                                                  event.xbutton.x,                                                         CurrentTime);
937                                                  event.xbutton.y);                                  rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
938                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
939                                    break;
940    
941                            case FocusIn:
942                                    if (xevent.xfocus.mode == NotifyGrab)
943                                            break;
944                                    g_focused = True;
945                                    XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
946                                                  &dummy, &dummy, &state);
947                                    reset_modifier_keys(state);
948                                    if (grab_keyboard && g_mouse_in_wnd)
949                                            XGrabKeyboard(display, wnd, True,
950                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
951                                    break;
952    
953                            case FocusOut:
954                                    if (xevent.xfocus.mode == NotifyUngrab)
955                                            break;
956                                    g_focused = False;
957                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
958                                            XUngrabKeyboard(display, CurrentTime);
959                                    break;
960    
961                            case EnterNotify:
962                                    /* we only register for this event when in fullscreen mode */
963                                    /* or grab_keyboard */
964                                    g_mouse_in_wnd = True;
965                                    if (g_fullscreen)
966                                    {
967                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
968                                                           CurrentTime);
969                                            break;
970                                    }
971                                    if (g_focused)
972                                            XGrabKeyboard(display, wnd, True,
973                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
974                                    break;
975    
976                            case LeaveNotify:
977                                    /* we only register for this event when grab_keyboard */
978                                    g_mouse_in_wnd = False;
979                                    XUngrabKeyboard(display, CurrentTime);
980                                    break;
981    
982                            case Expose:
983                                    XCopyArea(display, backstore, wnd, gc,
984                                              xevent.xexpose.x, xevent.xexpose.y,
985                                              xevent.xexpose.width,
986                                              xevent.xexpose.height,
987                                              xevent.xexpose.x, xevent.xexpose.y);
988                                    break;
989    
990                            case MappingNotify:
991                                    /* Refresh keyboard mapping if it has changed. This is important for
992                                       Xvnc, since it allocates keycodes dynamically */
993                                    if (xevent.xmapping.request == MappingKeyboard
994                                        || xevent.xmapping.request == MappingModifier)
995                                            XRefreshKeyboardMapping(&xevent.xmapping);
996    
997                                    if (xevent.xmapping.request == MappingModifier)
998                                    {
999                                            XFreeModifiermap(mod_map);
1000                                            mod_map = XGetModifierMapping(display);
1001                                    }
1002                                    break;
1003    
1004                                    /* clipboard stuff */
1005                            case SelectionNotify:
1006                                    xclip_handle_SelectionNotify(&xevent.xselection);
1007                                    break;
1008                            case SelectionRequest:
1009                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1010                                    break;
1011                            case SelectionClear:
1012                                    xclip_handle_SelectionClear();
1013                                    break;
1014                            case PropertyNotify:
1015                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1016                                    break;
1017                    }
1018            }
1019            /* Keep going */
1020            return 1;
1021    }
1022    
1023    /* Returns 0 after user quit, 1 otherwise */
1024    int
1025    ui_select(int rdp_socket)
1026    {
1027            int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
1028            fd_set rfds;
1029    
1030            FD_ZERO(&rfds);
1031    
1032            while (True)
1033            {
1034                    /* Process any events already waiting */
1035                    if (!xwin_process_events())
1036                            /* User quit */
1037                            return 0;
1038    
1039                    FD_ZERO(&rfds);
1040                    FD_SET(rdp_socket, &rfds);
1041                    FD_SET(x_socket, &rfds);
1042    
1043                    switch (select(n, &rfds, NULL, NULL, NULL))
1044                    {
1045                            case -1:
1046                                    error("select: %s\n", strerror(errno));
1047    
1048                            case 0:
1049                                    continue;
1050                  }                  }
1051    
1052                    if (FD_ISSET(rdp_socket, &rfds))
1053                            return 1;
1054          }          }
1055  }  }
1056    
1057  void ui_move_pointer(HWINDOW wnd, int x, int y)  void
1058    ui_move_pointer(int x, int y)
1059  {  {
1060          XWarpPointer(wnd->display, wnd->wnd, wnd->wnd, 0, 0, 0, 0, x, y);          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
1061  }  }
1062    
1063  HBITMAP ui_create_bitmap(HWINDOW wnd, int width, int height, uint8 *data)  HBITMAP
1064    ui_create_bitmap(int width, int height, uint8 * data)
1065  {  {
1066          XImage *image;          XImage *image;
1067          Pixmap bitmap;          Pixmap bitmap;
1068            uint8 *tdata;
1069    
1070            tdata = (owncolmap ? data : translate_image(width, height, data));
1071            bitmap = XCreatePixmap(display, wnd, width, height, depth);
1072            image = XCreateImage(display, visual, depth, ZPixmap, 0,
1073                                 (char *) tdata, width, height, g_server_bpp == 8 ? 8 : bpp, 0);
1074    
1075            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1076    
1077            XFree(image);
1078            if (!owncolmap)
1079                    xfree(tdata);
1080            return (HBITMAP) bitmap;
1081    }
1082    
1083    void
1084    ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1085    {
1086            XImage *image;
1087            uint8 *tdata;
1088            tdata = (owncolmap ? data : translate_image(width, height, data));
1089            image = XCreateImage(display, visual, depth, ZPixmap, 0,
1090                                 (char *) tdata, width, height, g_server_bpp == 8 ? 8 : bpp, 0);
1091    
1092          bitmap = XCreatePixmap(wnd->display, wnd->wnd, width, height, 8);          if (ownbackstore)
1093            {
1094                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1095                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1096            }
1097            else
1098            {
1099                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1100            }
1101    
         image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,  
                                 data, width, height, 8, width);  
         XSetFunction(wnd->display, wnd->gc, GXcopy);  
         XPutImage(wnd->display, bitmap, wnd->gc, image, 0, 0, 0, 0,  
                         width, height);  
1102          XFree(image);          XFree(image);
1103                    if (!owncolmap)
1104          return (HBITMAP)bitmap;                  xfree(tdata);
1105  }  }
1106    
1107  void ui_destroy_bitmap(HWINDOW wnd, HBITMAP bmp)  void
1108    ui_destroy_bitmap(HBITMAP bmp)
1109  {  {
1110          XFreePixmap(wnd->display, (Pixmap)bmp);          XFreePixmap(display, (Pixmap) bmp);
1111  }  }
1112    
1113  HGLYPH ui_create_glyph(HWINDOW wnd, int width, int height, uint8 *data)  HGLYPH
1114    ui_create_glyph(int width, int height, uint8 * data)
1115  {  {
1116          XImage *image;          XImage *image;
1117          Pixmap bitmap;          Pixmap bitmap;
# Line 201  HGLYPH ui_create_glyph(HWINDOW wnd, int Line 1120  HGLYPH ui_create_glyph(HWINDOW wnd, int
1120    
1121          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1122    
1123          bitmap = XCreatePixmap(wnd->display, wnd->wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
1124          gc = XCreateGC(wnd->display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
1125    
1126            image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1127                                 width, height, 8, scanline);
1128            image->byte_order = MSBFirst;
1129            image->bitmap_bit_order = MSBFirst;
1130            XInitImage(image);
1131    
1132            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1133    
         image = XCreateImage(wnd->display, wnd->visual, 1, ZPixmap, 0,  
                                 data, width, height, 8, scanline);  
         XSetFunction(wnd->display, wnd->gc, GXcopy);  
         XPutImage(wnd->display, bitmap, gc, image, 0, 0, 0, 0, width, height);  
1134          XFree(image);          XFree(image);
1135          XFreeGC(wnd->display, gc);          XFreeGC(display, gc);
1136                    return (HGLYPH) bitmap;
         return (HGLYPH)bitmap;  
1137  }  }
1138    
1139  void ui_destroy_glyph(HWINDOW wnd, HGLYPH glyph)  void
1140    ui_destroy_glyph(HGLYPH glyph)
1141  {  {
1142          XFreePixmap(wnd->display, (Pixmap)glyph);          XFreePixmap(display, (Pixmap) glyph);
1143  }  }
1144    
1145  HCOLOURMAP ui_create_colourmap(HWINDOW wnd, COLOURMAP *colours)  HCURSOR
1146    ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1147                     uint8 * andmask, uint8 * xormask)
1148    {
1149            HGLYPH maskglyph, cursorglyph;
1150            XColor bg, fg;
1151            Cursor xcursor;
1152            uint8 *cursor, *pcursor;
1153            uint8 *mask, *pmask;
1154            uint8 nextbit;
1155            int scanline, offset;
1156            int i, j;
1157    
1158            scanline = (width + 7) / 8;
1159            offset = scanline * height;
1160    
1161            cursor = (uint8 *) xmalloc(offset);
1162            memset(cursor, 0, offset);
1163    
1164            mask = (uint8 *) xmalloc(offset);
1165            memset(mask, 0, offset);
1166    
1167            /* approximate AND and XOR masks with a monochrome X pointer */
1168            for (i = 0; i < height; i++)
1169            {
1170                    offset -= scanline;
1171                    pcursor = &cursor[offset];
1172                    pmask = &mask[offset];
1173    
1174                    for (j = 0; j < scanline; j++)
1175                    {
1176                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1177                            {
1178                                    if (xormask[0] || xormask[1] || xormask[2])
1179                                    {
1180                                            *pcursor |= (~(*andmask) & nextbit);
1181                                            *pmask |= nextbit;
1182                                    }
1183                                    else
1184                                    {
1185                                            *pcursor |= ((*andmask) & nextbit);
1186                                            *pmask |= (~(*andmask) & nextbit);
1187                                    }
1188    
1189                                    xormask += 3;
1190                            }
1191    
1192                            andmask++;
1193                            pcursor++;
1194                            pmask++;
1195                    }
1196            }
1197    
1198            fg.red = fg.blue = fg.green = 0xffff;
1199            bg.red = bg.blue = bg.green = 0x0000;
1200            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1201    
1202            cursorglyph = ui_create_glyph(width, height, cursor);
1203            maskglyph = ui_create_glyph(width, height, mask);
1204    
1205            xcursor =
1206                    XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1207                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1208    
1209            ui_destroy_glyph(maskglyph);
1210            ui_destroy_glyph(cursorglyph);
1211            xfree(mask);
1212            xfree(cursor);
1213            return (HCURSOR) xcursor;
1214    }
1215    
1216    void
1217    ui_set_cursor(HCURSOR cursor)
1218    {
1219            current_cursor = (Cursor) cursor;
1220            XDefineCursor(display, wnd, current_cursor);
1221    }
1222    
1223    void
1224    ui_destroy_cursor(HCURSOR cursor)
1225    {
1226            XFreeCursor(display, (Cursor) cursor);
1227    }
1228    
1229    #define MAKE_XCOLOR(xc,c) \
1230                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
1231                    (xc)->green = ((c)->green << 8) | (c)->green; \
1232                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1233                    (xc)->flags = DoRed | DoGreen | DoBlue;
1234    
1235    
1236    HCOLOURMAP
1237    ui_create_colourmap(COLOURMAP * colours)
1238  {  {
1239          COLOURENTRY *entry;          COLOURENTRY *entry;
         XColor *xcolours, *xentry;  
         Colormap map;  
1240          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1241            if (!owncolmap)
         xcolours = malloc(sizeof(XColor) * ncolours);  
         for (i = 0; i < ncolours; i++)  
1242          {          {
1243                  entry = &colours->colours[i];                  uint32 *map = (uint32 *) xmalloc(sizeof(*colmap) * ncolours);
1244                  xentry = &xcolours[i];                  XColor xentry;
1245                    XColor xc_cache[256];
1246                    uint32 colour;
1247                    int colLookup = 256;
1248                    for (i = 0; i < ncolours; i++)
1249                    {
1250                            entry = &colours->colours[i];
1251                            MAKE_XCOLOR(&xentry, entry);
1252    
1253                            if (XAllocColor(display, xcolmap, &xentry) == 0)
1254                            {
1255                                    /* Allocation failed, find closest match. */
1256                                    int j = 256;
1257                                    int nMinDist = 3 * 256 * 256;
1258                                    long nDist = nMinDist;
1259    
1260                                    /* only get the colors once */
1261                                    while (colLookup--)
1262                                    {
1263                                            xc_cache[colLookup].pixel = colLookup;
1264                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1265                                                    xc_cache[colLookup].blue = 0;
1266                                            xc_cache[colLookup].flags = 0;
1267                                            XQueryColor(display,
1268                                                        DefaultColormap(display,
1269                                                                        DefaultScreen(display)),
1270                                                        &xc_cache[colLookup]);
1271                                    }
1272                                    colLookup = 0;
1273    
1274                                    /* approximate the pixel */
1275                                    while (j--)
1276                                    {
1277                                            if (xc_cache[j].flags)
1278                                            {
1279                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1280                                                             (long) (xentry.red >> 8)) *
1281                                                            ((long) (xc_cache[j].red >> 8) -
1282                                                             (long) (xentry.red >> 8)) +
1283                                                            ((long) (xc_cache[j].green >> 8) -
1284                                                             (long) (xentry.green >> 8)) *
1285                                                            ((long) (xc_cache[j].green >> 8) -
1286                                                             (long) (xentry.green >> 8)) +
1287                                                            ((long) (xc_cache[j].blue >> 8) -
1288                                                             (long) (xentry.blue >> 8)) *
1289                                                            ((long) (xc_cache[j].blue >> 8) -
1290                                                             (long) (xentry.blue >> 8));
1291                                            }
1292                                            if (nDist < nMinDist)
1293                                            {
1294                                                    nMinDist = nDist;
1295                                                    xentry.pixel = j;
1296                                            }
1297                                    }
1298                            }
1299                            colour = xentry.pixel;
1300    
1301                            /* update our cache */
1302                            if (xentry.pixel < 256)
1303                            {
1304                                    xc_cache[xentry.pixel].red = xentry.red;
1305                                    xc_cache[xentry.pixel].green = xentry.green;
1306                                    xc_cache[xentry.pixel].blue = xentry.blue;
1307    
1308                  xentry->pixel = i;                          }
1309                  xentry->red = entry->red << 8;  
1310                  xentry->blue = entry->blue << 8;  
1311                  xentry->green = entry->green << 8;                          /* byte swap here to make translate_image faster */
1312                  xentry->flags = DoRed | DoBlue | DoGreen;                          map[i] = translate_colour(colour);
1313                    }
1314                    return map;
1315          }          }
1316            else
1317            {
1318                    XColor *xcolours, *xentry;
1319                    Colormap map;
1320    
1321                    xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1322                    for (i = 0; i < ncolours; i++)
1323                    {
1324                            entry = &colours->colours[i];
1325                            xentry = &xcolours[i];
1326                            xentry->pixel = i;
1327                            MAKE_XCOLOR(xentry, entry);
1328                    }
1329    
1330          map = XCreateColormap(wnd->display, wnd->wnd, wnd->visual, AllocAll);                  map = XCreateColormap(display, wnd, visual, AllocAll);
1331          XStoreColors(wnd->display, map, xcolours, ncolours);                  XStoreColors(display, map, xcolours, ncolours);
1332    
1333          free(xcolours);                  xfree(xcolours);
1334          return (HCOLOURMAP)map;                  return (HCOLOURMAP) map;
1335            }
1336  }  }
1337    
1338  void ui_destroy_colourmap(HWINDOW wnd, HCOLOURMAP map)  void
1339    ui_destroy_colourmap(HCOLOURMAP map)
1340  {  {
1341          XFreeColormap(wnd->display, (Colormap)map);          if (!owncolmap)
1342                    xfree(map);
1343            else
1344                    XFreeColormap(display, (Colormap) map);
1345  }  }
1346    
1347  void ui_set_colourmap(HWINDOW wnd, HCOLOURMAP map)  void
1348    ui_set_colourmap(HCOLOURMAP map)
1349  {  {
1350          XSetWindowColormap(wnd->display, wnd->wnd, (Colormap)map);          if (!owncolmap)
1351            {
1352                    if (colmap)
1353                            xfree(colmap);
1354    
1355                    colmap = (uint32 *) map;
1356            }
1357            else
1358                    XSetWindowColormap(display, wnd, (Colormap) map);
1359  }  }
1360    
1361  void ui_set_clip(HWINDOW wnd, int x, int y, int cx, int cy)  void
1362    ui_set_clip(int x, int y, int cx, int cy)
1363  {  {
1364          XRectangle rect;          XRectangle rect;
1365    
# Line 264  void ui_set_clip(HWINDOW wnd, int x, int Line 1367  void ui_set_clip(HWINDOW wnd, int x, int
1367          rect.y = y;          rect.y = y;
1368          rect.width = cx;          rect.width = cx;
1369          rect.height = cy;          rect.height = cy;
1370          XSetClipRectangles(wnd->display, wnd->gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1371  }  }
1372    
1373  void ui_reset_clip(HWINDOW wnd)  void
1374    ui_reset_clip(void)
1375  {  {
1376          XRectangle rect;          XRectangle rect;
1377    
1378          rect.x = 0;          rect.x = 0;
1379          rect.y = 0;          rect.y = 0;
1380          rect.width = wnd->width;          rect.width = g_width;
1381          rect.height = wnd->height;          rect.height = g_height;
1382          XSetClipRectangles(wnd->display, wnd->gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1383  }  }
1384    
1385  static int rop2_map[] = {  void
1386          GXclear,        /* 0 */  ui_bell(void)
         GXnor,          /* DPon */  
         GXandInverted,  /* DPna */  
         GXcopyInverted, /* Pn */  
         GXandReverse,   /* PDna */  
         GXinvert,       /* Dn */  
         GXxor,          /* DPx */  
         GXnand,         /* DPan */  
         GXand,          /* DPa */  
         GXequiv,        /* DPxn */  
         GXnoop,         /* D */  
         GXorInverted,   /* DPno */  
         GXcopy,         /* P */  
         GXorReverse,    /* PDno */  
         GXor,           /* DPo */  
         GXset           /* 1 */  
 };  
   
 static void xwin_set_function(HWINDOW wnd, uint8 rop2)  
1387  {  {
1388          XSetFunction(wnd->display, wnd->gc, rop2_map[rop2]);          XBell(display, 0);
1389  }  }
1390    
1391  void ui_destblt(HWINDOW wnd, uint8 opcode,  void
1392          /* dest */  int x, int y, int cx, int cy)  ui_destblt(uint8 opcode,
1393               /* dest */ int x, int y, int cx, int cy)
1394  {  {
1395          xwin_set_function(wnd, opcode);          SET_FUNCTION(opcode);
1396            FILL_RECTANGLE(x, y, cx, cy);
1397          XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
1398  }  }
1399    
1400  void ui_patblt(HWINDOW wnd, uint8 opcode,  static uint8 hatch_patterns[] = {
1401          /* dest */  int x, int y, int cx, int cy,          0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1402          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)          0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1403            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1404            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1405            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1406            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
1407    };
1408    
1409    void
1410    ui_patblt(uint8 opcode,
1411              /* dest */ int x, int y, int cx, int cy,
1412              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1413  {  {
         Display *dpy = wnd->display;  
         GC gc = wnd->gc;  
1414          Pixmap fill;          Pixmap fill;
1415            uint8 i, ipattern[8];
1416    
1417          xwin_set_function(wnd, opcode);          SET_FUNCTION(opcode);
1418    
1419          switch (brush->style)          switch (brush->style)
1420          {          {
1421                  case 0: /* Solid */                  case 0: /* Solid */
1422                          XSetForeground(dpy, gc, fgcolour);                          SET_FOREGROUND(fgcolour);
1423                          XFillRectangle(dpy, wnd->wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1424                          break;                          break;
1425    
1426                  case 3: /* Pattern */                  case 2: /* Hatch */
1427                          fill = (Pixmap)ui_create_glyph(wnd, 8, 8, brush->pattern);                          fill = (Pixmap) ui_create_glyph(8, 8,
1428                                                            hatch_patterns + brush->pattern[0] * 8);
1429                          XSetForeground(dpy, gc, fgcolour);                          SET_FOREGROUND(bgcolour);
1430                          XSetBackground(dpy, gc, bgcolour);                          SET_BACKGROUND(fgcolour);
1431                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                          XSetFillStyle(display, gc, FillOpaqueStippled);
1432                          XSetStipple(dpy, gc, fill);                          XSetStipple(display, gc, fill);
1433                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1434                          XFillRectangle(dpy, wnd->wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1435                            XSetFillStyle(display, gc, FillSolid);
1436                            XSetTSOrigin(display, gc, 0, 0);
1437                            ui_destroy_glyph((HGLYPH) fill);
1438                            break;
1439    
1440                          XSetFillStyle(dpy, gc, FillSolid);                  case 3: /* Pattern */
1441                          ui_destroy_glyph(wnd, (HGLYPH)fill);                          for (i = 0; i != 8; i++)
1442                                    ipattern[7 - i] = brush->pattern[i];
1443                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1444    
1445                            SET_FOREGROUND(bgcolour);
1446                            SET_BACKGROUND(fgcolour);
1447                            XSetFillStyle(display, gc, FillOpaqueStippled);
1448                            XSetStipple(display, gc, fill);
1449                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1450    
1451                            FILL_RECTANGLE(x, y, cx, cy);
1452    
1453                            XSetFillStyle(display, gc, FillSolid);
1454                            XSetTSOrigin(display, gc, 0, 0);
1455                            ui_destroy_glyph((HGLYPH) fill);
1456                          break;                          break;
1457    
1458                  default:                  default:
1459                          NOTIMP("brush style %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
1460          }          }
 }  
   
 void ui_screenblt(HWINDOW wnd, uint8 opcode,  
                 /* dest */ int x, int y, int cx, int cy,  
                 /* src */  int srcx, int srcy)  
 {  
         xwin_set_function(wnd, opcode);  
   
         XCopyArea(wnd->display, wnd->wnd, wnd->wnd, wnd->gc, srcx, srcy,  
                         cx, cy, x, y);  
 }  
   
 void ui_memblt(HWINDOW wnd, uint8 opcode,  
         /* dest */  int x, int y, int cx, int cy,  
         /* src */   HBITMAP src, int srcx, int srcy)  
 {  
         xwin_set_function(wnd, opcode);  
1461    
1462          XCopyArea(wnd->display, (Pixmap)src, wnd->wnd, wnd->gc, srcx, srcy,          RESET_FUNCTION(opcode);
                         cx, cy, x, y);  
1463  }  }
1464    
1465  void ui_triblt(HWINDOW wnd, uint8 opcode,  void
1466          /* dest */  int x, int y, int cx, int cy,  ui_screenblt(uint8 opcode,
1467          /* src */   HBITMAP src, int srcx, int srcy,               /* dest */ int x, int y, int cx, int cy,
1468          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)               /* src */ int srcx, int srcy)
1469    {
1470            SET_FUNCTION(opcode);
1471            XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1472            if (ownbackstore)
1473                    XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1474            RESET_FUNCTION(opcode);
1475    }
1476    
1477    void
1478    ui_memblt(uint8 opcode,
1479              /* dest */ int x, int y, int cx, int cy,
1480              /* src */ HBITMAP src, int srcx, int srcy)
1481    {
1482            SET_FUNCTION(opcode);
1483            XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1484            if (ownbackstore)
1485                    XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1486            RESET_FUNCTION(opcode);
1487    }
1488    
1489    void
1490    ui_triblt(uint8 opcode,
1491              /* dest */ int x, int y, int cx, int cy,
1492              /* src */ HBITMAP src, int srcx, int srcy,
1493              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1494  {  {
1495          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1496             comes up with an efficient way of doing that I am using cases. */             comes up with a more efficient way of doing it I am using cases. */
1497    
1498          switch (opcode)          switch (opcode)
1499          {          {
1500                  case 0xb8: /* PSDPxax */                  case 0x69:      /* PDSxxn */
1501                          ui_patblt(wnd, ROP2_XOR, x, y, cx, cy,                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1502                                          brush, bgcolour, fgcolour);                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                         ui_memblt(wnd, ROP2_AND, x, y, cx, cy,  
                                         src, srcx, srcy);  
                         ui_patblt(wnd, ROP2_XOR, x, y, cx, cy,  
                                         brush, bgcolour, fgcolour);  
1503                          break;                          break;
1504    
1505                  default:                  case 0xb8:      /* PSDPxax */
1506                          NOTIMP("triblt opcode 0x%x\n", opcode);                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1507                          ui_memblt(wnd, ROP2_COPY, x, y, cx, cy,                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1508                                          brush, bgcolour, fgcolour);                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
         }  
 }  
   
 void ui_line(HWINDOW wnd, uint8 opcode,  
         /* dest */  int startx, int starty, int endx, int endy,  
         /* pen */   PEN *pen)  
 {  
         xwin_set_function(wnd, opcode);  
   
         XSetForeground(wnd->display, wnd->gc, pen->colour);  
         XDrawLine(wnd->display, wnd->wnd, wnd->gc, startx, starty, endx, endy);  
 }  
   
 void ui_rect(HWINDOW wnd,  
         /* dest */  int x, int y, int cx, int cy,  
         /* brush */ int colour)  
 {  
         xwin_set_function(wnd, ROP2_COPY);  
   
         XSetForeground(wnd->display, wnd->gc, colour);  
         XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, cx, cy);  
 }  
   
 void ui_draw_glyph(HWINDOW wnd, int mixmode,  
         /* dest */ int x, int y, int cx, int cy,  
         /* src */  HGLYPH glyph, int srcx, int srcy, int bgcolour, int fgcolour)  
 {  
         Pixmap pixmap = (Pixmap)glyph;  
   
         xwin_set_function(wnd, ROP2_COPY);  
   
         XSetForeground(wnd->display, wnd->gc, fgcolour);  
   
         switch (mixmode)  
         {  
                 case MIX_TRANSPARENT:  
                         XSetStipple(wnd->display, wnd->gc, pixmap);  
                         XSetFillStyle(wnd->display, wnd->gc, FillStippled);  
                         XSetTSOrigin(wnd->display, wnd->gc, x, y);  
                         XFillRectangle(wnd->display, wnd->wnd, wnd->gc,  
                                         x, y, cx, cy);  
                         XSetFillStyle(wnd->display, wnd->gc, FillSolid);  
1509                          break;                          break;
1510    
1511                  case MIX_OPAQUE:                  case 0xc0:      /* PSa */
1512                          XSetBackground(wnd->display, wnd->gc, bgcolour);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1513                          XCopyPlane(wnd->display, pixmap, wnd->wnd, wnd->gc,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                         srcx, srcy, cx, cy, x, y, 1);  
1514                          break;                          break;
1515    
1516                  default:                  default:
1517                          NOTIMP("mix mode %d\n", mixmode);                          unimpl("triblt 0x%x\n", opcode);
1518                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1519          }          }
1520  }  }
1521    
1522  void ui_draw_text(HWINDOW wnd, uint8 font, uint8 flags, int mixmode, int x,  void
1523                          int y, int boxx, int boxy, int boxcx, int boxcy,  ui_line(uint8 opcode,
1524                          int bgcolour, int fgcolour, uint8 *text, uint8 length)          /* dest */ int startx, int starty, int endx, int endy,
1525  {          /* pen */ PEN * pen)
1526          FONT_GLYPH *glyph;  {
1527          int i;          SET_FUNCTION(opcode);
1528            SET_FOREGROUND(pen->colour);
1529            XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1530            if (ownbackstore)
1531                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1532            RESET_FUNCTION(opcode);
1533    }
1534    
1535    void
1536    ui_rect(
1537                   /* dest */ int x, int y, int cx, int cy,
1538                   /* brush */ int colour)
1539    {
1540            SET_FOREGROUND(colour);
1541            FILL_RECTANGLE(x, y, cx, cy);
1542    }
1543    
1544    /* warning, this function only draws on wnd or backstore, not both */
1545    void
1546    ui_draw_glyph(int mixmode,
1547                  /* dest */ int x, int y, int cx, int cy,
1548                  /* src */ HGLYPH glyph, int srcx, int srcy,
1549                  int bgcolour, int fgcolour)
1550    {
1551            SET_FOREGROUND(fgcolour);
1552            SET_BACKGROUND(bgcolour);
1553    
1554            XSetFillStyle(display, gc,
1555                          (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1556            XSetStipple(display, gc, (Pixmap) glyph);
1557            XSetTSOrigin(display, gc, x, y);
1558    
1559            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1560    
1561            XSetFillStyle(display, gc, FillSolid);
1562    }
1563    
1564    #define DO_GLYPH(ttext,idx) \
1565    {\
1566      glyph = cache_get_font (font, ttext[idx]);\
1567      if (!(flags & TEXT2_IMPLICIT_X))\
1568        {\
1569          xyoffset = ttext[++idx];\
1570          if ((xyoffset & 0x80))\
1571            {\
1572              if (flags & TEXT2_VERTICAL) \
1573                y += ttext[idx+1] | (ttext[idx+2] << 8);\
1574              else\
1575                x += ttext[idx+1] | (ttext[idx+2] << 8);\
1576              idx += 2;\
1577            }\
1578          else\
1579            {\
1580              if (flags & TEXT2_VERTICAL) \
1581                y += xyoffset;\
1582              else\
1583                x += xyoffset;\
1584            }\
1585        }\
1586      if (glyph != NULL)\
1587        {\
1588          ui_draw_glyph (mixmode, x + glyph->offset,\
1589                         y + glyph->baseline,\
1590                         glyph->width, glyph->height,\
1591                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1592          if (flags & TEXT2_IMPLICIT_X)\
1593            x += glyph->width;\
1594        }\
1595    }
1596    
1597    void
1598    ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1599                 int clipx, int clipy, int clipcx, int clipcy,
1600                 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1601                 int fgcolour, uint8 * text, uint8 length)
1602    {
1603            FONTGLYPH *glyph;
1604            int i, j, xyoffset;
1605            DATABLOB *entry;
1606    
1607            SET_FOREGROUND(bgcolour);
1608    
1609          if (boxcx > 1)          if (boxcx > 1)
1610          {          {
1611                  ui_rect(wnd, boxx, boxy, boxcx, boxcy, bgcolour);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1612            }
1613            else if (mixmode == MIX_OPAQUE)
1614            {
1615                    FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1616          }          }
1617    
1618          /* Paint text, character by character */          /* Paint text, character by character */
1619          for (i = 0; i < length; i++)          for (i = 0; i < length;)
1620          {          {
1621                  glyph = cache_get_font(wnd->conn, font, text[i]);                  switch (text[i])
   
                 if (glyph != NULL)  
1622                  {                  {
1623                          ui_draw_glyph(wnd, mixmode, x,                          case 0xff:
1624                                          y + (short)glyph->baseline,                                  if (i + 2 < length)
1625                                          glyph->width, glyph->height,                                          cache_put_text(text[i + 1], text, text[i + 2]);
1626                                          glyph->pixmap, 0, 0,                                  else
1627                                          bgcolour, fgcolour);                                  {
1628                                            error("this shouldn't be happening\n");
1629                                            exit(1);
1630                                    }
1631                                    /* this will move pointer from start to first character after FF command */
1632                                    length -= i + 3;
1633                                    text = &(text[i + 3]);
1634                                    i = 0;
1635                                    break;
1636    
1637                          if (flags & TEXT2_IMPLICIT_X)                          case 0xfe:
1638                                  x += glyph->width;                                  entry = cache_get_text(text[i + 1]);
1639                          else                                  if (entry != NULL)
1640                                  x += text[++i];                                  {
1641                                            if ((((uint8 *) (entry->data))[1] ==
1642                                                 0) && (!(flags & TEXT2_IMPLICIT_X)))
1643                                            {
1644                                                    if (flags & TEXT2_VERTICAL)
1645                                                            y += text[i + 2];
1646                                                    else
1647                                                            x += text[i + 2];
1648                                            }
1649                                            for (j = 0; j < entry->size; j++)
1650                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1651                                    }
1652                                    if (i + 2 < length)
1653                                            i += 3;
1654                                    else
1655                                            i += 2;
1656                                    length -= i;
1657                                    /* this will move pointer from start to first character after FE command */
1658                                    text = &(text[i]);
1659                                    i = 0;
1660                                    break;
1661    
1662                            default:
1663                                    DO_GLYPH(text, i);
1664                                    i++;
1665                                    break;
1666                  }                  }
1667          }          }
1668            if (ownbackstore)
1669            {
1670                    if (boxcx > 1)
1671                            XCopyArea(display, backstore, wnd, gc, boxx,
1672                                      boxy, boxcx, boxcy, boxx, boxy);
1673                    else
1674                            XCopyArea(display, backstore, wnd, gc, clipx,
1675                                      clipy, clipcx, clipcy, clipx, clipy);
1676            }
1677  }  }
1678    
1679  void ui_desktop_save(HWINDOW wnd, uint8 *data, int x, int y, int cx, int cy)  void
1680    ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1681  {  {
1682            Pixmap pix;
1683          XImage *image;          XImage *image;
         int scanline;  
1684    
1685          scanline = (cx + 3) & ~3;          if (ownbackstore)
1686          image = XGetImage(wnd->display, wnd->wnd, x, y, cx, cy,          {
1687                                  0xffffffff, ZPixmap);                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1688          memcpy(data, image->data, scanline*cy);          }
1689            else
1690            {
1691                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
1692                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1693                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1694                    XFreePixmap(display, pix);
1695            }
1696    
1697            offset *= bpp / 8;
1698            cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1699    
1700          XDestroyImage(image);          XDestroyImage(image);
1701  }  }
1702    
1703  void ui_desktop_restore(HWINDOW wnd, uint8 *data, int x, int y, int cx, int cy)  void
1704    ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1705  {  {
1706          XImage *image;          XImage *image;
1707          int scanline;          uint8 *data;
1708    
1709            offset *= bpp / 8;
1710            data = cache_get_desktop(offset, cx, cy, bpp / 8);
1711            if (data == NULL)
1712                    return;
1713    
1714            image = XCreateImage(display, visual, depth, ZPixmap, 0,
1715                                 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1716    
1717            if (ownbackstore)
1718            {
1719                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1720                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1721            }
1722            else
1723            {
1724                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1725            }
1726    
         scanline = (cx + 3) & ~3;  
         image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,  
                                 data, cx, cy, 32, scanline);  
         XSetFunction(wnd->display, wnd->gc, GXcopy);  
         XPutImage(wnd->display, wnd->wnd, wnd->gc, image, 0, 0, x, y, cx, cy);  
1727          XFree(image);          XFree(image);
1728  }  }

Legend:
Removed from v.9  
changed lines
  Added in v.448

  ViewVC Help
Powered by ViewVC 1.1.26