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

Legend:
Removed from v.10  
changed lines
  Added in v.415

  ViewVC Help
Powered by ViewVC 1.1.26