/[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

Contents of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 118 - (show annotations)
Wed Sep 11 11:45:20 2002 UTC (21 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 27911 byte(s)
Support for Windows keys (via Ctrl-Esc)

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

  ViewVC Help
Powered by ViewVC 1.1.26