/[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 66 - (show annotations)
Thu Jul 18 18:28:12 2002 UTC (21 years, 10 months ago) by astrand
File MIME type: text/plain
File size: 24402 byte(s)
Merged new keysym-based keyboard handling (from alt. CVS repos)

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

  ViewVC Help
Powered by ViewVC 1.1.26