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

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

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

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

Legend:
Removed from v.10  
changed lines
  Added in v.697

  ViewVC Help
Powered by ViewVC 1.1.26