/[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 53 by matthewc, Tue May 28 11:48:55 2002 UTC revision 373 by jsorg71, Thu May 15 14:26:15 2003 UTC
# Line 1  Line 1 
1  /*  /*
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
# Line 20  Line 20 
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
 #include <X11/XKBlib.h>  
23  #include <time.h>  #include <time.h>
24  #include <errno.h>  #include <errno.h>
25  #include "rdesktop.h"  #include "rdesktop.h"
26    
 extern char keymapname[16];  
 extern int keylayout;  
27  extern int width;  extern int width;
28  extern int height;  extern int height;
29  extern BOOL sendmotion;  extern BOOL sendmotion;
30  extern BOOL fullscreen;  extern BOOL fullscreen;
31    extern BOOL grab_keyboard;
32    extern BOOL hide_decorations;
33    extern char title[];
34    extern int server_bpp;
35    extern int win_button_size;
36    BOOL enable_compose = False;
37    BOOL focused;
38    BOOL mouse_in_wnd;
39    
40  Display *display;  Display *display;
 XkbDescPtr xkb;  
41  static int x_socket;  static int x_socket;
42    static Screen *screen;
43  static Window wnd;  static Window wnd;
44  static GC gc;  static GC gc;
45  static Visual *visual;  static Visual *visual;
46  static int depth;  static int depth;
47  static int bpp;  static int bpp;
48    static XIM IM;
49    static XIC IC;
50    static XModifierKeymap *mod_map;
51    static Cursor current_cursor;
52    static Atom protocol_atom, kill_atom;
53    
54  /* endianness */  /* endianness */
55  static BOOL host_be;  static BOOL host_be;
# Line 49  static BOOL xserver_be; Line 59  static BOOL xserver_be;
59  static BOOL ownbackstore;  static BOOL ownbackstore;
60  static Pixmap backstore;  static Pixmap backstore;
61    
62  /* needed to keep track of the modifiers */  /* Moving in single app mode */
63  static unsigned int key_modifier_state = 0;  static BOOL moving_wnd;
64  static unsigned int key_down_state = 0;  static int move_x_offset = 0;
65    static int move_y_offset = 0;
66  #define DShift1Mask   (1<<0)  
67  #define DShift2Mask   (1<<1)  /* MWM decorations */
68  #define DControl1Mask (1<<2)  #define MWM_HINTS_DECORATIONS   (1L << 1)
69  #define DControl2Mask (1<<3)  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
70  #define DMod1Mask     (1<<4)  typedef struct
71  #define DMod2Mask     (1<<5)  {
72            uint32 flags;
73            uint32 functions;
74            uint32 decorations;
75            sint32 inputMode;
76            uint32 status;
77    }
78    PropMotifWmHints;
79    
80    typedef struct
81    {
82            uint32 red;
83            uint32 green;
84            uint32 blue;
85    }
86    PixelColour;
87    
88  #define FILL_RECTANGLE(x,y,cx,cy)\  #define FILL_RECTANGLE(x,y,cx,cy)\
89  { \  { \
# Line 67  static unsigned int key_down_state = 0; Line 92  static unsigned int key_down_state = 0;
92                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \                  XFillRectangle(display, backstore, gc, x, y, cx, cy); \
93  }  }
94    
95    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
96    { \
97            XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \
98    }
99    
100  /* colour maps */  /* colour maps */
101  static BOOL owncolmap;  BOOL owncolmap = False;
102  static Colormap xcolmap;  static Colormap xcolmap;
 static uint32 white;  
103  static uint32 *colmap;  static uint32 *colmap;
104    
105  #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )  #define TRANSLATE(col)          ( server_bpp != 8 ? translate_colour(col) : owncolmap ? col : translate_colour(colmap[col]) )
106  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
107  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
108    
# Line 99  static int rop2_map[] = { Line 128  static int rop2_map[] = {
128  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
129  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
130    
131  void xwin_release_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode);  static void
132  void xwin_press_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode);  mwm_hide_decorations(void)
133    {
134            PropMotifWmHints motif_hints;
135            Atom hintsatom;
136    
137            /* setup the property */
138            motif_hints.flags = MWM_HINTS_DECORATIONS;
139            motif_hints.decorations = 0;
140    
141            /* get the atom for the property */
142            hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
143            if (!hintsatom)
144            {
145                    warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
146                    return;
147            }
148    
149            XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
150                            (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
151    }
152    
153    static PixelColour
154    split_colour15(uint32 colour)
155    {
156            PixelColour rv;
157            rv.red = (colour & 0x7c00) >> 10;
158            rv.red = (rv.red * 0xff) / 0x1f;
159            rv.green = (colour & 0x03e0) >> 5;
160            rv.green = (rv.green * 0xff) / 0x1f;
161            rv.blue = (colour & 0x1f);
162            rv.blue = (rv.blue * 0xff) / 0x1f;
163            return rv;
164    }
165    
166    static PixelColour
167    split_colour16(uint32 colour)
168    {
169            PixelColour rv;
170            rv.red = (colour & 0xf800) >> 11;
171            rv.red = (rv.red * 0xff) / 0x1f;
172            rv.green = (colour & 0x07e0) >> 5;
173            rv.green = (rv.green * 0xff) / 0x3f;
174            rv.blue = (colour & 0x001f);
175            rv.blue = (rv.blue * 0xff) / 0x1f;
176            return rv;
177    }
178    
179    static PixelColour
180    split_colour24(uint32 colour)
181    {
182            PixelColour rv;
183            rv.blue = (colour & 0xff0000) >> 16;
184            rv.green = (colour & 0xff00) >> 8;
185            rv.red = (colour & 0xff);
186            return rv;
187    }
188    
189    static uint32
190    make_colour16(PixelColour pc)
191    {
192            pc.red = (pc.red * 0x1f) / 0xff;
193            pc.green = (pc.green * 0x3f) / 0xff;
194            pc.blue = (pc.blue * 0x1f) / 0xff;
195            return (pc.red << 11) | (pc.green << 5) | pc.blue;
196    }
197    
198    static uint32
199    make_colour24(PixelColour pc)
200    {
201            return (pc.red << 16) | (pc.green << 8) | pc.blue;
202    }
203    
204    static uint32
205    make_colour32(PixelColour pc)
206    {
207            return (pc.red << 16) | (pc.green << 8) | pc.blue;
208    }
209    
210    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
211    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
212    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
213                            x = (x << 16) | (x >> 16); }
214    
215    static uint32
216    translate_colour(uint32 colour)
217    {
218            switch (server_bpp)
219            {
220                    case 15:
221                            switch (bpp)
222                            {
223                                    case 16:
224                                            colour = make_colour16(split_colour15(colour));
225                                            break;
226                                    case 24:
227                                            colour = make_colour24(split_colour15(colour));
228                                            break;
229                                    case 32:
230                                            colour = make_colour32(split_colour15(colour));
231                                            break;
232                            }
233                            break;
234                    case 16:
235                            switch (bpp)
236                            {
237                                    case 16:
238                                            break;
239                                    case 24:
240                                            colour = make_colour24(split_colour16(colour));
241                                            break;
242                                    case 32:
243                                            colour = make_colour32(split_colour16(colour));
244                                            break;
245                            }
246                            break;
247                    case 24:
248                            switch (bpp)
249                            {
250                                    case 16:
251                                            colour = make_colour16(split_colour24(colour));
252                                            break;
253                                    case 24:
254                                            break;
255                                    case 32:
256                                            colour = make_colour32(split_colour24(colour));
257                                            break;
258                            }
259                            break;
260            }
261            switch (bpp)
262            {
263                    case 16:
264                            if (host_be != xserver_be)
265                                    BSWAP16(colour);
266                            break;
267    
268                    case 24:
269                            if (xserver_be)
270                                    BSWAP24(colour);
271                            break;
272    
273                    case 32:
274                            if (host_be != xserver_be)
275                                    BSWAP32(colour);
276                            break;
277            }
278    
279            return colour;
280    }
281    
282  static void  static void
283  translate8(uint8 *data, uint8 *out, uint8 *end)  translate8to8(uint8 * data, uint8 * out, uint8 * end)
284  {  {
285          while (out < end)          while (out < end)
286                  *(out++) = (uint8)colmap[*(data++)];                  *(out++) = (uint8) colmap[*(data++)];
287  }  }
288    
289  static void  static void
290  translate16(uint8 *data, uint16 *out, uint16 *end)  translate8to16(uint8 * data, uint16 * out, uint16 * end)
291  {  {
292          while (out < end)          while (out < end)
293                  *(out++) = (uint16)colmap[*(data++)];                  *(out++) = (uint16) colmap[*(data++)];
294  }  }
295    
296  /* little endian - conversion happens when colourmap is built */  /* little endian - conversion happens when colourmap is built */
297  static void  static void
298  translate24(uint8 *data, uint8 *out, uint8 *end)  translate8to24(uint8 * data, uint8 * out, uint8 * end)
299  {  {
300          uint32 value;          uint32 value;
301    
# Line 132  translate24(uint8 *data, uint8 *out, uin Line 309  translate24(uint8 *data, uint8 *out, uin
309  }  }
310    
311  static void  static void
312  translate32(uint8 *data, uint32 *out, uint32 *end)  translate8to32(uint8 * data, uint32 * out, uint32 * end)
313  {  {
314          while (out < end)          while (out < end)
315                  *(out++) = colmap[*(data++)];                  *(out++) = colmap[*(data++)];
316  }  }
317    
318  static uint8 *  /* todo the remaining translate function might need some big endian check ?? */
 translate_image(int width, int height, uint8 *data)  
 {  
         int size = width * height * bpp/8;  
         uint8 *out = xmalloc(size);  
         uint8 *end = out + size;  
319    
320          switch (bpp)  static void
321          {  translate15to16(uint16 * data, uint16 * out, uint16 * end)
322                  case 8:  {
323                          translate8(data, out, end);          while (out < end)
324                          break;                  *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
325    }
                 case 16:  
                         translate16(data, (uint16 *)out, (uint16 *)end);  
                         break;  
326    
327                  case 24:  static void
328                          translate24(data, out, end);  translate15to24(uint16 * data, uint8 * out, uint8 * end)
329                          break;  {
330            uint32 value;
331    
332                  case 32:          while (out < end)
333                          translate32(data, (uint32 *)out, (uint32 *)end);          {
334                          break;                  value = make_colour24(split_colour15(*(data++)));
335                    *(out++) = value;
336                    *(out++) = value >> 8;
337                    *(out++) = value >> 16;
338          }          }
339    }
340    
341          return out;  static void
342    translate15to32(uint16 * data, uint32 * out, uint32 * end)
343    {
344            while (out < end)
345                    *(out++) = make_colour32(split_colour15(*(data++)));
346  }  }
347    
348  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }  static void
349  #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }  translate16to16(uint16 * data, uint16 * out, uint16 * end)
350  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  {
351                          x = (x << 16) | (x >> 16); }          while (out < end)
352                    *(out++) = (uint16) (*(data++));
353    }
354    
355  static uint32  
356  translate_colour(uint32 colour)  static void
357    translate16to24(uint16 * data, uint8 * out, uint8 * end)
358  {  {
359          switch (bpp)          uint32 value;
360    
361            while (out < end)
362          {          {
363                  case 16:                  value = make_colour24(split_colour16(*(data++)));
364                          if (host_be != xserver_be)                  *(out++) = value;
365                                  BSWAP16(colour);                  *(out++) = value >> 8;
366                          break;                  *(out++) = value >> 16;
367            }
368    }
369    
370                  case 24:  static void
371                          if (xserver_be)  translate16to32(uint16 * data, uint32 * out, uint32 * end)
372                                  BSWAP24(colour);  {
373                          break;          while (out < end)
374                    *(out++) = make_colour32(split_colour16(*(data++)));
375    }
376    
377                  case 32:  static void
378                          if (host_be != xserver_be)  translate24to16(uint8 * data, uint16 * out, uint16 * end)
379                                  BSWAP32(colour);  {
380                          break;          uint32 pixel = 0;
381            while (out < end)
382            {
383                    pixel = *(data++) << 16;
384                    pixel |= *(data++) << 8;
385                    pixel |= *(data++);
386                    *(out++) = (uint16) make_colour16(split_colour24(pixel));
387          }          }
388    }
389    
390          return colour;  static void
391    translate24to24(uint8 * data, uint8 * out, uint8 * end)
392    {
393            while (out < end)
394            {
395                    *(out++) = (*(data++));
396            }
397  }  }
398    
399  BOOL  static void
400  ui_create_window(char *title)  translate24to32(uint8 * data, uint32 * out, uint32 * end)
401  {  {
402          XSetWindowAttributes attribs;          uint32 pixel = 0;
403          XClassHint *classhints;          while (out < end)
         XSizeHints *sizehints;  
         unsigned long input_mask;  
         XPixmapFormatValues *pfm;  
         Screen *screen;  
         uint16 test;  
         int i;  
           
         int xkb_minor, xkb_major;  
         int xkb_event, xkb_error, xkb_reason;  
   
         /* compare compiletime libs with runtime libs. */  
         xkb_major = XkbMajorVersion;  
         xkb_minor = XkbMinorVersion;  
         if( XkbLibraryVersion( &xkb_major, &xkb_minor ) == False )  
404          {          {
405                  error("please re-compile rdesktop\ncompile time version of xkb is not compatible with\nyour runtime version of the library\n");                  pixel = *(data++);
406                  return False;                  pixel |= *(data++) << 8;
407                    pixel |= *(data++) << 16;
408                    *(out++) = pixel;
409          }          }
410    }
411    
412    static uint8 *
413    translate_image(int width, int height, uint8 * data)
414    {
415            int size = width * height * bpp / 8;
416            uint8 *out = xmalloc(size);
417            uint8 *end = out + size;
418    
419          /* XKB is the 'new' keyboard handler in x.. ( the xkb code in Xfree86 originates from SGI, years 1993 and 1995 from what I could tell. )          switch (server_bpp)
          * it makes it possible for people with disabilities to use rdesktop, stickykeys, bouncekeys etc. VERY MUCH useful.  
          * XFree86 has had support for it since it's earliest incarnation. I believe it is a reasonable dependency.  
          */  
         display = XkbOpenDisplay( NULL, &xkb_event, &xkb_error, &xkb_major, &xkb_minor, &xkb_reason );  
         switch(xkb_reason)  
420          {          {
421                  case XkbOD_BadLibraryVersion:                  case 24:
422                          error("XkbOD_BadLibraryVersion: XKB extensions in server and the library rdesktop is linked against aren't compatible with each other.\n");                          switch (bpp)
423                          break;                          {
424                  case XkbOD_ConnectionRefused:                                  case 32:
425                          error("XkbOD_ConnectionRefused\n");                                          translate24to32(data, (uint32 *) out, (uint32 *) end);
426                                            break;
427                                    case 24:
428                                            translate24to24(data, out, end);
429                                            break;
430                                    case 16:
431                                            translate24to16(data, (uint16 *) out, (uint16 *) end);
432                                            break;
433                            }
434                          break;                          break;
435                  case XkbOD_BadServerVersion:                  case 16:
436                          error("XkbOD_BadServerVersion\n");                          switch (bpp)
437                            {
438                                    case 32:
439                                            translate16to32((uint16 *) data, (uint32 *) out,
440                                                            (uint32 *) end);
441                                            break;
442                                    case 24:
443                                            translate16to24((uint16 *) data, out, end);
444                                            break;
445                                    case 16:
446                                            translate16to16((uint16 *) data, (uint16 *) out,
447                                                            (uint16 *) end);
448                                            break;
449                            }
450                          break;                          break;
451                  case XkbOD_NonXkbServer:                  case 15:
452                          error("XkbOD_NonXkbServer: XKB extension not present in server\nupdate your X server.\n");                          switch (bpp)
453                            {
454                                    case 32:
455                                            translate15to32((uint16 *) data, (uint32 *) out,
456                                                            (uint32 *) end);
457                                            break;
458                                    case 24:
459                                            translate15to24((uint16 *) data, out, end);
460                                            break;
461                                    case 16:
462                                            translate15to16((uint16 *) data, (uint16 *) out,
463                                                            (uint16 *) end);
464                                            break;
465                            }
466                          break;                          break;
467                  case XkbOD_Success:                  case 8:
468                          DEBUG("XkbOD_Success: Connection established with display\n");                          switch (bpp)
469                            {
470                                    case 8:
471                                            translate8to8(data, out, end);
472                                            break;
473                                    case 16:
474                                            translate8to16(data, (uint16 *) out, (uint16 *) end);
475                                            break;
476                                    case 24:
477                                            translate8to24(data, out, end);
478                                            break;
479                                    case 32:
480                                            translate8to32(data, (uint32 *) out, (uint32 *) end);
481                                            break;
482                            }
483                          break;                          break;
484          }          }
485            return out;
486    }
487    
488    BOOL
489    get_key_state(unsigned int state, uint32 keysym)
490    {
491            int modifierpos, key, keysymMask = 0;
492            int offset;
493    
494            KeyCode keycode = XKeysymToKeycode(display, keysym);
495    
496            if (keycode == NoSymbol)
497                    return False;
498    
499            for (modifierpos = 0; modifierpos < 8; modifierpos++)
500            {
501                    offset = mod_map->max_keypermod * modifierpos;
502    
503                    for (key = 0; key < mod_map->max_keypermod; key++)
504                    {
505                            if (mod_map->modifiermap[offset + key] == keycode)
506                                    keysymMask |= 1 << modifierpos;
507                    }
508            }
509    
510            return (state & keysymMask) ? True : False;
511    }
512    
513    BOOL
514    ui_init(void)
515    {
516            XPixmapFormatValues *pfm;
517            uint16 test;
518            int i;
519    
520            display = XOpenDisplay(NULL);
521          if (display == NULL)          if (display == NULL)
522          {          {
523                  error("Failed to open display\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
524                  return False;                  return False;
525          }          }
526    
# Line 255  ui_create_window(char *title) Line 528  ui_create_window(char *title)
528          screen = DefaultScreenOfDisplay(display);          screen = DefaultScreenOfDisplay(display);
529          visual = DefaultVisualOfScreen(screen);          visual = DefaultVisualOfScreen(screen);
530          depth = DefaultDepthOfScreen(screen);          depth = DefaultDepthOfScreen(screen);
531            
532          pfm = XListPixmapFormats(display, &i);          pfm = XListPixmapFormats(display, &i);
533          if (pfm != NULL)          if (pfm != NULL)
534          {          {
# Line 263  ui_create_window(char *title) Line 536  ui_create_window(char *title)
536                     desirable, e.g. 24 bits->32 bits. */                     desirable, e.g. 24 bits->32 bits. */
537                  while (i--)                  while (i--)
538                  {                  {
539                          if ((pfm[i].depth == depth)                          if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
                             && (pfm[i].bits_per_pixel > bpp))  
540                          {                          {
541                                  bpp = pfm[i].bits_per_pixel;                                  bpp = pfm[i].bits_per_pixel;
542                          }                          }
# Line 279  ui_create_window(char *title) Line 551  ui_create_window(char *title)
551                  return False;                  return False;
552          }          }
553    
554          if (depth <= 8)          if (owncolmap != True)
555                  owncolmap = True;          {
         else  
556                  xcolmap = DefaultColormapOfScreen(screen);                  xcolmap = DefaultColormapOfScreen(screen);
557                    if (depth <= 8)
558                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
559            }
560    
561            gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
562    
563            if (DoesBackingStore(screen) != Always)
564                    ownbackstore = True;
565    
566          test = 1;          test = 1;
567          host_be = !(BOOL)(*(uint8 *)(&test));          host_be = !(BOOL) (*(uint8 *) (&test));
568          xserver_be = (ImageByteOrder(display) == MSBFirst);          xserver_be = (ImageByteOrder(display) == MSBFirst);
569    
570          white = WhitePixelOfScreen(screen);          if ((width == 0) || (height == 0))
571          attribs.background_pixel = BlackPixelOfScreen(screen);          {
572          attribs.backing_store = DoesBackingStore(screen);                  /* Fetch geometry from _NET_WORKAREA */
573                    uint32 x, y, cx, cy;
574    
575          if (attribs.backing_store == NotUseful)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
576                  ownbackstore = True;                  {
577                            width = cx;
578                            height = cy;
579                    }
580                    else
581                    {
582                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
583                            width = 800;
584                            height = 600;
585                    }
586            }
587    
588          if (fullscreen)          if (fullscreen)
589          {          {
                 attribs.override_redirect = True;  
590                  width = WidthOfScreen(screen);                  width = WidthOfScreen(screen);
591                  height = HeightOfScreen(screen);                  height = HeightOfScreen(screen);
592          }          }
593          else  
594            /* make sure width is a multiple of 4 */
595            width = (width + 3) & ~3;
596    
597            if (ownbackstore)
598          {          {
599                  attribs.override_redirect = False;                  backstore =
600                            XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
601    
602                    /* clear to prevent rubbish being exposed at startup */
603                    XSetForeground(display, gc, BlackPixelOfScreen(screen));
604                    XFillRectangle(display, backstore, gc, 0, 0, width, height);
605          }          }
606    
607          width = (width + 3) & ~3; /* make width a multiple of 32 bits */          mod_map = XGetModifierMapping(display);
608    
609            if (enable_compose)
610                    IM = XOpenIM(display, NULL, NULL, NULL);
611    
612            xkeymap_init();
613    
614            /* todo take this out when high colour is done */
615            printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth);
616    
617            return True;
618    }
619    
620    void
621    ui_deinit(void)
622    {
623            if (IM != NULL)
624                    XCloseIM(IM);
625    
626            XFreeModifiermap(mod_map);
627    
628            if (ownbackstore)
629                    XFreePixmap(display, backstore);
630    
631            XFreeGC(display, gc);
632            XCloseDisplay(display);
633            display = NULL;
634    }
635    
636    BOOL
637    ui_create_window(void)
638    {
639            XSetWindowAttributes attribs;
640            XClassHint *classhints;
641            XSizeHints *sizehints;
642            int wndwidth, wndheight;
643            long input_mask, ic_input_mask;
644            XEvent xevent;
645    
646            wndwidth = fullscreen ? WidthOfScreen(screen) : width;
647            wndheight = fullscreen ? HeightOfScreen(screen) : height;
648    
649            attribs.background_pixel = BlackPixelOfScreen(screen);
650            attribs.backing_store = ownbackstore ? NotUseful : Always;
651            attribs.override_redirect = fullscreen;
652    
653          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
654                              0, 0, width, height, 0, CopyFromParent,                              0, CopyFromParent, InputOutput, CopyFromParent,
655                              InputOutput, CopyFromParent,                              CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
                             CWBackingStore | CWBackPixel | CWOverrideRedirect,  
                             &attribs);  
656    
657          XStoreName(display, wnd, title);          XStoreName(display, wnd, title);
658    
659            if (hide_decorations)
660                    mwm_hide_decorations();
661    
662          classhints = XAllocClassHint();          classhints = XAllocClassHint();
663          if (classhints != NULL)          if (classhints != NULL)
664          {          {
# Line 334  ui_create_window(char *title) Line 677  ui_create_window(char *title)
677                  XFree(sizehints);                  XFree(sizehints);
678          }          }
679    
680          xkeymap_init();          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
681                    VisibilityChangeMask | FocusChangeMask;
682    
         input_mask = KeyPressMask | KeyReleaseMask |  
                          ButtonPressMask | ButtonReleaseMask |  
                          EnterWindowMask | LeaveWindowMask | KeymapStateMask;  
683          if (sendmotion)          if (sendmotion)
684                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
   
685          if (ownbackstore)          if (ownbackstore)
686                  input_mask |= ExposureMask;                  input_mask |= ExposureMask;
687            if (fullscreen || grab_keyboard)
688                    input_mask |= EnterWindowMask;
689            if (grab_keyboard)
690                    input_mask |= LeaveWindowMask;
691    
692            if (IM != NULL)
693            {
694                    IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
695                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
696    
697                    if ((IC != NULL)
698                        && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
699                            input_mask |= ic_input_mask;
700            }
701    
702          XSelectInput(display, wnd, input_mask);          XSelectInput(display, wnd, input_mask);
         gc = XCreateGC(display, wnd, 0, NULL);  
   
         if (ownbackstore)  
                 backstore = XCreatePixmap(display, wnd, width, height, depth);  
   
703          XMapWindow(display, wnd);          XMapWindow(display, wnd);
704    
705          /* TODO: error texts... make them friendly. */          /* wait for VisibilityNotify */
706          xkb = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);          do
         if ((int)xkb == BadAlloc || xkb == NULL)  
         {  
                         error( "XkbGetKeyboard failed.\n");  
                         exit(0);  
         }  
   
         /* TODO: error texts... make them friendly. */  
         if( XkbSelectEvents(display, xkb->device_spec, XkbAllEventsMask, XkbAllEventsMask) == False )  
707          {          {
708                          error( "XkbSelectEvents failed.\n");                  XMaskEvent(display, VisibilityChangeMask, &xevent);
                         exit(0);  
709          }          }
710            while (xevent.type != VisibilityNotify);
711    
712            focused = False;
713            mouse_in_wnd = False;
714    
715            /* handle the WM_DELETE_WINDOW protocol */
716            protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
717            kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
718            XSetWMProtocols(display, wnd, &kill_atom, 1);
719    
720          return True;          return True;
721  }  }
722    
723  void  void
724  ui_destroy_window()  ui_destroy_window(void)
725  {  {
726          if( xkb != NULL )          if (IC != NULL)
727                  XkbFreeKeyboard(xkb, XkbAllControlsMask, True);                  XDestroyIC(IC);
728    
         if (ownbackstore)  
                 XFreePixmap(display, backstore);  
   
         XFreeGC(display, gc);  
729          XDestroyWindow(display, wnd);          XDestroyWindow(display, wnd);
         XCloseDisplay(display);  
         display = NULL;  
730  }  }
731    
732  static void  void
733  xwin_process_events()  xwin_toggle_fullscreen(void)
734  {  {
735          XkbEvent xkbevent;          Pixmap contents = 0;
736            
737            if (!ownbackstore)
738            {
739                    /* need to save contents of window */
740                    contents = XCreatePixmap(display, wnd, width, height, depth);
741                    XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
742            }
743    
744            ui_destroy_window();
745            fullscreen = !fullscreen;
746            ui_create_window();
747    
748            XDefineCursor(display, wnd, current_cursor);
749    
750            if (!ownbackstore)
751            {
752                    XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
753                    XFreePixmap(display, contents);
754            }
755    }
756    
757    /* Process all events in Xlib queue
758       Returns 0 after user quit, 1 otherwise */
759    static int
760    xwin_process_events(void)
761    {
762            XEvent xevent;
763          KeySym keysym;          KeySym keysym;
         uint8 scancode;  
764          uint16 button, flags;          uint16 button, flags;
765          uint32 ev_time;          uint32 ev_time;
766          uint32 tmpmods;          key_translation tr;
767            char str[256];
768            Status status;
769            unsigned int state;
770            Window wdummy;
771            int dummy;
772    
773          while (XCheckMaskEvent(display, ~0, &xkbevent.core))          while (XPending(display) > 0)
774          {          {
775                  ev_time = time(NULL);                  XNextEvent(display, &xevent);
776    
777                    if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
778                    {
779                            DEBUG_KBD(("Filtering event\n"));
780                            continue;
781                    }
782    
783                  flags = 0;                  flags = 0;
784    
785                  switch (xkbevent.type)                  switch (xevent.type)
786                  {                  {
787                          case KeymapNotify:                          case ClientMessage:
788                                  /* TODO:                                  /* the window manager told us to quit */
789                                   * read modifier status at focus in, and update the local masks, and the other end as well..                                  if ((xevent.xclient.message_type == protocol_atom)
790                                   * if not, we may get out of sync.                                      && (xevent.xclient.data.l[0] == kill_atom))
791                                   * xkbevent.core.xkeymap.key_vector                                          /* Quit */
792                                   * char key_vector[32];                                          return 0;
                                  */  
793                                  break;                                  break;
794    
                         case KeyRelease:  
                                 flags = KBD_FLAG_DOWN | KBD_FLAG_UP;  
                                 /* fall through */  
   
795                          case KeyPress:                          case KeyPress:
796                                  if( XkbTranslateKeyCode(xkb, xkbevent.core.xkey.keycode, xkbevent.core.xkey.state, &tmpmods, &keysym) == False )                                  if (IC != NULL)
797                                            /* Multi_key compatible version */
798                                    {
799                                            XmbLookupString(IC,
800                                                            (XKeyPressedEvent *) &
801                                                            xevent, str, sizeof(str), &keysym, &status);
802                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
803                                            {
804                                                    error("XmbLookupString failed with status 0x%x\n",
805                                                          status);
806                                                    break;
807                                            }
808                                    }
809                                    else
810                                    {
811                                            /* Plain old XLookupString */
812                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
813                                            XLookupString((XKeyEvent *) & xevent,
814                                                          str, sizeof(str), &keysym, NULL);
815                                    }
816    
817                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
818                                               get_ksname(keysym)));
819    
820                                    ev_time = time(NULL);
821                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
822                                          break;                                          break;
                                 scancode = xkeymap_translate_key(keysym, xkbevent.core.xkey.keycode, &flags);  
823    
824                                  if (scancode == 0 )                                  tr = xkeymap_translate_key(keysym,
825                                                               xevent.xkey.keycode, xevent.xkey.state);
826    
827                                    if (tr.scancode == 0)
828                                          break;                                          break;
829    
830                                  /* keep track of the modifiers -- needed for stickykeys... */                                  ensure_remote_modifiers(ev_time, tr);
831                                  if( xkbevent.type == KeyPress )  
832                                          xwin_press_modifiers( &xkbevent.core.xkey, ev_time, scancode );                                  rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
833                                    break;
834    
835                            case KeyRelease:
836                                    XLookupString((XKeyEvent *) & xevent, str,
837                                                  sizeof(str), &keysym, NULL);
838    
839                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
840                                               get_ksname(keysym)));
841    
842                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, flags, scancode, 0);                                  ev_time = time(NULL);
843                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
844                                            break;
845    
846                                    tr = xkeymap_translate_key(keysym,
847                                                               xevent.xkey.keycode, xevent.xkey.state);
848    
849                                  if( xkbevent.type == KeyRelease )                                  if (tr.scancode == 0)
850                                          xwin_release_modifiers( &xkbevent.core.xkey, ev_time, scancode );                                          break;
851    
852                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
853                                  break;                                  break;
854    
855                          case ButtonPress:                          case ButtonPress:
# Line 441  xwin_process_events() Line 857  xwin_process_events()
857                                  /* fall through */                                  /* fall through */
858    
859                          case ButtonRelease:                          case ButtonRelease:
860                                  button = xkeymap_translate_button(xkbevent.core.xbutton.button);                                  button = xkeymap_translate_button(xevent.xbutton.button);
861                                  if (button == 0)                                  if (button == 0)
862                                          break;                                          break;
863    
864                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
865                                                 flags | button,                                  if (xevent.xbutton.y < win_button_size)
866                                                 xkbevent.core.xbutton.x,                                  {
867                                                 xkbevent.core.xbutton.y);                                          /* Stop moving window when button is released, regardless of cursor position */
868                                            if (moving_wnd && (xevent.type == ButtonRelease))
869                                                    moving_wnd = False;
870    
871                                            /*  Check from right to left: */
872    
873                                            if (xevent.xbutton.x >= width - win_button_size)
874                                            {
875                                                    /* The close button, continue */
876                                                    ;
877                                            }
878                                            else if (xevent.xbutton.x >= width - win_button_size * 2)
879                                            {
880                                                    /* The maximize/restore button. Do not send to
881                                                       server.  It might be a good idea to change the
882                                                       cursor or give some other visible indication
883                                                       that rdesktop inhibited this click */
884                                                    break;
885                                            }
886                                            else if (xevent.xbutton.x >= width - win_button_size * 3)
887                                            {
888                                                    /* The minimize button. Iconify window. */
889                                                    XIconifyWindow(display, wnd,
890                                                                   DefaultScreen(display));
891                                                    break;
892                                            }
893                                            else if (xevent.xbutton.x <= win_button_size)
894                                            {
895                                                    /* The system menu. Ignore. */
896                                                    break;
897                                            }
898                                            else
899                                            {
900                                                    /* The title bar. */
901                                                    if ((xevent.type == ButtonPress) && !fullscreen
902                                                        && hide_decorations)
903                                                    {
904                                                            moving_wnd = True;
905                                                            move_x_offset = xevent.xbutton.x;
906                                                            move_y_offset = xevent.xbutton.y;
907                                                    }
908                                                    break;
909    
910                                            }
911                                    }
912    
913                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
914                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
915                                  break;                                  break;
916    
917                          case MotionNotify:                          case MotionNotify:
918                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (moving_wnd)
919                                                 MOUSE_FLAG_MOVE,                                  {
920                                                 xkbevent.core.xmotion.x,                                          XMoveWindow(display, wnd,
921                                                 xkbevent.core.xmotion.y);                                                      xevent.xmotion.x_root - move_x_offset,
922                                                        xevent.xmotion.y_root - move_y_offset);
923                                            break;
924                                    }
925    
926                                    if (fullscreen && !focused)
927                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
928                                                           CurrentTime);
929                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
930                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
931                                    break;
932    
933                            case FocusIn:
934                                    if (xevent.xfocus.mode == NotifyGrab)
935                                            break;
936                                    focused = True;
937                                    XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
938                                                  &dummy, &dummy, &state);
939                                    reset_modifier_keys(state);
940                                    if (grab_keyboard && mouse_in_wnd)
941                                            XGrabKeyboard(display, wnd, True,
942                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
943                                    break;
944    
945                            case FocusOut:
946                                    if (xevent.xfocus.mode == NotifyUngrab)
947                                            break;
948                                    focused = False;
949                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
950                                            XUngrabKeyboard(display, CurrentTime);
951                                  break;                                  break;
952    
953                          case EnterNotify:                          case EnterNotify:
954                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,                                  /* we only register for this event when in fullscreen mode */
955                                                GrabModeAsync, CurrentTime);                                  /* or grab_keyboard */
956                                    mouse_in_wnd = True;
957                                    if (fullscreen)
958                                    {
959                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
960                                                           CurrentTime);
961                                            break;
962                                    }
963                                    if (focused)
964                                            XGrabKeyboard(display, wnd, True,
965                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
966                                  break;                                  break;
967    
968                          case LeaveNotify:                          case LeaveNotify:
969                                    /* we only register for this event when grab_keyboard */
970                                    mouse_in_wnd = False;
971                                  XUngrabKeyboard(display, CurrentTime);                                  XUngrabKeyboard(display, CurrentTime);
972                                  break;                                  break;
973    
974                          case Expose:                          case Expose:
975                                  XCopyArea(display, backstore, wnd, gc,                                  XCopyArea(display, backstore, wnd, gc,
976                                            xkbevent.core.xexpose.x, xkbevent.core.xexpose.y,                                            xevent.xexpose.x, xevent.xexpose.y,
977                                            xkbevent.core.xexpose.width, xkbevent.core.xexpose.height,                                            xevent.xexpose.width,
978                                            xkbevent.core.xexpose.x, xkbevent.core.xexpose.y);                                            xevent.xexpose.height,
979                                              xevent.xexpose.x, xevent.xexpose.y);
980                                  break;                                  break;
                 }  
         }  
 }  
   
 void  
 xwin_release_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode)  
 {  
         switch (scancode) {  
         case 0x2a:  
                 key_down_state &= ~DShift1Mask;  
                 break;  
         case 0x36:  
                 key_down_state &= ~DShift2Mask;  
                 break;  
         case 0x1d:  
                 key_down_state &= ~DControl1Mask;  
                 break;  
         case 0x9d:  
                 key_down_state &= ~DControl2Mask;  
                 break;  
         case 0x38:  
                 key_down_state &= ~DMod1Mask;  
                 break;  
         case 0xb8:  
                 key_down_state &= ~DMod2Mask;  
                 break;  
         }  
   
         if( !(ShiftMask & ev->state) && (key_down_state & DShift1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a, 0);  
                 key_down_state &= ~DShift1Mask;  
   
         }  
   
         if( !(ControlMask & ev->state) && (key_down_state & DControl1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d, 0);  
                 key_down_state &= ~DControl1Mask;  
   
         }  
           
         if( !(Mod1Mask & ev->state) && (key_down_state & DMod1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38, 0);  
                 key_down_state &= ~DMod1Mask;  
   
         }  
           
         if( !(Mod2Mask & ev->state) && (key_down_state & DMod2Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8, 0);  
                 key_down_state &= ~DMod2Mask;  
         }  
 }  
   
   
 void  
 xwin_press_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode)  
 {  
         key_modifier_state = ev->state;  
   
         switch (scancode) {  
         case 0x2a:  
                 key_down_state |= DShift1Mask;  
                 break;  
         case 0x36:  
                 key_down_state |= DShift2Mask;  
                 break;  
         case 0x1d:  
                 key_down_state |= DControl1Mask;  
                 break;  
         case 0x9d:  
                 key_down_state |= DControl2Mask;  
                 break;  
         case 0x38:  
                 key_down_state |= DMod1Mask;  
                 break;  
         case 0xb8:  
                 key_down_state |= DMod2Mask;  
                 break;  
         }  
   
         if( (ShiftMask & ev->state) && !((key_down_state & DShift1Mask) || (key_down_state & DShift2Mask)))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x2a, 0);  
                 key_down_state |= DShift1Mask;  
   
         }  
   
         if( (ControlMask & ev->state) && !((key_down_state & DControl1Mask) || (key_down_state & DControl2Mask)))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x1d, 0);  
                 key_down_state |= DControl1Mask;  
   
         }  
   
         if( (Mod1Mask & ev->state) && !(key_down_state & DMod1Mask))  
         {  
                 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x38, 0);  
                 key_down_state |= DMod1Mask;  
981    
982          }                          case MappingNotify:
983                                    /* Refresh keyboard mapping if it has changed. This is important for
984                                       Xvnc, since it allocates keycodes dynamically */
985                                    if (xevent.xmapping.request == MappingKeyboard
986                                        || xevent.xmapping.request == MappingModifier)
987                                            XRefreshKeyboardMapping(&xevent.xmapping);
988    
989          if( (Mod2Mask & ev->state) && !(key_down_state & DMod2Mask))                                  if (xevent.xmapping.request == MappingModifier)
990          {                                  {
991                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0xb8, 0);                                          XFreeModifiermap(mod_map);
992                  key_down_state |= DMod2Mask;                                          mod_map = XGetModifierMapping(display);
993                                    }
994                                    break;
995    
996                    }
997          }          }
998            /* Keep going */
999            return 1;
1000  }  }
1001    
1002  void  /* Returns 0 after user quit, 1 otherwise */
1003    int
1004  ui_select(int rdp_socket)  ui_select(int rdp_socket)
1005  {  {
1006          int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;          int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
1007          fd_set rfds;          fd_set rfds;
1008    
1009          FD_ZERO(&rfds);          FD_ZERO(&rfds);
1010    
1011          while (True)          while (True)
1012          {          {
1013                    /* Process any events already waiting */
1014                    if (!xwin_process_events())
1015                            /* User quit */
1016                            return 0;
1017    
1018                  FD_ZERO(&rfds);                  FD_ZERO(&rfds);
1019                  FD_SET(rdp_socket, &rfds);                  FD_SET(rdp_socket, &rfds);
1020                  if (display != NULL)                  FD_SET(x_socket, &rfds);
                 {  
                         FD_SET(x_socket, &rfds);  
                         XFlush(display);  
                 }  
1021    
1022                  switch (select(n, &rfds, NULL, NULL, NULL))                  switch (select(n, &rfds, NULL, NULL, NULL))
1023                  {                  {
# Line 612  ui_select(int rdp_socket) Line 1028  ui_select(int rdp_socket)
1028                                  continue;                                  continue;
1029                  }                  }
1030    
                 if (FD_ISSET(x_socket, &rfds))  
                         xwin_process_events();  
   
1031                  if (FD_ISSET(rdp_socket, &rfds))                  if (FD_ISSET(rdp_socket, &rfds))
1032                          return;                          return 1;
1033          }          }
1034  }  }
1035    
# Line 627  ui_move_pointer(int x, int y) Line 1040  ui_move_pointer(int x, int y)
1040  }  }
1041    
1042  HBITMAP  HBITMAP
1043  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1044  {  {
1045          XImage *image;          XImage *image;
1046          Pixmap bitmap;          Pixmap bitmap;
# Line 635  ui_create_bitmap(int width, int height, Line 1048  ui_create_bitmap(int width, int height,
1048    
1049          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (owncolmap ? data : translate_image(width, height, data));
1050          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(display, wnd, width, height, depth);
1051          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1052                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1053    
1054          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1055    
# Line 647  ui_create_bitmap(int width, int height, Line 1060  ui_create_bitmap(int width, int height,
1060  }  }
1061    
1062  void  void
1063  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)  
1064  {  {
1065          XImage *image;          XImage *image;
1066          uint8 *tdata;          uint8 *tdata;
   
1067          tdata = (owncolmap ? data : translate_image(width, height, data));          tdata = (owncolmap ? data : translate_image(width, height, data));
1068          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1069                               0, tdata, width, height, 8, 0);                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1070    
1071          if (ownbackstore)          if (ownbackstore)
1072          {          {
# Line 675  ui_paint_bitmap(int x, int y, int cx, in Line 1086  ui_paint_bitmap(int x, int y, int cx, in
1086  void  void
1087  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1088  {  {
1089          XFreePixmap(display, (Pixmap)bmp);          XFreePixmap(display, (Pixmap) bmp);
1090  }  }
1091    
1092  HGLYPH  HGLYPH
1093  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1094  {  {
1095          XImage *image;          XImage *image;
1096          Pixmap bitmap;          Pixmap bitmap;
# Line 691  ui_create_glyph(int width, int height, u Line 1102  ui_create_glyph(int width, int height, u
1102          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
1103          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
1104    
1105          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1106                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1107          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1108          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1109          XInitImage(image);          XInitImage(image);
# Line 701  ui_create_glyph(int width, int height, u Line 1112  ui_create_glyph(int width, int height, u
1112    
1113          XFree(image);          XFree(image);
1114          XFreeGC(display, gc);          XFreeGC(display, gc);
1115          return (HGLYPH)bitmap;          return (HGLYPH) bitmap;
1116  }  }
1117    
1118  void  void
1119  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1120  {  {
1121          XFreePixmap(display, (Pixmap)glyph);          XFreePixmap(display, (Pixmap) glyph);
1122  }  }
1123    
1124  HCURSOR  HCURSOR
1125  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1126                   int height, uint8 *andmask, uint8 *xormask)                   uint8 * andmask, uint8 * xormask)
1127  {  {
1128          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
1129          XColor bg, fg;          XColor bg, fg;
# Line 769  ui_create_cursor(unsigned int x, unsigne Line 1180  ui_create_cursor(unsigned int x, unsigne
1180    
1181          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
1182          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
1183            
1184          xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,          xcursor =
1185                                  (Pixmap)maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1186                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1187    
1188          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
1189          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
1190          xfree(mask);          xfree(mask);
1191          xfree(cursor);          xfree(cursor);
1192          return (HCURSOR)xcursor;          return (HCURSOR) xcursor;
1193  }  }
1194    
1195  void  void
1196  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
1197  {  {
1198          XDefineCursor(display, wnd, (Cursor)cursor);          current_cursor = (Cursor) cursor;
1199            XDefineCursor(display, wnd, current_cursor);
1200  }  }
1201    
1202  void  void
1203  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
1204  {  {
1205          XFreeCursor(display, (Cursor)cursor);          XFreeCursor(display, (Cursor) cursor);
1206  }  }
1207    
1208  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 798  ui_destroy_cursor(HCURSOR cursor) Line 1211  ui_destroy_cursor(HCURSOR cursor)
1211                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1212                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
1213    
1214    
1215  HCOLOURMAP  HCOLOURMAP
1216  ui_create_colourmap(COLOURMAP *colours)  ui_create_colourmap(COLOURMAP * colours)
1217  {  {
1218          COLOURENTRY *entry;          COLOURENTRY *entry;
1219          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1220            if (!owncolmap)
1221            {
1222                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
1223                    XColor xentry;
1224                    XColor xc_cache[256];
1225                    uint32 colour;
1226                    int colLookup = 256;
1227                    for (i = 0; i < ncolours; i++)
1228                    {
1229                            entry = &colours->colours[i];
1230                            MAKE_XCOLOR(&xentry, entry);
1231    
1232                            if (XAllocColor(display, xcolmap, &xentry) == 0)
1233                            {
1234                                    /* Allocation failed, find closest match. */
1235                                    int j = 256;
1236                                    int nMinDist = 3 * 256 * 256;
1237                                    long nDist = nMinDist;
1238    
1239                                    /* only get the colors once */
1240                                    while (colLookup--)
1241                                    {
1242                                            xc_cache[colLookup].pixel = colLookup;
1243                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1244                                                    xc_cache[colLookup].blue = 0;
1245                                            xc_cache[colLookup].flags = 0;
1246                                            XQueryColor(display,
1247                                                        DefaultColormap(display,
1248                                                                        DefaultScreen(display)),
1249                                                        &xc_cache[colLookup]);
1250                                    }
1251                                    colLookup = 0;
1252    
1253                                    /* approximate the pixel */
1254                                    while (j--)
1255                                    {
1256                                            if (xc_cache[j].flags)
1257                                            {
1258                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1259                                                             (long) (xentry.red >> 8)) *
1260                                                            ((long) (xc_cache[j].red >> 8) -
1261                                                             (long) (xentry.red >> 8)) +
1262                                                            ((long) (xc_cache[j].green >> 8) -
1263                                                             (long) (xentry.green >> 8)) *
1264                                                            ((long) (xc_cache[j].green >> 8) -
1265                                                             (long) (xentry.green >> 8)) +
1266                                                            ((long) (xc_cache[j].blue >> 8) -
1267                                                             (long) (xentry.blue >> 8)) *
1268                                                            ((long) (xc_cache[j].blue >> 8) -
1269                                                             (long) (xentry.blue >> 8));
1270                                            }
1271                                            if (nDist < nMinDist)
1272                                            {
1273                                                    nMinDist = nDist;
1274                                                    xentry.pixel = j;
1275                                            }
1276                                    }
1277                            }
1278                            colour = xentry.pixel;
1279    
1280                            /* update our cache */
1281                            if (xentry.pixel < 256)
1282                            {
1283                                    xc_cache[xentry.pixel].red = xentry.red;
1284                                    xc_cache[xentry.pixel].green = xentry.green;
1285                                    xc_cache[xentry.pixel].blue = xentry.blue;
1286    
1287          if (owncolmap)                          }
1288    
1289    
1290                            /* byte swap here to make translate_image faster */
1291                            map[i] = translate_colour(colour);
1292                    }
1293                    return map;
1294            }
1295            else
1296          {          {
1297                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
1298                  Colormap map;                  Colormap map;
# Line 822  ui_create_colourmap(COLOURMAP *colours) Line 1310  ui_create_colourmap(COLOURMAP *colours)
1310                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(display, map, xcolours, ncolours);
1311    
1312                  xfree(xcolours);                  xfree(xcolours);
1313                  return (HCOLOURMAP)map;                  return (HCOLOURMAP) map;
         }  
         else  
         {  
                 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);  
                 XColor xentry;  
                 uint32 colour;  
   
                 for (i = 0; i < ncolours; i++)  
                 {  
                         entry = &colours->colours[i];  
                         MAKE_XCOLOR(&xentry, entry);  
   
                         if (XAllocColor(display, xcolmap, &xentry) != 0)  
                                 colour = xentry.pixel;  
                         else  
                                 colour = white;  
   
                         /* byte swap here to make translate_image faster */  
                         map[i] = translate_colour(colour);  
                 }  
   
                 return map;  
1314          }          }
1315  }  }
1316    
1317  void  void
1318  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1319  {  {
1320          if (owncolmap)          if (!owncolmap)
                 XFreeColormap(display, (Colormap)map);  
         else  
1321                  xfree(map);                  xfree(map);
1322            else
1323                    XFreeColormap(display, (Colormap) map);
1324  }  }
1325    
1326  void  void
1327  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1328  {  {
1329          if (owncolmap)          if (!owncolmap)
                 XSetWindowColormap(display, wnd, (Colormap)map);  
         else  
1330                  colmap = map;                  colmap = map;
1331            else
1332                    XSetWindowColormap(display, wnd, (Colormap) map);
1333  }  }
1334    
1335  void  void
# Line 879  ui_set_clip(int x, int y, int cx, int cy Line 1345  ui_set_clip(int x, int y, int cx, int cy
1345  }  }
1346    
1347  void  void
1348  ui_reset_clip()  ui_reset_clip(void)
1349  {  {
1350          XRectangle rect;          XRectangle rect;
1351    
# Line 891  ui_reset_clip() Line 1357  ui_reset_clip()
1357  }  }
1358    
1359  void  void
1360  ui_bell()  ui_bell(void)
1361  {  {
1362          XBell(display, 0);          XBell(display, 0);
1363  }  }
# Line 905  ui_destblt(uint8 opcode, Line 1371  ui_destblt(uint8 opcode,
1371          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1372  }  }
1373    
1374    static uint8 hatch_patterns[] = {
1375            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1376            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1377            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1378            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1379            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1380            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
1381    };
1382    
1383  void  void
1384  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1385            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1386            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1387  {  {
1388          Pixmap fill;          Pixmap fill;
1389            uint8 i, ipattern[8];
1390    
1391          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1392    
# Line 921  ui_patblt(uint8 opcode, Line 1397  ui_patblt(uint8 opcode,
1397                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1398                          break;                          break;
1399    
1400                    case 2: /* Hatch */
1401                            fill = (Pixmap) ui_create_glyph(8, 8, hatch_patterns + brush->pattern[0] * 8);
1402                            SET_FOREGROUND(bgcolour);
1403                            SET_BACKGROUND(fgcolour);
1404                            XSetFillStyle(display, gc, FillOpaqueStippled);
1405                            XSetStipple(display, gc, fill);
1406                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1407                            FILL_RECTANGLE(x, y, cx, cy);
1408                            XSetFillStyle(display, gc, FillSolid);
1409                            XSetTSOrigin(display, gc, 0, 0);
1410                            ui_destroy_glyph((HGLYPH) fill);
1411                            break;
1412    
1413                  case 3: /* Pattern */                  case 3: /* Pattern */
1414                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);                          for (i = 0; i != 8; i++)
1415                                    ipattern[7 - i] = brush->pattern[i];
1416                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1417    
1418                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
1419                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
# Line 933  ui_patblt(uint8 opcode, Line 1424  ui_patblt(uint8 opcode,
1424                          FILL_RECTANGLE(x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1425    
1426                          XSetFillStyle(display, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
1427                          ui_destroy_glyph((HGLYPH)fill);                          XSetTSOrigin(display, gc, 0, 0);
1428                            ui_destroy_glyph((HGLYPH) fill);
1429                          break;                          break;
1430    
1431                  default:                  default:
# Line 951  ui_screenblt(uint8 opcode, Line 1443  ui_screenblt(uint8 opcode,
1443          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1444          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1445          if (ownbackstore)          if (ownbackstore)
1446                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,                  XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1447          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1448  }  }
1449    
# Line 962  ui_memblt(uint8 opcode, Line 1453  ui_memblt(uint8 opcode,
1453            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1454  {  {
1455          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1456          XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1457          if (ownbackstore)          if (ownbackstore)
1458                  XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,                  XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
                           cx, cy, x, y);  
1459          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
1460  }  }
1461    
# Line 973  void Line 1463  void
1463  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1464            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1465            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1466            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1467  {  {
1468          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1469             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 982  ui_triblt(uint8 opcode, Line 1472  ui_triblt(uint8 opcode,
1472          {          {
1473                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1474                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1475                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1476                          break;                          break;
1477    
1478                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1479                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1480                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1481                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1482                          break;                          break;
1483    
1484                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
1485                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1486                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1487                          break;                          break;
1488    
1489                  default:                  default:
# Line 1009  ui_triblt(uint8 opcode, Line 1495  ui_triblt(uint8 opcode,
1495  void  void
1496  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1497          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1498          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1499  {  {
1500          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
1501          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
# Line 1028  ui_rect( Line 1514  ui_rect(
1514          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
1515  }  }
1516    
1517    /* warning, this function only draws on wnd or backstore, not both */
1518  void  void
1519  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1520                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1521                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1522                int fgcolour)                int bgcolour, int fgcolour)
1523  {  {
1524          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
1525          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
1526    
1527          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(display, gc,
1528                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1529          XSetStipple(display, gc, (Pixmap)glyph);          XSetStipple(display, gc, (Pixmap) glyph);
1530          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(display, gc, x, y);
1531    
1532          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1533    
1534          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(display, gc, FillSolid);
1535  }  }
# Line 1056  ui_draw_glyph(int mixmode, Line 1543  ui_draw_glyph(int mixmode,
1543        if ((xyoffset & 0x80))\        if ((xyoffset & 0x80))\
1544          {\          {\
1545            if (flags & TEXT2_VERTICAL) \            if (flags & TEXT2_VERTICAL) \
1546              y += ttext[++idx] | (ttext[++idx] << 8);\              y += ttext[idx+1] | (ttext[idx+2] << 8);\
1547            else\            else\
1548              x += ttext[++idx] | (ttext[++idx] << 8);\              x += ttext[idx+1] | (ttext[idx+2] << 8);\
1549              idx += 2;\
1550          }\          }\
1551        else\        else\
1552          {\          {\
# Line 1070  ui_draw_glyph(int mixmode, Line 1558  ui_draw_glyph(int mixmode,
1558      }\      }\
1559    if (glyph != NULL)\    if (glyph != NULL)\
1560      {\      {\
1561        ui_draw_glyph (mixmode, x + (short) glyph->offset,\        ui_draw_glyph (mixmode, x + glyph->offset,\
1562                       y + (short) glyph->baseline,\                       y + glyph->baseline,\
1563                       glyph->width, glyph->height,\                       glyph->width, glyph->height,\
1564                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\                       glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1565        if (flags & TEXT2_IMPLICIT_X)\        if (flags & TEXT2_IMPLICIT_X)\
# Line 1081  ui_draw_glyph(int mixmode, Line 1569  ui_draw_glyph(int mixmode,
1569    
1570  void  void
1571  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,
1572               int clipx, int clipy, int clipcx, int clipcy, int boxx,               int clipx, int clipy, int clipcx, int clipcy,
1573               int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1574               int fgcolour, uint8 * text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1575  {  {
1576          FONTGLYPH *glyph;          FONTGLYPH *glyph;
# Line 1093  ui_draw_text(uint8 font, uint8 flags, in Line 1581  ui_draw_text(uint8 font, uint8 flags, in
1581    
1582          if (boxcx > 1)          if (boxcx > 1)
1583          {          {
1584                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1585          }          }
1586          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1587          {          {
1588                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1589          }          }
1590    
1591          /* Paint text, character by character */          /* Paint text, character by character */
1592          for (i = 0; i < length;) {          for (i = 0; i < length;)
1593                  switch (text[i]) {          {
1594                  case 0xff:                  switch (text[i])
1595                          if (i + 2 < length)                  {
1596                                  cache_put_text(text[i + 1], text, text[i + 2]);                          case 0xff:
1597                          else {                                  if (i + 2 < length)
1598                                  error("this shouldn't be happening\n");                                          cache_put_text(text[i + 1], text, text[i + 2]);
1599                                    else
1600                                    {
1601                                            error("this shouldn't be happening\n");
1602                                            exit(1);
1603                                    }
1604                                    /* this will move pointer from start to first character after FF command */
1605                                    length -= i + 3;
1606                                    text = &(text[i + 3]);
1607                                    i = 0;
1608                                  break;                                  break;
                         }  
                         /* this will move pointer from start to first character after FF command */  
                         length -= i + 3;  
                         text = &(text[i + 3]);  
                         i = 0;  
                         break;  
1609    
1610                  case 0xfe:                          case 0xfe:
1611                          entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
1612                          if (entry != NULL) {                                  if (entry != NULL)
1613                                  if ((((uint8 *) (entry->data))[1] == 0)                                  {
1614                                      && (!(flags & TEXT2_IMPLICIT_X))) {                                          if ((((uint8 *) (entry->data))[1] ==
1615                                          if (flags & TEXT2_VERTICAL)                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
1616                                                  y += text[i + 2];                                          {
1617                                          else                                                  if (flags & TEXT2_VERTICAL)
1618                                                  x += text[i + 2];                                                          y += text[i + 2];
1619                                                    else
1620                                                            x += text[i + 2];
1621                                            }
1622                                            for (j = 0; j < entry->size; j++)
1623                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1624                                  }                                  }
1625                                  if (i + 2 < length)                                  if (i + 2 < length)
1626                                          i += 3;                                          i += 3;
1627                                  else                                  else
1628                                          i += 2;                                          i += 2;
1629                                  length -= i;                                  length -= i;
1630                                  /* this will move pointer from start to first character after FE command */                                  /* this will move pointer from start to first character after FE command */
1631                                  text = &(text[i]);                                  text = &(text[i]);
1632                                  i = 0;                                  i = 0;
1633                                  for (j = 0; j < entry->size; j++)                                  break;
                                         DO_GLYPH(((uint8 *) (entry->data)), j);  
                         }  
                         break;  
1634    
1635                  default:                          default:
1636                          DO_GLYPH(text, i);                                  DO_GLYPH(text, i);
1637                          i++;                                  i++;
1638                          break;                                  break;
1639                  }                  }
1640          }          }
1641            if (ownbackstore)
1642            {
1643                    if (boxcx > 1)
1644                            XCopyArea(display, backstore, wnd, gc, boxx,
1645                                      boxy, boxcx, boxcy, boxx, boxy);
1646                    else
1647                            XCopyArea(display, backstore, wnd, gc, clipx,
1648                                      clipy, clipcx, clipcy, clipx, clipy);
1649            }
1650  }  }
1651    
1652  void  void
# Line 1157  ui_desktop_save(uint32 offset, int x, in Line 1657  ui_desktop_save(uint32 offset, int x, in
1657    
1658          if (ownbackstore)          if (ownbackstore)
1659          {          {
1660                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
1661          }          }
1662          else          else
1663          {          {
1664                  pix = XCreatePixmap(display, wnd, cx, cy, depth);                  pix = XCreatePixmap(display, wnd, cx, cy, depth);
1665                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);                  XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1666                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,                  image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
                                   ZPixmap);  
1667                  XFreePixmap(display, pix);                  XFreePixmap(display, pix);
1668          }          }
1669    
1670          offset *= bpp/8;          offset *= bpp / 8;
1671          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
                           bpp/8, (uint8 *)image->data);  
1672    
1673          XDestroyImage(image);          XDestroyImage(image);
1674  }  }
# Line 1182  ui_desktop_restore(uint32 offset, int x, Line 1679  ui_desktop_restore(uint32 offset, int x,
1679          XImage *image;          XImage *image;
1680          uint8 *data;          uint8 *data;
1681    
1682          offset *= bpp/8;          offset *= bpp / 8;
1683          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, bpp / 8);
1684          if (data == NULL)          if (data == NULL)
1685                  return;                  return;
1686    
1687          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1688                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
                              cx * bpp/8);  
1689    
1690          if (ownbackstore)          if (ownbackstore)
1691          {          {

Legend:
Removed from v.53  
changed lines
  Added in v.373

  ViewVC Help
Powered by ViewVC 1.1.26