/[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 100 - (show 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 /*
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 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 if (fullscreen)
261 {
262 screen = DefaultScreenOfDisplay(display);
263 width = WidthOfScreen(screen);
264 height = HeightOfScreen(screen);
265 }
266 return True;
267 }
268
269 BOOL
270 ui_create_window_obj(int xpos, int ypos, int width, int height, int valuemask)
271 {
272 XClassHint *classhints;
273 XSizeHints *sizehints;
274 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 XPixmapFormatValues *pfm;
335 Screen *screen;
336 uint16 test;
337 int i;
338
339 x_socket = ConnectionNumber(display);
340 screen = DefaultScreenOfDisplay(display);
341 visual = DefaultVisualOfScreen(screen);
342 depth = DefaultDepthOfScreen(screen);
343
344 pfm = XListPixmapFormats(display, &i);
345 if (pfm != NULL)
346 {
347 /* Use maximum bpp for this depth - this is generally
348 desirable, e.g. 24 bits->32 bits. */
349 while (i--)
350 {
351 if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
352 {
353 bpp = pfm[i].bits_per_pixel;
354 }
355 }
356 XFree(pfm);
357 }
358
359 if (bpp < 8)
360 {
361 error("Less than 8 bpp not currently supported.\n");
362 XCloseDisplay(display);
363 return False;
364 }
365
366 if (depth <= 8)
367 owncolmap = True;
368 else
369 xcolmap = DefaultColormapOfScreen(screen);
370
371 test = 1;
372 host_be = !(BOOL) (*(uint8 *) (&test));
373 xserver_be = (ImageByteOrder(display) == MSBFirst);
374
375 white = WhitePixelOfScreen(screen);
376 attribs.background_pixel = BlackPixelOfScreen(screen);
377 attribs.backing_store = DoesBackingStore(screen);
378
379 if (attribs.backing_store == NotUseful)
380 ownbackstore = True;
381
382 dpy_width = WidthOfScreen(screen);
383 dpy_height = HeightOfScreen(screen);
384
385 if (fullscreen)
386 {
387 attribs.override_redirect = True;
388 width = dpy_width;
389 height = dpy_height;
390 }
391 else
392 {
393 attribs.override_redirect = False;
394 }
395
396 width = (width + 3) & ~3; /* make width a multiple of 32 bits */
397
398
399 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
400 VisibilityChangeMask | FocusChangeMask;
401
402 if (grab_keyboard)
403 input_mask |= EnterWindowMask | LeaveWindowMask;
404 if (sendmotion)
405 input_mask |= PointerMotionMask;
406
407 if (ownbackstore)
408 input_mask |= ExposureMask;
409
410 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
415 xkeymap_init2();
416
417 return True;
418 }
419
420 void
421 ui_destroy_window()
422 {
423 if (ownbackstore)
424 XFreePixmap(display, backstore);
425
426 XFreeGC(display, gc);
427
428 close_inputmethod();
429
430 XDestroyWindow(display, wnd);
431 XCloseDisplay(display);
432 display = NULL;
433 }
434
435 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 static void
486 xwin_process_events()
487 {
488 XEvent xevent;
489
490 KeySym keysym;
491 uint16 button, flags;
492 uint32 ev_time;
493 key_translation tr;
494 char *ksname = NULL;
495 char str[256];
496 Status status;
497
498 /* Refresh keyboard mapping if it has changed. This is important for
499 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 while (XCheckMaskEvent(display, ~0, &xevent))
508 {
509 if (enable_compose && (XFilterEvent(&xevent, None) == True))
510 {
511 DEBUG_KBD(("Filtering event\n"));
512 continue;
513 }
514
515 ev_time = time(NULL);
516 flags = 0;
517
518 switch (xevent.type)
519 {
520 case KeyPress:
521 if (IC != NULL)
522 /* Multi_key compatible version */
523 {
524 XmbLookupString(IC,
525 (XKeyPressedEvent *) &
526 xevent, str, sizeof(str), &keysym, &status);
527 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
528 {
529 error("XmbLookupString failed with status 0x%x\n",
530 status);
531 break;
532 }
533 }
534 else
535 {
536 /* Plain old XLookupString */
537 DEBUG_KBD(("No input context, using XLookupString\n"));
538 XLookupString((XKeyEvent *) & xevent,
539 str, sizeof(str), &keysym, NULL);
540 }
541
542 /* FIXME needs alt modifier */
543 if (keysym == XK_Break) /* toggle full screen */
544 {
545 toggle_fullscreen();
546 break;
547 }
548 ksname = get_ksname(keysym);
549 DEBUG_KBD(("\nKeyPress for (keysym 0x%lx, %s)\n", keysym, ksname));
550
551 if (inhibit_key(keysym))
552 {
553 DEBUG_KBD(("Inhibiting key\n"));
554 break;
555 }
556
557 tr = xkeymap_translate_key(keysym,
558 xevent.xkey.keycode, xevent.xkey.state);
559
560 ensure_remote_modifiers(ev_time, tr);
561
562 if (tr.scancode == 0)
563 break;
564
565 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
566 break;
567 case KeyRelease:
568 XLookupString((XKeyEvent *) & xevent, str,
569 sizeof(str), &keysym, NULL);
570
571 ksname = get_ksname(keysym);
572 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
573 ksname));
574
575 if (inhibit_key(keysym))
576 break;
577
578 tr = xkeymap_translate_key(keysym,
579 xevent.xkey.keycode, xevent.xkey.state);
580
581 if (tr.scancode == 0)
582 break;
583
584 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
585 break;
586
587 case ButtonPress:
588 flags = MOUSE_FLAG_DOWN;
589 /* fall through */
590
591 case ButtonRelease:
592 button = xkeymap_translate_button(xevent.xbutton.button);
593 if (button == 0)
594 break;
595
596 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
597 flags | button, xevent.xbutton.x, xevent.xbutton.y);
598 break;
599
600 case MotionNotify:
601 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
602 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
603 break;
604
605 case FocusIn:
606 /* fall through */
607 case EnterNotify:
608 if (grab_keyboard)
609 XGrabKeyboard(display, wnd, True,
610 GrabModeAsync, GrabModeAsync, CurrentTime);
611 break;
612
613 case FocusOut:
614 reset_keys();
615 /* fall through */
616 case LeaveNotify:
617 if (grab_keyboard)
618 XUngrabKeyboard(display, CurrentTime);
619 break;
620
621 case Expose:
622 XCopyArea(display, backstore, wnd, gc,
623 xevent.xexpose.x, xevent.xexpose.y,
624 xevent.xexpose.width,
625 xevent.xexpose.height,
626 xevent.xexpose.x, xevent.xexpose.y);
627 break;
628 }
629 }
630 }
631
632 void
633 ui_select(int rdp_socket)
634 {
635 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
636 fd_set rfds;
637
638 FD_ZERO(&rfds);
639
640 while (True)
641 {
642 FD_ZERO(&rfds);
643 FD_SET(rdp_socket, &rfds);
644 if (display != NULL)
645 {
646 FD_SET(x_socket, &rfds);
647 XFlush(display);
648 }
649
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 ui_move_pointer(int x, int y)
669 {
670 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
671 }
672
673 HBITMAP
674 ui_create_bitmap(int width, int height, uint8 * data)
675 {
676 XImage *image;
677 Pixmap bitmap;
678 uint8 *tdata;
679
680 tdata = (owncolmap ? data : translate_image(width, height, data));
681 bitmap = XCreatePixmap(display, wnd, width, height, depth);
682 image = XCreateImage(display, visual, depth, ZPixmap, 0,
683 (char *) tdata, width, height, 8, 0);
684
685 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
686
687 XFree(image);
688 if (!owncolmap)
689 xfree(tdata);
690 return (HBITMAP) bitmap;
691 }
692
693 void
694 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
695 {
696 XImage *image;
697 uint8 *tdata;
698
699 tdata = (owncolmap ? data : translate_image(width, height, data));
700 image = XCreateImage(display, visual, depth, ZPixmap, 0,
701 (char *) tdata, width, height, 8, 0);
702
703 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
713 XFree(image);
714 if (!owncolmap)
715 xfree(tdata);
716 }
717
718 void
719 ui_destroy_bitmap(HBITMAP bmp)
720 {
721 XFreePixmap(display, (Pixmap) bmp);
722 }
723
724 HGLYPH
725 ui_create_glyph(int width, int height, uint8 * data)
726 {
727 XImage *image;
728 Pixmap bitmap;
729 int scanline;
730 GC gc;
731
732 scanline = (width + 7) / 8;
733
734 bitmap = XCreatePixmap(display, wnd, width, height, 1);
735 gc = XCreateGC(display, bitmap, 0, NULL);
736
737 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
738 width, height, 8, scanline);
739 image->byte_order = MSBFirst;
740 image->bitmap_bit_order = MSBFirst;
741 XInitImage(image);
742
743 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
744
745 XFree(image);
746 XFreeGC(display, gc);
747 return (HGLYPH) bitmap;
748 }
749
750 void
751 ui_destroy_glyph(HGLYPH glyph)
752 {
753 XFreePixmap(display, (Pixmap) glyph);
754 }
755
756 HCURSOR
757 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
758 uint8 * andmask, uint8 * xormask)
759 {
760 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 {
781 offset -= scanline;
782 pcursor = &cursor[offset];
783 pmask = &mask[offset];
784
785 for (j = 0; j < scanline; j++)
786 {
787 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 }
807 }
808
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 xcursor =
817 XCreatePixmapCursor(display, (Pixmap) cursorglyph,
818 (Pixmap) maskglyph, &fg, &bg, x, y);
819
820 ui_destroy_glyph(maskglyph);
821 ui_destroy_glyph(cursorglyph);
822 xfree(mask);
823 xfree(cursor);
824 return (HCURSOR) xcursor;
825 }
826
827 void
828 ui_set_cursor(HCURSOR cursor)
829 {
830 XDefineCursor(display, wnd, (Cursor) cursor);
831 }
832
833 void
834 ui_destroy_cursor(HCURSOR cursor)
835 {
836 XFreeCursor(display, (Cursor) cursor);
837 }
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 ui_create_colourmap(COLOURMAP * colours)
847 {
848 COLOURENTRY *entry;
849 int i, ncolours = colours->ncolours;
850
851 if (owncolmap)
852 {
853 XColor *xcolours, *xentry;
854 Colormap map;
855
856 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 MAKE_XCOLOR(xentry, entry);
863 }
864
865 map = XCreateColormap(display, wnd, visual, AllocAll);
866 XStoreColors(display, map, xcolours, ncolours);
867
868 xfree(xcolours);
869 return (HCOLOURMAP) map;
870 }
871 else
872 {
873 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
874 XColor xentry;
875 uint32 colour;
876
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 colour = xentry.pixel;
884 else
885 colour = white;
886
887 /* byte swap here to make translate_image faster */
888 map[i] = translate_colour(colour);
889 }
890
891 return map;
892 }
893 }
894
895 void
896 ui_destroy_colourmap(HCOLOURMAP map)
897 {
898 if (owncolmap)
899 XFreeColormap(display, (Colormap) map);
900 else
901 xfree(map);
902 }
903
904 void
905 ui_set_colourmap(HCOLOURMAP map)
906 {
907 if (owncolmap)
908 XSetWindowColormap(display, wnd, (Colormap) map);
909 else
910 colmap = map;
911 }
912
913 void
914 ui_set_clip(int x, int y, int cx, int cy)
915 {
916 XRectangle rect;
917
918 rect.x = x;
919 rect.y = y;
920 rect.width = cx;
921 rect.height = cy;
922 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
923 }
924
925 void
926 ui_reset_clip()
927 {
928 XRectangle rect;
929
930 rect.x = 0;
931 rect.y = 0;
932 rect.width = width;
933 rect.height = height;
934 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
935 }
936
937 void
938 ui_bell()
939 {
940 XBell(display, 0);
941 }
942
943 void
944 ui_destblt(uint8 opcode,
945 /* dest */ int x, int y, int cx, int cy)
946 {
947 SET_FUNCTION(opcode);
948 FILL_RECTANGLE(x, y, cx, cy);
949 RESET_FUNCTION(opcode);
950 }
951
952 void
953 ui_patblt(uint8 opcode,
954 /* dest */ int x, int y, int cx, int cy,
955 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
956 {
957 Pixmap fill;
958 uint8 i, ipattern[8];
959
960 SET_FUNCTION(opcode);
961
962 switch (brush->style)
963 {
964 case 0: /* Solid */
965 SET_FOREGROUND(fgcolour);
966 FILL_RECTANGLE(x, y, cx, cy);
967 break;
968
969 case 3: /* Pattern */
970 for (i = 0; i != 8; i++)
971 ipattern[7 - i] = brush->pattern[i];
972 fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
973
974 SET_FOREGROUND(bgcolour);
975 SET_BACKGROUND(fgcolour);
976 XSetFillStyle(display, gc, FillOpaqueStippled);
977 XSetStipple(display, gc, fill);
978 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
979
980 FILL_RECTANGLE(x, y, cx, cy);
981
982 XSetFillStyle(display, gc, FillSolid);
983 XSetTSOrigin(display, gc, 0, 0);
984 ui_destroy_glyph((HGLYPH) fill);
985 break;
986
987 default:
988 unimpl("brush %d\n", brush->style);
989 }
990
991 RESET_FUNCTION(opcode);
992 }
993
994 void
995 ui_screenblt(uint8 opcode,
996 /* dest */ int x, int y, int cx, int cy,
997 /* src */ int srcx, int srcy)
998 {
999 SET_FUNCTION(opcode);
1000 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1001 if (ownbackstore)
1002 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1003 RESET_FUNCTION(opcode);
1004 }
1005
1006 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 {
1011 SET_FUNCTION(opcode);
1012 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1013 if (ownbackstore)
1014 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1015 RESET_FUNCTION(opcode);
1016 }
1017
1018 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 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1023 {
1024 /* This is potentially difficult to do in general. Until someone
1025 comes up with a more efficient way of doing it I am using cases. */
1026
1027 switch (opcode)
1028 {
1029 case 0x69: /* PDSxxn */
1030 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1031 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1032 break;
1033
1034 case 0xb8: /* PSDPxax */
1035 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1036 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1037 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1038 break;
1039
1040 case 0xc0: /* PSa */
1041 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1042 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1043 break;
1044
1045 default:
1046 unimpl("triblt 0x%x\n", opcode);
1047 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1048 }
1049 }
1050
1051 void
1052 ui_line(uint8 opcode,
1053 /* dest */ int startx, int starty, int endx, int endy,
1054 /* pen */ PEN * pen)
1055 {
1056 SET_FUNCTION(opcode);
1057 SET_FOREGROUND(pen->colour);
1058 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1059 if (ownbackstore)
1060 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1061 RESET_FUNCTION(opcode);
1062 }
1063
1064 void
1065 ui_rect(
1066 /* dest */ int x, int y, int cx, int cy,
1067 /* brush */ int colour)
1068 {
1069 SET_FOREGROUND(colour);
1070 FILL_RECTANGLE(x, y, cx, cy);
1071 }
1072
1073 void
1074 ui_draw_glyph(int mixmode,
1075 /* dest */ int x, int y, int cx, int cy,
1076 /* src */ HGLYPH glyph, int srcx, int srcy,
1077 int bgcolour, int fgcolour)
1078 {
1079 SET_FOREGROUND(fgcolour);
1080 SET_BACKGROUND(bgcolour);
1081
1082 XSetFillStyle(display, gc,
1083 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1084 XSetStipple(display, gc, (Pixmap) glyph);
1085 XSetTSOrigin(display, gc, x, y);
1086
1087 FILL_RECTANGLE(x, y, cx, cy);
1088
1089 XSetFillStyle(display, gc, FillSolid);
1090 }
1091
1092 #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 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1102 else\
1103 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1104 idx += 2;\
1105 }\
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 void
1126 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1127 int clipx, int clipy, int clipcx, int clipcy,
1128 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1129 int fgcolour, uint8 * text, uint8 length)
1130 {
1131 FONTGLYPH *glyph;
1132 int i, j, xyoffset;
1133 DATABLOB *entry;
1134
1135 SET_FOREGROUND(bgcolour);
1136
1137 if (boxcx > 1)
1138 {
1139 FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1140 }
1141 else if (mixmode == MIX_OPAQUE)
1142 {
1143 FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1144 }
1145
1146 /* Paint text, character by character */
1147 for (i = 0; i < length;)
1148 {
1149 switch (text[i])
1150 {
1151 case 0xff:
1152 if (i + 2 < length)
1153 cache_put_text(text[i + 1], text, text[i + 2]);
1154 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 break;
1164
1165 case 0xfe:
1166 entry = cache_get_text(text[i + 1]);
1167 if (entry != NULL)
1168 {
1169 if ((((uint8 *) (entry->data))[1] ==
1170 0) && (!(flags & TEXT2_IMPLICIT_X)))
1171 {
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 else
1180 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 DO_GLYPH(((uint8 *) (entry->data)), j);
1187 }
1188 break;
1189
1190 default:
1191 DO_GLYPH(text, i);
1192 i++;
1193 break;
1194 }
1195 }
1196
1197
1198 }
1199
1200 void
1201 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1202 {
1203 Pixmap pix;
1204 XImage *image;
1205
1206 if (ownbackstore)
1207 {
1208 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1209 }
1210 else
1211 {
1212 pix = XCreatePixmap(display, wnd, cx, cy, depth);
1213 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1214 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1215 XFreePixmap(display, pix);
1216 }
1217
1218 offset *= bpp / 8;
1219 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1220
1221 XDestroyImage(image);
1222 }
1223
1224 void
1225 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1226 {
1227 XImage *image;
1228 uint8 *data;
1229
1230 offset *= bpp / 8;
1231 data = cache_get_desktop(offset, cx, cy, bpp / 8);
1232 if (data == NULL)
1233 return;
1234
1235 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1236 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1237
1238 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 XFree(image);
1249 }

  ViewVC Help
Powered by ViewVC 1.1.26