/[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 164 - (show annotations)
Mon Sep 16 13:19:54 2002 UTC (21 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 26644 byte(s)
Small indent fix.

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

  ViewVC Help
Powered by ViewVC 1.1.26