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

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

  ViewVC Help
Powered by ViewVC 1.1.26