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

Legend:
Removed from v.17  
changed lines
  Added in v.38

  ViewVC Help
Powered by ViewVC 1.1.26