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

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

  ViewVC Help
Powered by ViewVC 1.1.26