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

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

  ViewVC Help
Powered by ViewVC 1.1.26