/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 867 - (hide annotations)
Wed Mar 23 12:25:54 2005 UTC (19 years, 1 month ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 56620 byte(s)
Window-placement patch by <gregmhughes@comcast.net>
small modifications by me, to only set the PPosition sizehint, if the
position was specified on the command-line

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

  ViewVC Help
Powered by ViewVC 1.1.26