/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 72 - (show annotations)
Mon Jul 29 18:59:01 2002 UTC (21 years, 9 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 24519 byte(s)
Applied patch from Bob Bell (#1), which fixes compilation warning messages.

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

  ViewVC Help
Powered by ViewVC 1.1.26