/[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

Annotation of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 547 - (hide annotations)
Mon Nov 10 15:09:49 2003 UTC (20 years, 6 months ago) by astrand
File MIME type: text/plain
File size: 43297 byte(s)
When mixing -f and -g, the last option should take precedence.

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

  ViewVC Help
Powered by ViewVC 1.1.26