/[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 84 - (show annotations)
Tue Jul 30 07:30:12 2002 UTC (21 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 24912 byte(s)
Got rid of var-arg macros

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

  ViewVC Help
Powered by ViewVC 1.1.26