/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

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

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

Legend:
Removed from v.16  
changed lines
  Added in v.795

  ViewVC Help
Powered by ViewVC 1.1.26