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

Legend:
Removed from v.7  
changed lines
  Added in v.342

  ViewVC Help
Powered by ViewVC 1.1.26