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

Legend:
Removed from v.17  
changed lines
  Added in v.472

  ViewVC Help
Powered by ViewVC 1.1.26