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

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

  ViewVC Help
Powered by ViewVC 1.1.26