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

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

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

revision 9 by matty, Tue Jul 25 12:34:29 2000 UTC revision 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 "includes.h"  #include <X11/Xlib.h>
22    #include <X11/Xutil.h>
23    #include <time.h>
24    #include <errno.h>
25    #define XK_MISCELLANY
26    #include <X11/keysymdef.h>
27    #include "rdesktop.h"
28    
29    extern int width;
30    extern int height;
31    extern BOOL sendmotion;
32    extern BOOL fullscreen;
33    
34    Display *display = NULL;
35    static int x_socket;
36    static Window wnd;
37    static GC gc;
38    static Visual *visual;
39    static int depth;
40    static int bpp;
41    
42    /* 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  HWINDOW ui_create_window(HCONN conn, int width, int height)  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
89    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
90    
91    static void
92    translate8(uint8 * data, uint8 * out, uint8 * end)
93  {  {
94          struct window *wnd;          while (out < end)
95          XSetWindowAttributes attribs;                  *(out++) = (uint8) colmap[*(data++)];
96          Display *display;  }
         Visual *visual;  
         Window window;  
         int black;  
         GC gc;  
97    
98          display = XOpenDisplay(NULL);  static void
99          if (display == NULL)  translate16(uint8 * data, uint16 * out, uint16 * end)
100                  return NULL;  {
101            while (out < end)
102                    *(out++) = (uint16) colmap[*(data++)];
103    }
104    
105    /* little endian - conversion happens when colourmap is built */
106    static void
107    translate24(uint8 * data, uint8 * out, uint8 * end)
108    {
109            uint32 value;
110    
111          visual = DefaultVisual(display, DefaultScreen(display));          while (out < end)
112          black = BlackPixel(display, DefaultScreen(display));          {
113                    value = colmap[*(data++)];
114                    *(out++) = value;
115                    *(out++) = value >> 8;
116                    *(out++) = value >> 16;
117            }
118    }
119    
120    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          attribs.background_pixel = black;          switch (bpp)
135          attribs.backing_store = Always;          {
136          window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,                  case 8:
137                          width, height, 0, 8, InputOutput, visual,                          translate8(data, out, end);
138                          CWBackingStore | CWBackPixel, &attribs);                          break;
139    
140          XStoreName(display, window, "rdesktop");                  case 16:
141          XMapWindow(display, window);                          translate16(data, (uint16 *) out, (uint16 *) end);
142          XSelectInput(display, window, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);                          break;
         XSync(display, True);  
143    
144          gc = XCreateGC(display, window, 0, NULL);                  case 24:
145                            translate24(data, out, end);
146                            break;
147    
148          wnd = xmalloc(sizeof(struct window));                  case 32:
149          wnd->conn = conn;                          translate32(data, (uint32 *) out, (uint32 *) end);
150          wnd->width = width;                          break;
151          wnd->height = height;          }
         wnd->display = display;  
         wnd->wnd = window;  
         wnd->gc = gc;  
         wnd->visual = visual;  
152    
153          return wnd;          return out;
154  }  }
155    
156  void ui_destroy_window(HWINDOW wnd)  #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
157    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
158    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
159                            x = (x << 16) | (x >> 16); }
160    
161    static uint32
162    translate_colour(uint32 colour)
163  {  {
164          XFreeGC(wnd->display, wnd->gc);          switch (bpp)
165          XDestroyWindow(wnd->display, wnd->wnd);          {
166          XCloseDisplay(wnd->display);                  case 16:
167                            if (host_be != xserver_be)
168                                    BSWAP16(colour);
169                            break;
170    
171                    case 24:
172                            if (xserver_be)
173                                    BSWAP24(colour);
174                            break;
175    
176                    case 32:
177                            if (host_be != xserver_be)
178                                    BSWAP32(colour);
179                            break;
180            }
181    
182            return colour;
183  }  }
184    
185  static uint8 xwin_translate_key(unsigned long key)  static unsigned long
186    init_inputmethod(void)
187  {  {
188          DEBUG("KEY(code=0x%lx)\n", key);          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 ((key > 8) && (key <= 0x60))                  if (IC == NULL)
204                  return (key - 8);                  {
205                            error("Failed to create input context\n");
206                            XCloseIM(IM);
207                            IM = NULL;
208                    }
209            }
210    
211          switch (key)          /* For correct Multi_key/Compose processing, I guess.
212               It seems to work alright anyway, though. */
213            if (IC != NULL)
214          {          {
215                  case 0x62: /* left arrow */                  if (XGetICValues(IC, XNFilterEvents, &filtered_events, NULL)
216                          return 0x48;                      != NULL)
217                  case 0x64: /* up arrow */                  {
218                          return 0x4b;                          error("Failed to obtain XNFilterEvents value from IC\n");
219                  case 0x66: /* down arrow */                          filtered_events = 0;
220                          return 0x4d;                  }
                 case 0x68: /* right arrow */  
                         return 0x50;  
                 case 0x73: /* Windows key */  
                         DEBUG("CHECKPOINT\n");  
221          }          }
222            return filtered_events;
223    }
224    
225          return 0;  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  static uint16 xwin_translate_mouse(unsigned long button)  
240    BOOL
241    ui_create_window(char *title)
242  {  {
243          switch (button)          XSetWindowAttributes attribs;
244            XClassHint *classhints;
245            XSizeHints *sizehints;
246            unsigned long input_mask;
247            XPixmapFormatValues *pfm;
248            Screen *screen;
249            uint16 test;
250            int i;
251            unsigned long filtered_events;
252    
253            display = XOpenDisplay(NULL);
254    
255            if (display == NULL)
256          {          {
257                  case Button1: /* left */                  error("Failed to open display\n");
258                          return MOUSE_FLAG_BUTTON1;                  return False;
                 case Button2: /* middle */  
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3: /* right */  
                         return MOUSE_FLAG_BUTTON2;  
259          }          }
260    
261          return 0;          x_socket = ConnectionNumber(display);
262            screen = DefaultScreenOfDisplay(display);
263            visual = DefaultVisualOfScreen(screen);
264            depth = DefaultDepthOfScreen(screen);
265    
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 (bpp < 8)
283            {
284                    error("Less than 8 bpp not currently supported.\n");
285                    XCloseDisplay(display);
286                    return False;
287            }
288    
289            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            if (attribs.backing_store == NotUseful)
303                    ownbackstore = True;
304    
305            if (fullscreen)
306            {
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);
325    
326            classhints = XAllocClassHint();
327            if (classhints != NULL)
328            {
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;
351    
352            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);
360    
361            if (ownbackstore)
362                    backstore = XCreatePixmap(display, wnd, width, height, depth);
363    
364            XMapWindow(display, wnd);
365    
366            return True;
367  }  }
368    
369  void ui_process_events(HWINDOW wnd, HCONN conn)  void
370    ui_destroy_window()
371  {  {
372          XEvent event;          if (ownbackstore)
373          uint8 scancode;                  XFreePixmap(display, backstore);
         uint16 button;  
374    
375          if (wnd == NULL)          XFreeGC(display, gc);
                 return;  
376    
377          while (XCheckWindowEvent(wnd->display, wnd->wnd, 0xffffffff, &event))          close_inputmethod();
378    
379            XDestroyWindow(display, wnd);
380            XCloseDisplay(display);
381            display = NULL;
382    }
383    
384    static void
385    xwin_process_events()
386    {
387            XEvent xevent;
388    
389            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                    if (xevent.xmapping.request == MappingKeyboard
402                        || xevent.xmapping.request == MappingModifier)
403                            XRefreshKeyboardMapping(&xevent.xmapping);
404            }
405    
406            while (XCheckMaskEvent(display, ~0, &xevent))
407          {          {
408                  switch (event.type)                  if (XFilterEvent(&xevent, None) == True)
409                    {
410                            DEBUG_KBD("Filtering event\n");
411                            continue;
412                    }
413    
414                    ev_time = time(NULL);
415                    flags = 0;
416    
417                    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(conn, 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(conn, 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;
481    
482                                    tr = xkeymap_translate_key(keysym,
483                                                               xevent.xkey.
484                                                               keycode,
485                                                               xevent.xkey.state);
486    
487                                    if (tr.scancode == 0)
488                                          break;                                          break;
489    
490                                  rdp_send_input(conn, RDP_INPUT_MOUSE,                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE,
491                                                  button | MOUSE_FLAG_DOWN,                                                    tr.scancode);
                                                 event.xbutton.x,  
                                                 event.xbutton.y);  
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(conn, 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;
510    
511                            case MotionNotify:
512                                    rdp_send_input(ev_time, RDP_INPUT_MOUSE,
513                                                   MOUSE_FLAG_MOVE,
514                                                   xevent.xmotion.x,
515                                                   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(HWINDOW wnd, int x, int y)  void
575    ui_move_pointer(int x, int y)
576  {  {
577          XWarpPointer(wnd->display, wnd->wnd, 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(HWINDOW wnd, 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            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    
592            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
593    
594            XFree(image);
595            if (!owncolmap)
596                    xfree(tdata);
597            return (HBITMAP) bitmap;
598    }
599    
600    void
601    ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height,
602                    uint8 * data)
603    {
604            XImage *image;
605            uint8 *tdata;
606    
607            tdata = (owncolmap ? data : translate_image(width, height, data));
608            image = XCreateImage(display, visual, depth, ZPixmap, 0, tdata, width,
609                                 height, 8, 0);
610    
611          bitmap = XCreatePixmap(wnd->display, wnd->wnd, width, height, 8);          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    
         image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,  
                                 data, width, height, 8, width);  
         XSetFunction(wnd->display, wnd->gc, GXcopy);  
         XPutImage(wnd->display, bitmap, wnd->gc, image, 0, 0, 0, 0,  
                         width, height);  
621          XFree(image);          XFree(image);
622                    if (!owncolmap)
623          return (HBITMAP)bitmap;                  xfree(tdata);
624  }  }
625    
626  void ui_destroy_bitmap(HWINDOW wnd, HBITMAP bmp)  void
627    ui_destroy_bitmap(HBITMAP bmp)
628  {  {
629          XFreePixmap(wnd->display, (Pixmap)bmp);          XFreePixmap(display, (Pixmap) bmp);
630  }  }
631    
632  HGLYPH ui_create_glyph(HWINDOW wnd, 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 201  HGLYPH ui_create_glyph(HWINDOW wnd, int Line 639  HGLYPH ui_create_glyph(HWINDOW wnd, int
639    
640          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
641    
642          bitmap = XCreatePixmap(wnd->display, wnd->wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
643          gc = XCreateGC(wnd->display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
644    
645            image = XCreateImage(display, visual, 1, ZPixmap, 0, data, width,
646                                 height, 8, scanline);
647            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);
652    
         image = XCreateImage(wnd->display, wnd->visual, 1, ZPixmap, 0,  
                                 data, width, height, 8, scanline);  
         XSetFunction(wnd->display, wnd->gc, GXcopy);  
         XPutImage(wnd->display, bitmap, gc, image, 0, 0, 0, 0, width, height);  
653          XFree(image);          XFree(image);
654          XFreeGC(wnd->display, gc);          XFreeGC(display, gc);
655                    return (HGLYPH) bitmap;
         return (HGLYPH)bitmap;  
656  }  }
657    
658  void ui_destroy_glyph(HWINDOW wnd, HGLYPH glyph)  void
659    ui_destroy_glyph(HGLYPH glyph)
660  {  {
661          XFreePixmap(wnd->display, (Pixmap)glyph);          XFreePixmap(display, (Pixmap) glyph);
662  }  }
663    
664  HCOLOURMAP ui_create_colourmap(HWINDOW wnd, COLOURMAP *colours)  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
736    ui_set_cursor(HCURSOR cursor)
737    {
738            XDefineCursor(display, wnd, (Cursor) cursor);
739    }
740    
741    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 = malloc(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          map = XCreateColormap(wnd->display, wnd->wnd, wnd->visual, AllocAll);                          if (XAllocColor(display, xcolmap, &xentry) != 0)
791          XStoreColors(wnd->display, map, xcolours, ncolours);                                  colour = xentry.pixel;
792                            else
793                                    colour = white;
794    
795                            /* byte swap here to make translate_image faster */
796                            map[i] = translate_colour(colour);
797                    }
798    
799          free(xcolours);                  return map;
800          return (HCOLOURMAP)map;          }
801  }  }
802    
803  void ui_destroy_colourmap(HWINDOW wnd, HCOLOURMAP map)  void
804    ui_destroy_colourmap(HCOLOURMAP map)
805  {  {
806          XFreeColormap(wnd->display, (Colormap)map);          if (owncolmap)
807                    XFreeColormap(display, (Colormap) map);
808            else
809                    xfree(map);
810  }  }
811    
812  void ui_set_colourmap(HWINDOW wnd, HCOLOURMAP map)  void
813    ui_set_colourmap(HCOLOURMAP map)
814  {  {
815          XSetWindowColormap(wnd->display, wnd->wnd, (Colormap)map);          if (owncolmap)
816                    XSetWindowColormap(display, wnd, (Colormap) map);
817            else
818                    colmap = map;
819  }  }
820    
821  void ui_set_clip(HWINDOW wnd, 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 264  void ui_set_clip(HWINDOW wnd, int x, int Line 827  void ui_set_clip(HWINDOW wnd, int x, int
827          rect.y = y;          rect.y = y;
828          rect.width = cx;          rect.width = cx;
829          rect.height = cy;          rect.height = cy;
830          XSetClipRectangles(wnd->display, wnd->gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
831  }  }
832    
833  void ui_reset_clip(HWINDOW wnd)  void
834    ui_reset_clip()
835  {  {
836          XRectangle rect;          XRectangle rect;
837    
838          rect.x = 0;          rect.x = 0;
839          rect.y = 0;          rect.y = 0;
840          rect.width = wnd->width;          rect.width = width;
841          rect.height = wnd->height;          rect.height = height;
842          XSetClipRectangles(wnd->display, wnd->gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
843  }  }
844    
845  static int rop2_map[] = {  void
846          GXclear,        /* 0 */  ui_bell()
         GXnor,          /* DPon */  
         GXandInverted,  /* DPna */  
         GXcopyInverted, /* Pn */  
         GXandReverse,   /* PDna */  
         GXinvert,       /* Dn */  
         GXxor,          /* DPx */  
         GXnand,         /* DPan */  
         GXand,          /* DPa */  
         GXequiv,        /* DPxn */  
         GXnoop,         /* D */  
         GXorInverted,   /* DPno */  
         GXcopy,         /* P */  
         GXorReverse,    /* PDno */  
         GXor,           /* DPo */  
         GXset           /* 1 */  
 };  
   
 static void xwin_set_function(HWINDOW wnd, uint8 rop2)  
847  {  {
848          XSetFunction(wnd->display, wnd->gc, rop2_map[rop2]);          XBell(display, 0);
849  }  }
850    
851  void ui_destblt(HWINDOW wnd, uint8 opcode,  void
852          /* dest */  int x, int y, int cx, int cy)  ui_destblt(uint8 opcode,
853               /* dest */ int x, int y, int cx, int cy)
854  {  {
855          xwin_set_function(wnd, opcode);          SET_FUNCTION(opcode);
856            FILL_RECTANGLE(x, y, cx, cy);
857          XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
858  }  }
859    
860  void ui_patblt(HWINDOW wnd, uint8 opcode,  void
861          /* dest */  int x, int y, int cx, int cy,  ui_patblt(uint8 opcode,
862          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* dest */ int x, int y, int cx, int cy,
863              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
864  {  {
         Display *dpy = wnd->display;  
         GC gc = wnd->gc;  
865          Pixmap fill;          Pixmap fill;
866            uint8 i, ipattern[8];
867    
868          xwin_set_function(wnd, 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->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(wnd, 8, 8, brush->pattern);                          for (i = 0; i != 8; i++)
879                                    ipattern[7 - i] = brush->pattern[i];
880                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
881    
882                            SET_FOREGROUND(bgcolour);
883                            SET_BACKGROUND(fgcolour);
884                            XSetFillStyle(display, gc, FillOpaqueStippled);
885                            XSetStipple(display, gc, fill);
886                            XSetTSOrigin(display, gc, brush->xorigin,
887                                         brush->yorigin);
888    
889                          XSetForeground(dpy, gc, fgcolour);                          FILL_RECTANGLE(x, y, cx, cy);
                         XSetBackground(dpy, gc, bgcolour);  
                         XSetFillStyle(dpy, gc, FillOpaqueStippled);  
                         XSetStipple(dpy, gc, fill);  
890    
891                          XFillRectangle(dpy, wnd->wnd, gc, x, y, cx, cy);                          XSetFillStyle(display, gc, FillSolid);
892                            ui_destroy_glyph((HGLYPH) fill);
                         XSetFillStyle(dpy, gc, FillSolid);  
                         ui_destroy_glyph(wnd, (HGLYPH)fill);  
893                          break;                          break;
894    
895                  default:                  default:
896                          NOTIMP("brush style %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
897          }          }
 }  
   
 void ui_screenblt(HWINDOW wnd, uint8 opcode,  
                 /* dest */ int x, int y, int cx, int cy,  
                 /* src */  int srcx, int srcy)  
 {  
         xwin_set_function(wnd, opcode);  
   
         XCopyArea(wnd->display, wnd->wnd, wnd->wnd, wnd->gc, srcx, srcy,  
                         cx, cy, x, y);  
 }  
   
 void ui_memblt(HWINDOW wnd, uint8 opcode,  
         /* dest */  int x, int y, int cx, int cy,  
         /* src */   HBITMAP src, int srcx, int srcy)  
 {  
         xwin_set_function(wnd, opcode);  
898    
899          XCopyArea(wnd->display, (Pixmap)src, wnd->wnd, wnd->gc, srcx, srcy,          RESET_FUNCTION(opcode);
                         cx, cy, x, y);  
900  }  }
901    
902  void ui_triblt(HWINDOW wnd, 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 an efficient way of doing that 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(wnd, 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(wnd, ROP2_AND, x, y, cx, cy,                                    fgcolour);
                                         src, srcx, srcy);  
                         ui_patblt(wnd, ROP2_XOR, x, y, cx, cy,  
                                         brush, bgcolour, fgcolour);  
943                          break;                          break;
944    
945                  default:                  case 0xb8:      /* PSDPxax */
946                          NOTIMP("triblt opcode 0x%x\n", opcode);                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour,
947                          ui_memblt(wnd, 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(HWINDOW wnd, uint8 opcode,  
         /* dest */  int startx, int starty, int endx, int endy,  
         /* pen */   PEN *pen)  
 {  
         xwin_set_function(wnd, opcode);  
   
         XSetForeground(wnd->display, wnd->gc, pen->colour);  
         XDrawLine(wnd->display, wnd->wnd, wnd->gc, startx, starty, endx, endy);  
 }  
   
 void ui_rect(HWINDOW wnd,  
         /* dest */  int x, int y, int cx, int cy,  
         /* brush */ int colour)  
 {  
         xwin_set_function(wnd, ROP2_COPY);  
   
         XSetForeground(wnd->display, wnd->gc, colour);  
         XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, cx, cy);  
 }  
   
 void ui_draw_glyph(HWINDOW wnd, int mixmode,  
         /* dest */ int x, int y, int cx, int cy,  
         /* src */  HGLYPH glyph, int srcx, int srcy, int bgcolour, int fgcolour)  
 {  
         Pixmap pixmap = (Pixmap)glyph;  
   
         xwin_set_function(wnd, ROP2_COPY);  
   
         XSetForeground(wnd->display, wnd->gc, fgcolour);  
   
         switch (mixmode)  
         {  
                 case MIX_TRANSPARENT:  
                         XSetStipple(wnd->display, wnd->gc, pixmap);  
                         XSetFillStyle(wnd->display, wnd->gc, FillStippled);  
                         XSetTSOrigin(wnd->display, wnd->gc, x, y);  
                         XFillRectangle(wnd->display, wnd->wnd, wnd->gc,  
                                         x, y, cx, cy);  
                         XSetFillStyle(wnd->display, wnd->gc, FillSolid);  
951                          break;                          break;
952    
953                  case MIX_OPAQUE:                  case 0xc0:      /* PSa */
954                          XSetBackground(wnd->display, wnd->gc, bgcolour);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
955                          XCopyPlane(wnd->display, pixmap, wnd->wnd, 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 mode %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(HWINDOW wnd, 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          FONT_GLYPH *glyph;  {
970          int i;          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;
1046            int i, j, xyoffset;
1047            DATABLOB *entry;
1048    
1049            SET_FOREGROUND(bgcolour);
1050    
1051          if (boxcx > 1)          if (boxcx > 1)
1052          {          {
1053                  ui_rect(wnd, 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(wnd->conn, font, text[i]);                  switch (text[i])
   
                 if (glyph != NULL)  
1064                  {                  {
1065                          ui_draw_glyph(wnd, 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(HWINDOW wnd, uint8 *data, 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          image = XGetImage(wnd->display, wnd->wnd, x, y, cx, cy,          {
1126                                  0xffffffff, ZPixmap);                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
1127          memcpy(data, image->data, scanline*cy);                                    ZPixmap);
1128            }
1129            else
1130            {
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);          XDestroyImage(image);
1143  }  }
1144    
1145  void ui_desktop_restore(HWINDOW wnd, uint8 *data, 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;
1149          int scanline;          uint8 *data;
1150    
1151            offset *= bpp / 8;
1152            data = cache_get_desktop(offset, cx, cy, bpp / 8);
1153            if (data == NULL)
1154                    return;
1155    
1156            image = XCreateImage(display, visual, depth, ZPixmap, 0, data, cx, cy,
1157                                 BitmapPad(display), cx * bpp / 8);
1158    
1159            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    
         scanline = (cx + 3) & ~3;  
         image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,  
                                 data, cx, cy, 32, scanline);  
         XSetFunction(wnd->display, wnd->gc, GXcopy);  
         XPutImage(wnd->display, wnd->wnd, wnd->gc, image, 0, 0, x, y, cx, cy);  
1169          XFree(image);          XFree(image);
1170  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26