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

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

  ViewVC Help
Powered by ViewVC 1.1.26