/[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 536 - (hide annotations)
Fri Oct 31 04:29:57 2003 UTC (20 years, 6 months ago) by matthewc
File MIME type: text/plain
File size: 43556 byte(s)
Fix compile warnings on HP-UX.

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 matthewc 121 BOOL
853 matthewc 192 ui_create_window(void)
854 matty 6 {
855 matthewc 536 uint8 null_pointer_mask[1] = { 0x80 };
856     uint8 null_pointer_data[4] = { 0x00, 0x00, 0x00, 0x00 };
857 matthewc 121 XSetWindowAttributes attribs;
858 matty 28 XClassHint *classhints;
859     XSizeHints *sizehints;
860 matthewc 188 int wndwidth, wndheight;
861 matthewc 432 long input_mask, ic_input_mask;
862 jsorg71 100 XEvent xevent;
863    
864 jsorg71 450 wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
865     wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
866 matthewc 188
867 jsorg71 450 attribs.background_pixel = BlackPixelOfScreen(g_screen);
868     attribs.backing_store = g_ownbackstore ? NotUseful : Always;
869 jsorg71 447 attribs.override_redirect = g_fullscreen;
870 matthewc 188
871 jsorg71 450 g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
872 astrand 456 0, CopyFromParent, InputOutput, CopyFromParent,
873     CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
874 jsorg71 100
875 jsorg71 450 XStoreName(g_display, g_wnd, g_title);
876 jsorg71 100
877 jsorg71 450 if (g_hide_decorations)
878 astrand 262 mwm_hide_decorations();
879    
880 jsorg71 100 classhints = XAllocClassHint();
881     if (classhints != NULL)
882     {
883     classhints->res_name = classhints->res_class = "rdesktop";
884 jsorg71 450 XSetClassHint(g_display, g_wnd, classhints);
885 jsorg71 100 XFree(classhints);
886     }
887    
888     sizehints = XAllocSizeHints();
889     if (sizehints)
890     {
891     sizehints->flags = PMinSize | PMaxSize;
892 jsorg71 447 sizehints->min_width = sizehints->max_width = g_width;
893     sizehints->min_height = sizehints->max_height = g_height;
894 jsorg71 450 XSetWMNormalHints(g_display, g_wnd, sizehints);
895 jsorg71 100 XFree(sizehints);
896     }
897    
898 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
899 jsorg71 257 VisibilityChangeMask | FocusChangeMask;
900 matthewc 121
901 jsorg71 447 if (g_sendmotion)
902 matthewc 121 input_mask |= PointerMotionMask;
903 jsorg71 450 if (g_ownbackstore)
904 matthewc 121 input_mask |= ExposureMask;
905 jsorg71 450 if (g_fullscreen || g_grab_keyboard)
906 matthewc 250 input_mask |= EnterWindowMask;
907 jsorg71 450 if (g_grab_keyboard)
908 jsorg71 257 input_mask |= LeaveWindowMask;
909 jsorg71 100
910 jsorg71 450 if (g_IM != NULL)
911 matthewc 188 {
912 jsorg71 450 g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
913 astrand 456 XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
914 matthewc 188
915 jsorg71 450 if ((g_IC != NULL)
916     && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
917 matthewc 188 input_mask |= ic_input_mask;
918     }
919    
920 jsorg71 450 XSelectInput(g_display, g_wnd, input_mask);
921     XMapWindow(g_display, g_wnd);
922 jsorg71 100
923 matthewc 208 /* wait for VisibilityNotify */
924 astrand 196 do
925     {
926 jsorg71 450 XMaskEvent(g_display, VisibilityChangeMask, &xevent);
927 astrand 196 }
928 matthewc 208 while (xevent.type != VisibilityNotify);
929 matthewc 123
930 jsorg71 447 g_focused = False;
931     g_mouse_in_wnd = False;
932 jsorg71 257
933 astrand 275 /* handle the WM_DELETE_WINDOW protocol */
934 jsorg71 450 g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
935     g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
936     XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
937 astrand 275
938 astrand 508 /* create invisible 1x1 cursor to be used as null cursor */
939 matthewc 536 g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
940 astrand 508
941 matty 10 return True;
942 matty 6 }
943    
944 matty 25 void
945 matthewc 192 ui_destroy_window(void)
946 matty 6 {
947 astrand 508 ui_destroy_cursor(g_null_cursor);
948 astrand 532
949 jsorg71 450 if (g_IC != NULL)
950     XDestroyIC(g_IC);
951 matty 31
952 jsorg71 450 XDestroyWindow(g_display, g_wnd);
953 matty 6 }
954    
955 jsorg71 100 void
956 matthewc 192 xwin_toggle_fullscreen(void)
957 jsorg71 100 {
958 matthewc 188 Pixmap contents = 0;
959 matthewc 123
960 jsorg71 450 if (!g_ownbackstore)
961 matthewc 188 {
962     /* need to save contents of window */
963 jsorg71 450 contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
964     XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
965 matthewc 188 }
966    
967     ui_destroy_window();
968 jsorg71 447 g_fullscreen = !g_fullscreen;
969 matthewc 188 ui_create_window();
970 matthewc 123
971 jsorg71 450 XDefineCursor(g_display, g_wnd, g_current_cursor);
972 matthewc 188
973 jsorg71 450 if (!g_ownbackstore)
974 matthewc 188 {
975 jsorg71 450 XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
976     XFreePixmap(g_display, contents);
977 matthewc 188 }
978 jsorg71 100 }
979    
980 jsorg71 447 /* Process all events in Xlib queue
981 astrand 275 Returns 0 after user quit, 1 otherwise */
982     static int
983 matthewc 192 xwin_process_events(void)
984 matty 9 {
985 n-ki 54 XEvent xevent;
986 matthewc 38 KeySym keysym;
987 matthewc 50 uint16 button, flags;
988 matty 10 uint32 ev_time;
989 astrand 66 key_translation tr;
990     char str[256];
991     Status status;
992 matthewc 203 unsigned int state;
993     Window wdummy;
994     int dummy;
995 matty 9
996 jsorg71 450 while (XPending(g_display) > 0)
997 matty 9 {
998 jsorg71 450 XNextEvent(g_display, &xevent);
999 matthewc 123
1000 jsorg71 450 if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1001 astrand 66 {
1002 astrand 84 DEBUG_KBD(("Filtering event\n"));
1003 astrand 66 continue;
1004     }
1005    
1006 matthewc 50 flags = 0;
1007 matty 10
1008 n-ki 54 switch (xevent.type)
1009 matty 9 {
1010 astrand 275 case ClientMessage:
1011     /* the window manager told us to quit */
1012 jsorg71 450 if ((xevent.xclient.message_type == g_protocol_atom)
1013     && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1014 astrand 275 /* Quit */
1015     return 0;
1016     break;
1017    
1018 matty 9 case KeyPress:
1019 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
1020     if (g_IC != NULL)
1021 astrand 66 /* Multi_key compatible version */
1022     {
1023 jsorg71 450 XmbLookupString(g_IC,
1024 astrand 435 &xevent.xkey, str, sizeof(str), &keysym,
1025     &status);
1026 astrand 82 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1027 astrand 66 {
1028 astrand 82 error("XmbLookupString failed with status 0x%x\n",
1029     status);
1030 astrand 66 break;
1031     }
1032     }
1033     else
1034     {
1035     /* Plain old XLookupString */
1036 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1037 astrand 66 XLookupString((XKeyEvent *) & xevent,
1038 astrand 82 str, sizeof(str), &keysym, NULL);
1039 astrand 66 }
1040    
1041 astrand 261 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1042     get_ksname(keysym)));
1043 astrand 66
1044 matthewc 203 ev_time = time(NULL);
1045     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1046 astrand 118 break;
1047    
1048 astrand 66 tr = xkeymap_translate_key(keysym,
1049 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
1050 astrand 69
1051 astrand 66 if (tr.scancode == 0)
1052 n-ki 52 break;
1053    
1054 astrand 470 save_remote_modifiers(tr.scancode);
1055 astrand 115 ensure_remote_modifiers(ev_time, tr);
1056 astrand 449 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1057 astrand 470 restore_remote_modifiers(ev_time, tr.scancode);
1058 astrand 115
1059 astrand 66 break;
1060 matthewc 203
1061 astrand 66 case KeyRelease:
1062 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
1063 astrand 66 XLookupString((XKeyEvent *) & xevent, str,
1064     sizeof(str), &keysym, NULL);
1065 n-ki 52
1066 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1067 matthewc 203 get_ksname(keysym)));
1068 n-ki 52
1069 matthewc 203 ev_time = time(NULL);
1070     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1071 astrand 118 break;
1072    
1073 astrand 66 tr = xkeymap_translate_key(keysym,
1074 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
1075 astrand 66
1076     if (tr.scancode == 0)
1077     break;
1078    
1079 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
1080 matty 9 break;
1081    
1082     case ButtonPress:
1083 matthewc 50 flags = MOUSE_FLAG_DOWN;
1084     /* fall through */
1085 matty 9
1086     case ButtonRelease:
1087 jsorg71 450 g_last_gesturetime = xevent.xbutton.time;
1088 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
1089 matty 9 if (button == 0)
1090     break;
1091    
1092 astrand 328 /* If win_button_size is nonzero, enable single app mode */
1093 jsorg71 450 if (xevent.xbutton.y < g_win_button_size)
1094 astrand 328 {
1095 astrand 342 /* Stop moving window when button is released, regardless of cursor position */
1096 jsorg71 450 if (g_moving_wnd && (xevent.type == ButtonRelease))
1097     g_moving_wnd = False;
1098 astrand 332
1099 astrand 342 /* Check from right to left: */
1100    
1101 jsorg71 450 if (xevent.xbutton.x >= g_width - g_win_button_size)
1102 astrand 328 {
1103 astrand 331 /* The close button, continue */
1104 astrand 328 ;
1105     }
1106 astrand 456 else if (xevent.xbutton.x >=
1107     g_width - g_win_button_size * 2)
1108 astrand 328 {
1109     /* The maximize/restore button. Do not send to
1110     server. It might be a good idea to change the
1111 jsorg71 447 cursor or give some other visible indication
1112 astrand 328 that rdesktop inhibited this click */
1113     break;
1114     }
1115 astrand 456 else if (xevent.xbutton.x >=
1116     g_width - g_win_button_size * 3)
1117 astrand 328 {
1118     /* The minimize button. Iconify window. */
1119 jsorg71 450 XIconifyWindow(g_display, g_wnd,
1120     DefaultScreen(g_display));
1121 astrand 328 break;
1122     }
1123 jsorg71 450 else if (xevent.xbutton.x <= g_win_button_size)
1124 astrand 342 {
1125     /* The system menu. Ignore. */
1126     break;
1127     }
1128 astrand 332 else
1129     {
1130 astrand 342 /* The title bar. */
1131 jsorg71 447 if ((xevent.type == ButtonPress) && !g_fullscreen
1132 jsorg71 450 && g_hide_decorations)
1133 astrand 342 {
1134 jsorg71 450 g_moving_wnd = True;
1135     g_move_x_offset = xevent.xbutton.x;
1136     g_move_y_offset = xevent.xbutton.y;
1137 astrand 342 }
1138 astrand 332 break;
1139 astrand 342
1140 astrand 332 }
1141 astrand 328 }
1142    
1143 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1144 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
1145 matty 10 break;
1146    
1147     case MotionNotify:
1148 jsorg71 450 if (g_moving_wnd)
1149 astrand 342 {
1150 jsorg71 450 XMoveWindow(g_display, g_wnd,
1151     xevent.xmotion.x_root - g_move_x_offset,
1152     xevent.xmotion.y_root - g_move_y_offset);
1153 astrand 342 break;
1154     }
1155    
1156 jsorg71 447 if (g_fullscreen && !g_focused)
1157 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1158 jsorg71 288 CurrentTime);
1159 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1160 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1161 matty 28 break;
1162    
1163 matthewc 194 case FocusIn:
1164 jsorg71 257 if (xevent.xfocus.mode == NotifyGrab)
1165     break;
1166 jsorg71 447 g_focused = True;
1167 jsorg71 450 XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy,
1168 astrand 261 &dummy, &dummy, &state);
1169 matthewc 203 reset_modifier_keys(state);
1170 jsorg71 450 if (g_grab_keyboard && g_mouse_in_wnd)
1171     XGrabKeyboard(g_display, g_wnd, True,
1172 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
1173 matty 28 break;
1174    
1175 matthewc 194 case FocusOut:
1176 jsorg71 257 if (xevent.xfocus.mode == NotifyUngrab)
1177     break;
1178 jsorg71 447 g_focused = False;
1179 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
1180 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1181 matty 28 break;
1182 matty 31
1183 matthewc 250 case EnterNotify:
1184     /* we only register for this event when in fullscreen mode */
1185 jsorg71 257 /* or grab_keyboard */
1186 jsorg71 447 g_mouse_in_wnd = True;
1187     if (g_fullscreen)
1188 jsorg71 257 {
1189 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1190 astrand 261 CurrentTime);
1191 jsorg71 257 break;
1192     }
1193 jsorg71 447 if (g_focused)
1194 jsorg71 450 XGrabKeyboard(g_display, g_wnd, True,
1195 jsorg71 257 GrabModeAsync, GrabModeAsync, CurrentTime);
1196 matthewc 250 break;
1197    
1198 matthewc 253 case LeaveNotify:
1199 jsorg71 257 /* we only register for this event when grab_keyboard */
1200 jsorg71 447 g_mouse_in_wnd = False;
1201 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1202 matthewc 253 break;
1203    
1204 matty 31 case Expose:
1205 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1206 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
1207 astrand 64 xevent.xexpose.width,
1208     xevent.xexpose.height,
1209 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
1210 matty 31 break;
1211 astrand 119
1212     case MappingNotify:
1213     /* Refresh keyboard mapping if it has changed. This is important for
1214     Xvnc, since it allocates keycodes dynamically */
1215     if (xevent.xmapping.request == MappingKeyboard
1216     || xevent.xmapping.request == MappingModifier)
1217     XRefreshKeyboardMapping(&xevent.xmapping);
1218 matthewc 203
1219     if (xevent.xmapping.request == MappingModifier)
1220     {
1221 jsorg71 450 XFreeModifiermap(g_mod_map);
1222     g_mod_map = XGetModifierMapping(g_display);
1223 matthewc 203 }
1224 astrand 119 break;
1225 matthewc 432
1226 astrand 435 /* clipboard stuff */
1227 forsberg 415 case SelectionNotify:
1228 matthewc 432 xclip_handle_SelectionNotify(&xevent.xselection);
1229 forsberg 415 break;
1230     case SelectionRequest:
1231 matthewc 432 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1232 forsberg 415 break;
1233 matthewc 432 case SelectionClear:
1234     xclip_handle_SelectionClear();
1235     break;
1236 forsberg 415 case PropertyNotify:
1237 matthewc 432 xclip_handle_PropertyNotify(&xevent.xproperty);
1238 forsberg 415 break;
1239 matty 9 }
1240     }
1241 astrand 275 /* Keep going */
1242     return 1;
1243 matty 9 }
1244    
1245 astrand 275 /* Returns 0 after user quit, 1 otherwise */
1246     int
1247 matty 33 ui_select(int rdp_socket)
1248     {
1249 jsorg71 450 int n = (rdp_socket > g_x_socket) ? rdp_socket + 1 : g_x_socket + 1;
1250 matthewc 474 fd_set rfds, wfds;
1251 matty 33
1252     while (True)
1253     {
1254 matthewc 121 /* Process any events already waiting */
1255 astrand 275 if (!xwin_process_events())
1256     /* User quit */
1257     return 0;
1258 astrand 119
1259 matty 33 FD_ZERO(&rfds);
1260 matthewc 474 FD_ZERO(&wfds);
1261 matty 33 FD_SET(rdp_socket, &rfds);
1262 jsorg71 450 FD_SET(g_x_socket, &rfds);
1263 matty 33
1264 matthewc 474 #ifdef WITH_RDPSND
1265     /* FIXME: there should be an API for registering fds */
1266 stargo 504 if (g_dsp_busy)
1267 matty 33 {
1268 matthewc 474 FD_SET(g_dsp_fd, &wfds);
1269     n = (g_dsp_fd + 1 > n) ? g_dsp_fd + 1 : n;
1270 astrand 499 }
1271 matthewc 474 #endif
1272    
1273     switch (select(n, &rfds, &wfds, NULL, NULL))
1274     {
1275 matty 33 case -1:
1276     error("select: %s\n", strerror(errno));
1277    
1278     case 0:
1279     continue;
1280     }
1281    
1282     if (FD_ISSET(rdp_socket, &rfds))
1283 astrand 275 return 1;
1284 matthewc 474
1285     #ifdef WITH_RDPSND
1286 stargo 504 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1287 matthewc 474 wave_out_play();
1288     #endif
1289 matty 33 }
1290     }
1291    
1292     void
1293 matty 25 ui_move_pointer(int x, int y)
1294 matty 9 {
1295 jsorg71 450 XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1296 matty 9 }
1297    
1298 matty 25 HBITMAP
1299 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1300 matty 6 {
1301     XImage *image;
1302 matty 9 Pixmap bitmap;
1303 matty 28 uint8 *tdata;
1304 stargo 521 int bitmap_pad;
1305 matty 29
1306 stargo 521 if (g_server_bpp == 8)
1307     {
1308     bitmap_pad = 8;
1309     }
1310     else
1311     {
1312     bitmap_pad = g_bpp;
1313    
1314     if (g_bpp == 24)
1315     bitmap_pad = 32;
1316     }
1317    
1318 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1319     bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1320     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1321 stargo 521 (char *) tdata, width, height, bitmap_pad, 0);
1322 matty 6
1323 jsorg71 450 XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1324 matty 9
1325     XFree(image);
1326 jsorg71 450 if (!g_owncolmap)
1327 n-ki 279 xfree(tdata);
1328 matty 24 return (HBITMAP) bitmap;
1329 matty 6 }
1330    
1331 matty 25 void
1332 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1333 matty 6 {
1334 matty 10 XImage *image;
1335 matty 29 uint8 *tdata;
1336 stargo 521 int bitmap_pad;
1337    
1338     if (g_server_bpp == 8)
1339     {
1340     bitmap_pad = 8;
1341     }
1342     else
1343     {
1344     bitmap_pad = g_bpp;
1345    
1346     if (g_bpp == 24)
1347     bitmap_pad = 32;
1348     }
1349    
1350 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1351     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1352 stargo 521 (char *) tdata, width, height, bitmap_pad, 0);
1353 matty 28
1354 jsorg71 450 if (g_ownbackstore)
1355 matty 31 {
1356 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1357     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1358 matty 31 }
1359     else
1360     {
1361 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1362 matty 31 }
1363 matty 29
1364 matty 24 XFree(image);
1365 jsorg71 450 if (!g_owncolmap)
1366 n-ki 279 xfree(tdata);
1367 matty 6 }
1368    
1369 matty 25 void
1370     ui_destroy_bitmap(HBITMAP bmp)
1371 matty 6 {
1372 jsorg71 450 XFreePixmap(g_display, (Pixmap) bmp);
1373 matty 10 }
1374    
1375 matty 25 HGLYPH
1376 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1377 matty 10 {
1378 matty 9 XImage *image;
1379     Pixmap bitmap;
1380     int scanline;
1381     GC gc;
1382 matty 6
1383 matty 9 scanline = (width + 7) / 8;
1384 matty 6
1385 jsorg71 450 bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1386     gc = XCreateGC(g_display, bitmap, 0, NULL);
1387 matty 9
1388 jsorg71 450 image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1389 astrand 73 width, height, 8, scanline);
1390 matty 23 image->byte_order = MSBFirst;
1391     image->bitmap_bit_order = MSBFirst;
1392     XInitImage(image);
1393    
1394 jsorg71 450 XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1395 matty 29
1396 matty 9 XFree(image);
1397 jsorg71 450 XFreeGC(g_display, gc);
1398 astrand 64 return (HGLYPH) bitmap;
1399 matty 6 }
1400 matty 7
1401 matty 25 void
1402     ui_destroy_glyph(HGLYPH glyph)
1403 matty 7 {
1404 jsorg71 450 XFreePixmap(g_display, (Pixmap) glyph);
1405 matty 9 }
1406    
1407 matty 29 HCURSOR
1408 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1409     uint8 * andmask, uint8 * xormask)
1410 matty 9 {
1411 matty 29 HGLYPH maskglyph, cursorglyph;
1412     XColor bg, fg;
1413     Cursor xcursor;
1414     uint8 *cursor, *pcursor;
1415     uint8 *mask, *pmask;
1416     uint8 nextbit;
1417     int scanline, offset;
1418     int i, j;
1419    
1420     scanline = (width + 7) / 8;
1421     offset = scanline * height;
1422    
1423 forsberg 415 cursor = (uint8 *) xmalloc(offset);
1424 matty 29 memset(cursor, 0, offset);
1425    
1426 forsberg 415 mask = (uint8 *) xmalloc(offset);
1427 matty 29 memset(mask, 0, offset);
1428    
1429     /* approximate AND and XOR masks with a monochrome X pointer */
1430     for (i = 0; i < height; i++)
1431 matty 7 {
1432 matty 29 offset -= scanline;
1433     pcursor = &cursor[offset];
1434     pmask = &mask[offset];
1435    
1436     for (j = 0; j < scanline; j++)
1437 matty 28 {
1438 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1439     {
1440     if (xormask[0] || xormask[1] || xormask[2])
1441     {
1442     *pcursor |= (~(*andmask) & nextbit);
1443     *pmask |= nextbit;
1444     }
1445     else
1446     {
1447     *pcursor |= ((*andmask) & nextbit);
1448     *pmask |= (~(*andmask) & nextbit);
1449     }
1450    
1451     xormask += 3;
1452     }
1453    
1454     andmask++;
1455     pcursor++;
1456     pmask++;
1457 matty 28 }
1458 matty 7 }
1459 matty 29
1460     fg.red = fg.blue = fg.green = 0xffff;
1461     bg.red = bg.blue = bg.green = 0x0000;
1462     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1463    
1464     cursorglyph = ui_create_glyph(width, height, cursor);
1465     maskglyph = ui_create_glyph(width, height, mask);
1466    
1467 astrand 66 xcursor =
1468 jsorg71 450 XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1469 astrand 66 (Pixmap) maskglyph, &fg, &bg, x, y);
1470 astrand 64
1471 matty 29 ui_destroy_glyph(maskglyph);
1472     ui_destroy_glyph(cursorglyph);
1473     xfree(mask);
1474     xfree(cursor);
1475 astrand 64 return (HCURSOR) xcursor;
1476 matty 29 }
1477    
1478     void
1479     ui_set_cursor(HCURSOR cursor)
1480     {
1481 jsorg71 450 g_current_cursor = (Cursor) cursor;
1482     XDefineCursor(g_display, g_wnd, g_current_cursor);
1483 matty 29 }
1484    
1485     void
1486     ui_destroy_cursor(HCURSOR cursor)
1487     {
1488 jsorg71 450 XFreeCursor(g_display, (Cursor) cursor);
1489 matty 29 }
1490    
1491 astrand 508 void
1492     ui_set_null_cursor(void)
1493     {
1494     ui_set_cursor(g_null_cursor);
1495     }
1496    
1497 matty 29 #define MAKE_XCOLOR(xc,c) \
1498     (xc)->red = ((c)->red << 8) | (c)->red; \
1499     (xc)->green = ((c)->green << 8) | (c)->green; \
1500     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1501     (xc)->flags = DoRed | DoGreen | DoBlue;
1502    
1503 n-ki 279
1504 matty 29 HCOLOURMAP
1505 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1506 matty 29 {
1507     COLOURENTRY *entry;
1508     int i, ncolours = colours->ncolours;
1509 jsorg71 450 if (!g_owncolmap)
1510 matty 28 {
1511 jsorg71 450 uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1512 n-ki 279 XColor xentry;
1513     XColor xc_cache[256];
1514     uint32 colour;
1515     int colLookup = 256;
1516     for (i = 0; i < ncolours; i++)
1517 matty 28 {
1518 n-ki 279 entry = &colours->colours[i];
1519     MAKE_XCOLOR(&xentry, entry);
1520 matty 7
1521 jsorg71 450 if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1522 astrand 196 {
1523 n-ki 279 /* Allocation failed, find closest match. */
1524     int j = 256;
1525     int nMinDist = 3 * 256 * 256;
1526     long nDist = nMinDist;
1527 matty 28
1528 n-ki 279 /* only get the colors once */
1529     while (colLookup--)
1530 astrand 196 {
1531 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1532     xc_cache[colLookup].red = xc_cache[colLookup].green =
1533     xc_cache[colLookup].blue = 0;
1534     xc_cache[colLookup].flags = 0;
1535 jsorg71 450 XQueryColor(g_display,
1536     DefaultColormap(g_display,
1537     DefaultScreen(g_display)),
1538 n-ki 279 &xc_cache[colLookup]);
1539 n-ki 185 }
1540 n-ki 279 colLookup = 0;
1541    
1542     /* approximate the pixel */
1543     while (j--)
1544 astrand 196 {
1545 n-ki 279 if (xc_cache[j].flags)
1546     {
1547     nDist = ((long) (xc_cache[j].red >> 8) -
1548     (long) (xentry.red >> 8)) *
1549     ((long) (xc_cache[j].red >> 8) -
1550     (long) (xentry.red >> 8)) +
1551     ((long) (xc_cache[j].green >> 8) -
1552     (long) (xentry.green >> 8)) *
1553     ((long) (xc_cache[j].green >> 8) -
1554     (long) (xentry.green >> 8)) +
1555     ((long) (xc_cache[j].blue >> 8) -
1556     (long) (xentry.blue >> 8)) *
1557     ((long) (xc_cache[j].blue >> 8) -
1558     (long) (xentry.blue >> 8));
1559     }
1560     if (nDist < nMinDist)
1561     {
1562     nMinDist = nDist;
1563     xentry.pixel = j;
1564     }
1565 n-ki 185 }
1566     }
1567 n-ki 279 colour = xentry.pixel;
1568    
1569     /* update our cache */
1570     if (xentry.pixel < 256)
1571     {
1572     xc_cache[xentry.pixel].red = xentry.red;
1573     xc_cache[xentry.pixel].green = xentry.green;
1574     xc_cache[xentry.pixel].blue = xentry.blue;
1575    
1576     }
1577    
1578 matthewc 527 map[i] = colour;
1579 n-ki 185 }
1580 n-ki 279 return map;
1581     }
1582     else
1583     {
1584     XColor *xcolours, *xentry;
1585     Colormap map;
1586 matty 29
1587 forsberg 415 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1588 n-ki 279 for (i = 0; i < ncolours; i++)
1589 astrand 196 {
1590 n-ki 279 entry = &colours->colours[i];
1591     xentry = &xcolours[i];
1592     xentry->pixel = i;
1593     MAKE_XCOLOR(xentry, entry);
1594 matty 29 }
1595    
1596 jsorg71 450 map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1597     XStoreColors(g_display, map, xcolours, ncolours);
1598 n-ki 185
1599 n-ki 279 xfree(xcolours);
1600     return (HCOLOURMAP) map;
1601 matty 29 }
1602 matty 7 }
1603    
1604 matty 25 void
1605     ui_destroy_colourmap(HCOLOURMAP map)
1606 matty 7 {
1607 jsorg71 450 if (!g_owncolmap)
1608 n-ki 279 xfree(map);
1609     else
1610 jsorg71 450 XFreeColormap(g_display, (Colormap) map);
1611 matty 7 }
1612    
1613 matty 25 void
1614     ui_set_colourmap(HCOLOURMAP map)
1615 matty 7 {
1616 jsorg71 450 if (!g_owncolmap)
1617 astrand 448 {
1618 jsorg71 450 if (g_colmap)
1619     xfree(g_colmap);
1620 astrand 448
1621 jsorg71 450 g_colmap = (uint32 *) map;
1622 astrand 448 }
1623 n-ki 279 else
1624 jsorg71 450 XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1625 matty 7 }
1626    
1627 matty 25 void
1628     ui_set_clip(int x, int y, int cx, int cy)
1629 matty 7 {
1630 matty 9 XRectangle rect;
1631 matty 7
1632 matty 9 rect.x = x;
1633     rect.y = y;
1634     rect.width = cx;
1635     rect.height = cy;
1636 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1637 matty 9 }
1638 matty 7
1639 matty 25 void
1640 matthewc 192 ui_reset_clip(void)
1641 matty 9 {
1642     XRectangle rect;
1643    
1644     rect.x = 0;
1645     rect.y = 0;
1646 jsorg71 447 rect.width = g_width;
1647     rect.height = g_height;
1648 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1649 matty 7 }
1650    
1651 matty 25 void
1652 matthewc 192 ui_bell(void)
1653 matty 10 {
1654 jsorg71 450 XBell(g_display, 0);
1655 matty 10 }
1656    
1657 matty 25 void
1658     ui_destblt(uint8 opcode,
1659     /* dest */ int x, int y, int cx, int cy)
1660 matty 9 {
1661 matty 29 SET_FUNCTION(opcode);
1662 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1663 matty 29 RESET_FUNCTION(opcode);
1664 matty 9 }
1665    
1666 jsorg71 373 static uint8 hatch_patterns[] = {
1667 forsberg 415 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1668     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1669     0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1670     0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1671     0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1672     0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
1673 jsorg71 373 };
1674    
1675 matty 25 void
1676     ui_patblt(uint8 opcode,
1677     /* dest */ int x, int y, int cx, int cy,
1678 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1679 matty 9 {
1680     Pixmap fill;
1681 jsorg71 59 uint8 i, ipattern[8];
1682 matty 9
1683 matty 29 SET_FUNCTION(opcode);
1684 matty 9
1685     switch (brush->style)
1686     {
1687 matty 24 case 0: /* Solid */
1688 matty 29 SET_FOREGROUND(fgcolour);
1689 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1690 matty 9 break;
1691    
1692 jsorg71 373 case 2: /* Hatch */
1693 forsberg 415 fill = (Pixmap) ui_create_glyph(8, 8,
1694     hatch_patterns + brush->pattern[0] * 8);
1695 astrand 487 SET_FOREGROUND(fgcolour);
1696     SET_BACKGROUND(bgcolour);
1697 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1698     XSetStipple(g_display, g_gc, fill);
1699     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1700 jsorg71 373 FILL_RECTANGLE(x, y, cx, cy);
1701 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1702     XSetTSOrigin(g_display, g_gc, 0, 0);
1703 jsorg71 373 ui_destroy_glyph((HGLYPH) fill);
1704     break;
1705    
1706 matty 24 case 3: /* Pattern */
1707 jsorg71 59 for (i = 0; i != 8; i++)
1708     ipattern[7 - i] = brush->pattern[i];
1709     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1710 matty 9
1711 matty 29 SET_FOREGROUND(bgcolour);
1712     SET_BACKGROUND(fgcolour);
1713 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1714     XSetStipple(g_display, g_gc, fill);
1715     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1716 matty 9
1717 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1718 matty 9
1719 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1720     XSetTSOrigin(g_display, g_gc, 0, 0);
1721 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1722 matty 9 break;
1723    
1724     default:
1725 matty 30 unimpl("brush %d\n", brush->style);
1726 matty 9 }
1727 matty 29
1728     RESET_FUNCTION(opcode);
1729 matty 9 }
1730    
1731 matty 25 void
1732     ui_screenblt(uint8 opcode,
1733     /* dest */ int x, int y, int cx, int cy,
1734     /* src */ int srcx, int srcy)
1735 matty 9 {
1736 matty 29 SET_FUNCTION(opcode);
1737 jsorg71 450 XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1738     if (g_ownbackstore)
1739     XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1740 matty 29 RESET_FUNCTION(opcode);
1741 matty 9 }
1742    
1743 matty 25 void
1744     ui_memblt(uint8 opcode,
1745     /* dest */ int x, int y, int cx, int cy,
1746     /* src */ HBITMAP src, int srcx, int srcy)
1747 matty 9 {
1748 matty 29 SET_FUNCTION(opcode);
1749 jsorg71 450 XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1750     if (g_ownbackstore)
1751     XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1752 matty 29 RESET_FUNCTION(opcode);
1753 matty 9 }
1754    
1755 matty 25 void
1756     ui_triblt(uint8 opcode,
1757     /* dest */ int x, int y, int cx, int cy,
1758     /* src */ HBITMAP src, int srcx, int srcy,
1759 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1760 matty 9 {
1761     /* This is potentially difficult to do in general. Until someone
1762 matty 10 comes up with a more efficient way of doing it I am using cases. */
1763 matty 9
1764     switch (opcode)
1765     {
1766 matty 24 case 0x69: /* PDSxxn */
1767 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1768 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1769 matty 16 break;
1770    
1771 matty 24 case 0xb8: /* PSDPxax */
1772 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1773 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1774 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1775 matty 9 break;
1776    
1777 matty 29 case 0xc0: /* PSa */
1778 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1779 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1780 matty 28 break;
1781    
1782 matty 9 default:
1783 matty 30 unimpl("triblt 0x%x\n", opcode);
1784 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1785 matty 9 }
1786     }
1787    
1788 matty 25 void
1789     ui_line(uint8 opcode,
1790     /* dest */ int startx, int starty, int endx, int endy,
1791 astrand 64 /* pen */ PEN * pen)
1792 matty 9 {
1793 matty 29 SET_FUNCTION(opcode);
1794     SET_FOREGROUND(pen->colour);
1795 jsorg71 450 XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1796     if (g_ownbackstore)
1797     XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1798 matty 29 RESET_FUNCTION(opcode);
1799 matty 9 }
1800    
1801 matty 25 void
1802     ui_rect(
1803     /* dest */ int x, int y, int cx, int cy,
1804     /* brush */ int colour)
1805 matty 9 {
1806 matty 29 SET_FOREGROUND(colour);
1807 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1808 matty 9 }
1809    
1810 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
1811 matty 25 void
1812     ui_draw_glyph(int mixmode,
1813     /* dest */ int x, int y, int cx, int cy,
1814 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1815     int bgcolour, int fgcolour)
1816 matty 9 {
1817 matty 29 SET_FOREGROUND(fgcolour);
1818     SET_BACKGROUND(bgcolour);
1819 matty 9
1820 jsorg71 450 XSetFillStyle(g_display, g_gc,
1821 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1822 jsorg71 450 XSetStipple(g_display, g_gc, (Pixmap) glyph);
1823     XSetTSOrigin(g_display, g_gc, x, y);
1824 matty 9
1825 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1826 matty 9
1827 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1828 matty 9 }
1829    
1830 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1831     {\
1832     glyph = cache_get_font (font, ttext[idx]);\
1833     if (!(flags & TEXT2_IMPLICIT_X))\
1834     {\
1835     xyoffset = ttext[++idx];\
1836     if ((xyoffset & 0x80))\
1837     {\
1838     if (flags & TEXT2_VERTICAL) \
1839 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1840 mmihalik 49 else\
1841 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1842     idx += 2;\
1843 mmihalik 49 }\
1844     else\
1845     {\
1846     if (flags & TEXT2_VERTICAL) \
1847     y += xyoffset;\
1848     else\
1849     x += xyoffset;\
1850     }\
1851     }\
1852     if (glyph != NULL)\
1853     {\
1854 matthewc 299 ui_draw_glyph (mixmode, x + glyph->offset,\
1855     y + glyph->baseline,\
1856 mmihalik 49 glyph->width, glyph->height,\
1857     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1858     if (flags & TEXT2_IMPLICIT_X)\
1859     x += glyph->width;\
1860     }\
1861     }
1862    
1863 matty 25 void
1864     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1865 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1866     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1867 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1868 matty 9 {
1869 matty 10 FONTGLYPH *glyph;
1870 mmihalik 49 int i, j, xyoffset;
1871     DATABLOB *entry;
1872 matty 9
1873 matty 29 SET_FOREGROUND(bgcolour);
1874 matty 28
1875 matty 9 if (boxcx > 1)
1876 matty 31 {
1877 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1878 matty 31 }
1879 matty 17 else if (mixmode == MIX_OPAQUE)
1880 matty 31 {
1881 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1882 matty 31 }
1883 matty 9
1884     /* Paint text, character by character */
1885 astrand 64 for (i = 0; i < length;)
1886     {
1887     switch (text[i])
1888     {
1889     case 0xff:
1890     if (i + 2 < length)
1891 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1892 astrand 64 else
1893     {
1894     error("this shouldn't be happening\n");
1895 astrand 265 exit(1);
1896 astrand 64 }
1897     /* this will move pointer from start to first character after FF command */
1898     length -= i + 3;
1899     text = &(text[i + 3]);
1900     i = 0;
1901 mmihalik 49 break;
1902 matty 9
1903 astrand 64 case 0xfe:
1904     entry = cache_get_text(text[i + 1]);
1905     if (entry != NULL)
1906     {
1907     if ((((uint8 *) (entry->data))[1] ==
1908 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1909 astrand 64 {
1910     if (flags & TEXT2_VERTICAL)
1911     y += text[i + 2];
1912     else
1913     x += text[i + 2];
1914     }
1915     for (j = 0; j < entry->size; j++)
1916 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1917 matthewc 44 }
1918 jsorg71 286 if (i + 2 < length)
1919     i += 3;
1920     else
1921     i += 2;
1922     length -= i;
1923     /* this will move pointer from start to first character after FE command */
1924     text = &(text[i]);
1925     i = 0;
1926 astrand 64 break;
1927 matty 17
1928 astrand 64 default:
1929     DO_GLYPH(text, i);
1930     i++;
1931     break;
1932 matty 29 }
1933 mmihalik 49 }
1934 jsorg71 450 if (g_ownbackstore)
1935 jsorg71 278 {
1936     if (boxcx > 1)
1937 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
1938 jsorg71 278 boxy, boxcx, boxcy, boxx, boxy);
1939     else
1940 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
1941 jsorg71 278 clipy, clipcx, clipcy, clipx, clipy);
1942     }
1943 matty 9 }
1944    
1945 matty 25 void
1946     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1947 matty 9 {
1948 matty 28 Pixmap pix;
1949 matty 9 XImage *image;
1950    
1951 jsorg71 450 if (g_ownbackstore)
1952 matty 31 {
1953 jsorg71 450 image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1954 matty 31 }
1955     else
1956     {
1957 jsorg71 450 pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
1958     XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
1959     image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1960     XFreePixmap(g_display, pix);
1961 matty 31 }
1962 matty 28
1963 jsorg71 450 offset *= g_bpp / 8;
1964     cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
1965 matty 28
1966     XDestroyImage(image);
1967 matty 9 }
1968    
1969 matty 25 void
1970     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1971 matty 9 {
1972     XImage *image;
1973 matty 10 uint8 *data;
1974 matty 9
1975 jsorg71 450 offset *= g_bpp / 8;
1976     data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
1977 matty 10 if (data == NULL)
1978     return;
1979 matty 29
1980 jsorg71 450 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1981     (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
1982 matty 29
1983 jsorg71 450 if (g_ownbackstore)
1984 matty 31 {
1985 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1986     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1987 matty 31 }
1988     else
1989     {
1990 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1991 matty 31 }
1992    
1993 matty 9 XFree(image);
1994     }

  ViewVC Help
Powered by ViewVC 1.1.26