/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 76 - (hide annotations)
Mon Jul 29 20:16:22 2002 UTC (21 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 25039 byte(s)
Applied patch from Bob Bell for -K option

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

  ViewVC Help
Powered by ViewVC 1.1.26