/[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 541 - (hide annotations)
Sun Nov 2 16:43:29 2003 UTC (20 years, 6 months ago) by stargo
File MIME type: text/plain
File size: 43540 byte(s)
Fix crash bug when toggling fullscreen-mode with fancy cursors.
Do no longer destroy the global null_cursor, when destroying the
current window.

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

  ViewVC Help
Powered by ViewVC 1.1.26