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

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

  ViewVC Help
Powered by ViewVC 1.1.26