/[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 831 - (show annotations)
Tue Mar 8 00:43:10 2005 UTC (19 years, 2 months ago) by jdmeijer
File MIME type: text/plain
File size: 55816 byte(s)
Add support for ellipse and polygon orders

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

  ViewVC Help
Powered by ViewVC 1.1.26