/[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 887 - (hide annotations)
Sat Apr 16 11:57:19 2005 UTC (19 years, 1 month ago) by stargo
File MIME type: text/plain
File size: 56652 byte(s)
Handle RDP recv queue even in RDP send queue is full.
Patch from James Cameron <james.cameron@hp.com>
This closes Debian Bug #246461.

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 stargo 887 /* Process 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 stargo 887 int events = 0;
1357 matty 9
1358 stargo 887 while ((XPending(g_display) > 0) && events++ < 20)
1359 matty 9 {
1360 jsorg71 450 XNextEvent(g_display, &xevent);
1361 matthewc 123
1362 jsorg71 450 if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1363 astrand 66 {
1364 astrand 84 DEBUG_KBD(("Filtering event\n"));
1365 astrand 66 continue;
1366     }
1367    
1368 matthewc 50 flags = 0;
1369 matty 10
1370 n-ki 54 switch (xevent.type)
1371 matty 9 {
1372 jsorg71 688 case VisibilityNotify:
1373     g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1374     break;
1375 astrand 275 case ClientMessage:
1376     /* the window manager told us to quit */
1377 jsorg71 450 if ((xevent.xclient.message_type == g_protocol_atom)
1378     && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1379 astrand 275 /* Quit */
1380     return 0;
1381     break;
1382    
1383 matty 9 case KeyPress:
1384 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
1385     if (g_IC != NULL)
1386 astrand 66 /* Multi_key compatible version */
1387     {
1388 jsorg71 450 XmbLookupString(g_IC,
1389 astrand 435 &xevent.xkey, str, sizeof(str), &keysym,
1390     &status);
1391 astrand 82 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1392 astrand 66 {
1393 astrand 82 error("XmbLookupString failed with status 0x%x\n",
1394     status);
1395 astrand 66 break;
1396     }
1397     }
1398     else
1399     {
1400     /* Plain old XLookupString */
1401 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1402 astrand 66 XLookupString((XKeyEvent *) & xevent,
1403 astrand 82 str, sizeof(str), &keysym, NULL);
1404 astrand 66 }
1405    
1406 astrand 261 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1407     get_ksname(keysym)));
1408 astrand 66
1409 matthewc 203 ev_time = time(NULL);
1410     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1411 astrand 118 break;
1412    
1413 astrand 66 tr = xkeymap_translate_key(keysym,
1414 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
1415 astrand 69
1416 astrand 66 if (tr.scancode == 0)
1417 n-ki 52 break;
1418    
1419 astrand 470 save_remote_modifiers(tr.scancode);
1420 astrand 115 ensure_remote_modifiers(ev_time, tr);
1421 astrand 449 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1422 astrand 470 restore_remote_modifiers(ev_time, tr.scancode);
1423 astrand 115
1424 astrand 66 break;
1425 matthewc 203
1426 astrand 66 case KeyRelease:
1427 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
1428 astrand 66 XLookupString((XKeyEvent *) & xevent, str,
1429     sizeof(str), &keysym, NULL);
1430 n-ki 52
1431 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1432 matthewc 203 get_ksname(keysym)));
1433 n-ki 52
1434 matthewc 203 ev_time = time(NULL);
1435     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1436 astrand 118 break;
1437    
1438 astrand 66 tr = xkeymap_translate_key(keysym,
1439 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
1440 astrand 66
1441     if (tr.scancode == 0)
1442     break;
1443    
1444 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
1445 matty 9 break;
1446    
1447     case ButtonPress:
1448 matthewc 50 flags = MOUSE_FLAG_DOWN;
1449     /* fall through */
1450 matty 9
1451     case ButtonRelease:
1452 jsorg71 450 g_last_gesturetime = xevent.xbutton.time;
1453 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
1454 matty 9 if (button == 0)
1455     break;
1456    
1457 astrand 328 /* If win_button_size is nonzero, enable single app mode */
1458 jsorg71 450 if (xevent.xbutton.y < g_win_button_size)
1459 astrand 328 {
1460 astrand 342 /* Stop moving window when button is released, regardless of cursor position */
1461 jsorg71 450 if (g_moving_wnd && (xevent.type == ButtonRelease))
1462     g_moving_wnd = False;
1463 astrand 332
1464 astrand 342 /* Check from right to left: */
1465    
1466 jsorg71 450 if (xevent.xbutton.x >= g_width - g_win_button_size)
1467 astrand 328 {
1468 astrand 331 /* The close button, continue */
1469 astrand 328 ;
1470     }
1471 astrand 456 else if (xevent.xbutton.x >=
1472     g_width - g_win_button_size * 2)
1473 astrand 328 {
1474     /* The maximize/restore button. Do not send to
1475     server. It might be a good idea to change the
1476 jsorg71 447 cursor or give some other visible indication
1477 astrand 328 that rdesktop inhibited this click */
1478     break;
1479     }
1480 astrand 456 else if (xevent.xbutton.x >=
1481     g_width - g_win_button_size * 3)
1482 astrand 328 {
1483     /* The minimize button. Iconify window. */
1484 jsorg71 450 XIconifyWindow(g_display, g_wnd,
1485     DefaultScreen(g_display));
1486 astrand 328 break;
1487     }
1488 jsorg71 450 else if (xevent.xbutton.x <= g_win_button_size)
1489 astrand 342 {
1490     /* The system menu. Ignore. */
1491     break;
1492     }
1493 astrand 332 else
1494     {
1495 astrand 342 /* The title bar. */
1496 jsorg71 447 if ((xevent.type == ButtonPress) && !g_fullscreen
1497 jsorg71 450 && g_hide_decorations)
1498 astrand 342 {
1499 jsorg71 450 g_moving_wnd = True;
1500     g_move_x_offset = xevent.xbutton.x;
1501     g_move_y_offset = xevent.xbutton.y;
1502 astrand 342 }
1503 astrand 332 break;
1504 astrand 342
1505 astrand 332 }
1506 astrand 328 }
1507    
1508 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1509 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
1510 matty 10 break;
1511    
1512     case MotionNotify:
1513 jsorg71 450 if (g_moving_wnd)
1514 astrand 342 {
1515 jsorg71 450 XMoveWindow(g_display, g_wnd,
1516     xevent.xmotion.x_root - g_move_x_offset,
1517     xevent.xmotion.y_root - g_move_y_offset);
1518 astrand 342 break;
1519     }
1520    
1521 jsorg71 447 if (g_fullscreen && !g_focused)
1522 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1523 jsorg71 288 CurrentTime);
1524 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1525 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1526 matty 28 break;
1527    
1528 matthewc 194 case FocusIn:
1529 jsorg71 257 if (xevent.xfocus.mode == NotifyGrab)
1530     break;
1531 jsorg71 447 g_focused = True;
1532 astrand 543 reset_modifier_keys();
1533 jsorg71 450 if (g_grab_keyboard && g_mouse_in_wnd)
1534     XGrabKeyboard(g_display, g_wnd, True,
1535 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
1536 matty 28 break;
1537    
1538 matthewc 194 case FocusOut:
1539 jsorg71 257 if (xevent.xfocus.mode == NotifyUngrab)
1540     break;
1541 jsorg71 447 g_focused = False;
1542 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
1543 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1544 matty 28 break;
1545 matty 31
1546 matthewc 250 case EnterNotify:
1547     /* we only register for this event when in fullscreen mode */
1548 jsorg71 257 /* or grab_keyboard */
1549 jsorg71 447 g_mouse_in_wnd = True;
1550     if (g_fullscreen)
1551 jsorg71 257 {
1552 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1553 astrand 261 CurrentTime);
1554 jsorg71 257 break;
1555     }
1556 jsorg71 447 if (g_focused)
1557 jsorg71 450 XGrabKeyboard(g_display, g_wnd, True,
1558 jsorg71 257 GrabModeAsync, GrabModeAsync, CurrentTime);
1559 matthewc 250 break;
1560    
1561 matthewc 253 case LeaveNotify:
1562 jsorg71 257 /* we only register for this event when grab_keyboard */
1563 jsorg71 447 g_mouse_in_wnd = False;
1564 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1565 matthewc 253 break;
1566    
1567 matty 31 case Expose:
1568 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1569 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
1570 astrand 64 xevent.xexpose.width,
1571     xevent.xexpose.height,
1572 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
1573 matty 31 break;
1574 astrand 119
1575     case MappingNotify:
1576     /* Refresh keyboard mapping if it has changed. This is important for
1577     Xvnc, since it allocates keycodes dynamically */
1578     if (xevent.xmapping.request == MappingKeyboard
1579     || xevent.xmapping.request == MappingModifier)
1580     XRefreshKeyboardMapping(&xevent.xmapping);
1581 matthewc 203
1582     if (xevent.xmapping.request == MappingModifier)
1583     {
1584 jsorg71 450 XFreeModifiermap(g_mod_map);
1585     g_mod_map = XGetModifierMapping(g_display);
1586 matthewc 203 }
1587 astrand 119 break;
1588 matthewc 432
1589 astrand 435 /* clipboard stuff */
1590 forsberg 415 case SelectionNotify:
1591 matthewc 432 xclip_handle_SelectionNotify(&xevent.xselection);
1592 forsberg 415 break;
1593     case SelectionRequest:
1594 matthewc 432 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1595 forsberg 415 break;
1596 matthewc 432 case SelectionClear:
1597     xclip_handle_SelectionClear();
1598     break;
1599 forsberg 415 case PropertyNotify:
1600 matthewc 432 xclip_handle_PropertyNotify(&xevent.xproperty);
1601 forsberg 415 break;
1602 matty 9 }
1603     }
1604 astrand 275 /* Keep going */
1605     return 1;
1606 matty 9 }
1607    
1608 astrand 275 /* Returns 0 after user quit, 1 otherwise */
1609     int
1610 matty 33 ui_select(int rdp_socket)
1611     {
1612 stargo 606 int n;
1613 matthewc 474 fd_set rfds, wfds;
1614 n-ki 592 struct timeval tv;
1615     BOOL s_timeout = False;
1616 matty 33
1617     while (True)
1618     {
1619 stargo 606 n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1620 matthewc 121 /* Process any events already waiting */
1621 astrand 275 if (!xwin_process_events())
1622     /* User quit */
1623     return 0;
1624 astrand 119
1625 matty 33 FD_ZERO(&rfds);
1626 matthewc 474 FD_ZERO(&wfds);
1627 matty 33 FD_SET(rdp_socket, &rfds);
1628 jsorg71 450 FD_SET(g_x_socket, &rfds);
1629 matty 33
1630 matthewc 474 #ifdef WITH_RDPSND
1631     /* FIXME: there should be an API for registering fds */
1632 stargo 504 if (g_dsp_busy)
1633 matty 33 {
1634 matthewc 474 FD_SET(g_dsp_fd, &wfds);
1635 n-ki 592 n = (g_dsp_fd > n) ? g_dsp_fd : n;
1636 astrand 499 }
1637 matthewc 474 #endif
1638 n-ki 592 /* default timeout */
1639     tv.tv_sec = 60;
1640     tv.tv_usec = 0;
1641 matthewc 474
1642 n-ki 592 /* add redirection handles */
1643     rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1644    
1645     n++;
1646    
1647     switch (select(n, &rfds, &wfds, NULL, &tv))
1648 matthewc 474 {
1649 matty 33 case -1:
1650     error("select: %s\n", strerror(errno));
1651    
1652     case 0:
1653 stargo 795 /* Abort serial read calls */
1654     if (s_timeout)
1655     rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1656 matty 33 continue;
1657     }
1658    
1659 n-ki 592 rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
1660    
1661 stargo 754 if (FD_ISSET(rdp_socket, &rfds))
1662     return 1;
1663    
1664 matthewc 474 #ifdef WITH_RDPSND
1665 stargo 504 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1666 matthewc 474 wave_out_play();
1667     #endif
1668 matty 33 }
1669     }
1670    
1671     void
1672 matty 25 ui_move_pointer(int x, int y)
1673 matty 9 {
1674 jsorg71 450 XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1675 matty 9 }
1676    
1677 matty 25 HBITMAP
1678 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1679 matty 6 {
1680     XImage *image;
1681 matty 9 Pixmap bitmap;
1682 matty 28 uint8 *tdata;
1683 stargo 521 int bitmap_pad;
1684 matty 29
1685 stargo 521 if (g_server_bpp == 8)
1686     {
1687     bitmap_pad = 8;
1688     }
1689     else
1690     {
1691     bitmap_pad = g_bpp;
1692    
1693     if (g_bpp == 24)
1694     bitmap_pad = 32;
1695     }
1696    
1697 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1698     bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1699     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1700 stargo 521 (char *) tdata, width, height, bitmap_pad, 0);
1701 matty 6
1702 jsorg71 725 XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
1703 matty 9
1704     XFree(image);
1705 jsorg71 644 if (tdata != data)
1706 n-ki 279 xfree(tdata);
1707 matty 24 return (HBITMAP) bitmap;
1708 matty 6 }
1709    
1710 matty 25 void
1711 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1712 matty 6 {
1713 matty 10 XImage *image;
1714 matty 29 uint8 *tdata;
1715 stargo 521 int bitmap_pad;
1716    
1717     if (g_server_bpp == 8)
1718     {
1719     bitmap_pad = 8;
1720     }
1721     else
1722     {
1723     bitmap_pad = g_bpp;
1724    
1725     if (g_bpp == 24)
1726     bitmap_pad = 32;
1727     }
1728    
1729 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1730     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1731 stargo 521 (char *) tdata, width, height, bitmap_pad, 0);
1732 matty 28
1733 jsorg71 450 if (g_ownbackstore)
1734 matty 31 {
1735 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1736     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1737 matty 31 }
1738     else
1739     {
1740 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1741 matty 31 }
1742 matty 29
1743 matty 24 XFree(image);
1744 jsorg71 644 if (tdata != data)
1745 n-ki 279 xfree(tdata);
1746 matty 6 }
1747    
1748 matty 25 void
1749     ui_destroy_bitmap(HBITMAP bmp)
1750 matty 6 {
1751 jsorg71 450 XFreePixmap(g_display, (Pixmap) bmp);
1752 matty 10 }
1753    
1754 matty 25 HGLYPH
1755 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1756 matty 10 {
1757 matty 9 XImage *image;
1758     Pixmap bitmap;
1759     int scanline;
1760 matty 6
1761 matty 9 scanline = (width + 7) / 8;
1762 matty 6
1763 jsorg71 450 bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1764 jsorg71 725 if (g_create_glyph_gc == 0)
1765     g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1766 matty 9
1767 jsorg71 450 image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1768 astrand 73 width, height, 8, scanline);
1769 matty 23 image->byte_order = MSBFirst;
1770     image->bitmap_bit_order = MSBFirst;
1771     XInitImage(image);
1772    
1773 jsorg71 725 XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
1774 matty 29
1775 matty 9 XFree(image);
1776 astrand 64 return (HGLYPH) bitmap;
1777 matty 6 }
1778 matty 7
1779 matty 25 void
1780     ui_destroy_glyph(HGLYPH glyph)
1781 matty 7 {
1782 jsorg71 450 XFreePixmap(g_display, (Pixmap) glyph);
1783 matty 9 }
1784    
1785 matty 29 HCURSOR
1786 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1787     uint8 * andmask, uint8 * xormask)
1788 matty 9 {
1789 matty 29 HGLYPH maskglyph, cursorglyph;
1790     XColor bg, fg;
1791     Cursor xcursor;
1792     uint8 *cursor, *pcursor;
1793     uint8 *mask, *pmask;
1794     uint8 nextbit;
1795     int scanline, offset;
1796     int i, j;
1797    
1798     scanline = (width + 7) / 8;
1799     offset = scanline * height;
1800    
1801 forsberg 415 cursor = (uint8 *) xmalloc(offset);
1802 matty 29 memset(cursor, 0, offset);
1803    
1804 forsberg 415 mask = (uint8 *) xmalloc(offset);
1805 matty 29 memset(mask, 0, offset);
1806    
1807     /* approximate AND and XOR masks with a monochrome X pointer */
1808     for (i = 0; i < height; i++)
1809 matty 7 {
1810 matty 29 offset -= scanline;
1811     pcursor = &cursor[offset];
1812     pmask = &mask[offset];
1813    
1814     for (j = 0; j < scanline; j++)
1815 matty 28 {
1816 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1817     {
1818     if (xormask[0] || xormask[1] || xormask[2])
1819     {
1820     *pcursor |= (~(*andmask) & nextbit);
1821     *pmask |= nextbit;
1822     }
1823     else
1824     {
1825     *pcursor |= ((*andmask) & nextbit);
1826     *pmask |= (~(*andmask) & nextbit);
1827     }
1828    
1829     xormask += 3;
1830     }
1831    
1832     andmask++;
1833     pcursor++;
1834     pmask++;
1835 matty 28 }
1836 matty 7 }
1837 matty 29
1838     fg.red = fg.blue = fg.green = 0xffff;
1839     bg.red = bg.blue = bg.green = 0x0000;
1840     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1841    
1842     cursorglyph = ui_create_glyph(width, height, cursor);
1843     maskglyph = ui_create_glyph(width, height, mask);
1844    
1845 astrand 66 xcursor =
1846 jsorg71 450 XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1847 astrand 66 (Pixmap) maskglyph, &fg, &bg, x, y);
1848 astrand 64
1849 matty 29 ui_destroy_glyph(maskglyph);
1850     ui_destroy_glyph(cursorglyph);
1851     xfree(mask);
1852     xfree(cursor);
1853 astrand 64 return (HCURSOR) xcursor;
1854 matty 29 }
1855    
1856     void
1857     ui_set_cursor(HCURSOR cursor)
1858     {
1859 jsorg71 450 g_current_cursor = (Cursor) cursor;
1860     XDefineCursor(g_display, g_wnd, g_current_cursor);
1861 matty 29 }
1862    
1863     void
1864     ui_destroy_cursor(HCURSOR cursor)
1865     {
1866 jsorg71 450 XFreeCursor(g_display, (Cursor) cursor);
1867 matty 29 }
1868    
1869 astrand 508 void
1870     ui_set_null_cursor(void)
1871     {
1872     ui_set_cursor(g_null_cursor);
1873     }
1874    
1875 matty 29 #define MAKE_XCOLOR(xc,c) \
1876     (xc)->red = ((c)->red << 8) | (c)->red; \
1877     (xc)->green = ((c)->green << 8) | (c)->green; \
1878     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1879     (xc)->flags = DoRed | DoGreen | DoBlue;
1880    
1881 n-ki 279
1882 matty 29 HCOLOURMAP
1883 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1884 matty 29 {
1885     COLOURENTRY *entry;
1886     int i, ncolours = colours->ncolours;
1887 jsorg71 450 if (!g_owncolmap)
1888 matty 28 {
1889 jsorg71 450 uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1890 n-ki 279 XColor xentry;
1891     XColor xc_cache[256];
1892     uint32 colour;
1893     int colLookup = 256;
1894     for (i = 0; i < ncolours; i++)
1895 matty 28 {
1896 n-ki 279 entry = &colours->colours[i];
1897     MAKE_XCOLOR(&xentry, entry);
1898 matty 7
1899 jsorg71 450 if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1900 astrand 196 {
1901 n-ki 279 /* Allocation failed, find closest match. */
1902     int j = 256;
1903     int nMinDist = 3 * 256 * 256;
1904     long nDist = nMinDist;
1905 matty 28
1906 n-ki 279 /* only get the colors once */
1907     while (colLookup--)
1908 astrand 196 {
1909 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1910     xc_cache[colLookup].red = xc_cache[colLookup].green =
1911     xc_cache[colLookup].blue = 0;
1912     xc_cache[colLookup].flags = 0;
1913 jsorg71 450 XQueryColor(g_display,
1914     DefaultColormap(g_display,
1915     DefaultScreen(g_display)),
1916 n-ki 279 &xc_cache[colLookup]);
1917 n-ki 185 }
1918 n-ki 279 colLookup = 0;
1919    
1920     /* approximate the pixel */
1921     while (j--)
1922 astrand 196 {
1923 n-ki 279 if (xc_cache[j].flags)
1924     {
1925     nDist = ((long) (xc_cache[j].red >> 8) -
1926     (long) (xentry.red >> 8)) *
1927     ((long) (xc_cache[j].red >> 8) -
1928     (long) (xentry.red >> 8)) +
1929     ((long) (xc_cache[j].green >> 8) -
1930     (long) (xentry.green >> 8)) *
1931     ((long) (xc_cache[j].green >> 8) -
1932     (long) (xentry.green >> 8)) +
1933     ((long) (xc_cache[j].blue >> 8) -
1934     (long) (xentry.blue >> 8)) *
1935     ((long) (xc_cache[j].blue >> 8) -
1936     (long) (xentry.blue >> 8));
1937     }
1938     if (nDist < nMinDist)
1939     {
1940     nMinDist = nDist;
1941     xentry.pixel = j;
1942     }
1943 n-ki 185 }
1944     }
1945 n-ki 279 colour = xentry.pixel;
1946    
1947     /* update our cache */
1948     if (xentry.pixel < 256)
1949     {
1950     xc_cache[xentry.pixel].red = xentry.red;
1951     xc_cache[xentry.pixel].green = xentry.green;
1952     xc_cache[xentry.pixel].blue = xentry.blue;
1953    
1954     }
1955    
1956 matthewc 527 map[i] = colour;
1957 n-ki 185 }
1958 n-ki 279 return map;
1959     }
1960     else
1961     {
1962     XColor *xcolours, *xentry;
1963     Colormap map;
1964 matty 29
1965 forsberg 415 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1966 n-ki 279 for (i = 0; i < ncolours; i++)
1967 astrand 196 {
1968 n-ki 279 entry = &colours->colours[i];
1969     xentry = &xcolours[i];
1970     xentry->pixel = i;
1971     MAKE_XCOLOR(xentry, entry);
1972 matty 29 }
1973    
1974 jsorg71 450 map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1975     XStoreColors(g_display, map, xcolours, ncolours);
1976 n-ki 185
1977 n-ki 279 xfree(xcolours);
1978     return (HCOLOURMAP) map;
1979 matty 29 }
1980 matty 7 }
1981    
1982 matty 25 void
1983     ui_destroy_colourmap(HCOLOURMAP map)
1984 matty 7 {
1985 jsorg71 450 if (!g_owncolmap)
1986 n-ki 279 xfree(map);
1987     else
1988 jsorg71 450 XFreeColormap(g_display, (Colormap) map);
1989 matty 7 }
1990    
1991 matty 25 void
1992     ui_set_colourmap(HCOLOURMAP map)
1993 matty 7 {
1994 jsorg71 450 if (!g_owncolmap)
1995 astrand 448 {
1996 jsorg71 450 if (g_colmap)
1997     xfree(g_colmap);
1998 astrand 448
1999 jsorg71 450 g_colmap = (uint32 *) map;
2000 astrand 448 }
2001 n-ki 279 else
2002 jsorg71 450 XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2003 matty 7 }
2004    
2005 matty 25 void
2006     ui_set_clip(int x, int y, int cx, int cy)
2007 matty 7 {
2008 matty 9 XRectangle rect;
2009 matty 7
2010 matty 9 rect.x = x;
2011     rect.y = y;
2012     rect.width = cx;
2013     rect.height = cy;
2014 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
2015 matty 9 }
2016 matty 7
2017 matty 25 void
2018 matthewc 192 ui_reset_clip(void)
2019 matty 9 {
2020     XRectangle rect;
2021    
2022     rect.x = 0;
2023     rect.y = 0;
2024 jsorg71 447 rect.width = g_width;
2025     rect.height = g_height;
2026 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
2027 matty 7 }
2028    
2029 matty 25 void
2030 matthewc 192 ui_bell(void)
2031 matty 10 {
2032 jsorg71 450 XBell(g_display, 0);
2033 matty 10 }
2034    
2035 matty 25 void
2036     ui_destblt(uint8 opcode,
2037     /* dest */ int x, int y, int cx, int cy)
2038 matty 9 {
2039 matty 29 SET_FUNCTION(opcode);
2040 matty 31 FILL_RECTANGLE(x, y, cx, cy);
2041 matty 29 RESET_FUNCTION(opcode);
2042 matty 9 }
2043    
2044 jsorg71 373 static uint8 hatch_patterns[] = {
2045 forsberg 415 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
2046     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
2047     0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
2048     0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
2049     0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
2050     0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
2051 jsorg71 373 };
2052    
2053 matty 25 void
2054     ui_patblt(uint8 opcode,
2055     /* dest */ int x, int y, int cx, int cy,
2056 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2057 matty 9 {
2058     Pixmap fill;
2059 jsorg71 59 uint8 i, ipattern[8];
2060 matty 9
2061 matty 29 SET_FUNCTION(opcode);
2062 matty 9
2063     switch (brush->style)
2064     {
2065 matty 24 case 0: /* Solid */
2066 matty 29 SET_FOREGROUND(fgcolour);
2067 jsorg71 680 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2068 matty 9 break;
2069    
2070 jsorg71 373 case 2: /* Hatch */
2071 forsberg 415 fill = (Pixmap) ui_create_glyph(8, 8,
2072     hatch_patterns + brush->pattern[0] * 8);
2073 astrand 487 SET_FOREGROUND(fgcolour);
2074     SET_BACKGROUND(bgcolour);
2075 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2076     XSetStipple(g_display, g_gc, fill);
2077     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2078 jsorg71 680 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2079 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
2080     XSetTSOrigin(g_display, g_gc, 0, 0);
2081 jsorg71 373 ui_destroy_glyph((HGLYPH) fill);
2082     break;
2083    
2084 matty 24 case 3: /* Pattern */
2085 jsorg71 59 for (i = 0; i != 8; i++)
2086     ipattern[7 - i] = brush->pattern[i];
2087     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2088 matty 29 SET_FOREGROUND(bgcolour);
2089     SET_BACKGROUND(fgcolour);
2090 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2091     XSetStipple(g_display, g_gc, fill);
2092     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2093 jsorg71 680 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2094 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
2095     XSetTSOrigin(g_display, g_gc, 0, 0);
2096 astrand 64 ui_destroy_glyph((HGLYPH) fill);
2097 matty 9 break;
2098    
2099     default:
2100 matty 30 unimpl("brush %d\n", brush->style);
2101 matty 9 }
2102 matty 29
2103     RESET_FUNCTION(opcode);
2104 jsorg71 680
2105     if (g_ownbackstore)
2106     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2107 matty 9 }
2108    
2109 matty 25 void
2110     ui_screenblt(uint8 opcode,
2111     /* dest */ int x, int y, int cx, int cy,
2112     /* src */ int srcx, int srcy)
2113 matty 9 {
2114 matty 29 SET_FUNCTION(opcode);
2115 jsorg71 450 if (g_ownbackstore)
2116 stargo 609 {
2117 jsorg71 688 if (g_Unobscured)
2118     {
2119     XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2120 astrand 691 XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2121     y);
2122 jsorg71 688 }
2123     else
2124     {
2125     XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2126 astrand 691 XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2127     y);
2128 jsorg71 688 }
2129 stargo 609 }
2130     else
2131     {
2132     XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2133     }
2134 matty 29 RESET_FUNCTION(opcode);
2135 matty 9 }
2136    
2137 matty 25 void
2138     ui_memblt(uint8 opcode,
2139     /* dest */ int x, int y, int cx, int cy,
2140     /* src */ HBITMAP src, int srcx, int srcy)
2141 matty 9 {
2142 matty 29 SET_FUNCTION(opcode);
2143 jsorg71 450 XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2144     if (g_ownbackstore)
2145     XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2146 matty 29 RESET_FUNCTION(opcode);
2147 matty 9 }
2148    
2149 matty 25 void
2150     ui_triblt(uint8 opcode,
2151     /* dest */ int x, int y, int cx, int cy,
2152     /* src */ HBITMAP src, int srcx, int srcy,
2153 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2154 matty 9 {
2155     /* This is potentially difficult to do in general. Until someone
2156 matty 10 comes up with a more efficient way of doing it I am using cases. */
2157 matty 9
2158     switch (opcode)
2159     {
2160 matty 24 case 0x69: /* PDSxxn */
2161 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
2162 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
2163 matty 16 break;
2164    
2165 matty 24 case 0xb8: /* PSDPxax */
2166 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
2167 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
2168 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
2169 matty 9 break;
2170    
2171 matty 29 case 0xc0: /* PSa */
2172 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2173 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
2174 matty 28 break;
2175    
2176 matty 9 default:
2177 matty 30 unimpl("triblt 0x%x\n", opcode);
2178 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2179 matty 9 }
2180     }
2181    
2182 matty 25 void
2183     ui_line(uint8 opcode,
2184     /* dest */ int startx, int starty, int endx, int endy,
2185 astrand 64 /* pen */ PEN * pen)
2186 matty 9 {
2187 matty 29 SET_FUNCTION(opcode);
2188     SET_FOREGROUND(pen->colour);
2189 jsorg71 450 XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2190     if (g_ownbackstore)
2191     XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2192 matty 29 RESET_FUNCTION(opcode);
2193 matty 9 }
2194    
2195 matty 25 void
2196     ui_rect(
2197     /* dest */ int x, int y, int cx, int cy,
2198     /* brush */ int colour)
2199 matty 9 {
2200 matty 29 SET_FOREGROUND(colour);
2201 matty 31 FILL_RECTANGLE(x, y, cx, cy);
2202 matty 9 }
2203    
2204 jdmeijer 831 void
2205     ui_polygon(uint8 opcode,
2206     /* mode */ uint8 fillmode,
2207     /* dest */ POINT * point, int npoints,
2208     /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2209     {
2210     uint8 style, i, ipattern[8];
2211     Pixmap fill;
2212    
2213     SET_FUNCTION(opcode);
2214    
2215     switch (fillmode)
2216     {
2217     case ALTERNATE:
2218     XSetFillRule(g_display, g_gc, EvenOddRule);
2219     break;
2220     case WINDING:
2221     XSetFillRule(g_display, g_gc, WindingRule);
2222     break;
2223     default:
2224     unimpl("fill mode %d\n", fillmode);
2225     }
2226    
2227     if (brush)
2228     style = brush->style;
2229     else
2230     style = 0;
2231    
2232     switch (style)
2233     {
2234     case 0: /* Solid */
2235     SET_FOREGROUND(fgcolour);
2236     FILL_POLYGON((XPoint *) point, npoints);
2237     break;
2238    
2239     case 2: /* Hatch */
2240     fill = (Pixmap) ui_create_glyph(8, 8,
2241     hatch_patterns + brush->pattern[0] * 8);
2242     SET_FOREGROUND(fgcolour);
2243     SET_BACKGROUND(bgcolour);
2244     XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2245     XSetStipple(g_display, g_gc, fill);
2246     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2247     FILL_POLYGON((XPoint *) point, npoints);
2248     XSetFillStyle(g_display, g_gc, FillSolid);
2249     XSetTSOrigin(g_display, g_gc, 0, 0);
2250     ui_destroy_glyph((HGLYPH) fill);
2251     break;
2252    
2253     case 3: /* Pattern */
2254     for (i = 0; i != 8; i++)
2255     ipattern[7 - i] = brush->pattern[i];
2256     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2257     SET_FOREGROUND(bgcolour);
2258     SET_BACKGROUND(fgcolour);
2259     XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2260     XSetStipple(g_display, g_gc, fill);
2261     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2262     FILL_POLYGON((XPoint *) point, npoints);
2263     XSetFillStyle(g_display, g_gc, FillSolid);
2264     XSetTSOrigin(g_display, g_gc, 0, 0);
2265     ui_destroy_glyph((HGLYPH) fill);
2266     break;
2267    
2268     default:
2269     unimpl("brush %d\n", brush->style);
2270     }
2271    
2272     RESET_FUNCTION(opcode);
2273     }
2274    
2275     void
2276 jdmeijer 844 ui_polyline(uint8 opcode,
2277     /* dest */ POINT * points, int npoints,
2278     /* pen */ PEN * pen)
2279     {
2280     /* TODO: set join style */
2281     SET_FUNCTION(opcode);
2282     SET_FOREGROUND(pen->colour);
2283     XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2284     if (g_ownbackstore)
2285     XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2286     CoordModePrevious);
2287     RESET_FUNCTION(opcode);
2288     }
2289    
2290     void
2291 jdmeijer 831 ui_ellipse(uint8 opcode,
2292     /* mode */ uint8 fillmode,
2293     /* dest */ int x, int y, int cx, int cy,
2294     /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2295     {
2296     uint8 style, i, ipattern[8];
2297     Pixmap fill;
2298    
2299     SET_FUNCTION(opcode);
2300    
2301     if (brush)
2302     style = brush->style;
2303     else
2304     style = 0;
2305    
2306     switch (style)
2307     {
2308     case 0: /* Solid */
2309     SET_FOREGROUND(fgcolour);
2310     DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2311     break;
2312    
2313     case 2: /* Hatch */
2314     fill = (Pixmap) ui_create_glyph(8, 8,
2315     hatch_patterns + brush->pattern[0] * 8);
2316     SET_FOREGROUND(fgcolour);
2317     SET_BACKGROUND(bgcolour);
2318     XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2319     XSetStipple(g_display, g_gc, fill);
2320     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2321     DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2322     XSetFillStyle(g_display, g_gc, FillSolid);
2323     XSetTSOrigin(g_display, g_gc, 0, 0);
2324     ui_destroy_glyph((HGLYPH) fill);
2325     break;
2326    
2327     case 3: /* Pattern */
2328     for (i = 0; i != 8; i++)
2329     ipattern[7 - i] = brush->pattern[i];
2330     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2331     SET_FOREGROUND(bgcolour);
2332     SET_BACKGROUND(fgcolour);
2333     XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2334     XSetStipple(g_display, g_gc, fill);
2335     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2336     DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2337     XSetFillStyle(g_display, g_gc, FillSolid);
2338     XSetTSOrigin(g_display, g_gc, 0, 0);
2339     ui_destroy_glyph((HGLYPH) fill);
2340     break;
2341    
2342     default:
2343     unimpl("brush %d\n", brush->style);
2344     }
2345    
2346     RESET_FUNCTION(opcode);
2347     }
2348    
2349 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
2350 matty 25 void
2351     ui_draw_glyph(int mixmode,
2352     /* dest */ int x, int y, int cx, int cy,
2353 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
2354     int bgcolour, int fgcolour)
2355 matty 9 {
2356 matty 29 SET_FOREGROUND(fgcolour);
2357     SET_BACKGROUND(bgcolour);
2358 matty 9
2359 jsorg71 450 XSetFillStyle(g_display, g_gc,
2360 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2361 jsorg71 450 XSetStipple(g_display, g_gc, (Pixmap) glyph);
2362     XSetTSOrigin(g_display, g_gc, x, y);
2363 matty 9
2364 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2365 matty 9
2366 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
2367 matty 9 }
2368    
2369 mmihalik 49 #define DO_GLYPH(ttext,idx) \
2370     {\
2371     glyph = cache_get_font (font, ttext[idx]);\
2372     if (!(flags & TEXT2_IMPLICIT_X))\
2373 jsorg71 564 {\
2374     xyoffset = ttext[++idx];\
2375     if ((xyoffset & 0x80))\
2376 mmihalik 49 {\
2377 jsorg71 564 if (flags & TEXT2_VERTICAL)\
2378     y += ttext[idx+1] | (ttext[idx+2] << 8);\
2379 mmihalik 49 else\
2380 jsorg71 564 x += ttext[idx+1] | (ttext[idx+2] << 8);\
2381     idx += 2;\
2382 mmihalik 49 }\
2383 jsorg71 564 else\
2384 mmihalik 49 {\
2385 jsorg71 564 if (flags & TEXT2_VERTICAL)\
2386     y += xyoffset;\
2387     else\
2388     x += xyoffset;\
2389 mmihalik 49 }\
2390 jsorg71 564 }\
2391     if (glyph != NULL)\
2392     {\
2393     x1 = x + glyph->offset;\
2394     y1 = y + glyph->baseline;\
2395     XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2396     XSetTSOrigin(g_display, g_gc, x1, y1);\
2397     FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2398     if (flags & TEXT2_IMPLICIT_X)\
2399     x += glyph->width;\
2400     }\
2401 mmihalik 49 }
2402    
2403 matty 25 void
2404 jdmeijer 843 ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y,
2405 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
2406 jdmeijer 843 int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2407     int bgcolour, int fgcolour, uint8 * text, uint8 length)
2408 matty 9 {
2409 jdmeijer 843 /* TODO: use brush appropriately */
2410    
2411 matty 10 FONTGLYPH *glyph;
2412 jsorg71 564 int i, j, xyoffset, x1, y1;
2413 mmihalik 49 DATABLOB *entry;
2414 matty 9
2415 matty 29 SET_FOREGROUND(bgcolour);
2416 matty 28
2417 astrand 620 /* Sometimes, the boxcx value is something really large, like
2418     32691. This makes XCopyArea fail with Xvnc. The code below
2419     is a quick fix. */
2420     if (boxx + boxcx > g_width)
2421     boxcx = g_width - boxx;
2422    
2423 matty 9 if (boxcx > 1)
2424 matty 31 {
2425 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2426 matty 31 }
2427 matty 17 else if (mixmode == MIX_OPAQUE)
2428 matty 31 {
2429 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2430 matty 31 }
2431 matty 9
2432 jsorg71 564 SET_FOREGROUND(fgcolour);
2433     SET_BACKGROUND(bgcolour);
2434     XSetFillStyle(g_display, g_gc, FillStippled);
2435    
2436 matty 9 /* Paint text, character by character */
2437 astrand 64 for (i = 0; i < length;)
2438     {
2439     switch (text[i])
2440     {
2441     case 0xff:
2442     if (i + 2 < length)
2443 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
2444 astrand 64 else
2445     {
2446     error("this shouldn't be happening\n");
2447 astrand 265 exit(1);
2448 astrand 64 }
2449     /* this will move pointer from start to first character after FF command */
2450     length -= i + 3;
2451     text = &(text[i + 3]);
2452     i = 0;
2453 mmihalik 49 break;
2454 matty 9
2455 astrand 64 case 0xfe:
2456     entry = cache_get_text(text[i + 1]);
2457     if (entry != NULL)
2458     {
2459     if ((((uint8 *) (entry->data))[1] ==
2460 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
2461 astrand 64 {
2462     if (flags & TEXT2_VERTICAL)
2463     y += text[i + 2];
2464     else
2465     x += text[i + 2];
2466     }
2467     for (j = 0; j < entry->size; j++)
2468 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
2469 matthewc 44 }
2470 jsorg71 286 if (i + 2 < length)
2471     i += 3;
2472     else
2473     i += 2;
2474     length -= i;
2475     /* this will move pointer from start to first character after FE command */
2476     text = &(text[i]);
2477     i = 0;
2478 astrand 64 break;
2479 matty 17
2480 astrand 64 default:
2481     DO_GLYPH(text, i);
2482     i++;
2483     break;
2484 matty 29 }
2485 mmihalik 49 }
2486 jsorg71 564
2487     XSetFillStyle(g_display, g_gc, FillSolid);
2488    
2489 jsorg71 450 if (g_ownbackstore)
2490 jsorg71 278 {
2491     if (boxcx > 1)
2492 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2493 jsorg71 278 boxy, boxcx, boxcy, boxx, boxy);
2494     else
2495 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2496 jsorg71 278 clipy, clipcx, clipcy, clipx, clipy);
2497     }
2498 matty 9 }
2499    
2500 matty 25 void
2501     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
2502 matty 9 {
2503 matty 28 Pixmap pix;
2504 matty 9 XImage *image;
2505    
2506 jsorg71 450 if (g_ownbackstore)
2507 matty 31 {
2508 jsorg71 450 image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
2509 matty 31 }
2510     else
2511     {
2512 jsorg71 450 pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2513     XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
2514     image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2515     XFreePixmap(g_display, pix);
2516 matty 31 }
2517 matty 28
2518 jsorg71 450 offset *= g_bpp / 8;
2519     cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
2520 matty 28
2521     XDestroyImage(image);
2522 matty 9 }
2523    
2524 matty 25 void
2525     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
2526 matty 9 {
2527     XImage *image;
2528 matty 10 uint8 *data;
2529 matty 9
2530 jsorg71 450 offset *= g_bpp / 8;
2531     data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2532 matty 10 if (data == NULL)
2533     return;
2534 matty 29
2535 jsorg71 450 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2536     (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
2537 matty 29
2538 jsorg71 450 if (g_ownbackstore)
2539 matty 31 {
2540 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2541     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2542 matty 31 }
2543     else
2544     {
2545 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2546 matty 31 }
2547    
2548 matty 9 XFree(image);
2549     }
2550 jsorg71 713
2551     /* these do nothing here but are used in uiports */
2552     void
2553     ui_begin_update(void)
2554     {
2555     }
2556    
2557     void
2558     ui_end_update(void)
2559     {
2560     }

  ViewVC Help
Powered by ViewVC 1.1.26