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

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

  ViewVC Help
Powered by ViewVC 1.1.26