/[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 29 by matty, Fri Sep 14 03:38:39 2001 UTC revision 822 by stargo, Mon Feb 28 22:38:24 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-2000     Copyright (C) Matthew Chapman 1999-2002
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Line 20  Line 20 
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22  #include <X11/Xutil.h>  #include <X11/Xutil.h>
23    #include <unistd.h>
24    #include <sys/time.h>
25  #include <time.h>  #include <time.h>
26    #include <errno.h>
27    #include <strings.h>
28  #include "rdesktop.h"  #include "rdesktop.h"
29    #include "xproto.h"
30    
31  extern int 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 Window wnd;  extern BOOL g_grab_keyboard;
38  static GC gc;  extern BOOL g_hide_decorations;
39  static Visual *visual;  extern char g_title[];
40  static int depth;  extern int g_server_bpp;
41  static int bpp;  extern int g_win_button_size;
42  static BOOL backpixmap;  
43    Display *g_display;
44  static BOOL owncolmap;  Time g_last_gesturetime;
45  static Colormap xcolmap;  static int g_x_socket;
46  static uint32 white;  static Screen *g_screen;
47  static uint32 *colmap;  Window g_wnd;
48    extern uint32 g_embed_wnd;
49  #define TRANSLATE(col)          ( owncolmap ? col : colmap[col] )  BOOL g_enable_compose = False;
50  #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));  BOOL g_Unobscured;              /* used for screenblt */
51  #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));  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 */
68    static BOOL g_host_be;
69    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 */
74    extern BOOL g_ownbackstore;
75    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)\
111    { \
112            XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
113            if (g_ownbackstore) \
114                    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 */
123    extern BOOL g_owncolmap;
124    static Colormap g_xcolmap;
125    static uint32 *g_colmap = NULL;
126    
127    #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
128    #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
129    #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
130    
131  static int rop2_map[] = {  static int rop2_map[] = {
132          GXclear,                /* 0 */          GXclear,                /* 0 */
# Line 64  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  /* XXX endianness */  /* 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                    while (out < end)
316                    {
317                            value = g_colmap[*(data++)];
318                            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
332    translate8to32(const uint8 * data, uint8 * out, uint8 * end)
333    {
334            uint32 value;
335    
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 void
365    translate15to16(const uint16 * data, uint8 * out, uint8 * end)
366    {
367            uint16 pixel;
368            uint16 value;
369            PixelColour pc;
370    
371            if (g_xserver_be)
372            {
373                    while (out < end)
374                    {
375                            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                  value = colmap[*(data++)];                  while (out < end)
388                  *(out++) = value;                  {
389                  *(out++) = value >> 8;                          pixel = *(data++);
390                  *(out++) = value >> 16;                          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  static void  static void
402  translate32(uint8 *data, uint32 *out, uint32 *end)  translate15to24(const uint16 * data, uint8 * out, uint8 * end)
403  {  {
404            uint32 value;
405            uint16 pixel;
406            PixelColour pc;
407    
408            if (g_arch_match)
409            {
410                    /* *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    static void
452    translate15to32(const uint16 * data, uint8 * out, uint8 * end)
453    {
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    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    static void
560    translate16to24(const uint16 * data, uint8 * out, uint8 * end)
561    {
562            uint32 value;
563            uint16 pixel;
564            PixelColour pc;
565    
566            if (g_arch_match)
567            {
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            uint16 pixel;
633            uint32 value;
634            PixelColour pc;
635    
636            if (g_arch_match)
637            {
638                    /* *INDENT-OFF* */
639                    REPEAT4
640                    (
641                            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)          while (out < end)
707                  *(out++) = colmap[*(data++)];          {
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    #ifdef NEED_ALIGN
768                    REPEAT4
769                    (
770                            *(out++) = *(data++);
771                            *(out++) = *(data++);
772                            *(out++) = *(data++);
773                            *(out++) = 0;
774                    )
775    #else
776                    REPEAT4
777                    (
778                            *((uint32 *) out) = *((uint32 *) data);
779                            out += 4;
780                            data += 3;
781                    )
782    #endif
783                    /* *INDENT-ON* */
784            }
785            else if (g_xserver_be)
786            {
787                    while (out < end)
788                    {
789                            pixel = *(data++) << 16;
790                            pixel |= *(data++) << 8;
791                            pixel |= *(data++);
792                            SPLITCOLOUR24(pixel, pc);
793                            value = MAKECOLOUR(pc);
794                            BOUT32(out, value);
795                    }
796            }
797            else
798            {
799                    while (out < end)
800                    {
801                            pixel = *(data++) << 16;
802                            pixel |= *(data++) << 8;
803                            pixel |= *(data++);
804                            SPLITCOLOUR24(pixel, pc);
805                            value = MAKECOLOUR(pc);
806                            LOUT32(out, value);
807                    }
808            }
809  }  }
810    
811  static uint8 *  static uint8 *
812  translate(int width, int height, uint8 *data)  translate_image(int width, int height, uint8 * data)
813  {  {
814          int size = width * height * bpp/8;          int size;
815          uint8 *out = xmalloc(size);          uint8 *out;
816          uint8 *end = out + size;          uint8 *end;
817    
818            /* if server and xserver bpp match, */
819            /* and arch(endian) matches, no need to translate */
820            /* just return data */
821            if (g_arch_match)
822            {
823                    if (g_depth == 15 && g_server_bpp == 15)
824                            return data;
825                    if (g_depth == 16 && g_server_bpp == 16)
826                            return data;
827                    if (g_depth == 24 && g_bpp == 24 && g_server_bpp == 24)
828                            return data;
829            }
830    
831            size = width * height * (g_bpp / 8);
832            out = (uint8 *) xmalloc(size);
833            end = out + size;
834    
835          switch (bpp)          switch (g_server_bpp)
836          {          {
837                  case 8:                  case 24:
838                          translate8(data, out, end);                          switch (g_bpp)
839                            {
840                                    case 32:
841                                            translate24to32(data, out, end);
842                                            break;
843                                    case 24:
844                                            translate24to24(data, out, end);
845                                            break;
846                                    case 16:
847                                            translate24to16(data, out, end);
848                                            break;
849                            }
850                          break;                          break;
   
851                  case 16:                  case 16:
852                          translate16(data, (uint16 *)out, (uint16 *)end);                          switch (g_bpp)
853                            {
854                                    case 32:
855                                            translate16to32((uint16 *) data, out, end);
856                                            break;
857                                    case 24:
858                                            translate16to24((uint16 *) data, out, end);
859                                            break;
860                                    case 16:
861                                            translate16to16((uint16 *) data, out, end);
862                                            break;
863                            }
864                          break;                          break;
865                    case 15:
866                  case 24:                          switch (g_bpp)
867                          translate24(data, out, end);                          {
868                                    case 32:
869                                            translate15to32((uint16 *) data, out, end);
870                                            break;
871                                    case 24:
872                                            translate15to24((uint16 *) data, out, end);
873                                            break;
874                                    case 16:
875                                            translate15to16((uint16 *) data, out, end);
876                                            break;
877                            }
878                          break;                          break;
879                    case 8:
880                  case 32:                          switch (g_bpp)
881                          translate32(data, (uint32 *)out, (uint32 *)end);                          {
882                                    case 8:
883                                            translate8to8(data, out, end);
884                                            break;
885                                    case 16:
886                                            translate8to16(data, out, end);
887                                            break;
888                                    case 24:
889                                            translate8to24(data, out, end);
890                                            break;
891                                    case 32:
892                                            translate8to32(data, out, end);
893                                            break;
894                            }
895                          break;                          break;
896          }          }
   
897          return out;          return out;
898  }  }
899    
900  #define L_ENDIAN  BOOL
901  int screen_msbfirst = 0;  get_key_state(unsigned int state, uint32 keysym)
902    {
903            int modifierpos, key, keysymMask = 0;
904            int offset;
905    
906            KeyCode keycode = XKeysymToKeycode(g_display, keysym);
907    
908            if (keycode == NoSymbol)
909                    return False;
910    
911            for (modifierpos = 0; modifierpos < 8; modifierpos++)
912            {
913                    offset = g_mod_map->max_keypermod * modifierpos;
914    
915                    for (key = 0; key < g_mod_map->max_keypermod; key++)
916                    {
917                            if (g_mod_map->modifiermap[offset + key] == keycode)
918                                    keysymMask |= 1 << modifierpos;
919                    }
920            }
921    
922            return (state & keysymMask) ? True : False;
923    }
924    
925    static void
926    calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
927    {
928            *shift_l = ffs(mask) - 1;
929            mask >>= *shift_l;
930            *shift_r = 8 - ffs(mask & ~(mask >> 1));
931    }
932    
933  BOOL  BOOL
934  ui_create_window(char *title)  ui_init(void)
935  {  {
936          XSetWindowAttributes attribs;          XVisualInfo vi;
         XClassHint *classhints;  
         XSizeHints *sizehints;  
         unsigned long input_mask;  
937          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
938          Screen *screen;          uint16 test;
939          int i;          int i, screen_num, nvisuals;
940            XVisualInfo *vmatches = NULL;
941            XVisualInfo template;
942            Bool TrueColorVisual = False;
943    
944            g_display = XOpenDisplay(NULL);
945          display = XOpenDisplay(NULL);          if (g_display == NULL)
         if (display == NULL)  
946          {          {
947                  ERROR("Failed to open display\n");                  error("Failed to open display: %s\n", XDisplayName(NULL));
948                  return False;                  return False;
949          }          }
950    
951          screen = DefaultScreenOfDisplay(display);          screen_num = DefaultScreen(g_display);
952          visual = DefaultVisualOfScreen(screen);          g_x_socket = ConnectionNumber(g_display);
953          depth = DefaultDepthOfScreen(screen);          g_screen = ScreenOfDisplay(g_display, screen_num);
954            g_depth = DefaultDepthOfScreen(g_screen);
955    
956            /* Search for best TrueColor depth */
957            template.class = TrueColor;
958            vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);
959    
960            nvisuals--;
961            while (nvisuals >= 0)
962            {
963                    if ((vmatches + nvisuals)->depth > g_depth)
964                    {
965                            g_depth = (vmatches + nvisuals)->depth;
966                    }
967                    nvisuals--;
968                    TrueColorVisual = True;
969            }
970    
971            test = 1;
972            g_host_be = !(BOOL) (*(uint8 *) (&test));
973            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
974    
975            if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))
976            {
977                    /* we use a colourmap, so the default visual should do */
978                    g_visual = DefaultVisualOfScreen(g_screen);
979                    g_depth = DefaultDepthOfScreen(g_screen);
980    
981          pfm = XListPixmapFormats(display, &i);                  /* Do not allocate colours on a TrueColor visual */
982                    if (g_visual->class == TrueColor)
983                    {
984                            g_owncolmap = False;
985                    }
986            }
987            else
988            {
989                    /* need a truecolour visual */
990                    if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))
991                    {
992                            error("The display does not support true colour - high colour support unavailable.\n");
993                            return False;
994                    }
995    
996                    g_visual = vi.visual;
997                    g_owncolmap = False;
998                    calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);
999                    calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);
1000                    calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);
1001    
1002                    /* if RGB video and everything is little endian */
1003                    if ((vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask) &&
1004                        !g_xserver_be && !g_host_be)
1005                    {
1006                            if (g_depth <= 16 || (g_red_shift_l == 16 && g_green_shift_l == 8 &&
1007                                                  g_blue_shift_l == 0))
1008                            {
1009                                    g_arch_match = True;
1010                            }
1011                    }
1012    
1013                    if (g_arch_match)
1014                    {
1015                            DEBUG(("Architectures match, enabling little endian optimisations.\n"));
1016                    }
1017            }
1018    
1019            pfm = XListPixmapFormats(g_display, &i);
1020          if (pfm != NULL)          if (pfm != NULL)
1021          {          {
1022                  /* Use maximum bpp for this depth - this is generally                  /* Use maximum bpp for this depth - this is generally
1023                     desirable, e.g. 24 bits->32 bits. */                     desirable, e.g. 24 bits->32 bits. */
1024                  while (i--)                  while (i--)
1025                  {                  {
1026                          if ((pfm[i].depth == depth)                          if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
                             && (pfm[i].bits_per_pixel > bpp))  
1027                          {                          {
1028                                  bpp = pfm[i].bits_per_pixel;                                  g_bpp = pfm[i].bits_per_pixel;
1029                          }                          }
1030                  }                  }
1031                  XFree(pfm);                  XFree(pfm);
1032          }          }
1033    
1034          if (bpp < 8)          if (g_bpp < 8)
1035          {          {
1036                  ERROR("Less than 8 bpp not currently supported.\n");                  error("Less than 8 bpp not currently supported.\n");
1037                  XCloseDisplay(display);                  XCloseDisplay(g_display);
1038                  return False;                  return False;
1039          }          }
1040    
1041          if (depth <= 8)          if (!g_owncolmap)
1042                  owncolmap = True;          {
1043          else                  g_xcolmap =
1044                  xcolmap = DefaultColormapOfScreen(screen);                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1045                                            AllocNone);
1046          white = WhitePixelOfScreen(screen);                  if (g_depth <= 8)
1047          attribs.background_pixel = BlackPixelOfScreen(screen);                          warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
1048          attribs.backing_store = DoesBackingStore(screen);          }
1049    
1050          if (attribs.backing_store == NotUseful)          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1051                  backpixmap = True;          {
1052                    warning("External BackingStore not available, using internal\n");
1053                    g_ownbackstore = True;
1054            }
1055    
1056          if (fullscreen)          /*
1057             * Determine desktop size
1058             */
1059            if (g_fullscreen)
1060          {          {
1061                  attribs.override_redirect = True;                  g_width = WidthOfScreen(g_screen);
1062                  width = WidthOfScreen(screen);                  g_height = HeightOfScreen(g_screen);
                 height = HeightOfScreen(screen);  
1063          }          }
1064          else          else if (g_width < 0)
1065          {          {
1066                  attribs.override_redirect = False;                  /* Percent of screen */
1067                    g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1068                    g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1069          }          }
1070            else if (g_width == 0)
1071            {
1072                    /* Fetch geometry from _NET_WORKAREA */
1073                    uint32 x, y, cx, cy;
1074    
1075          width &= ~3; /* make width a multiple of 32 bits */                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1076                    {
1077                            g_width = cx;
1078                            g_height = cy;
1079                    }
1080                    else
1081                    {
1082                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1083                            g_width = 800;
1084                            g_height = 600;
1085                    }
1086            }
1087    
1088          wnd = XCreateWindow(display, RootWindowOfScreen(screen),          /* make sure width is a multiple of 4 */
1089                              0, 0, width, height, 0, CopyFromParent,          g_width = (g_width + 3) & ~3;
                             InputOutput, CopyFromParent,  
                             CWBackingStore | CWBackPixel | CWOverrideRedirect,  
                             &attribs);  
1090    
1091          XStoreName(display, wnd, title);          g_mod_map = XGetModifierMapping(g_display);
1092    
1093            xkeymap_init();
1094    
1095            if (g_enable_compose)
1096                    g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1097    
1098            xclip_init();
1099    
1100            DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));
1101    
1102            return True;
1103    }
1104    
1105    void
1106    ui_deinit(void)
1107    {
1108            if (g_IM != NULL)
1109                    XCloseIM(g_IM);
1110    
1111            if (g_null_cursor != NULL)
1112                    ui_destroy_cursor(g_null_cursor);
1113    
1114            XFreeModifiermap(g_mod_map);
1115    
1116            if (g_ownbackstore)
1117                    XFreePixmap(g_display, g_backstore);
1118    
1119            XFreeGC(g_display, g_gc);
1120            XCloseDisplay(g_display);
1121            g_display = NULL;
1122    }
1123    
1124    BOOL
1125    ui_create_window(void)
1126    {
1127            uint8 null_pointer_mask[1] = { 0x80 };
1128            uint8 null_pointer_data[24] = { 0x00 };
1129    
1130            XSetWindowAttributes attribs;
1131            XClassHint *classhints;
1132            XSizeHints *sizehints;
1133            int wndwidth, wndheight;
1134            long input_mask, ic_input_mask;
1135            XEvent xevent;
1136    
1137            wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1138            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1139    
1140            attribs.background_pixel = BlackPixelOfScreen(g_screen);
1141            attribs.border_pixel = WhitePixelOfScreen(g_screen);
1142            attribs.backing_store = g_ownbackstore ? NotUseful : Always;
1143            attribs.override_redirect = g_fullscreen;
1144            attribs.colormap = g_xcolmap;
1145    
1146            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1147                                  wndheight, 0, g_depth, InputOutput, g_visual,
1148                                  CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1149                                  CWBorderPixel, &attribs);
1150    
1151            if (g_gc == NULL)
1152                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1153    
1154            if (g_create_bitmap_gc == NULL)
1155                    g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1156    
1157            if ((g_ownbackstore) && (g_backstore == 0))
1158            {
1159                    g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1160    
1161                    /* clear to prevent rubbish being exposed at startup */
1162                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1163                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
1164            }
1165    
1166            XStoreName(g_display, g_wnd, g_title);
1167    
1168            if (g_hide_decorations)
1169                    mwm_hide_decorations();
1170    
1171          classhints = XAllocClassHint();          classhints = XAllocClassHint();
1172          if (classhints != NULL)          if (classhints != NULL)
1173          {          {
1174                  classhints->res_name = classhints->res_class = "rdesktop";                  classhints->res_name = classhints->res_class = "rdesktop";
1175                  XSetClassHint(display, wnd, classhints);                  XSetClassHint(g_display, g_wnd, classhints);
1176                  XFree(classhints);                  XFree(classhints);
1177          }          }
1178    
# Line 227  ui_create_window(char *title) Line 1180  ui_create_window(char *title)
1180          if (sizehints)          if (sizehints)
1181          {          {
1182                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1183                  sizehints->min_width = sizehints->max_width = width;                  sizehints->min_width = sizehints->max_width = g_width;
1184                  sizehints->min_height = sizehints->max_height = height;                  sizehints->min_height = sizehints->max_height = g_height;
1185                  XSetWMNormalHints(display, wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
1186                  XFree(sizehints);                  XFree(sizehints);
1187          }          }
1188    
1189          input_mask = KeyPressMask | KeyReleaseMask          if (g_embed_wnd)
1190                          | ButtonPressMask | ButtonReleaseMask          {
1191                          | EnterWindowMask | LeaveWindowMask;                  XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1192            }
1193    
1194            input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1195                    VisibilityChangeMask | FocusChangeMask;
1196    
1197          if (sendmotion)          if (g_sendmotion)
1198                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
1199            if (g_ownbackstore)
1200                    input_mask |= ExposureMask;
1201            if (g_fullscreen || g_grab_keyboard)
1202                    input_mask |= EnterWindowMask;
1203            if (g_grab_keyboard)
1204                    input_mask |= LeaveWindowMask;
1205    
1206          XSelectInput(display, wnd, input_mask);          if (g_IM != NULL)
1207          gc = XCreateGC(display, wnd, 0, NULL);          {
1208                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1209                                     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1210    
1211                    if ((g_IC != NULL)
1212                        && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1213                            input_mask |= ic_input_mask;
1214            }
1215    
1216            XSelectInput(g_display, g_wnd, input_mask);
1217            XMapWindow(g_display, g_wnd);
1218    
1219            /* wait for VisibilityNotify */
1220            do
1221            {
1222                    XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1223            }
1224            while (xevent.type != VisibilityNotify);
1225            g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1226    
1227            g_focused = False;
1228            g_mouse_in_wnd = False;
1229    
1230            /* handle the WM_DELETE_WINDOW protocol */
1231            g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1232            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1233            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1234    
1235            /* create invisible 1x1 cursor to be used as null cursor */
1236            if (g_null_cursor == NULL)
1237                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1238    
         XMapWindow(display, wnd);  
1239          return True;          return True;
1240  }  }
1241    
1242  void  void
1243  ui_destroy_window()  ui_resize_window()
1244  {  {
1245          XFreeGC(display, gc);          XSizeHints *sizehints;
1246          XDestroyWindow(display, wnd);          Pixmap bs;
         XCloseDisplay(display);  
         display = NULL;  
 }  
   
 static uint8  
 xwin_translate_key(unsigned long key)  
 {  
         DEBUG("KEY(code=0x%lx)\n", key);  
   
         if ((key > 8) && (key <= 0x60))  
                 return (key - 8);  
   
         switch (key)  
         {  
                 case 0x61:      /* home */  
                         return 0x47 | 0x80;  
                 case 0x62:      /* up arrow */  
                         return 0x48 | 0x80;  
                 case 0x63:      /* page up */  
                         return 0x49 | 0x80;  
                 case 0x64:      /* left arrow */  
                         return 0x4b | 0x80;  
                 case 0x66:      /* right arrow */  
                         return 0x4d | 0x80;  
                 case 0x67:      /* end */  
                         return 0x4f | 0x80;  
                 case 0x68:      /* down arrow */  
                         return 0x50 | 0x80;  
                 case 0x69:      /* page down */  
                         return 0x51 | 0x80;  
                 case 0x6a:      /* insert */  
                         return 0x52 | 0x80;  
                 case 0x6b:      /* delete */  
                         return 0x53 | 0x80;  
                 case 0x6c:      /* keypad enter */  
                         return 0x1c | 0x80;  
                 case 0x6d:      /* right ctrl */  
                         return 0x1d | 0x80;  
                 case 0x6f:      /* ctrl - print screen */  
                         return 0x37 | 0x80;  
                 case 0x70:      /* keypad '/' */  
                         return 0x35 | 0x80;  
                 case 0x71:      /* right alt */  
                         return 0x38 | 0x80;  
                 case 0x72:      /* ctrl break */  
                         return 0x46 | 0x80;  
                 case 0x73:      /* left window key */  
                         return 0xff;    /* real scancode is 5b */  
                 case 0x74:      /* right window key */  
                         return 0xff;    /* real scancode is 5c */  
                 case 0x75:      /* menu key */  
                         return 0x5d | 0x80;  
         }  
   
         return 0;  
 }  
   
 static uint16  
 xwin_translate_mouse(unsigned long button)  
 {  
         switch (button)  
         {  
                 case Button1:   /* left */  
                         return MOUSE_FLAG_BUTTON1;  
                 case Button2:   /* middle */  
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3:   /* right */  
                         return MOUSE_FLAG_BUTTON2;  
         }  
   
         return 0;  
 }  
   
 void  
 ui_process_events()  
 {  
         XEvent event;  
         uint8 scancode;  
         uint16 button;  
         uint32 ev_time;  
1247    
1248          if (display == NULL)          sizehints = XAllocSizeHints();
1249                  return;          if (sizehints)
1250            {
1251                    sizehints->flags = PMinSize | PMaxSize;
1252                    sizehints->min_width = sizehints->max_width = g_width;
1253                    sizehints->min_height = sizehints->max_height = g_height;
1254                    XSetWMNormalHints(g_display, g_wnd, sizehints);
1255                    XFree(sizehints);
1256            }
1257    
1258            if (!(g_fullscreen || g_embed_wnd))
1259            {
1260                    XResizeWindow(g_display, g_wnd, g_width, g_height);
1261            }
1262    
1263            /* create new backstore pixmap */
1264            if (g_backstore != 0)
1265            {
1266                    bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1267                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1268                    XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1269                    XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1270                    XFreePixmap(g_display, g_backstore);
1271                    g_backstore = bs;
1272            }
1273    }
1274    
1275    void
1276    ui_destroy_window(void)
1277    {
1278            if (g_IC != NULL)
1279                    XDestroyIC(g_IC);
1280    
1281            XDestroyWindow(g_display, g_wnd);
1282    }
1283    
1284    void
1285    xwin_toggle_fullscreen(void)
1286    {
1287            Pixmap contents = 0;
1288    
1289          while (XCheckWindowEvent(display, wnd, ~0, &event))          if (!g_ownbackstore)
1290          {          {
1291                  ev_time = time(NULL);                  /* need to save contents of window */
1292                    contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1293                    XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1294            }
1295    
1296            ui_destroy_window();
1297            g_fullscreen = !g_fullscreen;
1298            ui_create_window();
1299    
1300            XDefineCursor(g_display, g_wnd, g_current_cursor);
1301    
1302            if (!g_ownbackstore)
1303            {
1304                    XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1305                    XFreePixmap(g_display, contents);
1306            }
1307    }
1308    
1309                  switch (event.type)  /* Process all events in Xlib queue
1310       Returns 0 after user quit, 1 otherwise */
1311    static int
1312    xwin_process_events(void)
1313    {
1314            XEvent xevent;
1315            KeySym keysym;
1316            uint16 button, flags;
1317            uint32 ev_time;
1318            key_translation tr;
1319            char str[256];
1320            Status status;
1321    
1322            while (XPending(g_display) > 0)
1323            {
1324                    XNextEvent(g_display, &xevent);
1325    
1326                    if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1327                    {
1328                            DEBUG_KBD(("Filtering event\n"));
1329                            continue;
1330                    }
1331    
1332                    flags = 0;
1333    
1334                    switch (xevent.type)
1335                  {                  {
1336                            case VisibilityNotify:
1337                                    g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1338                                    break;
1339                            case ClientMessage:
1340                                    /* the window manager told us to quit */
1341                                    if ((xevent.xclient.message_type == g_protocol_atom)
1342                                        && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1343                                            /* Quit */
1344                                            return 0;
1345                                    break;
1346    
1347                          case KeyPress:                          case KeyPress:
1348                                  scancode = xwin_translate_key(event.xkey.keycode);                                  g_last_gesturetime = xevent.xkey.time;
1349                                  if (scancode == 0)                                  if (g_IC != NULL)
1350                                            /* Multi_key compatible version */
1351                                    {
1352                                            XmbLookupString(g_IC,
1353                                                            &xevent.xkey, str, sizeof(str), &keysym,
1354                                                            &status);
1355                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1356                                            {
1357                                                    error("XmbLookupString failed with status 0x%x\n",
1358                                                          status);
1359                                                    break;
1360                                            }
1361                                    }
1362                                    else
1363                                    {
1364                                            /* Plain old XLookupString */
1365                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1366                                            XLookupString((XKeyEvent *) & xevent,
1367                                                          str, sizeof(str), &keysym, NULL);
1368                                    }
1369    
1370                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1371                                               get_ksname(keysym)));
1372    
1373                                    ev_time = time(NULL);
1374                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1375                                          break;                                          break;
1376    
1377                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  tr = xkeymap_translate_key(keysym,
1378                                                 scancode, 0);                                                             xevent.xkey.keycode, xevent.xkey.state);
1379    
1380                                    if (tr.scancode == 0)
1381                                            break;
1382    
1383                                    save_remote_modifiers(tr.scancode);
1384                                    ensure_remote_modifiers(ev_time, tr);
1385                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1386                                    restore_remote_modifiers(ev_time, tr.scancode);
1387    
1388                                  break;                                  break;
1389    
1390                          case KeyRelease:                          case KeyRelease:
1391                                  scancode = xwin_translate_key(event.xkey.keycode);                                  g_last_gesturetime = xevent.xkey.time;
1392                                  if (scancode == 0)                                  XLookupString((XKeyEvent *) & xevent, str,
1393                                                  sizeof(str), &keysym, NULL);
1394    
1395                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1396                                               get_ksname(keysym)));
1397    
1398                                    ev_time = time(NULL);
1399                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1400                                          break;                                          break;
1401    
1402                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  tr = xkeymap_translate_key(keysym,
1403                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,                                                             xevent.xkey.keycode, xevent.xkey.state);
                                                scancode, 0);  
                                 break;  
1404    
1405                          case ButtonPress:                                  if (tr.scancode == 0)
                                 button = xwin_translate_mouse(event.xbutton.button);  
                                 if (button == 0)  
1406                                          break;                                          break;
1407    
1408                                  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);  
1409                                  break;                                  break;
1410    
1411                            case ButtonPress:
1412                                    flags = MOUSE_FLAG_DOWN;
1413                                    /* fall through */
1414    
1415                          case ButtonRelease:                          case ButtonRelease:
1416                                  button = xwin_translate_mouse(event.xbutton.button);                                  g_last_gesturetime = xevent.xbutton.time;
1417                                    button = xkeymap_translate_button(xevent.xbutton.button);
1418                                  if (button == 0)                                  if (button == 0)
1419                                          break;                                          break;
1420    
1421                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
1422                                                 button,                                  if (xevent.xbutton.y < g_win_button_size)
1423                                                 event.xbutton.x,                                  {
1424                                                 event.xbutton.y);                                          /* Stop moving window when button is released, regardless of cursor position */
1425                                            if (g_moving_wnd && (xevent.type == ButtonRelease))
1426                                                    g_moving_wnd = False;
1427    
1428                                            /*  Check from right to left: */
1429    
1430                                            if (xevent.xbutton.x >= g_width - g_win_button_size)
1431                                            {
1432                                                    /* The close button, continue */
1433                                                    ;
1434                                            }
1435                                            else if (xevent.xbutton.x >=
1436                                                     g_width - g_win_button_size * 2)
1437                                            {
1438                                                    /* The maximize/restore button. Do not send to
1439                                                       server.  It might be a good idea to change the
1440                                                       cursor or give some other visible indication
1441                                                       that rdesktop inhibited this click */
1442                                                    break;
1443                                            }
1444                                            else if (xevent.xbutton.x >=
1445                                                     g_width - g_win_button_size * 3)
1446                                            {
1447                                                    /* The minimize button. Iconify window. */
1448                                                    XIconifyWindow(g_display, g_wnd,
1449                                                                   DefaultScreen(g_display));
1450                                                    break;
1451                                            }
1452                                            else if (xevent.xbutton.x <= g_win_button_size)
1453                                            {
1454                                                    /* The system menu. Ignore. */
1455                                                    break;
1456                                            }
1457                                            else
1458                                            {
1459                                                    /* The title bar. */
1460                                                    if ((xevent.type == ButtonPress) && !g_fullscreen
1461                                                        && g_hide_decorations)
1462                                                    {
1463                                                            g_moving_wnd = True;
1464                                                            g_move_x_offset = xevent.xbutton.x;
1465                                                            g_move_y_offset = xevent.xbutton.y;
1466                                                    }
1467                                                    break;
1468    
1469                                            }
1470                                    }
1471    
1472                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1473                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1474                                  break;                                  break;
1475    
1476                          case MotionNotify:                          case MotionNotify:
1477                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  if (g_moving_wnd)
1478                                                 MOUSE_FLAG_MOVE,                                  {
1479                                                 event.xmotion.x,                                          XMoveWindow(g_display, g_wnd,
1480                                                 event.xmotion.y);                                                      xevent.xmotion.x_root - g_move_x_offset,
1481                                                        xevent.xmotion.y_root - g_move_y_offset);
1482                                            break;
1483                                    }
1484    
1485                                    if (g_fullscreen && !g_focused)
1486                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1487                                                           CurrentTime);
1488                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1489                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1490                                    break;
1491    
1492                            case FocusIn:
1493                                    if (xevent.xfocus.mode == NotifyGrab)
1494                                            break;
1495                                    g_focused = True;
1496                                    reset_modifier_keys();
1497                                    if (g_grab_keyboard && g_mouse_in_wnd)
1498                                            XGrabKeyboard(g_display, g_wnd, True,
1499                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1500                                    break;
1501    
1502                            case FocusOut:
1503                                    if (xevent.xfocus.mode == NotifyUngrab)
1504                                            break;
1505                                    g_focused = False;
1506                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1507                                            XUngrabKeyboard(g_display, CurrentTime);
1508                                  break;                                  break;
1509    
1510                          case EnterNotify:                          case EnterNotify:
1511                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,                                  /* we only register for this event when in fullscreen mode */
1512                                                GrabModeAsync, CurrentTime);                                  /* or grab_keyboard */
1513                                    g_mouse_in_wnd = True;
1514                                    if (g_fullscreen)
1515                                    {
1516                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1517                                                           CurrentTime);
1518                                            break;
1519                                    }
1520                                    if (g_focused)
1521                                            XGrabKeyboard(g_display, g_wnd, True,
1522                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1523                                  break;                                  break;
1524    
1525                          case LeaveNotify:                          case LeaveNotify:
1526                                  XUngrabKeyboard(display, CurrentTime);                                  /* we only register for this event when grab_keyboard */
1527                                    g_mouse_in_wnd = False;
1528                                    XUngrabKeyboard(g_display, CurrentTime);
1529                                    break;
1530    
1531                            case Expose:
1532                                    XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1533                                              xevent.xexpose.x, xevent.xexpose.y,
1534                                              xevent.xexpose.width,
1535                                              xevent.xexpose.height,
1536                                              xevent.xexpose.x, xevent.xexpose.y);
1537                                    break;
1538    
1539                            case MappingNotify:
1540                                    /* Refresh keyboard mapping if it has changed. This is important for
1541                                       Xvnc, since it allocates keycodes dynamically */
1542                                    if (xevent.xmapping.request == MappingKeyboard
1543                                        || xevent.xmapping.request == MappingModifier)
1544                                            XRefreshKeyboardMapping(&xevent.xmapping);
1545    
1546                                    if (xevent.xmapping.request == MappingModifier)
1547                                    {
1548                                            XFreeModifiermap(g_mod_map);
1549                                            g_mod_map = XGetModifierMapping(g_display);
1550                                    }
1551                                    break;
1552    
1553                                    /* clipboard stuff */
1554                            case SelectionNotify:
1555                                    xclip_handle_SelectionNotify(&xevent.xselection);
1556                                    break;
1557                            case SelectionRequest:
1558                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1559                                    break;
1560                            case SelectionClear:
1561                                    xclip_handle_SelectionClear();
1562                                    break;
1563                            case PropertyNotify:
1564                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1565                                  break;                                  break;
1566                  }                  }
1567          }          }
1568            /* Keep going */
1569            return 1;
1570    }
1571    
1572    /* Returns 0 after user quit, 1 otherwise */
1573    int
1574    ui_select(int rdp_socket)
1575    {
1576            int n;
1577            fd_set rfds, wfds;
1578            struct timeval tv;
1579            BOOL s_timeout = False;
1580    
1581            while (True)
1582            {
1583                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1584                    /* Process any events already waiting */
1585                    if (!xwin_process_events())
1586                            /* User quit */
1587                            return 0;
1588    
1589                    FD_ZERO(&rfds);
1590                    FD_ZERO(&wfds);
1591                    FD_SET(rdp_socket, &rfds);
1592                    FD_SET(g_x_socket, &rfds);
1593    
1594    #ifdef WITH_RDPSND
1595                    /* FIXME: there should be an API for registering fds */
1596                    if (g_dsp_busy)
1597                    {
1598                            FD_SET(g_dsp_fd, &wfds);
1599                            n = (g_dsp_fd > n) ? g_dsp_fd : n;
1600                    }
1601    #endif
1602                    /* default timeout */
1603                    tv.tv_sec = 60;
1604                    tv.tv_usec = 0;
1605    
1606                    /* add redirection handles */
1607                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1608    
1609                    n++;
1610    
1611                    switch (select(n, &rfds, &wfds, NULL, &tv))
1612                    {
1613                            case -1:
1614                                    error("select: %s\n", strerror(errno));
1615    
1616                            case 0:
1617                                    /* Abort serial read calls */
1618                                    if (s_timeout)
1619                                            rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1620                                    continue;
1621                    }
1622    
1623                    rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
1624    
1625                    if (FD_ISSET(rdp_socket, &rfds))
1626                            return 1;
1627    
1628    #ifdef WITH_RDPSND
1629                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1630                            wave_out_play();
1631    #endif
1632            }
1633  }  }
1634    
1635  void  void
1636  ui_move_pointer(int x, int y)  ui_move_pointer(int x, int y)
1637  {  {
1638          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1639  }  }
1640    
1641  HBITMAP  HBITMAP
1642  ui_create_bitmap(int width, int height, uint8 *data)  ui_create_bitmap(int width, int height, uint8 * data)
1643  {  {
1644          XImage *image;          XImage *image;
1645          Pixmap bitmap;          Pixmap bitmap;
1646          uint8 *tdata;          uint8 *tdata;
1647            int bitmap_pad;
1648    
1649          tdata = (owncolmap ? data : translate(width, height, data));          if (g_server_bpp == 8)
1650          bitmap = XCreatePixmap(display, wnd, width, height, depth);          {
1651          image = XCreateImage(display, visual, depth, ZPixmap,                  bitmap_pad = 8;
1652                               0, tdata, width, height, 8, 0);          }
1653            else
1654            {
1655                    bitmap_pad = g_bpp;
1656    
1657          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);                  if (g_bpp == 24)
1658                            bitmap_pad = 32;
1659            }
1660    
1661            tdata = (g_owncolmap ? data : translate_image(width, height, data));
1662            bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1663            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1664                                 (char *) tdata, width, height, bitmap_pad, 0);
1665    
1666            XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
1667    
1668          XFree(image);          XFree(image);
1669          if (!owncolmap)          if (tdata != data)
1670                  xfree(tdata);                  xfree(tdata);
1671          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1672  }  }
1673    
1674  void  void
1675  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)  
1676  {  {
1677          XImage *image;          XImage *image;
1678          uint8 *tdata;          uint8 *tdata;
1679            int bitmap_pad;
1680    
1681          tdata = (owncolmap ? data : translate(width, height, data));          if (g_server_bpp == 8)
1682          image = XCreateImage(display, visual, depth, ZPixmap,          {
1683                               0, tdata, width, height, 8, 0);                  bitmap_pad = 8;
1684            }
1685            else
1686            {
1687                    bitmap_pad = g_bpp;
1688    
1689                    if (g_bpp == 24)
1690                            bitmap_pad = 32;
1691            }
1692    
1693          XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1694            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1695                                 (char *) tdata, width, height, bitmap_pad, 0);
1696    
1697            if (g_ownbackstore)
1698            {
1699                    XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1700                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1701            }
1702            else
1703            {
1704                    XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1705            }
1706    
1707          XFree(image);          XFree(image);
1708          if (!owncolmap)          if (tdata != data)
1709                  xfree(tdata);                  xfree(tdata);
1710  }  }
1711    
1712  void  void
1713  ui_destroy_bitmap(HBITMAP bmp)  ui_destroy_bitmap(HBITMAP bmp)
1714  {  {
1715          XFreePixmap(display, (Pixmap)bmp);          XFreePixmap(g_display, (Pixmap) bmp);
1716  }  }
1717    
1718  HGLYPH  HGLYPH
1719  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
1720  {  {
1721          XImage *image;          XImage *image;
1722          Pixmap bitmap;          Pixmap bitmap;
1723          int scanline;          int scanline;
         GC gc;  
1724    
1725          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1726    
1727          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1728          gc = XCreateGC(display, bitmap, 0, NULL);          if (g_create_glyph_gc == 0)
1729                    g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1730    
1731          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1732                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1733          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1734          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1735          XInitImage(image);          XInitImage(image);
1736    
1737          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);
1738    
1739          XFree(image);          XFree(image);
1740          XFreeGC(display, gc);          return (HGLYPH) bitmap;
         return (HGLYPH)bitmap;  
1741  }  }
1742    
1743  void  void
1744  ui_destroy_glyph(HGLYPH glyph)  ui_destroy_glyph(HGLYPH glyph)
1745  {  {
1746          XFreePixmap(display, (Pixmap)glyph);          XFreePixmap(g_display, (Pixmap) glyph);
1747  }  }
1748    
1749  HCURSOR  HCURSOR
1750  ui_create_cursor(unsigned int x, unsigned int y, int width,  ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1751                   int height, uint8 *andmask, uint8 *xormask)                   uint8 * andmask, uint8 * xormask)
1752  {  {
1753          HGLYPH maskglyph, cursorglyph;          HGLYPH maskglyph, cursorglyph;
1754          XColor bg, fg;          XColor bg, fg;
# Line 500  ui_create_cursor(unsigned int x, unsigne Line 1762  ui_create_cursor(unsigned int x, unsigne
1762          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1763          offset = scanline * height;          offset = scanline * height;
1764    
1765          cursor = xmalloc(offset);          cursor = (uint8 *) xmalloc(offset);
1766          memset(cursor, 0, offset);          memset(cursor, 0, offset);
1767    
1768          mask = xmalloc(offset);          mask = (uint8 *) xmalloc(offset);
1769          memset(mask, 0, offset);          memset(mask, 0, offset);
1770    
1771          /* approximate AND and XOR masks with a monochrome X pointer */          /* approximate AND and XOR masks with a monochrome X pointer */
# Line 543  ui_create_cursor(unsigned int x, unsigne Line 1805  ui_create_cursor(unsigned int x, unsigne
1805    
1806          cursorglyph = ui_create_glyph(width, height, cursor);          cursorglyph = ui_create_glyph(width, height, cursor);
1807          maskglyph = ui_create_glyph(width, height, mask);          maskglyph = ui_create_glyph(width, height, mask);
1808            
1809          xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,          xcursor =
1810                                  (Pixmap)maskglyph, &fg, &bg, x, y);                  XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1811                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1812    
1813          ui_destroy_glyph(maskglyph);          ui_destroy_glyph(maskglyph);
1814          ui_destroy_glyph(cursorglyph);          ui_destroy_glyph(cursorglyph);
1815          xfree(mask);          xfree(mask);
1816          xfree(cursor);          xfree(cursor);
1817          return (HCURSOR)xcursor;          return (HCURSOR) xcursor;
1818  }  }
1819    
1820  void  void
1821  ui_set_cursor(HCURSOR cursor)  ui_set_cursor(HCURSOR cursor)
1822  {  {
1823          XDefineCursor(display, wnd, (Cursor)cursor);          g_current_cursor = (Cursor) cursor;
1824            XDefineCursor(g_display, g_wnd, g_current_cursor);
1825  }  }
1826    
1827  void  void
1828  ui_destroy_cursor(HCURSOR cursor)  ui_destroy_cursor(HCURSOR cursor)
1829  {  {
1830          XFreeCursor(display, (Cursor)cursor);          XFreeCursor(g_display, (Cursor) cursor);
1831    }
1832    
1833    void
1834    ui_set_null_cursor(void)
1835    {
1836            ui_set_cursor(g_null_cursor);
1837  }  }
1838    
1839  #define MAKE_XCOLOR(xc,c) \  #define MAKE_XCOLOR(xc,c) \
# Line 572  ui_destroy_cursor(HCURSOR cursor) Line 1842  ui_destroy_cursor(HCURSOR cursor)
1842                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \                  (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1843                  (xc)->flags = DoRed | DoGreen | DoBlue;                  (xc)->flags = DoRed | DoGreen | DoBlue;
1844    
1845    
1846  HCOLOURMAP  HCOLOURMAP
1847  ui_create_colourmap(COLOURMAP *colours)  ui_create_colourmap(COLOURMAP * colours)
1848  {  {
1849          COLOURENTRY *entry;          COLOURENTRY *entry;
1850          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1851            if (!g_owncolmap)
         if (owncolmap)  
1852          {          {
1853                  XColor *xcolours, *xentry;                  uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1854                  Colormap map;                  XColor xentry;
1855                    XColor xc_cache[256];
1856                  xcolours = xmalloc(sizeof(XColor) * ncolours);                  uint32 colour;
1857                    int colLookup = 256;
1858                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1859                  {                  {
1860                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1861                          xentry = &xcolours[i];                          MAKE_XCOLOR(&xentry, entry);
                         xentry->pixel = i;  
                         MAKE_XCOLOR(xentry, entry);  
                 }  
1862    
1863                  map = XCreateColormap(display, wnd, visual, AllocAll);                          if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1864                  XStoreColors(display, map, xcolours, ncolours);                          {
1865                                    /* Allocation failed, find closest match. */
1866                                    int j = 256;
1867                                    int nMinDist = 3 * 256 * 256;
1868                                    long nDist = nMinDist;
1869    
1870                  xfree(xcolours);                                  /* only get the colors once */
1871                  return (HCOLOURMAP)map;                                  while (colLookup--)
1872                                    {
1873                                            xc_cache[colLookup].pixel = colLookup;
1874                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1875                                                    xc_cache[colLookup].blue = 0;
1876                                            xc_cache[colLookup].flags = 0;
1877                                            XQueryColor(g_display,
1878                                                        DefaultColormap(g_display,
1879                                                                        DefaultScreen(g_display)),
1880                                                        &xc_cache[colLookup]);
1881                                    }
1882                                    colLookup = 0;
1883    
1884                                    /* approximate the pixel */
1885                                    while (j--)
1886                                    {
1887                                            if (xc_cache[j].flags)
1888                                            {
1889                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1890                                                             (long) (xentry.red >> 8)) *
1891                                                            ((long) (xc_cache[j].red >> 8) -
1892                                                             (long) (xentry.red >> 8)) +
1893                                                            ((long) (xc_cache[j].green >> 8) -
1894                                                             (long) (xentry.green >> 8)) *
1895                                                            ((long) (xc_cache[j].green >> 8) -
1896                                                             (long) (xentry.green >> 8)) +
1897                                                            ((long) (xc_cache[j].blue >> 8) -
1898                                                             (long) (xentry.blue >> 8)) *
1899                                                            ((long) (xc_cache[j].blue >> 8) -
1900                                                             (long) (xentry.blue >> 8));
1901                                            }
1902                                            if (nDist < nMinDist)
1903                                            {
1904                                                    nMinDist = nDist;
1905                                                    xentry.pixel = j;
1906                                            }
1907                                    }
1908                            }
1909                            colour = xentry.pixel;
1910    
1911                            /* update our cache */
1912                            if (xentry.pixel < 256)
1913                            {
1914                                    xc_cache[xentry.pixel].red = xentry.red;
1915                                    xc_cache[xentry.pixel].green = xentry.green;
1916                                    xc_cache[xentry.pixel].blue = xentry.blue;
1917    
1918                            }
1919    
1920                            map[i] = colour;
1921                    }
1922                    return map;
1923          }          }
1924          else          else
1925          {          {
1926                  uint32 *map = xmalloc(sizeof(*colmap) * ncolours);                  XColor *xcolours, *xentry;
1927                  XColor xentry;                  Colormap map;
1928    
1929                    xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1930                  for (i = 0; i < ncolours; i++)                  for (i = 0; i < ncolours; i++)
1931                  {                  {
1932                          entry = &colours->colours[i];                          entry = &colours->colours[i];
1933                          MAKE_XCOLOR(&xentry, entry);                          xentry = &xcolours[i];
1934                            xentry->pixel = i;
1935                          if (XAllocColor(display, xcolmap, &xentry) != 0)                          MAKE_XCOLOR(xentry, entry);
                                 map[i] = xentry.pixel;  
                         else  
                                 map[i] = white;  
1936                  }                  }
1937    
1938                  return map;                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1939                    XStoreColors(g_display, map, xcolours, ncolours);
1940    
1941                    xfree(xcolours);
1942                    return (HCOLOURMAP) map;
1943          }          }
1944  }  }
1945    
1946  void  void
1947  ui_destroy_colourmap(HCOLOURMAP map)  ui_destroy_colourmap(HCOLOURMAP map)
1948  {  {
1949          if (owncolmap)          if (!g_owncolmap)
                 XFreeColormap(display, (Colormap)map);  
         else  
1950                  xfree(map);                  xfree(map);
1951            else
1952                    XFreeColormap(g_display, (Colormap) map);
1953  }  }
1954    
1955  void  void
1956  ui_set_colourmap(HCOLOURMAP map)  ui_set_colourmap(HCOLOURMAP map)
1957  {  {
1958          if (owncolmap)          if (!g_owncolmap)
1959                  XSetWindowColormap(display, wnd, (Colormap)map);          {
1960                    if (g_colmap)
1961                            xfree(g_colmap);
1962    
1963                    g_colmap = (uint32 *) map;
1964            }
1965          else          else
1966                  colmap = map;                  XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1967  }  }
1968    
1969  void  void
# Line 645  ui_set_clip(int x, int y, int cx, int cy Line 1975  ui_set_clip(int x, int y, int cx, int cy
1975          rect.y = y;          rect.y = y;
1976          rect.width = cx;          rect.width = cx;
1977          rect.height = cy;          rect.height = cy;
1978          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1979  }  }
1980    
1981  void  void
1982  ui_reset_clip()  ui_reset_clip(void)
1983  {  {
1984          XRectangle rect;          XRectangle rect;
1985    
1986          rect.x = 0;          rect.x = 0;
1987          rect.y = 0;          rect.y = 0;
1988          rect.width = width;          rect.width = g_width;
1989          rect.height = height;          rect.height = g_height;
1990          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1991  }  }
1992    
1993  void  void
1994  ui_bell()  ui_bell(void)
1995  {  {
1996          XBell(display, 0);          XBell(g_display, 0);
1997  }  }
1998    
1999  void  void
# Line 671  ui_destblt(uint8 opcode, Line 2001  ui_destblt(uint8 opcode,
2001             /* dest */ int x, int y, int cx, int cy)             /* dest */ int x, int y, int cx, int cy)
2002  {  {
2003          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2004          XFillRectangle(display, wnd, gc, x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2005          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2006  }  }
2007    
2008    static uint8 hatch_patterns[] = {
2009            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
2010            0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
2011            0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
2012            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
2013            0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
2014            0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
2015    };
2016    
2017  void  void
2018  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
2019            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2020            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2021  {  {
2022          Pixmap fill;          Pixmap fill;
2023            uint8 i, ipattern[8];
2024    
2025          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2026    
# Line 688  ui_patblt(uint8 opcode, Line 2028  ui_patblt(uint8 opcode,
2028          {          {
2029                  case 0: /* Solid */                  case 0: /* Solid */
2030                          SET_FOREGROUND(fgcolour);                          SET_FOREGROUND(fgcolour);
2031                          XFillRectangle(display, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2032                          break;                          break;
2033    
2034                  case 3: /* Pattern */                  case 2: /* Hatch */
2035                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);                          fill = (Pixmap) ui_create_glyph(8, 8,
2036                                                            hatch_patterns + brush->pattern[0] * 8);
2037                            SET_FOREGROUND(fgcolour);
2038                            SET_BACKGROUND(bgcolour);
2039                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2040                            XSetStipple(g_display, g_gc, fill);
2041                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2042                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2043                            XSetFillStyle(g_display, g_gc, FillSolid);
2044                            XSetTSOrigin(g_display, g_gc, 0, 0);
2045                            ui_destroy_glyph((HGLYPH) fill);
2046                            break;
2047    
2048                    case 3: /* Pattern */
2049                            for (i = 0; i != 8; i++)
2050                                    ipattern[7 - i] = brush->pattern[i];
2051                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2052                          SET_FOREGROUND(bgcolour);                          SET_FOREGROUND(bgcolour);
2053                          SET_BACKGROUND(fgcolour);                          SET_BACKGROUND(fgcolour);
2054                          XSetFillStyle(display, gc, FillOpaqueStippled);                          XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2055                          XSetStipple(display, gc, fill);                          XSetStipple(g_display, g_gc, fill);
2056                          XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);                          XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2057                            FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2058                          XFillRectangle(display, wnd, gc, x, y, cx, cy);                          XSetFillStyle(g_display, g_gc, FillSolid);
2059                            XSetTSOrigin(g_display, g_gc, 0, 0);
2060                          XSetFillStyle(display, gc, FillSolid);                          ui_destroy_glyph((HGLYPH) fill);
                         ui_destroy_glyph((HGLYPH)fill);  
2061                          break;                          break;
2062    
2063                  default:                  default:
2064                          NOTIMP("brush %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
2065          }          }
2066    
2067          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2068    
2069            if (g_ownbackstore)
2070                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2071  }  }
2072    
2073  void  void
# Line 719  ui_screenblt(uint8 opcode, Line 2076  ui_screenblt(uint8 opcode,
2076               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
2077  {  {
2078          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2079          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          if (g_ownbackstore)
2080            {
2081                    if (g_Unobscured)
2082                    {
2083                            XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2084                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2085                                      y);
2086                    }
2087                    else
2088                    {
2089                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2090                            XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2091                                      y);
2092                    }
2093            }
2094            else
2095            {
2096                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2097            }
2098          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2099  }  }
2100    
# Line 729  ui_memblt(uint8 opcode, Line 2104  ui_memblt(uint8 opcode,
2104            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
2105  {  {
2106          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2107          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);
2108            if (g_ownbackstore)
2109                    XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2110          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2111  }  }
2112    
# Line 737  void Line 2114  void
2114  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
2115            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
2116            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
2117            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2118  {  {
2119          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
2120             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 746  ui_triblt(uint8 opcode, Line 2123  ui_triblt(uint8 opcode,
2123          {          {
2124                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
2125                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
2126                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2127                          break;                          break;
2128    
2129                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
2130                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2131                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
2132                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
2133                          break;                          break;
2134    
2135                  case 0xc0:      /* PSa */                  case 0xc0:      /* PSa */
2136                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2137                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   fgcolour);  
2138                          break;                          break;
2139    
2140                  default:                  default:
2141                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
2142                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2143          }          }
2144  }  }
# Line 773  ui_triblt(uint8 opcode, Line 2146  ui_triblt(uint8 opcode,
2146  void  void
2147  ui_line(uint8 opcode,  ui_line(uint8 opcode,
2148          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
2149          /* pen */ PEN *pen)          /* pen */ PEN * pen)
2150  {  {
2151          SET_FUNCTION(opcode);          SET_FUNCTION(opcode);
2152          SET_FOREGROUND(pen->colour);          SET_FOREGROUND(pen->colour);
2153          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2154            if (g_ownbackstore)
2155                    XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2156          RESET_FUNCTION(opcode);          RESET_FUNCTION(opcode);
2157  }  }
2158    
# Line 787  ui_rect( Line 2162  ui_rect(
2162                 /* brush */ int colour)                 /* brush */ int colour)
2163  {  {
2164          SET_FOREGROUND(colour);          SET_FOREGROUND(colour);
2165          XFillRectangle(display, wnd, gc, x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2166  }  }
2167    
2168    /* warning, this function only draws on wnd or backstore, not both */
2169  void  void
2170  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
2171                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
2172                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
2173                int fgcolour)                int bgcolour, int fgcolour)
2174  {  {
2175          SET_FOREGROUND(fgcolour);          SET_FOREGROUND(fgcolour);
2176          SET_BACKGROUND(bgcolour);          SET_BACKGROUND(bgcolour);
2177    
2178          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)          XSetFillStyle(g_display, g_gc,
2179                        ? FillStippled : FillOpaqueStippled);                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2180          XSetStipple(display, gc, (Pixmap)glyph);          XSetStipple(g_display, g_gc, (Pixmap) glyph);
2181          XSetTSOrigin(display, gc, x, y);          XSetTSOrigin(g_display, g_gc, x, y);
2182    
2183          XFillRectangle(display, wnd, gc, x, y, cx, cy);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2184    
2185          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(g_display, g_gc, FillSolid);
2186    }
2187    
2188    #define DO_GLYPH(ttext,idx) \
2189    {\
2190      glyph = cache_get_font (font, ttext[idx]);\
2191      if (!(flags & TEXT2_IMPLICIT_X))\
2192      {\
2193        xyoffset = ttext[++idx];\
2194        if ((xyoffset & 0x80))\
2195        {\
2196          if (flags & TEXT2_VERTICAL)\
2197            y += ttext[idx+1] | (ttext[idx+2] << 8);\
2198          else\
2199            x += ttext[idx+1] | (ttext[idx+2] << 8);\
2200          idx += 2;\
2201        }\
2202        else\
2203        {\
2204          if (flags & TEXT2_VERTICAL)\
2205            y += xyoffset;\
2206          else\
2207            x += xyoffset;\
2208        }\
2209      }\
2210      if (glyph != NULL)\
2211      {\
2212        x1 = x + glyph->offset;\
2213        y1 = y + glyph->baseline;\
2214        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2215        XSetTSOrigin(g_display, g_gc, x1, y1);\
2216        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2217        if (flags & TEXT2_IMPLICIT_X)\
2218          x += glyph->width;\
2219      }\
2220  }  }
2221    
2222  void  void
2223  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,
2224               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2225               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
2226               int bgcolour, int fgcolour, uint8 *text, uint8 length)               int fgcolour, uint8 * text, uint8 length)
2227  {  {
2228          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2229          int i, offset;          int i, j, xyoffset, x1, y1;
2230            DATABLOB *entry;
2231    
2232          SET_FOREGROUND(bgcolour);          SET_FOREGROUND(bgcolour);
2233    
2234            /* Sometimes, the boxcx value is something really large, like
2235               32691. This makes XCopyArea fail with Xvnc. The code below
2236               is a quick fix. */
2237            if (boxx + boxcx > g_width)
2238                    boxcx = g_width - boxx;
2239    
2240          if (boxcx > 1)          if (boxcx > 1)
2241                  XFillRectangle(display, wnd, gc, boxx, boxy, boxcx, boxcy);          {
2242                    FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2243            }
2244          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
2245                  XFillRectangle(display, wnd, gc, clipx, clipy, clipcx, clipcy);          {
2246                    FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2247            }
2248    
2249            SET_FOREGROUND(fgcolour);
2250            SET_BACKGROUND(bgcolour);
2251            XSetFillStyle(g_display, g_gc, FillStippled);
2252    
2253          /* Paint text, character by character */          /* Paint text, character by character */
2254          for (i = 0; i < length; i++)          for (i = 0; i < length;)
2255          {          {
2256                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
2257                  {                  {
2258                          offset = text[++i];                          case 0xff:
2259                          if (offset & 0x80)                                  if (i + 2 < length)
2260                                  offset = ((offset & 0x7f) << 8) | text[++i];                                          cache_put_text(text[i + 1], text, text[i + 2]);
2261                                    else
2262                                    {
2263                                            error("this shouldn't be happening\n");
2264                                            exit(1);
2265                                    }
2266                                    /* this will move pointer from start to first character after FF command */
2267                                    length -= i + 3;
2268                                    text = &(text[i + 3]);
2269                                    i = 0;
2270                                    break;
2271    
2272                          if (flags & TEXT2_VERTICAL)                          case 0xfe:
2273                                  y += offset;                                  entry = cache_get_text(text[i + 1]);
2274                          else                                  if (entry != NULL)
2275                                  x += offset;                                  {
2276                                            if ((((uint8 *) (entry->data))[1] ==
2277                                                 0) && (!(flags & TEXT2_IMPLICIT_X)))
2278                                            {
2279                                                    if (flags & TEXT2_VERTICAL)
2280                                                            y += text[i + 2];
2281                                                    else
2282                                                            x += text[i + 2];
2283                                            }
2284                                            for (j = 0; j < entry->size; j++)
2285                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
2286                                    }
2287                                    if (i + 2 < length)
2288                                            i += 3;
2289                                    else
2290                                            i += 2;
2291                                    length -= i;
2292                                    /* this will move pointer from start to first character after FE command */
2293                                    text = &(text[i]);
2294                                    i = 0;
2295                                    break;
2296    
2297                            default:
2298                                    DO_GLYPH(text, i);
2299                                    i++;
2300                                    break;
2301                  }                  }
2302            }
2303    
2304                  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);  
2305    
2306                          if (flags & TEXT2_IMPLICIT_X)          if (g_ownbackstore)
2307                                  x += glyph->width;          {
2308                  }                  if (boxcx > 1)
2309                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2310                                      boxy, boxcx, boxcy, boxx, boxy);
2311                    else
2312                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2313                                      clipy, clipcx, clipcy, clipx, clipy);
2314          }          }
2315  }  }
2316    
# Line 862  ui_desktop_save(uint32 offset, int x, in Line 2320  ui_desktop_save(uint32 offset, int x, in
2320          Pixmap pix;          Pixmap pix;
2321          XImage *image;          XImage *image;
2322    
2323          pix = XCreatePixmap(display, wnd, cx, cy, depth);          if (g_ownbackstore)
2324          XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);          {
2325                    image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
2326          image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);          }
2327            else
2328            {
2329                    pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2330                    XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
2331                    image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2332                    XFreePixmap(g_display, pix);
2333            }
2334    
2335          offset *= bpp/8;          offset *= g_bpp / 8;
2336          cache_put_desktop(offset, cx, cy, image->bytes_per_line,          cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
                           bpp/8, image->data);  
2337    
2338          XDestroyImage(image);          XDestroyImage(image);
         XFreePixmap(display, pix);  
2339  }  }
2340    
2341  void  void
# Line 881  ui_desktop_restore(uint32 offset, int x, Line 2344  ui_desktop_restore(uint32 offset, int x,
2344          XImage *image;          XImage *image;
2345          uint8 *data;          uint8 *data;
2346    
2347          offset *= bpp/8;          offset *= g_bpp / 8;
2348          data = cache_get_desktop(offset, cx, cy, bpp/8);          data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2349          if (data == NULL)          if (data == NULL)
2350                  return;                  return;
2351    
2352          image = XCreateImage(display, visual, depth, ZPixmap,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2353                               0, data, cx, cy, BitmapPad(display),                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
2354                               cx * bpp/8);  
2355            if (g_ownbackstore)
2356            {
2357                    XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2358                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2359            }
2360            else
2361            {
2362                    XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2363            }
2364    
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
2365          XFree(image);          XFree(image);
2366  }  }
2367    
2368    /* these do nothing here but are used in uiports */
2369    void
2370    ui_begin_update(void)
2371    {
2372    }
2373    
2374    void
2375    ui_end_update(void)
2376    {
2377    }

Legend:
Removed from v.29  
changed lines
  Added in v.822

  ViewVC Help
Powered by ViewVC 1.1.26