/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

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

  ViewVC Help
Powered by ViewVC 1.1.26