/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 116 - (show annotations)
Wed Sep 11 11:11:27 2002 UTC (21 years, 8 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 27968 byte(s)
Inhibited keys are defined in keymap files; not hardcoded

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

  ViewVC Help
Powered by ViewVC 1.1.26