/[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 253 - (show annotations)
Tue Nov 5 11:09:26 2002 UTC (21 years, 6 months ago) by matthewc
File MIME type: text/plain
File size: 26617 byte(s)
Need to make absolutely sure rdesktop ungrabs the keyboard - do it on
LeaveNotify as well.

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

  ViewVC Help
Powered by ViewVC 1.1.26