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

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

  ViewVC Help
Powered by ViewVC 1.1.26