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

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

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26