/[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 69 - (show annotations)
Sat Jul 27 22:35:38 2002 UTC (21 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 24461 byte(s)
Added "localstate" support to keymapping: Send local modifier state. This fixes problems with Shift-Home etc

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
29 extern int width;
30 extern int height;
31 extern BOOL sendmotion;
32 extern BOOL fullscreen;
33
34 Display *display = NULL;
35 static int x_socket;
36 static Window wnd;
37 static GC gc;
38 static Visual *visual;
39 static int depth;
40 static int bpp;
41
42 /* endianness */
43 static BOOL host_be;
44 static BOOL xserver_be;
45
46 /* software backing store */
47 static BOOL ownbackstore;
48 static Pixmap backstore;
49
50 #define FILL_RECTANGLE(x,y,cx,cy)\
51 { \
52 XFillRectangle(display, wnd, gc, x, y, cx, cy); \
53 if (ownbackstore) \
54 XFillRectangle(display, backstore, gc, x, y, cx, cy); \
55 }
56
57 /* colour maps */
58 static BOOL owncolmap;
59 static Colormap xcolmap;
60 static uint32 white;
61 static uint32 *colmap;
62 static XIM IM = NULL;
63 static XIC IC = NULL;
64
65 #define TRANSLATE(col) ( owncolmap ? col : translate_colour(colmap[col]) )
66 #define SET_FOREGROUND(col) XSetForeground(display, gc, TRANSLATE(col));
67 #define SET_BACKGROUND(col) XSetBackground(display, gc, TRANSLATE(col));
68
69 static int rop2_map[] = {
70 GXclear, /* 0 */
71 GXnor, /* DPon */
72 GXandInverted, /* DPna */
73 GXcopyInverted, /* Pn */
74 GXandReverse, /* PDna */
75 GXinvert, /* Dn */
76 GXxor, /* DPx */
77 GXnand, /* DPan */
78 GXand, /* DPa */
79 GXequiv, /* DPxn */
80 GXnoop, /* D */
81 GXorInverted, /* DPno */
82 GXcopy, /* P */
83 GXorReverse, /* PDno */
84 GXor, /* DPo */
85 GXset /* 1 */
86 };
87
88 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
89 #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
90
91 static void
92 translate8(uint8 * data, uint8 * out, uint8 * end)
93 {
94 while (out < end)
95 *(out++) = (uint8) colmap[*(data++)];
96 }
97
98 static void
99 translate16(uint8 * data, uint16 * out, uint16 * end)
100 {
101 while (out < end)
102 *(out++) = (uint16) colmap[*(data++)];
103 }
104
105 /* little endian - conversion happens when colourmap is built */
106 static void
107 translate24(uint8 * data, uint8 * out, uint8 * end)
108 {
109 uint32 value;
110
111 while (out < end)
112 {
113 value = colmap[*(data++)];
114 *(out++) = value;
115 *(out++) = value >> 8;
116 *(out++) = value >> 16;
117 }
118 }
119
120 static void
121 translate32(uint8 * data, uint32 * out, uint32 * end)
122 {
123 while (out < end)
124 *(out++) = colmap[*(data++)];
125 }
126
127 static uint8 *
128 translate_image(int width, int height, uint8 * data)
129 {
130 int size = width * height * bpp / 8;
131 uint8 *out = xmalloc(size);
132 uint8 *end = out + size;
133
134 switch (bpp)
135 {
136 case 8:
137 translate8(data, out, end);
138 break;
139
140 case 16:
141 translate16(data, (uint16 *) out, (uint16 *) end);
142 break;
143
144 case 24:
145 translate24(data, out, end);
146 break;
147
148 case 32:
149 translate32(data, (uint32 *) out, (uint32 *) end);
150 break;
151 }
152
153 return out;
154 }
155
156 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
157 #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
158 #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
159 x = (x << 16) | (x >> 16); }
160
161 static uint32
162 translate_colour(uint32 colour)
163 {
164 switch (bpp)
165 {
166 case 16:
167 if (host_be != xserver_be)
168 BSWAP16(colour);
169 break;
170
171 case 24:
172 if (xserver_be)
173 BSWAP24(colour);
174 break;
175
176 case 32:
177 if (host_be != xserver_be)
178 BSWAP32(colour);
179 break;
180 }
181
182 return colour;
183 }
184
185 static unsigned long
186 init_inputmethod(void)
187 {
188 unsigned long filtered_events;
189
190 IM = XOpenIM(display, NULL, NULL, NULL);
191 if (IM == NULL)
192 {
193 error("Failed to open input method\n");
194 }
195
196 if (IM != NULL)
197 {
198 /* Must be done after XCreateWindow */
199 IC = XCreateIC(IM, XNInputStyle,
200 (XIMPreeditNothing | XIMStatusNothing),
201 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
202
203 if (IC == NULL)
204 {
205 error("Failed to create input context\n");
206 XCloseIM(IM);
207 IM = NULL;
208 }
209 }
210
211 /* For correct Multi_key/Compose processing, I guess.
212 It seems to work alright anyway, though. */
213 if (IC != NULL)
214 {
215 if (XGetICValues(IC, XNFilterEvents, &filtered_events, NULL)
216 != NULL)
217 {
218 error("Failed to obtain XNFilterEvents value from IC\n");
219 filtered_events = 0;
220 }
221 }
222 return filtered_events;
223 }
224
225 static void
226 close_inputmethod(void)
227 {
228 if (IC != NULL)
229 {
230 XDestroyIC(IC);
231 if (IM != NULL)
232 {
233 XCloseIM(IM);
234 IM = NULL;
235 }
236 }
237 }
238
239
240 BOOL
241 ui_create_window(char *title)
242 {
243 XSetWindowAttributes attribs;
244 XClassHint *classhints;
245 XSizeHints *sizehints;
246 unsigned long input_mask;
247 XPixmapFormatValues *pfm;
248 Screen *screen;
249 uint16 test;
250 int i;
251 unsigned long filtered_events;
252
253 display = XOpenDisplay(NULL);
254
255 if (display == NULL)
256 {
257 error("Failed to open display\n");
258 return False;
259 }
260
261 x_socket = ConnectionNumber(display);
262 screen = DefaultScreenOfDisplay(display);
263 visual = DefaultVisualOfScreen(screen);
264 depth = DefaultDepthOfScreen(screen);
265
266 pfm = XListPixmapFormats(display, &i);
267 if (pfm != NULL)
268 {
269 /* Use maximum bpp for this depth - this is generally
270 desirable, e.g. 24 bits->32 bits. */
271 while (i--)
272 {
273 if ((pfm[i].depth == depth)
274 && (pfm[i].bits_per_pixel > bpp))
275 {
276 bpp = pfm[i].bits_per_pixel;
277 }
278 }
279 XFree(pfm);
280 }
281
282 if (bpp < 8)
283 {
284 error("Less than 8 bpp not currently supported.\n");
285 XCloseDisplay(display);
286 return False;
287 }
288
289 if (depth <= 8)
290 owncolmap = True;
291 else
292 xcolmap = DefaultColormapOfScreen(screen);
293
294 test = 1;
295 host_be = !(BOOL) (*(uint8 *) (&test));
296 xserver_be = (ImageByteOrder(display) == MSBFirst);
297
298 white = WhitePixelOfScreen(screen);
299 attribs.background_pixel = BlackPixelOfScreen(screen);
300 attribs.backing_store = DoesBackingStore(screen);
301
302 if (attribs.backing_store == NotUseful)
303 ownbackstore = True;
304
305 if (fullscreen)
306 {
307 attribs.override_redirect = True;
308 width = WidthOfScreen(screen);
309 height = HeightOfScreen(screen);
310 }
311 else
312 {
313 attribs.override_redirect = False;
314 }
315
316 width = (width + 3) & ~3; /* make width a multiple of 32 bits */
317
318 wnd = XCreateWindow(display, RootWindowOfScreen(screen),
319 0, 0, width, height, 0, CopyFromParent,
320 InputOutput, CopyFromParent,
321 CWBackingStore | CWBackPixel | CWOverrideRedirect,
322 &attribs);
323
324 XStoreName(display, wnd, title);
325
326 classhints = XAllocClassHint();
327 if (classhints != NULL)
328 {
329 classhints->res_name = classhints->res_class = "rdesktop";
330 XSetClassHint(display, wnd, classhints);
331 XFree(classhints);
332 }
333
334 sizehints = XAllocSizeHints();
335 if (sizehints)
336 {
337 sizehints->flags = PMinSize | PMaxSize;
338 sizehints->min_width = sizehints->max_width = width;
339 sizehints->min_height = sizehints->max_height = height;
340 XSetWMNormalHints(display, wnd, sizehints);
341 XFree(sizehints);
342 }
343
344 xkeymap_init2();
345
346 input_mask =
347 KeyPressMask | KeyReleaseMask | ButtonPressMask |
348 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask;
349 if (sendmotion)
350 input_mask |= PointerMotionMask;
351
352 if (ownbackstore)
353 input_mask |= ExposureMask;
354
355 filtered_events = init_inputmethod();
356
357 XSelectInput(display, wnd, input_mask | filtered_events);
358
359 gc = XCreateGC(display, wnd, 0, NULL);
360
361 if (ownbackstore)
362 backstore = XCreatePixmap(display, wnd, width, height, depth);
363
364 XMapWindow(display, wnd);
365
366 return True;
367 }
368
369 void
370 ui_destroy_window()
371 {
372 if (ownbackstore)
373 XFreePixmap(display, backstore);
374
375 XFreeGC(display, gc);
376
377 close_inputmethod();
378
379 XDestroyWindow(display, wnd);
380 XCloseDisplay(display);
381 display = NULL;
382 }
383
384 static void
385 xwin_process_events()
386 {
387 XEvent xevent;
388
389 KeySym keysym;
390 uint16 button, flags;
391 uint32 ev_time;
392 key_translation tr;
393 char *ksname = NULL;
394 char str[256];
395 Status status;
396
397 /* Refresh keyboard mapping if it has changed. This is important for
398 Xvnc, since it allocates keycodes dynamically */
399 if (XCheckTypedEvent(display, MappingNotify, &xevent))
400 {
401 if (xevent.xmapping.request == MappingKeyboard
402 || xevent.xmapping.request == MappingModifier)
403 XRefreshKeyboardMapping(&xevent.xmapping);
404 }
405
406 while (XCheckMaskEvent(display, ~0, &xevent))
407 {
408 if (XFilterEvent(&xevent, None) == True)
409 {
410 DEBUG_KBD("Filtering event\n");
411 continue;
412 }
413
414 ev_time = time(NULL);
415 flags = 0;
416
417 switch (xevent.type)
418 {
419 case KeyPress:
420 if (IC != NULL)
421 /* Multi_key compatible version */
422 {
423 XmbLookupString(IC,
424 (XKeyPressedEvent *) &
425 xevent, str,
426 sizeof(str), &keysym,
427 &status);
428 if (!
429 ((status == XLookupKeySym)
430 || (status == XLookupBoth)))
431 {
432 error("XmbLookupString failed with status 0x%x\n", status);
433 break;
434 }
435 }
436 else
437 {
438 /* Plain old XLookupString */
439 DEBUG_KBD
440 ("No input context, using XLookupString\n");
441 XLookupString((XKeyEvent *) & xevent,
442 str, sizeof(str),
443 &keysym, NULL);
444 }
445
446 ksname = get_ksname(keysym);
447 DEBUG_KBD
448 ("\nKeyPress for (keysym 0x%lx, %s)\n",
449 keysym, ksname);
450
451 if (inhibit_key(keysym))
452 {
453 DEBUG_KBD("Inhibiting key\n");
454 break;
455 }
456
457 tr = xkeymap_translate_key(keysym,
458 xevent.xkey.
459 keycode,
460 xevent.xkey.state);
461
462 ensure_remote_modifiers(ev_time, tr);
463
464 if (tr.scancode == 0)
465 break;
466
467 rdp_send_scancode(ev_time, RDP_KEYPRESS,
468 tr.scancode);
469 break;
470 case KeyRelease:
471 XLookupString((XKeyEvent *) & xevent, str,
472 sizeof(str), &keysym, NULL);
473
474 ksname = get_ksname(keysym);
475 DEBUG_KBD
476 ("\nKeyRelease for (keysym 0x%lx, %s)\n",
477 keysym, ksname);
478
479 if (inhibit_key(keysym))
480 break;
481
482 tr = xkeymap_translate_key(keysym,
483 xevent.xkey.
484 keycode,
485 xevent.xkey.state);
486
487 if (tr.scancode == 0)
488 break;
489
490 rdp_send_scancode(ev_time, RDP_KEYRELEASE,
491 tr.scancode);
492 break;
493
494 case ButtonPress:
495 flags = MOUSE_FLAG_DOWN;
496 /* fall through */
497
498 case ButtonRelease:
499 button = xkeymap_translate_button(xevent.
500 xbutton.
501 button);
502 if (button == 0)
503 break;
504
505 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
506 flags | button,
507 xevent.xbutton.x,
508 xevent.xbutton.y);
509 break;
510
511 case MotionNotify:
512 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
513 MOUSE_FLAG_MOVE,
514 xevent.xmotion.x,
515 xevent.xmotion.y);
516 break;
517
518 case EnterNotify:
519 XGrabKeyboard(display, wnd, True,
520 GrabModeAsync, GrabModeAsync,
521 CurrentTime);
522 break;
523
524 case LeaveNotify:
525 XUngrabKeyboard(display, CurrentTime);
526 break;
527
528 case Expose:
529 XCopyArea(display, backstore, wnd, gc,
530 xevent.xexpose.x, xevent.xexpose.y,
531 xevent.xexpose.width,
532 xevent.xexpose.height,
533 xevent.xexpose.x, xevent.xexpose.y);
534 break;
535 }
536 }
537 }
538
539 void
540 ui_select(int rdp_socket)
541 {
542 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
543 fd_set rfds;
544
545 FD_ZERO(&rfds);
546
547 while (True)
548 {
549 FD_ZERO(&rfds);
550 FD_SET(rdp_socket, &rfds);
551 if (display != NULL)
552 {
553 FD_SET(x_socket, &rfds);
554 XFlush(display);
555 }
556
557 switch (select(n, &rfds, NULL, NULL, NULL))
558 {
559 case -1:
560 error("select: %s\n", strerror(errno));
561
562 case 0:
563 continue;
564 }
565
566 if (FD_ISSET(x_socket, &rfds))
567 xwin_process_events();
568
569 if (FD_ISSET(rdp_socket, &rfds))
570 return;
571 }
572 }
573
574 void
575 ui_move_pointer(int x, int y)
576 {
577 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
578 }
579
580 HBITMAP
581 ui_create_bitmap(int width, int height, uint8 * data)
582 {
583 XImage *image;
584 Pixmap bitmap;
585 uint8 *tdata;
586
587 tdata = (owncolmap ? data : translate_image(width, height, data));
588 bitmap = XCreatePixmap(display, wnd, width, height, depth);
589 image = XCreateImage(display, visual, depth, ZPixmap, 0, tdata, width,
590 height, 8, 0);
591
592 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
593
594 XFree(image);
595 if (!owncolmap)
596 xfree(tdata);
597 return (HBITMAP) bitmap;
598 }
599
600 void
601 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height,
602 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, tdata, width,
609 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, data, width,
646 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,
887 brush->yorigin);
888
889 FILL_RECTANGLE(x, y, cx, cy);
890
891 XSetFillStyle(display, gc, FillSolid);
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,
911 cy, x, y);
912 RESET_FUNCTION(opcode);
913 }
914
915 void
916 ui_memblt(uint8 opcode,
917 /* dest */ int x, int y, int cx, int cy,
918 /* src */ HBITMAP src, int srcx, int srcy)
919 {
920 SET_FUNCTION(opcode);
921 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
922 if (ownbackstore)
923 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy,
924 cx, cy, x, y);
925 RESET_FUNCTION(opcode);
926 }
927
928 void
929 ui_triblt(uint8 opcode,
930 /* dest */ int x, int y, int cx, int cy,
931 /* src */ HBITMAP src, int srcx, int srcy,
932 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
933 {
934 /* This is potentially difficult to do in general. Until someone
935 comes up with a more efficient way of doing it I am using cases. */
936
937 switch (opcode)
938 {
939 case 0x69: /* PDSxxn */
940 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
941 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour,
942 fgcolour);
943 break;
944
945 case 0xb8: /* PSDPxax */
946 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour,
947 fgcolour);
948 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
949 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour,
950 fgcolour);
951 break;
952
953 case 0xc0: /* PSa */
954 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
955 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
956 fgcolour);
957 break;
958
959 default:
960 unimpl("triblt 0x%x\n", opcode);
961 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
962 }
963 }
964
965 void
966 ui_line(uint8 opcode,
967 /* dest */ int startx, int starty, int endx, int endy,
968 /* pen */ PEN * pen)
969 {
970 SET_FUNCTION(opcode);
971 SET_FOREGROUND(pen->colour);
972 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
973 if (ownbackstore)
974 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
975 RESET_FUNCTION(opcode);
976 }
977
978 void
979 ui_rect(
980 /* dest */ int x, int y, int cx, int cy,
981 /* brush */ int colour)
982 {
983 SET_FOREGROUND(colour);
984 FILL_RECTANGLE(x, y, cx, cy);
985 }
986
987 void
988 ui_draw_glyph(int mixmode,
989 /* dest */ int x, int y, int cx, int cy,
990 /* src */ HGLYPH glyph, int srcx, int srcy,
991 int bgcolour, int fgcolour)
992 {
993 SET_FOREGROUND(fgcolour);
994 SET_BACKGROUND(bgcolour);
995
996 XSetFillStyle(display, gc,
997 (mixmode ==
998 MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
999 XSetStipple(display, gc, (Pixmap) glyph);
1000 XSetTSOrigin(display, gc, x, y);
1001
1002 FILL_RECTANGLE(x, y, cx, cy);
1003
1004 XSetFillStyle(display, gc, FillSolid);
1005 }
1006
1007 #define DO_GLYPH(ttext,idx) \
1008 {\
1009 glyph = cache_get_font (font, ttext[idx]);\
1010 if (!(flags & TEXT2_IMPLICIT_X))\
1011 {\
1012 xyoffset = ttext[++idx];\
1013 if ((xyoffset & 0x80))\
1014 {\
1015 if (flags & TEXT2_VERTICAL) \
1016 y += ttext[++idx] | (ttext[++idx] << 8);\
1017 else\
1018 x += ttext[++idx] | (ttext[++idx] << 8);\
1019 }\
1020 else\
1021 {\
1022 if (flags & TEXT2_VERTICAL) \
1023 y += xyoffset;\
1024 else\
1025 x += xyoffset;\
1026 }\
1027 }\
1028 if (glyph != NULL)\
1029 {\
1030 ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1031 y + (short) glyph->baseline,\
1032 glyph->width, glyph->height,\
1033 glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1034 if (flags & TEXT2_IMPLICIT_X)\
1035 x += glyph->width;\
1036 }\
1037 }
1038
1039 void
1040 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1041 int clipx, int clipy, int clipcx, int clipcy,
1042 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1043 int fgcolour, uint8 * text, uint8 length)
1044 {
1045 FONTGLYPH *glyph;
1046 int i, j, xyoffset;
1047 DATABLOB *entry;
1048
1049 SET_FOREGROUND(bgcolour);
1050
1051 if (boxcx > 1)
1052 {
1053 FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1054 }
1055 else if (mixmode == MIX_OPAQUE)
1056 {
1057 FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1058 }
1059
1060 /* Paint text, character by character */
1061 for (i = 0; i < length;)
1062 {
1063 switch (text[i])
1064 {
1065 case 0xff:
1066 if (i + 2 < length)
1067 cache_put_text(text[i + 1], text,
1068 text[i + 2]);
1069 else
1070 {
1071 error("this shouldn't be happening\n");
1072 break;
1073 }
1074 /* this will move pointer from start to first character after FF command */
1075 length -= i + 3;
1076 text = &(text[i + 3]);
1077 i = 0;
1078 break;
1079
1080 case 0xfe:
1081 entry = cache_get_text(text[i + 1]);
1082 if (entry != NULL)
1083 {
1084 if ((((uint8 *) (entry->data))[1] ==
1085 0)
1086 && (!(flags & TEXT2_IMPLICIT_X)))
1087 {
1088 if (flags & TEXT2_VERTICAL)
1089 y += text[i + 2];
1090 else
1091 x += text[i + 2];
1092 }
1093 if (i + 2 < length)
1094 i += 3;
1095 else
1096 i += 2;
1097 length -= i;
1098 /* this will move pointer from start to first character after FE command */
1099 text = &(text[i]);
1100 i = 0;
1101 for (j = 0; j < entry->size; j++)
1102 DO_GLYPH(((uint8 *) (entry->
1103 data)),
1104 j);
1105 }
1106 break;
1107
1108 default:
1109 DO_GLYPH(text, i);
1110 i++;
1111 break;
1112 }
1113 }
1114
1115
1116 }
1117
1118 void
1119 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1120 {
1121 Pixmap pix;
1122 XImage *image;
1123
1124 if (ownbackstore)
1125 {
1126 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
1127 ZPixmap);
1128 }
1129 else
1130 {
1131 pix = XCreatePixmap(display, wnd, cx, cy, depth);
1132 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1133 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,
1134 ZPixmap);
1135 XFreePixmap(display, pix);
1136 }
1137
1138 offset *= bpp / 8;
1139 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8,
1140 (uint8 *) image->data);
1141
1142 XDestroyImage(image);
1143 }
1144
1145 void
1146 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1147 {
1148 XImage *image;
1149 uint8 *data;
1150
1151 offset *= bpp / 8;
1152 data = cache_get_desktop(offset, cx, cy, bpp / 8);
1153 if (data == NULL)
1154 return;
1155
1156 image = XCreateImage(display, visual, depth, ZPixmap, 0, data, cx, cy,
1157 BitmapPad(display), cx * bpp / 8);
1158
1159 if (ownbackstore)
1160 {
1161 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1162 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1163 }
1164 else
1165 {
1166 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1167 }
1168
1169 XFree(image);
1170 }

  ViewVC Help
Powered by ViewVC 1.1.26