/[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 182 - (hide annotations)
Tue Sep 17 16:55:43 2002 UTC (21 years, 8 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 26159 byte(s)
Small line-break fix for DEBUG_KBD.

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

  ViewVC Help
Powered by ViewVC 1.1.26