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

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

  ViewVC Help
Powered by ViewVC 1.1.26