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

Legend:
Removed from v.10  
changed lines
  Added in v.508

  ViewVC Help
Powered by ViewVC 1.1.26