/[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 194 - (show annotations)
Tue Sep 24 12:25:21 2002 UTC (21 years, 7 months ago) by matthewc
File MIME type: text/plain
File size: 26119 byte(s)
Move keyboard grabbing to FocusIn/FocusOut to fix "rdesktop gets screensaver
password" problem.  Hopefully this won't bring back the phantom flashing
titlebar...

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

  ViewVC Help
Powered by ViewVC 1.1.26