/[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 576 - (hide annotations)
Thu Jan 22 20:31:59 2004 UTC (20 years, 3 months ago) by stargo
File MIME type: text/plain
File size: 44454 byte(s)
fix g_null_pointer memleak
fixes for compiles on NetBSD & FreeBSD

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

  ViewVC Help
Powered by ViewVC 1.1.26