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

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

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

revision 9 by matty, Tue Jul 25 12:34:29 2000 UTC revision 42 by matthewc, Sun Apr 7 09:42:54 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 18  Line 18 
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include "includes.h"  #include <X11/Xlib.h>
22    #include <X11/Xutil.h>
23    #include <time.h>
24    #include <errno.h>
25    #include "rdesktop.h"
26    
27    extern char keymapname[16];
28    extern int keylayout;
29    extern int width;
30    extern int height;
31    extern BOOL sendmotion;
32    extern BOOL fullscreen;
33    
34    static Display *display;
35    static int x_socket;
36    static Window wnd;
37    static GC gc;
38    static Visual *visual;
39    static int depth;
40    static int bpp;
41    
42    /* endianness */
43    static BOOL host_be;
44    static BOOL xserver_be;
45    
46    /* software backing store */
47    static BOOL ownbackstore;
48    static Pixmap backstore;
49    
50    #define FILL_RECTANGLE(x,y,cx,cy)\
51    { \
52            XFillRectangle(display, wnd, gc, x, y, cx, cy); \
53            if (ownbackstore) \
54                    XFillRectangle(display, backstore, gc, x, y, cx, cy); \
55    }
56    
57    /* colour maps */
58    static BOOL owncolmap;
59    static Colormap xcolmap;
60    static uint32 white;
61    static uint32 *colmap;
62    
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  HWINDOW ui_create_window(HCONN conn, int width, int height)  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          struct window *wnd;          while (out < end)
93          XSetWindowAttributes attribs;                  *(out++) = (uint8)colmap[*(data++)];
94          Display *display;  }
         Visual *visual;  
         Window window;  
         int black;  
         GC gc;  
95    
96          display = XOpenDisplay(NULL);  static void
97          if (display == NULL)  translate16(uint8 *data, uint16 *out, uint16 *end)
98                  return NULL;  {
99            while (out < end)
100                    *(out++) = (uint16)colmap[*(data++)];
101    }
102    
103          visual = DefaultVisual(display, DefaultScreen(display));  /* little endian - conversion happens when colourmap is built */
104          black = BlackPixel(display, DefaultScreen(display));  static void
105    translate24(uint8 *data, uint8 *out, uint8 *end)
106    {
107            uint32 value;
108    
109          attribs.background_pixel = black;          while (out < end)
110          attribs.backing_store = Always;          {
111          window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,                  value = colmap[*(data++)];
112                          width, height, 0, 8, InputOutput, visual,                  *(out++) = value;
113                          CWBackingStore | CWBackPixel, &attribs);                  *(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          XStoreName(display, window, "rdesktop");                  case 16:
139          XMapWindow(display, window);                          translate16(data, (uint16 *)out, (uint16 *)end);
140          XSelectInput(display, window, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);                          break;
         XSync(display, True);  
141    
142          gc = XCreateGC(display, window, 0, NULL);                  case 24:
143                            translate24(data, out, end);
144                            break;
145    
146          wnd = xmalloc(sizeof(struct window));                  case 32:
147          wnd->conn = conn;                          translate32(data, (uint32 *)out, (uint32 *)end);
148          wnd->width = width;                          break;
149          wnd->height = height;          }
         wnd->display = display;  
         wnd->wnd = window;  
         wnd->gc = gc;  
         wnd->visual = visual;  
150    
151          return wnd;          return out;
152  }  }
153    
154  void ui_destroy_window(HWINDOW wnd)  #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          XFreeGC(wnd->display, wnd->gc);          switch (bpp)
163          XDestroyWindow(wnd->display, wnd->wnd);          {
164          XCloseDisplay(wnd->display);                  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  static uint8 xwin_translate_key(unsigned long key)  BOOL
184    ui_create_window(char *title)
185  {  {
186          DEBUG("KEY(code=0x%lx)\n", key);          XSetWindowAttributes attribs;
187            XClassHint *classhints;
188            XSizeHints *sizehints;
189            unsigned long input_mask;
190            XPixmapFormatValues *pfm;
191            Screen *screen;
192            uint16 test;
193            int i;
194    
195          if ((key > 8) && (key <= 0x60))          display = XOpenDisplay(NULL);
196                  return (key - 8);          if (display == NULL)
197            {
198                    error("Failed to open display\n");
199                    return False;
200            }
201    
202            x_socket = ConnectionNumber(display);
203            screen = DefaultScreenOfDisplay(display);
204            visual = DefaultVisualOfScreen(screen);
205            depth = DefaultDepthOfScreen(screen);
206    
207            pfm = XListPixmapFormats(display, &i);
208            if (pfm != NULL)
209            {
210                    /* 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          switch (key)          if (bpp < 8)
224          {          {
225                  case 0x62: /* left arrow */                  error("Less than 8 bpp not currently supported.\n");
226                          return 0x48;                  XCloseDisplay(display);
227                  case 0x64: /* up arrow */                  return False;
                         return 0x4b;  
                 case 0x66: /* down arrow */  
                         return 0x4d;  
                 case 0x68: /* right arrow */  
                         return 0x50;  
                 case 0x73: /* Windows key */  
                         DEBUG("CHECKPOINT\n");  
228          }          }
229    
230          return 0;          if (depth <= 8)
231  }                  owncolmap = True;
232            else
233                    xcolmap = DefaultColormapOfScreen(screen);
234    
235            test = 1;
236            host_be = !(BOOL)(*(uint8 *)(&test));
237            xserver_be = (ImageByteOrder(display) == MSBFirst);
238    
239            white = WhitePixelOfScreen(screen);
240            attribs.background_pixel = BlackPixelOfScreen(screen);
241            attribs.backing_store = DoesBackingStore(screen);
242    
243  static uint16 xwin_translate_mouse(unsigned long button)          if (attribs.backing_store == NotUseful)
244  {                  ownbackstore = True;
245          switch (button)  
246            if (fullscreen)
247            {
248                    attribs.override_redirect = True;
249                    width = WidthOfScreen(screen);
250                    height = HeightOfScreen(screen);
251            }
252            else
253          {          {
254                  case Button1: /* left */                  attribs.override_redirect = False;
                         return MOUSE_FLAG_BUTTON1;  
                 case Button2: /* middle */  
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3: /* right */  
                         return MOUSE_FLAG_BUTTON2;  
255          }          }
256    
257          return 0;          width = (width + 3) & ~3; /* make width a multiple of 32 bits */
258    
259            wnd = XCreateWindow(display, RootWindowOfScreen(screen),
260                                0, 0, width, height, 0, CopyFromParent,
261                                InputOutput, CopyFromParent,
262                                CWBackingStore | CWBackPixel | CWOverrideRedirect,
263                                &attribs);
264    
265            XStoreName(display, wnd, title);
266    
267            classhints = XAllocClassHint();
268            if (classhints != NULL)
269            {
270                    classhints->res_name = classhints->res_class = "rdesktop";
271                    XSetClassHint(display, wnd, classhints);
272                    XFree(classhints);
273            }
274    
275            sizehints = XAllocSizeHints();
276            if (sizehints)
277            {
278                    sizehints->flags = PMinSize | PMaxSize;
279                    sizehints->min_width = sizehints->max_width = width;
280                    sizehints->min_height = sizehints->max_height = height;
281                    XSetWMNormalHints(display, wnd, sizehints);
282                    XFree(sizehints);
283            }
284    
285            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    void
308    ui_destroy_window()
309    {
310            if (ownbackstore)
311                    XFreePixmap(display, backstore);
312    
313            XFreeGC(display, gc);
314            XDestroyWindow(display, wnd);
315            XCloseDisplay(display);
316            display = NULL;
317  }  }
318    
319  void ui_process_events(HWINDOW wnd, HCONN conn)  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;
327    
328          if (wnd == NULL)          if (display == NULL)
329                  return;                  return;
330    
331          while (XCheckWindowEvent(wnd->display, wnd->wnd, 0xffffffff, &event))          while (XCheckMaskEvent(display, ~0, &event))
332          {          {
333                    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(conn, 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(conn, 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(conn, 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(conn, 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;
379    
380                            case MotionNotify:
381                                    rdp_send_input(ev_time, RDP_INPUT_MOUSE,
382                                                   MOUSE_FLAG_MOVE,
383                                                   event.xmotion.x,
384                                                   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(HWINDOW wnd, int x, int y)  void
407    ui_select(int rdp_socket)
408  {  {
409          XWarpPointer(wnd->display, wnd->wnd, wnd->wnd, 0, 0, 0, 0, x, y);          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);
443  }  }
444    
445  HBITMAP ui_create_bitmap(HWINDOW wnd, 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            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    
457          bitmap = XCreatePixmap(wnd->display, wnd->wnd, width, height, 8);          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
458    
         image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,  
                                 data, width, height, 8, width);  
         XSetFunction(wnd->display, wnd->gc, GXcopy);  
         XPutImage(wnd->display, bitmap, wnd->gc, image, 0, 0, 0, 0,  
                         width, height);  
459          XFree(image);          XFree(image);
460                    if (!owncolmap)
461          return (HBITMAP)bitmap;                  xfree(tdata);
462            return (HBITMAP) bitmap;
463  }  }
464    
465  void ui_destroy_bitmap(HWINDOW wnd, HBITMAP bmp)  void
466    ui_paint_bitmap(int x, int y, int cx, int cy,
467                    int width, int height, uint8 *data)
468  {  {
469          XFreePixmap(wnd->display, (Pixmap)bmp);          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            XFree(image);
487            if (!owncolmap)
488                    xfree(tdata);
489    }
490    
491    void
492    ui_destroy_bitmap(HBITMAP bmp)
493    {
494            XFreePixmap(display, (Pixmap)bmp);
495  }  }
496    
497  HGLYPH ui_create_glyph(HWINDOW wnd, 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 201  HGLYPH ui_create_glyph(HWINDOW wnd, int Line 504  HGLYPH ui_create_glyph(HWINDOW wnd, int
504    
505          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
506    
507          bitmap = XCreatePixmap(wnd->display, wnd->wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
508          gc = XCreateGC(wnd->display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
509    
510            image = XCreateImage(display, visual, 1, ZPixmap, 0,
511                                 data, width, height, 8, scanline);
512            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);
517    
         image = XCreateImage(wnd->display, wnd->visual, 1, ZPixmap, 0,  
                                 data, width, height, 8, scanline);  
         XSetFunction(wnd->display, wnd->gc, GXcopy);  
         XPutImage(wnd->display, bitmap, gc, image, 0, 0, 0, 0, width, height);  
518          XFree(image);          XFree(image);
519          XFreeGC(wnd->display, gc);          XFreeGC(display, gc);
           
520          return (HGLYPH)bitmap;          return (HGLYPH)bitmap;
521  }  }
522    
523  void ui_destroy_glyph(HWINDOW wnd, HGLYPH glyph)  void
524    ui_destroy_glyph(HGLYPH glyph)
525    {
526            XFreePixmap(display, (Pixmap)glyph);
527    }
528    
529    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          XFreePixmap(wnd->display, (Pixmap)glyph);          XFreeCursor(display, (Cursor)cursor);
609  }  }
610    
611  HCOLOURMAP ui_create_colourmap(HWINDOW wnd, COLOURMAP *colours)  #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 = malloc(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                  xentry->pixel = i;                  xcolours = xmalloc(sizeof(XColor) * ncolours);
629                  xentry->red = entry->red << 8;                  for (i = 0; i < ncolours; i++)
630                  xentry->blue = entry->blue << 8;                  {
631                  xentry->green = entry->green << 8;                          entry = &colours->colours[i];
632                  xentry->flags = DoRed | DoBlue | DoGreen;                          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                    xfree(xcolours);
641                    return (HCOLOURMAP)map;
642          }          }
643            else
644            {
645                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
646                    XColor xentry;
647                    uint32 colour;
648    
649                    for (i = 0; i < ncolours; i++)
650                    {
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          map = XCreateColormap(wnd->display, wnd->wnd, wnd->visual, AllocAll);                          /* byte swap here to make translate_image faster */
660          XStoreColors(wnd->display, map, xcolours, ncolours);                          map[i] = translate_colour(colour);
661                    }
662    
663          free(xcolours);                  return map;
664          return (HCOLOURMAP)map;          }
665  }  }
666    
667  void ui_destroy_colourmap(HWINDOW wnd, HCOLOURMAP map)  void
668    ui_destroy_colourmap(HCOLOURMAP map)
669  {  {
670          XFreeColormap(wnd->display, (Colormap)map);          if (owncolmap)
671                    XFreeColormap(display, (Colormap)map);
672            else
673                    xfree(map);
674  }  }
675    
676  void ui_set_colourmap(HWINDOW wnd, HCOLOURMAP map)  void
677    ui_set_colourmap(HCOLOURMAP map)
678  {  {
679          XSetWindowColormap(wnd->display, wnd->wnd, (Colormap)map);          if (owncolmap)
680                    XSetWindowColormap(display, wnd, (Colormap)map);
681            else
682                    colmap = map;
683  }  }
684    
685  void ui_set_clip(HWINDOW wnd, 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 264  void ui_set_clip(HWINDOW wnd, int x, int Line 691  void ui_set_clip(HWINDOW wnd, int x, int
691          rect.y = y;          rect.y = y;
692          rect.width = cx;          rect.width = cx;
693          rect.height = cy;          rect.height = cy;
694          XSetClipRectangles(wnd->display, wnd->gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
695  }  }
696    
697  void ui_reset_clip(HWINDOW wnd)  void
698    ui_reset_clip()
699  {  {
700          XRectangle rect;          XRectangle rect;
701    
702          rect.x = 0;          rect.x = 0;
703          rect.y = 0;          rect.y = 0;
704          rect.width = wnd->width;          rect.width = width;
705          rect.height = wnd->height;          rect.height = height;
706          XSetClipRectangles(wnd->display, wnd->gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
707  }  }
708    
709  static int rop2_map[] = {  void
710          GXclear,        /* 0 */  ui_bell()
         GXnor,          /* DPon */  
         GXandInverted,  /* DPna */  
         GXcopyInverted, /* Pn */  
         GXandReverse,   /* PDna */  
         GXinvert,       /* Dn */  
         GXxor,          /* DPx */  
         GXnand,         /* DPan */  
         GXand,          /* DPa */  
         GXequiv,        /* DPxn */  
         GXnoop,         /* D */  
         GXorInverted,   /* DPno */  
         GXcopy,         /* P */  
         GXorReverse,    /* PDno */  
         GXor,           /* DPo */  
         GXset           /* 1 */  
 };  
   
 static void xwin_set_function(HWINDOW wnd, uint8 rop2)  
711  {  {
712          XSetFunction(wnd->display, wnd->gc, rop2_map[rop2]);          XBell(display, 0);
713  }  }
714    
715  void ui_destblt(HWINDOW wnd, uint8 opcode,  void
716          /* dest */  int x, int y, int cx, int cy)  ui_destblt(uint8 opcode,
717               /* dest */ int x, int y, int cx, int cy)
718  {  {
719          xwin_set_function(wnd, opcode);          SET_FUNCTION(opcode);
720            FILL_RECTANGLE(x, y, cx, cy);
721          XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
722  }  }
723    
724  void ui_patblt(HWINDOW wnd, uint8 opcode,  void
725          /* dest */  int x, int y, int cx, int cy,  ui_patblt(uint8 opcode,
726          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* dest */ int x, int y, int cx, int cy,
727              /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
728  {  {
         Display *dpy = wnd->display;  
         GC gc = wnd->gc;  
729          Pixmap fill;          Pixmap fill;
730    
731          xwin_set_function(wnd, 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->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(wnd, 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->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(wnd, (HGLYPH)fill);                          ui_destroy_glyph((HGLYPH)fill);
753                          break;                          break;
754    
755                  default:                  default:
756                          NOTIMP("brush style %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
757          }          }
 }  
758    
759  void ui_screenblt(HWINDOW wnd, uint8 opcode,          RESET_FUNCTION(opcode);
                 /* dest */ int x, int y, int cx, int cy,  
                 /* src */  int srcx, int srcy)  
 {  
         xwin_set_function(wnd, opcode);  
   
         XCopyArea(wnd->display, wnd->wnd, wnd->wnd, wnd->gc, srcx, srcy,  
                         cx, cy, x, y);  
760  }  }
761    
762  void ui_memblt(HWINDOW wnd, uint8 opcode,  void
763          /* dest */  int x, int y, int cx, int cy,  ui_screenblt(uint8 opcode,
764          /* src */   HBITMAP src, int srcx, int srcy)               /* dest */ int x, int y, int cx, int cy,
765  {               /* src */ int srcx, int srcy)
766          xwin_set_function(wnd, opcode);  {
767            SET_FUNCTION(opcode);
768          XCopyArea(wnd->display, (Pixmap)src, wnd->wnd, wnd->gc, srcx, srcy,          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
769                          cx, cy, x, y);          if (ownbackstore)
770  }                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,
771                              cx, cy, x, y);
772  void ui_triblt(HWINDOW wnd, uint8 opcode,          RESET_FUNCTION(opcode);
773          /* dest */  int x, int y, int cx, int cy,  }
774          /* src */   HBITMAP src, int srcx, int srcy,  
775          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)  void
776    ui_memblt(uint8 opcode,
777              /* dest */ int x, int y, int cx, int cy,
778              /* src */ HBITMAP src, int srcx, int srcy)
779    {
780            SET_FUNCTION(opcode);
781            XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);
782            if (ownbackstore)
783                    XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,
784                              cx, cy, x, y);
785            RESET_FUNCTION(opcode);
786    }
787    
788    void
789    ui_triblt(uint8 opcode,
790              /* dest */ int x, int y, int cx, int cy,
791              /* 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 an efficient way of doing that 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 0xb8: /* PSDPxax */                  case 0x69:      /* PDSxxn */
800                          ui_patblt(wnd, ROP2_XOR, x, y, cx, cy,                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
801                                          brush, bgcolour, fgcolour);                          ui_patblt(ROP2_NXOR, x, y, cx, cy,
802                          ui_memblt(wnd, ROP2_AND, x, y, cx, cy,                                    brush, bgcolour, fgcolour);
803                                          src, srcx, srcy);                          break;
804                          ui_patblt(wnd, ROP2_XOR, x, y, cx, cy,  
805                                          brush, bgcolour, fgcolour);                  case 0xb8:      /* PSDPxax */
806                            ui_patblt(ROP2_XOR, x, y, cx, cy,
807                                      brush, bgcolour, fgcolour);
808                            ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
809                            ui_patblt(ROP2_XOR, x, y, cx, cy,
810                                      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 opcode 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
821                          ui_memblt(wnd, ROP2_COPY, x, y, cx, cy,                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
                                         brush, bgcolour, fgcolour);  
822          }          }
823  }  }
824    
825  void ui_line(HWINDOW wnd, 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(wnd, opcode);          SET_FUNCTION(opcode);
831            SET_FOREGROUND(pen->colour);
832          XSetForeground(wnd->display, wnd->gc, pen->colour);          XDrawLine(display, wnd, gc, startx, starty, endx, endy);
833          XDrawLine(wnd->display, wnd->wnd, wnd->gc, startx, starty, endx, endy);          if (ownbackstore)
834                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
835            RESET_FUNCTION(opcode);
836  }  }
837    
838  void ui_rect(HWINDOW wnd,  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(wnd, ROP2_COPY);          SET_FOREGROUND(colour);
844            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(wnd->display, wnd->gc, colour);  
         XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, cx, cy);  
845  }  }
846    
847  void ui_draw_glyph(HWINDOW wnd, 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(wnd, ROP2_COPY);          XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)
857                          ? FillStippled : FillOpaqueStippled);
858          XSetForeground(wnd->display, wnd->gc, fgcolour);          XSetStipple(display, gc, (Pixmap)glyph);
859            XSetTSOrigin(display, gc, x, y);
         switch (mixmode)  
         {  
                 case MIX_TRANSPARENT:  
                         XSetStipple(wnd->display, wnd->gc, pixmap);  
                         XSetFillStyle(wnd->display, wnd->gc, FillStippled);  
                         XSetTSOrigin(wnd->display, wnd->gc, x, y);  
                         XFillRectangle(wnd->display, wnd->wnd, wnd->gc,  
                                         x, y, cx, cy);  
                         XSetFillStyle(wnd->display, wnd->gc, FillSolid);  
                         break;  
860    
861                  case MIX_OPAQUE:          FILL_RECTANGLE(x, y, cx, cy);
                         XSetBackground(wnd->display, wnd->gc, bgcolour);  
                         XCopyPlane(wnd->display, pixmap, wnd->wnd, wnd->gc,  
                                         srcx, srcy, cx, cy, x, y, 1);  
                         break;  
862    
863                  default:          XSetFillStyle(display, gc, FillSolid);
                         NOTIMP("mix mode %d\n", mixmode);  
         }  
864  }  }
865    
866  void ui_draw_text(HWINDOW wnd, uint8 font, uint8 flags, int mixmode, int x,  void
867                          int y, int boxx, int boxy, int boxcx, int boxcy,  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
868                          int bgcolour, int fgcolour, uint8 *text, uint8 length)               int clipx, int clipy, int clipcx, int clipcy,
869                 int boxx, int boxy, int boxcx, int boxcy,
870                 int bgcolour, int fgcolour, uint8 *text, uint8 length)
871  {  {
872          FONT_GLYPH *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(wnd, boxx, boxy, boxcx, boxcy, bgcolour);                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
880            }
881            else if (mixmode == MIX_OPAQUE)
882            {
883                    FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
884          }          }
885    
886          /* Paint text, character by character */          /* Paint text, character by character */
887          for (i = 0; i < length; i++)          for (i = 0; i < length; i++)
888          {          {
889                  glyph = cache_get_font(wnd->conn, font, text[i]);                  glyph = cache_get_font(font, text[i]);
890    
891                    if (!(flags & TEXT2_IMPLICIT_X))
892                    {
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(wnd, 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;
                         else  
                                 x += text[++i];  
913                  }                  }
914          }          }
915  }  }
916    
917  void ui_desktop_save(HWINDOW wnd, uint8 *data, 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;
         int scanline;  
922    
923          scanline = (cx + 3) & ~3;          if (ownbackstore)
924          image = XGetImage(wnd->display, wnd->wnd, x, y, cx, cy,          {
925                                  0xffffffff, ZPixmap);                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
926          memcpy(data, image->data, scanline*cy);                                    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);          XDestroyImage(image);
942  }  }
943    
944  void ui_desktop_restore(HWINDOW wnd, uint8 *data, 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          int scanline;          uint8 *data;
949    
950            offset *= bpp/8;
951            data = cache_get_desktop(offset, cx, cy, bpp/8);
952            if (data == NULL)
953                    return;
954    
955            image = XCreateImage(display, visual, depth, ZPixmap,
956                                 0, data, cx, cy, BitmapPad(display),
957                                 cx * bpp/8);
958    
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    
         scanline = (cx + 3) & ~3;  
         image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,  
                                 data, cx, cy, 32, scanline);  
         XSetFunction(wnd->display, wnd->gc, GXcopy);  
         XPutImage(wnd->display, wnd->wnd, wnd->gc, image, 0, 0, x, y, cx, cy);  
969          XFree(image);          XFree(image);
970  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26