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

Legend:
Removed from v.20  
changed lines
  Added in v.196

  ViewVC Help
Powered by ViewVC 1.1.26