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

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

  ViewVC Help
Powered by ViewVC 1.1.26