/[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 28 by matty, Wed Jun 20 13:54:48 2001 UTC revision 342 by astrand, Fri Mar 14 12:00:17 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-Windows     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2002
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Line 21  Line 21 
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23  #include <time.h>  #include <time.h>
24    #include <errno.h>
25  #include "rdesktop.h"  #include "rdesktop.h"
26    
27  extern int width;  extern int width;
28  extern int height;  extern int height;
29  extern BOOL motion;  extern BOOL sendmotion;
 extern BOOL grab_keyboard;  
30  extern BOOL fullscreen;  extern BOOL fullscreen;
31  extern int private_colormap;  extern BOOL grab_keyboard;
32    extern BOOL hide_decorations;
33  static int bpp;  extern char title[];
34  static int depth;  extern int server_bpp;
35  static Display *display;  extern int win_button_size;
36    BOOL enable_compose = False;
37    BOOL focused;
38    BOOL mouse_in_wnd;
39    
40    Display *display;
41    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 uint32 *colmap;  static int depth;
47    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 */
55    static BOOL host_be;
56    static BOOL xserver_be;
57    
58    /* software backing store */
59    static BOOL ownbackstore;
60    static Pixmap backstore;
61    
62    /* Moving in single app mode */
63    static BOOL moving_wnd;
64    static int move_x_offset = 0;
65    static int move_y_offset = 0;
66    
67    /* MWM decorations */
68    #define MWM_HINTS_DECORATIONS   (1L << 1)
69    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
70    typedef struct
71    {
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 Ctrans(col) ( private_colormap ? col : colmap[col])  #define FILL_RECTANGLE(x,y,cx,cy)\
89    { \
90            XFillRectangle(display, wnd, gc, x, y, cx, cy); \
91            if (ownbackstore) \
92                    XFillRectangle(display, backstore, gc, x, y, cx, cy); \
93    }
94    
95  #define L_ENDIAN  #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
96  int screen_msbfirst = 0;  { \
97            XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \
98    }
99    
100  static uint8 *translate(int width, int height, uint8 *data);  /* colour maps */
101    BOOL owncolmap = False;
102    static Colormap xcolmap;
103    static uint32 *colmap;
104    
105    #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));
107    #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
108    
109  static int rop2_map[] = {  static int rop2_map[] = {
110          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 64  static int rop2_map[] = { Line 125  static int rop2_map[] = {
125          GXset                   /* 1 */          GXset                   /* 1 */
126  };  };
127    
128    #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); }
130    
131    static void
132    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
283    translate8to8(uint8 * data, uint8 * out, uint8 * end)
284    {
285            while (out < end)
286                    *(out++) = (uint8) colmap[*(data++)];
287    }
288    
289  static void  static void
290  xwin_set_function(uint8 rop2)  translate8to16(uint8 * data, uint16 * out, uint16 * end)
291  {  {
292          static uint8 last_rop2 = ROP2_COPY;          while (out < end)
293                    *(out++) = (uint16) colmap[*(data++)];
294    }
295    
296          if (last_rop2 != rop2)  /* little endian - conversion happens when colourmap is built */
297    static void
298    translate8to24(uint8 * data, uint8 * out, uint8 * end)
299    {
300            uint32 value;
301    
302            while (out < end)
303          {          {
304                  XSetFunction(display, gc, rop2_map[rop2]);                  value = colmap[*(data++)];
305                  last_rop2 = rop2;                  *(out++) = value;
306                    *(out++) = value >> 8;
307                    *(out++) = value >> 16;
308          }          }
309  }  }
310    
311  static void  static void
312  xwin_grab_keyboard()  translate8to32(uint8 * data, uint32 * out, uint32 * end)
313    {
314            while (out < end)
315                    *(out++) = colmap[*(data++)];
316    }
317    
318    /* todo the remaining translate function might need some big endian check ?? */
319    
320    static void
321    translate15to16(uint16 * data, uint16 * out, uint16 * end)
322    {
323            while (out < end)
324                    *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
325    }
326    
327    static void
328    translate15to24(uint16 * data, uint8 * out, uint8 * end)
329  {  {
330          XGrabKeyboard(display, wnd, True, GrabModeAsync, GrabModeAsync,          uint32 value;
331                        CurrentTime);  
332            while (out < end)
333            {
334                    value = make_colour24(split_colour15(*(data++)));
335                    *(out++) = value;
336                    *(out++) = value >> 8;
337                    *(out++) = value >> 16;
338            }
339  }  }
340    
341  static void  static void
342  xwin_ungrab_keyboard()  translate15to32(uint16 * data, uint32 * out, uint32 * end)
343    {
344            while (out < end)
345                    *(out++) = make_colour32(split_colour15(*(data++)));
346    }
347    
348    static void
349    translate16to16(uint16 * data, uint16 * out, uint16 * end)
350    {
351            while (out < end)
352                    *(out++) = (uint16) (*(data++));
353    }
354    
355    
356    static void
357    translate16to24(uint16 * data, uint8 * out, uint8 * end)
358    {
359            uint32 value;
360    
361            while (out < end)
362            {
363                    value = make_colour24(split_colour16(*(data++)));
364                    *(out++) = value;
365                    *(out++) = value >> 8;
366                    *(out++) = value >> 16;
367            }
368    }
369    
370    static void
371    translate16to32(uint16 * data, uint32 * out, uint32 * end)
372    {
373            while (out < end)
374                    *(out++) = make_colour32(split_colour16(*(data++)));
375    }
376    
377    static void
378    translate24to16(uint8 * data, uint16 * out, uint16 * end)
379    {
380            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    static void
391    translate24to24(uint8 * data, uint8 * out, uint8 * end)
392    {
393            while (out < end)
394            {
395                    *(out++) = (*(data++));
396            }
397    }
398    
399    static void
400    translate24to32(uint8 * data, uint32 * out, uint32 * end)
401    {
402            uint32 pixel = 0;
403            while (out < end)
404            {
405                    memcpy(&pixel, data, 3);
406                    data += 3;
407                    *(out++) = pixel;
408            }
409    }
410    
411    static uint8 *
412    translate_image(int width, int height, uint8 * data)
413  {  {
414          XUngrabKeyboard(display, CurrentTime);          int size = width * height * bpp / 8;
415            uint8 *out = xmalloc(size);
416            uint8 *end = out + size;
417    
418            switch (server_bpp)
419            {
420                    case 24:
421                            switch (bpp)
422                            {
423                                    case 32:
424                                            translate24to32(data, (uint32 *) out, (uint32 *) end);
425                                            break;
426                                    case 24:
427                                            translate24to24(data, out, end);
428                                            break;
429                                    case 16:
430                                            translate24to16(data, (uint16 *) out, (uint16 *) end);
431                                            break;
432                            }
433                            break;
434                    case 16:
435                            switch (bpp)
436                            {
437                                    case 32:
438                                            translate16to32((uint16 *) data, (uint32 *) out,
439                                                            (uint32 *) end);
440                                            break;
441                                    case 24:
442                                            translate16to24((uint16 *) data, out, end);
443                                            break;
444                                    case 16:
445                                            translate16to16((uint16 *) data, (uint16 *) out,
446                                                            (uint16 *) end);
447                                            break;
448                            }
449                            break;
450                    case 15:
451                            switch (bpp)
452                            {
453                                    case 32:
454                                            translate15to32((uint16 *) data, (uint32 *) out,
455                                                            (uint32 *) end);
456                                            break;
457                                    case 24:
458                                            translate15to24((uint16 *) data, out, end);
459                                            break;
460                                    case 16:
461                                            translate15to16((uint16 *) data, (uint16 *) out,
462                                                            (uint16 *) end);
463                                            break;
464                            }
465                            break;
466                    case 8:
467                            switch (bpp)
468                            {
469                                    case 8:
470                                            translate8to8(data, out, end);
471                                            break;
472                                    case 16:
473                                            translate8to16(data, (uint16 *) out, (uint16 *) end);
474                                            break;
475                                    case 24:
476                                            translate8to24(data, out, end);
477                                            break;
478                                    case 32:
479                                            translate8to32(data, (uint32 *) out, (uint32 *) end);
480                                            break;
481                            }
482                            break;
483            }
484            return out;
485  }  }
486    
487  BOOL  BOOL
488  ui_create_window(char *title)  get_key_state(unsigned int state, uint32 keysym)
489    {
490            int modifierpos, key, keysymMask = 0;
491            int offset;
492    
493            KeyCode keycode = XKeysymToKeycode(display, keysym);
494    
495            if (keycode == NoSymbol)
496                    return False;
497    
498            for (modifierpos = 0; modifierpos < 8; modifierpos++)
499            {
500                    offset = mod_map->max_keypermod * modifierpos;
501    
502                    for (key = 0; key < mod_map->max_keypermod; key++)
503                    {
504                            if (mod_map->modifiermap[offset + key] == keycode)
505                                    keysymMask |= 1 << modifierpos;
506                    }
507            }
508    
509            return (state & keysymMask) ? True : False;
510    }
511    
512    BOOL
513    ui_init(void)
514  {  {
         XSetWindowAttributes attribs;  
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
515          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
516          int count;          uint16 test;
517            int i;
518    
519          display = XOpenDisplay(NULL);          display = XOpenDisplay(NULL);
520          if (display == NULL)          if (display == NULL)
521          {          {
522                  ERROR("Failed to open display\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
523                  return False;                  return False;
524          }          }
525    
526          visual = DefaultVisual(display, DefaultScreen(display));          x_socket = ConnectionNumber(display);
527          depth = DefaultDepth(display, DefaultScreen(display));          screen = DefaultScreenOfDisplay(display);
528          pfm = XListPixmapFormats(display, &count);          visual = DefaultVisualOfScreen(screen);
529            depth = DefaultDepthOfScreen(screen);
530    
531            pfm = XListPixmapFormats(display, &i);
532          if (pfm != NULL)          if (pfm != NULL)
533          {          {
534                  while (count--)                  /* Use maximum bpp for this depth - this is generally
535                       desirable, e.g. 24 bits->32 bits. */
536                    while (i--)
537                  {                  {
538                          if ((pfm + count)->depth == depth                          if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
                             && (pfm + count)->bits_per_pixel > bpp)  
539                          {                          {
540                                  bpp = (pfm + count)->bits_per_pixel;                                  bpp = pfm[i].bits_per_pixel;
541                          }                          }
542                  }                  }
543                  XFree(pfm);                  XFree(pfm);
# Line 124  ui_create_window(char *title) Line 545  ui_create_window(char *title)
545    
546          if (bpp < 8)          if (bpp < 8)
547          {          {
548                  ERROR("Less than 8 bpp not currently supported.\n");                  error("Less than 8 bpp not currently supported.\n");
549                  XCloseDisplay(display);                  XCloseDisplay(display);
550                  return False;                  return False;
551          }          }
552    
553          width &= ~3; /* make width nicely divisible */          if (owncolmap != True)
554            {
555                    xcolmap = DefaultColormapOfScreen(screen);
556                    if (depth <= 8)
557                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
558            }
559    
560            gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
561    
562          attribs.background_pixel = BlackPixel(display, DefaultScreen(display));          if (DoesBackingStore(screen) != Always)
563          attribs.backing_store = Always;                  ownbackstore = True;
564    
565            test = 1;
566            host_be = !(BOOL) (*(uint8 *) (&test));
567            xserver_be = (ImageByteOrder(display) == MSBFirst);
568    
569            if ((width == 0) || (height == 0))
570            {
571                    /* Fetch geometry from _NET_WORKAREA */
572                    uint32 x, y, cx, cy;
573    
574                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
575                    {
576                            width = cx;
577                            height = cy;
578                    }
579                    else
580                    {
581                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
582                            width = 800;
583                            height = 600;
584                    }
585            }
586    
587          if (fullscreen)          if (fullscreen)
588          {          {
589                  attribs.override_redirect = True;                  width = WidthOfScreen(screen);
590                  width = WidthOfScreen(DefaultScreenOfDisplay(display));                  height = HeightOfScreen(screen);
                 height = HeightOfScreen(DefaultScreenOfDisplay(display));  
                 XSetInputFocus(display, PointerRoot, RevertToPointerRoot,  
                                CurrentTime);  
591          }          }
592          else  
593            /* make sure width is a multiple of 4 */
594            width = (width + 3) & ~3;
595    
596            if (ownbackstore)
597          {          {
598                  attribs.override_redirect = False;                  backstore =
599                            XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
600    
601                    /* clear to prevent rubbish being exposed at startup */
602                    XSetForeground(display, gc, BlackPixelOfScreen(screen));
603                    XFillRectangle(display, backstore, gc, 0, 0, width, height);
604          }          }
605    
606          wnd = XCreateWindow(display, DefaultRootWindow(display),          mod_map = XGetModifierMapping(display);
607                              0, 0, width, height, 0, CopyFromParent,  
608                              InputOutput, CopyFromParent,          if (enable_compose)
609                              CWBackingStore | CWBackPixel | CWOverrideRedirect,                  IM = XOpenIM(display, NULL, NULL, NULL);
610                              &attribs);  
611            xkeymap_init();
612    
613            /* todo take this out when high colour is done */
614            printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth);
615    
616            return True;
617    }
618    
619    void
620    ui_deinit(void)
621    {
622            if (IM != NULL)
623                    XCloseIM(IM);
624    
625            XFreeModifiermap(mod_map);
626    
627            if (ownbackstore)
628                    XFreePixmap(display, backstore);
629    
630            XFreeGC(display, gc);
631            XCloseDisplay(display);
632            display = NULL;
633    }
634    
635    BOOL
636    ui_create_window(void)
637    {
638            XSetWindowAttributes attribs;
639            XClassHint *classhints;
640            XSizeHints *sizehints;
641            int wndwidth, wndheight;
642            long input_mask, ic_input_mask;
643            XEvent xevent;
644    
645            wndwidth = fullscreen ? WidthOfScreen(screen) : width;
646            wndheight = fullscreen ? HeightOfScreen(screen) : height;
647    
648            attribs.background_pixel = BlackPixelOfScreen(screen);
649            attribs.backing_store = ownbackstore ? NotUseful : Always;
650            attribs.override_redirect = fullscreen;
651    
652            wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
653                                0, CopyFromParent, InputOutput, CopyFromParent,
654                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
655    
656          XStoreName(display, wnd, title);          XStoreName(display, wnd, title);
657    
658            if (hide_decorations)
659                    mwm_hide_decorations();
660    
661          classhints = XAllocClassHint();          classhints = XAllocClassHint();
662          if (classhints != NULL)          if (classhints != NULL)
   
663          {          {
664                  classhints->res_name = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
                 classhints->res_class = "rdesktop";  
665                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(display, wnd, classhints);
666                  XFree(classhints);                  XFree(classhints);
667          }          }
# Line 168  ui_create_window(char *title) Line 669  ui_create_window(char *title)
669          sizehints = XAllocSizeHints();          sizehints = XAllocSizeHints();
670          if (sizehints)          if (sizehints)
671          {          {
672                  sizehints->flags =                  sizehints->flags = PMinSize | PMaxSize;
673                          PPosition | PSize | PMinSize | PMaxSize | PBaseSize;                  sizehints->min_width = sizehints->max_width = width;
674                  sizehints->min_width = width;                  sizehints->min_height = sizehints->max_height = height;
                 sizehints->max_width = width;  
                 sizehints->min_height = height;  
                 sizehints->max_height = height;  
                 sizehints->base_width = width;  
                 sizehints->base_height = height;  
675                  XSetWMNormalHints(display, wnd, sizehints);                  XSetWMNormalHints(display, wnd, sizehints);
676                  XFree(sizehints);                  XFree(sizehints);
677          }          }
678    
679          input_mask = KeyPressMask | KeyReleaseMask;          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
680          input_mask |= ButtonPressMask | ButtonReleaseMask;                  VisibilityChangeMask | FocusChangeMask;
681          if (motion)  
682            if (sendmotion)
683                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
684            if (ownbackstore)
685                    input_mask |= ExposureMask;
686            if (fullscreen || grab_keyboard)
687                    input_mask |= EnterWindowMask;
688          if (grab_keyboard)          if (grab_keyboard)
689                  input_mask |= EnterWindowMask | LeaveWindowMask;                  input_mask |= LeaveWindowMask;
690    
691          XSelectInput(display, wnd, input_mask);          if (IM != NULL)
692          gc = XCreateGC(display, wnd, 0, NULL);          {
693                    IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
694                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
695    
696                    if ((IC != NULL)
697                        && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
698                            input_mask |= ic_input_mask;
699            }
700    
701            XSelectInput(display, wnd, input_mask);
702          XMapWindow(display, wnd);          XMapWindow(display, wnd);
703    
704            /* wait for VisibilityNotify */
705            do
706            {
707                    XMaskEvent(display, VisibilityChangeMask, &xevent);
708            }
709            while (xevent.type != VisibilityNotify);
710    
711            focused = False;
712            mouse_in_wnd = False;
713    
714            /* handle the WM_DELETE_WINDOW protocol */
715            protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
716            kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
717            XSetWMProtocols(display, wnd, &kill_atom, 1);
718    
719          return True;          return True;
720  }  }
721    
722  void  void
723  ui_destroy_window()  ui_destroy_window(void)
724  {  {
725          XFreeGC(display, gc);          if (IC != NULL)
726                    XDestroyIC(IC);
727    
728          XDestroyWindow(display, wnd);          XDestroyWindow(display, wnd);
         XCloseDisplay(display);  
         display = NULL;  
729  }  }
730    
731  static uint8  void
732  xwin_translate_key(unsigned long key)  xwin_toggle_fullscreen(void)
733  {  {
734          DEBUG("KEY(code=0x%lx)\n", key);          Pixmap contents = 0;
735    
736          if ((key > 8) && (key <= 0x60))          if (!ownbackstore)
737                  return (key - 8);          {
738                    /* need to save contents of window */
739                    contents = XCreatePixmap(display, wnd, width, height, depth);
740                    XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
741            }
742    
743          switch (key)          ui_destroy_window();
744          {          fullscreen = !fullscreen;
745                  case 0x61:      /* home */          ui_create_window();
                         return 0x47 | 0x80;  
                 case 0x62:      /* up arrow */  
                         return 0x48 | 0x80;  
                 case 0x63:      /* page up */  
                         return 0x49 | 0x80;  
                 case 0x64:      /* left arrow */  
                         return 0x4b | 0x80;  
                 case 0x66:      /* right arrow */  
                         return 0x4d | 0x80;  
                 case 0x67:      /* end */  
                         return 0x4f | 0x80;  
                 case 0x68:      /* down arrow */  
                         return 0x50 | 0x80;  
                 case 0x69:      /* page down */  
                         return 0x51 | 0x80;  
                 case 0x6a:      /* insert */  
                         return 0x52 | 0x80;  
                 case 0x6b:      /* delete */  
                         return 0x53 | 0x80;  
                 case 0x6c:      /* keypad enter */  
                         return 0x1c | 0x80;  
                 case 0x6d:      /* right ctrl */  
                         return 0x1d | 0x80;  
                 case 0x6f:      /* ctrl - print screen */  
                         return 0x37 | 0x80;  
                 case 0x70:      /* keypad '/' */  
                         return 0x35 | 0x80;  
                 case 0x71:      /* right alt */  
                         return 0x38 | 0x80;  
                 case 0x72:      /* ctrl break */  
                         return 0x46 | 0x80;  
                 case 0x73:      /* left window key */  
                         return 0xff;    /* real scancode is 5b */  
                 case 0x74:      /* right window key */  
                         return 0xff;    /* real scancode is 5c */  
                 case 0x75:      /* menu key */  
                         return 0x5d | 0x80;  
         }  
   
         return 0;  
 }  
   
 static uint16  
 xwin_translate_mouse(unsigned long button)  
 {  
         switch (button)  
         {  
                 case Button1:   /* left */  
                         return MOUSE_FLAG_BUTTON1;  
                 case Button2:   /* middle */  
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3:   /* right */  
                         return MOUSE_FLAG_BUTTON2;  
         }  
   
         return 0;  
 }  
   
 void  
 ui_process_events()  
 {  
         XEvent event;  
         uint8 scancode;  
         uint16 button;  
         uint32 ev_time;  
746    
747          if (display == NULL)          XDefineCursor(display, wnd, current_cursor);
748                  return;  
749            if (!ownbackstore)
750            {
751                    XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
752                    XFreePixmap(display, contents);
753            }
754    }
755    
756    /* Process all events in Xlib queue
757       Returns 0 after user quit, 1 otherwise */
758    static int
759    xwin_process_events(void)
760    {
761            XEvent xevent;
762            KeySym keysym;
763            uint16 button, flags;
764            uint32 ev_time;
765            key_translation tr;
766            char str[256];
767            Status status;
768            unsigned int state;
769            Window wdummy;
770            int dummy;
771    
772          while (XCheckWindowEvent(display, wnd, ~0, &event))          while (XPending(display) > 0)
773          {          {
774                  ev_time = time(NULL);                  XNextEvent(display, &xevent);
775    
776                  switch (event.type)                  if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
777                  {                  {
778                            DEBUG_KBD(("Filtering event\n"));
779                            continue;
780                    }
781    
782                    flags = 0;
783    
784                    switch (xevent.type)
785                    {
786                            case ClientMessage:
787                                    /* the window manager told us to quit */
788                                    if ((xevent.xclient.message_type == protocol_atom)
789                                        && (xevent.xclient.data.l[0] == kill_atom))
790                                            /* Quit */
791                                            return 0;
792                                    break;
793    
794                          case KeyPress:                          case KeyPress:
795                                  scancode = xwin_translate_key(event.xkey.keycode);                                  if (IC != NULL)
796                                  if (scancode == 0)                                          /* Multi_key compatible version */
797                                    {
798                                            XmbLookupString(IC,
799                                                            (XKeyPressedEvent *) &
800                                                            xevent, str, sizeof(str), &keysym, &status);
801                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
802                                            {
803                                                    error("XmbLookupString failed with status 0x%x\n",
804                                                          status);
805                                                    break;
806                                            }
807                                    }
808                                    else
809                                    {
810                                            /* Plain old XLookupString */
811                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
812                                            XLookupString((XKeyEvent *) & xevent,
813                                                          str, sizeof(str), &keysym, NULL);
814                                    }
815    
816                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
817                                               get_ksname(keysym)));
818    
819                                    ev_time = time(NULL);
820                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
821                                          break;                                          break;
822    
823                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  tr = xkeymap_translate_key(keysym,
824                                                 scancode, 0);                                                             xevent.xkey.keycode, xevent.xkey.state);
825    
826                                    if (tr.scancode == 0)
827                                            break;
828    
829                                    ensure_remote_modifiers(ev_time, tr);
830    
831                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
832                                  break;                                  break;
833    
834                          case KeyRelease:                          case KeyRelease:
835                                  scancode = xwin_translate_key(event.xkey.keycode);                                  XLookupString((XKeyEvent *) & xevent, str,
836                                  if (scancode == 0)                                                sizeof(str), &keysym, NULL);
837    
838                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
839                                               get_ksname(keysym)));
840    
841                                    ev_time = time(NULL);
842                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
843                                          break;                                          break;
844    
845                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  tr = xkeymap_translate_key(keysym,
846                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                             xevent.xkey.keycode, xevent.xkey.state);
                                                scancode, 0);  
                                 break;  
847    
848                          case ButtonPress:                                  if (tr.scancode == 0)
                                 button = xwin_translate_mouse(event.xbutton.button);  
                                 if (button == 0)  
849                                          break;                                          break;
850    
851                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
                                                button | MOUSE_FLAG_DOWN,  
                                                event.xbutton.x,  
                                                event.xbutton.y);  
852                                  break;                                  break;
853    
854                            case ButtonPress:
855                                    flags = MOUSE_FLAG_DOWN;
856                                    /* fall through */
857    
858                          case ButtonRelease:                          case ButtonRelease:
859                                  button = xwin_translate_mouse(event.xbutton.button);                                  button = xkeymap_translate_button(xevent.xbutton.button);
860                                  if (button == 0)                                  if (button == 0)
861                                          break;                                          break;
862    
863                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
864                                                 button,                                  if (xevent.xbutton.y < win_button_size)
865                                                 event.xbutton.x,                                  {
866                                                 event.xbutton.y);                                          /* Stop moving window when button is released, regardless of cursor position */
867                                            if (moving_wnd && (xevent.type == ButtonRelease))
868                                                    moving_wnd = False;
869    
870                                            /*  Check from right to left: */
871    
872                                            if (xevent.xbutton.x >= width - win_button_size)
873                                            {
874                                                    /* The close button, continue */
875                                                    ;
876                                            }
877                                            else if (xevent.xbutton.x >= width - win_button_size * 2)
878                                            {
879                                                    /* The maximize/restore button. Do not send to
880                                                       server.  It might be a good idea to change the
881                                                       cursor or give some other visible indication
882                                                       that rdesktop inhibited this click */
883                                                    break;
884                                            }
885                                            else if (xevent.xbutton.x >= width - win_button_size * 3)
886                                            {
887                                                    /* The minimize button. Iconify window. */
888                                                    XIconifyWindow(display, wnd,
889                                                                   DefaultScreen(display));
890                                                    break;
891                                            }
892                                            else if (xevent.xbutton.x <= win_button_size)
893                                            {
894                                                    /* The system menu. Ignore. */
895                                                    break;
896                                            }
897                                            else
898                                            {
899                                                    /* The title bar. */
900                                                    if ((xevent.type == ButtonPress) && !fullscreen
901                                                        && hide_decorations)
902                                                    {
903                                                            moving_wnd = True;
904                                                            move_x_offset = xevent.xbutton.x;
905                                                            move_y_offset = xevent.xbutton.y;
906                                                    }
907                                                    break;
908    
909                                            }
910                                    }
911    
912                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
913                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
914                                  break;                                  break;
915    
916                          case MotionNotify:                          case MotionNotify:
917                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (moving_wnd)
918                                                 MOUSE_FLAG_MOVE,                                  {
919                                                 event.xmotion.x,                                          XMoveWindow(display, wnd,
920                                                 event.xmotion.y);                                                      xevent.xmotion.x_root - move_x_offset,
921                                                        xevent.xmotion.y_root - move_y_offset);
922                                            break;
923                                    }
924    
925                                    if (fullscreen && !focused)
926                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
927                                                           CurrentTime);
928                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
929                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
930                                    break;
931    
932                            case FocusIn:
933                                    if (xevent.xfocus.mode == NotifyGrab)
934                                            break;
935                                    focused = True;
936                                    XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
937                                                  &dummy, &dummy, &state);
938                                    reset_modifier_keys(state);
939                                    if (grab_keyboard && mouse_in_wnd)
940                                            XGrabKeyboard(display, wnd, True,
941                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
942                                    break;
943    
944                            case FocusOut:
945                                    if (xevent.xfocus.mode == NotifyUngrab)
946                                            break;
947                                    focused = False;
948                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
949                                            XUngrabKeyboard(display, CurrentTime);
950                                  break;                                  break;
951    
952                          case EnterNotify:                          case EnterNotify:
953                                  if (grab_keyboard)                                  /* we only register for this event when in fullscreen mode */
954                                          xwin_grab_keyboard();                                  /* or grab_keyboard */
955                                    mouse_in_wnd = True;
956                                    if (fullscreen)
957                                    {
958                                            XSetInputFocus(display, wnd, RevertToPointerRoot,
959                                                           CurrentTime);
960                                            break;
961                                    }
962                                    if (focused)
963                                            XGrabKeyboard(display, wnd, True,
964                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
965                                  break;                                  break;
966    
967                          case LeaveNotify:                          case LeaveNotify:
968                                  if (grab_keyboard)                                  /* we only register for this event when grab_keyboard */
969                                          xwin_ungrab_keyboard();                                  mouse_in_wnd = False;
970                                    XUngrabKeyboard(display, CurrentTime);
971                                    break;
972    
973                            case Expose:
974                                    XCopyArea(display, backstore, wnd, gc,
975                                              xevent.xexpose.x, xevent.xexpose.y,
976                                              xevent.xexpose.width,
977                                              xevent.xexpose.height,
978                                              xevent.xexpose.x, xevent.xexpose.y);
979                                    break;
980    
981                            case MappingNotify:
982                                    /* Refresh keyboard mapping if it has changed. This is important for
983                                       Xvnc, since it allocates keycodes dynamically */
984                                    if (xevent.xmapping.request == MappingKeyboard
985                                        || xevent.xmapping.request == MappingModifier)
986                                            XRefreshKeyboardMapping(&xevent.xmapping);
987    
988                                    if (xevent.xmapping.request == MappingModifier)
989                                    {
990                                            XFreeModifiermap(mod_map);
991                                            mod_map = XGetModifierMapping(display);
992                                    }
993                                  break;                                  break;
994    
995                  }                  }
996          }          }
997            /* Keep going */
998            return 1;
999    }
1000    
1001    /* Returns 0 after user quit, 1 otherwise */
1002    int
1003    ui_select(int rdp_socket)
1004    {
1005            int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
1006            fd_set rfds;
1007    
1008            FD_ZERO(&rfds);
1009    
1010            while (True)
1011            {
1012                    /* Process any events already waiting */
1013                    if (!xwin_process_events())
1014                            /* User quit */
1015                            return 0;
1016    
1017                    FD_ZERO(&rfds);
1018                    FD_SET(rdp_socket, &rfds);
1019                    FD_SET(x_socket, &rfds);
1020    
1021                    switch (select(n, &rfds, NULL, NULL, NULL))
1022                    {
1023                            case -1:
1024                                    error("select: %s\n", strerror(errno));
1025    
1026                            case 0:
1027                                    continue;
1028                    }
1029    
1030                    if (FD_ISSET(rdp_socket, &rfds))
1031                            return 1;
1032            }
1033  }  }
1034    
1035  void  void
# Line 357  ui_move_pointer(int x, int y) Line 1039  ui_move_pointer(int x, int y)
1039  }  }
1040    
1041  HBITMAP  HBITMAP
1042  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1043  {  {
1044          XImage *image;          XImage *image;
1045          Pixmap bitmap;          Pixmap bitmap;
1046          uint8 *tdata;          uint8 *tdata;
1047          tdata = (private_colormap ? data : translate(width, height, data));  
1048            tdata = (owncolmap ? data : translate_image(width, height, data));
1049          bitmap = XCreatePixmap(display, wnd, width, height, depth);          bitmap = XCreatePixmap(display, wnd, width, height, depth);
1050          image =          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1051                  XCreateImage(display, visual,                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
                              depth, ZPixmap,  
                              0, tdata, width, height, BitmapPad(display), 0);  
1052    
         xwin_set_function(ROP2_COPY);  
1053          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1054    
1055          XFree(image);          XFree(image);
1056          if (!private_colormap)          if (!owncolmap)
1057                  xfree(tdata);                  xfree(tdata);
1058          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1059  }  }
1060    
1061  void  void
1062  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)  
1063  {  {
1064          XImage *image;          XImage *image;
1065          uint8 *tdata =          uint8 *tdata;
1066                  (private_colormap ? data : translate(width, height, data));          tdata = (owncolmap ? data : translate_image(width, height, data));
1067          image =          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1068                  XCreateImage(display, visual, depth, ZPixmap, 0, tdata, width,                               (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
                              height, BitmapPad(display), 0);  
   
         xwin_set_function(ROP2_COPY);  
   
         /* Window */  
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
         XFree(image);  
         if (!private_colormap)  
                 xfree(tdata);  
 }  
   
 void  
 ui_destroy_bitmap(HBITMAP bmp)  
 {  
         XFreePixmap(display, (Pixmap) bmp);  
 }  
1069    
1070  HCURSOR          if (ownbackstore)
 ui_create_cursor(unsigned int x, unsigned int y, int width,  
                  int height, uint8 *mask, uint8 *data)  
 {  
         XImage *imagecursor;  
         XImage *imagemask;  
         Pixmap maskbitmap, cursorbitmap;  
         Cursor cursor;  
         XColor bg, fg;  
         GC lgc;  
         int i, x1, y1, scanlinelen;  
         uint8 *cdata, *cmask;  
         uint8 c;  
         cdata = (uint8 *) malloc(sizeof(uint8) * width * height);  
         if (!cdata)  
                 return NULL;  
         scanlinelen = (width + 7) >> 3;  
         cmask = (uint8 *) malloc(sizeof(uint8) * scanlinelen * height);  
         if (!cmask)  
1071          {          {
1072                  free(cdata);                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1073                  return NULL;                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
         }  
         i = (height - 1) * scanlinelen;  
   
         if (!screen_msbfirst)  
         {  
                 while (i >= 0)  
                 {  
                         for (x1 = 0; x1 < scanlinelen; x1++)  
                         {  
                                 c = *(mask++);  
                                 cmask[i + x1] =  
                                         ((c & 0x1) << 7) | ((c & 0x2) << 5) |  
                                         ((c & 0x4) << 3) | ((c & 0x8) << 1) |  
                                         ((c & 0x10) >> 1) | ((c & 0x20) >> 3)  
                                         | ((c & 0x40) >> 5) | ((c & 0x80) >>  
                                                                7);  
                         }  
                         i -= scanlinelen;  
                 }  
1074          }          }
1075          else          else
1076          {          {
1077                  while (i >= 0)                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
                 {  
                         for (x1 = 0; x1 < scanlinelen; x1++)  
                         {  
                                 cmask[i + x1] = *(mask++);  
                         }  
                         i -= scanlinelen;  
                 }  
1078          }          }
1079    
1080            XFree(image);
1081          fg.red = 0;          if (!owncolmap)
1082          fg.blue = 0;                  xfree(tdata);
         fg.green = 0;  
         fg.flags = DoRed | DoBlue | DoGreen;  
         bg.red = 65535;  
         bg.blue = 65535;  
         bg.green = 65535;  
         bg.flags = DoRed | DoBlue | DoGreen;  
         maskbitmap = XCreatePixmap(display, wnd, width, height, 1);  
         cursorbitmap = XCreatePixmap(display, wnd, width, height, 1);  
         lgc = XCreateGC(display, maskbitmap, 0, NULL);  
         XSetFunction(display, lgc, GXcopy);  
         imagemask =  
                 XCreateImage(display, visual, 1, XYBitmap, 0, cmask, width,  
                              height, 8, 0);  
         imagecursor =  
                 XCreateImage(display, visual, 1, XYBitmap, 0, cdata, width,  
                              height, 8, 0);  
         for (y1 = height - 1; y1 >= 0; y1--)  
                 for (x1 = 0; x1 < width; x1++)  
                 {  
                         if (data[0] >= 0x80 || data[1] >= 0x80  
                             || data[2] >= 0x80)  
                                 if (XGetPixel(imagemask, x1, y1))  
   
                                 {  
                                         XPutPixel(imagecursor, x1, y1, 0);  
                                         XPutPixel(imagemask, x1, y1, 0);        /* mask is blank for text cursor! */  
                                 }  
   
                                 else  
                                         XPutPixel(imagecursor, x1, y1, 1);  
   
                         else  
                                 XPutPixel(imagecursor, x1, y1,  
                                           XGetPixel(imagemask, x1, y1));  
                         data += 3;  
                 }  
         XPutImage(display, maskbitmap, lgc, imagemask, 0, 0, 0, 0, width,  
                   height);  
         XPutImage(display, cursorbitmap, lgc, imagecursor, 0, 0, 0, 0, width,  
                   height); XFree(imagemask);  
         XFree(imagecursor);  
         free(cmask);  
         free(cdata);  
         XFreeGC(display, lgc);  
         cursor =  
                 XCreatePixmapCursor(display, cursorbitmap, maskbitmap, &fg,  
                                     &bg, x, y);  
         XFreePixmap(display, maskbitmap);  
         XFreePixmap(display, cursorbitmap);  
         return (HCURSOR) cursor;  
 }  
   
 void  
 ui_set_cursor(HCURSOR cursor)  
 {  
         XDefineCursor(display, wnd, (Cursor) cursor);  
1083  }  }
1084    
1085  void  void
1086  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_bitmap(HBITMAP bmp)
1087  {  {
1088          XFreeCursor(display, (Cursor) cursor);          XFreePixmap(display, (Pixmap) bmp);
1089  }  }
1090    
1091  HGLYPH  HGLYPH
1092  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1093  {  {
1094          XImage *image;          XImage *image;
1095          Pixmap bitmap;          Pixmap bitmap;
# Line 538  ui_create_glyph(int width, int height, u Line 1101  ui_create_glyph(int width, int height, u
1101          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
1102          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
1103    
1104          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1105                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1106          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1107          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1108          XInitImage(image);          XInitImage(image);
1109    
         XSetFunction(display, gc, GXcopy);  
1110          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1111    
1112          XFree(image);          XFree(image);
1113          XFreeGC(display, gc);          XFreeGC(display, gc);
   
1114          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1115  }  }
1116    
# Line 558  ui_destroy_glyph(HGLYPH glyph) Line 1120  ui_destroy_glyph(HGLYPH glyph)
1120          XFreePixmap(display, (Pixmap) glyph);          XFreePixmap(display, (Pixmap) glyph);
1121  }  }
1122    
1123  HCOLOURMAP  HCURSOR
1124  ui_create_colourmap(COLOURMAP *colours)  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1125                     uint8 * andmask, uint8 * xormask)
1126  {  {
1127          if (!private_colormap)          HGLYPH maskglyph, cursorglyph;
1128            XColor bg, fg;
1129            Cursor xcursor;
1130            uint8 *cursor, *pcursor;
1131            uint8 *mask, *pmask;
1132            uint8 nextbit;
1133            int scanline, offset;
1134            int i, j;
1135    
1136            scanline = (width + 7) / 8;
1137            offset = scanline * height;
1138    
1139            cursor = xmalloc(offset);
1140            memset(cursor, 0, offset);
1141    
1142            mask = xmalloc(offset);
1143            memset(mask, 0, offset);
1144    
1145            /* approximate AND and XOR masks with a monochrome X pointer */
1146            for (i = 0; i < height; i++)
1147          {          {
1148                  COLOURENTRY *entry;                  offset -= scanline;
1149                  int i, ncolours = colours->ncolours;                  pcursor = &cursor[offset];
1150                  uint32 *nc = xmalloc(sizeof(*colmap) * ncolours);                  pmask = &mask[offset];
1151    
1152                    for (j = 0; j < scanline; j++)
1153                    {
1154                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1155                            {
1156                                    if (xormask[0] || xormask[1] || xormask[2])
1157                                    {
1158                                            *pcursor |= (~(*andmask) & nextbit);
1159                                            *pmask |= nextbit;
1160                                    }
1161                                    else
1162                                    {
1163                                            *pcursor |= ((*andmask) & nextbit);
1164                                            *pmask |= (~(*andmask) & nextbit);
1165                                    }
1166    
1167                                    xormask += 3;
1168                            }
1169    
1170                            andmask++;
1171                            pcursor++;
1172                            pmask++;
1173                    }
1174            }
1175    
1176            fg.red = fg.blue = fg.green = 0xffff;
1177            bg.red = bg.blue = bg.green = 0x0000;
1178            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1179    
1180            cursorglyph = ui_create_glyph(width, height, cursor);
1181            maskglyph = ui_create_glyph(width, height, mask);
1182    
1183            xcursor =
1184                    XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1185                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1186    
1187            ui_destroy_glyph(maskglyph);
1188            ui_destroy_glyph(cursorglyph);
1189            xfree(mask);
1190            xfree(cursor);
1191            return (HCURSOR) xcursor;
1192    }
1193    
1194    void
1195    ui_set_cursor(HCURSOR cursor)
1196    {
1197            current_cursor = (Cursor) cursor;
1198            XDefineCursor(display, wnd, current_cursor);
1199    }
1200    
1201    void
1202    ui_destroy_cursor(HCURSOR cursor)
1203    {
1204            XFreeCursor(display, (Cursor) cursor);
1205    }
1206    
1207    #define MAKE_XCOLOR(xc,c) \
1208                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
1209                    (xc)->green = ((c)->green << 8) | (c)->green; \
1210                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1211                    (xc)->flags = DoRed | DoGreen | DoBlue;
1212    
1213    
1214    HCOLOURMAP
1215    ui_create_colourmap(COLOURMAP * colours)
1216    {
1217            COLOURENTRY *entry;
1218            int i, ncolours = colours->ncolours;
1219            if (!owncolmap)
1220            {
1221                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
1222                    XColor xentry;
1223                    XColor xc_cache[256];
1224                    uint32 colour;
1225                    int colLookup = 256;
1226                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1227                  {                  {
                         XColor xc;  
1228                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1229                          xc.red = entry->red << 8;                          MAKE_XCOLOR(&xentry, entry);
1230                          xc.green = entry->green << 8;  
1231                          xc.blue = entry->blue << 8;                          if (XAllocColor(display, xcolmap, &xentry) == 0)
1232                          XAllocColor(display,                          {
1233                                      DefaultColormap(display,                                  /* Allocation failed, find closest match. */
1234                                                      DefaultScreen(display)),                                  int j = 256;
1235                                      &xc);                                  int nMinDist = 3 * 256 * 256;
1236                          /* XXX Check return value */                                  long nDist = nMinDist;
1237                          nc[i] = xc.pixel;  
1238                                    /* only get the colors once */
1239                                    while (colLookup--)
1240                                    {
1241                                            xc_cache[colLookup].pixel = colLookup;
1242                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1243                                                    xc_cache[colLookup].blue = 0;
1244                                            xc_cache[colLookup].flags = 0;
1245                                            XQueryColor(display,
1246                                                        DefaultColormap(display,
1247                                                                        DefaultScreen(display)),
1248                                                        &xc_cache[colLookup]);
1249                                    }
1250                                    colLookup = 0;
1251    
1252                                    /* approximate the pixel */
1253                                    while (j--)
1254                                    {
1255                                            if (xc_cache[j].flags)
1256                                            {
1257                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1258                                                             (long) (xentry.red >> 8)) *
1259                                                            ((long) (xc_cache[j].red >> 8) -
1260                                                             (long) (xentry.red >> 8)) +
1261                                                            ((long) (xc_cache[j].green >> 8) -
1262                                                             (long) (xentry.green >> 8)) *
1263                                                            ((long) (xc_cache[j].green >> 8) -
1264                                                             (long) (xentry.green >> 8)) +
1265                                                            ((long) (xc_cache[j].blue >> 8) -
1266                                                             (long) (xentry.blue >> 8)) *
1267                                                            ((long) (xc_cache[j].blue >> 8) -
1268                                                             (long) (xentry.blue >> 8));
1269                                            }
1270                                            if (nDist < nMinDist)
1271                                            {
1272                                                    nMinDist = nDist;
1273                                                    xentry.pixel = j;
1274                                            }
1275                                    }
1276                            }
1277                            colour = xentry.pixel;
1278    
1279                            /* update our cache */
1280                            if (xentry.pixel < 256)
1281                            {
1282                                    xc_cache[xentry.pixel].red = xentry.red;
1283                                    xc_cache[xentry.pixel].green = xentry.green;
1284                                    xc_cache[xentry.pixel].blue = xentry.blue;
1285    
1286                            }
1287    
1288    
1289                            /* byte swap here to make translate_image faster */
1290                            map[i] = translate_colour(colour);
1291                  }                  }
1292                  return nc;                  return map;
1293          }          }
1294          else          else
1295          {          {
                 COLOURENTRY *entry;  
1296                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
1297                  Colormap map;                  Colormap map;
1298                  int i, ncolours = colours->ncolours;  
1299                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = xmalloc(sizeof(XColor) * ncolours);
1300                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1301                  {                  {
1302                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1303                          xentry = &xcolours[i];                          xentry = &xcolours[i];
   
1304                          xentry->pixel = i;                          xentry->pixel = i;
1305                          xentry->red = entry->red << 8;                          MAKE_XCOLOR(xentry, entry);
                         xentry->blue = entry->blue << 8;  
                         xentry->green = entry->green << 8;  
                         xentry->flags = DoRed | DoBlue | DoGreen;  
1306                  }                  }
1307    
1308                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(display, wnd, visual, AllocAll);
# Line 612  ui_create_colourmap(COLOURMAP *colours) Line 1316  ui_create_colourmap(COLOURMAP *colours)
1316  void  void
1317  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1318  {  {
1319          XFreeColormap(display, (Colormap) map);          if (!owncolmap)
1320                    xfree(map);
1321            else
1322                    XFreeColormap(display, (Colormap) map);
1323  }  }
1324    
1325  void  void
1326  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1327  {  {
1328            if (!owncolmap)
         /* XXX, change values of all pixels on the screen if the new colmap  
          * doesn't have the same values as the old one? */  
         if (!private_colormap)  
1329                  colmap = map;                  colmap = map;
1330          else          else
         {  
1331                  XSetWindowColormap(display, wnd, (Colormap) map);                  XSetWindowColormap(display, wnd, (Colormap) map);
                 if (fullscreen)  
                         XInstallColormap(display, (Colormap) map);  
         }  
1332  }  }
1333    
1334  void  void
# Line 644  ui_set_clip(int x, int y, int cx, int cy Line 1344  ui_set_clip(int x, int y, int cx, int cy
1344  }  }
1345    
1346  void  void
1347  ui_reset_clip()  ui_reset_clip(void)
1348  {  {
1349          XRectangle rect;          XRectangle rect;
1350    
# Line 656  ui_reset_clip() Line 1356  ui_reset_clip()
1356  }  }
1357    
1358  void  void
1359  ui_bell()  ui_bell(void)
1360  {  {
1361          XBell(display, 0);          XBell(display, 0);
1362  }  }
# Line 665  void Line 1365  void
1365  ui_destblt(uint8 opcode,  ui_destblt(uint8 opcode,
1366             /* dest */ int x, int y, int cx, int cy)             /* dest */ int x, int y, int cx, int cy)
1367  {  {
1368          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1369            FILL_RECTANGLE(x, y, cx, cy);
1370          XFillRectangle(display, wnd, gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
1371  }  }
1372    
1373  void  void
1374  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1375            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1376            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1377  {  {
         Display *dpy = display;  
1378          Pixmap fill;          Pixmap fill;
1379          uint8 i, ipattern[8];          uint8 i, ipattern[8];
1380    
1381          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1382    
1383          switch (brush->style)          switch (brush->style)
1384          {          {
1385                  case 0: /* Solid */                  case 0: /* Solid */
1386                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_FOREGROUND(fgcolour);
1387                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1388                          break;                          break;
1389    
1390                  case 3: /* Pattern */                  case 3: /* Pattern */
1391                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
1392                                  ipattern[i] = ~brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
1393                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1394    
1395                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_FOREGROUND(bgcolour);
1396                          XSetBackground(dpy, gc, Ctrans(bgcolour));                          SET_BACKGROUND(fgcolour);
1397                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                          XSetFillStyle(display, gc, FillOpaqueStippled);
1398                          XSetStipple(dpy, gc, fill);                          XSetStipple(display, gc, fill);
1399                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1400    
1401                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1402    
1403                          XSetFillStyle(dpy, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
1404                            XSetTSOrigin(display, gc, 0, 0);
1405                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
1406                          break;                          break;
1407    
1408                  default:                  default:
1409                          NOTIMP("brush %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
1410          }          }
1411    
1412            RESET_FUNCTION(opcode);
1413  }  }
1414    
1415  void  void
# Line 714  ui_screenblt(uint8 opcode, Line 1417  ui_screenblt(uint8 opcode,
1417               /* dest */ int x, int y, int cx, int cy,               /* dest */ int x, int y, int cx, int cy,
1418               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
1419  {  {
1420          xwin_set_function(opcode);          SET_FUNCTION(opcode);
   
1421          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1422            if (ownbackstore)
1423                    XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1424            RESET_FUNCTION(opcode);
1425  }  }
1426    
1427  void  void
# Line 724  ui_memblt(uint8 opcode, Line 1429  ui_memblt(uint8 opcode,
1429            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1430            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1431  {  {
1432          xwin_set_function(opcode);          SET_FUNCTION(opcode);
   
1433          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1434            if (ownbackstore)
1435                    XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1436            RESET_FUNCTION(opcode);
1437  }  }
1438    
1439  void  void
1440  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1441            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1442            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1443            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1444  {  {
1445          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1446             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 742  ui_triblt(uint8 opcode, Line 1449  ui_triblt(uint8 opcode,
1449          {          {
1450                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1451                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1452                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1453                          break;                          break;
1454    
1455                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1456                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1457                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1458                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1459                          break;                          break;
1460    
1461                  case 0xc0:                  case 0xc0:      /* PSa */
1462                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1463                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1464                          break;                          break;
1465    
1466                  default:                  default:
1467                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
1468                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1469          }          }
1470  }  }
# Line 769  ui_triblt(uint8 opcode, Line 1472  ui_triblt(uint8 opcode,
1472  void  void
1473  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1474          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1475          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1476  {  {
1477          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1478            SET_FOREGROUND(pen->colour);
         XSetForeground(display, gc, Ctrans(pen->colour));  
1479          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1480            if (ownbackstore)
1481                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1482            RESET_FUNCTION(opcode);
1483  }  }
1484    
1485  void  void
# Line 782  ui_rect( Line 1487  ui_rect(
1487                 /* dest */ int x, int y, int cx, int cy,                 /* dest */ int x, int y, int cx, int cy,
1488                 /* brush */ int colour)                 /* brush */ int colour)
1489  {  {
1490          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(colour);
1491            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(display, gc, Ctrans(colour));  
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1492  }  }
1493    
1494    /* warning, this function only draws on wnd or backstore, not both */
1495  void  void
1496  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1497                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1498                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1499                int fgcolour)                int bgcolour, int fgcolour)
1500  {  {
1501          Pixmap pixmap = (Pixmap) glyph;          SET_FOREGROUND(fgcolour);
1502            SET_BACKGROUND(bgcolour);
         xwin_set_function(ROP2_COPY);  
   
   
         XSetForeground(display, gc, Ctrans(fgcolour));  
         switch (mixmode)  
         {  
                 case MIX_TRANSPARENT:  
                         XSetStipple(display, gc, pixmap);  
                         XSetFillStyle(display, gc, FillStippled);  
                         XSetTSOrigin(display, gc, x, y);  
                         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
                         XSetFillStyle(display, gc, FillSolid);  
                         break;  
1503    
1504                  case MIX_OPAQUE:          XSetFillStyle(display, gc,
1505                          XSetBackground(display, gc, Ctrans(bgcolour));                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1506  /*      XCopyPlane (display, pixmap, back_pixmap, back_gc, srcx, srcy, cx, cy, x, y, 1); */          XSetStipple(display, gc, (Pixmap) glyph);
1507                          XSetStipple(display, gc, pixmap);          XSetTSOrigin(display, gc, x, y);
1508                          XSetFillStyle(display, gc, FillOpaqueStippled);  
1509                          XSetTSOrigin(display, gc, x, y);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1510                          XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1511                          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(display, gc, FillSolid);
1512                          break;  }
1513    
1514                  default:  #define DO_GLYPH(ttext,idx) \
1515                          NOTIMP("mix %d\n", mixmode);  {\
1516          }    glyph = cache_get_font (font, ttext[idx]);\
1517      if (!(flags & TEXT2_IMPLICIT_X))\
1518        {\
1519          xyoffset = ttext[++idx];\
1520          if ((xyoffset & 0x80))\
1521            {\
1522              if (flags & TEXT2_VERTICAL) \
1523                y += ttext[idx+1] | (ttext[idx+2] << 8);\
1524              else\
1525                x += ttext[idx+1] | (ttext[idx+2] << 8);\
1526              idx += 2;\
1527            }\
1528          else\
1529            {\
1530              if (flags & TEXT2_VERTICAL) \
1531                y += xyoffset;\
1532              else\
1533                x += xyoffset;\
1534            }\
1535        }\
1536      if (glyph != NULL)\
1537        {\
1538          ui_draw_glyph (mixmode, x + glyph->offset,\
1539                         y + glyph->baseline,\
1540                         glyph->width, glyph->height,\
1541                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1542          if (flags & TEXT2_IMPLICIT_X)\
1543            x += glyph->width;\
1544        }\
1545  }  }
1546    
1547  void  void
1548  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,
1549               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
1550               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1551               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1552  {  {
1553          FONTGLYPH *glyph;          FONTGLYPH *glyph;
1554          int i, xyoffset;          int i, j, xyoffset;
1555            DATABLOB *entry;
1556    
1557          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(bgcolour);
         XSetForeground(display, gc, Ctrans(bgcolour));  
1558    
1559          if (boxcx > 1)          if (boxcx > 1)
1560                  XFillRectangle(display, wnd, gc, boxx, boxy, boxcx, boxcy);          {
1561                    FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1562            }
1563          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1564                  XFillRectangle(display, wnd, gc, clipx, clipy, clipcx, clipcy);          {
1565                    FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1566            }
1567    
1568          /* Paint text, character by character */          /* Paint text, character by character */
1569          for (i = 0; i < length; i++)          for (i = 0; i < length;)
1570          {          {
1571                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
   
1572                  {                  {
1573                          xyoffset = text[++i];                          case 0xff:
1574                          if ((xyoffset & 0x80))                                  if (i + 2 < length)
1575                          {                                          cache_put_text(text[i + 1], text, text[i + 2]);
                                 if (flags & 0x04)       /* vertical text */  
                                         y += text[++i] | (text[++i] << 8);  
1576                                  else                                  else
1577                                          x += text[++i] | (text[++i] << 8);                                  {
1578                          }                                          error("this shouldn't be happening\n");
1579                          else                                          exit(1);
1580                          {                                  }
1581                                  if (flags & 0x04)       /* vertical text */                                  /* this will move pointer from start to first character after FF command */
1582                                          y += xyoffset;                                  length -= i + 3;
1583                                  else                                  text = &(text[i + 3]);
1584                                          x += xyoffset;                                  i = 0;
1585                          }                                  break;
1586    
1587                  }                          case 0xfe:
1588                  if (glyph != NULL)                                  entry = cache_get_text(text[i + 1]);
1589                  {                                  if (entry != NULL)
1590                          ui_draw_glyph(mixmode, x + (short) glyph->offset,                                  {
1591                                        y + (short) glyph->baseline,                                          if ((((uint8 *) (entry->data))[1] ==
1592                                        glyph->width, glyph->height,                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
1593                                        glyph->pixmap, 0, 0,                                          {
1594                                        bgcolour, fgcolour);                                                  if (flags & TEXT2_VERTICAL)
1595                                                            y += text[i + 2];
1596                                                    else
1597                                                            x += text[i + 2];
1598                                            }
1599                                            for (j = 0; j < entry->size; j++)
1600                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1601                                    }
1602                                    if (i + 2 < length)
1603                                            i += 3;
1604                                    else
1605                                            i += 2;
1606                                    length -= i;
1607                                    /* this will move pointer from start to first character after FE command */
1608                                    text = &(text[i]);
1609                                    i = 0;
1610                                    break;
1611    
1612                          if (flags & TEXT2_IMPLICIT_X)                          default:
1613                                  x += glyph->width;                                  DO_GLYPH(text, i);
1614                                    i++;
1615                                    break;
1616                  }                  }
1617          }          }
1618            if (ownbackstore)
1619            {
1620                    if (boxcx > 1)
1621                            XCopyArea(display, backstore, wnd, gc, boxx,
1622                                      boxy, boxcx, boxcy, boxx, boxy);
1623                    else
1624                            XCopyArea(display, backstore, wnd, gc, clipx,
1625                                      clipy, clipcx, clipcy, clipx, clipy);
1626            }
1627  }  }
1628    
1629  void  void
# Line 887  ui_desktop_save(uint32 offset, int x, in Line 1632  ui_desktop_save(uint32 offset, int x, in
1632          Pixmap pix;          Pixmap pix;
1633          XImage *image;          XImage *image;
1634    
1635          pix = XCreatePixmap(display, wnd, cx, cy, depth);          if (ownbackstore)
1636          xwin_set_function(ROP2_COPY);          {
1637                    image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1638          XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);          }
1639          image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);          else
1640            {
1641                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
1642                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1643                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1644                    XFreePixmap(display, pix);
1645            }
1646    
1647          offset *= bpp/8;          offset *= bpp / 8;
1648          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, image->data);  
1649    
1650          XDestroyImage(image);          XDestroyImage(image);
         XFreePixmap(display, pix);  
1651  }  }
1652    
1653  void  void
# Line 907  ui_desktop_restore(uint32 offset, int x, Line 1656  ui_desktop_restore(uint32 offset, int x,
1656          XImage *image;          XImage *image;
1657          uint8 *data;          uint8 *data;
1658    
1659          offset *= bpp/8;          offset *= bpp / 8;
1660          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, bpp / 8);
1661          if (data == NULL)          if (data == NULL)
1662                  return;                  return;
         image =  
                 XCreateImage(display, visual,  
                              depth, ZPixmap,  
                              0, data, cx, cy, BitmapPad(display),  
                              cx * bpp/8);  
         xwin_set_function(ROP2_COPY);  
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
         XFree(image);  
 }  
1663    
1664  /* unroll defines, used to make the loops a bit more readable... */          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1665  #define unroll8Expr(uexp) uexp uexp uexp uexp uexp uexp uexp uexp                               (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
 #define unroll8Lefts(uexp) case 7: uexp \  
         case 6: uexp \  
         case 5: uexp \  
         case 4: uexp \  
         case 3: uexp \  
         case 2: uexp \  
         case 1: uexp  
   
 static uint8 *  
 translate(int width, int height, uint8 *data)  
 {  
         uint32 i;  
         uint32 size = width * height;  
         uint8 *d2 = xmalloc(size * bpp/8);  
         uint8 *d3 = d2;  
         uint32 pix;  
         i = (size & ~0x7);  
   
         /* XXX: where are the bits swapped??? */  
 #ifdef L_ENDIAN                 /* little-endian */  
         /* big-endian screen */  
         if (screen_msbfirst)  
         {  
                 switch (bpp)  
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix >> 24;  
                                                     *d3++ = pix >> 16;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix;) i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      24;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix >> 16;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix;) i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix;) i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                                 break;  
                 }  
         }  
         else  
         {                       /* little-endian screen */  
                 switch (bpp)  
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(*((uint32 *) d3) =  
                                                     colmap[*data++];  
                                                     d3 += sizeof(uint32);  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(*  
                                                                      ((uint32  
                                                                        *) d3)  
 = colmap[*data++];  
 d3 += sizeof(uint32);  
                                         )}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                         )}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                 }  
         }  
1666    
1667  #else /* bigendian-compiled */          if (ownbackstore)
         if (screen_msbfirst)  
1668          {          {
1669                  /* big-endian screen */                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1670                  switch (bpp)                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(*((uint32 *) d3) =  
                                                     colmap[*data++];  
                                                     d3 += sizeof(uint32);  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(*  
                                                                      ((uint32  
                                                                        *) d3)  
 = colmap[*data++];  
 d3 += sizeof(uint32);  
                                         )}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                         )}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                 }  
1671          }          }
1672          else          else
1673          {          {
1674                  /* little-endian screen */                  XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
                 switch (bpp)  
                 {  
                         case 32:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                     *d3++ = pix >> 24;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      24;)}  
                                 break;  
                         case 24:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                     *d3++ = pix >> 16;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                                                      *d3++ =  
                                                                      pix >>  
                                                                      16;)}  
                                 break;  
                         case 16:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                     *d3++ = pix >> 8;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;  
                                                                      *d3++ =  
                                                                      pix >> 8;  
                                         )}  
                                 break;  
                         case 8:  
                                 while (i)  
                                 {  
                                         unroll8Expr(pix = colmap[*data++];  
                                                     *d3++ = pix;  
                                                 )i -= 8;  
                                 }  
                                 i = (size & 0x7);  
                                 if (i != 0)  
                                         switch (i)  
                                         {  
                                                         unroll8Lefts(pix =  
                                                                      colmap  
                                                                      [*data++];  
                                                                      *d3++ =  
                                                                      pix;)}  
                 }  
1675          }          }
 #endif  
1676    
1677          return d2;          XFree(image);
1678  }  }

Legend:
Removed from v.28  
changed lines
  Added in v.342

  ViewVC Help
Powered by ViewVC 1.1.26