/[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 25 by matty, Sat Jan 6 03:47:04 2001 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    static void
104    translate8(uint8 * data, uint8 * out, uint8 * end)
105    {
106            while (out < end)
107                    *(out++) = (uint8) colmap[*(data++)];
108    }
109    
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  BOOL
251  ui_create_window(char *title)  ui_init()
252  {  {
253          Screen *screen;          Screen *screen;
         XSetWindowAttributes attribs;  
         unsigned long input_mask;  
         int i;  
   
254          display = XOpenDisplay(NULL);          display = XOpenDisplay(NULL);
255          if (display == NULL)          if (display == NULL)
256          {          {
257                  ERROR("Failed to open display\n");                  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 (i >= screen->ndepths)          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                  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 =          if (attribs.backing_store == NotUseful)
381                  BlackPixel(display, DefaultScreen(display));                  ownbackstore = True;
         attribs.backing_store = Always;  
         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  void
423  ui_destroy_window()  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  void
438  xwin_translate_key(unsigned long key)  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            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          switch (key)  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  static void
489  ui_process_events()  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 =                                  if (IC != NULL)
525                                          xwin_translate_key(event.                                          /* Multi_key compatible version */
526                                                             xkey.keycode);                                  {
527                                  if (scancode == 0)                                          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 =  
565                                          xwin_translate_key(event.                                  if (tr.scancode == 0)
                                                            xkey.keycode);  
                                 if (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 =                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
576                                          xwin_translate_mouse(event.                                             ksname));
                                                              xbutton.button);  
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 =                                  button = xkeymap_translate_button(xevent.xbutton.button);
                                         xwin_translate_mouse(event.  
                                                              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
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    
# Line 217  ui_move_pointer(int x, int y) Line 674  ui_move_pointer(int x, int y)
674  }  }
675    
676  HBITMAP  HBITMAP
677  ui_create_bitmap(int width, int height, uint8 *data)  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);
         XFree(image);  
689    
690            XFree(image);
691            if (!owncolmap)
692                    xfree(tdata);
693          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
694  }  }
695    
696  void  void
697  ui_paint_bitmap(int x, int y, int cx, int cy,  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
                 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    
         image = XCreateImage(display, visual, 8, ZPixmap, 0,  
                              data, width, height, 8, width);  
         XSetFunction(display, gc, GXcopy);  
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
716          XFree(image);          XFree(image);
717            if (!owncolmap)
718                    xfree(tdata);
719  }  }
720    
721  void  void
# Line 253  ui_destroy_bitmap(HBITMAP bmp) Line 725  ui_destroy_bitmap(HBITMAP bmp)
725  }  }
726    
727  HGLYPH  HGLYPH
728  ui_create_glyph(int width, int height, uint8 *data)  ui_create_glyph(int width, int height, uint8 * data)
729  {  {
730          XImage *image;          XImage *image;
731          Pixmap bitmap;          Pixmap bitmap;
# Line 265  ui_create_glyph(int width, int height, u Line 737  ui_create_glyph(int width, int height, u
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          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
743          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
744          XInitImage(image);          XInitImage(image);
745    
         XSetFunction(display, gc, GXcopy);  
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    
# Line 285  ui_destroy_glyph(HGLYPH glyph) Line 756  ui_destroy_glyph(HGLYPH glyph)
756          XFreePixmap(display, (Pixmap) glyph);          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
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  HCOLOURMAP
849  ui_create_colourmap(COLOURMAP *colours)  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                  xentry->pixel = i;                  xcolours = xmalloc(sizeof(XColor) * ncolours);
860                  xentry->red = entry->red << 8;                  for (i = 0; i < ncolours; i++)
861                  xentry->blue = entry->blue << 8;                  {
862                  xentry->green = entry->green << 8;                          entry = &colours->colours[i];
863                  xentry->flags = DoRed | DoBlue | DoGreen;                          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                    xfree(xcolours);
872                    return (HCOLOURMAP) map;
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          xfree(xcolours);                          /* byte swap here to make translate_image faster */
891          return (HCOLOURMAP) map;                          map[i] = translate_colour(colour);
892                    }
893    
894                    return map;
895            }
896  }  }
897    
898  void  void
899  ui_destroy_colourmap(HCOLOURMAP map)  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  void
908  ui_set_colourmap(HCOLOURMAP map)  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  void
# Line 355  ui_bell() Line 943  ui_bell()
943          XBell(display, 0);          XBell(display, 0);
944  }  }
945    
 static int rop2_map[] = {  
         GXclear,                /* 0 */  
         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(uint8 rop2)  
 {  
         XSetFunction(display, gc, rop2_map[rop2]);  
 }  
   
946  void  void
947  ui_destblt(uint8 opcode,  ui_destblt(uint8 opcode,
948             /* dest */ int x, int y, int cx, int cy)             /* dest */ int x, int y, int cx, int cy)
949  {  {
950          xwin_set_function(opcode);          SET_FUNCTION(opcode);
951            FILL_RECTANGLE(x, y, cx, cy);
952          XFillRectangle(display, wnd, gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
953  }  }
954    
955  void  void
956  ui_patblt(uint8 opcode,  ui_patblt(uint8 opcode,
957            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
958            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
959  {  {
         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                          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                            XSetStipple(display, gc, fill);
981                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
982    
983                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
984    
985                          XSetFillStyle(dpy, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
986                            XSetTSOrigin(display, gc, 0, 0);
987                          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          }          }
993    
994            RESET_FUNCTION(opcode);
995  }  }
996    
997  void  void
# Line 430  ui_screenblt(uint8 opcode, Line 999  ui_screenblt(uint8 opcode,
999               /* dest */ int x, int y, int cx, int cy,               /* dest */ int x, int y, int cx, int cy,
1000               /* src */ int srcx, int srcy)               /* src */ int srcx, int srcy)
1001  {  {
1002          xwin_set_function(opcode);          SET_FUNCTION(opcode);
   
1003          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);          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  void
# Line 440  ui_memblt(uint8 opcode, Line 1011  ui_memblt(uint8 opcode,
1011            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1012            /* src */ HBITMAP src, int srcx, int srcy)            /* src */ HBITMAP src, int srcx, int srcy)
1013  {  {
1014          xwin_set_function(opcode);          SET_FUNCTION(opcode);
   
1015          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          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  void
1022  ui_triblt(uint8 opcode,  ui_triblt(uint8 opcode,
1023            /* dest */ int x, int y, int cx, int cy,            /* dest */ int x, int y, int cx, int cy,
1024            /* src */ HBITMAP src, int srcx, int srcy,            /* src */ HBITMAP src, int srcx, int srcy,
1025            /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* 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. */
# Line 458  ui_triblt(uint8 opcode, Line 1031  ui_triblt(uint8 opcode,
1031          {          {
1032                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1033                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1034                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1035                          break;                          break;
1036    
1037                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1038                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1039                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1040                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1041                                    brush, bgcolour, fgcolour);                          break;
1042    
1043                    case 0xc0:      /* PSa */
1044                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1045                            ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1046                          break;                          break;
1047    
1048                  default:                  default:
1049                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
1050                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1051          }          }
1052  }  }
# Line 479  ui_triblt(uint8 opcode, Line 1054  ui_triblt(uint8 opcode,
1054  void  void
1055  ui_line(uint8 opcode,  ui_line(uint8 opcode,
1056          /* dest */ int startx, int starty, int endx, int endy,          /* dest */ int startx, int starty, int endx, int endy,
1057          /* pen */ PEN *pen)          /* pen */ PEN * pen)
1058  {  {
1059          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1060            SET_FOREGROUND(pen->colour);
         XSetForeground(display, gc, pen->colour);  
1061          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          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  void
# Line 492  ui_rect( Line 1069  ui_rect(
1069                 /* dest */ int x, int y, int cx, int cy,                 /* dest */ int x, int y, int cx, int cy,
1070                 /* brush */ int colour)                 /* brush */ int colour)
1071  {  {
1072          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(colour);
1073            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(display, gc, colour);  
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1074  }  }
1075    
1076  void  void
1077  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
1078                /* dest */ int x, int y, int cx, int cy,                /* dest */ int x, int y, int cx, int cy,
1079                /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,                /* src */ HGLYPH glyph, int srcx, int srcy,
1080                int fgcolour)                int bgcolour, int fgcolour)
1081  {  {
1082          Pixmap pixmap = (Pixmap) glyph;          SET_FOREGROUND(fgcolour);
1083            SET_BACKGROUND(bgcolour);
         xwin_set_function(ROP2_COPY);  
   
         XSetForeground(display, gc, fgcolour);  
1084    
1085          switch (mixmode)          XSetFillStyle(display, gc,
1086          {                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1087                  case MIX_TRANSPARENT:          XSetStipple(display, gc, (Pixmap) glyph);
1088                          XSetStipple(display, gc, pixmap);          XSetTSOrigin(display, gc, x, y);
1089                          XSetFillStyle(display, gc, FillStippled);  
1090                          XSetTSOrigin(display, gc, x, y);          FILL_RECTANGLE(x, y, cx, cy);
1091                          XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1092                          XSetFillStyle(display, gc, FillSolid);          XSetFillStyle(display, gc, FillSolid);
1093                          break;  }
1094    
1095                  case MIX_OPAQUE:  #define DO_GLYPH(ttext,idx) \
1096                          XSetBackground(display, gc, bgcolour);  {\
1097                          XCopyPlane(display, pixmap, wnd, gc,    glyph = cache_get_font (font, ttext[idx]);\
1098                                     srcx, srcy, cx, cy, x, y, 1);    if (!(flags & TEXT2_IMPLICIT_X))\
1099                          break;      {\
1100          xyoffset = ttext[++idx];\
1101                  default:        if ((xyoffset & 0x80))\
1102                          NOTIMP("mix %d\n", mixmode);          {\
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  void
1129  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1130               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
1131               int boxx, int boxy, int boxcx, int boxcy,               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1132               int bgcolour, int fgcolour, uint8 *text, uint8 length)               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)          else if (mixmode == MIX_OPAQUE)
1145          {          {
1146                  ui_rect(clipx, clipy, clipcx, clipcy, bgcolour);                  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 (!(flags & TEXT2_IMPLICIT_X))  
                         x += text[++i];  
   
                 if (glyph != NULL)  
1153                  {                  {
1154                          ui_draw_glyph(mixmode, x + (short) glyph->offset,                          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                                    if (entry != NULL)
1171                                    {
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  void
1204  ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)  ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1205  {  {
1206            Pixmap pix;
1207          XImage *image;          XImage *image;
1208    
1209          image = XGetImage(display, wnd, x, y, cx, cy, 0xffffffff, ZPixmap);          if (ownbackstore)
1210          cache_put_desktop(offset, cx, cy, image->bytes_per_line, image->data);          {
1211          XFree(image->data);                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1212          XFree(image);          }
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);
1225  }  }
1226    
1227  void  void
# Line 588  ui_desktop_restore(uint32 offset, int x, Line 1230  ui_desktop_restore(uint32 offset, int x,
1230          XImage *image;          XImage *image;
1231          uint8 *data;          uint8 *data;
1232    
1233          data = cache_get_desktop(offset, cx, cy);          offset *= bpp / 8;
1234            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, cx);                               (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.25  
changed lines
  Added in v.101

  ViewVC Help
Powered by ViewVC 1.1.26