/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.59  
changed lines
  Added in v.800

  ViewVC Help
Powered by ViewVC 1.1.26