/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

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

  ViewVC Help
Powered by ViewVC 1.1.26