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

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

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26