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

Legend:
Removed from v.23  
changed lines
  Added in v.677

  ViewVC Help
Powered by ViewVC 1.1.26