/[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 328 - (show annotations)
Tue Feb 18 13:03:51 2003 UTC (21 years, 3 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 36372 byte(s)
New option for running single applications maximized

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

  ViewVC Help
Powered by ViewVC 1.1.26