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

Diff of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26