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

Legend:
Removed from v.12  
changed lines
  Added in v.432

  ViewVC Help
Powered by ViewVC 1.1.26