/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 160 - (hide annotations)
Sun Sep 15 12:42:26 2002 UTC (21 years, 8 months ago) by matthewc
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 26645 byte(s)
Now that we have ui_init move rounding of geometry there (it's X-specific).

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 matthewc 160 /* make sure width is a multiple of 4 */
355     width = (width + 3) & ~3;
356    
357 matthewc 121 xkeymap_init();
358 jsorg71 81 return True;
359     }
360 astrand 66
361 matthewc 121 BOOL
362     ui_create_window()
363 matty 6 {
364 matthewc 121 XSetWindowAttributes attribs;
365 matty 28 XClassHint *classhints;
366     XSizeHints *sizehints;
367 jsorg71 100 XEvent xevent;
368    
369 matthewc 121 attribs.background_pixel = BlackPixelOfScreen(screen);
370     attribs.backing_store = ownbackstore ? NotUseful : Always;
371     attribs.override_redirect = fullscreen;
372     wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, width, height,
373     0, CopyFromParent, InputOutput, CopyFromParent,
374     CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
375 jsorg71 100
376 matthewc 123 if (ownbackstore)
377     backstore = XCreatePixmap(display, wnd, width, height, depth);
378    
379 jsorg71 100 XStoreName(display, wnd, title);
380    
381     classhints = XAllocClassHint();
382     if (classhints != NULL)
383     {
384     classhints->res_name = classhints->res_class = "rdesktop";
385     XSetClassHint(display, wnd, classhints);
386     XFree(classhints);
387     }
388    
389     sizehints = XAllocSizeHints();
390     if (sizehints)
391     {
392     sizehints->flags = PMinSize | PMaxSize;
393     sizehints->min_width = sizehints->max_width = width;
394     sizehints->min_height = sizehints->max_height = height;
395     XSetWMNormalHints(display, wnd, sizehints);
396     XFree(sizehints);
397     }
398    
399 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
400     VisibilityChangeMask | FocusChangeMask;
401    
402     if (grab_keyboard)
403     input_mask |= EnterWindowMask | LeaveWindowMask;
404     if (sendmotion)
405     input_mask |= PointerMotionMask;
406     if (ownbackstore)
407     input_mask |= ExposureMask;
408 jsorg71 100 if (enable_compose)
409     input_mask |= init_inputmethod();
410    
411     XSelectInput(display, wnd, input_mask);
412    
413 matthewc 123 xwin_map_window();
414    
415     /* clear the window so that cached data is not seen */
416 jsorg71 100 gc = XCreateGC(display, wnd, 0, NULL);
417     XSetForeground(display, gc, 0);
418     FILL_RECTANGLE(0, 0, width, height);
419    
420 matty 10 return True;
421 matty 6 }
422    
423 matty 25 void
424     ui_destroy_window()
425 matty 6 {
426 matty 31 if (ownbackstore)
427     XFreePixmap(display, backstore);
428    
429 matty 10 XFreeGC(display, gc);
430 astrand 66
431     close_inputmethod();
432    
433 matty 10 XDestroyWindow(display, wnd);
434     XCloseDisplay(display);
435 matty 28 display = NULL;
436 matty 6 }
437    
438 matthewc 123 static void
439     xwin_reset_keys()
440 jsorg71 100 {
441     /* reset keys */
442     uint32 ev_time;
443     ev_time = time(NULL);
444     rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
445     rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
446     rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
447     rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
448     rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
449     rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
450     }
451    
452     void
453 matthewc 123 xwin_toggle_fullscreen()
454 jsorg71 100 {
455 matthewc 123 XEvent xevent;
456     XSetWindowAttributes attribs;
457     int newwidth, newheight;
458    
459     fullscreen = !fullscreen;
460     newwidth = fullscreen ? WidthOfScreen(screen) : width;
461     newheight = fullscreen ? HeightOfScreen(screen) : height;
462    
463     XUnmapWindow(display, wnd);
464     attribs.override_redirect = fullscreen;
465 matthewc 157 XMoveResizeWindow(display, wnd, 0, 0, newwidth, newheight);
466 matthewc 123 XChangeWindowAttributes(display, wnd, CWOverrideRedirect, &attribs);
467     xwin_map_window();
468 jsorg71 100 }
469    
470 astrand 119 /* Process all events in Xlib queue */
471 matty 33 static void
472     xwin_process_events()
473 matty 9 {
474 n-ki 54 XEvent xevent;
475 matthewc 38 KeySym keysym;
476 matthewc 50 uint16 button, flags;
477 matty 10 uint32 ev_time;
478 astrand 66 key_translation tr;
479     char *ksname = NULL;
480     char str[256];
481     Status status;
482 matty 9
483 matthewc 123 while (XPending(display) > 0)
484 matty 9 {
485 matthewc 123 XNextEvent(display, &xevent);
486    
487 astrand 70 if (enable_compose && (XFilterEvent(&xevent, None) == True))
488 astrand 66 {
489 astrand 84 DEBUG_KBD(("Filtering event\n"));
490 astrand 66 continue;
491     }
492    
493 matty 10 ev_time = time(NULL);
494 matthewc 50 flags = 0;
495 matty 10
496 n-ki 54 switch (xevent.type)
497 matty 9 {
498     case KeyPress:
499 astrand 66 if (IC != NULL)
500     /* Multi_key compatible version */
501     {
502     XmbLookupString(IC,
503     (XKeyPressedEvent *) &
504 astrand 82 xevent, str, sizeof(str), &keysym, &status);
505     if (!((status == XLookupKeySym) || (status == XLookupBoth)))
506 astrand 66 {
507 astrand 82 error("XmbLookupString failed with status 0x%x\n",
508     status);
509 astrand 66 break;
510     }
511     }
512     else
513     {
514     /* Plain old XLookupString */
515 astrand 84 DEBUG_KBD(("No input context, using XLookupString\n"));
516 astrand 66 XLookupString((XKeyEvent *) & xevent,
517 astrand 82 str, sizeof(str), &keysym, NULL);
518 astrand 66 }
519    
520     ksname = get_ksname(keysym);
521 astrand 84 DEBUG_KBD(("\nKeyPress for (keysym 0x%lx, %s)\n", keysym, ksname));
522 astrand 66
523 astrand 118 if (handle_special_keys(keysym, ev_time, True))
524     break;
525    
526 astrand 66 tr = xkeymap_translate_key(keysym,
527 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
528 astrand 69
529 astrand 66 if (tr.scancode == 0)
530 n-ki 52 break;
531    
532 astrand 115 ensure_remote_modifiers(ev_time, tr);
533    
534 astrand 82 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
535 astrand 66 break;
536     case KeyRelease:
537     XLookupString((XKeyEvent *) & xevent, str,
538     sizeof(str), &keysym, NULL);
539 n-ki 52
540 astrand 66 ksname = get_ksname(keysym);
541 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
542     ksname));
543 n-ki 52
544 astrand 118 if (handle_special_keys(keysym, ev_time, False))
545     break;
546    
547 astrand 66 tr = xkeymap_translate_key(keysym,
548 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
549 astrand 66
550     if (tr.scancode == 0)
551     break;
552    
553 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
554 matty 9 break;
555    
556     case ButtonPress:
557 matthewc 50 flags = MOUSE_FLAG_DOWN;
558     /* fall through */
559 matty 9
560     case ButtonRelease:
561 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
562 matty 9 if (button == 0)
563     break;
564    
565 matty 10 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
566 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
567 matty 10 break;
568    
569     case MotionNotify:
570     rdp_send_input(ev_time, RDP_INPUT_MOUSE,
571 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
572 matty 28 break;
573    
574     case EnterNotify:
575 astrand 76 if (grab_keyboard)
576     XGrabKeyboard(display, wnd, True,
577 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
578 matty 28 break;
579    
580     case LeaveNotify:
581 astrand 76 if (grab_keyboard)
582     XUngrabKeyboard(display, CurrentTime);
583 matty 28 break;
584 matty 31
585 matthewc 158 case FocusOut:
586     xwin_reset_keys();
587     break;
588    
589 matty 31 case Expose:
590     XCopyArea(display, backstore, wnd, gc,
591 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
592 astrand 64 xevent.xexpose.width,
593     xevent.xexpose.height,
594 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
595 matty 31 break;
596 astrand 119
597     case MappingNotify:
598     /* Refresh keyboard mapping if it has changed. This is important for
599     Xvnc, since it allocates keycodes dynamically */
600     if (xevent.xmapping.request == MappingKeyboard
601     || xevent.xmapping.request == MappingModifier)
602     XRefreshKeyboardMapping(&xevent.xmapping);
603     break;
604    
605 matty 9 }
606     }
607     }
608    
609 matty 25 void
610 matty 33 ui_select(int rdp_socket)
611     {
612 astrand 64 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
613 matty 33 fd_set rfds;
614    
615     FD_ZERO(&rfds);
616    
617     while (True)
618     {
619 matthewc 121 /* Process any events already waiting */
620 astrand 119 xwin_process_events();
621    
622 matty 33 FD_ZERO(&rfds);
623     FD_SET(rdp_socket, &rfds);
624 matthewc 121 FD_SET(x_socket, &rfds);
625 matty 33
626     switch (select(n, &rfds, NULL, NULL, NULL))
627     {
628     case -1:
629     error("select: %s\n", strerror(errno));
630    
631     case 0:
632     continue;
633     }
634    
635     if (FD_ISSET(rdp_socket, &rfds))
636     return;
637     }
638     }
639    
640     void
641 matty 25 ui_move_pointer(int x, int y)
642 matty 9 {
643 matty 10 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
644 matty 9 }
645    
646 matty 25 HBITMAP
647 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
648 matty 6 {
649     XImage *image;
650 matty 9 Pixmap bitmap;
651 matty 28 uint8 *tdata;
652 matty 29
653 matty 33 tdata = (owncolmap ? data : translate_image(width, height, data));
654 matty 28 bitmap = XCreatePixmap(display, wnd, width, height, depth);
655 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
656     (char *) tdata, width, height, 8, 0);
657 matty 6
658 matty 28 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
659 matty 9
660     XFree(image);
661 matty 29 if (!owncolmap)
662 matty 28 xfree(tdata);
663 matty 24 return (HBITMAP) bitmap;
664 matty 6 }
665    
666 matty 25 void
667 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
668 matty 6 {
669 matty 10 XImage *image;
670 matty 29 uint8 *tdata;
671 matty 10
672 matty 33 tdata = (owncolmap ? data : translate_image(width, height, data));
673 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
674     (char *) tdata, width, height, 8, 0);
675 matty 28
676 matty 31 if (ownbackstore)
677     {
678     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
679     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
680     }
681     else
682     {
683     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
684     }
685 matty 29
686 matty 24 XFree(image);
687 matty 29 if (!owncolmap)
688 matty 28 xfree(tdata);
689 matty 6 }
690    
691 matty 25 void
692     ui_destroy_bitmap(HBITMAP bmp)
693 matty 6 {
694 astrand 64 XFreePixmap(display, (Pixmap) bmp);
695 matty 10 }
696    
697 matty 25 HGLYPH
698 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
699 matty 10 {
700 matty 9 XImage *image;
701     Pixmap bitmap;
702     int scanline;
703     GC gc;
704 matty 6
705 matty 9 scanline = (width + 7) / 8;
706 matty 6
707 matty 10 bitmap = XCreatePixmap(display, wnd, width, height, 1);
708     gc = XCreateGC(display, bitmap, 0, NULL);
709 matty 9
710 astrand 77 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
711 astrand 73 width, height, 8, scanline);
712 matty 23 image->byte_order = MSBFirst;
713     image->bitmap_bit_order = MSBFirst;
714     XInitImage(image);
715    
716 matty 10 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
717 matty 29
718 matty 9 XFree(image);
719 matty 10 XFreeGC(display, gc);
720 astrand 64 return (HGLYPH) bitmap;
721 matty 6 }
722 matty 7
723 matty 25 void
724     ui_destroy_glyph(HGLYPH glyph)
725 matty 7 {
726 astrand 64 XFreePixmap(display, (Pixmap) glyph);
727 matty 9 }
728    
729 matty 29 HCURSOR
730 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
731     uint8 * andmask, uint8 * xormask)
732 matty 9 {
733 matty 29 HGLYPH maskglyph, cursorglyph;
734     XColor bg, fg;
735     Cursor xcursor;
736     uint8 *cursor, *pcursor;
737     uint8 *mask, *pmask;
738     uint8 nextbit;
739     int scanline, offset;
740     int i, j;
741    
742     scanline = (width + 7) / 8;
743     offset = scanline * height;
744    
745     cursor = xmalloc(offset);
746     memset(cursor, 0, offset);
747    
748     mask = xmalloc(offset);
749     memset(mask, 0, offset);
750    
751     /* approximate AND and XOR masks with a monochrome X pointer */
752     for (i = 0; i < height; i++)
753 matty 7 {
754 matty 29 offset -= scanline;
755     pcursor = &cursor[offset];
756     pmask = &mask[offset];
757    
758     for (j = 0; j < scanline; j++)
759 matty 28 {
760 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
761     {
762     if (xormask[0] || xormask[1] || xormask[2])
763     {
764     *pcursor |= (~(*andmask) & nextbit);
765     *pmask |= nextbit;
766     }
767     else
768     {
769     *pcursor |= ((*andmask) & nextbit);
770     *pmask |= (~(*andmask) & nextbit);
771     }
772    
773     xormask += 3;
774     }
775    
776     andmask++;
777     pcursor++;
778     pmask++;
779 matty 28 }
780 matty 7 }
781 matty 29
782     fg.red = fg.blue = fg.green = 0xffff;
783     bg.red = bg.blue = bg.green = 0x0000;
784     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
785    
786     cursorglyph = ui_create_glyph(width, height, cursor);
787     maskglyph = ui_create_glyph(width, height, mask);
788    
789 astrand 66 xcursor =
790     XCreatePixmapCursor(display, (Pixmap) cursorglyph,
791     (Pixmap) maskglyph, &fg, &bg, x, y);
792 astrand 64
793 matty 29 ui_destroy_glyph(maskglyph);
794     ui_destroy_glyph(cursorglyph);
795     xfree(mask);
796     xfree(cursor);
797 astrand 64 return (HCURSOR) xcursor;
798 matty 29 }
799    
800     void
801     ui_set_cursor(HCURSOR cursor)
802     {
803 astrand 64 XDefineCursor(display, wnd, (Cursor) cursor);
804 matty 29 }
805    
806     void
807     ui_destroy_cursor(HCURSOR cursor)
808     {
809 astrand 64 XFreeCursor(display, (Cursor) cursor);
810 matty 29 }
811    
812     #define MAKE_XCOLOR(xc,c) \
813     (xc)->red = ((c)->red << 8) | (c)->red; \
814     (xc)->green = ((c)->green << 8) | (c)->green; \
815     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
816     (xc)->flags = DoRed | DoGreen | DoBlue;
817    
818     HCOLOURMAP
819 astrand 64 ui_create_colourmap(COLOURMAP * colours)
820 matty 29 {
821     COLOURENTRY *entry;
822     int i, ncolours = colours->ncolours;
823    
824     if (owncolmap)
825 matty 28 {
826     XColor *xcolours, *xentry;
827     Colormap map;
828 matty 29
829 matty 28 xcolours = xmalloc(sizeof(XColor) * ncolours);
830     for (i = 0; i < ncolours; i++)
831     {
832     entry = &colours->colours[i];
833     xentry = &xcolours[i];
834     xentry->pixel = i;
835 matty 29 MAKE_XCOLOR(xentry, entry);
836 matty 28 }
837 matty 7
838 matty 28 map = XCreateColormap(display, wnd, visual, AllocAll);
839     XStoreColors(display, map, xcolours, ncolours);
840    
841     xfree(xcolours);
842 astrand 64 return (HCOLOURMAP) map;
843 matty 28 }
844 matty 29 else
845     {
846     uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
847     XColor xentry;
848 matty 33 uint32 colour;
849 matty 29
850     for (i = 0; i < ncolours; i++)
851     {
852     entry = &colours->colours[i];
853     MAKE_XCOLOR(&xentry, entry);
854    
855     if (XAllocColor(display, xcolmap, &xentry) != 0)
856 matty 34 colour = xentry.pixel;
857 matty 29 else
858 matthewc 121 colour = WhitePixelOfScreen(screen);
859 matty 33
860     /* byte swap here to make translate_image faster */
861     map[i] = translate_colour(colour);
862 matty 29 }
863    
864     return map;
865     }
866 matty 7 }
867    
868 matty 25 void
869     ui_destroy_colourmap(HCOLOURMAP map)
870 matty 7 {
871 matty 29 if (owncolmap)
872 astrand 64 XFreeColormap(display, (Colormap) map);
873 matty 29 else
874     xfree(map);
875 matty 7 }
876    
877 matty 25 void
878     ui_set_colourmap(HCOLOURMAP map)
879 matty 7 {
880 matty 29 if (owncolmap)
881 astrand 64 XSetWindowColormap(display, wnd, (Colormap) map);
882 matty 29 else
883 matty 28 colmap = map;
884 matty 7 }
885    
886 matty 25 void
887     ui_set_clip(int x, int y, int cx, int cy)
888 matty 7 {
889 matty 9 XRectangle rect;
890 matty 7
891 matty 9 rect.x = x;
892     rect.y = y;
893     rect.width = cx;
894     rect.height = cy;
895 matty 10 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
896 matty 9 }
897 matty 7
898 matty 25 void
899     ui_reset_clip()
900 matty 9 {
901     XRectangle rect;
902    
903     rect.x = 0;
904     rect.y = 0;
905 matty 10 rect.width = width;
906     rect.height = height;
907     XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
908 matty 7 }
909    
910 matty 25 void
911     ui_bell()
912 matty 10 {
913     XBell(display, 0);
914     }
915    
916 matty 25 void
917     ui_destblt(uint8 opcode,
918     /* dest */ int x, int y, int cx, int cy)
919 matty 9 {
920 matty 29 SET_FUNCTION(opcode);
921 matty 31 FILL_RECTANGLE(x, y, cx, cy);
922 matty 29 RESET_FUNCTION(opcode);
923 matty 9 }
924    
925 matty 25 void
926     ui_patblt(uint8 opcode,
927     /* dest */ int x, int y, int cx, int cy,
928 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
929 matty 9 {
930     Pixmap fill;
931 jsorg71 59 uint8 i, ipattern[8];
932 matty 9
933 matty 29 SET_FUNCTION(opcode);
934 matty 9
935     switch (brush->style)
936     {
937 matty 24 case 0: /* Solid */
938 matty 29 SET_FOREGROUND(fgcolour);
939 matty 31 FILL_RECTANGLE(x, y, cx, cy);
940 matty 9 break;
941    
942 matty 24 case 3: /* Pattern */
943 jsorg71 59 for (i = 0; i != 8; i++)
944     ipattern[7 - i] = brush->pattern[i];
945     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
946 matty 9
947 matty 29 SET_FOREGROUND(bgcolour);
948     SET_BACKGROUND(fgcolour);
949     XSetFillStyle(display, gc, FillOpaqueStippled);
950     XSetStipple(display, gc, fill);
951 astrand 82 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
952 matty 9
953 matty 31 FILL_RECTANGLE(x, y, cx, cy);
954 matty 9
955 matty 29 XSetFillStyle(display, gc, FillSolid);
956 jsorg71 80 XSetTSOrigin(display, gc, 0, 0);
957 astrand 64 ui_destroy_glyph((HGLYPH) fill);
958 matty 9 break;
959    
960     default:
961 matty 30 unimpl("brush %d\n", brush->style);
962 matty 9 }
963 matty 29
964     RESET_FUNCTION(opcode);
965 matty 9 }
966    
967 matty 25 void
968     ui_screenblt(uint8 opcode,
969     /* dest */ int x, int y, int cx, int cy,
970     /* src */ int srcx, int srcy)
971 matty 9 {
972 matty 29 SET_FUNCTION(opcode);
973 matty 24 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
974 matty 31 if (ownbackstore)
975 astrand 82 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
976 matty 29 RESET_FUNCTION(opcode);
977 matty 9 }
978    
979 matty 25 void
980     ui_memblt(uint8 opcode,
981     /* dest */ int x, int y, int cx, int cy,
982     /* src */ HBITMAP src, int srcx, int srcy)
983 matty 9 {
984 matty 29 SET_FUNCTION(opcode);
985 astrand 64 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
986 matty 31 if (ownbackstore)
987 astrand 82 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
988 matty 29 RESET_FUNCTION(opcode);
989 matty 9 }
990    
991 matty 25 void
992     ui_triblt(uint8 opcode,
993     /* dest */ int x, int y, int cx, int cy,
994     /* src */ HBITMAP src, int srcx, int srcy,
995 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
996 matty 9 {
997     /* This is potentially difficult to do in general. Until someone
998 matty 10 comes up with a more efficient way of doing it I am using cases. */
999 matty 9
1000     switch (opcode)
1001     {
1002 matty 24 case 0x69: /* PDSxxn */
1003 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1004 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1005 matty 16 break;
1006    
1007 matty 24 case 0xb8: /* PSDPxax */
1008 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1009 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1010 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1011 matty 9 break;
1012    
1013 matty 29 case 0xc0: /* PSa */
1014 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1015 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1016 matty 28 break;
1017    
1018 matty 9 default:
1019 matty 30 unimpl("triblt 0x%x\n", opcode);
1020 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1021 matty 9 }
1022     }
1023    
1024 matty 25 void
1025     ui_line(uint8 opcode,
1026     /* dest */ int startx, int starty, int endx, int endy,
1027 astrand 64 /* pen */ PEN * pen)
1028 matty 9 {
1029 matty 29 SET_FUNCTION(opcode);
1030     SET_FOREGROUND(pen->colour);
1031 matty 10 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1032 matty 31 if (ownbackstore)
1033     XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1034 matty 29 RESET_FUNCTION(opcode);
1035 matty 9 }
1036    
1037 matty 25 void
1038     ui_rect(
1039     /* dest */ int x, int y, int cx, int cy,
1040     /* brush */ int colour)
1041 matty 9 {
1042 matty 29 SET_FOREGROUND(colour);
1043 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1044 matty 9 }
1045    
1046 matty 25 void
1047     ui_draw_glyph(int mixmode,
1048     /* dest */ int x, int y, int cx, int cy,
1049 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1050     int bgcolour, int fgcolour)
1051 matty 9 {
1052 matty 29 SET_FOREGROUND(fgcolour);
1053     SET_BACKGROUND(bgcolour);
1054 matty 9
1055 astrand 66 XSetFillStyle(display, gc,
1056 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1057 astrand 64 XSetStipple(display, gc, (Pixmap) glyph);
1058 matty 29 XSetTSOrigin(display, gc, x, y);
1059 matty 9
1060 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1061 matty 9
1062 matty 29 XSetFillStyle(display, gc, FillSolid);
1063 matty 9 }
1064    
1065 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1066     {\
1067     glyph = cache_get_font (font, ttext[idx]);\
1068     if (!(flags & TEXT2_IMPLICIT_X))\
1069     {\
1070     xyoffset = ttext[++idx];\
1071     if ((xyoffset & 0x80))\
1072     {\
1073     if (flags & TEXT2_VERTICAL) \
1074 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1075 mmihalik 49 else\
1076 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1077     idx += 2;\
1078 mmihalik 49 }\
1079     else\
1080     {\
1081     if (flags & TEXT2_VERTICAL) \
1082     y += xyoffset;\
1083     else\
1084     x += xyoffset;\
1085     }\
1086     }\
1087     if (glyph != NULL)\
1088     {\
1089     ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1090     y + (short) glyph->baseline,\
1091     glyph->width, glyph->height,\
1092     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1093     if (flags & TEXT2_IMPLICIT_X)\
1094     x += glyph->width;\
1095     }\
1096     }
1097    
1098 matty 25 void
1099     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1100 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1101     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1102 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1103 matty 9 {
1104 matty 10 FONTGLYPH *glyph;
1105 mmihalik 49 int i, j, xyoffset;
1106     DATABLOB *entry;
1107 matty 9
1108 matty 29 SET_FOREGROUND(bgcolour);
1109 matty 28
1110 matty 9 if (boxcx > 1)
1111 matty 31 {
1112     FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1113     }
1114 matty 17 else if (mixmode == MIX_OPAQUE)
1115 matty 31 {
1116     FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1117     }
1118 matty 9
1119     /* Paint text, character by character */
1120 astrand 64 for (i = 0; i < length;)
1121     {
1122     switch (text[i])
1123     {
1124     case 0xff:
1125     if (i + 2 < length)
1126 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1127 astrand 64 else
1128     {
1129     error("this shouldn't be happening\n");
1130     break;
1131     }
1132     /* this will move pointer from start to first character after FF command */
1133     length -= i + 3;
1134     text = &(text[i + 3]);
1135     i = 0;
1136 mmihalik 49 break;
1137 matty 9
1138 astrand 64 case 0xfe:
1139     entry = cache_get_text(text[i + 1]);
1140     if (entry != NULL)
1141     {
1142     if ((((uint8 *) (entry->data))[1] ==
1143 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1144 astrand 64 {
1145     if (flags & TEXT2_VERTICAL)
1146     y += text[i + 2];
1147     else
1148     x += text[i + 2];
1149     }
1150     if (i + 2 < length)
1151     i += 3;
1152 mmihalik 49 else
1153 astrand 64 i += 2;
1154     length -= i;
1155     /* this will move pointer from start to first character after FE command */
1156     text = &(text[i]);
1157     i = 0;
1158     for (j = 0; j < entry->size; j++)
1159 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1160 matthewc 44 }
1161 astrand 64 break;
1162 matty 17
1163 astrand 64 default:
1164     DO_GLYPH(text, i);
1165     i++;
1166     break;
1167 matty 29 }
1168 mmihalik 49 }
1169 matty 28
1170 matty 9
1171     }
1172    
1173 matty 25 void
1174     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1175 matty 9 {
1176 matty 28 Pixmap pix;
1177 matty 9 XImage *image;
1178    
1179 matty 31 if (ownbackstore)
1180     {
1181 astrand 82 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1182 matty 31 }
1183     else
1184     {
1185     pix = XCreatePixmap(display, wnd, cx, cy, depth);
1186     XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1187 astrand 82 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1188 matty 31 XFreePixmap(display, pix);
1189     }
1190 matty 28
1191 astrand 64 offset *= bpp / 8;
1192 astrand 82 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1193 matty 28
1194     XDestroyImage(image);
1195 matty 9 }
1196    
1197 matty 25 void
1198     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1199 matty 9 {
1200     XImage *image;
1201 matty 10 uint8 *data;
1202 matty 9
1203 astrand 64 offset *= bpp / 8;
1204     data = cache_get_desktop(offset, cx, cy, bpp / 8);
1205 matty 10 if (data == NULL)
1206     return;
1207 matty 29
1208 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1209 astrand 82 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1210 matty 29
1211 matty 31 if (ownbackstore)
1212     {
1213     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1214     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1215     }
1216     else
1217     {
1218     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1219     }
1220    
1221 matty 9 XFree(image);
1222     }

  ViewVC Help
Powered by ViewVC 1.1.26