/[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 332 - (show annotations)
Tue Feb 18 13:51:43 2003 UTC (21 years, 3 months ago) by astrand
File MIME type: text/plain
File size: 36603 byte(s)
Prevent restoring by double click in single app mode.

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

  ViewVC Help
Powered by ViewVC 1.1.26