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

  ViewVC Help
Powered by ViewVC 1.1.26