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

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

  ViewVC Help
Powered by ViewVC 1.1.26