/[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 123 - (hide annotations)
Sat Sep 14 13:47:24 2002 UTC (21 years, 8 months ago) by matthewc
File MIME type: text/plain
File size: 26616 byte(s)
Rewrite of toggle_fullscreen so it modifies the attributes of the existing
window instead of creating a new one.

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

  ViewVC Help
Powered by ViewVC 1.1.26