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

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

  ViewVC Help
Powered by ViewVC 1.1.26