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

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

  ViewVC Help
Powered by ViewVC 1.1.26