/[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 101 - (show annotations)
Mon Aug 26 17:12:43 2002 UTC (21 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 27316 byte(s)
Indent fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26