/[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 158 - (show annotations)
Sun Sep 15 11:53:50 2002 UTC (21 years, 8 months ago) by matthewc
File MIME type: text/plain
File size: 26575 byte(s)
Possible fix for "flashing title bar" problem (don't grab in response
to FocusIn/FocusOut - seems to cause an event loop).

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

  ViewVC Help
Powered by ViewVC 1.1.26