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

Legend:
Removed from v.7  
changed lines
  Added in v.35

  ViewVC Help
Powered by ViewVC 1.1.26