/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

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

revision 25 by matty, Sat Jan 6 03:47:04 2001 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 width;  extern int g_width;
29  extern int height;  extern int g_height;
30  extern BOOL motion;  extern BOOL g_sendmotion;
31    extern BOOL g_fullscreen;
32  static Display *display;  extern BOOL g_grab_keyboard;
33  static Window wnd;  extern BOOL g_hide_decorations;
34  static GC gc;  extern char g_title[];
35  static Visual *visual;  extern int g_server_bpp;
36  static XIM IM;  extern int g_win_button_size;
37    BOOL g_enable_compose = False;
38    BOOL g_focused;
39    BOOL g_mouse_in_wnd;
40    
41    Display *g_display;
42    Time g_last_gesturetime;
43    static int g_x_socket;
44    static Screen *g_screen;
45    Window g_wnd;
46    static GC g_gc;
47    static Visual *g_visual;
48    static int g_depth;
49    static int g_bpp;
50    static XIM g_IM;
51    static XIC g_IC;
52    static XModifierKeymap *g_mod_map;
53    static Cursor g_current_cursor;
54    static Atom g_protocol_atom, g_kill_atom;
55    
56    /* endianness */
57    static BOOL g_host_be;
58    static BOOL g_xserver_be;
59    
60    /* software backing store */
61    static BOOL g_ownbackstore;
62    static Pixmap g_backstore;
63    
64    /* Moving in single app mode */
65    static BOOL g_moving_wnd;
66    static int g_move_x_offset = 0;
67    static int g_move_y_offset = 0;
68    
69    /* MWM decorations */
70    #define MWM_HINTS_DECORATIONS   (1L << 1)
71    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
72    typedef struct
73    {
74            uint32 flags;
75            uint32 functions;
76            uint32 decorations;
77            sint32 inputMode;
78            uint32 status;
79    }
80    PropMotifWmHints;
81    
82    typedef struct
83    {
84            uint32 red;
85            uint32 green;
86            uint32 blue;
87    }
88    PixelColour;
89    
90    
91    #define FILL_RECTANGLE(x,y,cx,cy)\
92    { \
93            XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
94            if (g_ownbackstore) \
95                    XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
96    }
97    
98    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
99    { \
100            XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
101    }
102    
103    /* colour maps */
104    BOOL g_owncolmap = False;
105    static Colormap g_xcolmap;
106    static uint32 *g_colmap = NULL;
107    
108    #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : translate_colour(g_colmap[col]) )
109    #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
110    #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
111    
112    static int rop2_map[] = {
113            GXclear,                /* 0 */
114            GXnor,                  /* DPon */
115            GXandInverted,          /* DPna */
116            GXcopyInverted,         /* Pn */
117            GXandReverse,           /* PDna */
118            GXinvert,               /* Dn */
119            GXxor,                  /* DPx */
120            GXnand,                 /* DPan */
121            GXand,                  /* DPa */
122            GXequiv,                /* DPxn */
123            GXnoop,                 /* D */
124            GXorInverted,           /* DPno */
125            GXcopy,                 /* P */
126            GXorReverse,            /* PDno */
127            GXor,                   /* DPo */
128            GXset                   /* 1 */
129    };
130    
131    #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
132    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
133    
134    static void
135    mwm_hide_decorations(void)
136    {
137            PropMotifWmHints motif_hints;
138            Atom hintsatom;
139    
140            /* setup the property */
141            motif_hints.flags = MWM_HINTS_DECORATIONS;
142            motif_hints.decorations = 0;
143    
144            /* get the atom for the property */
145            hintsatom = XInternAtom(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  BOOL
541  ui_create_window(char *title)  get_key_state(unsigned int state, uint32 keysym)
542  {  {
543          Screen *screen;          int modifierpos, key, keysymMask = 0;
544          XSetWindowAttributes attribs;          int offset;
545          unsigned long input_mask;  
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\n");                  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);
583                          break;  
584            pfm = XListPixmapFormats(g_display, &i);
585            if (pfm != NULL)
586            {
587                    /* Use maximum bpp for this depth - this is generally
588                       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 (i >= screen->ndepths)          if (g_bpp < 8)
600          {          {
601                  ERROR("8-bit depth required (in this version).\n");                  error("Less than 8 bpp not currently supported.\n");
602                  XCloseDisplay(display);                  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          attribs.background_pixel =          g_gc = XCreateGC(g_display, RootWindowOfScreen(g_screen), 0, NULL);
614                  BlackPixel(display, DefaultScreen(display));  
615          attribs.backing_store = Always;          if (DoesBackingStore(g_screen) != Always)
616          wnd = XCreateWindow(display, DefaultRootWindow(display),                  g_ownbackstore = True;
617                              0, 0, width, height, 0, 8, InputOutput, visual,  
618                              CWBackingStore | CWBackPixel, &attribs);          test = 1;
619            g_host_be = !(BOOL) (*(uint8 *) (&test));
620          XStoreName(display, wnd, title);          g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
621          XMapWindow(display, wnd);  
622            if ((g_width == 0) || (g_height == 0))
623          input_mask = KeyPressMask | KeyReleaseMask;          {
624          input_mask |= ButtonPressMask | ButtonReleaseMask;                  /* Fetch geometry from _NET_WORKAREA */
625          if (motion)                  uint32 x, y, cx, cy;
626                  input_mask |= PointerMotionMask;  
627                    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          XSelectInput(display, wnd, input_mask);          /* make sure width is a multiple of 4 */
647          gc = XCreateGC(display, wnd, 0, NULL);          g_width = (g_width + 3) & ~3;
648    
649            if (g_ownbackstore)
650            {
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  void
675  ui_destroy_window()  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  BOOL
691  xwin_translate_key(unsigned long key)  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 ((key > 8) && (key <= 0x60))          if (g_hide_decorations)
714                  return (key - 8);                  mwm_hide_decorations();
715    
716          switch (key)          classhints = XAllocClassHint();
717            if (classhints != NULL)
718          {          {
719                  case 0x62:      /* left arrow */                  classhints->res_name = classhints->res_class = "rdesktop";
720                          return 0x48;                  XSetClassHint(g_display, g_wnd, classhints);
721                  case 0x64:      /* up arrow */                  XFree(classhints);
                         return 0x4b;  
                 case 0x66:      /* down arrow */  
                         return 0x4d;  
                 case 0x68:      /* right arrow */  
                         return 0x50;  
                 case 0x73:      /* Windows key */  
                         DEBUG("CHECKPOINT\n");  
722          }          }
723    
724          return 0;          sizehints = XAllocSizeHints();
725  }          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  static uint16          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
735  xwin_translate_mouse(unsigned long button)                  VisibilityChangeMask | FocusChangeMask;
736  {  
737          switch (button)          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            if (g_IM != NULL)
747          {          {
748                  case Button1:   /* left */                  g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
749                          return MOUSE_FLAG_BUTTON1;                                   XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
750                  case Button2:   /* middle */  
751                          return MOUSE_FLAG_BUTTON3;                  if ((g_IC != NULL)
752                  case Button3:   /* right */                      && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
753                          return MOUSE_FLAG_BUTTON2;                          input_mask |= ic_input_mask;
754          }          }
755    
756          return 0;          XSelectInput(g_display, g_wnd, input_mask);
757            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            /* 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  void  void
778  ui_process_events()  ui_destroy_window(void)
779  {  {
780          XEvent event;          if (g_IC != NULL)
781          uint8 scancode;                  XDestroyIC(g_IC);
         uint16 button;  
         uint32 ev_time;  
782    
783          if (display == NULL)          XDestroyWindow(g_display, g_wnd);
784                  return;  }
785    
786    void
787    xwin_toggle_fullscreen(void)
788    {
789            Pixmap contents = 0;
790    
791            if (!g_ownbackstore)
792            {
793                    /* need to save contents of window */
794                    contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
795                    XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
796            }
797    
798          while (XCheckWindowEvent(display, wnd, 0xffffffff, &event))          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    /* Process all events in Xlib queue
812       Returns 0 after user quit, 1 otherwise */
813    static int
814    xwin_process_events(void)
815    {
816            XEvent xevent;
817            KeySym keysym;
818            uint16 button, flags;
819            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            while (XPending(g_display) > 0)
828          {          {
829                  ev_time = time(NULL);                  XNextEvent(g_display, &xevent);
830    
831                  switch (event.type)                  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 (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 =                                  g_last_gesturetime = xevent.xkey.time;
851                                          xwin_translate_key(event.                                  if (g_IC != NULL)
852                                                             xkey.keycode);                                          /* Multi_key compatible version */
853                                  if (scancode == 0)                                  {
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;                                          break;
878    
879                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  tr = xkeymap_translate_key(keysym,
880                                                 scancode, 0);                                                             xevent.xkey.keycode, xevent.xkey.state);
881    
882                                    if (tr.scancode == 0)
883                                            break;
884    
885                                    save_remote_modifiers(tr.scancode);
886                                    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 =                                  g_last_gesturetime = xevent.xkey.time;
894                                          xwin_translate_key(event.                                  XLookupString((XKeyEvent *) & xevent, str,
895                                                             xkey.keycode);                                                sizeof(str), &keysym, NULL);
896                                  if (scancode == 0)  
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;
903    
904                                    tr = xkeymap_translate_key(keysym,
905                                                               xevent.xkey.keycode, xevent.xkey.state);
906    
907                                    if (tr.scancode == 0)
908                                          break;                                          break;
909    
910                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
                                                KBD_FLAG_DOWN | KBD_FLAG_UP,  
                                                scancode, 0);  
911                                  break;                                  break;
912    
913                          case ButtonPress:                          case ButtonPress:
914                                  button =                                  flags = MOUSE_FLAG_DOWN;
915                                          xwin_translate_mouse(event.                                  /* fall through */
                                                              xbutton.button);  
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;
977    
978                            case MotionNotify:
979                                    if (g_moving_wnd)
980                                    {
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;
985                                    }
986    
987                                    if (g_fullscreen && !g_focused)
988                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
989                                                           CurrentTime);
990                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
991                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
992                                  break;                                  break;
993    
994                          case ButtonRelease:                          case FocusIn:
995                                  button =                                  if (xevent.xfocus.mode == NotifyGrab)
                                         xwin_translate_mouse(event.  
                                                              xbutton.button);  
                                 if (button == 0)  
996                                          break;                                          break;
997                                    g_focused = True;
998                                    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                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                          case FocusOut:
1007                                                 button,                                  if (xevent.xfocus.mode == NotifyUngrab)
1008                                                 event.xbutton.x,                                          break;
1009                                                 event.xbutton.y);                                  g_focused = False;
1010                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1011                                            XUngrabKeyboard(g_display, CurrentTime);
1012                                  break;                                  break;
1013    
1014                          case MotionNotify:                          case EnterNotify:
1015                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* we only register for this event when in fullscreen mode */
1016                                                 MOUSE_FLAG_MOVE,                                  /* or grab_keyboard */
1017                                                 event.xmotion.x,                                  g_mouse_in_wnd = True;
1018                                                 event.xmotion.y);                                  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    /* Returns 0 after user quit, 1 otherwise */
1077    int
1078    ui_select(int rdp_socket)
1079    {
1080            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  void
1111  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
1112  {  {
1113          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1114  }  }
1115    
1116  HBITMAP  HBITMAP
1117  ui_create_bitmap(int width, int height, uint8 *data)  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          bitmap = XCreatePixmap(display, wnd, width, height, 8);          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          image = XCreateImage(display, visual, 8, ZPixmap, 0,          XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
                              data, width, height, 8, width);  
         XSetFunction(display, gc, GXcopy);  
         XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);  
         XFree(image);  
1129    
1130            XFree(image);
1131            if (!g_owncolmap)
1132                    xfree(tdata);
1133          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1134  }  }
1135    
1136  void  void
1137  ui_paint_bitmap(int x, int y, int cx, int cy,  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
                 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            if (g_ownbackstore)
1146            {
1147                    XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1148                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1149            }
1150            else
1151            {
1152                    XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1153            }
1154    
         image = XCreateImage(display, visual, 8, ZPixmap, 0,  
                              data, width, height, 8, width);  
         XSetFunction(display, gc, GXcopy);  
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
1155          XFree(image);          XFree(image);
1156            if (!g_owncolmap)
1157                    xfree(tdata);
1158  }  }
1159    
1160  void  void
1161  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1162  {  {
1163          XFreePixmap(display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
1164  }  }
1165    
1166  HGLYPH  HGLYPH
1167  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1168  {  {
1169          XImage *image;          XImage *image;
1170          Pixmap bitmap;          Pixmap bitmap;
# Line 262  ui_create_glyph(int width, int height, u Line 1173  ui_create_glyph(int width, int height, u
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(display, visual, 1, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1180                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1181          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1182          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1183          XInitImage(image);          XInitImage(image);
1184    
1185          XSetFunction(display, gc, GXcopy);          XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
         XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);  
         XFree(image);  
         XFreeGC(display, gc);  
1186    
1187            XFree(image);
1188            XFreeGC(g_display, gc);
1189          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1190  }  }
1191    
1192  void  void
1193  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1194  {  {
1195          XFreePixmap(display, (Pixmap) glyph);          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
1270    ui_set_cursor(HCURSOR cursor)
1271    {
1272            g_current_cursor = (Cursor) cursor;
1273            XDefineCursor(g_display, g_wnd, g_current_cursor);
1274  }  }
1275    
1276    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  HCOLOURMAP
1290  ui_create_colourmap(COLOURMAP *colours)  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                            }
1362    
1363                  xentry->pixel = i;  
1364                  xentry->red = entry->red << 8;                          /* byte swap here to make translate_image faster */
1365                  xentry->blue = entry->blue << 8;                          map[i] = translate_colour(colour);
1366                  xentry->green = entry->green << 8;                  }
1367                  xentry->flags = DoRed | DoBlue | DoGreen;                  return map;
1368          }          }
1369            else
1370            {
1371                    XColor *xcolours, *xentry;
1372                    Colormap map;
1373    
1374          map = XCreateColormap(display, wnd, visual, AllocAll);                  xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1375          XStoreColors(display, map, xcolours, ncolours);                  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          xfree(xcolours);                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1384          return (HCOLOURMAP) map;                  XStoreColors(g_display, map, xcolours, ncolours);
1385    
1386                    xfree(xcolours);
1387                    return (HCOLOURMAP) map;
1388            }
1389  }  }
1390    
1391  void  void
1392  ui_destroy_colourmap(HCOLOURMAP map)  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  void
1401  ui_set_colourmap(HCOLOURMAP map)  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  void
# Line 334  ui_set_clip(int x, int y, int cx, int cy Line 1420  ui_set_clip(int x, int y, int cx, int cy
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  void
1427  ui_reset_clip()  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  void
1439  ui_bell()  ui_bell(void)
 {  
         XBell(display, 0);  
 }  
   
 static int rop2_map[] = {  
         GXclear,                /* 0 */  
         GXnor,                  /* DPon */  
         GXandInverted,          /* DPna */  
         GXcopyInverted,         /* Pn */  
         GXandReverse,           /* PDna */  
         GXinvert,               /* Dn */  
         GXxor,                  /* DPx */  
         GXnand,                 /* DPan */  
         GXand,                  /* DPa */  
         GXequiv,                /* DPxn */  
         GXnoop,                 /* D */  
         GXorInverted,           /* DPno */  
         GXcopy,                 /* P */  
         GXorReverse,            /* PDno */  
         GXor,                   /* DPo */  
         GXset                   /* 1 */  
 };  
   
 static void  
 xwin_set_function(uint8 rop2)  
1440  {  {
1441          XSetFunction(display, gc, rop2_map[rop2]);          XBell(g_display, 0);
1442  }  }
1443    
1444  void  void
1445  ui_destblt(uint8 opcode,  ui_destblt(uint8 opcode,
1446             /* dest */ int x, int y, int cx, int cy)             /* dest */ int x, int y, int cx, int cy)
1447  {  {
1448          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1449            FILL_RECTANGLE(x, y, cx, cy);
1450          XFillRectangle(display, wnd, gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
1451  }  }
1452    
1453    static uint8 hatch_patterns[] = {
1454            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1455            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1456            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1457            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1458            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  void
1463  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1464            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1465            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* 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                            SET_FOREGROUND(bgcolour);
1483                            SET_BACKGROUND(fgcolour);
1484                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1485                            XSetStipple(g_display, g_gc, fill);
1486                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1487                            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                          XSetForeground(dpy, gc, fgcolour);                  case 3: /* Pattern */
1494                          XSetBackground(dpy, gc, bgcolour);                          for (i = 0; i != 8; i++)
1495                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                                  ipattern[7 - i] = brush->pattern[i];
1496                          XSetStipple(dpy, gc, fill);                          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                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1505    
1506                          XSetFillStyle(dpy, gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
1507                            XSetTSOrigin(g_display, g_gc, 0, 0);
1508                          ui_destroy_glyph((HGLYPH) fill);                          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          }          }
1514    
1515            RESET_FUNCTION(opcode);
1516  }  }
1517    
1518  void  void
# Line 430  ui_screenblt(uint8 opcode, Line 1520  ui_screenblt(uint8 opcode,
1520               /* dest */ int x, int y, int cx, int cy,               /* dest */ int x, int y, int cx, int cy,
1521               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
1522  {  {
1523          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1524            XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1525          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          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  void
# Line 440  ui_memblt(uint8 opcode, Line 1532  ui_memblt(uint8 opcode,
1532            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1533            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1534  {  {
1535          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1536            XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1537          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          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  void
1543  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1544            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1545            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1546            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* 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. */
# Line 458  ui_triblt(uint8 opcode, Line 1552  ui_triblt(uint8 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);
1562                                    brush, bgcolour, fgcolour);                          break;
1563    
1564                    case 0xc0:      /* PSa */
1565                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1566                            ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1567                          break;                          break;
1568    
1569                  default:                  default:
1570                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
1571                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1572          }          }
1573  }  }
# Line 479  ui_triblt(uint8 opcode, Line 1575  ui_triblt(uint8 opcode,
1575  void  void
1576  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1577          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1578          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1579  {  {
1580          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1581            SET_FOREGROUND(pen->colour);
1582          XSetForeground(display, gc, pen->colour);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1583          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          if (g_ownbackstore)
1584                    XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1585            RESET_FUNCTION(opcode);
1586  }  }
1587    
1588  void  void
# Line 492  ui_rect( Line 1590  ui_rect(
1590                 /* dest */ int x, int y, int cx, int cy,                 /* dest */ int x, int y, int cx, int cy,
1591                 /* brush */ int colour)                 /* brush */ int colour)
1592  {  {
1593          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(colour);
1594            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(display, gc, colour);  
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1595  }  }
1596    
1597    /* warning, this function only draws on wnd or backstore, not both */
1598  void  void
1599  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1600                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1601                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1602                int fgcolour)                int bgcolour, int fgcolour)
1603  {  {
1604          Pixmap pixmap = (Pixmap) glyph;          SET_FOREGROUND(fgcolour);
1605            SET_BACKGROUND(bgcolour);
         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);  
                         break;  
1606    
1607                  default:          XSetFillStyle(g_display, g_gc,
1608                          NOTIMP("mix %d\n", mixmode);                        (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  void
1651  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1652               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
1653               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1654               int bgcolour, int fgcolour, uint8 *text, uint8 length)               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 + (short) glyph->offset,                          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  void
1733  ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)  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  void
# Line 588  ui_desktop_restore(uint32 offset, int x, Line 1759  ui_desktop_restore(uint32 offset, int x,
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.25  
changed lines
  Added in v.472

  ViewVC Help
Powered by ViewVC 1.1.26