/[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 6 by matty, Wed Jul 5 07:44:21 2000 UTC revision 196 by astrand, Wed Sep 25 11:07:12 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  HWINDOW ui_create_window(int width, int height)  /* 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    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            if (bpp < 8)
254            {
255                    error("Less than 8 bpp not currently supported.\n");
256                    XCloseDisplay(display);
257                    return False;
258            }
259    
260            xcolmap = DefaultColormapOfScreen(screen);
261            gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
262    
263            if (DoesBackingStore(screen) != Always)
264                    ownbackstore = True;
265    
266            test = 1;
267            host_be = !(BOOL) (*(uint8 *) (&test));
268            xserver_be = (ImageByteOrder(display) == MSBFirst);
269    
270            if (fullscreen)
271            {
272                    width = WidthOfScreen(screen);
273                    height = HeightOfScreen(screen);
274            }
275    
276            /* make sure width is a multiple of 4 */
277            width = (width + 3) & ~3;
278    
279            if (ownbackstore)
280            {
281                    backstore =
282                            XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
283    
284                    /* clear to prevent rubbish being exposed at startup */
285                    XSetForeground(display, gc, BlackPixelOfScreen(screen));
286                    XFillRectangle(display, backstore, gc, 0, 0, width, height);
287            }
288    
289            if (enable_compose)
290                    IM = XOpenIM(display, NULL, NULL, NULL);
291    
292            xkeymap_init();
293            return True;
294    }
295    
296    void
297    ui_deinit(void)
298    {
299            if (IM != NULL)
300                    XCloseIM(IM);
301    
302            if (ownbackstore)
303                    XFreePixmap(display, backstore);
304    
305            XFreeGC(display, gc);
306            XCloseDisplay(display);
307            display = NULL;
308    }
309    
310    BOOL
311    ui_create_window(void)
312    {
313            XSetWindowAttributes attribs;
314            XClassHint *classhints;
315            XSizeHints *sizehints;
316            int wndwidth, wndheight;
317            long input_mask, ic_input_mask;
318            XEvent xevent;
319    
320            wndwidth = fullscreen ? WidthOfScreen(screen) : width;
321            wndheight = fullscreen ? HeightOfScreen(screen) : height;
322    
323            attribs.background_pixel = BlackPixelOfScreen(screen);
324            attribs.backing_store = ownbackstore ? NotUseful : Always;
325            attribs.override_redirect = fullscreen;
326    
327            wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
328                                0, CopyFromParent, InputOutput, CopyFromParent,
329                                CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
330    
331            XStoreName(display, wnd, title);
332    
333            classhints = XAllocClassHint();
334            if (classhints != NULL)
335            {
336                    classhints->res_name = classhints->res_class = "rdesktop";
337                    XSetClassHint(display, wnd, classhints);
338                    XFree(classhints);
339            }
340    
341            sizehints = XAllocSizeHints();
342            if (sizehints)
343            {
344                    sizehints->flags = PMinSize | PMaxSize;
345                    sizehints->min_width = sizehints->max_width = width;
346                    sizehints->min_height = sizehints->max_height = height;
347                    XSetWMNormalHints(display, wnd, sizehints);
348                    XFree(sizehints);
349            }
350    
351            input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
352                    StructureNotifyMask | FocusChangeMask;
353    
354            if (sendmotion)
355                    input_mask |= PointerMotionMask;
356            if (ownbackstore)
357                    input_mask |= ExposureMask;
358    
359            if (IM != NULL)
360            {
361                    IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
362                                   XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
363    
364                    if ((IC != NULL)
365                        && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
366                            input_mask |= ic_input_mask;
367            }
368    
369            XSelectInput(display, wnd, input_mask);
370            XMapWindow(display, wnd);
371    
372            /* wait for MapNotify */
373            do
374            {
375                    XMaskEvent(display, StructureNotifyMask, &xevent);
376            }
377            while (xevent.type != MapNotify);
378    
379            if (fullscreen)
380                    XSetInputFocus(display, wnd, RevertToPointerRoot, CurrentTime);
381    
382            return True;
383    }
384    
385    void
386    ui_destroy_window(void)
387    {
388            if (IC != NULL)
389                    XDestroyIC(IC);
390    
391            XDestroyWindow(display, wnd);
392    }
393    
394    void
395    xwin_toggle_fullscreen(void)
396    {
397            Pixmap contents = 0;
398    
399            if (!ownbackstore)
400            {
401                    /* need to save contents of window */
402                    contents = XCreatePixmap(display, wnd, width, height, depth);
403                    XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
404            }
405    
406            ui_destroy_window();
407            fullscreen = !fullscreen;
408            ui_create_window();
409    
410            XDefineCursor(display, wnd, current_cursor);
411    
412            if (!ownbackstore)
413            {
414                    XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
415                    XFreePixmap(display, contents);
416            }
417    }
418    
419    /* Process all events in Xlib queue */
420    static void
421    xwin_process_events(void)
422    {
423            XEvent xevent;
424            KeySym keysym;
425            uint16 button, flags;
426            uint32 ev_time;
427            key_translation tr;
428            char *ksname = NULL;
429            char str[256];
430            Status status;
431    
432            while (XPending(display) > 0)
433            {
434                    XNextEvent(display, &xevent);
435    
436                    if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
437                    {
438                            DEBUG_KBD(("Filtering event\n"));
439                            continue;
440                    }
441    
442                    ev_time = time(NULL);
443                    flags = 0;
444    
445                    switch (xevent.type)
446                    {
447                            case KeyPress:
448                                    if (IC != NULL)
449                                            /* Multi_key compatible version */
450                                    {
451                                            XmbLookupString(IC,
452                                                            (XKeyPressedEvent *) &
453                                                            xevent, str, sizeof(str), &keysym, &status);
454                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
455                                            {
456                                                    error("XmbLookupString failed with status 0x%x\n",
457                                                          status);
458                                                    break;
459                                            }
460                                    }
461                                    else
462                                    {
463                                            /* Plain old XLookupString */
464                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
465                                            XLookupString((XKeyEvent *) & xevent,
466                                                          str, sizeof(str), &keysym, NULL);
467                                    }
468    
469                                    ksname = get_ksname(keysym);
470                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym, ksname));
471    
472                                    if (handle_special_keys(keysym, ev_time, True))
473                                            break;
474    
475                                    tr = xkeymap_translate_key(keysym,
476                                                               xevent.xkey.keycode, xevent.xkey.state);
477    
478                                    if (tr.scancode == 0)
479                                            break;
480    
481                                    ensure_remote_modifiers(ev_time, tr);
482    
483                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
484                                    break;
485                            case KeyRelease:
486                                    XLookupString((XKeyEvent *) & xevent, str,
487                                                  sizeof(str), &keysym, NULL);
488    
489                                    ksname = get_ksname(keysym);
490                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
491                                               ksname));
492    
493                                    if (handle_special_keys(keysym, ev_time, False))
494                                            break;
495    
496                                    tr = xkeymap_translate_key(keysym,
497                                                               xevent.xkey.keycode, xevent.xkey.state);
498    
499                                    if (tr.scancode == 0)
500                                            break;
501    
502                                    rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
503                                    break;
504    
505                            case ButtonPress:
506                                    flags = MOUSE_FLAG_DOWN;
507                                    /* fall through */
508    
509                            case ButtonRelease:
510                                    button = xkeymap_translate_button(xevent.xbutton.button);
511                                    if (button == 0)
512                                            break;
513    
514                                    rdp_send_input(ev_time, RDP_INPUT_MOUSE,
515                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
516                                    break;
517    
518                            case MotionNotify:
519                                    rdp_send_input(ev_time, RDP_INPUT_MOUSE,
520                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
521                                    break;
522    
523                            case FocusIn:
524                                    reset_modifier_keys();
525                                    if (grab_keyboard)
526                                            XGrabKeyboard(display, wnd, True,
527                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
528                                    break;
529    
530                            case FocusOut:
531                                    if (grab_keyboard)
532                                            XUngrabKeyboard(display, CurrentTime);
533                                    break;
534    
535                            case Expose:
536                                    XCopyArea(display, backstore, wnd, gc,
537                                              xevent.xexpose.x, xevent.xexpose.y,
538                                              xevent.xexpose.width,
539                                              xevent.xexpose.height,
540                                              xevent.xexpose.x, xevent.xexpose.y);
541                                    break;
542    
543                            case MappingNotify:
544                                    /* Refresh keyboard mapping if it has changed. This is important for
545                                       Xvnc, since it allocates keycodes dynamically */
546                                    if (xevent.xmapping.request == MappingKeyboard
547                                        || xevent.xmapping.request == MappingModifier)
548                                            XRefreshKeyboardMapping(&xevent.xmapping);
549                                    break;
550    
551                    }
552            }
553    }
554    
555    void
556    ui_select(int rdp_socket)
557    {
558            int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
559            fd_set rfds;
560    
561            FD_ZERO(&rfds);
562    
563            while (True)
564            {
565                    /* Process any events already waiting */
566                    xwin_process_events();
567    
568                    FD_ZERO(&rfds);
569                    FD_SET(rdp_socket, &rfds);
570                    FD_SET(x_socket, &rfds);
571    
572          black = BlackPixel(display, DefaultScreen(display));                  switch (select(n, &rfds, NULL, NULL, NULL))
573          window = XCreateSimpleWindow(display, DefaultRootWindow(display),                  {
574                                  0, 0, width, height, 0, black, black);                          case -1:
575                                    error("select: %s\n", strerror(errno));
576    
577          XMapWindow(display, window);                          case 0:
578          XSync(display, True);                                  continue;
579                    }
580    
581          gc = XCreateGC(display, window, 0, NULL);                  if (FD_ISSET(rdp_socket, &rfds))
582                            return;
583            }
584    }
585    
586          wnd = xmalloc(sizeof(struct window));  void
587          wnd->display = display;  ui_move_pointer(int x, int y)
588          wnd->wnd = window;  {
589          wnd->gc = gc;          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
         return wnd;  
590  }  }
591    
592  void ui_destroy_window(HWINDOW wnd)  HBITMAP
593    ui_create_bitmap(int width, int height, uint8 * data)
594  {  {
595          XFreeGC(wnd->display, wnd->gc);          XImage *image;
596          XDestroyWindow(wnd->display, wnd->wnd);          Pixmap bitmap;
597          XCloseDisplay(wnd->display);          uint8 *tdata;
598    
599            tdata = translate_image(width, height, data);
600            bitmap = XCreatePixmap(display, wnd, width, height, depth);
601            image = XCreateImage(display, visual, depth, ZPixmap, 0,
602                                 (char *) tdata, width, height, 8, 0);
603    
604            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
605    
606            XFree(image);
607            xfree(tdata);
608            return (HBITMAP) bitmap;
609  }  }
610    
611  HBITMAP ui_create_bitmap(HWINDOW wnd, int width, int height, uint8 *data)  void
612    ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
613  {  {
614          XImage *image;          XImage *image;
615          Visual *visual;          uint8 *tdata;
616    
617            tdata = translate_image(width, height, data);
618            image = XCreateImage(display, visual, depth, ZPixmap, 0,
619                                 (char *) tdata, width, height, 8, 0);
620    
621            if (ownbackstore)
622            {
623                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
624                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
625            }
626            else
627            {
628                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
629            }
630    
631            XFree(image);
632            xfree(tdata);
633    }
634    
635    void
636    ui_destroy_bitmap(HBITMAP bmp)
637    {
638            XFreePixmap(display, (Pixmap) bmp);
639    }
640    
641    HGLYPH
642    ui_create_glyph(int width, int height, uint8 * data)
643    {
644            XImage *image;
645            Pixmap bitmap;
646            int scanline;
647            GC gc;
648    
649            scanline = (width + 7) / 8;
650    
651            bitmap = XCreatePixmap(display, wnd, width, height, 1);
652            gc = XCreateGC(display, bitmap, 0, NULL);
653    
654            image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
655                                 width, height, 8, scanline);
656            image->byte_order = MSBFirst;
657            image->bitmap_bit_order = MSBFirst;
658            XInitImage(image);
659    
660            XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
661    
662            XFree(image);
663            XFreeGC(display, gc);
664            return (HGLYPH) bitmap;
665    }
666    
667    void
668    ui_destroy_glyph(HGLYPH glyph)
669    {
670            XFreePixmap(display, (Pixmap) glyph);
671    }
672    
673    HCURSOR
674    ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
675                     uint8 * andmask, uint8 * xormask)
676    {
677            HGLYPH maskglyph, cursorglyph;
678            XColor bg, fg;
679            Cursor xcursor;
680            uint8 *cursor, *pcursor;
681            uint8 *mask, *pmask;
682            uint8 nextbit;
683            int scanline, offset;
684            int i, j;
685    
686            scanline = (width + 7) / 8;
687            offset = scanline * height;
688    
689            cursor = xmalloc(offset);
690            memset(cursor, 0, offset);
691    
692            mask = xmalloc(offset);
693            memset(mask, 0, offset);
694    
695            /* approximate AND and XOR masks with a monochrome X pointer */
696            for (i = 0; i < height; i++)
697            {
698                    offset -= scanline;
699                    pcursor = &cursor[offset];
700                    pmask = &mask[offset];
701    
702                    for (j = 0; j < scanline; j++)
703                    {
704                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
705                            {
706                                    if (xormask[0] || xormask[1] || xormask[2])
707                                    {
708                                            *pcursor |= (~(*andmask) & nextbit);
709                                            *pmask |= nextbit;
710                                    }
711                                    else
712                                    {
713                                            *pcursor |= ((*andmask) & nextbit);
714                                            *pmask |= (~(*andmask) & nextbit);
715                                    }
716    
717                                    xormask += 3;
718                            }
719    
720                            andmask++;
721                            pcursor++;
722                            pmask++;
723                    }
724            }
725    
726            fg.red = fg.blue = fg.green = 0xffff;
727            bg.red = bg.blue = bg.green = 0x0000;
728            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
729    
730            cursorglyph = ui_create_glyph(width, height, cursor);
731            maskglyph = ui_create_glyph(width, height, mask);
732    
733            xcursor =
734                    XCreatePixmapCursor(display, (Pixmap) cursorglyph,
735                                        (Pixmap) maskglyph, &fg, &bg, x, y);
736    
737            ui_destroy_glyph(maskglyph);
738            ui_destroy_glyph(cursorglyph);
739            xfree(mask);
740            xfree(cursor);
741            return (HCURSOR) xcursor;
742    }
743    
744    void
745    ui_set_cursor(HCURSOR cursor)
746    {
747            current_cursor = (Cursor) cursor;
748            XDefineCursor(display, wnd, current_cursor);
749    }
750    
751    void
752    ui_destroy_cursor(HCURSOR cursor)
753    {
754            XFreeCursor(display, (Cursor) cursor);
755    }
756    
757    #define MAKE_XCOLOR(xc,c) \
758                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
759                    (xc)->green = ((c)->green << 8) | (c)->green; \
760                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
761                    (xc)->flags = DoRed | DoGreen | DoBlue;
762    
763    HCOLOURMAP
764    ui_create_colourmap(COLOURMAP * colours)
765    {
766            COLOURENTRY *entry;
767            int i, ncolours = colours->ncolours;
768            uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
769            XColor xentry;
770            XColor xc_cache[256];
771            uint32 colour;
772            int colLookup = 256;
773            for (i = 0; i < ncolours; i++)
774            {
775                    entry = &colours->colours[i];
776                    MAKE_XCOLOR(&xentry, entry);
777    
778                    if (XAllocColor(display, xcolmap, &xentry) == 0)
779                    {
780                            /* Allocation failed, find closest match. */
781                            int j = 256;
782                            int nMinDist = 3 * 256 * 256;
783                            long nDist = nMinDist;
784    
785                            /* only get the colors once */
786                            while (colLookup--)
787                            {
788                                    xc_cache[colLookup].pixel = colLookup;
789                                    xc_cache[colLookup].red = xc_cache[colLookup].green =
790                                            xc_cache[colLookup].blue = 0;
791                                    xc_cache[colLookup].flags = 0;
792                                    XQueryColor(display,
793                                                DefaultColormap(display, DefaultScreen(display)),
794                                                &xc_cache[colLookup]);
795                            }
796                            colLookup = 0;
797    
798                            /* approximate the pixel */
799                            while (j--)
800                            {
801                                    if (xc_cache[j].flags)
802                                    {
803                                            nDist = ((long) (xc_cache[j].red >> 8) -
804                                                     (long) (xentry.red >> 8)) *
805                                                    ((long) (xc_cache[j].red >> 8) -
806                                                     (long) (xentry.red >> 8)) +
807                                                    ((long) (xc_cache[j].green >> 8) -
808                                                     (long) (xentry.green >> 8)) *
809                                                    ((long) (xc_cache[j].green >> 8) -
810                                                     (long) (xentry.green >> 8)) +
811                                                    ((long) (xc_cache[j].blue >> 8) -
812                                                     (long) (xentry.blue >> 8)) *
813                                                    ((long) (xc_cache[j].blue >> 8) -
814                                                     (long) (xentry.blue >> 8));
815                                    }
816                                    if (nDist < nMinDist)
817                                    {
818                                            nMinDist = nDist;
819                                            xentry.pixel = j;
820                                    }
821                            }
822                    }
823                    colour = xentry.pixel;
824    
825                    /* update our cache */
826                    if (xentry.pixel < 256)
827                    {
828                            xc_cache[xentry.pixel].red = xentry.red;
829                            xc_cache[xentry.pixel].green = xentry.green;
830                            xc_cache[xentry.pixel].blue = xentry.blue;
831    
832                    }
833    
834    
835                    /* byte swap here to make translate_image faster */
836                    map[i] = translate_colour(colour);
837            }
838    
839            return map;
840    }
841    
842    void
843    ui_destroy_colourmap(HCOLOURMAP map)
844    {
845            xfree(map);
846    }
847    
848    void
849    ui_set_colourmap(HCOLOURMAP map)
850    {
851            colmap = map;
852    }
853    
854    void
855    ui_set_clip(int x, int y, int cx, int cy)
856    {
857            XRectangle rect;
858    
859          visual = DefaultVisual(wnd->display, DefaultScreen(wnd->display));          rect.x = x;
860          image = XCreateImage(wnd->display, visual, 8, ZPixmap, 0,          rect.y = y;
861                                  data, width, height, 32, width);          rect.width = cx;
862            rect.height = cy;
863            XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
864    }
865    
866          return (HBITMAP)image;  void
867    ui_reset_clip(void)
868    {
869            XRectangle rect;
870    
871            rect.x = 0;
872            rect.y = 0;
873            rect.width = width;
874            rect.height = height;
875            XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
876  }  }
877    
878  void ui_destroy_bitmap(HBITMAP bmp)  void
879    ui_bell(void)
880  {  {
881          XDestroyImage((XImage *)bmp);          XBell(display, 0);
882  }  }
883    
884  void ui_paint_bitmap(HWINDOW wnd, HBITMAP bmp, int x, int y)  void
885    ui_destblt(uint8 opcode,
886               /* dest */ int x, int y, int cx, int cy)
887  {  {
888          XImage *image = (XImage *)bmp;          SET_FUNCTION(opcode);
889            FILL_RECTANGLE(x, y, cx, cy);
890            RESET_FUNCTION(opcode);
891    }
892    
893    void
894    ui_patblt(uint8 opcode,
895              /* dest */ int x, int y, int cx, int cy,
896              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
897    {
898            Pixmap fill;
899            uint8 i, ipattern[8];
900    
901            SET_FUNCTION(opcode);
902    
903            switch (brush->style)
904            {
905                    case 0: /* Solid */
906                            SET_FOREGROUND(fgcolour);
907                            FILL_RECTANGLE(x, y, cx, cy);
908                            break;
909    
910                    case 3: /* Pattern */
911                            for (i = 0; i != 8; i++)
912                                    ipattern[7 - i] = brush->pattern[i];
913                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
914    
915                            SET_FOREGROUND(bgcolour);
916                            SET_BACKGROUND(fgcolour);
917                            XSetFillStyle(display, gc, FillOpaqueStippled);
918                            XSetStipple(display, gc, fill);
919                            XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
920    
921                            FILL_RECTANGLE(x, y, cx, cy);
922    
923                            XSetFillStyle(display, gc, FillSolid);
924                            XSetTSOrigin(display, gc, 0, 0);
925                            ui_destroy_glyph((HGLYPH) fill);
926                            break;
927    
928                    default:
929                            unimpl("brush %d\n", brush->style);
930            }
931    
932            RESET_FUNCTION(opcode);
933    }
934    
935    void
936    ui_screenblt(uint8 opcode,
937                 /* dest */ int x, int y, int cx, int cy,
938                 /* src */ int srcx, int srcy)
939    {
940            SET_FUNCTION(opcode);
941            XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
942            if (ownbackstore)
943                    XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
944            RESET_FUNCTION(opcode);
945    }
946    
947    void
948    ui_memblt(uint8 opcode,
949              /* dest */ int x, int y, int cx, int cy,
950              /* src */ HBITMAP src, int srcx, int srcy)
951    {
952            SET_FUNCTION(opcode);
953            XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
954            if (ownbackstore)
955                    XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
956            RESET_FUNCTION(opcode);
957    }
958    
959    void
960    ui_triblt(uint8 opcode,
961              /* dest */ int x, int y, int cx, int cy,
962              /* src */ HBITMAP src, int srcx, int srcy,
963              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
964    {
965            /* This is potentially difficult to do in general. Until someone
966               comes up with a more efficient way of doing it I am using cases. */
967    
968            switch (opcode)
969            {
970                    case 0x69:      /* PDSxxn */
971                            ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
972                            ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
973                            break;
974    
975                    case 0xb8:      /* PSDPxax */
976                            ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
977                            ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
978                            ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
979                            break;
980    
981                    case 0xc0:      /* PSa */
982                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
983                            ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
984                            break;
985    
986                    default:
987                            unimpl("triblt 0x%x\n", opcode);
988                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
989            }
990    }
991    
992    void
993    ui_line(uint8 opcode,
994            /* dest */ int startx, int starty, int endx, int endy,
995            /* pen */ PEN * pen)
996    {
997            SET_FUNCTION(opcode);
998            SET_FOREGROUND(pen->colour);
999            XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1000            if (ownbackstore)
1001                    XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1002            RESET_FUNCTION(opcode);
1003    }
1004    
1005    void
1006    ui_rect(
1007                   /* dest */ int x, int y, int cx, int cy,
1008                   /* brush */ int colour)
1009    {
1010            SET_FOREGROUND(colour);
1011            FILL_RECTANGLE(x, y, cx, cy);
1012    }
1013    
1014    void
1015    ui_draw_glyph(int mixmode,
1016                  /* dest */ int x, int y, int cx, int cy,
1017                  /* src */ HGLYPH glyph, int srcx, int srcy,
1018                  int bgcolour, int fgcolour)
1019    {
1020            SET_FOREGROUND(fgcolour);
1021            SET_BACKGROUND(bgcolour);
1022    
1023            XSetFillStyle(display, gc,
1024                          (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1025            XSetStipple(display, gc, (Pixmap) glyph);
1026            XSetTSOrigin(display, gc, x, y);
1027    
1028            FILL_RECTANGLE(x, y, cx, cy);
1029    
1030            XSetFillStyle(display, gc, FillSolid);
1031    }
1032    
1033    #define DO_GLYPH(ttext,idx) \
1034    {\
1035      glyph = cache_get_font (font, ttext[idx]);\
1036      if (!(flags & TEXT2_IMPLICIT_X))\
1037        {\
1038          xyoffset = ttext[++idx];\
1039          if ((xyoffset & 0x80))\
1040            {\
1041              if (flags & TEXT2_VERTICAL) \
1042                y += ttext[idx+1] | (ttext[idx+2] << 8);\
1043              else\
1044                x += ttext[idx+1] | (ttext[idx+2] << 8);\
1045              idx += 2;\
1046            }\
1047          else\
1048            {\
1049              if (flags & TEXT2_VERTICAL) \
1050                y += xyoffset;\
1051              else\
1052                x += xyoffset;\
1053            }\
1054        }\
1055      if (glyph != NULL)\
1056        {\
1057          ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1058                         y + (short) glyph->baseline,\
1059                         glyph->width, glyph->height,\
1060                         glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1061          if (flags & TEXT2_IMPLICIT_X)\
1062            x += glyph->width;\
1063        }\
1064    }
1065    
1066    void
1067    ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1068                 int clipx, int clipy, int clipcx, int clipcy,
1069                 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1070                 int fgcolour, uint8 * text, uint8 length)
1071    {
1072            FONTGLYPH *glyph;
1073            int i, j, xyoffset;
1074            DATABLOB *entry;
1075    
1076            SET_FOREGROUND(bgcolour);
1077    
1078            if (boxcx > 1)
1079            {
1080                    FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1081            }
1082            else if (mixmode == MIX_OPAQUE)
1083            {
1084                    FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1085            }
1086    
1087            /* Paint text, character by character */
1088            for (i = 0; i < length;)
1089            {
1090                    switch (text[i])
1091                    {
1092                            case 0xff:
1093                                    if (i + 2 < length)
1094                                            cache_put_text(text[i + 1], text, text[i + 2]);
1095                                    else
1096                                    {
1097                                            error("this shouldn't be happening\n");
1098                                            break;
1099                                    }
1100                                    /* this will move pointer from start to first character after FF command */
1101                                    length -= i + 3;
1102                                    text = &(text[i + 3]);
1103                                    i = 0;
1104                                    break;
1105    
1106                            case 0xfe:
1107                                    entry = cache_get_text(text[i + 1]);
1108                                    if (entry != NULL)
1109                                    {
1110                                            if ((((uint8 *) (entry->data))[1] ==
1111                                                 0) && (!(flags & TEXT2_IMPLICIT_X)))
1112                                            {
1113                                                    if (flags & TEXT2_VERTICAL)
1114                                                            y += text[i + 2];
1115                                                    else
1116                                                            x += text[i + 2];
1117                                            }
1118                                            if (i + 2 < length)
1119                                                    i += 3;
1120                                            else
1121                                                    i += 2;
1122                                            length -= i;
1123                                            /* this will move pointer from start to first character after FE command */
1124                                            text = &(text[i]);
1125                                            i = 0;
1126                                            for (j = 0; j < entry->size; j++)
1127                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1128                                    }
1129                                    break;
1130    
1131                            default:
1132                                    DO_GLYPH(text, i);
1133                                    i++;
1134                                    break;
1135                    }
1136            }
1137    
1138    
1139    }
1140    
1141    void
1142    ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1143    {
1144            Pixmap pix;
1145            XImage *image;
1146    
1147            if (ownbackstore)
1148            {
1149                    image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1150            }
1151            else
1152            {
1153                    pix = XCreatePixmap(display, wnd, cx, cy, depth);
1154                    XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1155                    image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1156                    XFreePixmap(display, pix);
1157            }
1158    
1159            offset *= bpp / 8;
1160            cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1161    
1162            XDestroyImage(image);
1163    }
1164    
1165    void
1166    ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1167    {
1168            XImage *image;
1169            uint8 *data;
1170    
1171            offset *= bpp / 8;
1172            data = cache_get_desktop(offset, cx, cy, bpp / 8);
1173            if (data == NULL)
1174                    return;
1175    
1176            image = XCreateImage(display, visual, depth, ZPixmap, 0,
1177                                 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1178    
1179          XPutImage(wnd->display, wnd->wnd, wnd->gc, image,          if (ownbackstore)
1180                          0, 0, x, y, image->width, image->height);          {
1181                    XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1182                    XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1183            }
1184            else
1185            {
1186                    XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1187            }
1188    
1189          XSync(wnd->display, True);          XFree(image);
1190  }  }

Legend:
Removed from v.6  
changed lines
  Added in v.196

  ViewVC Help
Powered by ViewVC 1.1.26