/[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 566 - (hide annotations)
Mon Jan 19 23:45:26 2004 UTC (20 years, 4 months ago) by stargo
File MIME type: text/plain
File size: 44502 byte(s)
fix g_gc memleak

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

  ViewVC Help
Powered by ViewVC 1.1.26