/[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 158 - (hide annotations)
Sun Sep 15 11:53:50 2002 UTC (21 years, 8 months ago) by matthewc
File MIME type: text/plain
File size: 26575 byte(s)
Possible fix for "flashing title bar" problem (don't grab in response
to FocusIn/FocusOut - seems to cause an event loop).

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

  ViewVC Help
Powered by ViewVC 1.1.26