/[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 33 by matty, Sat Sep 15 12:34:34 2001 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-Windows
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
# Line 19  Line 19 
19  */  */
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22    #include <X11/Xutil.h>
23  #include <time.h>  #include <time.h>
24    #include <errno.h>
25  #include "rdesktop.h"  #include "rdesktop.h"
26    
27  extern int width;  extern int width;
28  extern int height;  extern int height;
29  extern BOOL motion;  extern BOOL sendmotion;
30    extern BOOL fullscreen;
31    
32  static Display *display;  static Display *display;
33    static int x_socket;
34  static Window wnd;  static Window wnd;
35  static GC gc;  static GC gc;
36  static Visual *visual;  static Visual *visual;
37  static XIM IM;  static int depth;
38    static int bpp;
39    
40  BOOL ui_create_window(char *title)  /* endianness */
41    static BOOL host_be;
42    static BOOL xserver_be;
43    
44    /* software backing store */
45    static BOOL ownbackstore;
46    static Pixmap backstore;
47    
48    #define FILL_RECTANGLE(x,y,cx,cy)\
49    { \
50            XFillRectangle(display, wnd, gc, x, y, cx, cy); \
51            if (ownbackstore) \
52                    XFillRectangle(display, backstore, gc, x, y, cx, cy); \
53    }
54    
55    /* colour maps */
56    static BOOL owncolmap;
57    static Colormap xcolmap;
58    static uint32 white;
59    static uint32 *colmap;
60    
61    #define TRANSLATE(col)          ( owncolmap ? col : translate_colour(colmap[col]) )
62    #define SET_FOREGROUND(col)     XSetForeground(display, gc, TRANSLATE(col));
63    #define SET_BACKGROUND(col)     XSetBackground(display, gc, TRANSLATE(col));
64    
65    static int rop2_map[] = {
66            GXclear,                /* 0 */
67            GXnor,                  /* DPon */
68            GXandInverted,          /* DPna */
69            GXcopyInverted,         /* Pn */
70            GXandReverse,           /* PDna */
71            GXinvert,               /* Dn */
72            GXxor,                  /* DPx */
73            GXnand,                 /* DPan */
74            GXand,                  /* DPa */
75            GXequiv,                /* DPxn */
76            GXnoop,                 /* D */
77            GXorInverted,           /* DPno */
78            GXcopy,                 /* P */
79            GXorReverse,            /* PDno */
80            GXor,                   /* DPo */
81            GXset                   /* 1 */
82    };
83    
84    #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
85    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
86    
87    static void
88    translate8(uint8 *data, uint8 *out, uint8 *end)
89    {
90            while (out < end)
91                    *(out++) = (uint8)colmap[*(data++)];
92    }
93    
94    static void
95    translate16(uint8 *data, uint16 *out, uint16 *end)
96    {
97            while (out < end)
98                    *(out++) = (uint16)colmap[*(data++)];
99    }
100    
101    /* little endian - conversion happens when colourmap is built */
102    static void
103    translate24(uint8 *data, uint8 *out, uint8 *end)
104    {
105            uint32 value;
106    
107            while (out < end)
108            {
109                    value = colmap[*(data++)];
110                    *(out++) = value;
111                    *(out++) = value >> 8;
112                    *(out++) = value >> 16;
113            }
114    }
115    
116    static void
117    translate32(uint8 *data, uint32 *out, uint32 *end)
118    {
119            while (out < end)
120                    *(out++) = colmap[*(data++)];
121    }
122    
123    static uint8 *
124    translate_image(int width, int height, uint8 *data)
125    {
126            int size = width * height * bpp/8;
127            uint8 *out = xmalloc(size);
128            uint8 *end = out + size;
129    
130            switch (bpp)
131            {
132                    case 8:
133                            translate8(data, out, end);
134                            break;
135    
136                    case 16:
137                            translate16(data, (uint16 *)out, (uint16 *)end);
138                            break;
139    
140                    case 24:
141                            translate24(data, out, end);
142                            break;
143    
144                    case 32:
145                            translate32(data, (uint32 *)out, (uint32 *)end);
146                            break;
147            }
148    
149            return out;
150    }
151    
152    #define BSWAP16(x) x = (((x & 0xff) << 8) | (x >> 8));
153    #define BSWAP24(x) x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00));
154    #define BSWAP32(x) x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
155                       x = (x << 16) | (x >> 16);
156    
157    static uint32
158    translate_colour(uint32 colour)
159    {
160            switch (bpp)
161            {
162                    case 16:
163                            if (host_be != xserver_be)
164                                    BSWAP16(colour);
165                            break;
166    
167                    case 24:
168                            if (xserver_be)
169                                    BSWAP24(colour);
170                            break;
171    
172                    case 32:
173                            if (host_be != xserver_be)
174                                    BSWAP32(colour);
175                            break;
176            }
177    
178            return colour;
179    }
180    
181    BOOL
182    ui_create_window(char *title)
183  {  {
         Screen *screen;  
184          XSetWindowAttributes attribs;          XSetWindowAttributes attribs;
185            XClassHint *classhints;
186            XSizeHints *sizehints;
187          unsigned long input_mask;          unsigned long input_mask;
188            XPixmapFormatValues *pfm;
189            Screen *screen;
190            uint16 test;
191          int i;          int i;
192    
193          display = XOpenDisplay(NULL);          display = XOpenDisplay(NULL);
194          if (display == NULL)          if (display == NULL)
195            {
196                    error("Failed to open display\n");
197                  return False;                  return False;
198            }
199    
200          /* Check the screen supports 8-bit depth. */          x_socket = ConnectionNumber(display);
201          screen = DefaultScreenOfDisplay(display);          screen = DefaultScreenOfDisplay(display);
202          for (i = 0; i < screen->ndepths; i++)          visual = DefaultVisualOfScreen(screen);
203                  if (screen->depths[i].depth == 8)          depth = DefaultDepthOfScreen(screen);
                         break;  
204    
205          if (i >= screen->ndepths)          pfm = XListPixmapFormats(display, &i);
206            if (pfm != NULL)
207          {          {
208                  ERROR("8-bit depth required (in this version).\n");                  /* Use maximum bpp for this depth - this is generally
209                       desirable, e.g. 24 bits->32 bits. */
210                    while (i--)
211                    {
212                            if ((pfm[i].depth == depth)
213                                && (pfm[i].bits_per_pixel > bpp))
214                            {
215                                    bpp = pfm[i].bits_per_pixel;
216                            }
217                    }
218                    XFree(pfm);
219            }
220    
221            if (bpp < 8)
222            {
223                    error("Less than 8 bpp not currently supported.\n");
224                  XCloseDisplay(display);                  XCloseDisplay(display);
225                  return False;                  return False;
226          }          }
227    
228          visual = DefaultVisual(display, DefaultScreen(display));          if (depth <= 8)
229                    owncolmap = True;
230            else
231                    xcolmap = DefaultColormapOfScreen(screen);
232    
233            test = 1;
234            host_be = !(BOOL)(*(uint8 *)(&test));
235            xserver_be = (ImageByteOrder(display) == MSBFirst);
236    
237            white = WhitePixelOfScreen(screen);
238            attribs.background_pixel = BlackPixelOfScreen(screen);
239            attribs.backing_store = DoesBackingStore(screen);
240    
241            if (attribs.backing_store == NotUseful)
242                    ownbackstore = True;
243    
244            if (fullscreen)
245            {
246                    attribs.override_redirect = True;
247                    width = WidthOfScreen(screen);
248                    height = HeightOfScreen(screen);
249            }
250            else
251            {
252                    attribs.override_redirect = False;
253            }
254    
255            width = (width + 3) & ~3; /* make width a multiple of 32 bits */
256    
257          attribs.background_pixel = BlackPixel(display, DefaultScreen(display));          wnd = XCreateWindow(display, RootWindowOfScreen(screen),
258          attribs.backing_store = Always;                              0, 0, width, height, 0, CopyFromParent,
259          wnd = XCreateWindow(display, DefaultRootWindow(display),                              InputOutput, CopyFromParent,
260                          0, 0, width, height, 0, 8, InputOutput, visual,                              CWBackingStore | CWBackPixel | CWOverrideRedirect,
261                          CWBackingStore | CWBackPixel, &attribs);                              &attribs);
262    
263          XStoreName(display, wnd, title);          XStoreName(display, wnd, title);
         XMapWindow(display, wnd);  
264    
265          input_mask  = KeyPressMask | KeyReleaseMask;          classhints = XAllocClassHint();
266          input_mask |= ButtonPressMask | ButtonReleaseMask;          if (classhints != NULL)
267          if (motion)          {
268                    classhints->res_name = classhints->res_class = "rdesktop";
269                    XSetClassHint(display, wnd, classhints);
270                    XFree(classhints);
271            }
272    
273            sizehints = XAllocSizeHints();
274            if (sizehints)
275            {
276                    sizehints->flags = PMinSize | PMaxSize;
277                    sizehints->min_width = sizehints->max_width = width;
278                    sizehints->min_height = sizehints->max_height = height;
279                    XSetWMNormalHints(display, wnd, sizehints);
280                    XFree(sizehints);
281            }
282    
283            input_mask = KeyPressMask | KeyReleaseMask
284                            | ButtonPressMask | ButtonReleaseMask
285                            | EnterWindowMask | LeaveWindowMask;
286    
287            if (sendmotion)
288                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
289    
290            if (ownbackstore)
291                    input_mask |= ExposureMask;
292    
293          XSelectInput(display, wnd, input_mask);          XSelectInput(display, wnd, input_mask);
294          gc = XCreateGC(display, wnd, 0, NULL);          gc = XCreateGC(display, wnd, 0, NULL);
295    
296          IM = XOpenIM(display, NULL, NULL, NULL);          if (ownbackstore)
297                    backstore = XCreatePixmap(display, wnd, width, height, depth);
298    
299            XMapWindow(display, wnd);
300          return True;          return True;
301  }  }
302    
303  void ui_destroy_window()  void
304    ui_destroy_window()
305  {  {
306          XCloseIM(IM);          if (ownbackstore)
307                    XFreePixmap(display, backstore);
308    
309          XFreeGC(display, gc);          XFreeGC(display, gc);
310          XDestroyWindow(display, wnd);          XDestroyWindow(display, wnd);
311          XCloseDisplay(display);          XCloseDisplay(display);
312            display = NULL;
313  }  }
314    
315  static uint8 xwin_translate_key(unsigned long key)  static uint8
316    xwin_translate_key(unsigned long key)
317  {  {
318          DEBUG("KEY(code=0x%lx)\n", key);          DEBUG(("KEY(code=0x%lx)\n", key));
319    
320          if ((key > 8) && (key <= 0x60))          if ((key > 8) && (key <= 0x60))
321                  return (key - 8);                  return (key - 8);
322    
323          switch (key)          switch (key)
324          {          {
325                  case 0x62: /* left arrow */                  case 0x61:      /* home */
326                          return 0x48;                          return 0x47 | 0x80;
327                  case 0x64: /* up arrow */                  case 0x62:      /* up arrow */
328                          return 0x4b;                          return 0x48 | 0x80;
329                  case 0x66: /* down arrow */                  case 0x63:      /* page up */
330                          return 0x4d;                          return 0x49 | 0x80;
331                  case 0x68: /* right arrow */                  case 0x64:      /* left arrow */
332                          return 0x50;                          return 0x4b | 0x80;
333                  case 0x73: /* Windows key */                  case 0x66:      /* right arrow */
334                          DEBUG("CHECKPOINT\n");                          return 0x4d | 0x80;
335                    case 0x67:      /* end */
336                            return 0x4f | 0x80;
337                    case 0x68:      /* down arrow */
338                            return 0x50 | 0x80;
339                    case 0x69:      /* page down */
340                            return 0x51 | 0x80;
341                    case 0x6a:      /* insert */
342                            return 0x52 | 0x80;
343                    case 0x6b:      /* delete */
344                            return 0x53 | 0x80;
345                    case 0x6c:      /* keypad enter */
346                            return 0x1c | 0x80;
347                    case 0x6d:      /* right ctrl */
348                            return 0x1d | 0x80;
349                    case 0x6f:      /* ctrl - print screen */
350                            return 0x37 | 0x80;
351                    case 0x70:      /* keypad '/' */
352                            return 0x35 | 0x80;
353                    case 0x71:      /* right alt */
354                            return 0x38 | 0x80;
355                    case 0x72:      /* ctrl break */
356                            return 0x46 | 0x80;
357                    case 0x73:      /* left window key */
358                            return 0xff;    /* real scancode is 5b */
359                    case 0x74:      /* right window key */
360                            return 0xff;    /* real scancode is 5c */
361                    case 0x75:      /* menu key */
362                            return 0x5d | 0x80;
363          }          }
364    
365          return 0;          return 0;
366  }  }
367    
368  static uint16 xwin_translate_mouse(unsigned long button)  static uint16
369    xwin_translate_mouse(unsigned long button)
370  {  {
371          switch (button)          switch (button)
372          {          {
373                  case Button1: /* left */                  case Button1:   /* left */
374                          return MOUSE_FLAG_BUTTON1;                          return MOUSE_FLAG_BUTTON1;
375                  case Button2: /* middle */                  case Button2:   /* middle */
376                          return MOUSE_FLAG_BUTTON3;                          return MOUSE_FLAG_BUTTON3;
377                  case Button3: /* right */                  case Button3:   /* right */
378                          return MOUSE_FLAG_BUTTON2;                          return MOUSE_FLAG_BUTTON2;
379          }          }
380    
381          return 0;          return 0;
382  }  }
383    
384  void ui_process_events()  static void
385    xwin_process_events()
386  {  {
387          XEvent event;          XEvent event;
388          uint8 scancode;          uint8 scancode;
# Line 136  void ui_process_events() Line 392  void ui_process_events()
392          if (display == NULL)          if (display == NULL)
393                  return;                  return;
394    
395          while (XCheckWindowEvent(display, wnd, 0xffffffff, &event))          while (XCheckWindowEvent(display, wnd, ~0, &event))
396          {          {
397                  ev_time = time(NULL);                  ev_time = time(NULL);
398    
# Line 148  void ui_process_events() Line 404  void ui_process_events()
404                                          break;                                          break;
405    
406                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,
407                                                  scancode, 0);                                                 scancode, 0);
408                                  break;                                  break;
409    
410                          case KeyRelease:                          case KeyRelease:
# Line 157  void ui_process_events() Line 413  void ui_process_events()
413                                          break;                                          break;
414    
415                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
416                                                  KBD_FLAG_DOWN | KBD_FLAG_UP,                                                 KBD_FLAG_DOWN | KBD_FLAG_UP,
417                                                  scancode, 0);                                                 scancode, 0);
418                                  break;                                  break;
419    
420                          case ButtonPress:                          case ButtonPress:
421                                  button = xwin_translate_mouse(event.xbutton.button);                                  button = xwin_translate_mouse(event.xbutton.button);
   
422                                  if (button == 0)                                  if (button == 0)
423                                          break;                                          break;
424    
425                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
426                                                  button | MOUSE_FLAG_DOWN,                                                 button | MOUSE_FLAG_DOWN,
427                                                  event.xbutton.x,                                                 event.xbutton.x,
428                                                  event.xbutton.y);                                                 event.xbutton.y);
429                                  break;                                  break;
430    
431                          case ButtonRelease:                          case ButtonRelease:
# Line 179  void ui_process_events() Line 434  void ui_process_events()
434                                          break;                                          break;
435    
436                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
437                                                  button,                                                 button,
438                                                  event.xbutton.x,                                                 event.xbutton.x,
439                                                  event.xbutton.y);                                                 event.xbutton.y);
440                                  break;                                  break;
441    
442                          case MotionNotify:                          case MotionNotify:
443                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
444                                                  MOUSE_FLAG_MOVE,                                                 MOUSE_FLAG_MOVE,
445                                                  event.xmotion.x,                                                 event.xmotion.x,
446                                                  event.xmotion.y);                                                 event.xmotion.y);
447                                    break;
448    
449                            case EnterNotify:
450                                    XGrabKeyboard(display, wnd, True, GrabModeAsync,
451                                                  GrabModeAsync, CurrentTime);
452                                    break;
453    
454                            case LeaveNotify:
455                                    XUngrabKeyboard(display, CurrentTime);
456                                    break;
457    
458                            case Expose:
459                                    XCopyArea(display, backstore, wnd, gc,
460                                              event.xexpose.x, event.xexpose.y,
461                                              event.xexpose.width, event.xexpose.height,
462                                              event.xexpose.x, event.xexpose.y);
463                                    break;
464                    }
465            }
466    }
467    
468    void
469    ui_select(int rdp_socket)
470    {
471            int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;
472            fd_set rfds;
473    
474            XFlush(display);
475    
476            FD_ZERO(&rfds);
477    
478            while (True)
479            {
480                    FD_ZERO(&rfds);
481                    FD_SET(rdp_socket, &rfds);
482                    FD_SET(x_socket, &rfds);
483    
484                    switch (select(n, &rfds, NULL, NULL, NULL))
485                    {
486                            case -1:
487                                    error("select: %s\n", strerror(errno));
488    
489                            case 0:
490                                    continue;
491                  }                  }
492    
493                    if (FD_ISSET(x_socket, &rfds))
494                            xwin_process_events();
495    
496                    if (FD_ISSET(rdp_socket, &rfds))
497                            return;
498          }          }
499  }  }
500    
501  void ui_move_pointer(int x, int y)  void
502    ui_move_pointer(int x, int y)
503  {  {
504          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
505  }  }
506    
507  HBITMAP ui_create_bitmap(int width, int height, uint8 *data)  HBITMAP
508    ui_create_bitmap(int width, int height, uint8 *data)
509  {  {
510          XImage *image;          XImage *image;
511          Pixmap bitmap;          Pixmap bitmap;
512            uint8 *tdata;
513    
514          bitmap = XCreatePixmap(display, wnd, width, height, 8);          tdata = (owncolmap ? data : translate_image(width, height, data));
515            bitmap = XCreatePixmap(display, wnd, width, height, depth);
516            image = XCreateImage(display, visual, depth, ZPixmap,
517                                 0, tdata, width, height, 8, 0);
518    
         image = XCreateImage(display, visual, 8, ZPixmap, 0,  
                                 data, width, height, 8, width);  
         XSetFunction(display, gc, GXcopy);  
519          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
520    
521          XFree(image);          XFree(image);
522                    if (!owncolmap)
523          return (HBITMAP)bitmap;                  xfree(tdata);
524            return (HBITMAP) bitmap;
525  }  }
526    
527  void ui_paint_bitmap(int x, int y, int cx, int cy,  void
528                          int width, int height, uint8 *data)  ui_paint_bitmap(int x, int y, int cx, int cy,
529                    int width, int height, uint8 *data)
530  {  {
531          XImage *image;          XImage *image;
532            uint8 *tdata;
533    
534          image = XCreateImage(display, visual, 8, ZPixmap, 0,          tdata = (owncolmap ? data : translate_image(width, height, data));
535                                  data, width, height, 8, width);          image = XCreateImage(display, visual, depth, ZPixmap,
536          XSetFunction(display, gc, GXcopy);                               0, tdata, width, height, 8, 0);
537          XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
538          XFree(image);          if (ownbackstore)
539            {
540                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
541                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
542            }
543            else
544            {
545                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
546            }
547    
548            XFree(image);
549            if (!owncolmap)
550                    xfree(tdata);
551  }  }
552    
553  void ui_destroy_bitmap(HBITMAP bmp)  void
554    ui_destroy_bitmap(HBITMAP bmp)
555  {  {
556          XFreePixmap(display, (Pixmap)bmp);          XFreePixmap(display, (Pixmap)bmp);
557  }  }
558    
559  HGLYPH ui_create_glyph(int width, int height, uint8 *data)  HGLYPH
560    ui_create_glyph(int width, int height, uint8 *data)
561  {  {
562          XImage *image;          XImage *image;
563          Pixmap bitmap;          Pixmap bitmap;
# Line 244  HGLYPH ui_create_glyph(int width, int he Line 570  HGLYPH ui_create_glyph(int width, int he
570          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
571    
572          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(display, visual, 1, ZPixmap, 0,
573                                  data, width, height, 8, scanline);                               data, width, height, 8, scanline);
574          XSetFunction(display, gc, GXcopy);          image->byte_order = MSBFirst;
575            image->bitmap_bit_order = MSBFirst;
576            XInitImage(image);
577    
578          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
579    
580          XFree(image);          XFree(image);
581          XFreeGC(display, gc);          XFreeGC(display, gc);
           
582          return (HGLYPH)bitmap;          return (HGLYPH)bitmap;
583  }  }
584    
585  void ui_destroy_glyph(HGLYPH glyph)  void
586    ui_destroy_glyph(HGLYPH glyph)
587  {  {
588          XFreePixmap(display, (Pixmap)glyph);          XFreePixmap(display, (Pixmap)glyph);
589  }  }
590    
591  HCOLOURMAP ui_create_colourmap(COLOURMAP *colours)  HCURSOR
592    ui_create_cursor(unsigned int x, unsigned int y, int width,
593                     int height, uint8 *andmask, uint8 *xormask)
594    {
595            HGLYPH maskglyph, cursorglyph;
596            XColor bg, fg;
597            Cursor xcursor;
598            uint8 *cursor, *pcursor;
599            uint8 *mask, *pmask;
600            uint8 nextbit;
601            int scanline, offset;
602            int i, j;
603    
604            scanline = (width + 7) / 8;
605            offset = scanline * height;
606    
607            cursor = xmalloc(offset);
608            memset(cursor, 0, offset);
609    
610            mask = xmalloc(offset);
611            memset(mask, 0, offset);
612    
613            /* approximate AND and XOR masks with a monochrome X pointer */
614            for (i = 0; i < height; i++)
615            {
616                    offset -= scanline;
617                    pcursor = &cursor[offset];
618                    pmask = &mask[offset];
619    
620                    for (j = 0; j < scanline; j++)
621                    {
622                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
623                            {
624                                    if (xormask[0] || xormask[1] || xormask[2])
625                                    {
626                                            *pcursor |= (~(*andmask) & nextbit);
627                                            *pmask |= nextbit;
628                                    }
629                                    else
630                                    {
631                                            *pcursor |= ((*andmask) & nextbit);
632                                            *pmask |= (~(*andmask) & nextbit);
633                                    }
634    
635                                    xormask += 3;
636                            }
637    
638                            andmask++;
639                            pcursor++;
640                            pmask++;
641                    }
642            }
643    
644            fg.red = fg.blue = fg.green = 0xffff;
645            bg.red = bg.blue = bg.green = 0x0000;
646            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
647    
648            cursorglyph = ui_create_glyph(width, height, cursor);
649            maskglyph = ui_create_glyph(width, height, mask);
650            
651            xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,
652                                    (Pixmap)maskglyph, &fg, &bg, x, y);
653    
654            ui_destroy_glyph(maskglyph);
655            ui_destroy_glyph(cursorglyph);
656            xfree(mask);
657            xfree(cursor);
658            return (HCURSOR)xcursor;
659    }
660    
661    void
662    ui_set_cursor(HCURSOR cursor)
663    {
664            XDefineCursor(display, wnd, (Cursor)cursor);
665    }
666    
667    void
668    ui_destroy_cursor(HCURSOR cursor)
669    {
670            XFreeCursor(display, (Cursor)cursor);
671    }
672    
673    #define MAKE_XCOLOR(xc,c) \
674                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
675                    (xc)->green = ((c)->green << 8) | (c)->green; \
676                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
677                    (xc)->flags = DoRed | DoGreen | DoBlue;
678    
679    HCOLOURMAP
680    ui_create_colourmap(COLOURMAP *colours)
681  {  {
682          COLOURENTRY *entry;          COLOURENTRY *entry;
         XColor *xcolours, *xentry;  
         Colormap map;  
683          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
684    
685          xcolours = xmalloc(sizeof(XColor) * ncolours);          if (owncolmap)
         for (i = 0; i < ncolours; i++)  
686          {          {
687                  entry = &colours->colours[i];                  XColor *xcolours, *xentry;
688                  xentry = &xcolours[i];                  Colormap map;
689    
690                    xcolours = xmalloc(sizeof(XColor) * ncolours);
691                    for (i = 0; i < ncolours; i++)
692                    {
693                            entry = &colours->colours[i];
694                            xentry = &xcolours[i];
695                            xentry->pixel = i;
696                            MAKE_XCOLOR(xentry, entry);
697                    }
698    
699                    map = XCreateColormap(display, wnd, visual, AllocAll);
700                    XStoreColors(display, map, xcolours, ncolours);
701    
702                  xentry->pixel = i;                  xfree(xcolours);
703                  xentry->red = entry->red << 8;                  return (HCOLOURMAP)map;
                 xentry->blue = entry->blue << 8;  
                 xentry->green = entry->green << 8;  
                 xentry->flags = DoRed | DoBlue | DoGreen;  
704          }          }
705            else
706            {
707                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
708                    XColor xentry;
709                    uint32 colour;
710    
711          map = XCreateColormap(display, wnd, visual, AllocAll);                  for (i = 0; i < ncolours; i++)
712          XStoreColors(display, map, xcolours, ncolours);                  {
713                            entry = &colours->colours[i];
714                            MAKE_XCOLOR(&xentry, entry);
715    
716                            if (XAllocColor(display, xcolmap, &xentry) != 0)
717                                    colour = translate_colour(xentry.pixel);
718                            else
719                                    colour = translate_colour(white);
720    
721          xfree(xcolours);                          /* byte swap here to make translate_image faster */
722          return (HCOLOURMAP)map;                          map[i] = translate_colour(colour);
723                    }
724    
725                    return map;
726            }
727  }  }
728    
729  void ui_destroy_colourmap(HCOLOURMAP map)  void
730    ui_destroy_colourmap(HCOLOURMAP map)
731  {  {
732          XFreeColormap(display, (Colormap)map);          if (owncolmap)
733                    XFreeColormap(display, (Colormap)map);
734            else
735                    xfree(map);
736  }  }
737    
738  void ui_set_colourmap(HCOLOURMAP map)  void
739    ui_set_colourmap(HCOLOURMAP map)
740  {  {
741          XSetWindowColormap(display, wnd, (Colormap)map);          if (owncolmap)
742                    XSetWindowColormap(display, wnd, (Colormap)map);
743            else
744                    colmap = map;
745  }  }
746    
747  void ui_set_clip(int x, int y, int cx, int cy)  void
748    ui_set_clip(int x, int y, int cx, int cy)
749  {  {
750          XRectangle rect;          XRectangle rect;
751    
# Line 306  void ui_set_clip(int x, int y, int cx, i Line 756  void ui_set_clip(int x, int y, int cx, i
756          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
757  }  }
758    
759  void ui_reset_clip()  void
760    ui_reset_clip()
761  {  {
762          XRectangle rect;          XRectangle rect;
763    
# Line 317  void ui_reset_clip() Line 768  void ui_reset_clip()
768          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
769  }  }
770    
771  void ui_bell()  void
772    ui_bell()
773  {  {
774          XBell(display, 0);          XBell(display, 0);
775  }  }
776    
777  static int rop2_map[] = {  void
778          GXclear,        /* 0 */  ui_destblt(uint8 opcode,
779          GXnor,          /* DPon */             /* dest */ int x, int y, int cx, int cy)
780          GXandInverted,  /* DPna */  {
781          GXcopyInverted, /* Pn */          SET_FUNCTION(opcode);
782          GXandReverse,   /* PDna */          FILL_RECTANGLE(x, y, cx, cy);
783          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]);  
784  }  }
785    
786  void ui_destblt(uint8 opcode,  void
787          /* dest */  int x, int y, int cx, int cy)  ui_patblt(uint8 opcode,
788              /* dest */ int x, int y, int cx, int cy,
789              /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
790  {  {
         xwin_set_function(opcode);  
   
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
 }  
   
 void ui_patblt(uint8 opcode,  
         /* dest */  int x, int y, int cx, int cy,  
         /* brush */ BRUSH *brush, int bgcolour, int fgcolour)  
 {  
         Display *dpy = display;  
791          Pixmap fill;          Pixmap fill;
792    
793          xwin_set_function(opcode);          SET_FUNCTION(opcode);
794    
795          switch (brush->style)          switch (brush->style)
796          {          {
797                  case 0: /* Solid */                  case 0: /* Solid */
798                          XSetForeground(dpy, gc, fgcolour);                          SET_FOREGROUND(fgcolour);
799                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
800                          break;                          break;
801    
802                  case 3: /* Pattern */                  case 3: /* Pattern */
803                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);
804    
805                          XSetForeground(dpy, gc, fgcolour);                          SET_FOREGROUND(bgcolour);
806                          XSetBackground(dpy, gc, bgcolour);                          SET_BACKGROUND(fgcolour);
807                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                          XSetFillStyle(display, gc, FillOpaqueStippled);
808                          XSetStipple(dpy, gc, fill);                          XSetStipple(display, gc, fill);
809                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
810    
811                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
812    
813                          XSetFillStyle(dpy, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
814                          ui_destroy_glyph((HGLYPH)fill);                          ui_destroy_glyph((HGLYPH)fill);
815                          break;                          break;
816    
817                  default:                  default:
818                          NOTIMP("brush %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
819          }          }
 }  
820    
821  void ui_screenblt(uint8 opcode,          RESET_FUNCTION(opcode);
                 /* dest */ int x, int y, int cx, int cy,  
                 /* src */  int srcx, int srcy)  
 {  
         xwin_set_function(opcode);  
   
         XCopyArea(display, wnd, wnd, gc, srcx, srcy,  
                         cx, cy, x, y);  
822  }  }
823    
824  void ui_memblt(uint8 opcode,  void
825          /* dest */  int x, int y, int cx, int cy,  ui_screenblt(uint8 opcode,
826          /* src */   HBITMAP src, int srcx, int srcy)               /* dest */ int x, int y, int cx, int cy,
827  {               /* src */ int srcx, int srcy)
828          xwin_set_function(opcode);  {
829            SET_FUNCTION(opcode);
830          XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy,          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
831                          cx, cy, x, y);          if (ownbackstore)
832  }                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,
833                              cx, cy, x, y);
834  void ui_triblt(uint8 opcode,          RESET_FUNCTION(opcode);
835          /* dest */  int x, int y, int cx, int cy,  }
836          /* src */   HBITMAP src, int srcx, int srcy,  
837          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)  void
838    ui_memblt(uint8 opcode,
839              /* dest */ int x, int y, int cx, int cy,
840              /* src */ HBITMAP src, int srcx, int srcy)
841    {
842            SET_FUNCTION(opcode);
843            XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);
844            if (ownbackstore)
845                    XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,
846                              cx, cy, x, y);
847            RESET_FUNCTION(opcode);
848    }
849    
850    void
851    ui_triblt(uint8 opcode,
852              /* dest */ int x, int y, int cx, int cy,
853              /* src */ HBITMAP src, int srcx, int srcy,
854              /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
855  {  {
856          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
857             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. */
858    
859          switch (opcode)          switch (opcode)
860          {          {
861                  case 0xb8: /* PSDPxax */                  case 0x69:      /* PDSxxn */
862                            ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
863                            ui_patblt(ROP2_NXOR, x, y, cx, cy,
864                                      brush, bgcolour, fgcolour);
865                            break;
866    
867                    case 0xb8:      /* PSDPxax */
868                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy,
869                                          brush, bgcolour, fgcolour);                                    brush, bgcolour, fgcolour);
870                          ui_memblt(ROP2_AND, x, y, cx, cy,                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
                                         src, srcx, srcy);  
871                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy,
872                                          brush, bgcolour, fgcolour);                                    brush, bgcolour, fgcolour);
873                            break;
874    
875                    case 0xc0:      /* PSa */
876                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
877                            ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
878                                      fgcolour);
879                          break;                          break;
880    
881                  default:                  default:
882                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
883                          ui_memblt(ROP2_COPY, x, y, cx, cy,                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
                                         brush, bgcolour, fgcolour);  
884          }          }
885  }  }
886    
887  void ui_line(uint8 opcode,  void
888          /* dest */  int startx, int starty, int endx, int endy,  ui_line(uint8 opcode,
889          /* pen */   PEN *pen)          /* dest */ int startx, int starty, int endx, int endy,
890            /* pen */ PEN *pen)
891  {  {
892          xwin_set_function(opcode);          SET_FUNCTION(opcode);
893            SET_FOREGROUND(pen->colour);
         XSetForeground(display, gc, pen->colour);  
894          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(display, wnd, gc, startx, starty, endx, endy);
895            if (ownbackstore)
896                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
897            RESET_FUNCTION(opcode);
898  }  }
899    
900  void ui_rect(  void
901          /* dest */  int x, int y, int cx, int cy,  ui_rect(
902          /* brush */ int colour)                 /* dest */ int x, int y, int cx, int cy,
903                   /* brush */ int colour)
904  {  {
905          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(colour);
906            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(display, gc, colour);  
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
907  }  }
908    
909  void ui_draw_glyph(int mixmode,  void
910          /* dest */ int x, int y, int cx, int cy,  ui_draw_glyph(int mixmode,
911          /* src */  HGLYPH glyph, int srcx, int srcy, int bgcolour, int fgcolour)                /* dest */ int x, int y, int cx, int cy,
912                  /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,
913                  int fgcolour)
914  {  {
915          Pixmap pixmap = (Pixmap)glyph;          SET_FOREGROUND(fgcolour);
916            SET_BACKGROUND(bgcolour);
917    
918          xwin_set_function(ROP2_COPY);          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)
919                          ? FillStippled : FillOpaqueStippled);
920          XSetForeground(display, gc, fgcolour);          XSetStipple(display, gc, (Pixmap)glyph);
921            XSetTSOrigin(display, gc, x, y);
         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);  
                         break;  
922    
923                  case MIX_OPAQUE:          FILL_RECTANGLE(x, y, cx, cy);
                         XSetBackground(display, gc, bgcolour);  
                         XCopyPlane(display, pixmap, wnd, gc,  
                                         srcx, srcy, cx, cy, x, y, 1);  
                         break;  
924    
925                  default:          XSetFillStyle(display, gc, FillSolid);
                         NOTIMP("mix %d\n", mixmode);  
         }  
926  }  }
927    
928  void ui_draw_text(uint8 font, uint8 flags, int mixmode, int x,  void
929                          int y, int boxx, int boxy, int boxcx, int boxcy,  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
930                          int bgcolour, int fgcolour, uint8 *text, uint8 length)               int clipx, int clipy, int clipcx, int clipcy,
931                 int boxx, int boxy, int boxcx, int boxcy,
932                 int bgcolour, int fgcolour, uint8 *text, uint8 length)
933  {  {
934          FONTGLYPH *glyph;          FONTGLYPH *glyph;
935          int i;          int i, offset;
936    
937            SET_FOREGROUND(bgcolour);
938    
939          if (boxcx > 1)          if (boxcx > 1)
940          {          {
941                  ui_rect(boxx, boxy, boxcx, boxcy, bgcolour);                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
942            }
943            else if (mixmode == MIX_OPAQUE)
944            {
945                    FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
946          }          }
947    
948          /* Paint text, character by character */          /* Paint text, character by character */
# Line 504  void ui_draw_text(uint8 font, uint8 flag Line 950  void ui_draw_text(uint8 font, uint8 flag
950          {          {
951                  glyph = cache_get_font(font, text[i]);                  glyph = cache_get_font(font, text[i]);
952    
953                    if (!(flags & TEXT2_IMPLICIT_X))
954                    {
955                            offset = text[++i];
956                            if (offset & 0x80)
957                                    offset = ((offset & 0x7f) << 8) | text[++i];
958    
959                            if (flags & TEXT2_VERTICAL)
960                                    y += offset;
961                            else
962                                    x += offset;
963                    }
964    
965                  if (glyph != NULL)                  if (glyph != NULL)
966                  {                  {
967                          ui_draw_glyph(mixmode, x,                          ui_draw_glyph(mixmode, x + (short) glyph->offset,
968                                          y + (short)glyph->baseline,                                        y + (short) glyph->baseline,
969                                          glyph->width, glyph->height,                                        glyph->width, glyph->height,
970                                          glyph->pixmap, 0, 0,                                        glyph->pixmap, 0, 0,
971                                          bgcolour, fgcolour);                                        bgcolour, fgcolour);
972    
973                          if (flags & TEXT2_IMPLICIT_X)                          if (flags & TEXT2_IMPLICIT_X)
974                                  x += glyph->width;                                  x += glyph->width;
                         else  
                                 x += text[++i];  
975                  }                  }
976          }          }
977  }  }
978    
979  void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)  void
980    ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
981  {  {
982            Pixmap pix;
983          XImage *image;          XImage *image;
         int scanline;  
984    
985          scanline = (cx + 3) & ~3;          if (ownbackstore)
986          STATUS("XGetImage(%p,%x,%d,%d,%d,%d,%x,%d)\n", display, wnd, x, y,          {
987                  cx, cy, 0xffffffff, ZPixmap);                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
988          image = XGetImage(display, wnd, x, y, cx, cy, 0xffffffff, ZPixmap);                                    ZPixmap);
989          cache_put_desktop(offset, scanline*cy, image->data);          }
990          XFree(image->data);          else
991          XFree(image);          {
992                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
993                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
994                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,
995                                      ZPixmap);
996                    XFreePixmap(display, pix);
997            }
998    
999            offset *= bpp/8;
1000            cache_put_desktop(offset, cx, cy, image->bytes_per_line,
1001                              bpp/8, image->data);
1002    
1003            XDestroyImage(image);
1004  }  }
1005    
1006  void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)  void
1007    ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1008  {  {
1009          XImage *image;          XImage *image;
         int scanline;  
1010          uint8 *data;          uint8 *data;
1011    
1012          scanline = (cx + 3) & ~3;          offset *= bpp/8;
1013          data = cache_get_desktop(offset, scanline*cy);          data = cache_get_desktop(offset, cx, cy, bpp/8);
1014          if (data == NULL)          if (data == NULL)
1015                  return;                  return;
1016    
1017          image = XCreateImage(display, visual, 8, ZPixmap, 0,          image = XCreateImage(display, visual, depth, ZPixmap,
1018                                  data, cx, cy, 32, scanline);                               0, data, cx, cy, BitmapPad(display),
1019          XSetFunction(display, gc, GXcopy);                               cx * bpp/8);
1020          XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
1021            if (ownbackstore)
1022            {
1023                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1024                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1025            }
1026            else
1027            {
1028                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1029            }
1030    
1031          XFree(image);          XFree(image);
1032  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26