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

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

  ViewVC Help
Powered by ViewVC 1.1.26