/[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 81 - (show annotations)
Tue Jul 30 01:57:39 2002 UTC (21 years, 9 months ago) by jsorg71
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 25281 byte(s)
added ui_init for pre connect inits like fullscreen

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

  ViewVC Help
Powered by ViewVC 1.1.26