/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 534 - (hide annotations)
Thu Oct 30 00:10:32 2003 UTC (20 years, 6 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 43530 byte(s)
translate24to{24,32} were not using make/split-colour which makes
them unuseable on BE RGB-Displays of this depth...
This should fix it.

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

  ViewVC Help
Powered by ViewVC 1.1.26