/[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 99 - (show annotations)
Tue Aug 20 01:20:08 2002 UTC (21 years, 9 months ago) by jsorg71
File MIME type: text/plain
File size: 25472 byte(s)
focus out reset keys so some keys do not stick down

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

  ViewVC Help
Powered by ViewVC 1.1.26