/[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 121 - (show annotations)
Sat Sep 14 11:48:44 2002 UTC (21 years, 8 months ago) by matthewc
File MIME type: text/plain
File size: 27033 byte(s)
Move non-window-related initialisation to ui_init.
All functions after ui_init can now assume display and other globals are valid.

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 static int dpy_width;
46 static int dpy_height;
47
48 /* endianness */
49 static BOOL host_be;
50 static BOOL xserver_be;
51
52 /* software backing store */
53 static BOOL ownbackstore;
54 static Pixmap backstore;
55
56 #define FILL_RECTANGLE(x,y,cx,cy)\
57 { \
58 XFillRectangle(display, wnd, gc, x, y, cx, cy); \
59 if (ownbackstore) \
60 XFillRectangle(display, backstore, gc, x, y, cx, cy); \
61 }
62
63 /* colour maps */
64 static BOOL owncolmap;
65 static Colormap xcolmap;
66 static uint32 *colmap;
67
68 /* Compose support */
69 BOOL enable_compose = False;
70 static XIM IM = NULL;
71 static XIC IC = NULL;
72
73 /* toggle fullscreen globals */
74 static unsigned long input_mask;
75
76 #define TRANSLATE(col) ( owncolmap ? col : translate_colour(colmap[col]) )
77 #define SET_FOREGROUND(col) XSetForeground(display, gc, TRANSLATE(col));
78 #define SET_BACKGROUND(col) XSetBackground(display, gc, TRANSLATE(col));
79
80 static int rop2_map[] = {
81 GXclear, /* 0 */
82 GXnor, /* DPon */
83 GXandInverted, /* DPna */
84 GXcopyInverted, /* Pn */
85 GXandReverse, /* PDna */
86 GXinvert, /* Dn */
87 GXxor, /* DPx */
88 GXnand, /* DPan */
89 GXand, /* DPa */
90 GXequiv, /* DPxn */
91 GXnoop, /* D */
92 GXorInverted, /* DPno */
93 GXcopy, /* P */
94 GXorReverse, /* PDno */
95 GXor, /* DPo */
96 GXset /* 1 */
97 };
98
99 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
100 #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
101
102 static void
103 translate8(uint8 * data, uint8 * out, uint8 * end)
104 {
105 while (out < end)
106 *(out++) = (uint8) colmap[*(data++)];
107 }
108
109 static void
110 translate16(uint8 * data, uint16 * out, uint16 * end)
111 {
112 while (out < end)
113 *(out++) = (uint16) colmap[*(data++)];
114 }
115
116 /* little endian - conversion happens when colourmap is built */
117 static void
118 translate24(uint8 * data, uint8 * out, uint8 * end)
119 {
120 uint32 value;
121
122 while (out < end)
123 {
124 value = colmap[*(data++)];
125 *(out++) = value;
126 *(out++) = value >> 8;
127 *(out++) = value >> 16;
128 }
129 }
130
131 static void
132 translate32(uint8 * data, uint32 * out, uint32 * end)
133 {
134 while (out < end)
135 *(out++) = colmap[*(data++)];
136 }
137
138 static uint8 *
139 translate_image(int width, int height, uint8 * data)
140 {
141 int size = width * height * bpp / 8;
142 uint8 *out = xmalloc(size);
143 uint8 *end = out + size;
144
145 switch (bpp)
146 {
147 case 8:
148 translate8(data, out, end);
149 break;
150
151 case 16:
152 translate16(data, (uint16 *) out, (uint16 *) end);
153 break;
154
155 case 24:
156 translate24(data, out, end);
157 break;
158
159 case 32:
160 translate32(data, (uint32 *) out, (uint32 *) end);
161 break;
162 }
163
164 return out;
165 }
166
167 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
168 #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
169 #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
170 x = (x << 16) | (x >> 16); }
171
172 static uint32
173 translate_colour(uint32 colour)
174 {
175 switch (bpp)
176 {
177 case 16:
178 if (host_be != xserver_be)
179 BSWAP16(colour);
180 break;
181
182 case 24:
183 if (xserver_be)
184 BSWAP24(colour);
185 break;
186
187 case 32:
188 if (host_be != xserver_be)
189 BSWAP32(colour);
190 break;
191 }
192
193 return colour;
194 }
195
196 static unsigned long
197 init_inputmethod(void)
198 {
199 unsigned long filtered_events = 0;
200
201 IM = XOpenIM(display, NULL, NULL, NULL);
202 if (IM == NULL)
203 {
204 error("Failed to open input method\n");
205 }
206
207 if (IM != NULL)
208 {
209 /* Must be done after XCreateWindow */
210 IC = XCreateIC(IM, XNInputStyle,
211 (XIMPreeditNothing | XIMStatusNothing),
212 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
213
214 if (IC == NULL)
215 {
216 error("Failed to create input context\n");
217 XCloseIM(IM);
218 IM = NULL;
219 }
220 }
221
222 /* For correct Multi_key/Compose processing, I guess.
223 It seems to work alright anyway, though. */
224 if (IC != NULL)
225 {
226 if (XGetICValues(IC, XNFilterEvents, &filtered_events, NULL) != NULL)
227 {
228 error("Failed to obtain XNFilterEvents value from IC\n");
229 filtered_events = 0;
230 }
231 }
232 return filtered_events;
233 }
234
235 static void
236 close_inputmethod(void)
237 {
238 if (IC != NULL)
239 {
240 XDestroyIC(IC);
241 if (IM != NULL)
242 {
243 XCloseIM(IM);
244 IM = NULL;
245 }
246 }
247 }
248
249 BOOL
250 get_key_state(int keysym)
251 {
252 int keysymMask = 0, modifierpos, key;
253 Window wDummy1, wDummy2;
254 int iDummy3, iDummy4, iDummy5, iDummy6;
255 unsigned int current_state;
256 int offset;
257
258 XModifierKeymap *map = XGetModifierMapping(display);
259 KeyCode keycode = XKeysymToKeycode(display, keysym);
260
261 if (keycode == NoSymbol)
262 return False;
263
264 for (modifierpos = 0; modifierpos < 8; modifierpos++)
265 {
266 offset = map->max_keypermod * modifierpos;
267
268 for (key = 0; key < map->max_keypermod; key++)
269 {
270 if (map->modifiermap[offset + key] == keycode)
271 keysymMask = 1 << modifierpos;
272 }
273 }
274
275 XQueryPointer(display, DefaultRootWindow(display), &wDummy1,
276 &wDummy2, &iDummy3, &iDummy4, &iDummy5, &iDummy6, &current_state);
277
278 XFreeModifiermap(map);
279
280 return (current_state & keysymMask) ? True : False;
281 }
282
283
284 BOOL
285 ui_init()
286 {
287 XPixmapFormatValues *pfm;
288 uint16 test;
289 int i;
290
291 display = XOpenDisplay(NULL);
292 if (display == NULL)
293 {
294 error("Failed to open display\n");
295 return False;
296 }
297
298 x_socket = ConnectionNumber(display);
299 screen = DefaultScreenOfDisplay(display);
300 visual = DefaultVisualOfScreen(screen);
301 depth = DefaultDepthOfScreen(screen);
302
303 pfm = XListPixmapFormats(display, &i);
304 if (pfm != NULL)
305 {
306 /* Use maximum bpp for this depth - this is generally
307 desirable, e.g. 24 bits->32 bits. */
308 while (i--)
309 {
310 if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
311 {
312 bpp = pfm[i].bits_per_pixel;
313 }
314 }
315 XFree(pfm);
316 }
317
318 if (bpp < 8)
319 {
320 error("Less than 8 bpp not currently supported.\n");
321 XCloseDisplay(display);
322 return False;
323 }
324
325 if (depth <= 8)
326 owncolmap = True;
327 else
328 xcolmap = DefaultColormapOfScreen(screen);
329
330 if (DoesBackingStore(screen) == NotUseful)
331 ownbackstore = True;
332
333 test = 1;
334 host_be = !(BOOL) (*(uint8 *) (&test));
335 xserver_be = (ImageByteOrder(display) == MSBFirst);
336
337 if (fullscreen)
338 {
339 width = WidthOfScreen(screen);
340 height = HeightOfScreen(screen);
341 }
342
343 xkeymap_init();
344 return True;
345 }
346
347 BOOL
348 ui_create_window()
349 {
350 XSetWindowAttributes attribs;
351 XClassHint *classhints;
352 XSizeHints *sizehints;
353 XEvent xevent;
354
355 attribs.background_pixel = BlackPixelOfScreen(screen);
356 attribs.backing_store = ownbackstore ? NotUseful : Always;
357 attribs.override_redirect = fullscreen;
358 wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, width, height,
359 0, CopyFromParent, InputOutput, CopyFromParent,
360 CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
361
362 XStoreName(display, wnd, title);
363
364 classhints = XAllocClassHint();
365 if (classhints != NULL)
366 {
367 classhints->res_name = classhints->res_class = "rdesktop";
368 XSetClassHint(display, wnd, classhints);
369 XFree(classhints);
370 }
371
372 sizehints = XAllocSizeHints();
373 if (sizehints)
374 {
375 sizehints->flags = PMinSize | PMaxSize;
376 sizehints->min_width = sizehints->max_width = width;
377 sizehints->min_height = sizehints->max_height = height;
378 XSetWMNormalHints(display, wnd, sizehints);
379 XFree(sizehints);
380 }
381
382 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
383 VisibilityChangeMask | FocusChangeMask;
384
385 if (grab_keyboard)
386 input_mask |= EnterWindowMask | LeaveWindowMask;
387 if (sendmotion)
388 input_mask |= PointerMotionMask;
389 if (ownbackstore)
390 input_mask |= ExposureMask;
391 if (enable_compose)
392 input_mask |= init_inputmethod();
393
394 XSelectInput(display, wnd, input_mask);
395
396 gc = XCreateGC(display, wnd, 0, NULL);
397
398 XMapWindow(display, wnd);
399
400 /* Wait for VisibilityNotify Event */
401 for (;;)
402 {
403 XNextEvent(display, &xevent);
404 if (xevent.type == VisibilityNotify)
405 break;
406 }
407
408 if (ownbackstore)
409 backstore = XCreatePixmap(display, wnd, width, height, depth);
410
411 /* clear the window so that cached data is not viewed upon start... */
412 XSetBackground(display, gc, 0);
413 XSetForeground(display, gc, 0);
414 FILL_RECTANGLE(0, 0, width, height);
415 /* make sure the window is focused */
416 XSetInputFocus(display, wnd, RevertToPointerRoot, CurrentTime);
417
418 return True;
419 }
420
421 void
422 ui_destroy_window()
423 {
424 if (ownbackstore)
425 XFreePixmap(display, backstore);
426
427 XFreeGC(display, gc);
428
429 close_inputmethod();
430
431 XDestroyWindow(display, wnd);
432 XCloseDisplay(display);
433 display = NULL;
434 }
435
436 void
437 reset_keys()
438 {
439 /* reset keys */
440 uint32 ev_time;
441 ev_time = time(NULL);
442 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
443 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
444 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
445 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
446 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
447 rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
448 }
449
450 void
451 toggle_fullscreen()
452 {
453 /* save window contents */
454 Pixmap pixmap;
455 pixmap = XCreatePixmap(display, wnd, width, height, depth);
456 if (ownbackstore)
457 XCopyArea(display, backstore, pixmap, gc, 0, 0, width, height, 0, 0);
458 else
459 XCopyArea(display, wnd, pixmap, gc, 0, 0, width, height, 0, 0);
460 fullscreen = fullscreen ? False : True;
461 close_inputmethod();
462 if (ownbackstore)
463 XFreePixmap(display, backstore);
464 XFreeGC(display, gc);
465 XDestroyWindow(display, wnd);
466 ui_create_window();
467 ui_set_cursor(cache_get_cursor(0));
468 ui_move_pointer(width / 2, height / 2);
469 reset_keys();
470 /* restore window contents */
471 if (ownbackstore)
472 XCopyArea(display, pixmap, backstore, gc, 0, 0, width, height, 0, 0);
473 XCopyArea(display, pixmap, wnd, gc, 0, 0, width, height, 0, 0);
474 XFreePixmap(display, pixmap);
475 }
476
477 /* Process all events in Xlib queue */
478 static void
479 xwin_process_events()
480 {
481 XEvent xevent;
482
483 KeySym keysym;
484 uint16 button, flags;
485 uint32 ev_time;
486 key_translation tr;
487 char *ksname = NULL;
488 char str[256];
489 Status status;
490
491 while (XCheckMaskEvent(display, ~0, &xevent))
492 {
493 if (enable_compose && (XFilterEvent(&xevent, None) == True))
494 {
495 DEBUG_KBD(("Filtering event\n"));
496 continue;
497 }
498
499 ev_time = time(NULL);
500 flags = 0;
501
502 switch (xevent.type)
503 {
504 case KeyPress:
505 if (IC != NULL)
506 /* Multi_key compatible version */
507 {
508 XmbLookupString(IC,
509 (XKeyPressedEvent *) &
510 xevent, str, sizeof(str), &keysym, &status);
511 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
512 {
513 error("XmbLookupString failed with status 0x%x\n",
514 status);
515 break;
516 }
517 }
518 else
519 {
520 /* Plain old XLookupString */
521 DEBUG_KBD(("No input context, using XLookupString\n"));
522 XLookupString((XKeyEvent *) & xevent,
523 str, sizeof(str), &keysym, NULL);
524 }
525
526 ksname = get_ksname(keysym);
527 DEBUG_KBD(("\nKeyPress for (keysym 0x%lx, %s)\n", keysym, ksname));
528
529 if (handle_special_keys(keysym, ev_time, True))
530 break;
531
532 tr = xkeymap_translate_key(keysym,
533 xevent.xkey.keycode, xevent.xkey.state);
534
535 if (tr.scancode == 0)
536 break;
537
538 ensure_remote_modifiers(ev_time, tr);
539
540 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
541 break;
542 case KeyRelease:
543 XLookupString((XKeyEvent *) & xevent, str,
544 sizeof(str), &keysym, NULL);
545
546 ksname = get_ksname(keysym);
547 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
548 ksname));
549
550 if (handle_special_keys(keysym, ev_time, False))
551 break;
552
553 tr = xkeymap_translate_key(keysym,
554 xevent.xkey.keycode, xevent.xkey.state);
555
556 if (tr.scancode == 0)
557 break;
558
559 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
560 break;
561
562 case ButtonPress:
563 flags = MOUSE_FLAG_DOWN;
564 /* fall through */
565
566 case ButtonRelease:
567 button = xkeymap_translate_button(xevent.xbutton.button);
568 if (button == 0)
569 break;
570
571 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
572 flags | button, xevent.xbutton.x, xevent.xbutton.y);
573 break;
574
575 case MotionNotify:
576 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
577 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
578 break;
579
580 case FocusIn:
581 /* fall through */
582 case EnterNotify:
583 if (grab_keyboard)
584 XGrabKeyboard(display, wnd, True,
585 GrabModeAsync, GrabModeAsync, CurrentTime);
586 break;
587
588 case FocusOut:
589 reset_keys();
590 /* fall through */
591 case LeaveNotify:
592 if (grab_keyboard)
593 XUngrabKeyboard(display, CurrentTime);
594 break;
595
596 case Expose:
597 XCopyArea(display, backstore, wnd, gc,
598 xevent.xexpose.x, xevent.xexpose.y,
599 xevent.xexpose.width,
600 xevent.xexpose.height,
601 xevent.xexpose.x, xevent.xexpose.y);
602 break;
603
604 case MappingNotify:
605 /* Refresh keyboard mapping if it has changed. This is important for
606 Xvnc, since it allocates keycodes dynamically */
607 if (xevent.xmapping.request == MappingKeyboard
608 || xevent.xmapping.request == MappingModifier)
609 XRefreshKeyboardMapping(&xevent.xmapping);
610 break;
611
612 }
613 }
614 }
615
616 void
617 ui_select(int rdp_socket)
618 {
619 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
620 fd_set rfds;
621
622 FD_ZERO(&rfds);
623
624 while (True)
625 {
626 /* Process any events already waiting */
627 XFlush(display);
628 xwin_process_events();
629
630 FD_ZERO(&rfds);
631 FD_SET(rdp_socket, &rfds);
632 FD_SET(x_socket, &rfds);
633
634 switch (select(n, &rfds, NULL, NULL, NULL))
635 {
636 case -1:
637 error("select: %s\n", strerror(errno));
638
639 case 0:
640 continue;
641 }
642
643 if (FD_ISSET(rdp_socket, &rfds))
644 return;
645 }
646 }
647
648 void
649 ui_move_pointer(int x, int y)
650 {
651 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
652 }
653
654 HBITMAP
655 ui_create_bitmap(int width, int height, uint8 * data)
656 {
657 XImage *image;
658 Pixmap bitmap;
659 uint8 *tdata;
660
661 tdata = (owncolmap ? data : translate_image(width, height, data));
662 bitmap = XCreatePixmap(display, wnd, width, height, depth);
663 image = XCreateImage(display, visual, depth, ZPixmap, 0,
664 (char *) tdata, width, height, 8, 0);
665
666 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
667
668 XFree(image);
669 if (!owncolmap)
670 xfree(tdata);
671 return (HBITMAP) bitmap;
672 }
673
674 void
675 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
676 {
677 XImage *image;
678 uint8 *tdata;
679
680 tdata = (owncolmap ? data : translate_image(width, height, data));
681 image = XCreateImage(display, visual, depth, ZPixmap, 0,
682 (char *) tdata, width, height, 8, 0);
683
684 if (ownbackstore)
685 {
686 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
687 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
688 }
689 else
690 {
691 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
692 }
693
694 XFree(image);
695 if (!owncolmap)
696 xfree(tdata);
697 }
698
699 void
700 ui_destroy_bitmap(HBITMAP bmp)
701 {
702 XFreePixmap(display, (Pixmap) bmp);
703 }
704
705 HGLYPH
706 ui_create_glyph(int width, int height, uint8 * data)
707 {
708 XImage *image;
709 Pixmap bitmap;
710 int scanline;
711 GC gc;
712
713 scanline = (width + 7) / 8;
714
715 bitmap = XCreatePixmap(display, wnd, width, height, 1);
716 gc = XCreateGC(display, bitmap, 0, NULL);
717
718 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
719 width, height, 8, scanline);
720 image->byte_order = MSBFirst;
721 image->bitmap_bit_order = MSBFirst;
722 XInitImage(image);
723
724 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
725
726 XFree(image);
727 XFreeGC(display, gc);
728 return (HGLYPH) bitmap;
729 }
730
731 void
732 ui_destroy_glyph(HGLYPH glyph)
733 {
734 XFreePixmap(display, (Pixmap) glyph);
735 }
736
737 HCURSOR
738 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
739 uint8 * andmask, uint8 * xormask)
740 {
741 HGLYPH maskglyph, cursorglyph;
742 XColor bg, fg;
743 Cursor xcursor;
744 uint8 *cursor, *pcursor;
745 uint8 *mask, *pmask;
746 uint8 nextbit;
747 int scanline, offset;
748 int i, j;
749
750 scanline = (width + 7) / 8;
751 offset = scanline * height;
752
753 cursor = xmalloc(offset);
754 memset(cursor, 0, offset);
755
756 mask = xmalloc(offset);
757 memset(mask, 0, offset);
758
759 /* approximate AND and XOR masks with a monochrome X pointer */
760 for (i = 0; i < height; i++)
761 {
762 offset -= scanline;
763 pcursor = &cursor[offset];
764 pmask = &mask[offset];
765
766 for (j = 0; j < scanline; j++)
767 {
768 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
769 {
770 if (xormask[0] || xormask[1] || xormask[2])
771 {
772 *pcursor |= (~(*andmask) & nextbit);
773 *pmask |= nextbit;
774 }
775 else
776 {
777 *pcursor |= ((*andmask) & nextbit);
778 *pmask |= (~(*andmask) & nextbit);
779 }
780
781 xormask += 3;
782 }
783
784 andmask++;
785 pcursor++;
786 pmask++;
787 }
788 }
789
790 fg.red = fg.blue = fg.green = 0xffff;
791 bg.red = bg.blue = bg.green = 0x0000;
792 fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
793
794 cursorglyph = ui_create_glyph(width, height, cursor);
795 maskglyph = ui_create_glyph(width, height, mask);
796
797 xcursor =
798 XCreatePixmapCursor(display, (Pixmap) cursorglyph,
799 (Pixmap) maskglyph, &fg, &bg, x, y);
800
801 ui_destroy_glyph(maskglyph);
802 ui_destroy_glyph(cursorglyph);
803 xfree(mask);
804 xfree(cursor);
805 return (HCURSOR) xcursor;
806 }
807
808 void
809 ui_set_cursor(HCURSOR cursor)
810 {
811 XDefineCursor(display, wnd, (Cursor) cursor);
812 }
813
814 void
815 ui_destroy_cursor(HCURSOR cursor)
816 {
817 XFreeCursor(display, (Cursor) cursor);
818 }
819
820 #define MAKE_XCOLOR(xc,c) \
821 (xc)->red = ((c)->red << 8) | (c)->red; \
822 (xc)->green = ((c)->green << 8) | (c)->green; \
823 (xc)->blue = ((c)->blue << 8) | (c)->blue; \
824 (xc)->flags = DoRed | DoGreen | DoBlue;
825
826 HCOLOURMAP
827 ui_create_colourmap(COLOURMAP * colours)
828 {
829 COLOURENTRY *entry;
830 int i, ncolours = colours->ncolours;
831
832 if (owncolmap)
833 {
834 XColor *xcolours, *xentry;
835 Colormap map;
836
837 xcolours = xmalloc(sizeof(XColor) * ncolours);
838 for (i = 0; i < ncolours; i++)
839 {
840 entry = &colours->colours[i];
841 xentry = &xcolours[i];
842 xentry->pixel = i;
843 MAKE_XCOLOR(xentry, entry);
844 }
845
846 map = XCreateColormap(display, wnd, visual, AllocAll);
847 XStoreColors(display, map, xcolours, ncolours);
848
849 xfree(xcolours);
850 return (HCOLOURMAP) map;
851 }
852 else
853 {
854 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
855 XColor xentry;
856 uint32 colour;
857
858 for (i = 0; i < ncolours; i++)
859 {
860 entry = &colours->colours[i];
861 MAKE_XCOLOR(&xentry, entry);
862
863 if (XAllocColor(display, xcolmap, &xentry) != 0)
864 colour = xentry.pixel;
865 else
866 colour = WhitePixelOfScreen(screen);
867
868 /* byte swap here to make translate_image faster */
869 map[i] = translate_colour(colour);
870 }
871
872 return map;
873 }
874 }
875
876 void
877 ui_destroy_colourmap(HCOLOURMAP map)
878 {
879 if (owncolmap)
880 XFreeColormap(display, (Colormap) map);
881 else
882 xfree(map);
883 }
884
885 void
886 ui_set_colourmap(HCOLOURMAP map)
887 {
888 if (owncolmap)
889 XSetWindowColormap(display, wnd, (Colormap) map);
890 else
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()
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()
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