/[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 80 - (show annotations)
Tue Jul 30 00:56:48 2002 UTC (21 years, 10 months ago) by jsorg71
File MIME type: text/plain
File size: 25099 byte(s)
patblt reset orgin from up19-7-4

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 XSetTSOrigin(display, gc, 0, 0);
914 ui_destroy_glyph((HGLYPH) fill);
915 break;
916
917 default:
918 unimpl("brush %d\n", brush->style);
919 }
920
921 RESET_FUNCTION(opcode);
922 }
923
924 void
925 ui_screenblt(uint8 opcode,
926 /* dest */ int x, int y, int cx, int cy,
927 /* src */ int srcx, int srcy)
928 {
929 SET_FUNCTION(opcode);
930 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
931 if (ownbackstore)
932 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx,
933 cy, x, y);
934 RESET_FUNCTION(opcode);
935 }
936
937 void
938 ui_memblt(uint8 opcode,
939 /* dest */ int x, int y, int cx, int cy,
940 /* src */ HBITMAP src, int srcx, int srcy)
941 {
942 SET_FUNCTION(opcode);
943 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
944 if (ownbackstore)
945 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy,
946 cx, cy, x, y);
947 RESET_FUNCTION(opcode);
948 }
949
950 void
951 ui_triblt(uint8 opcode,
952 /* dest */ int x, int y, int cx, int cy,
953 /* src */ HBITMAP src, int srcx, int srcy,
954 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
955 {
956 /* This is potentially difficult to do in general. Until someone
957 comes up with a more efficient way of doing it I am using cases. */
958
959 switch (opcode)
960 {
961 case 0x69: /* PDSxxn */
962 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
963 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour,
964 fgcolour);
965 break;
966
967 case 0xb8: /* PSDPxax */
968 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour,
969 fgcolour);
970 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
971 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour,
972 fgcolour);
973 break;
974
975 case 0xc0: /* PSa */
976 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
977 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
978 fgcolour);
979 break;
980
981 default:
982 unimpl("triblt 0x%x\n", opcode);
983 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
984 }
985 }
986
987 void
988 ui_line(uint8 opcode,
989 /* dest */ int startx, int starty, int endx, int endy,
990 /* pen */ PEN * pen)
991 {
992 SET_FUNCTION(opcode);
993 SET_FOREGROUND(pen->colour);
994 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
995 if (ownbackstore)
996 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
997 RESET_FUNCTION(opcode);
998 }
999
1000 void
1001 ui_rect(
1002 /* dest */ int x, int y, int cx, int cy,
1003 /* brush */ int colour)
1004 {
1005 SET_FOREGROUND(colour);
1006 FILL_RECTANGLE(x, y, cx, cy);
1007 }
1008
1009 void
1010 ui_draw_glyph(int mixmode,
1011 /* dest */ int x, int y, int cx, int cy,
1012 /* src */ HGLYPH glyph, int srcx, int srcy,
1013 int bgcolour, int fgcolour)
1014 {
1015 SET_FOREGROUND(fgcolour);
1016 SET_BACKGROUND(bgcolour);
1017
1018 XSetFillStyle(display, gc,
1019 (mixmode ==
1020 MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1021 XSetStipple(display, gc, (Pixmap) glyph);
1022 XSetTSOrigin(display, gc, x, y);
1023
1024 FILL_RECTANGLE(x, y, cx, cy);
1025
1026 XSetFillStyle(display, gc, FillSolid);
1027 }
1028
1029 #define DO_GLYPH(ttext,idx) \
1030 {\
1031 glyph = cache_get_font (font, ttext[idx]);\
1032 if (!(flags & TEXT2_IMPLICIT_X))\
1033 {\
1034 xyoffset = ttext[++idx];\
1035 if ((xyoffset & 0x80))\
1036 {\
1037 if (flags & TEXT2_VERTICAL) \
1038 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1039 else\
1040 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1041 idx += 2;\
1042 }\
1043 else\
1044 {\
1045 if (flags & TEXT2_VERTICAL) \
1046 y += xyoffset;\
1047 else\
1048 x += xyoffset;\
1049 }\
1050 }\
1051 if (glyph != NULL)\
1052 {\
1053 ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1054 y + (short) glyph->baseline,\
1055 glyph->width, glyph->height,\
1056 glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1057 if (flags & TEXT2_IMPLICIT_X)\
1058 x += glyph->width;\
1059 }\
1060 }
1061
1062 void
1063 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1064 int clipx, int clipy, int clipcx, int clipcy,
1065 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1066 int fgcolour, uint8 * text, uint8 length)
1067 {
1068 FONTGLYPH *glyph;
1069 int i, j, xyoffset;
1070 DATABLOB *entry;
1071
1072 SET_FOREGROUND(bgcolour);
1073
1074 if (boxcx > 1)
1075 {
1076 FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1077 }
1078 else if (mixmode == MIX_OPAQUE)
1079 {
1080 FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1081 }
1082
1083 /* Paint text, character by character */
1084 for (i = 0; i < length;)
1085 {
1086 switch (text[i])
1087 {
1088 case 0xff:
1089 if (i + 2 < length)
1090 cache_put_text(text[i + 1], text,
1091 text[i + 2]);
1092 else
1093 {
1094 error("this shouldn't be happening\n");
1095 break;
1096 }
1097 /* this will move pointer from start to first character after FF command */
1098 length -= i + 3;
1099 text = &(text[i + 3]);
1100 i = 0;
1101 break;
1102
1103 case 0xfe:
1104 entry = cache_get_text(text[i + 1]);
1105 if (entry != NULL)
1106 {
1107 if ((((uint8 *) (entry->data))[1] ==
1108 0)
1109 && (!(flags & TEXT2_IMPLICIT_X)))
1110 {
1111 if (flags & TEXT2_VERTICAL)
1112 y += text[i + 2];
1113 else
1114 x += text[i + 2];
1115 }
1116 if (i + 2 < length)
1117 i += 3;
1118 else
1119 i += 2;
1120 length -= i;
1121 /* this will move pointer from start to first character after FE command */
1122 text = &(text[i]);
1123 i = 0;
1124 for (j = 0; j < entry->size; j++)
1125 DO_GLYPH(((uint8 *) (entry->
1126 data)),
1127 j);
1128 }
1129 break;
1130
1131 default:
1132 DO_GLYPH(text, i);
1133 i++;
1134 break;
1135 }
1136 }
1137
1138
1139 }
1140
1141 void
1142 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1143 {
1144 Pixmap pix;
1145 XImage *image;
1146
1147 if (ownbackstore)
1148 {
1149 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
1150 ZPixmap);
1151 }
1152 else
1153 {
1154 pix = XCreatePixmap(display, wnd, cx, cy, depth);
1155 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1156 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,
1157 ZPixmap);
1158 XFreePixmap(display, pix);
1159 }
1160
1161 offset *= bpp / 8;
1162 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8,
1163 (uint8 *) image->data);
1164
1165 XDestroyImage(image);
1166 }
1167
1168 void
1169 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1170 {
1171 XImage *image;
1172 uint8 *data;
1173
1174 offset *= bpp / 8;
1175 data = cache_get_desktop(offset, cx, cy, bpp / 8);
1176 if (data == NULL)
1177 return;
1178
1179 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1180 (char *) data, cx, cy, BitmapPad(display),
1181 cx * bpp / 8);
1182
1183 if (ownbackstore)
1184 {
1185 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1186 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1187 }
1188 else
1189 {
1190 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1191 }
1192
1193 XFree(image);
1194 }

  ViewVC Help
Powered by ViewVC 1.1.26