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

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

  ViewVC Help
Powered by ViewVC 1.1.26