/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26