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

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

  ViewVC Help
Powered by ViewVC 1.1.26