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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 82 - (show annotations)
Tue Jul 30 07:18:48 2002 UTC (21 years, 9 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 24894 byte(s)
Changed max line length to 100

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

  ViewVC Help
Powered by ViewVC 1.1.26