/[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 17 by matty, Thu Sep 28 15:54:11 2000 UTC revision 34 by matty, Sat Sep 15 13:03:35 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);
204                          break;  
205            pfm = XListPixmapFormats(display, &i);
206            if (pfm != NULL)
207            {
208                    /* 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 (i >= screen->ndepths)          if (bpp < 8)
222          {          {
223                  ERROR("8-bit depth required (in this version).\n");                  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            tdata = (owncolmap ? data : translate_image(width, height, data));
535            image = XCreateImage(display, visual, depth, ZPixmap,
536                                 0, tdata, width, height, 8, 0);
537    
538          image = XCreateImage(display, visual, 8, ZPixmap, 0,          if (ownbackstore)
539                                  data, width, height, 8, width);          {
540          XSetFunction(display, gc, GXcopy);                  XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
541          XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);                  XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
542          XFree(image);          }
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                    for (i = 0; i < ncolours; i++)
712                    {
713                            entry = &colours->colours[i];
714                            MAKE_XCOLOR(&xentry, entry);
715    
716          map = XCreateColormap(display, wnd, visual, AllocAll);                          if (XAllocColor(display, xcolmap, &xentry) != 0)
717          XStoreColors(display, map, xcolours, ncolours);                                  colour = xentry.pixel;
718                            else
719                                    colour = white;
720    
721                            /* byte swap here to make translate_image faster */
722                            map[i] = translate_colour(colour);
723                    }
724    
725          xfree(xcolours);                  return map;
726          return (HCOLOURMAP)map;          }
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]);  
 }  
   
 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);  
784  }  }
785    
786  void ui_patblt(uint8 opcode,  void
787          /* dest */  int x, int y, int cx, int cy,  ui_patblt(uint8 opcode,
788          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* dest */ int x, int y, int cx, int cy,
789              /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
790  {  {
         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          }          }
 }  
   
 void ui_screenblt(uint8 opcode,  
                 /* dest */ int x, int y, int cx, int cy,  
                 /* src */  int srcx, int srcy)  
 {  
         xwin_set_function(opcode);  
   
         XCopyArea(display, wnd, wnd, gc, srcx, srcy,  
                         cx, cy, x, y);  
 }  
820    
821  void ui_memblt(uint8 opcode,          RESET_FUNCTION(opcode);
         /* dest */  int x, int y, int cx, int cy,  
         /* src */   HBITMAP src, int srcx, int srcy)  
 {  
         xwin_set_function(opcode);  
   
         XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy,  
                         cx, cy, x, y);  
822  }  }
823    
824  void ui_triblt(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          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)               /* src */ int srcx, int srcy)
828    {
829            SET_FUNCTION(opcode);
830            XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
831            if (ownbackstore)
832                    XCopyArea(display, backstore, backstore, gc, srcx, srcy,
833                              cx, cy, x, y);
834            RESET_FUNCTION(opcode);
835    }
836    
837    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 0x69: /* PDSxxn */                  case 0x69:      /* PDSxxn */
862                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
863                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy,
864                                          brush, bgcolour, fgcolour);                                    brush, bgcolour, fgcolour);
865                          break;                          break;
866    
867                  case 0xb8: /* PSDPxax */                  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, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, 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, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
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            XSetStipple(display, gc, (Pixmap)glyph);
921            XSetTSOrigin(display, gc, x, y);
922    
923          XSetForeground(display, gc, fgcolour);          FILL_RECTANGLE(x, y, cx, cy);
924    
925          switch (mixmode)          XSetFillStyle(display, gc, FillSolid);
         {  
                 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;  
   
                 case MIX_OPAQUE:  
                         XSetBackground(display, gc, bgcolour);  
                         XCopyPlane(display, pixmap, wnd, gc,  
                                         srcx, srcy, cx, cy, x, y, 1);  
                         break;  
   
                 default:  
                         NOTIMP("mix %d\n", mixmode);  
         }  
926  }  }
927    
928  void ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  void
929                          int clipx, int clipy, int clipcx, int clipcy,  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
930                          int boxx, int boxy, int boxcx, int boxcy,               int clipx, int clipy, int clipcx, int clipcy,
931                          int bgcolour, int fgcolour, uint8 *text, uint8 length)               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)          else if (mixmode == MIX_OPAQUE)
944          {          {
945                  ui_rect(clipx, clipy, clipcx, clipcy, bgcolour);                  FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
946          }          }
947    
948          /* Paint text, character by character */          /* Paint text, character by character */
# Line 514  void ui_draw_text(uint8 font, uint8 flag Line 951  void ui_draw_text(uint8 font, uint8 flag
951                  glyph = cache_get_font(font, text[i]);                  glyph = cache_get_font(font, text[i]);
952    
953                  if (!(flags & TEXT2_IMPLICIT_X))                  if (!(flags & TEXT2_IMPLICIT_X))
954                          x += text[++i];                  {
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;
# Line 530  void ui_draw_text(uint8 font, uint8 flag Line 976  void ui_draw_text(uint8 font, uint8 flag
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;
984    
985          image = XGetImage(display, wnd, x, y, cx, cy, 0xffffffff, ZPixmap);          if (ownbackstore)
986          cache_put_desktop(offset, cx, cy, image->bytes_per_line, image->data);          {
987          XFree(image->data);                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
988          XFree(image);                                    ZPixmap);
989            }
990            else
991            {
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;
1010          uint8 *data;          uint8 *data;
1011    
1012          data = cache_get_desktop(offset, cx, cy);          offset *= bpp/8;
1013            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, cx);                               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.17  
changed lines
  Added in v.34

  ViewVC Help
Powered by ViewVC 1.1.26