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

Legend:
Removed from v.9  
changed lines
  Added in v.695

  ViewVC Help
Powered by ViewVC 1.1.26