/[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 376 - (show annotations)
Mon May 19 21:36:33 2003 UTC (21 years ago) by jsorg71
File MIME type: text/plain
File size: 38278 byte(s)
changes so it compiles with g++(mainly for ports)

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

  ViewVC Help
Powered by ViewVC 1.1.26