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

Legend:
Removed from v.36  
changed lines
  Added in v.821

  ViewVC Help
Powered by ViewVC 1.1.26