/[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 528 - (hide annotations)
Wed Oct 29 08:37:20 2003 UTC (20 years, 6 months ago) by matthewc
File MIME type: text/plain
File size: 43055 byte(s)
Fix translate16to16 along the lines of all the other translate functions.

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

  ViewVC Help
Powered by ViewVC 1.1.26