/[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 617 - (hide annotations)
Wed Feb 25 18:28:52 2004 UTC (20 years, 2 months ago) by jsorg71
File MIME type: text/plain
File size: 44929 byte(s)
optimize split_colour15 and 16

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

  ViewVC Help
Powered by ViewVC 1.1.26