/[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 342 - (show annotations)
Fri Mar 14 12:00:17 2003 UTC (21 years, 2 months ago) by astrand
File MIME type: text/plain
File size: 37257 byte(s)
Support for moving window by dragging applications title bar. To be used
in conjunction with -s, -S and -D.

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

  ViewVC Help
Powered by ViewVC 1.1.26