/[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 100 - (hide annotations)
Sat Aug 24 20:04:56 2002 UTC (21 years, 8 months ago) by jsorg71
File MIME type: text/plain
File size: 27308 byte(s)
toggle full screen

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

  ViewVC Help
Powered by ViewVC 1.1.26