/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

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

  ViewVC Help
Powered by ViewVC 1.1.26