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

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

  ViewVC Help
Powered by ViewVC 1.1.26