/[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 432 - (show annotations)
Tue Jul 1 09:31:25 2003 UTC (20 years, 10 months ago) by matthewc
File MIME type: text/plain
File size: 38849 byte(s)
Commit of work in progress on channels (so that other people can hack on
RDPSND), in particular:
* channel layer takes care of virtual channel header
* split X dependent parts out of CLIPRDR, simplified IPC implementation
* initial RDPDR implementation

1 /* -*- c-basic-offset: 8 -*-
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 #include "xproto.h"
27
28 extern int width;
29 extern int height;
30 extern BOOL sendmotion;
31 extern BOOL fullscreen;
32 extern BOOL grab_keyboard;
33 extern BOOL hide_decorations;
34 extern char title[];
35 extern int server_bpp;
36 extern int win_button_size;
37 BOOL enable_compose = False;
38 BOOL focused;
39 BOOL mouse_in_wnd;
40
41 Display *display;
42 Time last_gesturetime;
43 static int x_socket;
44 static Screen *screen;
45 Window wnd;
46 static GC gc;
47 static Visual *visual;
48 static int depth;
49 static int bpp;
50 static XIM IM;
51 static XIC IC;
52 static XModifierKeymap *mod_map;
53 static Cursor current_cursor;
54 static Atom protocol_atom, kill_atom;
55
56 /* endianness */
57 static BOOL host_be;
58 static BOOL xserver_be;
59
60 /* software backing store */
61 static BOOL ownbackstore;
62 static Pixmap backstore;
63
64 /* Moving in single app mode */
65 static BOOL moving_wnd;
66 static int move_x_offset = 0;
67 static int move_y_offset = 0;
68
69 /* MWM decorations */
70 #define MWM_HINTS_DECORATIONS (1L << 1)
71 #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
72 typedef struct
73 {
74 uint32 flags;
75 uint32 functions;
76 uint32 decorations;
77 sint32 inputMode;
78 uint32 status;
79 }
80 PropMotifWmHints;
81
82 typedef struct
83 {
84 uint32 red;
85 uint32 green;
86 uint32 blue;
87 }
88 PixelColour;
89
90
91 #define FILL_RECTANGLE(x,y,cx,cy)\
92 { \
93 XFillRectangle(display, wnd, gc, x, y, cx, cy); \
94 if (ownbackstore) \
95 XFillRectangle(display, backstore, gc, x, y, cx, cy); \
96 }
97
98 #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
99 { \
100 XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \
101 }
102
103 /* colour maps */
104 BOOL owncolmap = False;
105 static Colormap xcolmap;
106 static uint32 *colmap;
107
108 #define TRANSLATE(col) ( server_bpp != 8 ? translate_colour(col) : owncolmap ? col : translate_colour(colmap[col]) )
109 #define SET_FOREGROUND(col) XSetForeground(display, gc, TRANSLATE(col));
110 #define SET_BACKGROUND(col) XSetBackground(display, gc, TRANSLATE(col));
111
112 static int rop2_map[] = {
113 GXclear, /* 0 */
114 GXnor, /* DPon */
115 GXandInverted, /* DPna */
116 GXcopyInverted, /* Pn */
117 GXandReverse, /* PDna */
118 GXinvert, /* Dn */
119 GXxor, /* DPx */
120 GXnand, /* DPan */
121 GXand, /* DPa */
122 GXequiv, /* DPxn */
123 GXnoop, /* D */
124 GXorInverted, /* DPno */
125 GXcopy, /* P */
126 GXorReverse, /* PDno */
127 GXor, /* DPo */
128 GXset /* 1 */
129 };
130
131 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
132 #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
133
134 static void
135 mwm_hide_decorations(void)
136 {
137 PropMotifWmHints motif_hints;
138 Atom hintsatom;
139
140 /* setup the property */
141 motif_hints.flags = MWM_HINTS_DECORATIONS;
142 motif_hints.decorations = 0;
143
144 /* get the atom for the property */
145 hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
146 if (!hintsatom)
147 {
148 warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
149 return;
150 }
151
152 XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
153 (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
154 }
155
156 static PixelColour
157 split_colour15(uint32 colour)
158 {
159 PixelColour rv;
160 rv.red = (colour & 0x7c00) >> 10;
161 rv.red = (rv.red * 0xff) / 0x1f;
162 rv.green = (colour & 0x03e0) >> 5;
163 rv.green = (rv.green * 0xff) / 0x1f;
164 rv.blue = (colour & 0x1f);
165 rv.blue = (rv.blue * 0xff) / 0x1f;
166 return rv;
167 }
168
169 static PixelColour
170 split_colour16(uint32 colour)
171 {
172 PixelColour rv;
173 rv.red = (colour & 0xf800) >> 11;
174 rv.red = (rv.red * 0xff) / 0x1f;
175 rv.green = (colour & 0x07e0) >> 5;
176 rv.green = (rv.green * 0xff) / 0x3f;
177 rv.blue = (colour & 0x001f);
178 rv.blue = (rv.blue * 0xff) / 0x1f;
179 return rv;
180 }
181
182 static PixelColour
183 split_colour24(uint32 colour)
184 {
185 PixelColour rv;
186 rv.blue = (colour & 0xff0000) >> 16;
187 rv.green = (colour & 0xff00) >> 8;
188 rv.red = (colour & 0xff);
189 return rv;
190 }
191
192 static uint32
193 make_colour16(PixelColour pc)
194 {
195 pc.red = (pc.red * 0x1f) / 0xff;
196 pc.green = (pc.green * 0x3f) / 0xff;
197 pc.blue = (pc.blue * 0x1f) / 0xff;
198 return (pc.red << 11) | (pc.green << 5) | pc.blue;
199 }
200
201 static uint32
202 make_colour24(PixelColour pc)
203 {
204 return (pc.red << 16) | (pc.green << 8) | pc.blue;
205 }
206
207 static uint32
208 make_colour32(PixelColour pc)
209 {
210 return (pc.red << 16) | (pc.green << 8) | pc.blue;
211 }
212
213 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
214 #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
215 #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
216 x = (x << 16) | (x >> 16); }
217
218 static uint32
219 translate_colour(uint32 colour)
220 {
221 switch (server_bpp)
222 {
223 case 15:
224 switch (bpp)
225 {
226 case 16:
227 colour = make_colour16(split_colour15(colour));
228 break;
229 case 24:
230 colour = make_colour24(split_colour15(colour));
231 break;
232 case 32:
233 colour = make_colour32(split_colour15(colour));
234 break;
235 }
236 break;
237 case 16:
238 switch (bpp)
239 {
240 case 16:
241 break;
242 case 24:
243 colour = make_colour24(split_colour16(colour));
244 break;
245 case 32:
246 colour = make_colour32(split_colour16(colour));
247 break;
248 }
249 break;
250 case 24:
251 switch (bpp)
252 {
253 case 16:
254 colour = make_colour16(split_colour24(colour));
255 break;
256 case 24:
257 break;
258 case 32:
259 colour = make_colour32(split_colour24(colour));
260 break;
261 }
262 break;
263 }
264 switch (bpp)
265 {
266 case 16:
267 if (host_be != xserver_be)
268 BSWAP16(colour);
269 break;
270
271 case 24:
272 if (xserver_be)
273 BSWAP24(colour);
274 break;
275
276 case 32:
277 if (host_be != xserver_be)
278 BSWAP32(colour);
279 break;
280 }
281
282 return colour;
283 }
284
285 static void
286 translate8to8(uint8 * data, uint8 * out, uint8 * end)
287 {
288 while (out < end)
289 *(out++) = (uint8) colmap[*(data++)];
290 }
291
292 static void
293 translate8to16(uint8 * data, uint16 * out, uint16 * end)
294 {
295 while (out < end)
296 *(out++) = (uint16) colmap[*(data++)];
297 }
298
299 /* little endian - conversion happens when colourmap is built */
300 static void
301 translate8to24(uint8 * data, uint8 * out, uint8 * end)
302 {
303 uint32 value;
304
305 while (out < end)
306 {
307 value = colmap[*(data++)];
308 *(out++) = value;
309 *(out++) = value >> 8;
310 *(out++) = value >> 16;
311 }
312 }
313
314 static void
315 translate8to32(uint8 * data, uint32 * out, uint32 * end)
316 {
317 while (out < end)
318 *(out++) = colmap[*(data++)];
319 }
320
321 /* todo the remaining translate function might need some big endian check ?? */
322
323 static void
324 translate15to16(uint16 * data, uint16 * out, uint16 * end)
325 {
326 while (out < end)
327 *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
328 }
329
330 static void
331 translate15to24(uint16 * data, uint8 * out, uint8 * end)
332 {
333 uint32 value;
334
335 while (out < end)
336 {
337 value = make_colour24(split_colour15(*(data++)));
338 *(out++) = value;
339 *(out++) = value >> 8;
340 *(out++) = value >> 16;
341 }
342 }
343
344 static void
345 translate15to32(uint16 * data, uint32 * out, uint32 * end)
346 {
347 while (out < end)
348 *(out++) = make_colour32(split_colour15(*(data++)));
349 }
350
351 static void
352 translate16to16(uint16 * data, uint16 * out, uint16 * end)
353 {
354 while (out < end)
355 *(out++) = (uint16) (*(data++));
356 }
357
358
359 static void
360 translate16to24(uint16 * data, uint8 * out, uint8 * end)
361 {
362 uint32 value;
363
364 while (out < end)
365 {
366 value = make_colour24(split_colour16(*(data++)));
367 *(out++) = value;
368 *(out++) = value >> 8;
369 *(out++) = value >> 16;
370 }
371 }
372
373 static void
374 translate16to32(uint16 * data, uint32 * out, uint32 * end)
375 {
376 while (out < end)
377 *(out++) = make_colour32(split_colour16(*(data++)));
378 }
379
380 static void
381 translate24to16(uint8 * data, uint16 * out, uint16 * end)
382 {
383 uint32 pixel = 0;
384 while (out < end)
385 {
386 pixel = *(data++) << 16;
387 pixel |= *(data++) << 8;
388 pixel |= *(data++);
389 *(out++) = (uint16) make_colour16(split_colour24(pixel));
390 }
391 }
392
393 static void
394 translate24to24(uint8 * data, uint8 * out, uint8 * end)
395 {
396 while (out < end)
397 {
398 *(out++) = (*(data++));
399 }
400 }
401
402 static void
403 translate24to32(uint8 * data, uint32 * out, uint32 * end)
404 {
405 uint32 pixel = 0;
406 while (out < end)
407 {
408 pixel = *(data++);
409 pixel |= *(data++) << 8;
410 pixel |= *(data++) << 16;
411 *(out++) = pixel;
412 }
413 }
414
415 static uint8 *
416 translate_image(int width, int height, uint8 * data)
417 {
418 int size = width * height * bpp / 8;
419 uint8 *out = (uint8 *) xmalloc(size);
420 uint8 *end = out + size;
421
422 switch (server_bpp)
423 {
424 case 24:
425 switch (bpp)
426 {
427 case 32:
428 translate24to32(data, (uint32 *) out, (uint32 *) end);
429 break;
430 case 24:
431 translate24to24(data, out, end);
432 break;
433 case 16:
434 translate24to16(data, (uint16 *) out, (uint16 *) end);
435 break;
436 }
437 break;
438 case 16:
439 switch (bpp)
440 {
441 case 32:
442 translate16to32((uint16 *) data, (uint32 *) out,
443 (uint32 *) end);
444 break;
445 case 24:
446 translate16to24((uint16 *) data, out, end);
447 break;
448 case 16:
449 translate16to16((uint16 *) data, (uint16 *) out,
450 (uint16 *) end);
451 break;
452 }
453 break;
454 case 15:
455 switch (bpp)
456 {
457 case 32:
458 translate15to32((uint16 *) data, (uint32 *) out,
459 (uint32 *) end);
460 break;
461 case 24:
462 translate15to24((uint16 *) data, out, end);
463 break;
464 case 16:
465 translate15to16((uint16 *) data, (uint16 *) out,
466 (uint16 *) end);
467 break;
468 }
469 break;
470 case 8:
471 switch (bpp)
472 {
473 case 8:
474 translate8to8(data, out, end);
475 break;
476 case 16:
477 translate8to16(data, (uint16 *) out, (uint16 *) end);
478 break;
479 case 24:
480 translate8to24(data, out, end);
481 break;
482 case 32:
483 translate8to32(data, (uint32 *) out, (uint32 *) end);
484 break;
485 }
486 break;
487 }
488 return out;
489 }
490
491 BOOL
492 get_key_state(unsigned int state, uint32 keysym)
493 {
494 int modifierpos, key, keysymMask = 0;
495 int offset;
496
497 KeyCode keycode = XKeysymToKeycode(display, keysym);
498
499 if (keycode == NoSymbol)
500 return False;
501
502 for (modifierpos = 0; modifierpos < 8; modifierpos++)
503 {
504 offset = mod_map->max_keypermod * modifierpos;
505
506 for (key = 0; key < mod_map->max_keypermod; key++)
507 {
508 if (mod_map->modifiermap[offset + key] == keycode)
509 keysymMask |= 1 << modifierpos;
510 }
511 }
512
513 return (state & keysymMask) ? True : False;
514 }
515
516 BOOL
517 ui_init(void)
518 {
519 XPixmapFormatValues *pfm;
520 uint16 test;
521 int i;
522
523 display = XOpenDisplay(NULL);
524 if (display == NULL)
525 {
526 error("Failed to open display: %s\n", XDisplayName(NULL));
527 return False;
528 }
529
530 x_socket = ConnectionNumber(display);
531 screen = DefaultScreenOfDisplay(display);
532 visual = DefaultVisualOfScreen(screen);
533 depth = DefaultDepthOfScreen(screen);
534
535 pfm = XListPixmapFormats(display, &i);
536 if (pfm != NULL)
537 {
538 /* Use maximum bpp for this depth - this is generally
539 desirable, e.g. 24 bits->32 bits. */
540 while (i--)
541 {
542 if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
543 {
544 bpp = pfm[i].bits_per_pixel;
545 }
546 }
547 XFree(pfm);
548 }
549
550 if (bpp < 8)
551 {
552 error("Less than 8 bpp not currently supported.\n");
553 XCloseDisplay(display);
554 return False;
555 }
556
557 if (owncolmap != True)
558 {
559 xcolmap = DefaultColormapOfScreen(screen);
560 if (depth <= 8)
561 warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
562 }
563
564 gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
565
566 if (DoesBackingStore(screen) != Always)
567 ownbackstore = True;
568
569 test = 1;
570 host_be = !(BOOL) (*(uint8 *) (&test));
571 xserver_be = (ImageByteOrder(display) == MSBFirst);
572
573 if ((width == 0) || (height == 0))
574 {
575 /* Fetch geometry from _NET_WORKAREA */
576 uint32 x, y, cx, cy;
577
578 if (get_current_workarea(&x, &y, &cx, &cy) == 0)
579 {
580 width = cx;
581 height = cy;
582 }
583 else
584 {
585 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
586 width = 800;
587 height = 600;
588 }
589 }
590
591 if (fullscreen)
592 {
593 width = WidthOfScreen(screen);
594 height = HeightOfScreen(screen);
595 }
596
597 /* make sure width is a multiple of 4 */
598 width = (width + 3) & ~3;
599
600 if (ownbackstore)
601 {
602 backstore =
603 XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
604
605 /* clear to prevent rubbish being exposed at startup */
606 XSetForeground(display, gc, BlackPixelOfScreen(screen));
607 XFillRectangle(display, backstore, gc, 0, 0, width, height);
608 }
609
610 mod_map = XGetModifierMapping(display);
611
612 if (enable_compose)
613 IM = XOpenIM(display, NULL, NULL, NULL);
614
615 xkeymap_init();
616 xclip_init();
617
618 /* todo take this out when high colour is done */
619 printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth);
620
621 return True;
622 }
623
624 void
625 ui_deinit(void)
626 {
627 if (IM != NULL)
628 XCloseIM(IM);
629
630 XFreeModifiermap(mod_map);
631
632 if (ownbackstore)
633 XFreePixmap(display, backstore);
634
635 XFreeGC(display, gc);
636 XCloseDisplay(display);
637 display = NULL;
638 }
639
640 BOOL
641 ui_create_window(void)
642 {
643 XSetWindowAttributes attribs;
644 XClassHint *classhints;
645 XSizeHints *sizehints;
646 int wndwidth, wndheight;
647 long input_mask, ic_input_mask;
648 XEvent xevent;
649
650 wndwidth = fullscreen ? WidthOfScreen(screen) : width;
651 wndheight = fullscreen ? HeightOfScreen(screen) : height;
652
653 attribs.background_pixel = BlackPixelOfScreen(screen);
654 attribs.backing_store = ownbackstore ? NotUseful : Always;
655 attribs.override_redirect = fullscreen;
656
657 wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
658 0, CopyFromParent, InputOutput, CopyFromParent,
659 CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
660
661 XStoreName(display, wnd, title);
662
663 if (hide_decorations)
664 mwm_hide_decorations();
665
666 classhints = XAllocClassHint();
667 if (classhints != NULL)
668 {
669 classhints->res_name = classhints->res_class = "rdesktop";
670 XSetClassHint(display, wnd, classhints);
671 XFree(classhints);
672 }
673
674 sizehints = XAllocSizeHints();
675 if (sizehints)
676 {
677 sizehints->flags = PMinSize | PMaxSize;
678 sizehints->min_width = sizehints->max_width = width;
679 sizehints->min_height = sizehints->max_height = height;
680 XSetWMNormalHints(display, wnd, sizehints);
681 XFree(sizehints);
682 }
683
684 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
685 VisibilityChangeMask | FocusChangeMask;
686
687 if (sendmotion)
688 input_mask |= PointerMotionMask;
689 if (ownbackstore)
690 input_mask |= ExposureMask;
691 if (fullscreen || grab_keyboard)
692 input_mask |= EnterWindowMask;
693 if (grab_keyboard)
694 input_mask |= LeaveWindowMask;
695
696 if (IM != NULL)
697 {
698 IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
699 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
700
701 if ((IC != NULL)
702 && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
703 input_mask |= ic_input_mask;
704 }
705
706 XSelectInput(display, wnd, input_mask);
707 XMapWindow(display, wnd);
708
709 /* wait for VisibilityNotify */
710 do
711 {
712 XMaskEvent(display, VisibilityChangeMask, &xevent);
713 }
714 while (xevent.type != VisibilityNotify);
715
716 focused = False;
717 mouse_in_wnd = False;
718
719 /* handle the WM_DELETE_WINDOW protocol */
720 protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
721 kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
722 XSetWMProtocols(display, wnd, &kill_atom, 1);
723
724 return True;
725 }
726
727 void
728 ui_destroy_window(void)
729 {
730 if (IC != NULL)
731 XDestroyIC(IC);
732
733 XDestroyWindow(display, wnd);
734 }
735
736 void
737 xwin_toggle_fullscreen(void)
738 {
739 Pixmap contents = 0;
740
741 if (!ownbackstore)
742 {
743 /* need to save contents of window */
744 contents = XCreatePixmap(display, wnd, width, height, depth);
745 XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
746 }
747
748 ui_destroy_window();
749 fullscreen = !fullscreen;
750 ui_create_window();
751
752 XDefineCursor(display, wnd, current_cursor);
753
754 if (!ownbackstore)
755 {
756 XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
757 XFreePixmap(display, contents);
758 }
759 }
760
761 /* Process all events in Xlib queue
762 Returns 0 after user quit, 1 otherwise */
763 static int
764 xwin_process_events(void)
765 {
766 XEvent xevent;
767 KeySym keysym;
768 uint16 button, flags;
769 uint32 ev_time;
770 key_translation tr;
771 char str[256];
772 Status status;
773 unsigned int state;
774 Window wdummy;
775 int dummy;
776
777 while (XPending(display) > 0)
778 {
779 XNextEvent(display, &xevent);
780
781 if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
782 {
783 DEBUG_KBD(("Filtering event\n"));
784 continue;
785 }
786
787 flags = 0;
788
789 switch (xevent.type)
790 {
791 case ClientMessage:
792 /* the window manager told us to quit */
793 if ((xevent.xclient.message_type == protocol_atom)
794 && ((Atom) xevent.xclient.data.l[0] == kill_atom))
795 /* Quit */
796 return 0;
797 break;
798
799 case KeyPress:
800 last_gesturetime = xevent.xkey.time;
801 if (IC != NULL)
802 /* Multi_key compatible version */
803 {
804 XmbLookupString(IC,
805 &xevent.xkey, str, sizeof(str), &keysym, &status);
806 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
807 {
808 error("XmbLookupString failed with status 0x%x\n",
809 status);
810 break;
811 }
812 }
813 else
814 {
815 /* Plain old XLookupString */
816 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
817 XLookupString((XKeyEvent *) & xevent,
818 str, sizeof(str), &keysym, NULL);
819 }
820
821 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
822 get_ksname(keysym)));
823
824 ev_time = time(NULL);
825 if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
826 break;
827
828 tr = xkeymap_translate_key(keysym,
829 xevent.xkey.keycode, xevent.xkey.state);
830
831 if (tr.scancode == 0)
832 break;
833
834 ensure_remote_modifiers(ev_time, tr);
835
836 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
837 break;
838
839 case KeyRelease:
840 last_gesturetime = xevent.xkey.time;
841 XLookupString((XKeyEvent *) & xevent, str,
842 sizeof(str), &keysym, NULL);
843
844 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
845 get_ksname(keysym)));
846
847 ev_time = time(NULL);
848 if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
849 break;
850
851 tr = xkeymap_translate_key(keysym,
852 xevent.xkey.keycode, xevent.xkey.state);
853
854 if (tr.scancode == 0)
855 break;
856
857 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
858 break;
859
860 case ButtonPress:
861 flags = MOUSE_FLAG_DOWN;
862 /* fall through */
863
864 case ButtonRelease:
865 last_gesturetime = xevent.xbutton.time;
866 button = xkeymap_translate_button(xevent.xbutton.button);
867 if (button == 0)
868 break;
869
870 /* If win_button_size is nonzero, enable single app mode */
871 if (xevent.xbutton.y < win_button_size)
872 {
873 /* Stop moving window when button is released, regardless of cursor position */
874 if (moving_wnd && (xevent.type == ButtonRelease))
875 moving_wnd = False;
876
877 /* Check from right to left: */
878
879 if (xevent.xbutton.x >= width - win_button_size)
880 {
881 /* The close button, continue */
882 ;
883 }
884 else if (xevent.xbutton.x >= width - win_button_size * 2)
885 {
886 /* The maximize/restore button. Do not send to
887 server. It might be a good idea to change the
888 cursor or give some other visible indication
889 that rdesktop inhibited this click */
890 break;
891 }
892 else if (xevent.xbutton.x >= width - win_button_size * 3)
893 {
894 /* The minimize button. Iconify window. */
895 XIconifyWindow(display, wnd,
896 DefaultScreen(display));
897 break;
898 }
899 else if (xevent.xbutton.x <= win_button_size)
900 {
901 /* The system menu. Ignore. */
902 break;
903 }
904 else
905 {
906 /* The title bar. */
907 if ((xevent.type == ButtonPress) && !fullscreen
908 && hide_decorations)
909 {
910 moving_wnd = True;
911 move_x_offset = xevent.xbutton.x;
912 move_y_offset = xevent.xbutton.y;
913 }
914 break;
915
916 }
917 }
918
919 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
920 flags | button, xevent.xbutton.x, xevent.xbutton.y);
921 break;
922
923 case MotionNotify:
924 if (moving_wnd)
925 {
926 XMoveWindow(display, wnd,
927 xevent.xmotion.x_root - move_x_offset,
928 xevent.xmotion.y_root - move_y_offset);
929 break;
930 }
931
932 if (fullscreen && !focused)
933 XSetInputFocus(display, wnd, RevertToPointerRoot,
934 CurrentTime);
935 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
936 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
937 break;
938
939 case FocusIn:
940 if (xevent.xfocus.mode == NotifyGrab)
941 break;
942 focused = True;
943 XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
944 &dummy, &dummy, &state);
945 reset_modifier_keys(state);
946 if (grab_keyboard && mouse_in_wnd)
947 XGrabKeyboard(display, wnd, True,
948 GrabModeAsync, GrabModeAsync, CurrentTime);
949 break;
950
951 case FocusOut:
952 if (xevent.xfocus.mode == NotifyUngrab)
953 break;
954 focused = False;
955 if (xevent.xfocus.mode == NotifyWhileGrabbed)
956 XUngrabKeyboard(display, CurrentTime);
957 break;
958
959 case EnterNotify:
960 /* we only register for this event when in fullscreen mode */
961 /* or grab_keyboard */
962 mouse_in_wnd = True;
963 if (fullscreen)
964 {
965 XSetInputFocus(display, wnd, RevertToPointerRoot,
966 CurrentTime);
967 break;
968 }
969 if (focused)
970 XGrabKeyboard(display, wnd, True,
971 GrabModeAsync, GrabModeAsync, CurrentTime);
972 break;
973
974 case LeaveNotify:
975 /* we only register for this event when grab_keyboard */
976 mouse_in_wnd = False;
977 XUngrabKeyboard(display, CurrentTime);
978 break;
979
980 case Expose:
981 XCopyArea(display, backstore, wnd, gc,
982 xevent.xexpose.x, xevent.xexpose.y,
983 xevent.xexpose.width,
984 xevent.xexpose.height,
985 xevent.xexpose.x, xevent.xexpose.y);
986 break;
987
988 case MappingNotify:
989 /* Refresh keyboard mapping if it has changed. This is important for
990 Xvnc, since it allocates keycodes dynamically */
991 if (xevent.xmapping.request == MappingKeyboard
992 || xevent.xmapping.request == MappingModifier)
993 XRefreshKeyboardMapping(&xevent.xmapping);
994
995 if (xevent.xmapping.request == MappingModifier)
996 {
997 XFreeModifiermap(mod_map);
998 mod_map = XGetModifierMapping(display);
999 }
1000 break;
1001
1002 /* clipboard stuff */
1003 case SelectionNotify:
1004 xclip_handle_SelectionNotify(&xevent.xselection);
1005 break;
1006 case SelectionRequest:
1007 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1008 break;
1009 case SelectionClear:
1010 xclip_handle_SelectionClear();
1011 break;
1012 case PropertyNotify:
1013 xclip_handle_PropertyNotify(&xevent.xproperty);
1014 break;
1015 }
1016 }
1017 /* Keep going */
1018 return 1;
1019 }
1020
1021 /* Returns 0 after user quit, 1 otherwise */
1022 int
1023 ui_select(int rdp_socket)
1024 {
1025 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
1026 fd_set rfds;
1027
1028 FD_ZERO(&rfds);
1029
1030 while (True)
1031 {
1032 /* Process any events already waiting */
1033 if (!xwin_process_events())
1034 /* User quit */
1035 return 0;
1036
1037 FD_ZERO(&rfds);
1038 FD_SET(rdp_socket, &rfds);
1039 FD_SET(x_socket, &rfds);
1040
1041 switch (select(n, &rfds, NULL, NULL, NULL))
1042 {
1043 case -1:
1044 error("select: %s\n", strerror(errno));
1045
1046 case 0:
1047 continue;
1048 }
1049
1050 if (FD_ISSET(rdp_socket, &rfds))
1051 return 1;
1052 }
1053 }
1054
1055 void
1056 ui_move_pointer(int x, int y)
1057 {
1058 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
1059 }
1060
1061 HBITMAP
1062 ui_create_bitmap(int width, int height, uint8 * data)
1063 {
1064 XImage *image;
1065 Pixmap bitmap;
1066 uint8 *tdata;
1067
1068 tdata = (owncolmap ? data : translate_image(width, height, data));
1069 bitmap = XCreatePixmap(display, wnd, width, height, depth);
1070 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1071 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1072
1073 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1074
1075 XFree(image);
1076 if (!owncolmap)
1077 xfree(tdata);
1078 return (HBITMAP) bitmap;
1079 }
1080
1081 void
1082 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1083 {
1084 XImage *image;
1085 uint8 *tdata;
1086 tdata = (owncolmap ? data : translate_image(width, height, data));
1087 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1088 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1089
1090 if (ownbackstore)
1091 {
1092 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1093 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1094 }
1095 else
1096 {
1097 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1098 }
1099
1100 XFree(image);
1101 if (!owncolmap)
1102 xfree(tdata);
1103 }
1104
1105 void
1106 ui_destroy_bitmap(HBITMAP bmp)
1107 {
1108 XFreePixmap(display, (Pixmap) bmp);
1109 }
1110
1111 HGLYPH
1112 ui_create_glyph(int width, int height, uint8 * data)
1113 {
1114 XImage *image;
1115 Pixmap bitmap;
1116 int scanline;
1117 GC gc;
1118
1119 scanline = (width + 7) / 8;
1120
1121 bitmap = XCreatePixmap(display, wnd, width, height, 1);
1122 gc = XCreateGC(display, bitmap, 0, NULL);
1123
1124 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1125 width, height, 8, scanline);
1126 image->byte_order = MSBFirst;
1127 image->bitmap_bit_order = MSBFirst;
1128 XInitImage(image);
1129
1130 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1131
1132 XFree(image);
1133 XFreeGC(display, gc);
1134 return (HGLYPH) bitmap;
1135 }
1136
1137 void
1138 ui_destroy_glyph(HGLYPH glyph)
1139 {
1140 XFreePixmap(display, (Pixmap) glyph);
1141 }
1142
1143 HCURSOR
1144 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1145 uint8 * andmask, uint8 * xormask)
1146 {
1147 HGLYPH maskglyph, cursorglyph;
1148 XColor bg, fg;
1149 Cursor xcursor;
1150 uint8 *cursor, *pcursor;
1151 uint8 *mask, *pmask;
1152 uint8 nextbit;
1153 int scanline, offset;
1154 int i, j;
1155
1156 scanline = (width + 7) / 8;
1157 offset = scanline * height;
1158
1159 cursor = (uint8 *) xmalloc(offset);
1160 memset(cursor, 0, offset);
1161
1162 mask = (uint8 *) xmalloc(offset);
1163 memset(mask, 0, offset);
1164
1165 /* approximate AND and XOR masks with a monochrome X pointer */
1166 for (i = 0; i < height; i++)
1167 {
1168 offset -= scanline;
1169 pcursor = &cursor[offset];
1170 pmask = &mask[offset];
1171
1172 for (j = 0; j < scanline; j++)
1173 {
1174 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1175 {
1176 if (xormask[0] || xormask[1] || xormask[2])
1177 {
1178 *pcursor |= (~(*andmask) & nextbit);
1179 *pmask |= nextbit;
1180 }
1181 else
1182 {
1183 *pcursor |= ((*andmask) & nextbit);
1184 *pmask |= (~(*andmask) & nextbit);
1185 }
1186
1187 xormask += 3;
1188 }
1189
1190 andmask++;
1191 pcursor++;
1192 pmask++;
1193 }
1194 }
1195
1196 fg.red = fg.blue = fg.green = 0xffff;
1197 bg.red = bg.blue = bg.green = 0x0000;
1198 fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1199
1200 cursorglyph = ui_create_glyph(width, height, cursor);
1201 maskglyph = ui_create_glyph(width, height, mask);
1202
1203 xcursor =
1204 XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1205 (Pixmap) maskglyph, &fg, &bg, x, y);
1206
1207 ui_destroy_glyph(maskglyph);
1208 ui_destroy_glyph(cursorglyph);
1209 xfree(mask);
1210 xfree(cursor);
1211 return (HCURSOR) xcursor;
1212 }
1213
1214 void
1215 ui_set_cursor(HCURSOR cursor)
1216 {
1217 current_cursor = (Cursor) cursor;
1218 XDefineCursor(display, wnd, current_cursor);
1219 }
1220
1221 void
1222 ui_destroy_cursor(HCURSOR cursor)
1223 {
1224 XFreeCursor(display, (Cursor) cursor);
1225 }
1226
1227 #define MAKE_XCOLOR(xc,c) \
1228 (xc)->red = ((c)->red << 8) | (c)->red; \
1229 (xc)->green = ((c)->green << 8) | (c)->green; \
1230 (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1231 (xc)->flags = DoRed | DoGreen | DoBlue;
1232
1233
1234 HCOLOURMAP
1235 ui_create_colourmap(COLOURMAP * colours)
1236 {
1237 COLOURENTRY *entry;
1238 int i, ncolours = colours->ncolours;
1239 if (!owncolmap)
1240 {
1241 uint32 *map = (uint32 *) xmalloc(sizeof(*colmap) * ncolours);
1242 XColor xentry;
1243 XColor xc_cache[256];
1244 uint32 colour;
1245 int colLookup = 256;
1246 for (i = 0; i < ncolours; i++)
1247 {
1248 entry = &colours->colours[i];
1249 MAKE_XCOLOR(&xentry, entry);
1250
1251 if (XAllocColor(display, xcolmap, &xentry) == 0)
1252 {
1253 /* Allocation failed, find closest match. */
1254 int j = 256;
1255 int nMinDist = 3 * 256 * 256;
1256 long nDist = nMinDist;
1257
1258 /* only get the colors once */
1259 while (colLookup--)
1260 {
1261 xc_cache[colLookup].pixel = colLookup;
1262 xc_cache[colLookup].red = xc_cache[colLookup].green =
1263 xc_cache[colLookup].blue = 0;
1264 xc_cache[colLookup].flags = 0;
1265 XQueryColor(display,
1266 DefaultColormap(display,
1267 DefaultScreen(display)),
1268 &xc_cache[colLookup]);
1269 }
1270 colLookup = 0;
1271
1272 /* approximate the pixel */
1273 while (j--)
1274 {
1275 if (xc_cache[j].flags)
1276 {
1277 nDist = ((long) (xc_cache[j].red >> 8) -
1278 (long) (xentry.red >> 8)) *
1279 ((long) (xc_cache[j].red >> 8) -
1280 (long) (xentry.red >> 8)) +
1281 ((long) (xc_cache[j].green >> 8) -
1282 (long) (xentry.green >> 8)) *
1283 ((long) (xc_cache[j].green >> 8) -
1284 (long) (xentry.green >> 8)) +
1285 ((long) (xc_cache[j].blue >> 8) -
1286 (long) (xentry.blue >> 8)) *
1287 ((long) (xc_cache[j].blue >> 8) -
1288 (long) (xentry.blue >> 8));
1289 }
1290 if (nDist < nMinDist)
1291 {
1292 nMinDist = nDist;
1293 xentry.pixel = j;
1294 }
1295 }
1296 }
1297 colour = xentry.pixel;
1298
1299 /* update our cache */
1300 if (xentry.pixel < 256)
1301 {
1302 xc_cache[xentry.pixel].red = xentry.red;
1303 xc_cache[xentry.pixel].green = xentry.green;
1304 xc_cache[xentry.pixel].blue = xentry.blue;
1305
1306 }
1307
1308
1309 /* byte swap here to make translate_image faster */
1310 map[i] = translate_colour(colour);
1311 }
1312 return map;
1313 }
1314 else
1315 {
1316 XColor *xcolours, *xentry;
1317 Colormap map;
1318
1319 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1320 for (i = 0; i < ncolours; i++)
1321 {
1322 entry = &colours->colours[i];
1323 xentry = &xcolours[i];
1324 xentry->pixel = i;
1325 MAKE_XCOLOR(xentry, entry);
1326 }
1327
1328 map = XCreateColormap(display, wnd, visual, AllocAll);
1329 XStoreColors(display, map, xcolours, ncolours);
1330
1331 xfree(xcolours);
1332 return (HCOLOURMAP) map;
1333 }
1334 }
1335
1336 void
1337 ui_destroy_colourmap(HCOLOURMAP map)
1338 {
1339 if (!owncolmap)
1340 xfree(map);
1341 else
1342 XFreeColormap(display, (Colormap) map);
1343 }
1344
1345 void
1346 ui_set_colourmap(HCOLOURMAP map)
1347 {
1348 if (!owncolmap)
1349 colmap = (uint32 *) map;
1350 else
1351 XSetWindowColormap(display, wnd, (Colormap) map);
1352 }
1353
1354 void
1355 ui_set_clip(int x, int y, int cx, int cy)
1356 {
1357 XRectangle rect;
1358
1359 rect.x = x;
1360 rect.y = y;
1361 rect.width = cx;
1362 rect.height = cy;
1363 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1364 }
1365
1366 void
1367 ui_reset_clip(void)
1368 {
1369 XRectangle rect;
1370
1371 rect.x = 0;
1372 rect.y = 0;
1373 rect.width = width;
1374 rect.height = height;
1375 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1376 }
1377
1378 void
1379 ui_bell(void)
1380 {
1381 XBell(display, 0);
1382 }
1383
1384 void
1385 ui_destblt(uint8 opcode,
1386 /* dest */ int x, int y, int cx, int cy)
1387 {
1388 SET_FUNCTION(opcode);
1389 FILL_RECTANGLE(x, y, cx, cy);
1390 RESET_FUNCTION(opcode);
1391 }
1392
1393 static uint8 hatch_patterns[] = {
1394 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1395 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1396 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1397 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1398 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1399 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
1400 };
1401
1402 void
1403 ui_patblt(uint8 opcode,
1404 /* dest */ int x, int y, int cx, int cy,
1405 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1406 {
1407 Pixmap fill;
1408 uint8 i, ipattern[8];
1409
1410 SET_FUNCTION(opcode);
1411
1412 switch (brush->style)
1413 {
1414 case 0: /* Solid */
1415 SET_FOREGROUND(fgcolour);
1416 FILL_RECTANGLE(x, y, cx, cy);
1417 break;
1418
1419 case 2: /* Hatch */
1420 fill = (Pixmap) ui_create_glyph(8, 8,
1421 hatch_patterns + brush->pattern[0] * 8);
1422 SET_FOREGROUND(bgcolour);
1423 SET_BACKGROUND(fgcolour);
1424 XSetFillStyle(display, gc, FillOpaqueStippled);
1425 XSetStipple(display, gc, fill);
1426 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1427 FILL_RECTANGLE(x, y, cx, cy);
1428 XSetFillStyle(display, gc, FillSolid);
1429 XSetTSOrigin(display, gc, 0, 0);
1430 ui_destroy_glyph((HGLYPH) fill);
1431 break;
1432
1433 case 3: /* Pattern */
1434 for (i = 0; i != 8; i++)
1435 ipattern[7 - i] = brush->pattern[i];
1436 fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1437
1438 SET_FOREGROUND(bgcolour);
1439 SET_BACKGROUND(fgcolour);
1440 XSetFillStyle(display, gc, FillOpaqueStippled);
1441 XSetStipple(display, gc, fill);
1442 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1443
1444 FILL_RECTANGLE(x, y, cx, cy);
1445
1446 XSetFillStyle(display, gc, FillSolid);
1447 XSetTSOrigin(display, gc, 0, 0);
1448 ui_destroy_glyph((HGLYPH) fill);
1449 break;
1450
1451 default:
1452 unimpl("brush %d\n", brush->style);
1453 }
1454
1455 RESET_FUNCTION(opcode);
1456 }
1457
1458 void
1459 ui_screenblt(uint8 opcode,
1460 /* dest */ int x, int y, int cx, int cy,
1461 /* src */ int srcx, int srcy)
1462 {
1463 SET_FUNCTION(opcode);
1464 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1465 if (ownbackstore)
1466 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1467 RESET_FUNCTION(opcode);
1468 }
1469
1470 void
1471 ui_memblt(uint8 opcode,
1472 /* dest */ int x, int y, int cx, int cy,
1473 /* src */ HBITMAP src, int srcx, int srcy)
1474 {
1475 SET_FUNCTION(opcode);
1476 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1477 if (ownbackstore)
1478 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1479 RESET_FUNCTION(opcode);
1480 }
1481
1482 void
1483 ui_triblt(uint8 opcode,
1484 /* dest */ int x, int y, int cx, int cy,
1485 /* src */ HBITMAP src, int srcx, int srcy,
1486 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1487 {
1488 /* This is potentially difficult to do in general. Until someone
1489 comes up with a more efficient way of doing it I am using cases. */
1490
1491 switch (opcode)
1492 {
1493 case 0x69: /* PDSxxn */
1494 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1495 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1496 break;
1497
1498 case 0xb8: /* PSDPxax */
1499 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1500 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1501 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1502 break;
1503
1504 case 0xc0: /* PSa */
1505 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1506 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1507 break;
1508
1509 default:
1510 unimpl("triblt 0x%x\n", opcode);
1511 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1512 }
1513 }
1514
1515 void
1516 ui_line(uint8 opcode,
1517 /* dest */ int startx, int starty, int endx, int endy,
1518 /* pen */ PEN * pen)
1519 {
1520 SET_FUNCTION(opcode);
1521 SET_FOREGROUND(pen->colour);
1522 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1523 if (ownbackstore)
1524 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1525 RESET_FUNCTION(opcode);
1526 }
1527
1528 void
1529 ui_rect(
1530 /* dest */ int x, int y, int cx, int cy,
1531 /* brush */ int colour)
1532 {
1533 SET_FOREGROUND(colour);
1534 FILL_RECTANGLE(x, y, cx, cy);
1535 }
1536
1537 /* warning, this function only draws on wnd or backstore, not both */
1538 void
1539 ui_draw_glyph(int mixmode,
1540 /* dest */ int x, int y, int cx, int cy,
1541 /* src */ HGLYPH glyph, int srcx, int srcy,
1542 int bgcolour, int fgcolour)
1543 {
1544 SET_FOREGROUND(fgcolour);
1545 SET_BACKGROUND(bgcolour);
1546
1547 XSetFillStyle(display, gc,
1548 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1549 XSetStipple(display, gc, (Pixmap) glyph);
1550 XSetTSOrigin(display, gc, x, y);
1551
1552 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1553
1554 XSetFillStyle(display, gc, FillSolid);
1555 }
1556
1557 #define DO_GLYPH(ttext,idx) \
1558 {\
1559 glyph = cache_get_font (font, ttext[idx]);\
1560 if (!(flags & TEXT2_IMPLICIT_X))\
1561 {\
1562 xyoffset = ttext[++idx];\
1563 if ((xyoffset & 0x80))\
1564 {\
1565 if (flags & TEXT2_VERTICAL) \
1566 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1567 else\
1568 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1569 idx += 2;\
1570 }\
1571 else\
1572 {\
1573 if (flags & TEXT2_VERTICAL) \
1574 y += xyoffset;\
1575 else\
1576 x += xyoffset;\
1577 }\
1578 }\
1579 if (glyph != NULL)\
1580 {\
1581 ui_draw_glyph (mixmode, x + glyph->offset,\
1582 y + glyph->baseline,\
1583 glyph->width, glyph->height,\
1584 glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1585 if (flags & TEXT2_IMPLICIT_X)\
1586 x += glyph->width;\
1587 }\
1588 }
1589
1590 void
1591 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1592 int clipx, int clipy, int clipcx, int clipcy,
1593 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1594 int fgcolour, uint8 * text, uint8 length)
1595 {
1596 FONTGLYPH *glyph;
1597 int i, j, xyoffset;
1598 DATABLOB *entry;
1599
1600 SET_FOREGROUND(bgcolour);
1601
1602 if (boxcx > 1)
1603 {
1604 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1605 }
1606 else if (mixmode == MIX_OPAQUE)
1607 {
1608 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1609 }
1610
1611 /* Paint text, character by character */
1612 for (i = 0; i < length;)
1613 {
1614 switch (text[i])
1615 {
1616 case 0xff:
1617 if (i + 2 < length)
1618 cache_put_text(text[i + 1], text, text[i + 2]);
1619 else
1620 {
1621 error("this shouldn't be happening\n");
1622 exit(1);
1623 }
1624 /* this will move pointer from start to first character after FF command */
1625 length -= i + 3;
1626 text = &(text[i + 3]);
1627 i = 0;
1628 break;
1629
1630 case 0xfe:
1631 entry = cache_get_text(text[i + 1]);
1632 if (entry != NULL)
1633 {
1634 if ((((uint8 *) (entry->data))[1] ==
1635 0) && (!(flags & TEXT2_IMPLICIT_X)))
1636 {
1637 if (flags & TEXT2_VERTICAL)
1638 y += text[i + 2];
1639 else
1640 x += text[i + 2];
1641 }
1642 for (j = 0; j < entry->size; j++)
1643 DO_GLYPH(((uint8 *) (entry->data)), j);
1644 }
1645 if (i + 2 < length)
1646 i += 3;
1647 else
1648 i += 2;
1649 length -= i;
1650 /* this will move pointer from start to first character after FE command */
1651 text = &(text[i]);
1652 i = 0;
1653 break;
1654
1655 default:
1656 DO_GLYPH(text, i);
1657 i++;
1658 break;
1659 }
1660 }
1661 if (ownbackstore)
1662 {
1663 if (boxcx > 1)
1664 XCopyArea(display, backstore, wnd, gc, boxx,
1665 boxy, boxcx, boxcy, boxx, boxy);
1666 else
1667 XCopyArea(display, backstore, wnd, gc, clipx,
1668 clipy, clipcx, clipcy, clipx, clipy);
1669 }
1670 }
1671
1672 void
1673 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1674 {
1675 Pixmap pix;
1676 XImage *image;
1677
1678 if (ownbackstore)
1679 {
1680 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1681 }
1682 else
1683 {
1684 pix = XCreatePixmap(display, wnd, cx, cy, depth);
1685 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1686 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1687 XFreePixmap(display, pix);
1688 }
1689
1690 offset *= bpp / 8;
1691 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1692
1693 XDestroyImage(image);
1694 }
1695
1696 void
1697 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1698 {
1699 XImage *image;
1700 uint8 *data;
1701
1702 offset *= bpp / 8;
1703 data = cache_get_desktop(offset, cx, cy, bpp / 8);
1704 if (data == NULL)
1705 return;
1706
1707 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1708 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1709
1710 if (ownbackstore)
1711 {
1712 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1713 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1714 }
1715 else
1716 {
1717 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1718 }
1719
1720 XFree(image);
1721 }
1722

  ViewVC Help
Powered by ViewVC 1.1.26