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

  ViewVC Help
Powered by ViewVC 1.1.26