/[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 76 - (show annotations)
Mon Jul 29 20:16:22 2002 UTC (21 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 25039 byte(s)
Applied patch from Bob Bell for -K option

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

  ViewVC Help
Powered by ViewVC 1.1.26