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

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

  ViewVC Help
Powered by ViewVC 1.1.26