/[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 182 - (show annotations)
Tue Sep 17 16:55:43 2002 UTC (21 years, 7 months ago) by astrand
File MIME type: text/plain
File size: 26159 byte(s)
Small line-break fix for DEBUG_KBD.

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

  ViewVC Help
Powered by ViewVC 1.1.26