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

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

  ViewVC Help
Powered by ViewVC 1.1.26