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

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

  ViewVC Help
Powered by ViewVC 1.1.26