/[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 50 by matthewc, Sat Apr 20 09:41:03 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    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          XStoreName(display, window, "rdesktop");  static void
119          XMapWindow(display, window);  translate32(uint8 *data, uint32 *out, uint32 *end)
120          XSelectInput(display, window, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);  {
121          XSync(display, True);          while (out < end)
122                    *(out++) = colmap[*(data++)];
123    }
124    
125          gc = XCreateGC(display, window, 0, NULL);  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          wnd = xmalloc(sizeof(struct window));                  case 16:
139          wnd->conn = conn;                          translate16(data, (uint16 *)out, (uint16 *)end);
140          wnd->width = width;                          break;
141          wnd->height = height;  
142          wnd->display = display;                  case 24:
143          wnd->wnd = window;                          translate24(data, out, end);
144          wnd->gc = gc;                          break;
145          wnd->visual = visual;  
146                    case 32:
147                            translate32(data, (uint32 *)out, (uint32 *)end);
148                            break;
149            }
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          switch (key)          pfm = XListPixmapFormats(display, &i);
208            if (pfm != NULL)
209          {          {
210                  case 0x62: /* left arrow */                  /* Use maximum bpp for this depth - this is generally
211                          return 0x48;                     desirable, e.g. 24 bits->32 bits. */
212                  case 0x64: /* up arrow */                  while (i--)
213                          return 0x4b;                  {
214                  case 0x66: /* down arrow */                          if ((pfm[i].depth == depth)
215                          return 0x4d;                              && (pfm[i].bits_per_pixel > bpp))
216                  case 0x68: /* right arrow */                          {
217                          return 0x50;                                  bpp = pfm[i].bits_per_pixel;
218                  case 0x73: /* Windows key */                          }
219                          DEBUG("CHECKPOINT\n");                  }
220                    XFree(pfm);
221          }          }
222    
223          return 0;          if (bpp < 8)
224  }          {
225                    error("Less than 8 bpp not currently supported.\n");
226                    XCloseDisplay(display);
227                    return False;
228            }
229    
230  static uint16 xwin_translate_mouse(unsigned long button)          if (depth <= 8)
231  {                  owncolmap = True;
232          switch (button)          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            if (attribs.backing_store == NotUseful)
244                    ownbackstore = True;
245    
246            if (fullscreen)
247          {          {
248                  case Button1: /* left */                  attribs.override_redirect = True;
249                          return MOUSE_FLAG_BUTTON1;                  width = WidthOfScreen(screen);
250                  case Button2: /* middle */                  height = HeightOfScreen(screen);
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3: /* right */  
                         return MOUSE_FLAG_BUTTON2;  
251          }          }
252            else
253            {
254                    attribs.override_redirect = False;
255            }
256    
257            width = (width + 3) & ~3; /* make width a multiple of 32 bits */
258    
259          return 0;          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();
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 ui_process_events(HWINDOW wnd, HCONN conn)  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    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, flags;
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                    flags = 0;
335    
336                  switch (event.type)                  switch (event.type)
337                  {                  {
338                            case KeyRelease:
339                                    flags = KBD_FLAG_DOWN | KBD_FLAG_UP;
340                                    /* fall through */
341    
342                          case KeyPress:                          case KeyPress:
343                                  scancode = xwin_translate_key(event.xkey.keycode);                                  keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);
344                                    scancode = xkeymap_translate_key(keysym, event.xkey.keycode, &flags);
345                                  if (scancode == 0)                                  if (scancode == 0)
346                                          break;                                          break;
347    
348                                  rdp_send_input(conn, RDP_INPUT_SCANCODE, 0,                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, flags, scancode, 0);
                                                 scancode, 0);  
349                                  break;                                  break;
350    
351                          case KeyRelease:                          case ButtonPress:
352                                  scancode = xwin_translate_key(event.xkey.keycode);                                  flags = MOUSE_FLAG_DOWN;
353                                  if (scancode == 0)                                  /* fall through */
354    
355                            case ButtonRelease:
356                                    button = xkeymap_translate_button(event.xbutton.button);
357                                    if (button == 0)
358                                          break;                                          break;
359    
360                                  rdp_send_input(conn, RDP_INPUT_SCANCODE,                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
361                                                  KBD_FLAG_DOWN | KBD_FLAG_UP,                                                 flags | button,
362                                                  scancode, 0);                                                 event.xbutton.x,
363                                                   event.xbutton.y);
364                                  break;                                  break;
365    
366                          case ButtonPress:                          case MotionNotify:
367                                  button = xwin_translate_mouse(event.xbutton.button);                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,
368                                                   MOUSE_FLAG_MOVE,
369                                                   event.xmotion.x,
370                                                   event.xmotion.y);
371                                    break;
372    
373                                  if (button == 0)                          case EnterNotify:
374                                          break;                                  XGrabKeyboard(display, wnd, True, GrabModeAsync,
375                                                  GrabModeAsync, CurrentTime);
376                                    break;
377    
378                                  rdp_send_input(conn, RDP_INPUT_MOUSE,                          case LeaveNotify:
379                                                  button | MOUSE_FLAG_DOWN,                                  XUngrabKeyboard(display, CurrentTime);
                                                 event.xbutton.x,  
                                                 event.xbutton.y);  
380                                  break;                                  break;
381    
382                          case ButtonRelease:                          case Expose:
383                                  button = xwin_translate_mouse(event.xbutton.button);                                  XCopyArea(display, backstore, wnd, gc,
384                                  if (button == 0)                                            event.xexpose.x, event.xexpose.y,
385                                          break;                                            event.xexpose.width, event.xexpose.height,
386                                              event.xexpose.x, event.xexpose.y);
387                                    break;
388                    }
389            }
390    }
391    
392                                  rdp_send_input(conn, RDP_INPUT_MOUSE,  void
393                                                  button,  ui_select(int rdp_socket)
394                                                  event.xbutton.x,  {
395                                                  event.xbutton.y);          int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;
396            fd_set rfds;
397    
398            XFlush(display);
399    
400            FD_ZERO(&rfds);
401    
402            while (True)
403            {
404                    FD_ZERO(&rfds);
405                    FD_SET(rdp_socket, &rfds);
406                    FD_SET(x_socket, &rfds);
407    
408                    switch (select(n, &rfds, NULL, NULL, NULL))
409                    {
410                            case -1:
411                                    error("select: %s\n", strerror(errno));
412    
413                            case 0:
414                                    continue;
415                  }                  }
416    
417                    if (FD_ISSET(x_socket, &rfds))
418                            xwin_process_events();
419    
420                    if (FD_ISSET(rdp_socket, &rfds))
421                            return;
422          }          }
423  }  }
424    
425  void ui_move_pointer(HWINDOW wnd, int x, int y)  void
426    ui_move_pointer(int x, int y)
427  {  {
428          XWarpPointer(wnd->display, wnd->wnd, wnd->wnd, 0, 0, 0, 0, x, y);          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
429  }  }
430    
431  HBITMAP ui_create_bitmap(HWINDOW wnd, int width, int height, uint8 *data)  HBITMAP
432    ui_create_bitmap(int width, int height, uint8 *data)
433  {  {
434          XImage *image;          XImage *image;
435          Pixmap bitmap;          Pixmap bitmap;
436            uint8 *tdata;
437    
438          bitmap = XCreatePixmap(wnd->display, wnd->wnd, width, height, 8);          tdata = (owncolmap ? data : translate_image(width, height, data));
439            bitmap = XCreatePixmap(display, wnd, width, height, depth);
440            image = XCreateImage(display, visual, depth, ZPixmap,
441                                 0, tdata, width, height, 8, 0);
442    
443            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
444    
         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);  
445          XFree(image);          XFree(image);
446                    if (!owncolmap)
447          return (HBITMAP)bitmap;                  xfree(tdata);
448            return (HBITMAP) bitmap;
449    }
450    
451    void
452    ui_paint_bitmap(int x, int y, int cx, int cy,
453                    int width, int height, uint8 *data)
454    {
455            XImage *image;
456            uint8 *tdata;
457    
458            tdata = (owncolmap ? data : translate_image(width, height, data));
459            image = XCreateImage(display, visual, depth, ZPixmap,
460                                 0, tdata, width, height, 8, 0);
461    
462            if (ownbackstore)
463            {
464                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
465                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
466            }
467            else
468            {
469                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
470            }
471    
472            XFree(image);
473            if (!owncolmap)
474                    xfree(tdata);
475  }  }
476    
477  void ui_destroy_bitmap(HWINDOW wnd, HBITMAP bmp)  void
478    ui_destroy_bitmap(HBITMAP bmp)
479  {  {
480          XFreePixmap(wnd->display, (Pixmap)bmp);          XFreePixmap(display, (Pixmap)bmp);
481  }  }
482    
483  HGLYPH ui_create_glyph(HWINDOW wnd, int width, int height, uint8 *data)  HGLYPH
484    ui_create_glyph(int width, int height, uint8 *data)
485  {  {
486          XImage *image;          XImage *image;
487          Pixmap bitmap;          Pixmap bitmap;
# Line 201  HGLYPH ui_create_glyph(HWINDOW wnd, int Line 490  HGLYPH ui_create_glyph(HWINDOW wnd, int
490    
491          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
492    
493          bitmap = XCreatePixmap(wnd->display, wnd->wnd, width, height, 1);          bitmap = XCreatePixmap(display, wnd, width, height, 1);
494          gc = XCreateGC(wnd->display, bitmap, 0, NULL);          gc = XCreateGC(display, bitmap, 0, NULL);
495    
496            image = XCreateImage(display, visual, 1, ZPixmap, 0,
497                                 data, width, height, 8, scanline);
498            image->byte_order = MSBFirst;
499            image->bitmap_bit_order = MSBFirst;
500            XInitImage(image);
501    
502            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
503    
         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);  
504          XFree(image);          XFree(image);
505          XFreeGC(wnd->display, gc);          XFreeGC(display, gc);
           
506          return (HGLYPH)bitmap;          return (HGLYPH)bitmap;
507  }  }
508    
509  void ui_destroy_glyph(HWINDOW wnd, HGLYPH glyph)  void
510    ui_destroy_glyph(HGLYPH glyph)
511    {
512            XFreePixmap(display, (Pixmap)glyph);
513    }
514    
515    HCURSOR
516    ui_create_cursor(unsigned int x, unsigned int y, int width,
517                     int height, uint8 *andmask, uint8 *xormask)
518    {
519            HGLYPH maskglyph, cursorglyph;
520            XColor bg, fg;
521            Cursor xcursor;
522            uint8 *cursor, *pcursor;
523            uint8 *mask, *pmask;
524            uint8 nextbit;
525            int scanline, offset;
526            int i, j;
527    
528            scanline = (width + 7) / 8;
529            offset = scanline * height;
530    
531            cursor = xmalloc(offset);
532            memset(cursor, 0, offset);
533    
534            mask = xmalloc(offset);
535            memset(mask, 0, offset);
536    
537            /* approximate AND and XOR masks with a monochrome X pointer */
538            for (i = 0; i < height; i++)
539            {
540                    offset -= scanline;
541                    pcursor = &cursor[offset];
542                    pmask = &mask[offset];
543    
544                    for (j = 0; j < scanline; j++)
545                    {
546                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
547                            {
548                                    if (xormask[0] || xormask[1] || xormask[2])
549                                    {
550                                            *pcursor |= (~(*andmask) & nextbit);
551                                            *pmask |= nextbit;
552                                    }
553                                    else
554                                    {
555                                            *pcursor |= ((*andmask) & nextbit);
556                                            *pmask |= (~(*andmask) & nextbit);
557                                    }
558    
559                                    xormask += 3;
560                            }
561    
562                            andmask++;
563                            pcursor++;
564                            pmask++;
565                    }
566            }
567    
568            fg.red = fg.blue = fg.green = 0xffff;
569            bg.red = bg.blue = bg.green = 0x0000;
570            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
571    
572            cursorglyph = ui_create_glyph(width, height, cursor);
573            maskglyph = ui_create_glyph(width, height, mask);
574            
575            xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,
576                                    (Pixmap)maskglyph, &fg, &bg, x, y);
577    
578            ui_destroy_glyph(maskglyph);
579            ui_destroy_glyph(cursorglyph);
580            xfree(mask);
581            xfree(cursor);
582            return (HCURSOR)xcursor;
583    }
584    
585    void
586    ui_set_cursor(HCURSOR cursor)
587    {
588            XDefineCursor(display, wnd, (Cursor)cursor);
589    }
590    
591    void
592    ui_destroy_cursor(HCURSOR cursor)
593  {  {
594          XFreePixmap(wnd->display, (Pixmap)glyph);          XFreeCursor(display, (Cursor)cursor);
595  }  }
596    
597  HCOLOURMAP ui_create_colourmap(HWINDOW wnd, COLOURMAP *colours)  #define MAKE_XCOLOR(xc,c) \
598                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
599                    (xc)->green = ((c)->green << 8) | (c)->green; \
600                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
601                    (xc)->flags = DoRed | DoGreen | DoBlue;
602    
603    HCOLOURMAP
604    ui_create_colourmap(COLOURMAP *colours)
605  {  {
606          COLOURENTRY *entry;          COLOURENTRY *entry;
         XColor *xcolours, *xentry;  
         Colormap map;  
607          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
608    
609          xcolours = malloc(sizeof(XColor) * ncolours);          if (owncolmap)
         for (i = 0; i < ncolours; i++)  
610          {          {
611                  entry = &colours->colours[i];                  XColor *xcolours, *xentry;
612                  xentry = &xcolours[i];                  Colormap map;
613    
614                    xcolours = xmalloc(sizeof(XColor) * ncolours);
615                    for (i = 0; i < ncolours; i++)
616                    {
617                            entry = &colours->colours[i];
618                            xentry = &xcolours[i];
619                            xentry->pixel = i;
620                            MAKE_XCOLOR(xentry, entry);
621                    }
622    
623                    map = XCreateColormap(display, wnd, visual, AllocAll);
624                    XStoreColors(display, map, xcolours, ncolours);
625    
626                  xentry->pixel = i;                  xfree(xcolours);
627                  xentry->red = entry->red << 8;                  return (HCOLOURMAP)map;
                 xentry->blue = entry->blue << 8;  
                 xentry->green = entry->green << 8;  
                 xentry->flags = DoRed | DoBlue | DoGreen;  
628          }          }
629            else
630            {
631                    uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
632                    XColor xentry;
633                    uint32 colour;
634    
635                    for (i = 0; i < ncolours; i++)
636                    {
637                            entry = &colours->colours[i];
638                            MAKE_XCOLOR(&xentry, entry);
639    
640          map = XCreateColormap(wnd->display, wnd->wnd, wnd->visual, AllocAll);                          if (XAllocColor(display, xcolmap, &xentry) != 0)
641          XStoreColors(wnd->display, map, xcolours, ncolours);                                  colour = xentry.pixel;
642                            else
643                                    colour = white;
644    
645          free(xcolours);                          /* byte swap here to make translate_image faster */
646          return (HCOLOURMAP)map;                          map[i] = translate_colour(colour);
647                    }
648    
649                    return map;
650            }
651  }  }
652    
653  void ui_destroy_colourmap(HWINDOW wnd, HCOLOURMAP map)  void
654    ui_destroy_colourmap(HCOLOURMAP map)
655  {  {
656          XFreeColormap(wnd->display, (Colormap)map);          if (owncolmap)
657                    XFreeColormap(display, (Colormap)map);
658            else
659                    xfree(map);
660  }  }
661    
662  void ui_set_colourmap(HWINDOW wnd, HCOLOURMAP map)  void
663    ui_set_colourmap(HCOLOURMAP map)
664  {  {
665          XSetWindowColormap(wnd->display, wnd->wnd, (Colormap)map);          if (owncolmap)
666                    XSetWindowColormap(display, wnd, (Colormap)map);
667            else
668                    colmap = map;
669  }  }
670    
671  void ui_set_clip(HWINDOW wnd, int x, int y, int cx, int cy)  void
672    ui_set_clip(int x, int y, int cx, int cy)
673  {  {
674          XRectangle rect;          XRectangle rect;
675    
# Line 264  void ui_set_clip(HWINDOW wnd, int x, int Line 677  void ui_set_clip(HWINDOW wnd, int x, int
677          rect.y = y;          rect.y = y;
678          rect.width = cx;          rect.width = cx;
679          rect.height = cy;          rect.height = cy;
680          XSetClipRectangles(wnd->display, wnd->gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
681  }  }
682    
683  void ui_reset_clip(HWINDOW wnd)  void
684    ui_reset_clip()
685  {  {
686          XRectangle rect;          XRectangle rect;
687    
688          rect.x = 0;          rect.x = 0;
689          rect.y = 0;          rect.y = 0;
690          rect.width = wnd->width;          rect.width = width;
691          rect.height = wnd->height;          rect.height = height;
692          XSetClipRectangles(wnd->display, wnd->gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
693  }  }
694    
695  static int rop2_map[] = {  void
696          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)  
697  {  {
698          XSetFunction(wnd->display, wnd->gc, rop2_map[rop2]);          XBell(display, 0);
699  }  }
700    
701  void ui_destblt(HWINDOW wnd, uint8 opcode,  void
702          /* dest */  int x, int y, int cx, int cy)  ui_destblt(uint8 opcode,
703               /* dest */ int x, int y, int cx, int cy)
704  {  {
705          xwin_set_function(wnd, opcode);          SET_FUNCTION(opcode);
706            FILL_RECTANGLE(x, y, cx, cy);
707          XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, cx, cy);          RESET_FUNCTION(opcode);
708  }  }
709    
710  void ui_patblt(HWINDOW wnd, uint8 opcode,  void
711          /* dest */  int x, int y, int cx, int cy,  ui_patblt(uint8 opcode,
712          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* dest */ int x, int y, int cx, int cy,
713              /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
714  {  {
         Display *dpy = wnd->display;  
         GC gc = wnd->gc;  
715          Pixmap fill;          Pixmap fill;
716    
717          xwin_set_function(wnd, opcode);          SET_FUNCTION(opcode);
718    
719          switch (brush->style)          switch (brush->style)
720          {          {
721                  case 0: /* Solid */                  case 0: /* Solid */
722                          XSetForeground(dpy, gc, fgcolour);                          SET_FOREGROUND(fgcolour);
723                          XFillRectangle(dpy, wnd->wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
724                          break;                          break;
725    
726                  case 3: /* Pattern */                  case 3: /* Pattern */
727                          fill = (Pixmap)ui_create_glyph(wnd, 8, 8, brush->pattern);                          fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);
728    
729                          XSetForeground(dpy, gc, fgcolour);                          SET_FOREGROUND(bgcolour);
730                          XSetBackground(dpy, gc, bgcolour);                          SET_BACKGROUND(fgcolour);
731                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                          XSetFillStyle(display, gc, FillOpaqueStippled);
732                          XSetStipple(dpy, gc, fill);                          XSetStipple(display, gc, fill);
733                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
734    
735                          XFillRectangle(dpy, wnd->wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
736    
737                          XSetFillStyle(dpy, gc, FillSolid);                          XSetFillStyle(display, gc, FillSolid);
738                          ui_destroy_glyph(wnd, (HGLYPH)fill);                          ui_destroy_glyph((HGLYPH)fill);
739                          break;                          break;
740    
741                  default:                  default:
742                          NOTIMP("brush style %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
743          }          }
 }  
744    
745  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);  
746  }  }
747    
748  void ui_memblt(HWINDOW wnd, uint8 opcode,  void
749          /* dest */  int x, int y, int cx, int cy,  ui_screenblt(uint8 opcode,
750          /* src */   HBITMAP src, int srcx, int srcy)               /* dest */ int x, int y, int cx, int cy,
751  {               /* src */ int srcx, int srcy)
752          xwin_set_function(wnd, opcode);  {
753            SET_FUNCTION(opcode);
754          XCopyArea(wnd->display, (Pixmap)src, wnd->wnd, wnd->gc, srcx, srcy,          XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
755                          cx, cy, x, y);          if (ownbackstore)
756  }                  XCopyArea(display, backstore, backstore, gc, srcx, srcy,
757                              cx, cy, x, y);
758  void ui_triblt(HWINDOW wnd, uint8 opcode,          RESET_FUNCTION(opcode);
759          /* dest */  int x, int y, int cx, int cy,  }
760          /* src */   HBITMAP src, int srcx, int srcy,  
761          /* brush */ BRUSH *brush, int bgcolour, int fgcolour)  void
762    ui_memblt(uint8 opcode,
763              /* dest */ int x, int y, int cx, int cy,
764              /* src */ HBITMAP src, int srcx, int srcy)
765    {
766            SET_FUNCTION(opcode);
767            XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);
768            if (ownbackstore)
769                    XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,
770                              cx, cy, x, y);
771            RESET_FUNCTION(opcode);
772    }
773    
774    void
775    ui_triblt(uint8 opcode,
776              /* dest */ int x, int y, int cx, int cy,
777              /* src */ HBITMAP src, int srcx, int srcy,
778              /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
779  {  {
780          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
781             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. */
782    
783          switch (opcode)          switch (opcode)
784          {          {
785                  case 0xb8: /* PSDPxax */                  case 0x69:      /* PDSxxn */
786                          ui_patblt(wnd, ROP2_XOR, x, y, cx, cy,                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
787                                          brush, bgcolour, fgcolour);                          ui_patblt(ROP2_NXOR, x, y, cx, cy,
788                          ui_memblt(wnd, ROP2_AND, x, y, cx, cy,                                    brush, bgcolour, fgcolour);
                                         src, srcx, srcy);  
                         ui_patblt(wnd, ROP2_XOR, x, y, cx, cy,  
                                         brush, bgcolour, fgcolour);  
789                          break;                          break;
790    
791                  default:                  case 0xb8:      /* PSDPxax */
792                          NOTIMP("triblt opcode 0x%x\n", opcode);                          ui_patblt(ROP2_XOR, x, y, cx, cy,
793                          ui_memblt(wnd, ROP2_COPY, x, y, cx, cy,                                    brush, bgcolour, fgcolour);
794                                          brush, bgcolour, fgcolour);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
795          }                          ui_patblt(ROP2_XOR, x, y, cx, cy,
796  }                                    brush, bgcolour, fgcolour);
   
 void ui_line(HWINDOW wnd, uint8 opcode,  
         /* dest */  int startx, int starty, int endx, int endy,  
         /* pen */   PEN *pen)  
 {  
         xwin_set_function(wnd, opcode);  
   
         XSetForeground(wnd->display, wnd->gc, pen->colour);  
         XDrawLine(wnd->display, wnd->wnd, wnd->gc, startx, starty, endx, endy);  
 }  
   
 void ui_rect(HWINDOW wnd,  
         /* dest */  int x, int y, int cx, int cy,  
         /* brush */ int colour)  
 {  
         xwin_set_function(wnd, ROP2_COPY);  
   
         XSetForeground(wnd->display, wnd->gc, colour);  
         XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, cx, cy);  
 }  
   
 void ui_draw_glyph(HWINDOW wnd, int mixmode,  
         /* dest */ int x, int y, int cx, int cy,  
         /* src */  HGLYPH glyph, int srcx, int srcy, int bgcolour, int fgcolour)  
 {  
         Pixmap pixmap = (Pixmap)glyph;  
   
         xwin_set_function(wnd, ROP2_COPY);  
   
         XSetForeground(wnd->display, wnd->gc, fgcolour);  
   
         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);  
797                          break;                          break;
798    
799                  case MIX_OPAQUE:                  case 0xc0:      /* PSa */
800                          XSetBackground(wnd->display, wnd->gc, bgcolour);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
801                          XCopyPlane(wnd->display, pixmap, wnd->wnd, wnd->gc,                          ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
802                                          srcx, srcy, cx, cy, x, y, 1);                                    fgcolour);
803                          break;                          break;
804    
805                  default:                  default:
806                          NOTIMP("mix mode %d\n", mixmode);                          unimpl("triblt 0x%x\n", opcode);
807                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
808          }          }
809  }  }
810    
811  void ui_draw_text(HWINDOW wnd, uint8 font, uint8 flags, int mixmode, int x,  void
812                          int y, int boxx, int boxy, int boxcx, int boxcy,  ui_line(uint8 opcode,
813                          int bgcolour, int fgcolour, uint8 *text, uint8 length)          /* dest */ int startx, int starty, int endx, int endy,
814  {          /* pen */ PEN *pen)
815          FONT_GLYPH *glyph;  {
816          int i;          SET_FUNCTION(opcode);
817            SET_FOREGROUND(pen->colour);
818            XDrawLine(display, wnd, gc, startx, starty, endx, endy);
819            if (ownbackstore)
820                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
821            RESET_FUNCTION(opcode);
822    }
823    
824    void
825    ui_rect(
826                   /* dest */ int x, int y, int cx, int cy,
827                   /* brush */ int colour)
828    {
829            SET_FOREGROUND(colour);
830            FILL_RECTANGLE(x, y, cx, cy);
831    }
832    
833    void
834    ui_draw_glyph(int mixmode,
835                  /* dest */ int x, int y, int cx, int cy,
836                  /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,
837                  int fgcolour)
838    {
839            SET_FOREGROUND(fgcolour);
840            SET_BACKGROUND(bgcolour);
841    
842            XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)
843                          ? FillStippled : FillOpaqueStippled);
844            XSetStipple(display, gc, (Pixmap)glyph);
845            XSetTSOrigin(display, gc, x, y);
846    
847            FILL_RECTANGLE(x, y, cx, cy);
848    
849            XSetFillStyle(display, gc, FillSolid);
850    }
851    
852    #define DO_GLYPH(ttext,idx) \
853    {\
854      glyph = cache_get_font (font, ttext[idx]);\
855      if (!(flags & TEXT2_IMPLICIT_X))\
856        {\
857          xyoffset = ttext[++idx];\
858          if ((xyoffset & 0x80))\
859            {\
860              if (flags & TEXT2_VERTICAL) \
861                y += ttext[++idx] | (ttext[++idx] << 8);\
862              else\
863                x += ttext[++idx] | (ttext[++idx] << 8);\
864            }\
865          else\
866            {\
867              if (flags & TEXT2_VERTICAL) \
868                y += xyoffset;\
869              else\
870                x += xyoffset;\
871            }\
872        }\
873      if (glyph != NULL)\
874        {\
875          ui_draw_glyph (mixmode, x + (short) glyph->offset,\
876                         y + (short) glyph->baseline,\
877                         glyph->width, glyph->height,\
878                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
879          if (flags & TEXT2_IMPLICIT_X)\
880            x += glyph->width;\
881        }\
882    }
883    
884    void
885    ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
886                 int clipx, int clipy, int clipcx, int clipcy, int boxx,
887                 int boxy, int boxcx, int boxcy, int bgcolour,
888                 int fgcolour, uint8 * text, uint8 length)
889    {
890            FONTGLYPH *glyph;
891            int i, j, xyoffset;
892            DATABLOB *entry;
893    
894            SET_FOREGROUND(bgcolour);
895    
896          if (boxcx > 1)          if (boxcx > 1)
897          {          {
898                  ui_rect(wnd, boxx, boxy, boxcx, boxcy, bgcolour);                  FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
899            }
900            else if (mixmode == MIX_OPAQUE)
901            {
902                    FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
903          }          }
904    
905          /* Paint text, character by character */          /* Paint text, character by character */
906          for (i = 0; i < length; i++)          for (i = 0; i < length;) {
907          {                  switch (text[i]) {
908                  glyph = cache_get_font(wnd->conn, font, text[i]);                  case 0xff:
909                            if (i + 2 < length)
910                                    cache_put_text(text[i + 1], text, text[i + 2]);
911                            else {
912                                    error("this shouldn't be happening\n");
913                                    break;
914                            }
915                            /* this will move pointer from start to first character after FF command */
916                            length -= i + 3;
917                            text = &(text[i + 3]);
918                            i = 0;
919                            break;
920    
921                  if (glyph != NULL)                  case 0xfe:
922                  {                          entry = cache_get_text(text[i + 1]);
923                          ui_draw_glyph(wnd, mixmode, x,                          if (entry != NULL) {
924                                          y + (short)glyph->baseline,                                  if ((((uint8 *) (entry->data))[1] == 0)
925                                          glyph->width, glyph->height,                                      && (!(flags & TEXT2_IMPLICIT_X))) {
926                                          glyph->pixmap, 0, 0,                                          if (flags & TEXT2_VERTICAL)      
927                                          bgcolour, fgcolour);                                                  y += text[i + 2];
928                                            else
929                                                    x += text[i + 2];
930                                    }
931                                    if (i + 2 < length)
932                                            i += 3;
933                                    else
934                                            i += 2;
935                                    length -= i;  
936                                    /* this will move pointer from start to first character after FE command */
937                                    text = &(text[i]);
938                                    i = 0;
939                                    for (j = 0; j < entry->size; j++)
940                                            DO_GLYPH(((uint8 *) (entry->data)), j);
941                            }
942                            break;
943    
944                          if (flags & TEXT2_IMPLICIT_X)                  default:
945                                  x += glyph->width;                          DO_GLYPH(text, i);
946                          else                          i++;
947                                  x += text[++i];                          break;
948                  }                  }
949          }          }
950    
951    
952  }  }
953    
954  void ui_desktop_save(HWINDOW wnd, uint8 *data, int x, int y, int cx, int cy)  void
955    ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
956  {  {
957            Pixmap pix;
958          XImage *image;          XImage *image;
         int scanline;  
959    
960          scanline = (cx + 3) & ~3;          if (ownbackstore)
961          image = XGetImage(wnd->display, wnd->wnd, x, y, cx, cy,          {
962                                  0xffffffff, ZPixmap);                  image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
963          memcpy(data, image->data, scanline*cy);                                    ZPixmap);
964            }
965            else
966            {
967                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
968                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
969                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,
970                                      ZPixmap);
971                    XFreePixmap(display, pix);
972            }
973    
974            offset *= bpp/8;
975            cache_put_desktop(offset, cx, cy, image->bytes_per_line,
976                              bpp/8, (uint8 *)image->data);
977    
978          XDestroyImage(image);          XDestroyImage(image);
979  }  }
980    
981  void ui_desktop_restore(HWINDOW wnd, uint8 *data, int x, int y, int cx, int cy)  void
982    ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
983  {  {
984          XImage *image;          XImage *image;
985          int scanline;          uint8 *data;
986    
987            offset *= bpp/8;
988            data = cache_get_desktop(offset, cx, cy, bpp/8);
989            if (data == NULL)
990                    return;
991    
992            image = XCreateImage(display, visual, depth, ZPixmap,
993                                 0, data, cx, cy, BitmapPad(display),
994                                 cx * bpp/8);
995    
996            if (ownbackstore)
997            {
998                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
999                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1000            }
1001            else
1002            {
1003                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1004            }
1005    
         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);  
1006          XFree(image);          XFree(image);
1007  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26