/[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 87 - (show annotations)
Sat Aug 3 22:28:05 2002 UTC (21 years, 9 months ago) by jsorg71
File MIME type: text/plain
File size: 25267 byte(s)
clear window upon startup so cached data is not viewed on screen from up19-7-5

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

  ViewVC Help
Powered by ViewVC 1.1.26