/[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 435 - (show annotations)
Wed Jul 9 09:18:20 2003 UTC (20 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 38856 byte(s)
Indent fixes

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,
806 &status);
807 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
808 {
809 error("XmbLookupString failed with status 0x%x\n",
810 status);
811 break;
812 }
813 }
814 else
815 {
816 /* Plain old XLookupString */
817 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
818 XLookupString((XKeyEvent *) & xevent,
819 str, sizeof(str), &keysym, NULL);
820 }
821
822 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
823 get_ksname(keysym)));
824
825 ev_time = time(NULL);
826 if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
827 break;
828
829 tr = xkeymap_translate_key(keysym,
830 xevent.xkey.keycode, xevent.xkey.state);
831
832 if (tr.scancode == 0)
833 break;
834
835 ensure_remote_modifiers(ev_time, tr);
836
837 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
838 break;
839
840 case KeyRelease:
841 last_gesturetime = xevent.xkey.time;
842 XLookupString((XKeyEvent *) & xevent, str,
843 sizeof(str), &keysym, NULL);
844
845 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
846 get_ksname(keysym)));
847
848 ev_time = time(NULL);
849 if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
850 break;
851
852 tr = xkeymap_translate_key(keysym,
853 xevent.xkey.keycode, xevent.xkey.state);
854
855 if (tr.scancode == 0)
856 break;
857
858 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
859 break;
860
861 case ButtonPress:
862 flags = MOUSE_FLAG_DOWN;
863 /* fall through */
864
865 case ButtonRelease:
866 last_gesturetime = xevent.xbutton.time;
867 button = xkeymap_translate_button(xevent.xbutton.button);
868 if (button == 0)
869 break;
870
871 /* If win_button_size is nonzero, enable single app mode */
872 if (xevent.xbutton.y < win_button_size)
873 {
874 /* Stop moving window when button is released, regardless of cursor position */
875 if (moving_wnd && (xevent.type == ButtonRelease))
876 moving_wnd = False;
877
878 /* Check from right to left: */
879
880 if (xevent.xbutton.x >= width - win_button_size)
881 {
882 /* The close button, continue */
883 ;
884 }
885 else if (xevent.xbutton.x >= width - win_button_size * 2)
886 {
887 /* The maximize/restore button. Do not send to
888 server. It might be a good idea to change the
889 cursor or give some other visible indication
890 that rdesktop inhibited this click */
891 break;
892 }
893 else if (xevent.xbutton.x >= width - win_button_size * 3)
894 {
895 /* The minimize button. Iconify window. */
896 XIconifyWindow(display, wnd,
897 DefaultScreen(display));
898 break;
899 }
900 else if (xevent.xbutton.x <= win_button_size)
901 {
902 /* The system menu. Ignore. */
903 break;
904 }
905 else
906 {
907 /* The title bar. */
908 if ((xevent.type == ButtonPress) && !fullscreen
909 && hide_decorations)
910 {
911 moving_wnd = True;
912 move_x_offset = xevent.xbutton.x;
913 move_y_offset = xevent.xbutton.y;
914 }
915 break;
916
917 }
918 }
919
920 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
921 flags | button, xevent.xbutton.x, xevent.xbutton.y);
922 break;
923
924 case MotionNotify:
925 if (moving_wnd)
926 {
927 XMoveWindow(display, wnd,
928 xevent.xmotion.x_root - move_x_offset,
929 xevent.xmotion.y_root - move_y_offset);
930 break;
931 }
932
933 if (fullscreen && !focused)
934 XSetInputFocus(display, wnd, RevertToPointerRoot,
935 CurrentTime);
936 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
937 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
938 break;
939
940 case FocusIn:
941 if (xevent.xfocus.mode == NotifyGrab)
942 break;
943 focused = True;
944 XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
945 &dummy, &dummy, &state);
946 reset_modifier_keys(state);
947 if (grab_keyboard && mouse_in_wnd)
948 XGrabKeyboard(display, wnd, True,
949 GrabModeAsync, GrabModeAsync, CurrentTime);
950 break;
951
952 case FocusOut:
953 if (xevent.xfocus.mode == NotifyUngrab)
954 break;
955 focused = False;
956 if (xevent.xfocus.mode == NotifyWhileGrabbed)
957 XUngrabKeyboard(display, CurrentTime);
958 break;
959
960 case EnterNotify:
961 /* we only register for this event when in fullscreen mode */
962 /* or grab_keyboard */
963 mouse_in_wnd = True;
964 if (fullscreen)
965 {
966 XSetInputFocus(display, wnd, RevertToPointerRoot,
967 CurrentTime);
968 break;
969 }
970 if (focused)
971 XGrabKeyboard(display, wnd, True,
972 GrabModeAsync, GrabModeAsync, CurrentTime);
973 break;
974
975 case LeaveNotify:
976 /* we only register for this event when grab_keyboard */
977 mouse_in_wnd = False;
978 XUngrabKeyboard(display, CurrentTime);
979 break;
980
981 case Expose:
982 XCopyArea(display, backstore, wnd, gc,
983 xevent.xexpose.x, xevent.xexpose.y,
984 xevent.xexpose.width,
985 xevent.xexpose.height,
986 xevent.xexpose.x, xevent.xexpose.y);
987 break;
988
989 case MappingNotify:
990 /* Refresh keyboard mapping if it has changed. This is important for
991 Xvnc, since it allocates keycodes dynamically */
992 if (xevent.xmapping.request == MappingKeyboard
993 || xevent.xmapping.request == MappingModifier)
994 XRefreshKeyboardMapping(&xevent.xmapping);
995
996 if (xevent.xmapping.request == MappingModifier)
997 {
998 XFreeModifiermap(mod_map);
999 mod_map = XGetModifierMapping(display);
1000 }
1001 break;
1002
1003 /* clipboard stuff */
1004 case SelectionNotify:
1005 xclip_handle_SelectionNotify(&xevent.xselection);
1006 break;
1007 case SelectionRequest:
1008 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1009 break;
1010 case SelectionClear:
1011 xclip_handle_SelectionClear();
1012 break;
1013 case PropertyNotify:
1014 xclip_handle_PropertyNotify(&xevent.xproperty);
1015 break;
1016 }
1017 }
1018 /* Keep going */
1019 return 1;
1020 }
1021
1022 /* Returns 0 after user quit, 1 otherwise */
1023 int
1024 ui_select(int rdp_socket)
1025 {
1026 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
1027 fd_set rfds;
1028
1029 FD_ZERO(&rfds);
1030
1031 while (True)
1032 {
1033 /* Process any events already waiting */
1034 if (!xwin_process_events())
1035 /* User quit */
1036 return 0;
1037
1038 FD_ZERO(&rfds);
1039 FD_SET(rdp_socket, &rfds);
1040 FD_SET(x_socket, &rfds);
1041
1042 switch (select(n, &rfds, NULL, NULL, NULL))
1043 {
1044 case -1:
1045 error("select: %s\n", strerror(errno));
1046
1047 case 0:
1048 continue;
1049 }
1050
1051 if (FD_ISSET(rdp_socket, &rfds))
1052 return 1;
1053 }
1054 }
1055
1056 void
1057 ui_move_pointer(int x, int y)
1058 {
1059 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
1060 }
1061
1062 HBITMAP
1063 ui_create_bitmap(int width, int height, uint8 * data)
1064 {
1065 XImage *image;
1066 Pixmap bitmap;
1067 uint8 *tdata;
1068
1069 tdata = (owncolmap ? data : translate_image(width, height, data));
1070 bitmap = XCreatePixmap(display, wnd, width, height, depth);
1071 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1072 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1073
1074 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1075
1076 XFree(image);
1077 if (!owncolmap)
1078 xfree(tdata);
1079 return (HBITMAP) bitmap;
1080 }
1081
1082 void
1083 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1084 {
1085 XImage *image;
1086 uint8 *tdata;
1087 tdata = (owncolmap ? data : translate_image(width, height, data));
1088 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1089 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1090
1091 if (ownbackstore)
1092 {
1093 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1094 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1095 }
1096 else
1097 {
1098 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1099 }
1100
1101 XFree(image);
1102 if (!owncolmap)
1103 xfree(tdata);
1104 }
1105
1106 void
1107 ui_destroy_bitmap(HBITMAP bmp)
1108 {
1109 XFreePixmap(display, (Pixmap) bmp);
1110 }
1111
1112 HGLYPH
1113 ui_create_glyph(int width, int height, uint8 * data)
1114 {
1115 XImage *image;
1116 Pixmap bitmap;
1117 int scanline;
1118 GC gc;
1119
1120 scanline = (width + 7) / 8;
1121
1122 bitmap = XCreatePixmap(display, wnd, width, height, 1);
1123 gc = XCreateGC(display, bitmap, 0, NULL);
1124
1125 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1126 width, height, 8, scanline);
1127 image->byte_order = MSBFirst;
1128 image->bitmap_bit_order = MSBFirst;
1129 XInitImage(image);
1130
1131 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1132
1133 XFree(image);
1134 XFreeGC(display, gc);
1135 return (HGLYPH) bitmap;
1136 }
1137
1138 void
1139 ui_destroy_glyph(HGLYPH glyph)
1140 {
1141 XFreePixmap(display, (Pixmap) glyph);
1142 }
1143
1144 HCURSOR
1145 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1146 uint8 * andmask, uint8 * xormask)
1147 {
1148 HGLYPH maskglyph, cursorglyph;
1149 XColor bg, fg;
1150 Cursor xcursor;
1151 uint8 *cursor, *pcursor;
1152 uint8 *mask, *pmask;
1153 uint8 nextbit;
1154 int scanline, offset;
1155 int i, j;
1156
1157 scanline = (width + 7) / 8;
1158 offset = scanline * height;
1159
1160 cursor = (uint8 *) xmalloc(offset);
1161 memset(cursor, 0, offset);
1162
1163 mask = (uint8 *) xmalloc(offset);
1164 memset(mask, 0, offset);
1165
1166 /* approximate AND and XOR masks with a monochrome X pointer */
1167 for (i = 0; i < height; i++)
1168 {
1169 offset -= scanline;
1170 pcursor = &cursor[offset];
1171 pmask = &mask[offset];
1172
1173 for (j = 0; j < scanline; j++)
1174 {
1175 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1176 {
1177 if (xormask[0] || xormask[1] || xormask[2])
1178 {
1179 *pcursor |= (~(*andmask) & nextbit);
1180 *pmask |= nextbit;
1181 }
1182 else
1183 {
1184 *pcursor |= ((*andmask) & nextbit);
1185 *pmask |= (~(*andmask) & nextbit);
1186 }
1187
1188 xormask += 3;
1189 }
1190
1191 andmask++;
1192 pcursor++;
1193 pmask++;
1194 }
1195 }
1196
1197 fg.red = fg.blue = fg.green = 0xffff;
1198 bg.red = bg.blue = bg.green = 0x0000;
1199 fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1200
1201 cursorglyph = ui_create_glyph(width, height, cursor);
1202 maskglyph = ui_create_glyph(width, height, mask);
1203
1204 xcursor =
1205 XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1206 (Pixmap) maskglyph, &fg, &bg, x, y);
1207
1208 ui_destroy_glyph(maskglyph);
1209 ui_destroy_glyph(cursorglyph);
1210 xfree(mask);
1211 xfree(cursor);
1212 return (HCURSOR) xcursor;
1213 }
1214
1215 void
1216 ui_set_cursor(HCURSOR cursor)
1217 {
1218 current_cursor = (Cursor) cursor;
1219 XDefineCursor(display, wnd, current_cursor);
1220 }
1221
1222 void
1223 ui_destroy_cursor(HCURSOR cursor)
1224 {
1225 XFreeCursor(display, (Cursor) cursor);
1226 }
1227
1228 #define MAKE_XCOLOR(xc,c) \
1229 (xc)->red = ((c)->red << 8) | (c)->red; \
1230 (xc)->green = ((c)->green << 8) | (c)->green; \
1231 (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1232 (xc)->flags = DoRed | DoGreen | DoBlue;
1233
1234
1235 HCOLOURMAP
1236 ui_create_colourmap(COLOURMAP * colours)
1237 {
1238 COLOURENTRY *entry;
1239 int i, ncolours = colours->ncolours;
1240 if (!owncolmap)
1241 {
1242 uint32 *map = (uint32 *) xmalloc(sizeof(*colmap) * ncolours);
1243 XColor xentry;
1244 XColor xc_cache[256];
1245 uint32 colour;
1246 int colLookup = 256;
1247 for (i = 0; i < ncolours; i++)
1248 {
1249 entry = &colours->colours[i];
1250 MAKE_XCOLOR(&xentry, entry);
1251
1252 if (XAllocColor(display, xcolmap, &xentry) == 0)
1253 {
1254 /* Allocation failed, find closest match. */
1255 int j = 256;
1256 int nMinDist = 3 * 256 * 256;
1257 long nDist = nMinDist;
1258
1259 /* only get the colors once */
1260 while (colLookup--)
1261 {
1262 xc_cache[colLookup].pixel = colLookup;
1263 xc_cache[colLookup].red = xc_cache[colLookup].green =
1264 xc_cache[colLookup].blue = 0;
1265 xc_cache[colLookup].flags = 0;
1266 XQueryColor(display,
1267 DefaultColormap(display,
1268 DefaultScreen(display)),
1269 &xc_cache[colLookup]);
1270 }
1271 colLookup = 0;
1272
1273 /* approximate the pixel */
1274 while (j--)
1275 {
1276 if (xc_cache[j].flags)
1277 {
1278 nDist = ((long) (xc_cache[j].red >> 8) -
1279 (long) (xentry.red >> 8)) *
1280 ((long) (xc_cache[j].red >> 8) -
1281 (long) (xentry.red >> 8)) +
1282 ((long) (xc_cache[j].green >> 8) -
1283 (long) (xentry.green >> 8)) *
1284 ((long) (xc_cache[j].green >> 8) -
1285 (long) (xentry.green >> 8)) +
1286 ((long) (xc_cache[j].blue >> 8) -
1287 (long) (xentry.blue >> 8)) *
1288 ((long) (xc_cache[j].blue >> 8) -
1289 (long) (xentry.blue >> 8));
1290 }
1291 if (nDist < nMinDist)
1292 {
1293 nMinDist = nDist;
1294 xentry.pixel = j;
1295 }
1296 }
1297 }
1298 colour = xentry.pixel;
1299
1300 /* update our cache */
1301 if (xentry.pixel < 256)
1302 {
1303 xc_cache[xentry.pixel].red = xentry.red;
1304 xc_cache[xentry.pixel].green = xentry.green;
1305 xc_cache[xentry.pixel].blue = xentry.blue;
1306
1307 }
1308
1309
1310 /* byte swap here to make translate_image faster */
1311 map[i] = translate_colour(colour);
1312 }
1313 return map;
1314 }
1315 else
1316 {
1317 XColor *xcolours, *xentry;
1318 Colormap map;
1319
1320 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1321 for (i = 0; i < ncolours; i++)
1322 {
1323 entry = &colours->colours[i];
1324 xentry = &xcolours[i];
1325 xentry->pixel = i;
1326 MAKE_XCOLOR(xentry, entry);
1327 }
1328
1329 map = XCreateColormap(display, wnd, visual, AllocAll);
1330 XStoreColors(display, map, xcolours, ncolours);
1331
1332 xfree(xcolours);
1333 return (HCOLOURMAP) map;
1334 }
1335 }
1336
1337 void
1338 ui_destroy_colourmap(HCOLOURMAP map)
1339 {
1340 if (!owncolmap)
1341 xfree(map);
1342 else
1343 XFreeColormap(display, (Colormap) map);
1344 }
1345
1346 void
1347 ui_set_colourmap(HCOLOURMAP map)
1348 {
1349 if (!owncolmap)
1350 colmap = (uint32 *) map;
1351 else
1352 XSetWindowColormap(display, wnd, (Colormap) map);
1353 }
1354
1355 void
1356 ui_set_clip(int x, int y, int cx, int cy)
1357 {
1358 XRectangle rect;
1359
1360 rect.x = x;
1361 rect.y = y;
1362 rect.width = cx;
1363 rect.height = cy;
1364 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1365 }
1366
1367 void
1368 ui_reset_clip(void)
1369 {
1370 XRectangle rect;
1371
1372 rect.x = 0;
1373 rect.y = 0;
1374 rect.width = width;
1375 rect.height = height;
1376 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1377 }
1378
1379 void
1380 ui_bell(void)
1381 {
1382 XBell(display, 0);
1383 }
1384
1385 void
1386 ui_destblt(uint8 opcode,
1387 /* dest */ int x, int y, int cx, int cy)
1388 {
1389 SET_FUNCTION(opcode);
1390 FILL_RECTANGLE(x, y, cx, cy);
1391 RESET_FUNCTION(opcode);
1392 }
1393
1394 static uint8 hatch_patterns[] = {
1395 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1396 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1397 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1398 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1399 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1400 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
1401 };
1402
1403 void
1404 ui_patblt(uint8 opcode,
1405 /* dest */ int x, int y, int cx, int cy,
1406 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1407 {
1408 Pixmap fill;
1409 uint8 i, ipattern[8];
1410
1411 SET_FUNCTION(opcode);
1412
1413 switch (brush->style)
1414 {
1415 case 0: /* Solid */
1416 SET_FOREGROUND(fgcolour);
1417 FILL_RECTANGLE(x, y, cx, cy);
1418 break;
1419
1420 case 2: /* Hatch */
1421 fill = (Pixmap) ui_create_glyph(8, 8,
1422 hatch_patterns + brush->pattern[0] * 8);
1423 SET_FOREGROUND(bgcolour);
1424 SET_BACKGROUND(fgcolour);
1425 XSetFillStyle(display, gc, FillOpaqueStippled);
1426 XSetStipple(display, gc, fill);
1427 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1428 FILL_RECTANGLE(x, y, cx, cy);
1429 XSetFillStyle(display, gc, FillSolid);
1430 XSetTSOrigin(display, gc, 0, 0);
1431 ui_destroy_glyph((HGLYPH) fill);
1432 break;
1433
1434 case 3: /* Pattern */
1435 for (i = 0; i != 8; i++)
1436 ipattern[7 - i] = brush->pattern[i];
1437 fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1438
1439 SET_FOREGROUND(bgcolour);
1440 SET_BACKGROUND(fgcolour);
1441 XSetFillStyle(display, gc, FillOpaqueStippled);
1442 XSetStipple(display, gc, fill);
1443 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1444
1445 FILL_RECTANGLE(x, y, cx, cy);
1446
1447 XSetFillStyle(display, gc, FillSolid);
1448 XSetTSOrigin(display, gc, 0, 0);
1449 ui_destroy_glyph((HGLYPH) fill);
1450 break;
1451
1452 default:
1453 unimpl("brush %d\n", brush->style);
1454 }
1455
1456 RESET_FUNCTION(opcode);
1457 }
1458
1459 void
1460 ui_screenblt(uint8 opcode,
1461 /* dest */ int x, int y, int cx, int cy,
1462 /* src */ int srcx, int srcy)
1463 {
1464 SET_FUNCTION(opcode);
1465 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1466 if (ownbackstore)
1467 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1468 RESET_FUNCTION(opcode);
1469 }
1470
1471 void
1472 ui_memblt(uint8 opcode,
1473 /* dest */ int x, int y, int cx, int cy,
1474 /* src */ HBITMAP src, int srcx, int srcy)
1475 {
1476 SET_FUNCTION(opcode);
1477 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1478 if (ownbackstore)
1479 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1480 RESET_FUNCTION(opcode);
1481 }
1482
1483 void
1484 ui_triblt(uint8 opcode,
1485 /* dest */ int x, int y, int cx, int cy,
1486 /* src */ HBITMAP src, int srcx, int srcy,
1487 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1488 {
1489 /* This is potentially difficult to do in general. Until someone
1490 comes up with a more efficient way of doing it I am using cases. */
1491
1492 switch (opcode)
1493 {
1494 case 0x69: /* PDSxxn */
1495 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1496 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1497 break;
1498
1499 case 0xb8: /* PSDPxax */
1500 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1501 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1502 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1503 break;
1504
1505 case 0xc0: /* PSa */
1506 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1507 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1508 break;
1509
1510 default:
1511 unimpl("triblt 0x%x\n", opcode);
1512 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1513 }
1514 }
1515
1516 void
1517 ui_line(uint8 opcode,
1518 /* dest */ int startx, int starty, int endx, int endy,
1519 /* pen */ PEN * pen)
1520 {
1521 SET_FUNCTION(opcode);
1522 SET_FOREGROUND(pen->colour);
1523 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1524 if (ownbackstore)
1525 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1526 RESET_FUNCTION(opcode);
1527 }
1528
1529 void
1530 ui_rect(
1531 /* dest */ int x, int y, int cx, int cy,
1532 /* brush */ int colour)
1533 {
1534 SET_FOREGROUND(colour);
1535 FILL_RECTANGLE(x, y, cx, cy);
1536 }
1537
1538 /* warning, this function only draws on wnd or backstore, not both */
1539 void
1540 ui_draw_glyph(int mixmode,
1541 /* dest */ int x, int y, int cx, int cy,
1542 /* src */ HGLYPH glyph, int srcx, int srcy,
1543 int bgcolour, int fgcolour)
1544 {
1545 SET_FOREGROUND(fgcolour);
1546 SET_BACKGROUND(bgcolour);
1547
1548 XSetFillStyle(display, gc,
1549 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1550 XSetStipple(display, gc, (Pixmap) glyph);
1551 XSetTSOrigin(display, gc, x, y);
1552
1553 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1554
1555 XSetFillStyle(display, gc, FillSolid);
1556 }
1557
1558 #define DO_GLYPH(ttext,idx) \
1559 {\
1560 glyph = cache_get_font (font, ttext[idx]);\
1561 if (!(flags & TEXT2_IMPLICIT_X))\
1562 {\
1563 xyoffset = ttext[++idx];\
1564 if ((xyoffset & 0x80))\
1565 {\
1566 if (flags & TEXT2_VERTICAL) \
1567 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1568 else\
1569 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1570 idx += 2;\
1571 }\
1572 else\
1573 {\
1574 if (flags & TEXT2_VERTICAL) \
1575 y += xyoffset;\
1576 else\
1577 x += xyoffset;\
1578 }\
1579 }\
1580 if (glyph != NULL)\
1581 {\
1582 ui_draw_glyph (mixmode, x + glyph->offset,\
1583 y + glyph->baseline,\
1584 glyph->width, glyph->height,\
1585 glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1586 if (flags & TEXT2_IMPLICIT_X)\
1587 x += glyph->width;\
1588 }\
1589 }
1590
1591 void
1592 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1593 int clipx, int clipy, int clipcx, int clipcy,
1594 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1595 int fgcolour, uint8 * text, uint8 length)
1596 {
1597 FONTGLYPH *glyph;
1598 int i, j, xyoffset;
1599 DATABLOB *entry;
1600
1601 SET_FOREGROUND(bgcolour);
1602
1603 if (boxcx > 1)
1604 {
1605 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1606 }
1607 else if (mixmode == MIX_OPAQUE)
1608 {
1609 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1610 }
1611
1612 /* Paint text, character by character */
1613 for (i = 0; i < length;)
1614 {
1615 switch (text[i])
1616 {
1617 case 0xff:
1618 if (i + 2 < length)
1619 cache_put_text(text[i + 1], text, text[i + 2]);
1620 else
1621 {
1622 error("this shouldn't be happening\n");
1623 exit(1);
1624 }
1625 /* this will move pointer from start to first character after FF command */
1626 length -= i + 3;
1627 text = &(text[i + 3]);
1628 i = 0;
1629 break;
1630
1631 case 0xfe:
1632 entry = cache_get_text(text[i + 1]);
1633 if (entry != NULL)
1634 {
1635 if ((((uint8 *) (entry->data))[1] ==
1636 0) && (!(flags & TEXT2_IMPLICIT_X)))
1637 {
1638 if (flags & TEXT2_VERTICAL)
1639 y += text[i + 2];
1640 else
1641 x += text[i + 2];
1642 }
1643 for (j = 0; j < entry->size; j++)
1644 DO_GLYPH(((uint8 *) (entry->data)), j);
1645 }
1646 if (i + 2 < length)
1647 i += 3;
1648 else
1649 i += 2;
1650 length -= i;
1651 /* this will move pointer from start to first character after FE command */
1652 text = &(text[i]);
1653 i = 0;
1654 break;
1655
1656 default:
1657 DO_GLYPH(text, i);
1658 i++;
1659 break;
1660 }
1661 }
1662 if (ownbackstore)
1663 {
1664 if (boxcx > 1)
1665 XCopyArea(display, backstore, wnd, gc, boxx,
1666 boxy, boxcx, boxcy, boxx, boxy);
1667 else
1668 XCopyArea(display, backstore, wnd, gc, clipx,
1669 clipy, clipcx, clipcy, clipx, clipy);
1670 }
1671 }
1672
1673 void
1674 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1675 {
1676 Pixmap pix;
1677 XImage *image;
1678
1679 if (ownbackstore)
1680 {
1681 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1682 }
1683 else
1684 {
1685 pix = XCreatePixmap(display, wnd, cx, cy, depth);
1686 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1687 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1688 XFreePixmap(display, pix);
1689 }
1690
1691 offset *= bpp / 8;
1692 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1693
1694 XDestroyImage(image);
1695 }
1696
1697 void
1698 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1699 {
1700 XImage *image;
1701 uint8 *data;
1702
1703 offset *= bpp / 8;
1704 data = cache_get_desktop(offset, cx, cy, bpp / 8);
1705 if (data == NULL)
1706 return;
1707
1708 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1709 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1710
1711 if (ownbackstore)
1712 {
1713 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1714 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1715 }
1716 else
1717 {
1718 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1719 }
1720
1721 XFree(image);
1722 }

  ViewVC Help
Powered by ViewVC 1.1.26