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

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

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26