/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 185 - (show annotations)
Wed Sep 18 12:13:08 2002 UTC (21 years, 8 months ago) by n-ki
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 26637 byte(s)
Owncolmap removed in favour of more intelligent color allocation.

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

  ViewVC Help
Powered by ViewVC 1.1.26