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

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

  ViewVC Help
Powered by ViewVC 1.1.26