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

Legend:
Removed from v.17  
changed lines
  Added in v.643

  ViewVC Help
Powered by ViewVC 1.1.26