/[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 121 - (hide annotations)
Sat Sep 14 11:48:44 2002 UTC (21 years, 8 months ago) by matthewc
File MIME type: text/plain
File size: 27033 byte(s)
Move non-window-related initialisation to ui_init.
All functions after ui_init can now assume display and other globals are valid.

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

  ViewVC Help
Powered by ViewVC 1.1.26