/[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 9 by matty, Tue Jul 25 12:34:29 2000 UTC revision 101 by astrand, Mon Aug 26 17:12:43 2002 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-2001
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include "includes.h"  #include <X11/Xlib.h>
22    #include <X11/Xutil.h>
23    #include <time.h>
24    #include <errno.h>
25    #define XK_MISCELLANY
26    #include <X11/keysymdef.h>
27    #include "rdesktop.h"
28    #include "scancodes.h"
29    
30    extern int width;
31    extern int height;
32    extern BOOL sendmotion;
33    extern BOOL fullscreen;
34    extern BOOL grab_keyboard;
35    extern char title[];
36    
37    Display *display = NULL;
38    static int x_socket;
39    static Window wnd;
40    static GC gc;
41    static Visual *visual;
42    static int depth;
43    static int bpp;
44    static int dpy_width;
45    static int dpy_height;
46    
47    /* endianness */
48    static BOOL host_be;
49    static BOOL xserver_be;
50    
51    /* software backing store */
52    static BOOL ownbackstore;
53    static Pixmap backstore;
54    
55    #define FILL_RECTANGLE(x,y,cx,cy)\
56    { \
57            XFillRectangle(display, wnd, gc, x, y, cx, cy); \
58            if (ownbackstore) \
59                    XFillRectangle(display, backstore, gc, x, y, cx, cy); \
60    }
61    
62    /* colour maps */
63    static BOOL owncolmap;
64    static Colormap xcolmap;
65    static uint32 white;
66    static uint32 *colmap;
67    static XIM IM = NULL;
68    static XIC IC = NULL;
69    
70    /* Compose support */
71    BOOL enable_compose = False;
72    
73    /* toggle fullscreen globals */
74    static XSetWindowAttributes attribs;
75    static unsigned long input_mask;
76    
77    #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )
78    #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
79    #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
80    
81  HWINDOW ui_create_window(HCONN conn, int width, int height)  static int rop2_map[] = {
82            GXclear,                /* 0 */
83            GXnor,                  /* DPon */
84            GXandInverted,          /* DPna */
85            GXcopyInverted,         /* Pn */
86            GXandReverse,           /* PDna */
87            GXinvert,               /* Dn */
88            GXxor,                  /* DPx */
89            GXnand,                 /* DPan */
90            GXand,                  /* DPa */
91            GXequiv,                /* DPxn */
92            GXnoop,                 /* D */
93            GXorInverted,           /* DPno */
94            GXcopy,                 /* P */
95            GXorReverse,            /* PDno */
96            GXor,                   /* DPo */
97            GXset                   /* 1 */
98    };
99    
100    #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
101    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
102    
103    static void
104    translate8(uint8 * data, uint8 * out, uint8 * end)
105  {  {
106          struct window *wnd;          while (out < end)
107          XSetWindowAttributes attribs;                  *(out++) = (uint8) colmap[*(data++)];
108          Display *display;  }
         Visual *visual;  
         Window window;  
         int black;  
         GC gc;  
109    
110          display = XOpenDisplay(NULL);  static void
111          if (display == NULL)  translate16(uint8 * data, uint16 * out, uint16 * end)
112                  return NULL;  {
113            while (out < end)
114                    *(out++) = (uint16) colmap[*(data++)];
115    }
116    
117    /* little endian - conversion happens when colourmap is built */
118    static void
119    translate24(uint8 * data, uint8 * out, uint8 * end)
120    {
121            uint32 value;
122    
123            while (out < end)
124            {
125                    value = colmap[*(data++)];
126                    *(out++) = value;
127                    *(out++) = value >> 8;
128                    *(out++) = value >> 16;
129            }
130    }
131    
132          visual = DefaultVisual(display, DefaultScreen(display));  static void
133          black = BlackPixel(display, DefaultScreen(display));  translate32(uint8 * data, uint32 * out, uint32 * end)
134    {
135            while (out < end)
136                    *(out++) = colmap[*(data++)];
137    }
138    
139          attribs.background_pixel = black;  static uint8 *
140          attribs.backing_store = Always;  translate_image(int width, int height, uint8 * data)
141          window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,  {
142                          width, height, 0, 8, InputOutput, visual,          int size = width * height * bpp / 8;
143                          CWBackingStore | CWBackPixel, &attribs);          uint8 *out = xmalloc(size);
144            uint8 *end = out + size;
145    
146          XStoreName(display, window, "rdesktop");          switch (bpp)
147          XMapWindow(display, window);          {
148          XSelectInput(display, window, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);                  case 8:
149          XSync(display, True);                          translate8(data, out, end);
150                            break;
151    
152          gc = XCreateGC(display, window, 0, NULL);                  case 16:
153                            translate16(data, (uint16 *) out, (uint16 *) end);
154                            break;
155    
156          wnd = xmalloc(sizeof(struct window));                  case 24:
157          wnd->conn = conn;                          translate24(data, out, end);
158          wnd->width = width;                          break;
         wnd->height = height;  
         wnd->display = display;  
         wnd->wnd = window;  
         wnd->gc = gc;  
         wnd->visual = visual;  
159    
160          return wnd;                  case 32:
161                            translate32(data, (uint32 *) out, (uint32 *) end);
162                            break;
163            }
164    
165            return out;
166  }  }
167    
168  void ui_destroy_window(HWINDOW wnd)  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
169    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
170    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
171                            x = (x << 16) | (x >> 16); }
172    
173    static uint32
174    translate_colour(uint32 colour)
175  {  {
176          XFreeGC(wnd->display, wnd->gc);          switch (bpp)
177          XDestroyWindow(wnd->display, wnd->wnd);          {
178          XCloseDisplay(wnd->display);                  case 16:
179                            if (host_be != xserver_be)
180                                    BSWAP16(colour);
181                            break;
182    
183                    case 24:
184                            if (xserver_be)
185                                    BSWAP24(colour);
186                            break;
187    
188                    case 32:
189                            if (host_be != xserver_be)
190                                    BSWAP32(colour);
191                            break;
192            }
193    
194            return colour;
195  }  }
196    
197  static uint8 xwin_translate_key(unsigned long key)  static unsigned long
198    init_inputmethod(void)
199  {  {
200          DEBUG("KEY(code=0x%lx)\n", key);          unsigned long filtered_events = 0;
201    
202          if ((key > 8) && (key <= 0x60))          IM = XOpenIM(display, NULL, NULL, NULL);
203                  return (key - 8);          if (IM == NULL)
204            {
205                    error("Failed to open input method\n");
206            }
207    
208          switch (key)          if (IM != NULL)
209          {          {
210                  case 0x62: /* left arrow */                  /* Must be done after XCreateWindow */
211                          return 0x48;                  IC = XCreateIC(IM, XNInputStyle,
212                  case 0x64: /* up arrow */                                 (XIMPreeditNothing | XIMStatusNothing),
213                          return 0x4b;                                 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
214                  case 0x66: /* down arrow */  
215                          return 0x4d;                  if (IC == NULL)
216                  case 0x68: /* right arrow */                  {
217                          return 0x50;                          error("Failed to create input context\n");
218                  case 0x73: /* Windows key */                          XCloseIM(IM);
219                          DEBUG("CHECKPOINT\n");                          IM = NULL;
220                    }
221          }          }
222    
223          return 0;          /* For correct Multi_key/Compose processing, I guess.
224               It seems to work alright anyway, though. */
225            if (IC != NULL)
226            {
227                    if (XGetICValues(IC, XNFilterEvents, &filtered_events, NULL) != NULL)
228                    {
229                            error("Failed to obtain XNFilterEvents value from IC\n");
230                            filtered_events = 0;
231                    }
232            }
233            return filtered_events;
234  }  }
235    
236  static uint16 xwin_translate_mouse(unsigned long button)  static void
237    close_inputmethod(void)
238  {  {
239          switch (button)          if (IC != NULL)
240          {          {
241                  case Button1: /* left */                  XDestroyIC(IC);
242                          return MOUSE_FLAG_BUTTON1;                  if (IM != NULL)
243                  case Button2: /* middle */                  {
244                          return MOUSE_FLAG_BUTTON3;                          XCloseIM(IM);
245                  case Button3: /* right */                          IM = NULL;
246                          return MOUSE_FLAG_BUTTON2;                  }
247          }          }
248    }
249    
250          return 0;  BOOL
251    ui_init()
252    {
253            Screen *screen;
254            display = XOpenDisplay(NULL);
255            if (display == NULL)
256            {
257                    error("Failed to open display\n");
258                    return False;
259            }
260            if (fullscreen)
261            {
262                    screen = DefaultScreenOfDisplay(display);
263                    width = WidthOfScreen(screen);
264                    height = HeightOfScreen(screen);
265            }
266            return True;
267  }  }
268    
269  void ui_process_events(HWINDOW wnd, HCONN conn)  BOOL
270    ui_create_window_obj(int xpos, int ypos, int width, int height, int valuemask)
271  {  {
272          XEvent event;          XClassHint *classhints;
273          uint8 scancode;          XSizeHints *sizehints;
274          uint16 button;          XEvent xevent;
275            Screen *screen;
276    
277          if (wnd == NULL)          screen = DefaultScreenOfDisplay(display);
278                  return;  
279            wnd = XCreateWindow(display, RootWindowOfScreen(screen), xpos,
280                                ypos, width, height, 0, CopyFromParent,
281                                InputOutput, CopyFromParent, valuemask, &attribs);
282    
283    
284            XStoreName(display, wnd, title);
285    
286            classhints = XAllocClassHint();
287            if (classhints != NULL)
288            {
289                    classhints->res_name = classhints->res_class = "rdesktop";
290                    XSetClassHint(display, wnd, classhints);
291                    XFree(classhints);
292            }
293    
294            sizehints = XAllocSizeHints();
295            if (sizehints)
296            {
297                    sizehints->flags = PMinSize | PMaxSize;
298                    sizehints->min_width = sizehints->max_width = width;
299                    sizehints->min_height = sizehints->max_height = height;
300                    XSetWMNormalHints(display, wnd, sizehints);
301                    XFree(sizehints);
302            }
303    
304            if (enable_compose)
305                    input_mask |= init_inputmethod();
306    
307          while (XCheckWindowEvent(wnd->display, wnd->wnd, 0xffffffff, &event))          XSelectInput(display, wnd, input_mask);
308    
309            gc = XCreateGC(display, wnd, 0, NULL);
310    
311            XMapWindow(display, wnd);
312    
313            /* Wait for VisibilityNotify Event */
314            for (;;)
315            {
316                    XNextEvent(display, &xevent);
317                    if (xevent.type == VisibilityNotify)
318                            break;
319            }
320    
321            if (ownbackstore)
322                    backstore = XCreatePixmap(display, wnd, width, height, depth);
323    
324            /* clear the window so that cached data is not viewed upon start... */
325            XSetBackground(display, gc, 0);
326            XSetForeground(display, gc, 0);
327            FILL_RECTANGLE(0, 0, width, height);
328            /* make sure the window is focused */
329            XSetInputFocus(display, wnd, RevertToPointerRoot, CurrentTime);
330    }
331    
332    BOOL
333    ui_create_window()
334    {
335            XPixmapFormatValues *pfm;
336            Screen *screen;
337            uint16 test;
338            int i;
339    
340            x_socket = ConnectionNumber(display);
341            screen = DefaultScreenOfDisplay(display);
342            visual = DefaultVisualOfScreen(screen);
343            depth = DefaultDepthOfScreen(screen);
344    
345            pfm = XListPixmapFormats(display, &i);
346            if (pfm != NULL)
347            {
348                    /* Use maximum bpp for this depth - this is generally
349                       desirable, e.g. 24 bits->32 bits. */
350                    while (i--)
351                    {
352                            if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
353                            {
354                                    bpp = pfm[i].bits_per_pixel;
355                            }
356                    }
357                    XFree(pfm);
358            }
359    
360            if (bpp < 8)
361            {
362                    error("Less than 8 bpp not currently supported.\n");
363                    XCloseDisplay(display);
364                    return False;
365            }
366    
367            if (depth <= 8)
368                    owncolmap = True;
369            else
370                    xcolmap = DefaultColormapOfScreen(screen);
371    
372            test = 1;
373            host_be = !(BOOL) (*(uint8 *) (&test));
374            xserver_be = (ImageByteOrder(display) == MSBFirst);
375    
376            white = WhitePixelOfScreen(screen);
377            attribs.background_pixel = BlackPixelOfScreen(screen);
378            attribs.backing_store = DoesBackingStore(screen);
379    
380            if (attribs.backing_store == NotUseful)
381                    ownbackstore = True;
382    
383            dpy_width = WidthOfScreen(screen);
384            dpy_height = HeightOfScreen(screen);
385    
386            if (fullscreen)
387            {
388                    attribs.override_redirect = True;
389                    width = dpy_width;
390                    height = dpy_height;
391            }
392            else
393            {
394                    attribs.override_redirect = False;
395            }
396    
397            width = (width + 3) & ~3;       /* make width a multiple of 32 bits */
398    
399    
400            input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
401                    VisibilityChangeMask | FocusChangeMask;
402    
403            if (grab_keyboard)
404                    input_mask |= EnterWindowMask | LeaveWindowMask;
405            if (sendmotion)
406                    input_mask |= PointerMotionMask;
407    
408            if (ownbackstore)
409                    input_mask |= ExposureMask;
410    
411            if (fullscreen)
412                    ui_create_window_obj(0, 0, width, height,
413                                         CWBackingStore | CWBackPixel | CWOverrideRedirect);
414            else
415                    ui_create_window_obj(0, 0, width, height, CWBackingStore | CWBackPixel);
416    
417            xkeymap_init2();
418    
419            return True;
420    }
421    
422    void
423    ui_destroy_window()
424    {
425            if (ownbackstore)
426                    XFreePixmap(display, backstore);
427    
428            XFreeGC(display, gc);
429    
430            close_inputmethod();
431    
432            XDestroyWindow(display, wnd);
433            XCloseDisplay(display);
434            display = NULL;
435    }
436    
437    void
438    reset_keys()
439    {
440            /* reset keys */
441            uint32 ev_time;
442            ev_time = time(NULL);
443            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
444            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
445            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
446            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
447            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
448            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
449    }
450    
451    void
452    toggle_fullscreen()
453    {
454            /* save window contents */
455            Pixmap pixmap;
456            pixmap = XCreatePixmap(display, wnd, width, height, depth);
457            if (ownbackstore)
458                    XCopyArea(display, backstore, pixmap, gc, 0, 0, width, height, 0, 0);
459            else
460                    XCopyArea(display, wnd, pixmap, gc, 0, 0, width, height, 0, 0);
461            fullscreen = fullscreen ? False : True;
462            close_inputmethod();
463            if (ownbackstore)
464                    XFreePixmap(display, backstore);
465            XFreeGC(display, gc);
466            XDestroyWindow(display, wnd);
467            if (fullscreen)
468            {
469                    attribs.override_redirect = True;
470                    ui_create_window_obj(0, 0, dpy_width, dpy_height,
471                                         CWBackingStore | CWBackPixel | CWOverrideRedirect);
472            }
473            else
474            {
475                    attribs.override_redirect = False;
476                    ui_create_window_obj(0, 0, width, height, CWBackingStore | CWBackPixel);
477            }
478            ui_set_cursor(cache_get_cursor(0));
479            ui_move_pointer(width / 2, height / 2);
480            reset_keys();
481            /* restore window contents */
482            if (ownbackstore)
483                    XCopyArea(display, pixmap, backstore, gc, 0, 0, width, height, 0, 0);
484            XCopyArea(display, pixmap, wnd, gc, 0, 0, width, height, 0, 0);
485            XFreePixmap(display, pixmap);
486    }
487    
488    static void
489    xwin_process_events()
490    {
491            XEvent xevent;
492    
493            KeySym keysym;
494            uint16 button, flags;
495            uint32 ev_time;
496            key_translation tr;
497            char *ksname = NULL;
498            char str[256];
499            Status status;
500    
501            /* Refresh keyboard mapping if it has changed. This is important for
502               Xvnc, since it allocates keycodes dynamically */
503            if (XCheckTypedEvent(display, MappingNotify, &xevent))
504            {
505                    if (xevent.xmapping.request == MappingKeyboard
506                        || xevent.xmapping.request == MappingModifier)
507                            XRefreshKeyboardMapping(&xevent.xmapping);
508            }
509    
510            while (XCheckMaskEvent(display, ~0, &xevent))
511          {          {
512                  switch (event.type)                  if (enable_compose && (XFilterEvent(&xevent, None) == True))
513                    {
514                            DEBUG_KBD(("Filtering event\n"));
515                            continue;
516                    }
517    
518                    ev_time = time(NULL);
519                    flags = 0;
520    
521                    switch (xevent.type)
522                  {                  {
523                          case KeyPress:                          case KeyPress:
524                                  scancode = xwin_translate_key(event.xkey.keycode);                                  if (IC != NULL)
525                                  if (scancode == 0)                                          /* Multi_key compatible version */
526                                    {
527                                            XmbLookupString(IC,
528                                                            (XKeyPressedEvent *) &
529                                                            xevent, str, sizeof(str), &keysym, &status);
530                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
531                                            {
532                                                    error("XmbLookupString failed with status 0x%x\n",
533                                                          status);
534                                                    break;
535                                            }
536                                    }
537                                    else
538                                    {
539                                            /* Plain old XLookupString */
540                                            DEBUG_KBD(("No input context, using XLookupString\n"));
541                                            XLookupString((XKeyEvent *) & xevent,
542                                                          str, sizeof(str), &keysym, NULL);
543                                    }
544    
545                                    /* FIXME needs alt modifier */
546                                    if (keysym == XK_Break) /* toggle full screen */
547                                    {
548                                            toggle_fullscreen();
549                                            break;
550                                    }
551                                    ksname = get_ksname(keysym);
552                                    DEBUG_KBD(("\nKeyPress for (keysym 0x%lx, %s)\n", keysym, ksname));
553    
554                                    if (inhibit_key(keysym))
555                                    {
556                                            DEBUG_KBD(("Inhibiting key\n"));
557                                          break;                                          break;
558                                    }
559    
560                                  rdp_send_input(conn, RDP_INPUT_SCANCODE, 0,                                  tr = xkeymap_translate_key(keysym,
561                                                  scancode, 0);                                                             xevent.xkey.keycode, xevent.xkey.state);
                                 break;  
562    
563                          case KeyRelease:                                  ensure_remote_modifiers(ev_time, tr);
564                                  scancode = xwin_translate_key(event.xkey.keycode);  
565                                  if (scancode == 0)                                  if (tr.scancode == 0)
566                                          break;                                          break;
567    
568                                  rdp_send_input(conn, RDP_INPUT_SCANCODE,                                  rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,  
                                                 scancode, 0);  
569                                  break;                                  break;
570                            case KeyRelease:
571                                    XLookupString((XKeyEvent *) & xevent, str,
572                                                  sizeof(str), &keysym, NULL);
573    
574                          case ButtonPress:                                  ksname = get_ksname(keysym);
575                                  button = xwin_translate_mouse(event.xbutton.button);                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
576                                               ksname));
577    
578                                  if (button == 0)                                  if (inhibit_key(keysym))
579                                          break;                                          break;
580    
581                                  rdp_send_input(conn, RDP_INPUT_MOUSE,                                  tr = xkeymap_translate_key(keysym,
582                                                  button | MOUSE_FLAG_DOWN,                                                             xevent.xkey.keycode, xevent.xkey.state);
583                                                  event.xbutton.x,  
584                                                  event.xbutton.y);                                  if (tr.scancode == 0)
585                                            break;
586    
587                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
588                                  break;                                  break;
589    
590                            case ButtonPress:
591                                    flags = MOUSE_FLAG_DOWN;
592                                    /* fall through */
593    
594                          case ButtonRelease:                          case ButtonRelease:
595                                  button = xwin_translate_mouse(event.xbutton.button);                                  button = xkeymap_translate_button(xevent.xbutton.button);
596                                  if (button == 0)                                  if (button == 0)
597                                          break;                                          break;
598    
599                                  rdp_send_input(conn, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
600                                                  button,                                                 flags | button, xevent.xbutton.x, xevent.xbutton.y);
601                                                  event.xbutton.x,                                  break;
602                                                  event.xbutton.y);  
603                            case MotionNotify:
604                                    rdp_send_input(ev_time, RDP_INPUT_MOUSE,
605                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
606                                    break;
607    
608                            case FocusIn:
609                                    /* fall through */
610                            case EnterNotify:
611                                    if (grab_keyboard)
612                                            XGrabKeyboard(display, wnd, True,
613                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
614                                    break;
615    
616                            case FocusOut:
617                                    reset_keys();
618                                    /* fall through */
619                            case LeaveNotify:
620                                    if (grab_keyboard)
621                                            XUngrabKeyboard(display, CurrentTime);
622                                    break;
623    
624                            case Expose:
625                                    XCopyArea(display, backstore, wnd, gc,
626                                              xevent.xexpose.x, xevent.xexpose.y,
627                                              xevent.xexpose.width,
628                                              xevent.xexpose.height,
629                                              xevent.xexpose.x, xevent.xexpose.y);
630                                    break;
631                    }
632            }
633    }
634    
635    void
636    ui_select(int rdp_socket)
637    {
638            int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
639            fd_set rfds;
640    
641            FD_ZERO(&rfds);
642    
643            while (True)
644            {
645                    FD_ZERO(&rfds);
646                    FD_SET(rdp_socket, &rfds);
647                    if (display != NULL)
648                    {
649                            FD_SET(x_socket, &rfds);
650                            XFlush(display);
651                  }                  }
652    
653                    switch (select(n, &rfds, NULL, NULL, NULL))
654                    {
655                            case -1:
656                                    error("select: %s\n", strerror(errno));
657    
658                            case 0:
659                                    continue;
660                    }
661    
662                    if (FD_ISSET(x_socket, &rfds))
663                            xwin_process_events();
664    
665                    if (FD_ISSET(rdp_socket, &rfds))
666                            return;
667          }          }
668  }  }
669    
670  void ui_move_pointer(HWINDOW wnd, int x, int y)  void
671    ui_move_pointer(int x, int y)
672  {  {
673          XWarpPointer(wnd->display, wnd->wnd, wnd->wnd, 0, 0, 0, 0, x, y);          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
674  }  }
675    
676  HBITMAP ui_create_bitmap(HWINDOW wnd, int width, int height, uint8 *data)  HBITMAP
677    ui_create_bitmap(int width, int height, uint8 * data)
678  {  {
679          XImage *image;          XImage *image;
680          Pixmap bitmap;          Pixmap bitmap;
681            uint8 *tdata;
682    
683            tdata = (owncolmap ? data : translate_image(width, height, data));
684            bitmap = XCreatePixmap(display, wnd, width, height, depth);
685            image = XCreateImage(display, visual, depth, ZPixmap, 0,
686                                 (char *) tdata, width, height, 8, 0);
687    
688            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
689    
690            XFree(image);
691            if (!owncolmap)
692                    xfree(tdata);
693            return (HBITMAP) bitmap;
694    }
695    
696    void
697    ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
698    {
699            XImage *image;
700            uint8 *tdata;
701    
702            tdata = (owncolmap ? data : translate_image(width, height, data));
703            image = XCreateImage(display, visual, depth, ZPixmap, 0,
704                                 (char *) tdata, width, height, 8, 0);
705    
706          bitmap = XCreatePixmap(wnd->display, wnd->wnd, width, height, 8);          if (ownbackstore)
707            {
708                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
709                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
710            }
711            else
712            {
713                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
714            }
715    
         image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,  
                                 data, width, height, 8, width);  
         XSetFunction(wnd->display, wnd->gc, GXcopy);  
         XPutImage(wnd->display, bitmap, wnd->gc, image, 0, 0, 0, 0,  
                         width, height);  
716          XFree(image);          XFree(image);
717                    if (!owncolmap)
718          return (HBITMAP)bitmap;                  xfree(tdata);
719  }  }
720    
721  void ui_destroy_bitmap(HWINDOW wnd, HBITMAP bmp)  void
722    ui_destroy_bitmap(HBITMAP bmp)
723  {  {
724          XFreePixmap(wnd->display, (Pixmap)bmp);          XFreePixmap(display, (Pixmap) bmp);
725  }  }
726    
727  HGLYPH ui_create_glyph(HWINDOW wnd, int width, int height, uint8 *data)  HGLYPH
728    ui_create_glyph(int width, int height, uint8 * data)
729  {  {
730          XImage *image;          XImage *image;
731          Pixmap bitmap;          Pixmap bitmap;
# Line 201  HGLYPH ui_create_glyph(HWINDOW wnd, int Line 734  HGLYPH ui_create_glyph(HWINDOW wnd, int
734    
735          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
736    
737          bitmap = XCreatePixmap(wnd->display, wnd->wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
738          gc = XCreateGC(wnd->display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
739    
740            image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
741                                 width, height, 8, scanline);
742            image->byte_order = MSBFirst;
743            image->bitmap_bit_order = MSBFirst;
744            XInitImage(image);
745    
746            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
747    
         image = XCreateImage(wnd->display, wnd->visual, 1, ZPixmap, 0,  
                                 data, width, height, 8, scanline);  
         XSetFunction(wnd->display, wnd->gc, GXcopy);  
         XPutImage(wnd->display, bitmap, gc, image, 0, 0, 0, 0, width, height);  
748          XFree(image);          XFree(image);
749          XFreeGC(wnd->display, gc);          XFreeGC(display, gc);
750                    return (HGLYPH) bitmap;
751          return (HGLYPH)bitmap;  }
752    
753    void
754    ui_destroy_glyph(HGLYPH glyph)
755    {
756            XFreePixmap(display, (Pixmap) glyph);
757    }
758    
759    HCURSOR
760    ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
761                     uint8 * andmask, uint8 * xormask)
762    {
763            HGLYPH maskglyph, cursorglyph;
764            XColor bg, fg;
765            Cursor xcursor;
766            uint8 *cursor, *pcursor;
767            uint8 *mask, *pmask;
768            uint8 nextbit;
769            int scanline, offset;
770            int i, j;
771    
772            scanline = (width + 7) / 8;
773            offset = scanline * height;
774    
775            cursor = xmalloc(offset);
776            memset(cursor, 0, offset);
777    
778            mask = xmalloc(offset);
779            memset(mask, 0, offset);
780    
781            /* approximate AND and XOR masks with a monochrome X pointer */
782            for (i = 0; i < height; i++)
783            {
784                    offset -= scanline;
785                    pcursor = &cursor[offset];
786                    pmask = &mask[offset];
787    
788                    for (j = 0; j < scanline; j++)
789                    {
790                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
791                            {
792                                    if (xormask[0] || xormask[1] || xormask[2])
793                                    {
794                                            *pcursor |= (~(*andmask) & nextbit);
795                                            *pmask |= nextbit;
796                                    }
797                                    else
798                                    {
799                                            *pcursor |= ((*andmask) & nextbit);
800                                            *pmask |= (~(*andmask) & nextbit);
801                                    }
802    
803                                    xormask += 3;
804                            }
805    
806                            andmask++;
807                            pcursor++;
808                            pmask++;
809                    }
810            }
811    
812            fg.red = fg.blue = fg.green = 0xffff;
813            bg.red = bg.blue = bg.green = 0x0000;
814            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
815    
816            cursorglyph = ui_create_glyph(width, height, cursor);
817            maskglyph = ui_create_glyph(width, height, mask);
818    
819            xcursor =
820                    XCreatePixmapCursor(display, (Pixmap) cursorglyph,
821                                        (Pixmap) maskglyph, &fg, &bg, x, y);
822    
823            ui_destroy_glyph(maskglyph);
824            ui_destroy_glyph(cursorglyph);
825            xfree(mask);
826            xfree(cursor);
827            return (HCURSOR) xcursor;
828  }  }
829    
830  void ui_destroy_glyph(HWINDOW wnd, HGLYPH glyph)  void
831    ui_set_cursor(HCURSOR cursor)
832  {  {
833          XFreePixmap(wnd->display, (Pixmap)glyph);          XDefineCursor(display, wnd, (Cursor) cursor);
834  }  }
835    
836  HCOLOURMAP ui_create_colourmap(HWINDOW wnd, COLOURMAP *colours)  void
837    ui_destroy_cursor(HCURSOR cursor)
838    {
839            XFreeCursor(display, (Cursor) cursor);
840    }
841    
842    #define MAKE_XCOLOR(xc,c) \
843                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
844                    (xc)->green = ((c)->green << 8) | (c)->green; \
845                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
846                    (xc)->flags = DoRed | DoGreen | DoBlue;
847    
848    HCOLOURMAP
849    ui_create_colourmap(COLOURMAP * colours)
850  {  {
851          COLOURENTRY *entry;          COLOURENTRY *entry;
         XColor *xcolours, *xentry;  
         Colormap map;  
852          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
853    
854          xcolours = malloc(sizeof(XColor) * ncolours);          if (owncolmap)
         for (i = 0; i < ncolours; i++)  
855          {          {
856                  entry = &colours->colours[i];                  XColor *xcolours, *xentry;
857                  xentry = &xcolours[i];                  Colormap map;
858    
859                    xcolours = xmalloc(sizeof(XColor) * ncolours);
860                    for (i = 0; i < ncolours; i++)
861                    {
862                            entry = &colours->colours[i];
863                            xentry = &xcolours[i];
864                            xentry->pixel = i;
865                            MAKE_XCOLOR(xentry, entry);
866                    }
867    
868                    map = XCreateColormap(display, wnd, visual, AllocAll);
869                    XStoreColors(display, map, xcolours, ncolours);
870    
871                  xentry->pixel = i;                  xfree(xcolours);
872                  xentry->red = entry->red << 8;                  return (HCOLOURMAP) map;
                 xentry->blue = entry->blue << 8;  
                 xentry->green = entry->green << 8;  
                 xentry->flags = DoRed | DoBlue | DoGreen;  
873          }          }
874            else
875            {
876                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
877                    XColor xentry;
878                    uint32 colour;
879    
880          map = XCreateColormap(wnd->display, wnd->wnd, wnd->visual, AllocAll);                  for (i = 0; i < ncolours; i++)
881          XStoreColors(wnd->display, map, xcolours, ncolours);                  {
882                            entry = &colours->colours[i];
883                            MAKE_XCOLOR(&xentry, entry);
884    
885          free(xcolours);                          if (XAllocColor(display, xcolmap, &xentry) != 0)
886          return (HCOLOURMAP)map;                                  colour = xentry.pixel;
887                            else
888                                    colour = white;
889    
890                            /* byte swap here to make translate_image faster */
891                            map[i] = translate_colour(colour);
892                    }
893    
894                    return map;
895            }
896  }  }
897    
898  void ui_destroy_colourmap(HWINDOW wnd, HCOLOURMAP map)  void
899    ui_destroy_colourmap(HCOLOURMAP map)
900  {  {
901          XFreeColormap(wnd->display, (Colormap)map);          if (owncolmap)
902                    XFreeColormap(display, (Colormap) map);
903            else
904                    xfree(map);
905  }  }
906    
907  void ui_set_colourmap(HWINDOW wnd, HCOLOURMAP map)  void
908    ui_set_colourmap(HCOLOURMAP map)
909  {  {
910          XSetWindowColormap(wnd->display, wnd->wnd, (Colormap)map);          if (owncolmap)
911                    XSetWindowColormap(display, wnd, (Colormap) map);
912            else
913                    colmap = map;
914  }  }
915    
916  void ui_set_clip(HWINDOW wnd, int x, int y, int cx, int cy)  void
917    ui_set_clip(int x, int y, int cx, int cy)
918  {  {
919          XRectangle rect;          XRectangle rect;
920    
# Line 264  void ui_set_clip(HWINDOW wnd, int x, int Line 922  void ui_set_clip(HWINDOW wnd, int x, int
922          rect.y = y;          rect.y = y;
923          rect.width = cx;          rect.width = cx;
924          rect.height = cy;          rect.height = cy;
925          XSetClipRectangles(wnd->display, wnd->gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
926  }  }
927    
928  void ui_reset_clip(HWINDOW wnd)  void
929    ui_reset_clip()
930  {  {
931          XRectangle rect;          XRectangle rect;
932    
933          rect.x = 0;          rect.x = 0;
934          rect.y = 0;          rect.y = 0;
935          rect.width = wnd->width;          rect.width = width;
936          rect.height = wnd->height;          rect.height = height;
937          XSetClipRectangles(wnd->display, wnd->gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
938  }  }
939    
940  static int rop2_map[] = {  void
941          GXclear,        /* 0 */  ui_bell()
         GXnor,          /* DPon */  
         GXandInverted,  /* DPna */  
         GXcopyInverted, /* Pn */  
         GXandReverse,   /* PDna */  
         GXinvert,       /* Dn */  
         GXxor,          /* DPx */  
         GXnand,         /* DPan */  
         GXand,          /* DPa */  
         GXequiv,        /* DPxn */  
         GXnoop,         /* D */  
         GXorInverted,   /* DPno */  
         GXcopy,         /* P */  
         GXorReverse,    /* PDno */  
         GXor,           /* DPo */  
         GXset           /* 1 */  
 };  
   
 static void xwin_set_function(HWINDOW wnd, uint8 rop2)  
942  {  {
943          XSetFunction(wnd->display, wnd->gc, rop2_map[rop2]);          XBell(display, 0);
944  }  }
945    
946  void ui_destblt(HWINDOW wnd, uint8 opcode,  void
947          /* dest */  int x, int y, int cx, int cy)  ui_destblt(uint8 opcode,
948               /* dest */ int x, int y, int cx, int cy)
949  {  {
950          xwin_set_function(wnd, opcode);          SET_FUNCTION(opcode);
951            FILL_RECTANGLE(x, y, cx, cy);
952          XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
953  }  }
954    
955  void ui_patblt(HWINDOW wnd, uint8 opcode,  void
956          /* dest */  int x, int y, int cx, int cy,  ui_patblt(uint8 opcode,
957          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* dest */ int x, int y, int cx, int cy,
958              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
959  {  {
         Display *dpy = wnd->display;  
         GC gc = wnd->gc;  
960          Pixmap fill;          Pixmap fill;
961            uint8 i, ipattern[8];
962    
963          xwin_set_function(wnd, opcode);          SET_FUNCTION(opcode);
964    
965          switch (brush->style)          switch (brush->style)
966          {          {
967                  case 0: /* Solid */                  case 0: /* Solid */
968                          XSetForeground(dpy, gc, fgcolour);                          SET_FOREGROUND(fgcolour);
969                          XFillRectangle(dpy, wnd->wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
970                          break;                          break;
971    
972                  case 3: /* Pattern */                  case 3: /* Pattern */
973                          fill = (Pixmap)ui_create_glyph(wnd, 8, 8, brush->pattern);                          for (i = 0; i != 8; i++)
974                                    ipattern[7 - i] = brush->pattern[i];
975                          XSetForeground(dpy, gc, fgcolour);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
976                          XSetBackground(dpy, gc, bgcolour);  
977                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                          SET_FOREGROUND(bgcolour);
978                          XSetStipple(dpy, gc, fill);                          SET_BACKGROUND(fgcolour);
979                            XSetFillStyle(display, gc, FillOpaqueStippled);
980                          XFillRectangle(dpy, wnd->wnd, gc, x, y, cx, cy);                          XSetStipple(display, gc, fill);
981                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
982                          XSetFillStyle(dpy, gc, FillSolid);  
983                          ui_destroy_glyph(wnd, (HGLYPH)fill);                          FILL_RECTANGLE(x, y, cx, cy);
984    
985                            XSetFillStyle(display, gc, FillSolid);
986                            XSetTSOrigin(display, gc, 0, 0);
987                            ui_destroy_glyph((HGLYPH) fill);
988                          break;                          break;
989    
990                  default:                  default:
991                          NOTIMP("brush style %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
992          }          }
 }  
   
 void ui_screenblt(HWINDOW wnd, uint8 opcode,  
                 /* dest */ int x, int y, int cx, int cy,  
                 /* src */  int srcx, int srcy)  
 {  
         xwin_set_function(wnd, opcode);  
993    
994          XCopyArea(wnd->display, wnd->wnd, wnd->wnd, wnd->gc, srcx, srcy,          RESET_FUNCTION(opcode);
                         cx, cy, x, y);  
995  }  }
996    
997  void ui_memblt(HWINDOW wnd, uint8 opcode,  void
998          /* dest */  int x, int y, int cx, int cy,  ui_screenblt(uint8 opcode,
999          /* src */   HBITMAP src, int srcx, int srcy)               /* dest */ int x, int y, int cx, int cy,
1000  {               /* src */ int srcx, int srcy)
1001          xwin_set_function(wnd, opcode);  {
1002            SET_FUNCTION(opcode);
1003          XCopyArea(wnd->display, (Pixmap)src, wnd->wnd, wnd->gc, srcx, srcy,          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1004                          cx, cy, x, y);          if (ownbackstore)
1005  }                  XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1006            RESET_FUNCTION(opcode);
1007  void ui_triblt(HWINDOW wnd, uint8 opcode,  }
1008          /* dest */  int x, int y, int cx, int cy,  
1009          /* src */   HBITMAP src, int srcx, int srcy,  void
1010          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)  ui_memblt(uint8 opcode,
1011              /* dest */ int x, int y, int cx, int cy,
1012              /* src */ HBITMAP src, int srcx, int srcy)
1013    {
1014            SET_FUNCTION(opcode);
1015            XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1016            if (ownbackstore)
1017                    XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1018            RESET_FUNCTION(opcode);
1019    }
1020    
1021    void
1022    ui_triblt(uint8 opcode,
1023              /* dest */ int x, int y, int cx, int cy,
1024              /* src */ HBITMAP src, int srcx, int srcy,
1025              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1026  {  {
1027          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1028             comes up with an efficient way of doing that I am using cases. */             comes up with a more efficient way of doing it I am using cases. */
1029    
1030          switch (opcode)          switch (opcode)
1031          {          {
1032                  case 0xb8: /* PSDPxax */                  case 0x69:      /* PDSxxn */
1033                          ui_patblt(wnd, ROP2_XOR, x, y, cx, cy,                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1034                                          brush, bgcolour, fgcolour);                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                         ui_memblt(wnd, ROP2_AND, x, y, cx, cy,  
                                         src, srcx, srcy);  
                         ui_patblt(wnd, ROP2_XOR, x, y, cx, cy,  
                                         brush, bgcolour, fgcolour);  
1035                          break;                          break;
1036    
1037                  default:                  case 0xb8:      /* PSDPxax */
1038                          NOTIMP("triblt opcode 0x%x\n", opcode);                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1039                          ui_memblt(wnd, ROP2_COPY, x, y, cx, cy,                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1040                                          brush, bgcolour, fgcolour);                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
         }  
 }  
   
 void ui_line(HWINDOW wnd, uint8 opcode,  
         /* dest */  int startx, int starty, int endx, int endy,  
         /* pen */   PEN *pen)  
 {  
         xwin_set_function(wnd, opcode);  
   
         XSetForeground(wnd->display, wnd->gc, pen->colour);  
         XDrawLine(wnd->display, wnd->wnd, wnd->gc, startx, starty, endx, endy);  
 }  
   
 void ui_rect(HWINDOW wnd,  
         /* dest */  int x, int y, int cx, int cy,  
         /* brush */ int colour)  
 {  
         xwin_set_function(wnd, ROP2_COPY);  
   
         XSetForeground(wnd->display, wnd->gc, colour);  
         XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, cx, cy);  
 }  
   
 void ui_draw_glyph(HWINDOW wnd, 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(wnd, ROP2_COPY);  
   
         XSetForeground(wnd->display, wnd->gc, fgcolour);  
   
         switch (mixmode)  
         {  
                 case MIX_TRANSPARENT:  
                         XSetStipple(wnd->display, wnd->gc, pixmap);  
                         XSetFillStyle(wnd->display, wnd->gc, FillStippled);  
                         XSetTSOrigin(wnd->display, wnd->gc, x, y);  
                         XFillRectangle(wnd->display, wnd->wnd, wnd->gc,  
                                         x, y, cx, cy);  
                         XSetFillStyle(wnd->display, wnd->gc, FillSolid);  
1041                          break;                          break;
1042    
1043                  case MIX_OPAQUE:                  case 0xc0:      /* PSa */
1044                          XSetBackground(wnd->display, wnd->gc, bgcolour);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1045                          XCopyPlane(wnd->display, pixmap, wnd->wnd, wnd->gc,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
                                         srcx, srcy, cx, cy, x, y, 1);  
1046                          break;                          break;
1047    
1048                  default:                  default:
1049                          NOTIMP("mix mode %d\n", mixmode);                          unimpl("triblt 0x%x\n", opcode);
1050                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1051          }          }
1052  }  }
1053    
1054  void ui_draw_text(HWINDOW wnd, uint8 font, uint8 flags, int mixmode, int x,  void
1055                          int y, int boxx, int boxy, int boxcx, int boxcy,  ui_line(uint8 opcode,
1056                          int bgcolour, int fgcolour, uint8 *text, uint8 length)          /* dest */ int startx, int starty, int endx, int endy,
1057  {          /* pen */ PEN * pen)
1058          FONT_GLYPH *glyph;  {
1059          int i;          SET_FUNCTION(opcode);
1060            SET_FOREGROUND(pen->colour);
1061            XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1062            if (ownbackstore)
1063                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1064            RESET_FUNCTION(opcode);
1065    }
1066    
1067    void
1068    ui_rect(
1069                   /* dest */ int x, int y, int cx, int cy,
1070                   /* brush */ int colour)
1071    {
1072            SET_FOREGROUND(colour);
1073            FILL_RECTANGLE(x, y, cx, cy);
1074    }
1075    
1076    void
1077    ui_draw_glyph(int mixmode,
1078                  /* dest */ int x, int y, int cx, int cy,
1079                  /* src */ HGLYPH glyph, int srcx, int srcy,
1080                  int bgcolour, int fgcolour)
1081    {
1082            SET_FOREGROUND(fgcolour);
1083            SET_BACKGROUND(bgcolour);
1084    
1085            XSetFillStyle(display, gc,
1086                          (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1087            XSetStipple(display, gc, (Pixmap) glyph);
1088            XSetTSOrigin(display, gc, x, y);
1089    
1090            FILL_RECTANGLE(x, y, cx, cy);
1091    
1092            XSetFillStyle(display, gc, FillSolid);
1093    }
1094    
1095    #define DO_GLYPH(ttext,idx) \
1096    {\
1097      glyph = cache_get_font (font, ttext[idx]);\
1098      if (!(flags & TEXT2_IMPLICIT_X))\
1099        {\
1100          xyoffset = ttext[++idx];\
1101          if ((xyoffset & 0x80))\
1102            {\
1103              if (flags & TEXT2_VERTICAL) \
1104                y += ttext[idx+1] | (ttext[idx+2] << 8);\
1105              else\
1106                x += ttext[idx+1] | (ttext[idx+2] << 8);\
1107              idx += 2;\
1108            }\
1109          else\
1110            {\
1111              if (flags & TEXT2_VERTICAL) \
1112                y += xyoffset;\
1113              else\
1114                x += xyoffset;\
1115            }\
1116        }\
1117      if (glyph != NULL)\
1118        {\
1119          ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1120                         y + (short) glyph->baseline,\
1121                         glyph->width, glyph->height,\
1122                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1123          if (flags & TEXT2_IMPLICIT_X)\
1124            x += glyph->width;\
1125        }\
1126    }
1127    
1128    void
1129    ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1130                 int clipx, int clipy, int clipcx, int clipcy,
1131                 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1132                 int fgcolour, uint8 * text, uint8 length)
1133    {
1134            FONTGLYPH *glyph;
1135            int i, j, xyoffset;
1136            DATABLOB *entry;
1137    
1138            SET_FOREGROUND(bgcolour);
1139    
1140          if (boxcx > 1)          if (boxcx > 1)
1141          {          {
1142                  ui_rect(wnd, boxx, boxy, boxcx, boxcy, bgcolour);                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1143            }
1144            else if (mixmode == MIX_OPAQUE)
1145            {
1146                    FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1147          }          }
1148    
1149          /* Paint text, character by character */          /* Paint text, character by character */
1150          for (i = 0; i < length; i++)          for (i = 0; i < length;)
1151          {          {
1152                  glyph = cache_get_font(wnd->conn, font, text[i]);                  switch (text[i])
   
                 if (glyph != NULL)  
1153                  {                  {
1154                          ui_draw_glyph(wnd, mixmode, x,                          case 0xff:
1155                                          y + (short)glyph->baseline,                                  if (i + 2 < length)
1156                                          glyph->width, glyph->height,                                          cache_put_text(text[i + 1], text, text[i + 2]);
1157                                          glyph->pixmap, 0, 0,                                  else
1158                                          bgcolour, fgcolour);                                  {
1159                                            error("this shouldn't be happening\n");
1160                                            break;
1161                                    }
1162                                    /* this will move pointer from start to first character after FF command */
1163                                    length -= i + 3;
1164                                    text = &(text[i + 3]);
1165                                    i = 0;
1166                                    break;
1167    
1168                          if (flags & TEXT2_IMPLICIT_X)                          case 0xfe:
1169                                  x += glyph->width;                                  entry = cache_get_text(text[i + 1]);
1170                          else                                  if (entry != NULL)
1171                                  x += text[++i];                                  {
1172                                            if ((((uint8 *) (entry->data))[1] ==
1173                                                 0) && (!(flags & TEXT2_IMPLICIT_X)))
1174                                            {
1175                                                    if (flags & TEXT2_VERTICAL)
1176                                                            y += text[i + 2];
1177                                                    else
1178                                                            x += text[i + 2];
1179                                            }
1180                                            if (i + 2 < length)
1181                                                    i += 3;
1182                                            else
1183                                                    i += 2;
1184                                            length -= i;
1185                                            /* this will move pointer from start to first character after FE command */
1186                                            text = &(text[i]);
1187                                            i = 0;
1188                                            for (j = 0; j < entry->size; j++)
1189                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1190                                    }
1191                                    break;
1192    
1193                            default:
1194                                    DO_GLYPH(text, i);
1195                                    i++;
1196                                    break;
1197                  }                  }
1198          }          }
1199    
1200    
1201  }  }
1202    
1203  void ui_desktop_save(HWINDOW wnd, uint8 *data, int x, int y, int cx, int cy)  void
1204    ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1205  {  {
1206            Pixmap pix;
1207          XImage *image;          XImage *image;
         int scanline;  
1208    
1209          scanline = (cx + 3) & ~3;          if (ownbackstore)
1210          image = XGetImage(wnd->display, wnd->wnd, x, y, cx, cy,          {
1211                                  0xffffffff, ZPixmap);                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1212          memcpy(data, image->data, scanline*cy);          }
1213            else
1214            {
1215                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
1216                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1217                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1218                    XFreePixmap(display, pix);
1219            }
1220    
1221            offset *= bpp / 8;
1222            cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1223    
1224          XDestroyImage(image);          XDestroyImage(image);
1225  }  }
1226    
1227  void ui_desktop_restore(HWINDOW wnd, uint8 *data, int x, int y, int cx, int cy)  void
1228    ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1229  {  {
1230          XImage *image;          XImage *image;
1231          int scanline;          uint8 *data;
1232    
1233            offset *= bpp / 8;
1234            data = cache_get_desktop(offset, cx, cy, bpp / 8);
1235            if (data == NULL)
1236                    return;
1237    
1238            image = XCreateImage(display, visual, depth, ZPixmap, 0,
1239                                 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1240    
1241            if (ownbackstore)
1242            {
1243                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1244                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1245            }
1246            else
1247            {
1248                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1249            }
1250    
         scanline = (cx + 3) & ~3;  
         image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,  
                                 data, cx, cy, 32, scanline);  
         XSetFunction(wnd->display, wnd->gc, GXcopy);  
         XPutImage(wnd->display, wnd->wnd, wnd->gc, image, 0, 0, x, y, cx, cy);  
1251          XFree(image);          XFree(image);
1252  }  }

Legend:
Removed from v.9  
changed lines
  Added in v.101

  ViewVC Help
Powered by ViewVC 1.1.26