/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 28 by matty, Wed Jun 20 13:54:48 2001 UTC revision 487 by astrand, Mon Oct 13 12:34:15 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  static void
302  xwin_set_function(uint8 rop2)  translate8to24(uint8 * data, uint8 * out, uint8 * end)
303  {  {
304          static uint8 last_rop2 = ROP2_COPY;          uint32 value;
305    
306          if (last_rop2 != rop2)          while (out < end)
307          {          {
308                  XSetFunction(display, gc, rop2_map[rop2]);                  value = g_colmap[*(data++)];
309                  last_rop2 = rop2;                  *(out++) = value;
310                    *(out++) = value >> 8;
311                    *(out++) = value >> 16;
312          }          }
313  }  }
314    
315  static void  static void
316  xwin_grab_keyboard()  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          XGrabKeyboard(display, wnd, True, GrabModeAsync, GrabModeAsync,          uint16 pixel;
328                        CurrentTime);          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  static void
355  xwin_ungrab_keyboard()  translate15to24(uint16 * data, uint8 * out, uint8 * end)
356  {  {
357          XUngrabKeyboard(display, CurrentTime);          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
449    translate16to24(uint16 * data, uint8 * out, uint8 * end)
450    {
451            uint32 value;
452            uint16 pixel;
453    
454            while (out < end)
455            {
456                    pixel = *(data++);
457    
458                    if (g_host_be)
459                    {
460                            BSWAP16(pixel)
461                    }
462    
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
481    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            uint32 pixel = 0;
518            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
541    translate24to24(uint8 * data, uint8 * out, uint8 * end)
542    {
543            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          attribs.background_pixel = BlackPixel(display, DefaultScreen(display));          test = 1;
723          attribs.backing_store = Always;          g_host_be = !(BOOL) (*(uint8 *) (&test));
724            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
725    
726          if (fullscreen)          if ((g_width == 0) || (g_height == 0))
727          {          {
728                  attribs.override_redirect = True;                  /* Fetch geometry from _NET_WORKAREA */
729                  width = WidthOfScreen(DefaultScreenOfDisplay(display));                  uint32 x, y, cx, cy;
730                  height = HeightOfScreen(DefaultScreenOfDisplay(display));  
731                  XSetInputFocus(display, PointerRoot, RevertToPointerRoot,                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
732                                 CurrentTime);                  {
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          else  
744            if (g_fullscreen)
745          {          {
746                  attribs.override_redirect = False;                  g_width = WidthOfScreen(g_screen);
747                    g_height = HeightOfScreen(g_screen);
748            }
749    
750            /* make sure width is a multiple of 4 */
751            g_width = (g_width + 3) & ~3;
752    
753            if (g_ownbackstore)
754            {
755                    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,          if (g_enable_compose)
767                              CWBackingStore | CWBackPixel | CWOverrideRedirect,                  g_IM = XOpenIM(g_display, NULL, NULL, NULL);
768                              &attribs);  
769            xkeymap_init();
770            xclip_init();
771    
772            /* todo take this out when high colour is done */
773            printf("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth);
774    
775            return True;
776    }
777    
778    void
779    ui_deinit(void)
780    {
781            if (g_IM != NULL)
782                    XCloseIM(g_IM);
783    
784            XFreeModifiermap(g_mod_map);
785    
786            if (g_ownbackstore)
787                    XFreePixmap(g_display, g_backstore);
788    
789            XFreeGC(g_display, g_gc);
790            XCloseDisplay(g_display);
791            g_display = NULL;
792    }
793    
794    BOOL
795    ui_create_window(void)
796    {
797            XSetWindowAttributes attribs;
798            XClassHint *classhints;
799            XSizeHints *sizehints;
800            int wndwidth, wndheight;
801            long input_mask, ic_input_mask;
802            XEvent xevent;
803    
804            wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
805            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
806    
807            attribs.background_pixel = BlackPixelOfScreen(g_screen);
808            attribs.backing_store = g_ownbackstore ? NotUseful : Always;
809            attribs.override_redirect = g_fullscreen;
810    
811            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
812                                  0, CopyFromParent, InputOutput, CopyFromParent,
813                                  CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
814    
815          XStoreName(display, wnd, title);          XStoreName(g_display, g_wnd, g_title);
816    
817            if (g_hide_decorations)
818                    mwm_hide_decorations();
819    
820          classhints = XAllocClassHint();          classhints = XAllocClassHint();
821          if (classhints != NULL)          if (classhints != NULL)
   
822          {          {
823                  classhints->res_name = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
824                  classhints->res_class = "rdesktop";                  XSetClassHint(g_display, g_wnd, classhints);
                 XSetClassHint(display, wnd, classhints);  
825                  XFree(classhints);                  XFree(classhints);
826          }          }
827    
828          sizehints = XAllocSizeHints();          sizehints = XAllocSizeHints();
829          if (sizehints)          if (sizehints)
830          {          {
831                  sizehints->flags =                  sizehints->flags = PMinSize | PMaxSize;
832                          PPosition | PSize | PMinSize | PMaxSize | PBaseSize;                  sizehints->min_width = sizehints->max_width = g_width;
833                  sizehints->min_width = width;                  sizehints->min_height = sizehints->max_height = g_height;
834                  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);  
835                  XFree(sizehints);                  XFree(sizehints);
836          }          }
837    
838          input_mask = KeyPressMask | KeyReleaseMask;          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
839          input_mask |= ButtonPressMask | ButtonReleaseMask;                  VisibilityChangeMask | FocusChangeMask;
840          if (motion)  
841            if (g_sendmotion)
842                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
843          if (grab_keyboard)          if (g_ownbackstore)
844                  input_mask |= EnterWindowMask | LeaveWindowMask;                  input_mask |= ExposureMask;
845            if (g_fullscreen || g_grab_keyboard)
846                    input_mask |= EnterWindowMask;
847            if (g_grab_keyboard)
848                    input_mask |= LeaveWindowMask;
849    
850            if (g_IM != NULL)
851            {
852                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
853                                     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
854    
855                    if ((g_IC != NULL)
856                        && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
857                            input_mask |= ic_input_mask;
858            }
859    
860          XSelectInput(display, wnd, input_mask);          XSelectInput(g_display, g_wnd, input_mask);
861          gc = XCreateGC(display, wnd, 0, NULL);          XMapWindow(g_display, g_wnd);
862    
863            /* wait for VisibilityNotify */
864            do
865            {
866                    XMaskEvent(g_display, VisibilityChangeMask, &xevent);
867            }
868            while (xevent.type != VisibilityNotify);
869    
870            g_focused = False;
871            g_mouse_in_wnd = False;
872    
873            /* handle the WM_DELETE_WINDOW protocol */
874            g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
875            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
876            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
877    
         XMapWindow(display, wnd);  
878          return True;          return True;
879  }  }
880    
881  void  void
882  ui_destroy_window()  ui_destroy_window(void)
883  {  {
884          XFreeGC(display, gc);          if (g_IC != NULL)
885          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;  
886    
887          if (display == NULL)          XDestroyWindow(g_display, g_wnd);
888                  return;  }
889    
890    void
891    xwin_toggle_fullscreen(void)
892    {
893            Pixmap contents = 0;
894    
895            if (!g_ownbackstore)
896            {
897                    /* need to save contents of window */
898                    contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
899                    XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
900            }
901    
902            ui_destroy_window();
903            g_fullscreen = !g_fullscreen;
904            ui_create_window();
905    
906            XDefineCursor(g_display, g_wnd, g_current_cursor);
907    
908            if (!g_ownbackstore)
909            {
910                    XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
911                    XFreePixmap(g_display, contents);
912            }
913    }
914    
915          while (XCheckWindowEvent(display, wnd, ~0, &event))  /* Process all events in Xlib queue
916       Returns 0 after user quit, 1 otherwise */
917    static int
918    xwin_process_events(void)
919    {
920            XEvent xevent;
921            KeySym keysym;
922            uint16 button, flags;
923            uint32 ev_time;
924            key_translation tr;
925            char str[256];
926            Status status;
927            unsigned int state;
928            Window wdummy;
929            int dummy;
930    
931            while (XPending(g_display) > 0)
932          {          {
933                  ev_time = time(NULL);                  XNextEvent(g_display, &xevent);
934    
935                    if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
936                    {
937                            DEBUG_KBD(("Filtering event\n"));
938                            continue;
939                    }
940    
941                    flags = 0;
942    
943                  switch (event.type)                  switch (xevent.type)
944                  {                  {
945                            case ClientMessage:
946                                    /* the window manager told us to quit */
947                                    if ((xevent.xclient.message_type == g_protocol_atom)
948                                        && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
949                                            /* Quit */
950                                            return 0;
951                                    break;
952    
953                          case KeyPress:                          case KeyPress:
954                                  scancode = xwin_translate_key(event.xkey.keycode);                                  g_last_gesturetime = xevent.xkey.time;
955                                  if (scancode == 0)                                  if (g_IC != NULL)
956                                            /* Multi_key compatible version */
957                                    {
958                                            XmbLookupString(g_IC,
959                                                            &xevent.xkey, str, sizeof(str), &keysym,
960                                                            &status);
961                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
962                                            {
963                                                    error("XmbLookupString failed with status 0x%x\n",
964                                                          status);
965                                                    break;
966                                            }
967                                    }
968                                    else
969                                    {
970                                            /* Plain old XLookupString */
971                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
972                                            XLookupString((XKeyEvent *) & xevent,
973                                                          str, sizeof(str), &keysym, NULL);
974                                    }
975    
976                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
977                                               get_ksname(keysym)));
978    
979                                    ev_time = time(NULL);
980                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
981                                            break;
982    
983                                    tr = xkeymap_translate_key(keysym,
984                                                               xevent.xkey.keycode, xevent.xkey.state);
985    
986                                    if (tr.scancode == 0)
987                                          break;                                          break;
988    
989                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  save_remote_modifiers(tr.scancode);
990                                                 scancode, 0);                                  ensure_remote_modifiers(ev_time, tr);
991                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
992                                    restore_remote_modifiers(ev_time, tr.scancode);
993    
994                                  break;                                  break;
995    
996                          case KeyRelease:                          case KeyRelease:
997                                  scancode = xwin_translate_key(event.xkey.keycode);                                  g_last_gesturetime = xevent.xkey.time;
998                                  if (scancode == 0)                                  XLookupString((XKeyEvent *) & xevent, str,
999                                                  sizeof(str), &keysym, NULL);
1000    
1001                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1002                                               get_ksname(keysym)));
1003    
1004                                    ev_time = time(NULL);
1005                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1006                                          break;                                          break;
1007    
1008                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  tr = xkeymap_translate_key(keysym,
1009                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                             xevent.xkey.keycode, xevent.xkey.state);
                                                scancode, 0);  
                                 break;  
1010    
1011                          case ButtonPress:                                  if (tr.scancode == 0)
                                 button = xwin_translate_mouse(event.xbutton.button);  
                                 if (button == 0)  
1012                                          break;                                          break;
1013    
1014                                  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);  
1015                                  break;                                  break;
1016    
1017                            case ButtonPress:
1018                                    flags = MOUSE_FLAG_DOWN;
1019                                    /* fall through */
1020    
1021                          case ButtonRelease:                          case ButtonRelease:
1022                                  button = xwin_translate_mouse(event.xbutton.button);                                  g_last_gesturetime = xevent.xbutton.time;
1023                                    button = xkeymap_translate_button(xevent.xbutton.button);
1024                                  if (button == 0)                                  if (button == 0)
1025                                          break;                                          break;
1026    
1027                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
1028                                                 button,                                  if (xevent.xbutton.y < g_win_button_size)
1029                                                 event.xbutton.x,                                  {
1030                                                 event.xbutton.y);                                          /* Stop moving window when button is released, regardless of cursor position */
1031                                            if (g_moving_wnd && (xevent.type == ButtonRelease))
1032                                                    g_moving_wnd = False;
1033    
1034                                            /*  Check from right to left: */
1035    
1036                                            if (xevent.xbutton.x >= g_width - g_win_button_size)
1037                                            {
1038                                                    /* The close button, continue */
1039                                                    ;
1040                                            }
1041                                            else if (xevent.xbutton.x >=
1042                                                     g_width - g_win_button_size * 2)
1043                                            {
1044                                                    /* The maximize/restore button. Do not send to
1045                                                       server.  It might be a good idea to change the
1046                                                       cursor or give some other visible indication
1047                                                       that rdesktop inhibited this click */
1048                                                    break;
1049                                            }
1050                                            else if (xevent.xbutton.x >=
1051                                                     g_width - g_win_button_size * 3)
1052                                            {
1053                                                    /* The minimize button. Iconify window. */
1054                                                    XIconifyWindow(g_display, g_wnd,
1055                                                                   DefaultScreen(g_display));
1056                                                    break;
1057                                            }
1058                                            else if (xevent.xbutton.x <= g_win_button_size)
1059                                            {
1060                                                    /* The system menu. Ignore. */
1061                                                    break;
1062                                            }
1063                                            else
1064                                            {
1065                                                    /* The title bar. */
1066                                                    if ((xevent.type == ButtonPress) && !g_fullscreen
1067                                                        && g_hide_decorations)
1068                                                    {
1069                                                            g_moving_wnd = True;
1070                                                            g_move_x_offset = xevent.xbutton.x;
1071                                                            g_move_y_offset = xevent.xbutton.y;
1072                                                    }
1073                                                    break;
1074    
1075                                            }
1076                                    }
1077    
1078                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1079                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1080                                  break;                                  break;
1081    
1082                          case MotionNotify:                          case MotionNotify:
1083                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (g_moving_wnd)
1084                                                 MOUSE_FLAG_MOVE,                                  {
1085                                                 event.xmotion.x,                                          XMoveWindow(g_display, g_wnd,
1086                                                 event.xmotion.y);                                                      xevent.xmotion.x_root - g_move_x_offset,
1087                                                        xevent.xmotion.y_root - g_move_y_offset);
1088                                            break;
1089                                    }
1090    
1091                                    if (g_fullscreen && !g_focused)
1092                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1093                                                           CurrentTime);
1094                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1095                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1096                                    break;
1097    
1098                            case FocusIn:
1099                                    if (xevent.xfocus.mode == NotifyGrab)
1100                                            break;
1101                                    g_focused = True;
1102                                    XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy,
1103                                                  &dummy, &dummy, &state);
1104                                    reset_modifier_keys(state);
1105                                    if (g_grab_keyboard && g_mouse_in_wnd)
1106                                            XGrabKeyboard(g_display, g_wnd, True,
1107                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1108                                    break;
1109    
1110                            case FocusOut:
1111                                    if (xevent.xfocus.mode == NotifyUngrab)
1112                                            break;
1113                                    g_focused = False;
1114                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1115                                            XUngrabKeyboard(g_display, CurrentTime);
1116                                  break;                                  break;
1117    
1118                          case EnterNotify:                          case EnterNotify:
1119                                  if (grab_keyboard)                                  /* we only register for this event when in fullscreen mode */
1120                                          xwin_grab_keyboard();                                  /* or grab_keyboard */
1121                                    g_mouse_in_wnd = True;
1122                                    if (g_fullscreen)
1123                                    {
1124                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1125                                                           CurrentTime);
1126                                            break;
1127                                    }
1128                                    if (g_focused)
1129                                            XGrabKeyboard(g_display, g_wnd, True,
1130                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1131                                  break;                                  break;
1132    
1133                          case LeaveNotify:                          case LeaveNotify:
1134                                  if (grab_keyboard)                                  /* we only register for this event when grab_keyboard */
1135                                          xwin_ungrab_keyboard();                                  g_mouse_in_wnd = False;
1136                                    XUngrabKeyboard(g_display, CurrentTime);
1137                                    break;
1138    
1139                            case Expose:
1140                                    XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1141                                              xevent.xexpose.x, xevent.xexpose.y,
1142                                              xevent.xexpose.width,
1143                                              xevent.xexpose.height,
1144                                              xevent.xexpose.x, xevent.xexpose.y);
1145                                    break;
1146    
1147                            case MappingNotify:
1148                                    /* Refresh keyboard mapping if it has changed. This is important for
1149                                       Xvnc, since it allocates keycodes dynamically */
1150                                    if (xevent.xmapping.request == MappingKeyboard
1151                                        || xevent.xmapping.request == MappingModifier)
1152                                            XRefreshKeyboardMapping(&xevent.xmapping);
1153    
1154                                    if (xevent.xmapping.request == MappingModifier)
1155                                    {
1156                                            XFreeModifiermap(g_mod_map);
1157                                            g_mod_map = XGetModifierMapping(g_display);
1158                                    }
1159                                  break;                                  break;
1160    
1161                                    /* clipboard stuff */
1162                            case SelectionNotify:
1163                                    xclip_handle_SelectionNotify(&xevent.xselection);
1164                                    break;
1165                            case SelectionRequest:
1166                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1167                                    break;
1168                            case SelectionClear:
1169                                    xclip_handle_SelectionClear();
1170                                    break;
1171                            case PropertyNotify:
1172                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1173                                    break;
1174                    }
1175            }
1176            /* Keep going */
1177            return 1;
1178    }
1179    
1180    /* Returns 0 after user quit, 1 otherwise */
1181    int
1182    ui_select(int rdp_socket)
1183    {
1184            int n = (rdp_socket > g_x_socket) ? rdp_socket + 1 : g_x_socket + 1;
1185            fd_set rfds, wfds;
1186    
1187            while (True)
1188            {
1189                    /* Process any events already waiting */
1190                    if (!xwin_process_events())
1191                            /* User quit */
1192                            return 0;
1193    
1194                    FD_ZERO(&rfds);
1195                    FD_ZERO(&wfds);
1196                    FD_SET(rdp_socket, &rfds);
1197                    FD_SET(g_x_socket, &rfds);
1198    
1199    #ifdef WITH_RDPSND
1200                    /* FIXME: there should be an API for registering fds */
1201                    if (g_dsp_busy)
1202                    {
1203                            FD_SET(g_dsp_fd, &wfds);
1204                            n = (g_dsp_fd + 1 > n) ? g_dsp_fd + 1 : n;
1205                    }
1206    #endif
1207    
1208                    switch (select(n, &rfds, &wfds, NULL, NULL))
1209                    {
1210                            case -1:
1211                                    error("select: %s\n", strerror(errno));
1212    
1213                            case 0:
1214                                    continue;
1215                  }                  }
1216    
1217                    if (FD_ISSET(rdp_socket, &rfds))
1218                            return 1;
1219    
1220    #ifdef WITH_RDPSND
1221                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1222                            wave_out_play();
1223    #endif
1224          }          }
1225  }  }
1226    
1227  void  void
1228  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
1229  {  {
1230          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1231  }  }
1232    
1233  HBITMAP  HBITMAP
1234  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1235  {  {
1236          XImage *image;          XImage *image;
1237          Pixmap bitmap;          Pixmap bitmap;
1238          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);  
1239    
1240          xwin_set_function(ROP2_COPY);          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1241          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1242            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1243                                 (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1244    
1245            XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1246    
1247          XFree(image);          XFree(image);
1248          if (!private_colormap)          if (!g_owncolmap)
1249                  xfree(tdata);                  xfree(tdata);
1250          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1251  }  }
1252    
1253  void  void
1254  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)  
1255  {  {
1256          XImage *image;          XImage *image;
1257          uint8 *tdata =          uint8 *tdata;
1258                  (private_colormap ? data : translate(width, height, data));          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1259          image =          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1260                  XCreateImage(display, visual, depth, ZPixmap, 0, tdata, width,                               (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
                              height, BitmapPad(display), 0);  
1261    
1262          xwin_set_function(ROP2_COPY);          if (g_ownbackstore)
1263            {
1264                    XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1265                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1266            }
1267            else
1268            {
1269                    XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1270            }
1271    
         /* Window */  
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
1272          XFree(image);          XFree(image);
1273          if (!private_colormap)          if (!g_owncolmap)
1274                  xfree(tdata);                  xfree(tdata);
1275  }  }
1276    
1277  void  void
1278  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1279  {  {
1280          XFreePixmap(display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
1281    }
1282    
1283    HGLYPH
1284    ui_create_glyph(int width, int height, uint8 * data)
1285    {
1286            XImage *image;
1287            Pixmap bitmap;
1288            int scanline;
1289            GC gc;
1290    
1291            scanline = (width + 7) / 8;
1292    
1293            bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1294            gc = XCreateGC(g_display, bitmap, 0, NULL);
1295    
1296            image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1297                                 width, height, 8, scanline);
1298            image->byte_order = MSBFirst;
1299            image->bitmap_bit_order = MSBFirst;
1300            XInitImage(image);
1301    
1302            XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1303    
1304            XFree(image);
1305            XFreeGC(g_display, gc);
1306            return (HGLYPH) bitmap;
1307    }
1308    
1309    void
1310    ui_destroy_glyph(HGLYPH glyph)
1311    {
1312            XFreePixmap(g_display, (Pixmap) glyph);
1313  }  }
1314    
1315  HCURSOR  HCURSOR
1316  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1317                   int height, uint8 *mask, uint8 *data)                   uint8 * andmask, uint8 * xormask)
1318  {  {
1319          XImage *imagecursor;          HGLYPH maskglyph, cursorglyph;
         XImage *imagemask;  
         Pixmap maskbitmap, cursorbitmap;  
         Cursor cursor;  
1320          XColor bg, fg;          XColor bg, fg;
1321          GC lgc;          Cursor xcursor;
1322          int i, x1, y1, scanlinelen;          uint8 *cursor, *pcursor;
1323          uint8 *cdata, *cmask;          uint8 *mask, *pmask;
1324          uint8 c;          uint8 nextbit;
1325          cdata = (uint8 *) malloc(sizeof(uint8) * width * height);          int scanline, offset;
1326          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;  
1327    
1328          if (!screen_msbfirst)          scanline = (width + 7) / 8;
1329          {          offset = scanline * height;
1330                  while (i >= 0)  
1331                  {          cursor = (uint8 *) xmalloc(offset);
1332                          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;  
                 }  
         }  
1333    
1334            mask = (uint8 *) xmalloc(offset);
1335            memset(mask, 0, offset);
1336    
1337          fg.red = 0;          /* approximate AND and XOR masks with a monochrome X pointer */
1338          fg.blue = 0;          for (i = 0; i < height; i++)
1339          fg.green = 0;          {
1340          fg.flags = DoRed | DoBlue | DoGreen;                  offset -= scanline;
1341          bg.red = 65535;                  pcursor = &cursor[offset];
1342          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))  
1343    
1344                    for (j = 0; j < scanline; j++)
1345                    {
1346                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1347                            {
1348                                    if (xormask[0] || xormask[1] || xormask[2])
1349                                  {                                  {
1350                                          XPutPixel(imagecursor, x1, y1, 0);                                          *pcursor |= (~(*andmask) & nextbit);
1351                                          XPutPixel(imagemask, x1, y1, 0);        /* mask is blank for text cursor! */                                          *pmask |= nextbit;
1352                                  }                                  }
   
1353                                  else                                  else
1354                                          XPutPixel(imagecursor, x1, y1, 1);                                  {
1355                                            *pcursor |= ((*andmask) & nextbit);
1356                                            *pmask |= (~(*andmask) & nextbit);
1357                                    }
1358    
1359                                    xormask += 3;
1360                            }
1361    
1362                          else                          andmask++;
1363                                  XPutPixel(imagecursor, x1, y1,                          pcursor++;
1364                                            XGetPixel(imagemask, x1, y1));                          pmask++;
1365                          data += 3;                  }
1366                  }          }
1367          XPutImage(display, maskbitmap, lgc, imagemask, 0, 0, 0, 0, width,  
1368                    height);          fg.red = fg.blue = fg.green = 0xffff;
1369          XPutImage(display, cursorbitmap, lgc, imagecursor, 0, 0, 0, 0, width,          bg.red = bg.blue = bg.green = 0x0000;
1370                    height); XFree(imagemask);          fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1371          XFree(imagecursor);  
1372          free(cmask);          cursorglyph = ui_create_glyph(width, height, cursor);
1373          free(cdata);          maskglyph = ui_create_glyph(width, height, mask);
1374          XFreeGC(display, lgc);  
1375          cursor =          xcursor =
1376                  XCreatePixmapCursor(display, cursorbitmap, maskbitmap, &fg,                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1377                                      &bg, x, y);                                      (Pixmap) maskglyph, &fg, &bg, x, y);
1378          XFreePixmap(display, maskbitmap);  
1379          XFreePixmap(display, cursorbitmap);          ui_destroy_glyph(maskglyph);
1380          return (HCURSOR) cursor;          ui_destroy_glyph(cursorglyph);
1381            xfree(mask);
1382            xfree(cursor);
1383            return (HCURSOR) xcursor;
1384  }  }
1385    
1386  void  void
1387  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
1388  {  {
1389          XDefineCursor(display, wnd, (Cursor) cursor);          g_current_cursor = (Cursor) cursor;
1390            XDefineCursor(g_display, g_wnd, g_current_cursor);
1391  }  }
1392    
1393  void  void
1394  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
1395  {  {
1396          XFreeCursor(display, (Cursor) cursor);          XFreeCursor(g_display, (Cursor) cursor);
1397  }  }
1398    
1399  HGLYPH  #define MAKE_XCOLOR(xc,c) \
1400  ui_create_glyph(int width, int height, uint8 *data)                  (xc)->red   = ((c)->red   << 8) | (c)->red; \
1401                    (xc)->green = ((c)->green << 8) | (c)->green; \
1402                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1403                    (xc)->flags = DoRed | DoGreen | DoBlue;
1404    
1405    
1406    HCOLOURMAP
1407    ui_create_colourmap(COLOURMAP * colours)
1408  {  {
1409          XImage *image;          COLOURENTRY *entry;
1410          Pixmap bitmap;          int i, ncolours = colours->ncolours;
1411          int scanline;          if (!g_owncolmap)
1412          GC gc;          {
1413                    uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1414                    XColor xentry;
1415                    XColor xc_cache[256];
1416                    uint32 colour;
1417                    int colLookup = 256;
1418                    for (i = 0; i < ncolours; i++)
1419                    {
1420                            entry = &colours->colours[i];
1421                            MAKE_XCOLOR(&xentry, entry);
1422    
1423          scanline = (width + 7) / 8;                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1424                            {
1425                                    /* Allocation failed, find closest match. */
1426                                    int j = 256;
1427                                    int nMinDist = 3 * 256 * 256;
1428                                    long nDist = nMinDist;
1429    
1430          bitmap = XCreatePixmap(display, wnd, width, height, 1);                                  /* only get the colors once */
1431          gc = XCreateGC(display, bitmap, 0, NULL);                                  while (colLookup--)
1432                                    {
1433                                            xc_cache[colLookup].pixel = colLookup;
1434                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1435                                                    xc_cache[colLookup].blue = 0;
1436                                            xc_cache[colLookup].flags = 0;
1437                                            XQueryColor(g_display,
1438                                                        DefaultColormap(g_display,
1439                                                                        DefaultScreen(g_display)),
1440                                                        &xc_cache[colLookup]);
1441                                    }
1442                                    colLookup = 0;
1443    
1444          image = XCreateImage(display, visual, 1, ZPixmap, 0,                                  /* approximate the pixel */
1445                               data, width, height, 8, scanline);                                  while (j--)
1446          image->byte_order = MSBFirst;                                  {
1447          image->bitmap_bit_order = MSBFirst;                                          if (xc_cache[j].flags)
1448          XInitImage(image);                                          {
1449                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1450                                                             (long) (xentry.red >> 8)) *
1451                                                            ((long) (xc_cache[j].red >> 8) -
1452                                                             (long) (xentry.red >> 8)) +
1453                                                            ((long) (xc_cache[j].green >> 8) -
1454                                                             (long) (xentry.green >> 8)) *
1455                                                            ((long) (xc_cache[j].green >> 8) -
1456                                                             (long) (xentry.green >> 8)) +
1457                                                            ((long) (xc_cache[j].blue >> 8) -
1458                                                             (long) (xentry.blue >> 8)) *
1459                                                            ((long) (xc_cache[j].blue >> 8) -
1460                                                             (long) (xentry.blue >> 8));
1461                                            }
1462                                            if (nDist < nMinDist)
1463                                            {
1464                                                    nMinDist = nDist;
1465                                                    xentry.pixel = j;
1466                                            }
1467                                    }
1468                            }
1469                            colour = xentry.pixel;
1470    
1471          XSetFunction(display, gc, GXcopy);                          /* update our cache */
1472          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);                          if (xentry.pixel < 256)
1473          XFree(image);                          {
1474          XFreeGC(display, gc);                                  xc_cache[xentry.pixel].red = xentry.red;
1475                                    xc_cache[xentry.pixel].green = xentry.green;
1476                                    xc_cache[xentry.pixel].blue = xentry.blue;
1477    
1478          return (HGLYPH) bitmap;                          }
 }  
1479    
 void  
 ui_destroy_glyph(HGLYPH glyph)  
 {  
         XFreePixmap(display, (Pixmap) glyph);  
 }  
1480    
1481  HCOLOURMAP                          /* byte swap here to make translate_image faster */
1482  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;  
1483                  }                  }
1484                  return nc;                  return map;
1485          }          }
1486          else          else
1487          {          {
                 COLOURENTRY *entry;  
1488                  XColor *xcolours, *xentry;                  XColor *xcolours, *xentry;
1489                  Colormap map;                  Colormap map;
1490                  int i, ncolours = colours->ncolours;  
1491                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1492                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1493                  {                  {
1494                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1495                          xentry = &xcolours[i];                          xentry = &xcolours[i];
   
1496                          xentry->pixel = i;                          xentry->pixel = i;
1497                          xentry->red = entry->red << 8;                          MAKE_XCOLOR(xentry, entry);
                         xentry->blue = entry->blue << 8;  
                         xentry->green = entry->green << 8;  
                         xentry->flags = DoRed | DoBlue | DoGreen;  
1498                  }                  }
1499    
1500                  map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1501                  XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
1502    
1503                  xfree(xcolours);                  xfree(xcolours);
1504                  return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
# Line 612  ui_create_colourmap(COLOURMAP *colours) Line 1508  ui_create_colourmap(COLOURMAP *colours)
1508  void  void
1509  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1510  {  {
1511          XFreeColormap(display, (Colormap) map);          if (!g_owncolmap)
1512                    xfree(map);
1513            else
1514                    XFreeColormap(g_display, (Colormap) map);
1515  }  }
1516    
1517  void  void
1518  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1519  {  {
1520            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  
1521          {          {
1522                  XSetWindowColormap(display, wnd, (Colormap) map);                  if (g_colmap)
1523                  if (fullscreen)                          xfree(g_colmap);
1524                          XInstallColormap(display, (Colormap) map);  
1525                    g_colmap = (uint32 *) map;
1526          }          }
1527            else
1528                    XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1529  }  }
1530    
1531  void  void
# Line 640  ui_set_clip(int x, int y, int cx, int cy Line 1537  ui_set_clip(int x, int y, int cx, int cy
1537          rect.y = y;          rect.y = y;
1538          rect.width = cx;          rect.width = cx;
1539          rect.height = cy;          rect.height = cy;
1540          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1541  }  }
1542    
1543  void  void
1544  ui_reset_clip()  ui_reset_clip(void)
1545  {  {
1546          XRectangle rect;          XRectangle rect;
1547    
1548          rect.x = 0;          rect.x = 0;
1549          rect.y = 0;          rect.y = 0;
1550          rect.width = width;          rect.width = g_width;
1551          rect.height = height;          rect.height = g_height;
1552          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1553  }  }
1554    
1555  void  void
1556  ui_bell()  ui_bell(void)
1557  {  {
1558          XBell(display, 0);          XBell(g_display, 0);
1559  }  }
1560    
1561  void  void
1562  ui_destblt(uint8 opcode,  ui_destblt(uint8 opcode,
1563             /* dest */ int x, int y, int cx, int cy)             /* dest */ int x, int y, int cx, int cy)
1564  {  {
1565          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1566            FILL_RECTANGLE(x, y, cx, cy);
1567          XFillRectangle(display, wnd, gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
1568  }  }
1569    
1570    static uint8 hatch_patterns[] = {
1571            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1572            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1573            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1574            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1575            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1576            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
1577    };
1578    
1579  void  void
1580  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
1581            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1582            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1583  {  {
         Display *dpy = display;  
1584          Pixmap fill;          Pixmap fill;
1585          uint8 i, ipattern[8];          uint8 i, ipattern[8];
1586    
1587          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1588    
1589          switch (brush->style)          switch (brush->style)
1590          {          {
1591                  case 0: /* Solid */                  case 0: /* Solid */
1592                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_FOREGROUND(fgcolour);
1593                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1594                            break;
1595    
1596                    case 2: /* Hatch */
1597                            fill = (Pixmap) ui_create_glyph(8, 8,
1598                                                            hatch_patterns + brush->pattern[0] * 8);
1599                            SET_FOREGROUND(fgcolour);
1600                            SET_BACKGROUND(bgcolour);
1601                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1602                            XSetStipple(g_display, g_gc, fill);
1603                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1604                            FILL_RECTANGLE(x, y, cx, cy);
1605                            XSetFillStyle(g_display, g_gc, FillSolid);
1606                            XSetTSOrigin(g_display, g_gc, 0, 0);
1607                            ui_destroy_glyph((HGLYPH) fill);
1608                          break;                          break;
1609    
1610                  case 3: /* Pattern */                  case 3: /* Pattern */
1611                          for (i = 0; i != 8; i++)                          for (i = 0; i != 8; i++)
1612                                  ipattern[i] = ~brush->pattern[i];                                  ipattern[7 - i] = brush->pattern[i];
1613                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1614    
1615                          XSetForeground(dpy, gc, Ctrans(fgcolour));                          SET_FOREGROUND(bgcolour);
1616                          XSetBackground(dpy, gc, Ctrans(bgcolour));                          SET_BACKGROUND(fgcolour);
1617                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1618                          XSetStipple(dpy, gc, fill);                          XSetStipple(g_display, g_gc, fill);
1619                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1620    
1621                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1622    
1623                          XSetFillStyle(dpy, gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
1624                            XSetTSOrigin(g_display, g_gc, 0, 0);
1625                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
1626                          break;                          break;
1627    
1628                  default:                  default:
1629                          NOTIMP("brush %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
1630          }          }
1631    
1632            RESET_FUNCTION(opcode);
1633  }  }
1634    
1635  void  void
# Line 714  ui_screenblt(uint8 opcode, Line 1637  ui_screenblt(uint8 opcode,
1637               /* dest */ int x, int y, int cx, int cy,               /* dest */ int x, int y, int cx, int cy,
1638               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
1639  {  {
1640          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1641            XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1642          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          if (g_ownbackstore)
1643                    XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1644            RESET_FUNCTION(opcode);
1645  }  }
1646    
1647  void  void
# Line 724  ui_memblt(uint8 opcode, Line 1649  ui_memblt(uint8 opcode,
1649            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1650            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1651  {  {
1652          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1653            XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1654          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          if (g_ownbackstore)
1655                    XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1656            RESET_FUNCTION(opcode);
1657  }  }
1658    
1659  void  void
1660  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1661            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1662            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1663            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1664  {  {
1665          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1666             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 1669  ui_triblt(uint8 opcode,
1669          {          {
1670                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1671                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1672                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1673                          break;                          break;
1674    
1675                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1676                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1677                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1678                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1679                          break;                          break;
1680    
1681                  case 0xc0:                  case 0xc0:      /* PSa */
1682                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1683                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
1684                          break;                          break;
1685    
1686                  default:                  default:
1687                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
1688                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1689          }          }
1690  }  }
# Line 769  ui_triblt(uint8 opcode, Line 1692  ui_triblt(uint8 opcode,
1692  void  void
1693  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1694          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1695          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1696  {  {
1697          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1698            SET_FOREGROUND(pen->colour);
1699          XSetForeground(display, gc, Ctrans(pen->colour));          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1700          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          if (g_ownbackstore)
1701                    XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1702            RESET_FUNCTION(opcode);
1703  }  }
1704    
1705  void  void
# Line 782  ui_rect( Line 1707  ui_rect(
1707                 /* dest */ int x, int y, int cx, int cy,                 /* dest */ int x, int y, int cx, int cy,
1708                 /* brush */ int colour)                 /* brush */ int colour)
1709  {  {
1710          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(colour);
1711            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(display, gc, Ctrans(colour));  
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1712  }  }
1713    
1714    /* warning, this function only draws on wnd or backstore, not both */
1715  void  void
1716  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1717                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1718                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1719                int fgcolour)                int bgcolour, int fgcolour)
1720  {  {
1721          Pixmap pixmap = (Pixmap) glyph;          SET_FOREGROUND(fgcolour);
1722            SET_BACKGROUND(bgcolour);
         xwin_set_function(ROP2_COPY);  
   
1723    
1724          XSetForeground(display, gc, Ctrans(fgcolour));          XSetFillStyle(g_display, g_gc,
1725          switch (mixmode)                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1726          {          XSetStipple(g_display, g_gc, (Pixmap) glyph);
1727                  case MIX_TRANSPARENT:          XSetTSOrigin(g_display, g_gc, x, y);
1728                          XSetStipple(display, gc, pixmap);  
1729                          XSetFillStyle(display, gc, FillStippled);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1730                          XSetTSOrigin(display, gc, x, y);  
1731                          XFillRectangle(display, wnd, gc, x, y, cx, cy);          XSetFillStyle(g_display, g_gc, FillSolid);
1732                          XSetFillStyle(display, gc, FillSolid);  }
1733                          break;  
1734    #define DO_GLYPH(ttext,idx) \
1735                  case MIX_OPAQUE:  {\
1736                          XSetBackground(display, gc, Ctrans(bgcolour));    glyph = cache_get_font (font, ttext[idx]);\
1737  /*      XCopyPlane (display, pixmap, back_pixmap, back_gc, srcx, srcy, cx, cy, x, y, 1); */    if (!(flags & TEXT2_IMPLICIT_X))\
1738                          XSetStipple(display, gc, pixmap);      {\
1739                          XSetFillStyle(display, gc, FillOpaqueStippled);        xyoffset = ttext[++idx];\
1740                          XSetTSOrigin(display, gc, x, y);        if ((xyoffset & 0x80))\
1741                          XFillRectangle(display, wnd, gc, x, y, cx, cy);          {\
1742                          XSetFillStyle(display, gc, FillSolid);            if (flags & TEXT2_VERTICAL) \
1743                          break;              y += ttext[idx+1] | (ttext[idx+2] << 8);\
1744              else\
1745                  default:              x += ttext[idx+1] | (ttext[idx+2] << 8);\
1746                          NOTIMP("mix %d\n", mixmode);            idx += 2;\
1747          }          }\
1748          else\
1749            {\
1750              if (flags & TEXT2_VERTICAL) \
1751                y += xyoffset;\
1752              else\
1753                x += xyoffset;\
1754            }\
1755        }\
1756      if (glyph != NULL)\
1757        {\
1758          ui_draw_glyph (mixmode, x + glyph->offset,\
1759                         y + glyph->baseline,\
1760                         glyph->width, glyph->height,\
1761                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1762          if (flags & TEXT2_IMPLICIT_X)\
1763            x += glyph->width;\
1764        }\
1765  }  }
1766    
1767  void  void
1768  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,
1769               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
1770               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1771               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
1772  {  {
1773          FONTGLYPH *glyph;          FONTGLYPH *glyph;
1774          int i, xyoffset;          int i, j, xyoffset;
1775            DATABLOB *entry;
1776    
1777          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(bgcolour);
         XSetForeground(display, gc, Ctrans(bgcolour));  
1778    
1779          if (boxcx > 1)          if (boxcx > 1)
1780                  XFillRectangle(display, wnd, gc, boxx, boxy, boxcx, boxcy);          {
1781                    FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1782            }
1783          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1784                  XFillRectangle(display, wnd, gc, clipx, clipy, clipcx, clipcy);          {
1785                    FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1786            }
1787    
1788          /* Paint text, character by character */          /* Paint text, character by character */
1789          for (i = 0; i < length; i++)          for (i = 0; i < length;)
1790          {          {
1791                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
   
1792                  {                  {
1793                          xyoffset = text[++i];                          case 0xff:
1794                          if ((xyoffset & 0x80))                                  if (i + 2 < length)
1795                          {                                          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;  
1796                                  else                                  else
1797                                          x += xyoffset;                                  {
1798                          }                                          error("this shouldn't be happening\n");
1799                                            exit(1);
1800                                    }
1801                                    /* this will move pointer from start to first character after FF command */
1802                                    length -= i + 3;
1803                                    text = &(text[i + 3]);
1804                                    i = 0;
1805                                    break;
1806    
1807                  }                          case 0xfe:
1808                  if (glyph != NULL)                                  entry = cache_get_text(text[i + 1]);
1809                  {                                  if (entry != NULL)
1810                          ui_draw_glyph(mixmode, x + (short) glyph->offset,                                  {
1811                                        y + (short) glyph->baseline,                                          if ((((uint8 *) (entry->data))[1] ==
1812                                        glyph->width, glyph->height,                                               0) && (!(flags & TEXT2_IMPLICIT_X)))
1813                                        glyph->pixmap, 0, 0,                                          {
1814                                        bgcolour, fgcolour);                                                  if (flags & TEXT2_VERTICAL)
1815                                                            y += text[i + 2];
1816                                                    else
1817                                                            x += text[i + 2];
1818                                            }
1819                                            for (j = 0; j < entry->size; j++)
1820                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1821                                    }
1822                                    if (i + 2 < length)
1823                                            i += 3;
1824                                    else
1825                                            i += 2;
1826                                    length -= i;
1827                                    /* this will move pointer from start to first character after FE command */
1828                                    text = &(text[i]);
1829                                    i = 0;
1830                                    break;
1831    
1832                          if (flags & TEXT2_IMPLICIT_X)                          default:
1833                                  x += glyph->width;                                  DO_GLYPH(text, i);
1834                                    i++;
1835                                    break;
1836                  }                  }
1837          }          }
1838            if (g_ownbackstore)
1839            {
1840                    if (boxcx > 1)
1841                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
1842                                      boxy, boxcx, boxcy, boxx, boxy);
1843                    else
1844                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
1845                                      clipy, clipcx, clipcy, clipx, clipy);
1846            }
1847  }  }
1848    
1849  void  void
# Line 887  ui_desktop_save(uint32 offset, int x, in Line 1852  ui_desktop_save(uint32 offset, int x, in
1852          Pixmap pix;          Pixmap pix;
1853          XImage *image;          XImage *image;
1854    
1855          pix = XCreatePixmap(display, wnd, cx, cy, depth);          if (g_ownbackstore)
1856          xwin_set_function(ROP2_COPY);          {
1857                    image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1858          XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);          }
1859          image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);          else
1860            {
1861                    pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
1862                    XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
1863                    image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1864                    XFreePixmap(g_display, pix);
1865            }
1866    
1867          offset *= bpp/8;          offset *= g_bpp / 8;
1868          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);  
1869    
1870          XDestroyImage(image);          XDestroyImage(image);
         XFreePixmap(display, pix);  
1871  }  }
1872    
1873  void  void
# Line 907  ui_desktop_restore(uint32 offset, int x, Line 1876  ui_desktop_restore(uint32 offset, int x,
1876          XImage *image;          XImage *image;
1877          uint8 *data;          uint8 *data;
1878    
1879          offset *= bpp/8;          offset *= g_bpp / 8;
1880          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
1881          if (data == NULL)          if (data == NULL)
1882                  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);  
 }  
1883    
1884  /* unroll defines, used to make the loops a bit more readable... */          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1885  #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  
1886    
1887  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)  
1888          {          {
1889                  /* big-endian screen */                  XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1890                  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;)}  
                 }  
1891          }          }
1892          else          else
1893          {          {
1894                  /* 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;)}  
                 }  
1895          }          }
 #endif  
1896    
1897          return d2;          XFree(image);
1898  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26