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

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

  ViewVC Help
Powered by ViewVC 1.1.26