/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/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 194 by matthewc, Tue Sep 24 12:25:21 2002 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X-Windows     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2001
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
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    extern BOOL grab_keyboard;
32    extern char title[];
33    BOOL enable_compose = False;
34    
35    Display *display;
36    static int x_socket;
37    static Screen *screen;
38    static Window wnd;
39    static GC gc;
40    static Visual *visual;
41    static int depth;
42    static int bpp;
43    static XIM IM;
44    static XIC IC;
45    static Cursor current_cursor;
46    
47    /* endianness */
48    static BOOL host_be;
49    static BOOL xserver_be;
50    
51    /* software backing store */
52    static BOOL ownbackstore;
53    static Pixmap backstore;
54    
55    #define FILL_RECTANGLE(x,y,cx,cy)\
56    { \
57            XFillRectangle(display, wnd, gc, x, y, cx, cy); \
58            if (ownbackstore) \
59                    XFillRectangle(display, backstore, gc, x, y, cx, cy); \
60    }
61    
62    /* colour maps */
63    static Colormap xcolmap;
64    static uint32 *colmap;
65    
66    #define SET_FOREGROUND(col)     XSetForeground(display, gc, translate_colour(colmap[col]));
67    #define SET_BACKGROUND(col)     XSetBackground(display, gc, translate_colour(colmap[col]));
68    
69    static int rop2_map[] = {
70            GXclear,                /* 0 */
71            GXnor,                  /* DPon */
72            GXandInverted,          /* DPna */
73            GXcopyInverted,         /* Pn */
74            GXandReverse,           /* PDna */
75            GXinvert,               /* Dn */
76            GXxor,                  /* DPx */
77            GXnand,                 /* DPan */
78            GXand,                  /* DPa */
79            GXequiv,                /* DPxn */
80            GXnoop,                 /* D */
81            GXorInverted,           /* DPno */
82            GXcopy,                 /* P */
83            GXorReverse,            /* PDno */
84            GXor,                   /* DPo */
85            GXset                   /* 1 */
86    };
87    
88    #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
89    #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
90    
91  HWINDOW ui_create_window(int width, int height)  static void
92    translate8(uint8 * data, uint8 * out, uint8 * end)
93  {  {
94          struct window *wnd;          while (out < end)
95          Display *display;                  *(out++) = (uint8) colmap[*(data++)];
96          Window window;  }
97          int black;  
98          GC gc;  static void
99    translate16(uint8 * data, uint16 * out, uint16 * end)
100    {
101            while (out < end)
102                    *(out++) = (uint16) colmap[*(data++)];
103    }
104    
105    /* little endian - conversion happens when colourmap is built */
106    static void
107    translate24(uint8 * data, uint8 * out, uint8 * end)
108    {
109            uint32 value;
110    
111            while (out < end)
112            {
113                    value = colmap[*(data++)];
114                    *(out++) = value;
115                    *(out++) = value >> 8;
116                    *(out++) = value >> 16;
117            }
118    }
119    
120    static void
121    translate32(uint8 * data, uint32 * out, uint32 * end)
122    {
123            while (out < end)
124                    *(out++) = colmap[*(data++)];
125    }
126    
127    static uint8 *
128    translate_image(int width, int height, uint8 * data)
129    {
130            int size = width * height * bpp / 8;
131            uint8 *out = xmalloc(size);
132            uint8 *end = out + size;
133    
134            switch (bpp)
135            {
136                    case 8:
137                            translate8(data, out, end);
138                            break;
139    
140                    case 16:
141                            translate16(data, (uint16 *) out, (uint16 *) end);
142                            break;
143    
144                    case 24:
145                            translate24(data, out, end);
146                            break;
147    
148                    case 32:
149                            translate32(data, (uint32 *) out, (uint32 *) end);
150                            break;
151            }
152    
153            return out;
154    }
155    
156    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
157    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
158    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
159                            x = (x << 16) | (x >> 16); }
160    
161    static uint32
162    translate_colour(uint32 colour)
163    {
164            switch (bpp)
165            {
166                    case 16:
167                            if (host_be != xserver_be)
168                                    BSWAP16(colour);
169                            break;
170    
171                    case 24:
172                            if (xserver_be)
173                                    BSWAP24(colour);
174                            break;
175    
176                    case 32:
177                            if (host_be != xserver_be)
178                                    BSWAP32(colour);
179                            break;
180            }
181    
182            return colour;
183    }
184    
185    BOOL
186    get_key_state(int keysym)
187    {
188            int keysymMask = 0, modifierpos, key;
189            Window wDummy1, wDummy2;
190            int iDummy3, iDummy4, iDummy5, iDummy6;
191            unsigned int current_state;
192            int offset;
193    
194            XModifierKeymap *map = XGetModifierMapping(display);
195            KeyCode keycode = XKeysymToKeycode(display, keysym);
196    
197            if (keycode == NoSymbol)
198                    return False;
199    
200            for (modifierpos = 0; modifierpos < 8; modifierpos++)
201            {
202                    offset = map->max_keypermod * modifierpos;
203    
204                    for (key = 0; key < map->max_keypermod; key++)
205                    {
206                            if (map->modifiermap[offset + key] == keycode)
207                                    keysymMask = 1 << modifierpos;
208                    }
209            }
210    
211            XQueryPointer(display, DefaultRootWindow(display), &wDummy1,
212                          &wDummy2, &iDummy3, &iDummy4, &iDummy5, &iDummy6, &current_state);
213    
214            XFreeModifiermap(map);
215    
216            return (current_state & keysymMask) ? True : False;
217    }
218    
219    BOOL
220    ui_init(void)
221    {
222            XPixmapFormatValues *pfm;
223            uint16 test;
224            int i;
225    
226          display = XOpenDisplay(NULL);          display = XOpenDisplay(NULL);
227          if (display == NULL)          if (display == NULL)
228                  return NULL;          {
229                    error("Failed to open display\n");
230                    return False;
231            }
232    
233            x_socket = ConnectionNumber(display);
234            screen = DefaultScreenOfDisplay(display);
235            visual = DefaultVisualOfScreen(screen);
236            depth = DefaultDepthOfScreen(screen);
237    
238            pfm = XListPixmapFormats(display, &i);
239            if (pfm != NULL)
240            {
241                    /* Use maximum bpp for this depth - this is generally
242                       desirable, e.g. 24 bits->32 bits. */
243                    while (i--)
244                    {
245                            if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
246                            {
247                                    bpp = pfm[i].bits_per_pixel;
248                            }
249                    }
250                    XFree(pfm);
251            }
252    
253          black = BlackPixel(display, DefaultScreen(display));          if (bpp < 8)
254          window = XCreateSimpleWindow(display, DefaultRootWindow(display),          {
255                                  0, 0, width, height, 0, black, black);                  error("Less than 8 bpp not currently supported.\n");
256                    XCloseDisplay(display);
257                    return False;
258            }
259    
260          XMapWindow(display, window);          xcolmap = DefaultColormapOfScreen(screen);
261          XSync(display, True);          gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
262    
263          gc = XCreateGC(display, window, 0, NULL);          if (DoesBackingStore(screen) != Always)
264                    ownbackstore = True;
265    
266          wnd = xmalloc(sizeof(struct window));          test = 1;
267          wnd->display = display;          host_be = !(BOOL) (*(uint8 *) (&test));
268          wnd->wnd = window;          xserver_be = (ImageByteOrder(display) == MSBFirst);
269          wnd->gc = gc;  
270          wnd->visual = DefaultVisual(wnd->display, DefaultScreen(wnd->display));          if (fullscreen)
271            {
272                    width = WidthOfScreen(screen);
273                    height = HeightOfScreen(screen);
274            }
275    
276          return wnd;          /* make sure width is a multiple of 4 */
277            width = (width + 3) & ~3;
278    
279            if (ownbackstore)
280            {
281                    backstore = XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
282    
283                    /* clear to prevent rubbish being exposed at startup */
284                    XSetForeground(display, gc, BlackPixelOfScreen(screen));
285                    XFillRectangle(display, backstore, gc, 0, 0, width, height);
286            }
287    
288            if (enable_compose)
289                    IM = XOpenIM(display, NULL, NULL, NULL);
290    
291            xkeymap_init();
292            return True;
293    }
294    
295    void
296    ui_deinit(void)
297    {
298            if (IM != NULL)
299                    XCloseIM(IM);
300    
301            if (ownbackstore)
302                    XFreePixmap(display, backstore);
303    
304            XFreeGC(display, gc);
305            XCloseDisplay(display);
306            display = NULL;
307    }
308    
309    BOOL
310    ui_create_window(void)
311    {
312            XSetWindowAttributes attribs;
313            XClassHint *classhints;
314            XSizeHints *sizehints;
315            int wndwidth, wndheight;
316            long input_mask, ic_input_mask;
317            XEvent xevent;
318    
319            wndwidth  = fullscreen ? WidthOfScreen(screen)  : width;
320            wndheight = fullscreen ? HeightOfScreen(screen) : height;
321    
322            attribs.background_pixel = BlackPixelOfScreen(screen);
323            attribs.backing_store = ownbackstore ? NotUseful : Always;
324            attribs.override_redirect = fullscreen;
325    
326            wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
327                                0, CopyFromParent, InputOutput, CopyFromParent,
328                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
329    
330            XStoreName(display, wnd, title);
331    
332            classhints = XAllocClassHint();
333            if (classhints != NULL)
334            {
335                    classhints->res_name = classhints->res_class = "rdesktop";
336                    XSetClassHint(display, wnd, classhints);
337                    XFree(classhints);
338            }
339    
340            sizehints = XAllocSizeHints();
341            if (sizehints)
342            {
343                    sizehints->flags = PMinSize | PMaxSize;
344                    sizehints->min_width = sizehints->max_width = width;
345                    sizehints->min_height = sizehints->max_height = height;
346                    XSetWMNormalHints(display, wnd, sizehints);
347                    XFree(sizehints);
348            }
349    
350            input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
351                    StructureNotifyMask | FocusChangeMask;
352    
353            if (sendmotion)
354                    input_mask |= PointerMotionMask;
355            if (ownbackstore)
356                    input_mask |= ExposureMask;
357    
358            if (IM != NULL)
359            {
360                    IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
361                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
362    
363                    if ((IC != NULL) && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
364                            input_mask |= ic_input_mask;
365            }
366    
367            XSelectInput(display, wnd, input_mask);
368            XMapWindow(display, wnd);
369    
370            /* wait for MapNotify */
371            do {
372                    XMaskEvent(display, StructureNotifyMask, &xevent);
373            } while (xevent.type != MapNotify);
374    
375            if (fullscreen)
376                    XSetInputFocus(display, wnd, RevertToPointerRoot, CurrentTime);
377    
378            return True;
379  }  }
380    
381  void ui_destroy_window(HWINDOW wnd)  void
382    ui_destroy_window(void)
383  {  {
384          XFreeGC(wnd->display, wnd->gc);          if (IC != NULL)
385          XDestroyWindow(wnd->display, wnd->wnd);                  XDestroyIC(IC);
386          XCloseDisplay(wnd->display);  
387            XDestroyWindow(display, wnd);
388  }  }
389    
390  HBITMAP ui_create_bitmap(HWINDOW wnd, int width, int height, uint8 *data)  void
391    xwin_toggle_fullscreen(void)
392    {
393            Pixmap contents = 0;
394    
395            if (!ownbackstore)
396            {
397                    /* need to save contents of window */
398                    contents = XCreatePixmap(display, wnd, width, height, depth);
399                    XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
400            }
401    
402            ui_destroy_window();
403            fullscreen = !fullscreen;
404            ui_create_window();
405    
406            XDefineCursor(display, wnd, current_cursor);
407    
408            if (!ownbackstore)
409            {
410                    XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
411                    XFreePixmap(display, contents);
412            }
413    }
414    
415    /* Process all events in Xlib queue */
416    static void
417    xwin_process_events(void)
418    {
419            XEvent xevent;
420            KeySym keysym;
421            uint16 button, flags;
422            uint32 ev_time;
423            key_translation tr;
424            char *ksname = NULL;
425            char str[256];
426            Status status;
427    
428            while (XPending(display) > 0)
429            {
430                    XNextEvent(display, &xevent);
431    
432                    if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
433                    {
434                            DEBUG_KBD(("Filtering event\n"));
435                            continue;
436                    }
437    
438                    ev_time = time(NULL);
439                    flags = 0;
440    
441                    switch (xevent.type)
442                    {
443                            case KeyPress:
444                                    if (IC != NULL)
445                                            /* Multi_key compatible version */
446                                    {
447                                            XmbLookupString(IC,
448                                                            (XKeyPressedEvent *) &
449                                                            xevent, str, sizeof(str), &keysym, &status);
450                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
451                                            {
452                                                    error("XmbLookupString failed with status 0x%x\n",
453                                                          status);
454                                                    break;
455                                            }
456                                    }
457                                    else
458                                    {
459                                            /* Plain old XLookupString */
460                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
461                                            XLookupString((XKeyEvent *) & xevent,
462                                                          str, sizeof(str), &keysym, NULL);
463                                    }
464    
465                                    ksname = get_ksname(keysym);
466                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym, ksname));
467    
468                                    if (handle_special_keys(keysym, ev_time, True))
469                                            break;
470    
471                                    tr = xkeymap_translate_key(keysym,
472                                                               xevent.xkey.keycode, xevent.xkey.state);
473    
474                                    if (tr.scancode == 0)
475                                            break;
476    
477                                    ensure_remote_modifiers(ev_time, tr);
478    
479                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
480                                    break;
481                            case KeyRelease:
482                                    XLookupString((XKeyEvent *) & xevent, str,
483                                                  sizeof(str), &keysym, NULL);
484    
485                                    ksname = get_ksname(keysym);
486                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
487                                               ksname));
488    
489                                    if (handle_special_keys(keysym, ev_time, False))
490                                            break;
491    
492                                    tr = xkeymap_translate_key(keysym,
493                                                               xevent.xkey.keycode, xevent.xkey.state);
494    
495                                    if (tr.scancode == 0)
496                                            break;
497    
498                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
499                                    break;
500    
501                            case ButtonPress:
502                                    flags = MOUSE_FLAG_DOWN;
503                                    /* fall through */
504    
505                            case ButtonRelease:
506                                    button = xkeymap_translate_button(xevent.xbutton.button);
507                                    if (button == 0)
508                                            break;
509    
510                                    rdp_send_input(ev_time, RDP_INPUT_MOUSE,
511                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
512                                    break;
513    
514                            case MotionNotify:
515                                    rdp_send_input(ev_time, RDP_INPUT_MOUSE,
516                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
517                                    break;
518    
519                            case FocusIn:
520                                    reset_modifier_keys();
521                                    if (grab_keyboard)
522                                            XGrabKeyboard(display, wnd, True,
523                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
524                                    break;
525    
526                            case FocusOut:
527                                    if (grab_keyboard)
528                                            XUngrabKeyboard(display, CurrentTime);
529                                    break;
530    
531                            case Expose:
532                                    XCopyArea(display, backstore, wnd, gc,
533                                              xevent.xexpose.x, xevent.xexpose.y,
534                                              xevent.xexpose.width,
535                                              xevent.xexpose.height,
536                                              xevent.xexpose.x, xevent.xexpose.y);
537                                    break;
538    
539                            case MappingNotify:
540                                    /* Refresh keyboard mapping if it has changed. This is important for
541                                       Xvnc, since it allocates keycodes dynamically */
542                                    if (xevent.xmapping.request == MappingKeyboard
543                                        || xevent.xmapping.request == MappingModifier)
544                                            XRefreshKeyboardMapping(&xevent.xmapping);
545                                    break;
546    
547                    }
548            }
549    }
550    
551    void
552    ui_select(int rdp_socket)
553    {
554            int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
555            fd_set rfds;
556    
557            FD_ZERO(&rfds);
558    
559            while (True)
560            {
561                    /* Process any events already waiting */
562                    xwin_process_events();
563    
564                    FD_ZERO(&rfds);
565                    FD_SET(rdp_socket, &rfds);
566                    FD_SET(x_socket, &rfds);
567    
568                    switch (select(n, &rfds, NULL, NULL, NULL))
569                    {
570                            case -1:
571                                    error("select: %s\n", strerror(errno));
572    
573                            case 0:
574                                    continue;
575                    }
576    
577                    if (FD_ISSET(rdp_socket, &rfds))
578                            return;
579            }
580    }
581    
582    void
583    ui_move_pointer(int x, int y)
584    {
585            XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
586    }
587    
588    HBITMAP
589    ui_create_bitmap(int width, int height, uint8 * data)
590  {  {
591          XImage *image;          XImage *image;
592            Pixmap bitmap;
593            uint8 *tdata;
594    
595            tdata = translate_image(width, height, data);
596            bitmap = XCreatePixmap(display, wnd, width, height, depth);
597            image = XCreateImage(display, visual, depth, ZPixmap, 0,
598                                 (char *) tdata, width, height, 8, 0);
599    
600            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
601    
602            XFree(image);
603            xfree(tdata);
604            return (HBITMAP) bitmap;
605    }
606    
607    void
608    ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
609    {
610            XImage *image;
611            uint8 *tdata;
612    
613            tdata = translate_image(width, height, data);
614            image = XCreateImage(display, visual, depth, ZPixmap, 0,
615                                 (char *) tdata, width, height, 8, 0);
616    
617            if (ownbackstore)
618            {
619                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
620                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
621            }
622            else
623            {
624                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
625            }
626    
627            XFree(image);
628            xfree(tdata);
629    }
630    
631    void
632    ui_destroy_bitmap(HBITMAP bmp)
633    {
634            XFreePixmap(display, (Pixmap) bmp);
635    }
636    
637    HGLYPH
638    ui_create_glyph(int width, int height, uint8 * data)
639    {
640            XImage *image;
641            Pixmap bitmap;
642            int scanline;
643            GC gc;
644    
645            scanline = (width + 7) / 8;
646    
647            bitmap = XCreatePixmap(display, wnd, width, height, 1);
648            gc = XCreateGC(display, bitmap, 0, NULL);
649    
650            image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
651                                 width, height, 8, scanline);
652            image->byte_order = MSBFirst;
653            image->bitmap_bit_order = MSBFirst;
654            XInitImage(image);
655    
656            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
657    
658            XFree(image);
659            XFreeGC(display, gc);
660            return (HGLYPH) bitmap;
661    }
662    
663    void
664    ui_destroy_glyph(HGLYPH glyph)
665    {
666            XFreePixmap(display, (Pixmap) glyph);
667    }
668    
669    HCURSOR
670    ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
671                     uint8 * andmask, uint8 * xormask)
672    {
673            HGLYPH maskglyph, cursorglyph;
674            XColor bg, fg;
675            Cursor xcursor;
676            uint8 *cursor, *pcursor;
677            uint8 *mask, *pmask;
678            uint8 nextbit;
679            int scanline, offset;
680            int i, j;
681    
682            scanline = (width + 7) / 8;
683            offset = scanline * height;
684    
685            cursor = xmalloc(offset);
686            memset(cursor, 0, offset);
687    
688            mask = xmalloc(offset);
689            memset(mask, 0, offset);
690    
691            /* approximate AND and XOR masks with a monochrome X pointer */
692            for (i = 0; i < height; i++)
693            {
694                    offset -= scanline;
695                    pcursor = &cursor[offset];
696                    pmask = &mask[offset];
697    
698                    for (j = 0; j < scanline; j++)
699                    {
700                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
701                            {
702                                    if (xormask[0] || xormask[1] || xormask[2])
703                                    {
704                                            *pcursor |= (~(*andmask) & nextbit);
705                                            *pmask |= nextbit;
706                                    }
707                                    else
708                                    {
709                                            *pcursor |= ((*andmask) & nextbit);
710                                            *pmask |= (~(*andmask) & nextbit);
711                                    }
712    
713                                    xormask += 3;
714                            }
715    
716                            andmask++;
717                            pcursor++;
718                            pmask++;
719                    }
720            }
721    
722            fg.red = fg.blue = fg.green = 0xffff;
723            bg.red = bg.blue = bg.green = 0x0000;
724            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
725    
726            cursorglyph = ui_create_glyph(width, height, cursor);
727            maskglyph = ui_create_glyph(width, height, mask);
728    
729            xcursor =
730                    XCreatePixmapCursor(display, (Pixmap) cursorglyph,
731                                        (Pixmap) maskglyph, &fg, &bg, x, y);
732    
733            ui_destroy_glyph(maskglyph);
734            ui_destroy_glyph(cursorglyph);
735            xfree(mask);
736            xfree(cursor);
737            return (HCURSOR) xcursor;
738    }
739    
740    void
741    ui_set_cursor(HCURSOR cursor)
742    {
743            current_cursor = (Cursor) cursor;
744            XDefineCursor(display, wnd, current_cursor);
745    }
746    
747    void
748    ui_destroy_cursor(HCURSOR cursor)
749    {
750            XFreeCursor(display, (Cursor) cursor);
751    }
752    
753    #define MAKE_XCOLOR(xc,c) \
754                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
755                    (xc)->green = ((c)->green << 8) | (c)->green; \
756                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
757                    (xc)->flags = DoRed | DoGreen | DoBlue;
758    
759    HCOLOURMAP
760    ui_create_colourmap(COLOURMAP * colours)
761    {
762            COLOURENTRY *entry;
763            int i, ncolours = colours->ncolours;
764            uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
765            XColor xentry;
766            XColor xc_cache[256];
767            uint32 colour;
768            int colLookup = 256;
769            for (i = 0; i < ncolours; i++)
770            {
771                    entry = &colours->colours[i];
772                    MAKE_XCOLOR(&xentry, entry);
773    
774                    if (XAllocColor(display, xcolmap, &xentry) == 0)
775                    {
776                            /* Allocation failed, find closest match. */
777                            int j = 256;
778                            int nMinDist = 3 * 256 * 256;
779                            long nDist = nMinDist;
780    
781                            /* only get the colors once */
782                            while( colLookup-- ){
783                                    xc_cache[colLookup].pixel = colLookup;
784                                    xc_cache[colLookup].red = xc_cache[colLookup].green = xc_cache[colLookup].blue = 0;
785                                    xc_cache[colLookup].flags = 0;
786                                    XQueryColor(display, DefaultColormap(display, DefaultScreen(display)), &xc_cache[colLookup]);
787                            }
788                            colLookup = 0;
789    
790                            /* approximate the pixel */
791                            while( j-- ){
792                                    if( xc_cache[j].flags ){
793                                            nDist =
794                                            ((long) (xc_cache[j].red >> 8) - (long) (xentry.red >> 8)) *
795                                            ((long) (xc_cache[j].red >> 8) - (long) (xentry.red >> 8)) +
796                                            ((long) (xc_cache[j].green >> 8) - (long) (xentry.green >> 8)) *
797                                            ((long) (xc_cache[j].green >> 8) - (long) (xentry.green >> 8)) +
798                                            ((long) (xc_cache[j].blue >> 8) - (long) (xentry.blue >> 8)) *
799                                            ((long) (xc_cache[j].blue >> 8) - (long) (xentry.blue >> 8));
800                                    }
801                                    if( nDist < nMinDist ){
802                                            nMinDist = nDist;
803                                            xentry.pixel = j;
804                                    }
805                            }
806                    }
807                    colour = xentry.pixel;
808    
809                    /* update our cache */
810                    if( xentry.pixel < 256 ){
811                            xc_cache[xentry.pixel].red = xentry.red;
812                            xc_cache[xentry.pixel].green = xentry.green;
813                            xc_cache[xentry.pixel].blue = xentry.blue;
814    
815                    }
816    
817    
818                    /* byte swap here to make translate_image faster */
819                    map[i] = translate_colour(colour);
820            }
821    
822            return map;
823    }
824    
825          image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,  void
826                                  data, width, height, 32, width);  ui_destroy_colourmap(HCOLOURMAP map)
827    {
828            xfree(map);
829    }
830    
831          return (HBITMAP)image;  void
832    ui_set_colourmap(HCOLOURMAP map)
833    {
834            colmap = map;
835  }  }
836    
837  void ui_destroy_bitmap(HWINDOW wnd, HBITMAP bmp)  void
838    ui_set_clip(int x, int y, int cx, int cy)
839  {  {
840          XDestroyImage((XImage *)bmp);          XRectangle rect;
841    
842            rect.x = x;
843            rect.y = y;
844            rect.width = cx;
845            rect.height = cy;
846            XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
847  }  }
848    
849  void ui_paint_bitmap(HWINDOW wnd, HBITMAP bmp, int x, int y)  void
850    ui_reset_clip(void)
851  {  {
852          XImage *image = (XImage *)bmp;          XRectangle rect;
853    
854          XPutImage(wnd->display, wnd->wnd, wnd->gc, image,          rect.x = 0;
855                          0, 0, x, y, image->width, image->height);          rect.y = 0;
856            rect.width = width;
857            rect.height = height;
858            XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
859    }
860    
861          XSync(wnd->display, True);  void
862    ui_bell(void)
863    {
864            XBell(display, 0);
865  }  }
866    
867  HCOLORMAP ui_create_colormap(HWINDOW wnd, COLORMAP *colors)  void
868    ui_destblt(uint8 opcode,
869               /* dest */ int x, int y, int cx, int cy)
870  {  {
871          COLORENTRY *entry;          SET_FUNCTION(opcode);
872          XColor *xcolors, *xentry;          FILL_RECTANGLE(x, y, cx, cy);
873          Colormap map;          RESET_FUNCTION(opcode);
874          int i, ncolors = colors->ncolors;  }
875    
876          xcolors = malloc(sizeof(XColor) * ncolors);  void
877          for (i = 0; i < ncolors; i++)  ui_patblt(uint8 opcode,
878              /* dest */ int x, int y, int cx, int cy,
879              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
880    {
881            Pixmap fill;
882            uint8 i, ipattern[8];
883    
884            SET_FUNCTION(opcode);
885    
886            switch (brush->style)
887          {          {
888                  entry = &colors->colors[i];                  case 0: /* Solid */
889                  xentry = &xcolors[i];                          SET_FOREGROUND(fgcolour);
890                            FILL_RECTANGLE(x, y, cx, cy);
891                            break;
892    
893                    case 3: /* Pattern */
894                            for (i = 0; i != 8; i++)
895                                    ipattern[7 - i] = brush->pattern[i];
896                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
897    
898                            SET_FOREGROUND(bgcolour);
899                            SET_BACKGROUND(fgcolour);
900                            XSetFillStyle(display, gc, FillOpaqueStippled);
901                            XSetStipple(display, gc, fill);
902                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
903    
904                            FILL_RECTANGLE(x, y, cx, cy);
905    
906                            XSetFillStyle(display, gc, FillSolid);
907                            XSetTSOrigin(display, gc, 0, 0);
908                            ui_destroy_glyph((HGLYPH) fill);
909                            break;
910    
911                  xentry->pixel = i;                  default:
912                  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;  
913          }          }
914    
915          map = XCreateColormap(wnd->display, wnd->wnd, wnd->visual, AllocAll);          RESET_FUNCTION(opcode);
916          XStoreColors(wnd->display, map, xcolors, ncolors);  }
917    
918          free(xcolors);  void
919          return (HCOLORMAP)map;  ui_screenblt(uint8 opcode,
920                 /* dest */ int x, int y, int cx, int cy,
921                 /* src */ int srcx, int srcy)
922    {
923            SET_FUNCTION(opcode);
924            XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
925            if (ownbackstore)
926                    XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
927            RESET_FUNCTION(opcode);
928    }
929    
930    void
931    ui_memblt(uint8 opcode,
932              /* dest */ int x, int y, int cx, int cy,
933              /* src */ HBITMAP src, int srcx, int srcy)
934    {
935            SET_FUNCTION(opcode);
936            XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
937            if (ownbackstore)
938                    XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
939            RESET_FUNCTION(opcode);
940  }  }
941    
942  void ui_destroy_colormap(HWINDOW wnd, HCOLORMAP map)  void
943    ui_triblt(uint8 opcode,
944              /* dest */ int x, int y, int cx, int cy,
945              /* src */ HBITMAP src, int srcx, int srcy,
946              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
947  {  {
948          XFreeColormap(wnd->display, (Colormap)map);          /* This is potentially difficult to do in general. Until someone
949               comes up with a more efficient way of doing it I am using cases. */
950    
951            switch (opcode)
952            {
953                    case 0x69:      /* PDSxxn */
954                            ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
955                            ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
956                            break;
957    
958                    case 0xb8:      /* PSDPxax */
959                            ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
960                            ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
961                            ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
962                            break;
963    
964                    case 0xc0:      /* PSa */
965                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
966                            ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
967                            break;
968    
969                    default:
970                            unimpl("triblt 0x%x\n", opcode);
971                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
972            }
973    }
974    
975    void
976    ui_line(uint8 opcode,
977            /* dest */ int startx, int starty, int endx, int endy,
978            /* pen */ PEN * pen)
979    {
980            SET_FUNCTION(opcode);
981            SET_FOREGROUND(pen->colour);
982            XDrawLine(display, wnd, gc, startx, starty, endx, endy);
983            if (ownbackstore)
984                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
985            RESET_FUNCTION(opcode);
986    }
987    
988    void
989    ui_rect(
990                   /* dest */ int x, int y, int cx, int cy,
991                   /* brush */ int colour)
992    {
993            SET_FOREGROUND(colour);
994            FILL_RECTANGLE(x, y, cx, cy);
995    }
996    
997    void
998    ui_draw_glyph(int mixmode,
999                  /* dest */ int x, int y, int cx, int cy,
1000                  /* src */ HGLYPH glyph, int srcx, int srcy,
1001                  int bgcolour, int fgcolour)
1002    {
1003            SET_FOREGROUND(fgcolour);
1004            SET_BACKGROUND(bgcolour);
1005    
1006            XSetFillStyle(display, gc,
1007                          (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1008            XSetStipple(display, gc, (Pixmap) glyph);
1009            XSetTSOrigin(display, gc, x, y);
1010    
1011            FILL_RECTANGLE(x, y, cx, cy);
1012    
1013            XSetFillStyle(display, gc, FillSolid);
1014    }
1015    
1016    #define DO_GLYPH(ttext,idx) \
1017    {\
1018      glyph = cache_get_font (font, ttext[idx]);\
1019      if (!(flags & TEXT2_IMPLICIT_X))\
1020        {\
1021          xyoffset = ttext[++idx];\
1022          if ((xyoffset & 0x80))\
1023            {\
1024              if (flags & TEXT2_VERTICAL) \
1025                y += ttext[idx+1] | (ttext[idx+2] << 8);\
1026              else\
1027                x += ttext[idx+1] | (ttext[idx+2] << 8);\
1028              idx += 2;\
1029            }\
1030          else\
1031            {\
1032              if (flags & TEXT2_VERTICAL) \
1033                y += xyoffset;\
1034              else\
1035                x += xyoffset;\
1036            }\
1037        }\
1038      if (glyph != NULL)\
1039        {\
1040          ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1041                         y + (short) glyph->baseline,\
1042                         glyph->width, glyph->height,\
1043                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1044          if (flags & TEXT2_IMPLICIT_X)\
1045            x += glyph->width;\
1046        }\
1047  }  }
1048    
1049  void ui_set_colormap(HWINDOW wnd, HCOLORMAP map)  void
1050    ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1051                 int clipx, int clipy, int clipcx, int clipcy,
1052                 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1053                 int fgcolour, uint8 * text, uint8 length)
1054  {  {
1055          XSetWindowColormap(wnd->display, wnd->wnd, (Colormap)map);          FONTGLYPH *glyph;
1056            int i, j, xyoffset;
1057            DATABLOB *entry;
1058    
1059            SET_FOREGROUND(bgcolour);
1060    
1061            if (boxcx > 1)
1062            {
1063                    FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1064            }
1065            else if (mixmode == MIX_OPAQUE)
1066            {
1067                    FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1068            }
1069    
1070            /* Paint text, character by character */
1071            for (i = 0; i < length;)
1072            {
1073                    switch (text[i])
1074                    {
1075                            case 0xff:
1076                                    if (i + 2 < length)
1077                                            cache_put_text(text[i + 1], text, text[i + 2]);
1078                                    else
1079                                    {
1080                                            error("this shouldn't be happening\n");
1081                                            break;
1082                                    }
1083                                    /* this will move pointer from start to first character after FF command */
1084                                    length -= i + 3;
1085                                    text = &(text[i + 3]);
1086                                    i = 0;
1087                                    break;
1088    
1089                            case 0xfe:
1090                                    entry = cache_get_text(text[i + 1]);
1091                                    if (entry != NULL)
1092                                    {
1093                                            if ((((uint8 *) (entry->data))[1] ==
1094                                                 0) && (!(flags & TEXT2_IMPLICIT_X)))
1095                                            {
1096                                                    if (flags & TEXT2_VERTICAL)
1097                                                            y += text[i + 2];
1098                                                    else
1099                                                            x += text[i + 2];
1100                                            }
1101                                            if (i + 2 < length)
1102                                                    i += 3;
1103                                            else
1104                                                    i += 2;
1105                                            length -= i;
1106                                            /* this will move pointer from start to first character after FE command */
1107                                            text = &(text[i]);
1108                                            i = 0;
1109                                            for (j = 0; j < entry->size; j++)
1110                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1111                                    }
1112                                    break;
1113    
1114                            default:
1115                                    DO_GLYPH(text, i);
1116                                    i++;
1117                                    break;
1118                    }
1119            }
1120    
1121    
1122  }  }
1123    
1124  void ui_draw_rectangle(HWINDOW wnd, int x, int y, int width, int height)  void
1125    ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1126  {  {
1127          static int white = 0;          Pixmap pix;
1128            XImage *image;
1129    
1130          XSetForeground(wnd->display, wnd->gc, white);          if (ownbackstore)
1131          XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, width, height);          {
1132                    image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1133            }
1134            else
1135            {
1136                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
1137                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1138                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1139                    XFreePixmap(display, pix);
1140            }
1141    
1142          white++;          offset *= bpp / 8;
1143            cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1144    
1145            XDestroyImage(image);
1146  }  }
1147    
1148  void ui_move_pointer(HWINDOW wnd, int x, int y)  void
1149    ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1150  {  {
1151          XWarpPointer(wnd->display, wnd->wnd, wnd->wnd, 0, 0, 0, 0, x, y);          XImage *image;
1152            uint8 *data;
1153    
1154            offset *= bpp / 8;
1155            data = cache_get_desktop(offset, cx, cy, bpp / 8);
1156            if (data == NULL)
1157                    return;
1158    
1159            image = XCreateImage(display, visual, depth, ZPixmap, 0,
1160                                 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1161    
1162            if (ownbackstore)
1163            {
1164                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1165                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1166            }
1167            else
1168            {
1169                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1170            }
1171    
1172            XFree(image);
1173  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26