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

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

  ViewVC Help
Powered by ViewVC 1.1.26