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

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

  ViewVC Help
Powered by ViewVC 1.1.26