/[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 823 - (show annotations)
Mon Feb 28 23:30:00 2005 UTC (19 years, 2 months ago) by stargo
File MIME type: text/plain
File size: 51794 byte(s)
fix missing while. This garbled data when displaying on a BE host running
at 32bpp, when rdesktop is running on a LE host connecting with 16bpp to
the TS

1 /* -*- c-basic-offset: 8 -*-
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 <unistd.h>
24 #include <sys/time.h>
25 #include <time.h>
26 #include <errno.h>
27 #include <strings.h>
28 #include "rdesktop.h"
29 #include "xproto.h"
30
31 extern int g_width;
32 extern int g_height;
33 extern int g_xpos;
34 extern int g_ypos;
35 extern BOOL g_sendmotion;
36 extern BOOL g_fullscreen;
37 extern BOOL g_grab_keyboard;
38 extern BOOL g_hide_decorations;
39 extern char g_title[];
40 extern int g_server_bpp;
41 extern int g_win_button_size;
42
43 Display *g_display;
44 Time g_last_gesturetime;
45 static int g_x_socket;
46 static Screen *g_screen;
47 Window g_wnd;
48 extern uint32 g_embed_wnd;
49 BOOL g_enable_compose = False;
50 BOOL g_Unobscured; /* used for screenblt */
51 static GC g_gc = NULL;
52 static GC g_create_bitmap_gc = NULL;
53 static GC g_create_glyph_gc = NULL;
54 static Visual *g_visual;
55 static int g_depth;
56 static int g_bpp;
57 static XIM g_IM;
58 static XIC g_IC;
59 static XModifierKeymap *g_mod_map;
60 static Cursor g_current_cursor;
61 static HCURSOR g_null_cursor = NULL;
62 static Atom g_protocol_atom, g_kill_atom;
63 static BOOL g_focused;
64 static BOOL g_mouse_in_wnd;
65 static BOOL g_arch_match = False; /* set to True if RGB XServer and little endian */
66
67 /* endianness */
68 static BOOL g_host_be;
69 static BOOL g_xserver_be;
70 static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
71 static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
72
73 /* software backing store */
74 extern BOOL g_ownbackstore;
75 static Pixmap g_backstore = 0;
76
77 /* Moving in single app mode */
78 static BOOL g_moving_wnd;
79 static int g_move_x_offset = 0;
80 static int g_move_y_offset = 0;
81
82 #ifdef WITH_RDPSND
83 extern int g_dsp_fd;
84 extern BOOL g_dsp_busy;
85 extern BOOL g_rdpsnd;
86 #endif
87
88 /* MWM decorations */
89 #define MWM_HINTS_DECORATIONS (1L << 1)
90 #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
91 typedef struct
92 {
93 uint32 flags;
94 uint32 functions;
95 uint32 decorations;
96 sint32 inputMode;
97 uint32 status;
98 }
99 PropMotifWmHints;
100
101 typedef struct
102 {
103 uint32 red;
104 uint32 green;
105 uint32 blue;
106 }
107 PixelColour;
108
109
110 #define FILL_RECTANGLE(x,y,cx,cy)\
111 { \
112 XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
113 if (g_ownbackstore) \
114 XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
115 }
116
117 #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
118 { \
119 XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
120 }
121
122 /* colour maps */
123 extern BOOL g_owncolmap;
124 static Colormap g_xcolmap;
125 static uint32 *g_colmap = NULL;
126
127 #define TRANSLATE(col) ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
128 #define SET_FOREGROUND(col) XSetForeground(g_display, g_gc, TRANSLATE(col));
129 #define SET_BACKGROUND(col) XSetBackground(g_display, g_gc, TRANSLATE(col));
130
131 static int rop2_map[] = {
132 GXclear, /* 0 */
133 GXnor, /* DPon */
134 GXandInverted, /* DPna */
135 GXcopyInverted, /* Pn */
136 GXandReverse, /* PDna */
137 GXinvert, /* Dn */
138 GXxor, /* DPx */
139 GXnand, /* DPan */
140 GXand, /* DPa */
141 GXequiv, /* DPxn */
142 GXnoop, /* D */
143 GXorInverted, /* DPno */
144 GXcopy, /* P */
145 GXorReverse, /* PDno */
146 GXor, /* DPo */
147 GXset /* 1 */
148 };
149
150 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
151 #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
152
153 static void
154 mwm_hide_decorations(void)
155 {
156 PropMotifWmHints motif_hints;
157 Atom hintsatom;
158
159 /* setup the property */
160 motif_hints.flags = MWM_HINTS_DECORATIONS;
161 motif_hints.decorations = 0;
162
163 /* get the atom for the property */
164 hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
165 if (!hintsatom)
166 {
167 warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
168 return;
169 }
170
171 XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
172 (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
173 }
174
175 #define SPLITCOLOUR15(colour, rv) \
176 { \
177 rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
178 rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
179 rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
180 }
181
182 #define SPLITCOLOUR16(colour, rv) \
183 { \
184 rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
185 rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
186 rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
187 } \
188
189 #define SPLITCOLOUR24(colour, rv) \
190 { \
191 rv.blue = (colour & 0xff0000) >> 16; \
192 rv.green = (colour & 0x00ff00) >> 8; \
193 rv.red = (colour & 0x0000ff); \
194 }
195
196 #define MAKECOLOUR(pc) \
197 ((pc.red >> g_red_shift_r) << g_red_shift_l) \
198 | ((pc.green >> g_green_shift_r) << g_green_shift_l) \
199 | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
200
201 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
202 #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
203 #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
204 x = (x << 16) | (x >> 16); }
205
206 #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
207 #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
208 #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
209 #define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
210 #define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
211 #define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
212
213 static uint32
214 translate_colour(uint32 colour)
215 {
216 PixelColour pc;
217 switch (g_server_bpp)
218 {
219 case 15:
220 SPLITCOLOUR15(colour, pc);
221 break;
222 case 16:
223 SPLITCOLOUR16(colour, pc);
224 break;
225 case 24:
226 SPLITCOLOUR24(colour, pc);
227 break;
228 }
229 return MAKECOLOUR(pc);
230 }
231
232 /* indent is confused by UNROLL8 */
233 /* *INDENT-OFF* */
234
235 /* repeat and unroll, similar to bitmap.c */
236 /* potentialy any of the following translate */
237 /* functions can use repeat but just doing */
238 /* the most common ones */
239
240 #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
241 /* 2 byte output repeat */
242 #define REPEAT2(stm) \
243 { \
244 while (out <= end - 8 * 2) \
245 UNROLL8(stm) \
246 while (out < end) \
247 { stm } \
248 }
249 /* 3 byte output repeat */
250 #define REPEAT3(stm) \
251 { \
252 while (out <= end - 8 * 3) \
253 UNROLL8(stm) \
254 while (out < end) \
255 { stm } \
256 }
257 /* 4 byte output repeat */
258 #define REPEAT4(stm) \
259 { \
260 while (out <= end - 8 * 4) \
261 UNROLL8(stm) \
262 while (out < end) \
263 { stm } \
264 }
265 /* *INDENT-ON* */
266
267 static void
268 translate8to8(const uint8 * data, uint8 * out, uint8 * end)
269 {
270 while (out < end)
271 *(out++) = (uint8) g_colmap[*(data++)];
272 }
273
274 static void
275 translate8to16(const uint8 * data, uint8 * out, uint8 * end)
276 {
277 uint16 value;
278
279 if (g_arch_match)
280 {
281 /* *INDENT-OFF* */
282 REPEAT2
283 (
284 *((uint16 *) out) = g_colmap[*(data++)];
285 out += 2;
286 )
287 /* *INDENT-ON* */
288 }
289 else if (g_xserver_be)
290 {
291 while (out < end)
292 {
293 value = (uint16) g_colmap[*(data++)];
294 BOUT16(out, value);
295 }
296 }
297 else
298 {
299 while (out < end)
300 {
301 value = (uint16) g_colmap[*(data++)];
302 LOUT16(out, value);
303 }
304 }
305 }
306
307 /* little endian - conversion happens when colourmap is built */
308 static void
309 translate8to24(const uint8 * data, uint8 * out, uint8 * end)
310 {
311 uint32 value;
312
313 if (g_xserver_be)
314 {
315 while (out < end)
316 {
317 value = g_colmap[*(data++)];
318 BOUT24(out, value);
319 }
320 }
321 else
322 {
323 while (out < end)
324 {
325 value = g_colmap[*(data++)];
326 LOUT24(out, value);
327 }
328 }
329 }
330
331 static void
332 translate8to32(const uint8 * data, uint8 * out, uint8 * end)
333 {
334 uint32 value;
335
336 if (g_arch_match)
337 {
338 /* *INDENT-OFF* */
339 REPEAT4
340 (
341 *((uint32 *) out) = g_colmap[*(data++)];
342 out += 4;
343 )
344 /* *INDENT-ON* */
345 }
346 else if (g_xserver_be)
347 {
348 while (out < end)
349 {
350 value = g_colmap[*(data++)];
351 BOUT32(out, value);
352 }
353 }
354 else
355 {
356 while (out < end)
357 {
358 value = g_colmap[*(data++)];
359 LOUT32(out, value);
360 }
361 }
362 }
363
364 static void
365 translate15to16(const uint16 * data, uint8 * out, uint8 * end)
366 {
367 uint16 pixel;
368 uint16 value;
369 PixelColour pc;
370
371 if (g_xserver_be)
372 {
373 while (out < end)
374 {
375 pixel = *(data++);
376 if (g_host_be)
377 {
378 BSWAP16(pixel);
379 }
380 SPLITCOLOUR15(pixel, pc);
381 value = MAKECOLOUR(pc);
382 BOUT16(out, value);
383 }
384 }
385 else
386 {
387 while (out < end)
388 {
389 pixel = *(data++);
390 if (g_host_be)
391 {
392 BSWAP16(pixel);
393 }
394 SPLITCOLOUR15(pixel, pc);
395 value = MAKECOLOUR(pc);
396 LOUT16(out, value);
397 }
398 }
399 }
400
401 static void
402 translate15to24(const uint16 * data, uint8 * out, uint8 * end)
403 {
404 uint32 value;
405 uint16 pixel;
406 PixelColour pc;
407
408 if (g_arch_match)
409 {
410 /* *INDENT-OFF* */
411 REPEAT3
412 (
413 pixel = *(data++);
414 SPLITCOLOUR15(pixel, pc);
415 *(out++) = pc.blue;
416 *(out++) = pc.green;
417 *(out++) = pc.red;
418 )
419 /* *INDENT-ON* */
420 }
421 else if (g_xserver_be)
422 {
423 while (out < end)
424 {
425 pixel = *(data++);
426 if (g_host_be)
427 {
428 BSWAP16(pixel);
429 }
430 SPLITCOLOUR15(pixel, pc);
431 value = MAKECOLOUR(pc);
432 BOUT24(out, value);
433 }
434 }
435 else
436 {
437 while (out < end)
438 {
439 pixel = *(data++);
440 if (g_host_be)
441 {
442 BSWAP16(pixel);
443 }
444 SPLITCOLOUR15(pixel, pc);
445 value = MAKECOLOUR(pc);
446 LOUT24(out, value);
447 }
448 }
449 }
450
451 static void
452 translate15to32(const uint16 * data, uint8 * out, uint8 * end)
453 {
454 uint16 pixel;
455 uint32 value;
456 PixelColour pc;
457
458 if (g_arch_match)
459 {
460 /* *INDENT-OFF* */
461 REPEAT4
462 (
463 pixel = *(data++);
464 SPLITCOLOUR15(pixel, pc);
465 *(out++) = pc.blue;
466 *(out++) = pc.green;
467 *(out++) = pc.red;
468 *(out++) = 0;
469 )
470 /* *INDENT-ON* */
471 }
472 else if (g_xserver_be)
473 {
474 while (out < end)
475 {
476 pixel = *(data++);
477 if (g_host_be)
478 {
479 BSWAP16(pixel);
480 }
481 SPLITCOLOUR15(pixel, pc);
482 value = MAKECOLOUR(pc);
483 BOUT32(out, value);
484 }
485 }
486 else
487 {
488 while (out < end)
489 {
490 pixel = *(data++);
491 if (g_host_be)
492 {
493 BSWAP16(pixel);
494 }
495 SPLITCOLOUR15(pixel, pc);
496 value = MAKECOLOUR(pc);
497 LOUT32(out, value);
498 }
499 }
500 }
501
502 static void
503 translate16to16(const uint16 * data, uint8 * out, uint8 * end)
504 {
505 uint16 pixel;
506 uint16 value;
507 PixelColour pc;
508
509 if (g_xserver_be)
510 {
511 if (g_host_be)
512 {
513 while (out < end)
514 {
515 pixel = *(data++);
516 BSWAP16(pixel);
517 SPLITCOLOUR16(pixel, pc);
518 value = MAKECOLOUR(pc);
519 BOUT16(out, value);
520 }
521 }
522 else
523 {
524 while (out < end)
525 {
526 pixel = *(data++);
527 SPLITCOLOUR16(pixel, pc);
528 value = MAKECOLOUR(pc);
529 BOUT16(out, value);
530 }
531 }
532 }
533 else
534 {
535 if (g_host_be)
536 {
537 while (out < end)
538 {
539 pixel = *(data++);
540 BSWAP16(pixel);
541 SPLITCOLOUR16(pixel, pc);
542 value = MAKECOLOUR(pc);
543 LOUT16(out, value);
544 }
545 }
546 else
547 {
548 while (out < end)
549 {
550 pixel = *(data++);
551 SPLITCOLOUR16(pixel, pc);
552 value = MAKECOLOUR(pc);
553 LOUT16(out, value);
554 }
555 }
556 }
557 }
558
559 static void
560 translate16to24(const uint16 * data, uint8 * out, uint8 * end)
561 {
562 uint32 value;
563 uint16 pixel;
564 PixelColour pc;
565
566 if (g_arch_match)
567 {
568 /* *INDENT-OFF* */
569 REPEAT3
570 (
571 pixel = *(data++);
572 SPLITCOLOUR16(pixel, pc);
573 *(out++) = pc.blue;
574 *(out++) = pc.green;
575 *(out++) = pc.red;
576 )
577 /* *INDENT-ON* */
578 }
579 else if (g_xserver_be)
580 {
581 if (g_host_be)
582 {
583 while (out < end)
584 {
585 pixel = *(data++);
586 BSWAP16(pixel);
587 SPLITCOLOUR16(pixel, pc);
588 value = MAKECOLOUR(pc);
589 BOUT24(out, value);
590 }
591 }
592 else
593 {
594 while (out < end)
595 {
596 pixel = *(data++);
597 SPLITCOLOUR16(pixel, pc);
598 value = MAKECOLOUR(pc);
599 BOUT24(out, value);
600 }
601 }
602 }
603 else
604 {
605 if (g_host_be)
606 {
607 while (out < end)
608 {
609 pixel = *(data++);
610 BSWAP16(pixel);
611 SPLITCOLOUR16(pixel, pc);
612 value = MAKECOLOUR(pc);
613 LOUT24(out, value);
614 }
615 }
616 else
617 {
618 while (out < end)
619 {
620 pixel = *(data++);
621 SPLITCOLOUR16(pixel, pc);
622 value = MAKECOLOUR(pc);
623 LOUT24(out, value);
624 }
625 }
626 }
627 }
628
629 static void
630 translate16to32(const uint16 * data, uint8 * out, uint8 * end)
631 {
632 uint16 pixel;
633 uint32 value;
634 PixelColour pc;
635
636 if (g_arch_match)
637 {
638 /* *INDENT-OFF* */
639 REPEAT4
640 (
641 pixel = *(data++);
642 SPLITCOLOUR16(pixel, pc);
643 *(out++) = pc.blue;
644 *(out++) = pc.green;
645 *(out++) = pc.red;
646 *(out++) = 0;
647 )
648 /* *INDENT-ON* */
649 }
650 else if (g_xserver_be)
651 {
652 if (g_host_be)
653 {
654 while (out < end)
655 {
656 pixel = *(data++);
657 BSWAP16(pixel);
658 SPLITCOLOUR16(pixel, pc);
659 value = MAKECOLOUR(pc);
660 BOUT32(out, value);
661 }
662 }
663 else
664 {
665 while (out < end)
666 {
667 pixel = *(data++);
668 SPLITCOLOUR16(pixel, pc);
669 value = MAKECOLOUR(pc);
670 BOUT32(out, value);
671 }
672 }
673 }
674 else
675 {
676 if (g_host_be)
677 {
678 while (out < end)
679 {
680 pixel = *(data++);
681 BSWAP16(pixel);
682 SPLITCOLOUR16(pixel, pc);
683 value = MAKECOLOUR(pc);
684 LOUT32(out, value);
685 }
686 }
687 else
688 {
689 while (out < end)
690 {
691 pixel = *(data++);
692 SPLITCOLOUR16(pixel, pc);
693 value = MAKECOLOUR(pc);
694 LOUT32(out, value);
695 }
696 }
697 }
698 }
699
700 static void
701 translate24to16(const uint8 * data, uint8 * out, uint8 * end)
702 {
703 uint32 pixel = 0;
704 uint16 value;
705 PixelColour pc;
706
707 while (out < end)
708 {
709 pixel = *(data++) << 16;
710 pixel |= *(data++) << 8;
711 pixel |= *(data++);
712 SPLITCOLOUR24(pixel, pc);
713 value = MAKECOLOUR(pc);
714 if (g_xserver_be)
715 {
716 BOUT16(out, value);
717 }
718 else
719 {
720 LOUT16(out, value);
721 }
722 }
723 }
724
725 static void
726 translate24to24(const uint8 * data, uint8 * out, uint8 * end)
727 {
728 uint32 pixel;
729 uint32 value;
730 PixelColour pc;
731
732 if (g_xserver_be)
733 {
734 while (out < end)
735 {
736 pixel = *(data++) << 16;
737 pixel |= *(data++) << 8;
738 pixel |= *(data++);
739 SPLITCOLOUR24(pixel, pc);
740 value = MAKECOLOUR(pc);
741 BOUT24(out, value);
742 }
743 }
744 else
745 {
746 while (out < end)
747 {
748 pixel = *(data++) << 16;
749 pixel |= *(data++) << 8;
750 pixel |= *(data++);
751 SPLITCOLOUR24(pixel, pc);
752 value = MAKECOLOUR(pc);
753 LOUT24(out, value);
754 }
755 }
756 }
757
758 static void
759 translate24to32(const uint8 * data, uint8 * out, uint8 * end)
760 {
761 uint32 pixel;
762 uint32 value;
763 PixelColour pc;
764
765 if (g_arch_match)
766 {
767 /* *INDENT-OFF* */
768 #ifdef NEED_ALIGN
769 REPEAT4
770 (
771 *(out++) = *(data++);
772 *(out++) = *(data++);
773 *(out++) = *(data++);
774 *(out++) = 0;
775 )
776 #else
777 REPEAT4
778 (
779 *((uint32 *) out) = *((uint32 *) data);
780 out += 4;
781 data += 3;
782 )
783 #endif
784 /* *INDENT-ON* */
785 }
786 else if (g_xserver_be)
787 {
788 while (out < end)
789 {
790 pixel = *(data++) << 16;
791 pixel |= *(data++) << 8;
792 pixel |= *(data++);
793 SPLITCOLOUR24(pixel, pc);
794 value = MAKECOLOUR(pc);
795 BOUT32(out, value);
796 }
797 }
798 else
799 {
800 while (out < end)
801 {
802 pixel = *(data++) << 16;
803 pixel |= *(data++) << 8;
804 pixel |= *(data++);
805 SPLITCOLOUR24(pixel, pc);
806 value = MAKECOLOUR(pc);
807 LOUT32(out, value);
808 }
809 }
810 }
811
812 static uint8 *
813 translate_image(int width, int height, uint8 * data)
814 {
815 int size;
816 uint8 *out;
817 uint8 *end;
818
819 /* if server and xserver bpp match, */
820 /* and arch(endian) matches, no need to translate */
821 /* just return data */
822 if (g_arch_match)
823 {
824 if (g_depth == 15 && g_server_bpp == 15)
825 return data;
826 if (g_depth == 16 && g_server_bpp == 16)
827 return data;
828 if (g_depth == 24 && g_bpp == 24 && g_server_bpp == 24)
829 return data;
830 }
831
832 size = width * height * (g_bpp / 8);
833 out = (uint8 *) xmalloc(size);
834 end = out + size;
835
836 switch (g_server_bpp)
837 {
838 case 24:
839 switch (g_bpp)
840 {
841 case 32:
842 translate24to32(data, out, end);
843 break;
844 case 24:
845 translate24to24(data, out, end);
846 break;
847 case 16:
848 translate24to16(data, out, end);
849 break;
850 }
851 break;
852 case 16:
853 switch (g_bpp)
854 {
855 case 32:
856 translate16to32((uint16 *) data, out, end);
857 break;
858 case 24:
859 translate16to24((uint16 *) data, out, end);
860 break;
861 case 16:
862 translate16to16((uint16 *) data, out, end);
863 break;
864 }
865 break;
866 case 15:
867 switch (g_bpp)
868 {
869 case 32:
870 translate15to32((uint16 *) data, out, end);
871 break;
872 case 24:
873 translate15to24((uint16 *) data, out, end);
874 break;
875 case 16:
876 translate15to16((uint16 *) data, out, end);
877 break;
878 }
879 break;
880 case 8:
881 switch (g_bpp)
882 {
883 case 8:
884 translate8to8(data, out, end);
885 break;
886 case 16:
887 translate8to16(data, out, end);
888 break;
889 case 24:
890 translate8to24(data, out, end);
891 break;
892 case 32:
893 translate8to32(data, out, end);
894 break;
895 }
896 break;
897 }
898 return out;
899 }
900
901 BOOL
902 get_key_state(unsigned int state, uint32 keysym)
903 {
904 int modifierpos, key, keysymMask = 0;
905 int offset;
906
907 KeyCode keycode = XKeysymToKeycode(g_display, keysym);
908
909 if (keycode == NoSymbol)
910 return False;
911
912 for (modifierpos = 0; modifierpos < 8; modifierpos++)
913 {
914 offset = g_mod_map->max_keypermod * modifierpos;
915
916 for (key = 0; key < g_mod_map->max_keypermod; key++)
917 {
918 if (g_mod_map->modifiermap[offset + key] == keycode)
919 keysymMask |= 1 << modifierpos;
920 }
921 }
922
923 return (state & keysymMask) ? True : False;
924 }
925
926 static void
927 calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
928 {
929 *shift_l = ffs(mask) - 1;
930 mask >>= *shift_l;
931 *shift_r = 8 - ffs(mask & ~(mask >> 1));
932 }
933
934 BOOL
935 ui_init(void)
936 {
937 XVisualInfo vi;
938 XPixmapFormatValues *pfm;
939 uint16 test;
940 int i, screen_num, nvisuals;
941 XVisualInfo *vmatches = NULL;
942 XVisualInfo template;
943 Bool TrueColorVisual = False;
944
945 g_display = XOpenDisplay(NULL);
946 if (g_display == NULL)
947 {
948 error("Failed to open display: %s\n", XDisplayName(NULL));
949 return False;
950 }
951
952 screen_num = DefaultScreen(g_display);
953 g_x_socket = ConnectionNumber(g_display);
954 g_screen = ScreenOfDisplay(g_display, screen_num);
955 g_depth = DefaultDepthOfScreen(g_screen);
956
957 /* Search for best TrueColor depth */
958 template.class = TrueColor;
959 vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);
960
961 nvisuals--;
962 while (nvisuals >= 0)
963 {
964 if ((vmatches + nvisuals)->depth > g_depth)
965 {
966 g_depth = (vmatches + nvisuals)->depth;
967 }
968 nvisuals--;
969 TrueColorVisual = True;
970 }
971
972 test = 1;
973 g_host_be = !(BOOL) (*(uint8 *) (&test));
974 g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
975
976 if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))
977 {
978 /* we use a colourmap, so the default visual should do */
979 g_visual = DefaultVisualOfScreen(g_screen);
980 g_depth = DefaultDepthOfScreen(g_screen);
981
982 /* Do not allocate colours on a TrueColor visual */
983 if (g_visual->class == TrueColor)
984 {
985 g_owncolmap = False;
986 }
987 }
988 else
989 {
990 /* need a truecolour visual */
991 if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))
992 {
993 error("The display does not support true colour - high colour support unavailable.\n");
994 return False;
995 }
996
997 g_visual = vi.visual;
998 g_owncolmap = False;
999 calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);
1000 calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);
1001 calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);
1002
1003 /* if RGB video and everything is little endian */
1004 if ((vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask) &&
1005 !g_xserver_be && !g_host_be)
1006 {
1007 if (g_depth <= 16 || (g_red_shift_l == 16 && g_green_shift_l == 8 &&
1008 g_blue_shift_l == 0))
1009 {
1010 g_arch_match = True;
1011 }
1012 }
1013
1014 if (g_arch_match)
1015 {
1016 DEBUG(("Architectures match, enabling little endian optimisations.\n"));
1017 }
1018 }
1019
1020 pfm = XListPixmapFormats(g_display, &i);
1021 if (pfm != NULL)
1022 {
1023 /* Use maximum bpp for this depth - this is generally
1024 desirable, e.g. 24 bits->32 bits. */
1025 while (i--)
1026 {
1027 if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
1028 {
1029 g_bpp = pfm[i].bits_per_pixel;
1030 }
1031 }
1032 XFree(pfm);
1033 }
1034
1035 if (g_bpp < 8)
1036 {
1037 error("Less than 8 bpp not currently supported.\n");
1038 XCloseDisplay(g_display);
1039 return False;
1040 }
1041
1042 if (!g_owncolmap)
1043 {
1044 g_xcolmap =
1045 XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1046 AllocNone);
1047 if (g_depth <= 8)
1048 warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
1049 }
1050
1051 if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1052 {
1053 warning("External BackingStore not available, using internal\n");
1054 g_ownbackstore = True;
1055 }
1056
1057 /*
1058 * Determine desktop size
1059 */
1060 if (g_fullscreen)
1061 {
1062 g_width = WidthOfScreen(g_screen);
1063 g_height = HeightOfScreen(g_screen);
1064 }
1065 else if (g_width < 0)
1066 {
1067 /* Percent of screen */
1068 g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1069 g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1070 }
1071 else if (g_width == 0)
1072 {
1073 /* Fetch geometry from _NET_WORKAREA */
1074 uint32 x, y, cx, cy;
1075
1076 if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1077 {
1078 g_width = cx;
1079 g_height = cy;
1080 }
1081 else
1082 {
1083 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1084 g_width = 800;
1085 g_height = 600;
1086 }
1087 }
1088
1089 /* make sure width is a multiple of 4 */
1090 g_width = (g_width + 3) & ~3;
1091
1092 g_mod_map = XGetModifierMapping(g_display);
1093
1094 xkeymap_init();
1095
1096 if (g_enable_compose)
1097 g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1098
1099 xclip_init();
1100
1101 DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));
1102
1103 return True;
1104 }
1105
1106 void
1107 ui_deinit(void)
1108 {
1109 if (g_IM != NULL)
1110 XCloseIM(g_IM);
1111
1112 if (g_null_cursor != NULL)
1113 ui_destroy_cursor(g_null_cursor);
1114
1115 XFreeModifiermap(g_mod_map);
1116
1117 if (g_ownbackstore)
1118 XFreePixmap(g_display, g_backstore);
1119
1120 XFreeGC(g_display, g_gc);
1121 XCloseDisplay(g_display);
1122 g_display = NULL;
1123 }
1124
1125 BOOL
1126 ui_create_window(void)
1127 {
1128 uint8 null_pointer_mask[1] = { 0x80 };
1129 uint8 null_pointer_data[24] = { 0x00 };
1130
1131 XSetWindowAttributes attribs;
1132 XClassHint *classhints;
1133 XSizeHints *sizehints;
1134 int wndwidth, wndheight;
1135 long input_mask, ic_input_mask;
1136 XEvent xevent;
1137
1138 wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1139 wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1140
1141 attribs.background_pixel = BlackPixelOfScreen(g_screen);
1142 attribs.border_pixel = WhitePixelOfScreen(g_screen);
1143 attribs.backing_store = g_ownbackstore ? NotUseful : Always;
1144 attribs.override_redirect = g_fullscreen;
1145 attribs.colormap = g_xcolmap;
1146
1147 g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1148 wndheight, 0, g_depth, InputOutput, g_visual,
1149 CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1150 CWBorderPixel, &attribs);
1151
1152 if (g_gc == NULL)
1153 g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1154
1155 if (g_create_bitmap_gc == NULL)
1156 g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1157
1158 if ((g_ownbackstore) && (g_backstore == 0))
1159 {
1160 g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1161
1162 /* clear to prevent rubbish being exposed at startup */
1163 XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1164 XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
1165 }
1166
1167 XStoreName(g_display, g_wnd, g_title);
1168
1169 if (g_hide_decorations)
1170 mwm_hide_decorations();
1171
1172 classhints = XAllocClassHint();
1173 if (classhints != NULL)
1174 {
1175 classhints->res_name = classhints->res_class = "rdesktop";
1176 XSetClassHint(g_display, g_wnd, classhints);
1177 XFree(classhints);
1178 }
1179
1180 sizehints = XAllocSizeHints();
1181 if (sizehints)
1182 {
1183 sizehints->flags = PMinSize | PMaxSize;
1184 sizehints->min_width = sizehints->max_width = g_width;
1185 sizehints->min_height = sizehints->max_height = g_height;
1186 XSetWMNormalHints(g_display, g_wnd, sizehints);
1187 XFree(sizehints);
1188 }
1189
1190 if (g_embed_wnd)
1191 {
1192 XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1193 }
1194
1195 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1196 VisibilityChangeMask | FocusChangeMask;
1197
1198 if (g_sendmotion)
1199 input_mask |= PointerMotionMask;
1200 if (g_ownbackstore)
1201 input_mask |= ExposureMask;
1202 if (g_fullscreen || g_grab_keyboard)
1203 input_mask |= EnterWindowMask;
1204 if (g_grab_keyboard)
1205 input_mask |= LeaveWindowMask;
1206
1207 if (g_IM != NULL)
1208 {
1209 g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1210 XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1211
1212 if ((g_IC != NULL)
1213 && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1214 input_mask |= ic_input_mask;
1215 }
1216
1217 XSelectInput(g_display, g_wnd, input_mask);
1218 XMapWindow(g_display, g_wnd);
1219
1220 /* wait for VisibilityNotify */
1221 do
1222 {
1223 XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1224 }
1225 while (xevent.type != VisibilityNotify);
1226 g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1227
1228 g_focused = False;
1229 g_mouse_in_wnd = False;
1230
1231 /* handle the WM_DELETE_WINDOW protocol */
1232 g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1233 g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1234 XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1235
1236 /* create invisible 1x1 cursor to be used as null cursor */
1237 if (g_null_cursor == NULL)
1238 g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1239
1240 return True;
1241 }
1242
1243 void
1244 ui_resize_window()
1245 {
1246 XSizeHints *sizehints;
1247 Pixmap bs;
1248
1249 sizehints = XAllocSizeHints();
1250 if (sizehints)
1251 {
1252 sizehints->flags = PMinSize | PMaxSize;
1253 sizehints->min_width = sizehints->max_width = g_width;
1254 sizehints->min_height = sizehints->max_height = g_height;
1255 XSetWMNormalHints(g_display, g_wnd, sizehints);
1256 XFree(sizehints);
1257 }
1258
1259 if (!(g_fullscreen || g_embed_wnd))
1260 {
1261 XResizeWindow(g_display, g_wnd, g_width, g_height);
1262 }
1263
1264 /* create new backstore pixmap */
1265 if (g_backstore != 0)
1266 {
1267 bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1268 XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1269 XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1270 XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1271 XFreePixmap(g_display, g_backstore);
1272 g_backstore = bs;
1273 }
1274 }
1275
1276 void
1277 ui_destroy_window(void)
1278 {
1279 if (g_IC != NULL)
1280 XDestroyIC(g_IC);
1281
1282 XDestroyWindow(g_display, g_wnd);
1283 }
1284
1285 void
1286 xwin_toggle_fullscreen(void)
1287 {
1288 Pixmap contents = 0;
1289
1290 if (!g_ownbackstore)
1291 {
1292 /* need to save contents of window */
1293 contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1294 XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1295 }
1296
1297 ui_destroy_window();
1298 g_fullscreen = !g_fullscreen;
1299 ui_create_window();
1300
1301 XDefineCursor(g_display, g_wnd, g_current_cursor);
1302
1303 if (!g_ownbackstore)
1304 {
1305 XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1306 XFreePixmap(g_display, contents);
1307 }
1308 }
1309
1310 /* Process all events in Xlib queue
1311 Returns 0 after user quit, 1 otherwise */
1312 static int
1313 xwin_process_events(void)
1314 {
1315 XEvent xevent;
1316 KeySym keysym;
1317 uint16 button, flags;
1318 uint32 ev_time;
1319 key_translation tr;
1320 char str[256];
1321 Status status;
1322
1323 while (XPending(g_display) > 0)
1324 {
1325 XNextEvent(g_display, &xevent);
1326
1327 if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1328 {
1329 DEBUG_KBD(("Filtering event\n"));
1330 continue;
1331 }
1332
1333 flags = 0;
1334
1335 switch (xevent.type)
1336 {
1337 case VisibilityNotify:
1338 g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1339 break;
1340 case ClientMessage:
1341 /* the window manager told us to quit */
1342 if ((xevent.xclient.message_type == g_protocol_atom)
1343 && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1344 /* Quit */
1345 return 0;
1346 break;
1347
1348 case KeyPress:
1349 g_last_gesturetime = xevent.xkey.time;
1350 if (g_IC != NULL)
1351 /* Multi_key compatible version */
1352 {
1353 XmbLookupString(g_IC,
1354 &xevent.xkey, str, sizeof(str), &keysym,
1355 &status);
1356 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1357 {
1358 error("XmbLookupString failed with status 0x%x\n",
1359 status);
1360 break;
1361 }
1362 }
1363 else
1364 {
1365 /* Plain old XLookupString */
1366 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1367 XLookupString((XKeyEvent *) & xevent,
1368 str, sizeof(str), &keysym, NULL);
1369 }
1370
1371 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1372 get_ksname(keysym)));
1373
1374 ev_time = time(NULL);
1375 if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1376 break;
1377
1378 tr = xkeymap_translate_key(keysym,
1379 xevent.xkey.keycode, xevent.xkey.state);
1380
1381 if (tr.scancode == 0)
1382 break;
1383
1384 save_remote_modifiers(tr.scancode);
1385 ensure_remote_modifiers(ev_time, tr);
1386 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1387 restore_remote_modifiers(ev_time, tr.scancode);
1388
1389 break;
1390
1391 case KeyRelease:
1392 g_last_gesturetime = xevent.xkey.time;
1393 XLookupString((XKeyEvent *) & xevent, str,
1394 sizeof(str), &keysym, NULL);
1395
1396 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1397 get_ksname(keysym)));
1398
1399 ev_time = time(NULL);
1400 if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1401 break;
1402
1403 tr = xkeymap_translate_key(keysym,
1404 xevent.xkey.keycode, xevent.xkey.state);
1405
1406 if (tr.scancode == 0)
1407 break;
1408
1409 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
1410 break;
1411
1412 case ButtonPress:
1413 flags = MOUSE_FLAG_DOWN;
1414 /* fall through */
1415
1416 case ButtonRelease:
1417 g_last_gesturetime = xevent.xbutton.time;
1418 button = xkeymap_translate_button(xevent.xbutton.button);
1419 if (button == 0)
1420 break;
1421
1422 /* If win_button_size is nonzero, enable single app mode */
1423 if (xevent.xbutton.y < g_win_button_size)
1424 {
1425 /* Stop moving window when button is released, regardless of cursor position */
1426 if (g_moving_wnd && (xevent.type == ButtonRelease))
1427 g_moving_wnd = False;
1428
1429 /* Check from right to left: */
1430
1431 if (xevent.xbutton.x >= g_width - g_win_button_size)
1432 {
1433 /* The close button, continue */
1434 ;
1435 }
1436 else if (xevent.xbutton.x >=
1437 g_width - g_win_button_size * 2)
1438 {
1439 /* The maximize/restore button. Do not send to
1440 server. It might be a good idea to change the
1441 cursor or give some other visible indication
1442 that rdesktop inhibited this click */
1443 break;
1444 }
1445 else if (xevent.xbutton.x >=
1446 g_width - g_win_button_size * 3)
1447 {
1448 /* The minimize button. Iconify window. */
1449 XIconifyWindow(g_display, g_wnd,
1450 DefaultScreen(g_display));
1451 break;
1452 }
1453 else if (xevent.xbutton.x <= g_win_button_size)
1454 {
1455 /* The system menu. Ignore. */
1456 break;
1457 }
1458 else
1459 {
1460 /* The title bar. */
1461 if ((xevent.type == ButtonPress) && !g_fullscreen
1462 && g_hide_decorations)
1463 {
1464 g_moving_wnd = True;
1465 g_move_x_offset = xevent.xbutton.x;
1466 g_move_y_offset = xevent.xbutton.y;
1467 }
1468 break;
1469
1470 }
1471 }
1472
1473 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1474 flags | button, xevent.xbutton.x, xevent.xbutton.y);
1475 break;
1476
1477 case MotionNotify:
1478 if (g_moving_wnd)
1479 {
1480 XMoveWindow(g_display, g_wnd,
1481 xevent.xmotion.x_root - g_move_x_offset,
1482 xevent.xmotion.y_root - g_move_y_offset);
1483 break;
1484 }
1485
1486 if (g_fullscreen && !g_focused)
1487 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1488 CurrentTime);
1489 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1490 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1491 break;
1492
1493 case FocusIn:
1494 if (xevent.xfocus.mode == NotifyGrab)
1495 break;
1496 g_focused = True;
1497 reset_modifier_keys();
1498 if (g_grab_keyboard && g_mouse_in_wnd)
1499 XGrabKeyboard(g_display, g_wnd, True,
1500 GrabModeAsync, GrabModeAsync, CurrentTime);
1501 break;
1502
1503 case FocusOut:
1504 if (xevent.xfocus.mode == NotifyUngrab)
1505 break;
1506 g_focused = False;
1507 if (xevent.xfocus.mode == NotifyWhileGrabbed)
1508 XUngrabKeyboard(g_display, CurrentTime);
1509 break;
1510
1511 case EnterNotify:
1512 /* we only register for this event when in fullscreen mode */
1513 /* or grab_keyboard */
1514 g_mouse_in_wnd = True;
1515 if (g_fullscreen)
1516 {
1517 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1518 CurrentTime);
1519 break;
1520 }
1521 if (g_focused)
1522 XGrabKeyboard(g_display, g_wnd, True,
1523 GrabModeAsync, GrabModeAsync, CurrentTime);
1524 break;
1525
1526 case LeaveNotify:
1527 /* we only register for this event when grab_keyboard */
1528 g_mouse_in_wnd = False;
1529 XUngrabKeyboard(g_display, CurrentTime);
1530 break;
1531
1532 case Expose:
1533 XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1534 xevent.xexpose.x, xevent.xexpose.y,
1535 xevent.xexpose.width,
1536 xevent.xexpose.height,
1537 xevent.xexpose.x, xevent.xexpose.y);
1538 break;
1539
1540 case MappingNotify:
1541 /* Refresh keyboard mapping if it has changed. This is important for
1542 Xvnc, since it allocates keycodes dynamically */
1543 if (xevent.xmapping.request == MappingKeyboard
1544 || xevent.xmapping.request == MappingModifier)
1545 XRefreshKeyboardMapping(&xevent.xmapping);
1546
1547 if (xevent.xmapping.request == MappingModifier)
1548 {
1549 XFreeModifiermap(g_mod_map);
1550 g_mod_map = XGetModifierMapping(g_display);
1551 }
1552 break;
1553
1554 /* clipboard stuff */
1555 case SelectionNotify:
1556 xclip_handle_SelectionNotify(&xevent.xselection);
1557 break;
1558 case SelectionRequest:
1559 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1560 break;
1561 case SelectionClear:
1562 xclip_handle_SelectionClear();
1563 break;
1564 case PropertyNotify:
1565 xclip_handle_PropertyNotify(&xevent.xproperty);
1566 break;
1567 }
1568 }
1569 /* Keep going */
1570 return 1;
1571 }
1572
1573 /* Returns 0 after user quit, 1 otherwise */
1574 int
1575 ui_select(int rdp_socket)
1576 {
1577 int n;
1578 fd_set rfds, wfds;
1579 struct timeval tv;
1580 BOOL s_timeout = False;
1581
1582 while (True)
1583 {
1584 n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1585 /* Process any events already waiting */
1586 if (!xwin_process_events())
1587 /* User quit */
1588 return 0;
1589
1590 FD_ZERO(&rfds);
1591 FD_ZERO(&wfds);
1592 FD_SET(rdp_socket, &rfds);
1593 FD_SET(g_x_socket, &rfds);
1594
1595 #ifdef WITH_RDPSND
1596 /* FIXME: there should be an API for registering fds */
1597 if (g_dsp_busy)
1598 {
1599 FD_SET(g_dsp_fd, &wfds);
1600 n = (g_dsp_fd > n) ? g_dsp_fd : n;
1601 }
1602 #endif
1603 /* default timeout */
1604 tv.tv_sec = 60;
1605 tv.tv_usec = 0;
1606
1607 /* add redirection handles */
1608 rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1609
1610 n++;
1611
1612 switch (select(n, &rfds, &wfds, NULL, &tv))
1613 {
1614 case -1:
1615 error("select: %s\n", strerror(errno));
1616
1617 case 0:
1618 /* Abort serial read calls */
1619 if (s_timeout)
1620 rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1621 continue;
1622 }
1623
1624 rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
1625
1626 if (FD_ISSET(rdp_socket, &rfds))
1627 return 1;
1628
1629 #ifdef WITH_RDPSND
1630 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1631 wave_out_play();
1632 #endif
1633 }
1634 }
1635
1636 void
1637 ui_move_pointer(int x, int y)
1638 {
1639 XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1640 }
1641
1642 HBITMAP
1643 ui_create_bitmap(int width, int height, uint8 * data)
1644 {
1645 XImage *image;
1646 Pixmap bitmap;
1647 uint8 *tdata;
1648 int bitmap_pad;
1649
1650 if (g_server_bpp == 8)
1651 {
1652 bitmap_pad = 8;
1653 }
1654 else
1655 {
1656 bitmap_pad = g_bpp;
1657
1658 if (g_bpp == 24)
1659 bitmap_pad = 32;
1660 }
1661
1662 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1663 bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1664 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1665 (char *) tdata, width, height, bitmap_pad, 0);
1666
1667 XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
1668
1669 XFree(image);
1670 if (tdata != data)
1671 xfree(tdata);
1672 return (HBITMAP) bitmap;
1673 }
1674
1675 void
1676 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1677 {
1678 XImage *image;
1679 uint8 *tdata;
1680 int bitmap_pad;
1681
1682 if (g_server_bpp == 8)
1683 {
1684 bitmap_pad = 8;
1685 }
1686 else
1687 {
1688 bitmap_pad = g_bpp;
1689
1690 if (g_bpp == 24)
1691 bitmap_pad = 32;
1692 }
1693
1694 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1695 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1696 (char *) tdata, width, height, bitmap_pad, 0);
1697
1698 if (g_ownbackstore)
1699 {
1700 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1701 XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1702 }
1703 else
1704 {
1705 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1706 }
1707
1708 XFree(image);
1709 if (tdata != data)
1710 xfree(tdata);
1711 }
1712
1713 void
1714 ui_destroy_bitmap(HBITMAP bmp)
1715 {
1716 XFreePixmap(g_display, (Pixmap) bmp);
1717 }
1718
1719 HGLYPH
1720 ui_create_glyph(int width, int height, uint8 * data)
1721 {
1722 XImage *image;
1723 Pixmap bitmap;
1724 int scanline;
1725
1726 scanline = (width + 7) / 8;
1727
1728 bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1729 if (g_create_glyph_gc == 0)
1730 g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1731
1732 image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1733 width, height, 8, scanline);
1734 image->byte_order = MSBFirst;
1735 image->bitmap_bit_order = MSBFirst;
1736 XInitImage(image);
1737
1738 XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
1739
1740 XFree(image);
1741 return (HGLYPH) bitmap;
1742 }
1743
1744 void
1745 ui_destroy_glyph(HGLYPH glyph)
1746 {
1747 XFreePixmap(g_display, (Pixmap) glyph);
1748 }
1749
1750 HCURSOR
1751 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1752 uint8 * andmask, uint8 * xormask)
1753 {
1754 HGLYPH maskglyph, cursorglyph;
1755 XColor bg, fg;
1756 Cursor xcursor;
1757 uint8 *cursor, *pcursor;
1758 uint8 *mask, *pmask;
1759 uint8 nextbit;
1760 int scanline, offset;
1761 int i, j;
1762
1763 scanline = (width + 7) / 8;
1764 offset = scanline * height;
1765
1766 cursor = (uint8 *) xmalloc(offset);
1767 memset(cursor, 0, offset);
1768
1769 mask = (uint8 *) xmalloc(offset);
1770 memset(mask, 0, offset);
1771
1772 /* approximate AND and XOR masks with a monochrome X pointer */
1773 for (i = 0; i < height; i++)
1774 {
1775 offset -= scanline;
1776 pcursor = &cursor[offset];
1777 pmask = &mask[offset];
1778
1779 for (j = 0; j < scanline; j++)
1780 {
1781 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1782 {
1783 if (xormask[0] || xormask[1] || xormask[2])
1784 {
1785 *pcursor |= (~(*andmask) & nextbit);
1786 *pmask |= nextbit;
1787 }
1788 else
1789 {
1790 *pcursor |= ((*andmask) & nextbit);
1791 *pmask |= (~(*andmask) & nextbit);
1792 }
1793
1794 xormask += 3;
1795 }
1796
1797 andmask++;
1798 pcursor++;
1799 pmask++;
1800 }
1801 }
1802
1803 fg.red = fg.blue = fg.green = 0xffff;
1804 bg.red = bg.blue = bg.green = 0x0000;
1805 fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1806
1807 cursorglyph = ui_create_glyph(width, height, cursor);
1808 maskglyph = ui_create_glyph(width, height, mask);
1809
1810 xcursor =
1811 XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1812 (Pixmap) maskglyph, &fg, &bg, x, y);
1813
1814 ui_destroy_glyph(maskglyph);
1815 ui_destroy_glyph(cursorglyph);
1816 xfree(mask);
1817 xfree(cursor);
1818 return (HCURSOR) xcursor;
1819 }
1820
1821 void
1822 ui_set_cursor(HCURSOR cursor)
1823 {
1824 g_current_cursor = (Cursor) cursor;
1825 XDefineCursor(g_display, g_wnd, g_current_cursor);
1826 }
1827
1828 void
1829 ui_destroy_cursor(HCURSOR cursor)
1830 {
1831 XFreeCursor(g_display, (Cursor) cursor);
1832 }
1833
1834 void
1835 ui_set_null_cursor(void)
1836 {
1837 ui_set_cursor(g_null_cursor);
1838 }
1839
1840 #define MAKE_XCOLOR(xc,c) \
1841 (xc)->red = ((c)->red << 8) | (c)->red; \
1842 (xc)->green = ((c)->green << 8) | (c)->green; \
1843 (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1844 (xc)->flags = DoRed | DoGreen | DoBlue;
1845
1846
1847 HCOLOURMAP
1848 ui_create_colourmap(COLOURMAP * colours)
1849 {
1850 COLOURENTRY *entry;
1851 int i, ncolours = colours->ncolours;
1852 if (!g_owncolmap)
1853 {
1854 uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1855 XColor xentry;
1856 XColor xc_cache[256];
1857 uint32 colour;
1858 int colLookup = 256;
1859 for (i = 0; i < ncolours; i++)
1860 {
1861 entry = &colours->colours[i];
1862 MAKE_XCOLOR(&xentry, entry);
1863
1864 if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1865 {
1866 /* Allocation failed, find closest match. */
1867 int j = 256;
1868 int nMinDist = 3 * 256 * 256;
1869 long nDist = nMinDist;
1870
1871 /* only get the colors once */
1872 while (colLookup--)
1873 {
1874 xc_cache[colLookup].pixel = colLookup;
1875 xc_cache[colLookup].red = xc_cache[colLookup].green =
1876 xc_cache[colLookup].blue = 0;
1877 xc_cache[colLookup].flags = 0;
1878 XQueryColor(g_display,
1879 DefaultColormap(g_display,
1880 DefaultScreen(g_display)),
1881 &xc_cache[colLookup]);
1882 }
1883 colLookup = 0;
1884
1885 /* approximate the pixel */
1886 while (j--)
1887 {
1888 if (xc_cache[j].flags)
1889 {
1890 nDist = ((long) (xc_cache[j].red >> 8) -
1891 (long) (xentry.red >> 8)) *
1892 ((long) (xc_cache[j].red >> 8) -
1893 (long) (xentry.red >> 8)) +
1894 ((long) (xc_cache[j].green >> 8) -
1895 (long) (xentry.green >> 8)) *
1896 ((long) (xc_cache[j].green >> 8) -
1897 (long) (xentry.green >> 8)) +
1898 ((long) (xc_cache[j].blue >> 8) -
1899 (long) (xentry.blue >> 8)) *
1900 ((long) (xc_cache[j].blue >> 8) -
1901 (long) (xentry.blue >> 8));
1902 }
1903 if (nDist < nMinDist)
1904 {
1905 nMinDist = nDist;
1906 xentry.pixel = j;
1907 }
1908 }
1909 }
1910 colour = xentry.pixel;
1911
1912 /* update our cache */
1913 if (xentry.pixel < 256)
1914 {
1915 xc_cache[xentry.pixel].red = xentry.red;
1916 xc_cache[xentry.pixel].green = xentry.green;
1917 xc_cache[xentry.pixel].blue = xentry.blue;
1918
1919 }
1920
1921 map[i] = colour;
1922 }
1923 return map;
1924 }
1925 else
1926 {
1927 XColor *xcolours, *xentry;
1928 Colormap map;
1929
1930 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1931 for (i = 0; i < ncolours; i++)
1932 {
1933 entry = &colours->colours[i];
1934 xentry = &xcolours[i];
1935 xentry->pixel = i;
1936 MAKE_XCOLOR(xentry, entry);
1937 }
1938
1939 map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1940 XStoreColors(g_display, map, xcolours, ncolours);
1941
1942 xfree(xcolours);
1943 return (HCOLOURMAP) map;
1944 }
1945 }
1946
1947 void
1948 ui_destroy_colourmap(HCOLOURMAP map)
1949 {
1950 if (!g_owncolmap)
1951 xfree(map);
1952 else
1953 XFreeColormap(g_display, (Colormap) map);
1954 }
1955
1956 void
1957 ui_set_colourmap(HCOLOURMAP map)
1958 {
1959 if (!g_owncolmap)
1960 {
1961 if (g_colmap)
1962 xfree(g_colmap);
1963
1964 g_colmap = (uint32 *) map;
1965 }
1966 else
1967 XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1968 }
1969
1970 void
1971 ui_set_clip(int x, int y, int cx, int cy)
1972 {
1973 XRectangle rect;
1974
1975 rect.x = x;
1976 rect.y = y;
1977 rect.width = cx;
1978 rect.height = cy;
1979 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1980 }
1981
1982 void
1983 ui_reset_clip(void)
1984 {
1985 XRectangle rect;
1986
1987 rect.x = 0;
1988 rect.y = 0;
1989 rect.width = g_width;
1990 rect.height = g_height;
1991 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1992 }
1993
1994 void
1995 ui_bell(void)
1996 {
1997 XBell(g_display, 0);
1998 }
1999
2000 void
2001 ui_destblt(uint8 opcode,
2002 /* dest */ int x, int y, int cx, int cy)
2003 {
2004 SET_FUNCTION(opcode);
2005 FILL_RECTANGLE(x, y, cx, cy);
2006 RESET_FUNCTION(opcode);
2007 }
2008
2009 static uint8 hatch_patterns[] = {
2010 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
2011 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
2012 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
2013 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
2014 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
2015 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
2016 };
2017
2018 void
2019 ui_patblt(uint8 opcode,
2020 /* dest */ int x, int y, int cx, int cy,
2021 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2022 {
2023 Pixmap fill;
2024 uint8 i, ipattern[8];
2025
2026 SET_FUNCTION(opcode);
2027
2028 switch (brush->style)
2029 {
2030 case 0: /* Solid */
2031 SET_FOREGROUND(fgcolour);
2032 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2033 break;
2034
2035 case 2: /* Hatch */
2036 fill = (Pixmap) ui_create_glyph(8, 8,
2037 hatch_patterns + brush->pattern[0] * 8);
2038 SET_FOREGROUND(fgcolour);
2039 SET_BACKGROUND(bgcolour);
2040 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2041 XSetStipple(g_display, g_gc, fill);
2042 XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2043 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2044 XSetFillStyle(g_display, g_gc, FillSolid);
2045 XSetTSOrigin(g_display, g_gc, 0, 0);
2046 ui_destroy_glyph((HGLYPH) fill);
2047 break;
2048
2049 case 3: /* Pattern */
2050 for (i = 0; i != 8; i++)
2051 ipattern[7 - i] = brush->pattern[i];
2052 fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2053 SET_FOREGROUND(bgcolour);
2054 SET_BACKGROUND(fgcolour);
2055 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2056 XSetStipple(g_display, g_gc, fill);
2057 XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2058 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2059 XSetFillStyle(g_display, g_gc, FillSolid);
2060 XSetTSOrigin(g_display, g_gc, 0, 0);
2061 ui_destroy_glyph((HGLYPH) fill);
2062 break;
2063
2064 default:
2065 unimpl("brush %d\n", brush->style);
2066 }
2067
2068 RESET_FUNCTION(opcode);
2069
2070 if (g_ownbackstore)
2071 XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2072 }
2073
2074 void
2075 ui_screenblt(uint8 opcode,
2076 /* dest */ int x, int y, int cx, int cy,
2077 /* src */ int srcx, int srcy)
2078 {
2079 SET_FUNCTION(opcode);
2080 if (g_ownbackstore)
2081 {
2082 if (g_Unobscured)
2083 {
2084 XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2085 XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2086 y);
2087 }
2088 else
2089 {
2090 XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2091 XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2092 y);
2093 }
2094 }
2095 else
2096 {
2097 XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2098 }
2099 RESET_FUNCTION(opcode);
2100 }
2101
2102 void
2103 ui_memblt(uint8 opcode,
2104 /* dest */ int x, int y, int cx, int cy,
2105 /* src */ HBITMAP src, int srcx, int srcy)
2106 {
2107 SET_FUNCTION(opcode);
2108 XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2109 if (g_ownbackstore)
2110 XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2111 RESET_FUNCTION(opcode);
2112 }
2113
2114 void
2115 ui_triblt(uint8 opcode,
2116 /* dest */ int x, int y, int cx, int cy,
2117 /* src */ HBITMAP src, int srcx, int srcy,
2118 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2119 {
2120 /* This is potentially difficult to do in general. Until someone
2121 comes up with a more efficient way of doing it I am using cases. */
2122
2123 switch (opcode)
2124 {
2125 case 0x69: /* PDSxxn */
2126 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
2127 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
2128 break;
2129
2130 case 0xb8: /* PSDPxax */
2131 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
2132 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
2133 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
2134 break;
2135
2136 case 0xc0: /* PSa */
2137 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2138 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
2139 break;
2140
2141 default:
2142 unimpl("triblt 0x%x\n", opcode);
2143 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2144 }
2145 }
2146
2147 void
2148 ui_line(uint8 opcode,
2149 /* dest */ int startx, int starty, int endx, int endy,
2150 /* pen */ PEN * pen)
2151 {
2152 SET_FUNCTION(opcode);
2153 SET_FOREGROUND(pen->colour);
2154 XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2155 if (g_ownbackstore)
2156 XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2157 RESET_FUNCTION(opcode);
2158 }
2159
2160 void
2161 ui_rect(
2162 /* dest */ int x, int y, int cx, int cy,
2163 /* brush */ int colour)
2164 {
2165 SET_FOREGROUND(colour);
2166 FILL_RECTANGLE(x, y, cx, cy);
2167 }
2168
2169 /* warning, this function only draws on wnd or backstore, not both */
2170 void
2171 ui_draw_glyph(int mixmode,
2172 /* dest */ int x, int y, int cx, int cy,
2173 /* src */ HGLYPH glyph, int srcx, int srcy,
2174 int bgcolour, int fgcolour)
2175 {
2176 SET_FOREGROUND(fgcolour);
2177 SET_BACKGROUND(bgcolour);
2178
2179 XSetFillStyle(g_display, g_gc,
2180 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2181 XSetStipple(g_display, g_gc, (Pixmap) glyph);
2182 XSetTSOrigin(g_display, g_gc, x, y);
2183
2184 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2185
2186 XSetFillStyle(g_display, g_gc, FillSolid);
2187 }
2188
2189 #define DO_GLYPH(ttext,idx) \
2190 {\
2191 glyph = cache_get_font (font, ttext[idx]);\
2192 if (!(flags & TEXT2_IMPLICIT_X))\
2193 {\
2194 xyoffset = ttext[++idx];\
2195 if ((xyoffset & 0x80))\
2196 {\
2197 if (flags & TEXT2_VERTICAL)\
2198 y += ttext[idx+1] | (ttext[idx+2] << 8);\
2199 else\
2200 x += ttext[idx+1] | (ttext[idx+2] << 8);\
2201 idx += 2;\
2202 }\
2203 else\
2204 {\
2205 if (flags & TEXT2_VERTICAL)\
2206 y += xyoffset;\
2207 else\
2208 x += xyoffset;\
2209 }\
2210 }\
2211 if (glyph != NULL)\
2212 {\
2213 x1 = x + glyph->offset;\
2214 y1 = y + glyph->baseline;\
2215 XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2216 XSetTSOrigin(g_display, g_gc, x1, y1);\
2217 FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2218 if (flags & TEXT2_IMPLICIT_X)\
2219 x += glyph->width;\
2220 }\
2221 }
2222
2223 void
2224 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
2225 int clipx, int clipy, int clipcx, int clipcy,
2226 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
2227 int fgcolour, uint8 * text, uint8 length)
2228 {
2229 FONTGLYPH *glyph;
2230 int i, j, xyoffset, x1, y1;
2231 DATABLOB *entry;
2232
2233 SET_FOREGROUND(bgcolour);
2234
2235 /* Sometimes, the boxcx value is something really large, like
2236 32691. This makes XCopyArea fail with Xvnc. The code below
2237 is a quick fix. */
2238 if (boxx + boxcx > g_width)
2239 boxcx = g_width - boxx;
2240
2241 if (boxcx > 1)
2242 {
2243 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2244 }
2245 else if (mixmode == MIX_OPAQUE)
2246 {
2247 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2248 }
2249
2250 SET_FOREGROUND(fgcolour);
2251 SET_BACKGROUND(bgcolour);
2252 XSetFillStyle(g_display, g_gc, FillStippled);
2253
2254 /* Paint text, character by character */
2255 for (i = 0; i < length;)
2256 {
2257 switch (text[i])
2258 {
2259 case 0xff:
2260 if (i + 2 < length)
2261 cache_put_text(text[i + 1], text, text[i + 2]);
2262 else
2263 {
2264 error("this shouldn't be happening\n");
2265 exit(1);
2266 }
2267 /* this will move pointer from start to first character after FF command */
2268 length -= i + 3;
2269 text = &(text[i + 3]);
2270 i = 0;
2271 break;
2272
2273 case 0xfe:
2274 entry = cache_get_text(text[i + 1]);
2275 if (entry != NULL)
2276 {
2277 if ((((uint8 *) (entry->data))[1] ==
2278 0) && (!(flags & TEXT2_IMPLICIT_X)))
2279 {
2280 if (flags & TEXT2_VERTICAL)
2281 y += text[i + 2];
2282 else
2283 x += text[i + 2];
2284 }
2285 for (j = 0; j < entry->size; j++)
2286 DO_GLYPH(((uint8 *) (entry->data)), j);
2287 }
2288 if (i + 2 < length)
2289 i += 3;
2290 else
2291 i += 2;
2292 length -= i;
2293 /* this will move pointer from start to first character after FE command */
2294 text = &(text[i]);
2295 i = 0;
2296 break;
2297
2298 default:
2299 DO_GLYPH(text, i);
2300 i++;
2301 break;
2302 }
2303 }
2304
2305 XSetFillStyle(g_display, g_gc, FillSolid);
2306
2307 if (g_ownbackstore)
2308 {
2309 if (boxcx > 1)
2310 XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2311 boxy, boxcx, boxcy, boxx, boxy);
2312 else
2313 XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2314 clipy, clipcx, clipcy, clipx, clipy);
2315 }
2316 }
2317
2318 void
2319 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
2320 {
2321 Pixmap pix;
2322 XImage *image;
2323
2324 if (g_ownbackstore)
2325 {
2326 image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
2327 }
2328 else
2329 {
2330 pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2331 XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
2332 image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2333 XFreePixmap(g_display, pix);
2334 }
2335
2336 offset *= g_bpp / 8;
2337 cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
2338
2339 XDestroyImage(image);
2340 }
2341
2342 void
2343 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
2344 {
2345 XImage *image;
2346 uint8 *data;
2347
2348 offset *= g_bpp / 8;
2349 data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2350 if (data == NULL)
2351 return;
2352
2353 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2354 (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
2355
2356 if (g_ownbackstore)
2357 {
2358 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2359 XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2360 }
2361 else
2362 {
2363 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2364 }
2365
2366 XFree(image);
2367 }
2368
2369 /* these do nothing here but are used in uiports */
2370 void
2371 ui_begin_update(void)
2372 {
2373 }
2374
2375 void
2376 ui_end_update(void)
2377 {
2378 }

  ViewVC Help
Powered by ViewVC 1.1.26