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

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

  ViewVC Help
Powered by ViewVC 1.1.26