/[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 448 - (show annotations)
Wed Aug 27 08:21:53 2003 UTC (20 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 39038 byte(s)
Fixed memory leak with colormap allocation.

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 g_width;
29 extern int g_height;
30 extern BOOL g_sendmotion;
31 extern BOOL g_fullscreen;
32 extern BOOL grab_keyboard;
33 extern BOOL hide_decorations;
34 extern char title[];
35 extern int g_server_bpp;
36 extern int win_button_size;
37 BOOL g_enable_compose = False;
38 BOOL g_focused;
39 BOOL g_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 = NULL;
107
108 #define TRANSLATE(col) ( g_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 (g_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 (g_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 ((g_width == 0) || (g_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 g_width = cx;
581 g_height = cy;
582 }
583 else
584 {
585 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
586 g_width = 800;
587 g_height = 600;
588 }
589 }
590
591 if (g_fullscreen)
592 {
593 g_width = WidthOfScreen(screen);
594 g_height = HeightOfScreen(screen);
595 }
596
597 /* make sure width is a multiple of 4 */
598 g_width = (g_width + 3) & ~3;
599
600 if (ownbackstore)
601 {
602 backstore =
603 XCreatePixmap(display, RootWindowOfScreen(screen), g_width, g_height,
604 depth);
605
606 /* clear to prevent rubbish being exposed at startup */
607 XSetForeground(display, gc, BlackPixelOfScreen(screen));
608 XFillRectangle(display, backstore, gc, 0, 0, g_width, g_height);
609 }
610
611 mod_map = XGetModifierMapping(display);
612
613 if (g_enable_compose)
614 IM = XOpenIM(display, NULL, NULL, NULL);
615
616 xkeymap_init();
617 xclip_init();
618
619 /* todo take this out when high colour is done */
620 printf("server bpp %d client bpp %d depth %d\n", g_server_bpp, bpp, depth);
621
622 return True;
623 }
624
625 void
626 ui_deinit(void)
627 {
628 if (IM != NULL)
629 XCloseIM(IM);
630
631 XFreeModifiermap(mod_map);
632
633 if (ownbackstore)
634 XFreePixmap(display, backstore);
635
636 XFreeGC(display, gc);
637 XCloseDisplay(display);
638 display = NULL;
639 }
640
641 BOOL
642 ui_create_window(void)
643 {
644 XSetWindowAttributes attribs;
645 XClassHint *classhints;
646 XSizeHints *sizehints;
647 int wndwidth, wndheight;
648 long input_mask, ic_input_mask;
649 XEvent xevent;
650
651 wndwidth = g_fullscreen ? WidthOfScreen(screen) : g_width;
652 wndheight = g_fullscreen ? HeightOfScreen(screen) : g_height;
653
654 attribs.background_pixel = BlackPixelOfScreen(screen);
655 attribs.backing_store = ownbackstore ? NotUseful : Always;
656 attribs.override_redirect = g_fullscreen;
657
658 wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
659 0, CopyFromParent, InputOutput, CopyFromParent,
660 CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
661
662 XStoreName(display, wnd, title);
663
664 if (hide_decorations)
665 mwm_hide_decorations();
666
667 classhints = XAllocClassHint();
668 if (classhints != NULL)
669 {
670 classhints->res_name = classhints->res_class = "rdesktop";
671 XSetClassHint(display, wnd, classhints);
672 XFree(classhints);
673 }
674
675 sizehints = XAllocSizeHints();
676 if (sizehints)
677 {
678 sizehints->flags = PMinSize | PMaxSize;
679 sizehints->min_width = sizehints->max_width = g_width;
680 sizehints->min_height = sizehints->max_height = g_height;
681 XSetWMNormalHints(display, wnd, sizehints);
682 XFree(sizehints);
683 }
684
685 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
686 VisibilityChangeMask | FocusChangeMask;
687
688 if (g_sendmotion)
689 input_mask |= PointerMotionMask;
690 if (ownbackstore)
691 input_mask |= ExposureMask;
692 if (g_fullscreen || grab_keyboard)
693 input_mask |= EnterWindowMask;
694 if (grab_keyboard)
695 input_mask |= LeaveWindowMask;
696
697 if (IM != NULL)
698 {
699 IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
700 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
701
702 if ((IC != NULL)
703 && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
704 input_mask |= ic_input_mask;
705 }
706
707 XSelectInput(display, wnd, input_mask);
708 XMapWindow(display, wnd);
709
710 /* wait for VisibilityNotify */
711 do
712 {
713 XMaskEvent(display, VisibilityChangeMask, &xevent);
714 }
715 while (xevent.type != VisibilityNotify);
716
717 g_focused = False;
718 g_mouse_in_wnd = False;
719
720 /* handle the WM_DELETE_WINDOW protocol */
721 protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
722 kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
723 XSetWMProtocols(display, wnd, &kill_atom, 1);
724
725 return True;
726 }
727
728 void
729 ui_destroy_window(void)
730 {
731 if (IC != NULL)
732 XDestroyIC(IC);
733
734 XDestroyWindow(display, wnd);
735 }
736
737 void
738 xwin_toggle_fullscreen(void)
739 {
740 Pixmap contents = 0;
741
742 if (!ownbackstore)
743 {
744 /* need to save contents of window */
745 contents = XCreatePixmap(display, wnd, g_width, g_height, depth);
746 XCopyArea(display, wnd, contents, gc, 0, 0, g_width, g_height, 0, 0);
747 }
748
749 ui_destroy_window();
750 g_fullscreen = !g_fullscreen;
751 ui_create_window();
752
753 XDefineCursor(display, wnd, current_cursor);
754
755 if (!ownbackstore)
756 {
757 XCopyArea(display, contents, wnd, gc, 0, 0, g_width, g_height, 0, 0);
758 XFreePixmap(display, contents);
759 }
760 }
761
762 /* Process all events in Xlib queue
763 Returns 0 after user quit, 1 otherwise */
764 static int
765 xwin_process_events(void)
766 {
767 XEvent xevent;
768 KeySym keysym;
769 uint16 button, flags;
770 uint32 ev_time;
771 key_translation tr;
772 char str[256];
773 Status status;
774 unsigned int state;
775 Window wdummy;
776 int dummy;
777
778 while (XPending(display) > 0)
779 {
780 XNextEvent(display, &xevent);
781
782 if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
783 {
784 DEBUG_KBD(("Filtering event\n"));
785 continue;
786 }
787
788 flags = 0;
789
790 switch (xevent.type)
791 {
792 case ClientMessage:
793 /* the window manager told us to quit */
794 if ((xevent.xclient.message_type == protocol_atom)
795 && ((Atom) xevent.xclient.data.l[0] == kill_atom))
796 /* Quit */
797 return 0;
798 break;
799
800 case KeyPress:
801 last_gesturetime = xevent.xkey.time;
802 if (IC != NULL)
803 /* Multi_key compatible version */
804 {
805 XmbLookupString(IC,
806 &xevent.xkey, str, sizeof(str), &keysym,
807 &status);
808 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
809 {
810 error("XmbLookupString failed with status 0x%x\n",
811 status);
812 break;
813 }
814 }
815 else
816 {
817 /* Plain old XLookupString */
818 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
819 XLookupString((XKeyEvent *) & xevent,
820 str, sizeof(str), &keysym, NULL);
821 }
822
823 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
824 get_ksname(keysym)));
825
826 ev_time = time(NULL);
827 if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
828 break;
829
830 tr = xkeymap_translate_key(keysym,
831 xevent.xkey.keycode, xevent.xkey.state);
832
833 if (tr.scancode == 0)
834 break;
835
836 ensure_remote_modifiers(ev_time, tr);
837
838 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
839 break;
840
841 case KeyRelease:
842 last_gesturetime = xevent.xkey.time;
843 XLookupString((XKeyEvent *) & xevent, str,
844 sizeof(str), &keysym, NULL);
845
846 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
847 get_ksname(keysym)));
848
849 ev_time = time(NULL);
850 if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
851 break;
852
853 tr = xkeymap_translate_key(keysym,
854 xevent.xkey.keycode, xevent.xkey.state);
855
856 if (tr.scancode == 0)
857 break;
858
859 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
860 break;
861
862 case ButtonPress:
863 flags = MOUSE_FLAG_DOWN;
864 /* fall through */
865
866 case ButtonRelease:
867 last_gesturetime = xevent.xbutton.time;
868 button = xkeymap_translate_button(xevent.xbutton.button);
869 if (button == 0)
870 break;
871
872 /* If win_button_size is nonzero, enable single app mode */
873 if (xevent.xbutton.y < win_button_size)
874 {
875 /* Stop moving window when button is released, regardless of cursor position */
876 if (moving_wnd && (xevent.type == ButtonRelease))
877 moving_wnd = False;
878
879 /* Check from right to left: */
880
881 if (xevent.xbutton.x >= g_width - win_button_size)
882 {
883 /* The close button, continue */
884 ;
885 }
886 else if (xevent.xbutton.x >= g_width - win_button_size * 2)
887 {
888 /* The maximize/restore button. Do not send to
889 server. It might be a good idea to change the
890 cursor or give some other visible indication
891 that rdesktop inhibited this click */
892 break;
893 }
894 else if (xevent.xbutton.x >= g_width - win_button_size * 3)
895 {
896 /* The minimize button. Iconify window. */
897 XIconifyWindow(display, wnd,
898 DefaultScreen(display));
899 break;
900 }
901 else if (xevent.xbutton.x <= win_button_size)
902 {
903 /* The system menu. Ignore. */
904 break;
905 }
906 else
907 {
908 /* The title bar. */
909 if ((xevent.type == ButtonPress) && !g_fullscreen
910 && hide_decorations)
911 {
912 moving_wnd = True;
913 move_x_offset = xevent.xbutton.x;
914 move_y_offset = xevent.xbutton.y;
915 }
916 break;
917
918 }
919 }
920
921 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
922 flags | button, xevent.xbutton.x, xevent.xbutton.y);
923 break;
924
925 case MotionNotify:
926 if (moving_wnd)
927 {
928 XMoveWindow(display, wnd,
929 xevent.xmotion.x_root - move_x_offset,
930 xevent.xmotion.y_root - move_y_offset);
931 break;
932 }
933
934 if (g_fullscreen && !g_focused)
935 XSetInputFocus(display, wnd, RevertToPointerRoot,
936 CurrentTime);
937 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
938 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
939 break;
940
941 case FocusIn:
942 if (xevent.xfocus.mode == NotifyGrab)
943 break;
944 g_focused = True;
945 XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
946 &dummy, &dummy, &state);
947 reset_modifier_keys(state);
948 if (grab_keyboard && g_mouse_in_wnd)
949 XGrabKeyboard(display, wnd, True,
950 GrabModeAsync, GrabModeAsync, CurrentTime);
951 break;
952
953 case FocusOut:
954 if (xevent.xfocus.mode == NotifyUngrab)
955 break;
956 g_focused = False;
957 if (xevent.xfocus.mode == NotifyWhileGrabbed)
958 XUngrabKeyboard(display, CurrentTime);
959 break;
960
961 case EnterNotify:
962 /* we only register for this event when in fullscreen mode */
963 /* or grab_keyboard */
964 g_mouse_in_wnd = True;
965 if (g_fullscreen)
966 {
967 XSetInputFocus(display, wnd, RevertToPointerRoot,
968 CurrentTime);
969 break;
970 }
971 if (g_focused)
972 XGrabKeyboard(display, wnd, True,
973 GrabModeAsync, GrabModeAsync, CurrentTime);
974 break;
975
976 case LeaveNotify:
977 /* we only register for this event when grab_keyboard */
978 g_mouse_in_wnd = False;
979 XUngrabKeyboard(display, CurrentTime);
980 break;
981
982 case Expose:
983 XCopyArea(display, backstore, wnd, gc,
984 xevent.xexpose.x, xevent.xexpose.y,
985 xevent.xexpose.width,
986 xevent.xexpose.height,
987 xevent.xexpose.x, xevent.xexpose.y);
988 break;
989
990 case MappingNotify:
991 /* Refresh keyboard mapping if it has changed. This is important for
992 Xvnc, since it allocates keycodes dynamically */
993 if (xevent.xmapping.request == MappingKeyboard
994 || xevent.xmapping.request == MappingModifier)
995 XRefreshKeyboardMapping(&xevent.xmapping);
996
997 if (xevent.xmapping.request == MappingModifier)
998 {
999 XFreeModifiermap(mod_map);
1000 mod_map = XGetModifierMapping(display);
1001 }
1002 break;
1003
1004 /* clipboard stuff */
1005 case SelectionNotify:
1006 xclip_handle_SelectionNotify(&xevent.xselection);
1007 break;
1008 case SelectionRequest:
1009 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1010 break;
1011 case SelectionClear:
1012 xclip_handle_SelectionClear();
1013 break;
1014 case PropertyNotify:
1015 xclip_handle_PropertyNotify(&xevent.xproperty);
1016 break;
1017 }
1018 }
1019 /* Keep going */
1020 return 1;
1021 }
1022
1023 /* Returns 0 after user quit, 1 otherwise */
1024 int
1025 ui_select(int rdp_socket)
1026 {
1027 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
1028 fd_set rfds;
1029
1030 FD_ZERO(&rfds);
1031
1032 while (True)
1033 {
1034 /* Process any events already waiting */
1035 if (!xwin_process_events())
1036 /* User quit */
1037 return 0;
1038
1039 FD_ZERO(&rfds);
1040 FD_SET(rdp_socket, &rfds);
1041 FD_SET(x_socket, &rfds);
1042
1043 switch (select(n, &rfds, NULL, NULL, NULL))
1044 {
1045 case -1:
1046 error("select: %s\n", strerror(errno));
1047
1048 case 0:
1049 continue;
1050 }
1051
1052 if (FD_ISSET(rdp_socket, &rfds))
1053 return 1;
1054 }
1055 }
1056
1057 void
1058 ui_move_pointer(int x, int y)
1059 {
1060 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
1061 }
1062
1063 HBITMAP
1064 ui_create_bitmap(int width, int height, uint8 * data)
1065 {
1066 XImage *image;
1067 Pixmap bitmap;
1068 uint8 *tdata;
1069
1070 tdata = (owncolmap ? data : translate_image(width, height, data));
1071 bitmap = XCreatePixmap(display, wnd, width, height, depth);
1072 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1073 (char *) tdata, width, height, g_server_bpp == 8 ? 8 : bpp, 0);
1074
1075 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1076
1077 XFree(image);
1078 if (!owncolmap)
1079 xfree(tdata);
1080 return (HBITMAP) bitmap;
1081 }
1082
1083 void
1084 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1085 {
1086 XImage *image;
1087 uint8 *tdata;
1088 tdata = (owncolmap ? data : translate_image(width, height, data));
1089 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1090 (char *) tdata, width, height, g_server_bpp == 8 ? 8 : bpp, 0);
1091
1092 if (ownbackstore)
1093 {
1094 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1095 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1096 }
1097 else
1098 {
1099 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1100 }
1101
1102 XFree(image);
1103 if (!owncolmap)
1104 xfree(tdata);
1105 }
1106
1107 void
1108 ui_destroy_bitmap(HBITMAP bmp)
1109 {
1110 XFreePixmap(display, (Pixmap) bmp);
1111 }
1112
1113 HGLYPH
1114 ui_create_glyph(int width, int height, uint8 * data)
1115 {
1116 XImage *image;
1117 Pixmap bitmap;
1118 int scanline;
1119 GC gc;
1120
1121 scanline = (width + 7) / 8;
1122
1123 bitmap = XCreatePixmap(display, wnd, width, height, 1);
1124 gc = XCreateGC(display, bitmap, 0, NULL);
1125
1126 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1127 width, height, 8, scanline);
1128 image->byte_order = MSBFirst;
1129 image->bitmap_bit_order = MSBFirst;
1130 XInitImage(image);
1131
1132 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1133
1134 XFree(image);
1135 XFreeGC(display, gc);
1136 return (HGLYPH) bitmap;
1137 }
1138
1139 void
1140 ui_destroy_glyph(HGLYPH glyph)
1141 {
1142 XFreePixmap(display, (Pixmap) glyph);
1143 }
1144
1145 HCURSOR
1146 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1147 uint8 * andmask, uint8 * xormask)
1148 {
1149 HGLYPH maskglyph, cursorglyph;
1150 XColor bg, fg;
1151 Cursor xcursor;
1152 uint8 *cursor, *pcursor;
1153 uint8 *mask, *pmask;
1154 uint8 nextbit;
1155 int scanline, offset;
1156 int i, j;
1157
1158 scanline = (width + 7) / 8;
1159 offset = scanline * height;
1160
1161 cursor = (uint8 *) xmalloc(offset);
1162 memset(cursor, 0, offset);
1163
1164 mask = (uint8 *) xmalloc(offset);
1165 memset(mask, 0, offset);
1166
1167 /* approximate AND and XOR masks with a monochrome X pointer */
1168 for (i = 0; i < height; i++)
1169 {
1170 offset -= scanline;
1171 pcursor = &cursor[offset];
1172 pmask = &mask[offset];
1173
1174 for (j = 0; j < scanline; j++)
1175 {
1176 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1177 {
1178 if (xormask[0] || xormask[1] || xormask[2])
1179 {
1180 *pcursor |= (~(*andmask) & nextbit);
1181 *pmask |= nextbit;
1182 }
1183 else
1184 {
1185 *pcursor |= ((*andmask) & nextbit);
1186 *pmask |= (~(*andmask) & nextbit);
1187 }
1188
1189 xormask += 3;
1190 }
1191
1192 andmask++;
1193 pcursor++;
1194 pmask++;
1195 }
1196 }
1197
1198 fg.red = fg.blue = fg.green = 0xffff;
1199 bg.red = bg.blue = bg.green = 0x0000;
1200 fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1201
1202 cursorglyph = ui_create_glyph(width, height, cursor);
1203 maskglyph = ui_create_glyph(width, height, mask);
1204
1205 xcursor =
1206 XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1207 (Pixmap) maskglyph, &fg, &bg, x, y);
1208
1209 ui_destroy_glyph(maskglyph);
1210 ui_destroy_glyph(cursorglyph);
1211 xfree(mask);
1212 xfree(cursor);
1213 return (HCURSOR) xcursor;
1214 }
1215
1216 void
1217 ui_set_cursor(HCURSOR cursor)
1218 {
1219 current_cursor = (Cursor) cursor;
1220 XDefineCursor(display, wnd, current_cursor);
1221 }
1222
1223 void
1224 ui_destroy_cursor(HCURSOR cursor)
1225 {
1226 XFreeCursor(display, (Cursor) cursor);
1227 }
1228
1229 #define MAKE_XCOLOR(xc,c) \
1230 (xc)->red = ((c)->red << 8) | (c)->red; \
1231 (xc)->green = ((c)->green << 8) | (c)->green; \
1232 (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1233 (xc)->flags = DoRed | DoGreen | DoBlue;
1234
1235
1236 HCOLOURMAP
1237 ui_create_colourmap(COLOURMAP * colours)
1238 {
1239 COLOURENTRY *entry;
1240 int i, ncolours = colours->ncolours;
1241 if (!owncolmap)
1242 {
1243 uint32 *map = (uint32 *) xmalloc(sizeof(*colmap) * ncolours);
1244 XColor xentry;
1245 XColor xc_cache[256];
1246 uint32 colour;
1247 int colLookup = 256;
1248 for (i = 0; i < ncolours; i++)
1249 {
1250 entry = &colours->colours[i];
1251 MAKE_XCOLOR(&xentry, entry);
1252
1253 if (XAllocColor(display, xcolmap, &xentry) == 0)
1254 {
1255 /* Allocation failed, find closest match. */
1256 int j = 256;
1257 int nMinDist = 3 * 256 * 256;
1258 long nDist = nMinDist;
1259
1260 /* only get the colors once */
1261 while (colLookup--)
1262 {
1263 xc_cache[colLookup].pixel = colLookup;
1264 xc_cache[colLookup].red = xc_cache[colLookup].green =
1265 xc_cache[colLookup].blue = 0;
1266 xc_cache[colLookup].flags = 0;
1267 XQueryColor(display,
1268 DefaultColormap(display,
1269 DefaultScreen(display)),
1270 &xc_cache[colLookup]);
1271 }
1272 colLookup = 0;
1273
1274 /* approximate the pixel */
1275 while (j--)
1276 {
1277 if (xc_cache[j].flags)
1278 {
1279 nDist = ((long) (xc_cache[j].red >> 8) -
1280 (long) (xentry.red >> 8)) *
1281 ((long) (xc_cache[j].red >> 8) -
1282 (long) (xentry.red >> 8)) +
1283 ((long) (xc_cache[j].green >> 8) -
1284 (long) (xentry.green >> 8)) *
1285 ((long) (xc_cache[j].green >> 8) -
1286 (long) (xentry.green >> 8)) +
1287 ((long) (xc_cache[j].blue >> 8) -
1288 (long) (xentry.blue >> 8)) *
1289 ((long) (xc_cache[j].blue >> 8) -
1290 (long) (xentry.blue >> 8));
1291 }
1292 if (nDist < nMinDist)
1293 {
1294 nMinDist = nDist;
1295 xentry.pixel = j;
1296 }
1297 }
1298 }
1299 colour = xentry.pixel;
1300
1301 /* update our cache */
1302 if (xentry.pixel < 256)
1303 {
1304 xc_cache[xentry.pixel].red = xentry.red;
1305 xc_cache[xentry.pixel].green = xentry.green;
1306 xc_cache[xentry.pixel].blue = xentry.blue;
1307
1308 }
1309
1310
1311 /* byte swap here to make translate_image faster */
1312 map[i] = translate_colour(colour);
1313 }
1314 return map;
1315 }
1316 else
1317 {
1318 XColor *xcolours, *xentry;
1319 Colormap map;
1320
1321 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1322 for (i = 0; i < ncolours; i++)
1323 {
1324 entry = &colours->colours[i];
1325 xentry = &xcolours[i];
1326 xentry->pixel = i;
1327 MAKE_XCOLOR(xentry, entry);
1328 }
1329
1330 map = XCreateColormap(display, wnd, visual, AllocAll);
1331 XStoreColors(display, map, xcolours, ncolours);
1332
1333 xfree(xcolours);
1334 return (HCOLOURMAP) map;
1335 }
1336 }
1337
1338 void
1339 ui_destroy_colourmap(HCOLOURMAP map)
1340 {
1341 if (!owncolmap)
1342 xfree(map);
1343 else
1344 XFreeColormap(display, (Colormap) map);
1345 }
1346
1347 void
1348 ui_set_colourmap(HCOLOURMAP map)
1349 {
1350 if (!owncolmap)
1351 {
1352 if (colmap)
1353 xfree(colmap);
1354
1355 colmap = (uint32 *) map;
1356 }
1357 else
1358 XSetWindowColormap(display, wnd, (Colormap) map);
1359 }
1360
1361 void
1362 ui_set_clip(int x, int y, int cx, int cy)
1363 {
1364 XRectangle rect;
1365
1366 rect.x = x;
1367 rect.y = y;
1368 rect.width = cx;
1369 rect.height = cy;
1370 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1371 }
1372
1373 void
1374 ui_reset_clip(void)
1375 {
1376 XRectangle rect;
1377
1378 rect.x = 0;
1379 rect.y = 0;
1380 rect.width = g_width;
1381 rect.height = g_height;
1382 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1383 }
1384
1385 void
1386 ui_bell(void)
1387 {
1388 XBell(display, 0);
1389 }
1390
1391 void
1392 ui_destblt(uint8 opcode,
1393 /* dest */ int x, int y, int cx, int cy)
1394 {
1395 SET_FUNCTION(opcode);
1396 FILL_RECTANGLE(x, y, cx, cy);
1397 RESET_FUNCTION(opcode);
1398 }
1399
1400 static uint8 hatch_patterns[] = {
1401 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1402 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1403 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1404 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1405 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1406 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
1407 };
1408
1409 void
1410 ui_patblt(uint8 opcode,
1411 /* dest */ int x, int y, int cx, int cy,
1412 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1413 {
1414 Pixmap fill;
1415 uint8 i, ipattern[8];
1416
1417 SET_FUNCTION(opcode);
1418
1419 switch (brush->style)
1420 {
1421 case 0: /* Solid */
1422 SET_FOREGROUND(fgcolour);
1423 FILL_RECTANGLE(x, y, cx, cy);
1424 break;
1425
1426 case 2: /* Hatch */
1427 fill = (Pixmap) ui_create_glyph(8, 8,
1428 hatch_patterns + brush->pattern[0] * 8);
1429 SET_FOREGROUND(bgcolour);
1430 SET_BACKGROUND(fgcolour);
1431 XSetFillStyle(display, gc, FillOpaqueStippled);
1432 XSetStipple(display, gc, fill);
1433 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1434 FILL_RECTANGLE(x, y, cx, cy);
1435 XSetFillStyle(display, gc, FillSolid);
1436 XSetTSOrigin(display, gc, 0, 0);
1437 ui_destroy_glyph((HGLYPH) fill);
1438 break;
1439
1440 case 3: /* Pattern */
1441 for (i = 0; i != 8; i++)
1442 ipattern[7 - i] = brush->pattern[i];
1443 fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1444
1445 SET_FOREGROUND(bgcolour);
1446 SET_BACKGROUND(fgcolour);
1447 XSetFillStyle(display, gc, FillOpaqueStippled);
1448 XSetStipple(display, gc, fill);
1449 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1450
1451 FILL_RECTANGLE(x, y, cx, cy);
1452
1453 XSetFillStyle(display, gc, FillSolid);
1454 XSetTSOrigin(display, gc, 0, 0);
1455 ui_destroy_glyph((HGLYPH) fill);
1456 break;
1457
1458 default:
1459 unimpl("brush %d\n", brush->style);
1460 }
1461
1462 RESET_FUNCTION(opcode);
1463 }
1464
1465 void
1466 ui_screenblt(uint8 opcode,
1467 /* dest */ int x, int y, int cx, int cy,
1468 /* src */ int srcx, int srcy)
1469 {
1470 SET_FUNCTION(opcode);
1471 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1472 if (ownbackstore)
1473 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1474 RESET_FUNCTION(opcode);
1475 }
1476
1477 void
1478 ui_memblt(uint8 opcode,
1479 /* dest */ int x, int y, int cx, int cy,
1480 /* src */ HBITMAP src, int srcx, int srcy)
1481 {
1482 SET_FUNCTION(opcode);
1483 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1484 if (ownbackstore)
1485 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1486 RESET_FUNCTION(opcode);
1487 }
1488
1489 void
1490 ui_triblt(uint8 opcode,
1491 /* dest */ int x, int y, int cx, int cy,
1492 /* src */ HBITMAP src, int srcx, int srcy,
1493 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1494 {
1495 /* This is potentially difficult to do in general. Until someone
1496 comes up with a more efficient way of doing it I am using cases. */
1497
1498 switch (opcode)
1499 {
1500 case 0x69: /* PDSxxn */
1501 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1502 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1503 break;
1504
1505 case 0xb8: /* PSDPxax */
1506 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1507 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1508 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1509 break;
1510
1511 case 0xc0: /* PSa */
1512 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1513 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1514 break;
1515
1516 default:
1517 unimpl("triblt 0x%x\n", opcode);
1518 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1519 }
1520 }
1521
1522 void
1523 ui_line(uint8 opcode,
1524 /* dest */ int startx, int starty, int endx, int endy,
1525 /* pen */ PEN * pen)
1526 {
1527 SET_FUNCTION(opcode);
1528 SET_FOREGROUND(pen->colour);
1529 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1530 if (ownbackstore)
1531 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1532 RESET_FUNCTION(opcode);
1533 }
1534
1535 void
1536 ui_rect(
1537 /* dest */ int x, int y, int cx, int cy,
1538 /* brush */ int colour)
1539 {
1540 SET_FOREGROUND(colour);
1541 FILL_RECTANGLE(x, y, cx, cy);
1542 }
1543
1544 /* warning, this function only draws on wnd or backstore, not both */
1545 void
1546 ui_draw_glyph(int mixmode,
1547 /* dest */ int x, int y, int cx, int cy,
1548 /* src */ HGLYPH glyph, int srcx, int srcy,
1549 int bgcolour, int fgcolour)
1550 {
1551 SET_FOREGROUND(fgcolour);
1552 SET_BACKGROUND(bgcolour);
1553
1554 XSetFillStyle(display, gc,
1555 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1556 XSetStipple(display, gc, (Pixmap) glyph);
1557 XSetTSOrigin(display, gc, x, y);
1558
1559 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1560
1561 XSetFillStyle(display, gc, FillSolid);
1562 }
1563
1564 #define DO_GLYPH(ttext,idx) \
1565 {\
1566 glyph = cache_get_font (font, ttext[idx]);\
1567 if (!(flags & TEXT2_IMPLICIT_X))\
1568 {\
1569 xyoffset = ttext[++idx];\
1570 if ((xyoffset & 0x80))\
1571 {\
1572 if (flags & TEXT2_VERTICAL) \
1573 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1574 else\
1575 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1576 idx += 2;\
1577 }\
1578 else\
1579 {\
1580 if (flags & TEXT2_VERTICAL) \
1581 y += xyoffset;\
1582 else\
1583 x += xyoffset;\
1584 }\
1585 }\
1586 if (glyph != NULL)\
1587 {\
1588 ui_draw_glyph (mixmode, x + glyph->offset,\
1589 y + glyph->baseline,\
1590 glyph->width, glyph->height,\
1591 glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1592 if (flags & TEXT2_IMPLICIT_X)\
1593 x += glyph->width;\
1594 }\
1595 }
1596
1597 void
1598 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1599 int clipx, int clipy, int clipcx, int clipcy,
1600 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1601 int fgcolour, uint8 * text, uint8 length)
1602 {
1603 FONTGLYPH *glyph;
1604 int i, j, xyoffset;
1605 DATABLOB *entry;
1606
1607 SET_FOREGROUND(bgcolour);
1608
1609 if (boxcx > 1)
1610 {
1611 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1612 }
1613 else if (mixmode == MIX_OPAQUE)
1614 {
1615 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1616 }
1617
1618 /* Paint text, character by character */
1619 for (i = 0; i < length;)
1620 {
1621 switch (text[i])
1622 {
1623 case 0xff:
1624 if (i + 2 < length)
1625 cache_put_text(text[i + 1], text, text[i + 2]);
1626 else
1627 {
1628 error("this shouldn't be happening\n");
1629 exit(1);
1630 }
1631 /* this will move pointer from start to first character after FF command */
1632 length -= i + 3;
1633 text = &(text[i + 3]);
1634 i = 0;
1635 break;
1636
1637 case 0xfe:
1638 entry = cache_get_text(text[i + 1]);
1639 if (entry != NULL)
1640 {
1641 if ((((uint8 *) (entry->data))[1] ==
1642 0) && (!(flags & TEXT2_IMPLICIT_X)))
1643 {
1644 if (flags & TEXT2_VERTICAL)
1645 y += text[i + 2];
1646 else
1647 x += text[i + 2];
1648 }
1649 for (j = 0; j < entry->size; j++)
1650 DO_GLYPH(((uint8 *) (entry->data)), j);
1651 }
1652 if (i + 2 < length)
1653 i += 3;
1654 else
1655 i += 2;
1656 length -= i;
1657 /* this will move pointer from start to first character after FE command */
1658 text = &(text[i]);
1659 i = 0;
1660 break;
1661
1662 default:
1663 DO_GLYPH(text, i);
1664 i++;
1665 break;
1666 }
1667 }
1668 if (ownbackstore)
1669 {
1670 if (boxcx > 1)
1671 XCopyArea(display, backstore, wnd, gc, boxx,
1672 boxy, boxcx, boxcy, boxx, boxy);
1673 else
1674 XCopyArea(display, backstore, wnd, gc, clipx,
1675 clipy, clipcx, clipcy, clipx, clipy);
1676 }
1677 }
1678
1679 void
1680 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1681 {
1682 Pixmap pix;
1683 XImage *image;
1684
1685 if (ownbackstore)
1686 {
1687 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1688 }
1689 else
1690 {
1691 pix = XCreatePixmap(display, wnd, cx, cy, depth);
1692 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1693 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1694 XFreePixmap(display, pix);
1695 }
1696
1697 offset *= bpp / 8;
1698 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1699
1700 XDestroyImage(image);
1701 }
1702
1703 void
1704 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1705 {
1706 XImage *image;
1707 uint8 *data;
1708
1709 offset *= bpp / 8;
1710 data = cache_get_desktop(offset, cx, cy, bpp / 8);
1711 if (data == NULL)
1712 return;
1713
1714 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1715 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1716
1717 if (ownbackstore)
1718 {
1719 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1720 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1721 }
1722 else
1723 {
1724 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1725 }
1726
1727 XFree(image);
1728 }

  ViewVC Help
Powered by ViewVC 1.1.26