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

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

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

revision 10 by matty, Tue Aug 15 10:23:24 2000 UTC revision 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 <X11/Xlib.h>  #include <X11/Xlib.h>
22    #include <X11/Xutil.h>
23  #include <time.h>  #include <time.h>
24    #include <errno.h>
25    #define XK_MISCELLANY
26    #include <X11/keysymdef.h>
27  #include "rdesktop.h"  #include "rdesktop.h"
28    #include "scancodes.h"
29    
30  extern int width;  extern int width;
31  extern int height;  extern int height;
32  extern BOOL motion;  extern BOOL sendmotion;
33    extern BOOL fullscreen;
34    extern BOOL grab_keyboard;
35    extern char title[];
36    
37  static Display *display;  Display *display = NULL;
38    static int x_socket;
39  static Window wnd;  static Window wnd;
40  static GC gc;  static GC gc;
41  static Visual *visual;  static Visual *visual;
42  static XIM IM;  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    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  BOOL ui_create_window(char *title)  static void
104    translate8(uint8 * data, uint8 * out, uint8 * end)
105  {  {
106          Screen *screen;          while (out < end)
107          XSetWindowAttributes attribs;                  *(out++) = (uint8) colmap[*(data++)];
108          unsigned long input_mask;  }
109          int i;  
110    static void
111    translate16(uint8 * data, uint16 * out, uint16 * end)
112    {
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    static void
133    translate32(uint8 * data, uint32 * out, uint32 * end)
134    {
135            while (out < end)
136                    *(out++) = colmap[*(data++)];
137    }
138    
139    static uint8 *
140    translate_image(int width, int height, uint8 * data)
141    {
142            int size = width * height * bpp / 8;
143            uint8 *out = xmalloc(size);
144            uint8 *end = out + size;
145    
146            switch (bpp)
147            {
148                    case 8:
149                            translate8(data, out, end);
150                            break;
151    
152                    case 16:
153                            translate16(data, (uint16 *) out, (uint16 *) end);
154                            break;
155    
156                    case 24:
157                            translate24(data, out, end);
158                            break;
159    
160                    case 32:
161                            translate32(data, (uint32 *) out, (uint32 *) end);
162                            break;
163            }
164    
165            return out;
166    }
167    
168    #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            switch (bpp)
177            {
178                    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 unsigned long
198    init_inputmethod(void)
199    {
200            unsigned long filtered_events = 0;
201    
202            IM = XOpenIM(display, NULL, NULL, NULL);
203            if (IM == NULL)
204            {
205                    error("Failed to open input method\n");
206            }
207    
208            if (IM != NULL)
209            {
210                    /* Must be done after XCreateWindow */
211                    IC = XCreateIC(IM, XNInputStyle,
212                                   (XIMPreeditNothing | XIMStatusNothing),
213                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
214    
215                    if (IC == NULL)
216                    {
217                            error("Failed to create input context\n");
218                            XCloseIM(IM);
219                            IM = NULL;
220                    }
221            }
222    
223            /* 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 void
237    close_inputmethod(void)
238    {
239            if (IC != NULL)
240            {
241                    XDestroyIC(IC);
242                    if (IM != NULL)
243                    {
244                            XCloseIM(IM);
245                            IM = NULL;
246                    }
247            }
248    }
249    
250    BOOL
251    ui_init()
252    {
253            Screen *screen;
254          display = XOpenDisplay(NULL);          display = XOpenDisplay(NULL);
255          if (display == NULL)          if (display == NULL)
256            {
257                    error("Failed to open display\n");
258                  return False;                  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    BOOL
270    ui_create_window_obj(int xpos, int ypos, int width, int height, int valuemask)
271    {
272            XClassHint *classhints;
273            XSizeHints *sizehints;
274            XEvent xevent;
275            Screen *screen;
276    
         /* Check the screen supports 8-bit depth. */  
277          screen = DefaultScreenOfDisplay(display);          screen = DefaultScreenOfDisplay(display);
278          for (i = 0; i < screen->ndepths; i++)  
279                  if (screen->depths[i].depth == 8)          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            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;                          break;
319            }
320    
321            if (ownbackstore)
322                    backstore = XCreatePixmap(display, wnd, width, height, depth);
323    
324          if (i >= screen->ndepths)          /* 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                  ERROR("8-bit depth required (in this version).\n");                  /* 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);                  XCloseDisplay(display);
364                  return False;                  return False;
365          }          }
366    
367          visual = DefaultVisual(display, DefaultScreen(display));          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          attribs.background_pixel = BlackPixel(display, DefaultScreen(display));          if (attribs.backing_store == NotUseful)
381          attribs.backing_store = Always;                  ownbackstore = True;
         wnd = XCreateWindow(display, DefaultRootWindow(display),  
                         0, 0, width, height, 0, 8, InputOutput, visual,  
                         CWBackingStore | CWBackPixel, &attribs);  
382    
383          XStoreName(display, wnd, title);          dpy_width = WidthOfScreen(screen);
384          XMapWindow(display, wnd);          dpy_height = HeightOfScreen(screen);
385    
386          input_mask  = KeyPressMask | KeyReleaseMask;          if (fullscreen)
387          input_mask |= ButtonPressMask | ButtonReleaseMask;          {
388          if (motion)                  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;                  input_mask |= PointerMotionMask;
407    
408          XSelectInput(display, wnd, input_mask);          if (ownbackstore)
409          gc = XCreateGC(display, wnd, 0, NULL);                  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    
         IM = XOpenIM(display, NULL, NULL, NULL);  
419          return True;          return True;
420  }  }
421    
422  void ui_destroy_window()  void
423    ui_destroy_window()
424  {  {
425          XCloseIM(IM);          if (ownbackstore)
426                    XFreePixmap(display, backstore);
427    
428          XFreeGC(display, gc);          XFreeGC(display, gc);
429    
430            close_inputmethod();
431    
432          XDestroyWindow(display, wnd);          XDestroyWindow(display, wnd);
433          XCloseDisplay(display);          XCloseDisplay(display);
434            display = NULL;
435  }  }
436    
437  static uint8 xwin_translate_key(unsigned long key)  void
438    reset_keys()
439  {  {
440          DEBUG("KEY(code=0x%lx)\n", key);          /* reset keys */
441            uint32 ev_time;
442          if ((key > 8) && (key <= 0x60))          ev_time = time(NULL);
443                  return (key - 8);          rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
444            rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
445          switch (key)          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                  case 0x62: /* left arrow */                  attribs.override_redirect = True;
470                          return 0x48;                  ui_create_window_obj(0, 0, dpy_width, dpy_height,
471                  case 0x64: /* up arrow */                                       CWBackingStore | CWBackPixel | CWOverrideRedirect);
                         return 0x4b;  
                 case 0x66: /* down arrow */  
                         return 0x4d;  
                 case 0x68: /* right arrow */  
                         return 0x50;  
                 case 0x73: /* Windows key */  
                         DEBUG("CHECKPOINT\n");  
472          }          }
473            else
         return 0;  
 }  
   
 static uint16 xwin_translate_mouse(unsigned long button)  
 {  
         switch (button)  
474          {          {
475                  case Button1: /* left */                  attribs.override_redirect = False;
476                          return MOUSE_FLAG_BUTTON1;                  ui_create_window_obj(0, 0, width, height, CWBackingStore | CWBackPixel);
                 case Button2: /* middle */  
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3: /* right */  
                         return MOUSE_FLAG_BUTTON2;  
477          }          }
478            ui_set_cursor(cache_get_cursor(0));
479          return 0;          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  void ui_process_events()  static void
489    xwin_process_events()
490  {  {
491          XEvent event;          XEvent xevent;
         uint8 scancode;  
         uint16 button;  
         uint32 ev_time;  
492    
493          if (display == NULL)          KeySym keysym;
494                  return;          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 (XCheckWindowEvent(display, wnd, 0xffffffff, &event))          while (XCheckMaskEvent(display, ~0, &xevent))
511          {          {
512                    if (enable_compose && (XFilterEvent(&xevent, None) == True))
513                    {
514                            DEBUG_KBD(("Filtering event\n"));
515                            continue;
516                    }
517    
518                  ev_time = time(NULL);                  ev_time = time(NULL);
519                    flags = 0;
520    
521                  switch (event.type)                  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(ev_time, 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(ev_time, 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(ev_time, 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(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
600                                                  button,                                                 flags | button, xevent.xbutton.x, xevent.xbutton.y);
                                                 event.xbutton.x,  
                                                 event.xbutton.y);  
601                                  break;                                  break;
602    
603                          case MotionNotify:                          case MotionNotify:
604                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
605                                                  MOUSE_FLAG_MOVE,                                                 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
606                                                  event.xmotion.x,                                  break;
607                                                  event.xmotion.y);  
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 ui_move_pointer(int x, int y)  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
671    ui_move_pointer(int x, int y)
672  {  {
673          XWarpPointer(display, 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(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          bitmap = XCreatePixmap(display, wnd, width, height, 8);          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    
         image = XCreateImage(display, visual, 8, ZPixmap, 0,  
                                 data, width, height, 8, width);  
         XSetFunction(display, gc, GXcopy);  
688          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
689    
690          XFree(image);          XFree(image);
691                    if (!owncolmap)
692          return (HBITMAP)bitmap;                  xfree(tdata);
693            return (HBITMAP) bitmap;
694  }  }
695    
696  void ui_paint_bitmap(int x, int y, int cx, int cy,  void
697                          int width, int height, uint8 *data)  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
698  {  {
699          XImage *image;          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            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    
716          image = XCreateImage(display, visual, 8, ZPixmap, 0,          XFree(image);
717                                  data, width, height, 8, width);          if (!owncolmap)
718          XSetFunction(display, gc, GXcopy);                  xfree(tdata);
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
         XFree(image);  
719  }  }
720    
721  void ui_destroy_bitmap(HBITMAP bmp)  void
722    ui_destroy_bitmap(HBITMAP bmp)
723  {  {
724          XFreePixmap(display, (Pixmap)bmp);          XFreePixmap(display, (Pixmap) bmp);
725  }  }
726    
727  HGLYPH ui_create_glyph(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 243  HGLYPH ui_create_glyph(int width, int he Line 737  HGLYPH ui_create_glyph(int width, int he
737          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
738          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
739    
740          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
741                                  data, width, height, 8, scanline);                               width, height, 8, scanline);
742          XSetFunction(display, gc, GXcopy);          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);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
747    
748          XFree(image);          XFree(image);
749          XFreeGC(display, gc);          XFreeGC(display, gc);
750                    return (HGLYPH) bitmap;
         return (HGLYPH)bitmap;  
751  }  }
752    
753  void ui_destroy_glyph(HGLYPH glyph)  void
754    ui_destroy_glyph(HGLYPH glyph)
755  {  {
756          XFreePixmap(display, (Pixmap)glyph);          XFreePixmap(display, (Pixmap) glyph);
757  }  }
758    
759  HCOLOURMAP ui_create_colourmap(COLOURMAP *colours)  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
831    ui_set_cursor(HCURSOR cursor)
832    {
833            XDefineCursor(display, wnd, (Cursor) cursor);
834    }
835    
836    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 = xmalloc(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                    for (i = 0; i < ncolours; i++)
881                    {
882                            entry = &colours->colours[i];
883                            MAKE_XCOLOR(&xentry, entry);
884    
885          map = XCreateColormap(display, wnd, visual, AllocAll);                          if (XAllocColor(display, xcolmap, &xentry) != 0)
886          XStoreColors(display, map, xcolours, ncolours);                                  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          xfree(xcolours);                  return map;
895          return (HCOLOURMAP)map;          }
896  }  }
897    
898  void ui_destroy_colourmap(HCOLOURMAP map)  void
899    ui_destroy_colourmap(HCOLOURMAP map)
900  {  {
901          XFreeColormap(display, (Colormap)map);          if (owncolmap)
902                    XFreeColormap(display, (Colormap) map);
903            else
904                    xfree(map);
905  }  }
906    
907  void ui_set_colourmap(HCOLOURMAP map)  void
908    ui_set_colourmap(HCOLOURMAP map)
909  {  {
910          XSetWindowColormap(display, wnd, (Colormap)map);          if (owncolmap)
911                    XSetWindowColormap(display, wnd, (Colormap) map);
912            else
913                    colmap = map;
914  }  }
915    
916  void ui_set_clip(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 306  void ui_set_clip(int x, int y, int cx, i Line 925  void ui_set_clip(int x, int y, int cx, i
925          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
926  }  }
927    
928  void ui_reset_clip()  void
929    ui_reset_clip()
930  {  {
931          XRectangle rect;          XRectangle rect;
932    
# Line 317  void ui_reset_clip() Line 937  void ui_reset_clip()
937          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
938  }  }
939    
940  void ui_bell()  void
941    ui_bell()
942  {  {
943          XBell(display, 0);          XBell(display, 0);
944  }  }
945    
946  static int rop2_map[] = {  void
947          GXclear,        /* 0 */  ui_destblt(uint8 opcode,
948          GXnor,          /* DPon */             /* dest */ int x, int y, int cx, int cy)
949          GXandInverted,  /* DPna */  {
950          GXcopyInverted, /* Pn */          SET_FUNCTION(opcode);
951          GXandReverse,   /* PDna */          FILL_RECTANGLE(x, y, cx, cy);
952          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]);  
953  }  }
954    
955  void ui_destblt(uint8 opcode,  void
956          /* dest */  int x, int y, int cx, int cy)  ui_patblt(uint8 opcode,
957              /* dest */ int x, int y, int cx, int cy,
958              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
959  {  {
         xwin_set_function(opcode);  
   
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
 }  
   
 void ui_patblt(uint8 opcode,  
         /* dest */  int x, int y, int cx, int cy,  
         /* brush */ BRUSH *brush, int bgcolour, int fgcolour)  
 {  
         Display *dpy = display;  
960          Pixmap fill;          Pixmap fill;
961            uint8 i, ipattern[8];
962    
963          xwin_set_function(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, 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(8, 8, brush->pattern);                          for (i = 0; i != 8; i++)
974                                    ipattern[7 - i] = brush->pattern[i];
975                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
976    
977                            SET_FOREGROUND(bgcolour);
978                            SET_BACKGROUND(fgcolour);
979                            XSetFillStyle(display, gc, FillOpaqueStippled);
980                            XSetStipple(display, gc, fill);
981                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
982    
983                          XSetForeground(dpy, gc, fgcolour);                          FILL_RECTANGLE(x, y, cx, cy);
                         XSetBackground(dpy, gc, bgcolour);  
                         XSetFillStyle(dpy, gc, FillOpaqueStippled);  
                         XSetStipple(dpy, gc, fill);  
984    
985                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          XSetFillStyle(display, gc, FillSolid);
986                            XSetTSOrigin(display, gc, 0, 0);
987                          XSetFillStyle(dpy, gc, FillSolid);                          ui_destroy_glyph((HGLYPH) fill);
                         ui_destroy_glyph((HGLYPH)fill);  
988                          break;                          break;
989    
990                  default:                  default:
991                          NOTIMP("brush %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
992          }          }
 }  
   
 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);  
 }  
993    
994  void ui_memblt(uint8 opcode,          RESET_FUNCTION(opcode);
         /* dest */  int x, int y, int cx, int cy,  
         /* src */   HBITMAP src, int srcx, int srcy)  
 {  
         xwin_set_function(opcode);  
   
         XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy,  
                         cx, cy, x, y);  
995  }  }
996    
997  void ui_triblt(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          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)               /* src */ int srcx, int srcy)
1001    {
1002            SET_FUNCTION(opcode);
1003            XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1004            if (ownbackstore)
1005                    XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1006            RESET_FUNCTION(opcode);
1007    }
1008    
1009    void
1010    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 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. */
1029    
1030          switch (opcode)          switch (opcode)
1031          {          {
1032                  case 0xb8: /* PSDPxax */                  case 0x69:      /* PDSxxn */
1033                          ui_patblt(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(ROP2_AND, x, y, cx, cy,  
                                         src, srcx, srcy);  
                         ui_patblt(ROP2_XOR, x, y, cx, cy,  
                                         brush, bgcolour, fgcolour);  
1035                          break;                          break;
1036    
1037                  default:                  case 0xb8:      /* PSDPxax */
1038                          NOTIMP("triblt 0x%x\n", opcode);                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1039                          ui_memblt(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(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);  
1041                          break;                          break;
1042    
1043                  case MIX_OPAQUE:                  case 0xc0:      /* PSa */
1044                          XSetBackground(display, gc, bgcolour);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1045                          XCopyPlane(display, pixmap, 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 %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(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    {
1059            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;          FONTGLYPH *glyph;
1135          int i;          int i, j, xyoffset;
1136            DATABLOB *entry;
1137    
1138            SET_FOREGROUND(bgcolour);
1139    
1140          if (boxcx > 1)          if (boxcx > 1)
1141          {          {
1142                  ui_rect(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(font, text[i]);                  switch (text[i])
   
                 if (glyph != NULL)  
1153                  {                  {
1154                          ui_draw_glyph(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(uint32 offset, 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          STATUS("XGetImage(%p,%x,%d,%d,%d,%d,%x,%d)\n", display, wnd, x, y,          {
1211                  cx, cy, 0xffffffff, ZPixmap);                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1212          image = XGetImage(display, wnd, x, y, cx, cy, 0xffffffff, ZPixmap);          }
1213          cache_put_desktop(offset, scanline*cy, image->data);          else
1214          XFree(image->data);          {
1215          XFree(image);                  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);
1225  }  }
1226    
1227  void ui_desktop_restore(uint32 offset, 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;
         int scanline;  
1231          uint8 *data;          uint8 *data;
1232    
1233          scanline = (cx + 3) & ~3;          offset *= bpp / 8;
1234          data = cache_get_desktop(offset, scanline*cy);          data = cache_get_desktop(offset, cx, cy, bpp / 8);
1235          if (data == NULL)          if (data == NULL)
1236                  return;                  return;
1237    
1238          image = XCreateImage(display, visual, 8, ZPixmap, 0,          image = XCreateImage(display, visual, depth, ZPixmap, 0,
1239                                  data, cx, cy, 32, scanline);                               (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1240          XSetFunction(display, gc, GXcopy);  
1241          XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);          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    
1251          XFree(image);          XFree(image);
1252  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26