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

Legend:
Removed from v.31  
changed lines
  Added in v.566

  ViewVC Help
Powered by ViewVC 1.1.26