/[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 257 - (show annotations)
Mon Nov 11 23:15:27 2002 UTC (21 years, 6 months ago) by jsorg71
File MIME type: text/plain
File size: 27207 byte(s)
can't grabkeyboard on focusin unless mouse is in window, can't grabkeyboard on enternotiy unless window is focused, cache them, other grabkeyboard fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26