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

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

  ViewVC Help
Powered by ViewVC 1.1.26