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

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

  ViewVC Help
Powered by ViewVC 1.1.26