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

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

  ViewVC Help
Powered by ViewVC 1.1.26