/[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 1029 - (hide annotations)
Fri Nov 18 22:46:38 2005 UTC (18 years, 6 months ago) by astrand
File MIME type: text/plain
File size: 56904 byte(s)
Handle too short 0xff and 0xfe commands in ui_draw_text.

This fix should remove both a segfault and a "this shouldn't be
happening" abortion, which I can trigger with vertical text in
OpenOffice 2.0.

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 991 static BOOL g_using_full_workarea = False;
83 astrand 342
84 matthewc 474 #ifdef WITH_RDPSND
85     extern int g_dsp_fd;
86     extern BOOL g_dsp_busy;
87 stargo 501 extern BOOL g_rdpsnd;
88 matthewc 474 #endif
89    
90 astrand 262 /* MWM decorations */
91     #define MWM_HINTS_DECORATIONS (1L << 1)
92     #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
93     typedef struct
94     {
95 matthewc 301 uint32 flags;
96     uint32 functions;
97     uint32 decorations;
98     sint32 inputMode;
99     uint32 status;
100 astrand 262 }
101     PropMotifWmHints;
102    
103 jsorg71 316 typedef struct
104     {
105     uint32 red;
106     uint32 green;
107     uint32 blue;
108     }
109     PixelColour;
110 astrand 262
111 forsberg 415
112 matty 31 #define FILL_RECTANGLE(x,y,cx,cy)\
113     { \
114 jsorg71 450 XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
115     if (g_ownbackstore) \
116     XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
117 matty 31 }
118    
119 matthewc 296 #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
120 jsorg71 281 { \
121 jsorg71 450 XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
122 jsorg71 281 }
123    
124 jdmeijer 831 #define FILL_POLYGON(p,np)\
125     { \
126     XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
127     if (g_ownbackstore) \
128     XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
129     }
130    
131     #define DRAW_ELLIPSE(x,y,cx,cy,m)\
132     { \
133     switch (m) \
134     { \
135     case 0: /* Outline */ \
136     XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
137     if (g_ownbackstore) \
138     XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
139     break; \
140     case 1: /* Filled */ \
141 jsorg71 1022 XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
142 jdmeijer 831 if (g_ownbackstore) \
143 jsorg71 1022 XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
144 jdmeijer 831 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 astrand 991 if (-g_width >= 100)
1095     g_using_full_workarea = True;
1096 astrand 500 g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1097     g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1098     }
1099     else if (g_width == 0)
1100     {
1101 astrand 263 /* Fetch geometry from _NET_WORKAREA */
1102 matthewc 300 uint32 x, y, cx, cy;
1103 astrand 991 g_using_full_workarea = True;
1104 astrand 263
1105 matthewc 300 if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1106 astrand 263 {
1107 jsorg71 447 g_width = cx;
1108     g_height = cy;
1109 matthewc 300 }
1110     else
1111     {
1112 matthewc 297 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1113 jsorg71 447 g_width = 800;
1114     g_height = 600;
1115 astrand 263 }
1116     }
1117 matthewc 121
1118 matthewc 160 /* make sure width is a multiple of 4 */
1119 jsorg71 447 g_width = (g_width + 3) & ~3;
1120 matthewc 160
1121 jsorg71 450 g_mod_map = XGetModifierMapping(g_display);
1122 matthewc 203
1123 astrand 498 xkeymap_init();
1124    
1125 jsorg71 447 if (g_enable_compose)
1126 jsorg71 450 g_IM = XOpenIM(g_display, NULL, NULL, NULL);
1127 matthewc 188
1128 matthewc 432 xclip_init();
1129 jsorg71 316
1130 matthewc 519 DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));
1131 jsorg71 316
1132 jsorg71 81 return True;
1133     }
1134 astrand 66
1135 matthewc 188 void
1136 matthewc 192 ui_deinit(void)
1137 matthewc 188 {
1138 jsorg71 450 if (g_IM != NULL)
1139     XCloseIM(g_IM);
1140 astrand 580
1141 stargo 576 if (g_null_cursor != NULL)
1142     ui_destroy_cursor(g_null_cursor);
1143 matthewc 188
1144 jsorg71 450 XFreeModifiermap(g_mod_map);
1145 matthewc 203
1146 jsorg71 450 if (g_ownbackstore)
1147     XFreePixmap(g_display, g_backstore);
1148 matthewc 188
1149 jsorg71 450 XFreeGC(g_display, g_gc);
1150     XCloseDisplay(g_display);
1151     g_display = NULL;
1152 matthewc 188 }
1153    
1154 matthewc 121 BOOL
1155 matthewc 192 ui_create_window(void)
1156 matty 6 {
1157 matthewc 536 uint8 null_pointer_mask[1] = { 0x80 };
1158 astrand 788 uint8 null_pointer_data[24] = { 0x00 };
1159    
1160 matthewc 121 XSetWindowAttributes attribs;
1161 matty 28 XClassHint *classhints;
1162     XSizeHints *sizehints;
1163 matthewc 188 int wndwidth, wndheight;
1164 matthewc 432 long input_mask, ic_input_mask;
1165 jsorg71 100 XEvent xevent;
1166    
1167 jsorg71 450 wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1168     wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1169 matthewc 188
1170 stargo 867 /* Handle -x-y portion of geometry string */
1171     if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1172     g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1173     if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1174     g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1175    
1176 jsorg71 450 attribs.background_pixel = BlackPixelOfScreen(g_screen);
1177 stargo 565 attribs.border_pixel = WhitePixelOfScreen(g_screen);
1178 jsorg71 450 attribs.backing_store = g_ownbackstore ? NotUseful : Always;
1179 jsorg71 447 attribs.override_redirect = g_fullscreen;
1180 stargo 565 attribs.colormap = g_xcolmap;
1181 matthewc 188
1182 astrand 801 g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
1183     wndheight, 0, g_depth, InputOutput, g_visual,
1184     CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
1185     CWBorderPixel, &attribs);
1186 jsorg71 100
1187 stargo 576 if (g_gc == NULL)
1188 stargo 566 g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1189 stargo 565
1190 jsorg71 725 if (g_create_bitmap_gc == NULL)
1191     g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
1192    
1193 stargo 603 if ((g_ownbackstore) && (g_backstore == 0))
1194 stargo 565 {
1195 astrand 580 g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1196 stargo 565
1197     /* clear to prevent rubbish being exposed at startup */
1198     XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1199     XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
1200     }
1201    
1202 jsorg71 450 XStoreName(g_display, g_wnd, g_title);
1203 jsorg71 100
1204 jsorg71 450 if (g_hide_decorations)
1205 astrand 262 mwm_hide_decorations();
1206    
1207 jsorg71 100 classhints = XAllocClassHint();
1208     if (classhints != NULL)
1209     {
1210     classhints->res_name = classhints->res_class = "rdesktop";
1211 jsorg71 450 XSetClassHint(g_display, g_wnd, classhints);
1212 jsorg71 100 XFree(classhints);
1213     }
1214    
1215     sizehints = XAllocSizeHints();
1216     if (sizehints)
1217     {
1218     sizehints->flags = PMinSize | PMaxSize;
1219 stargo 867 if (g_pos)
1220     sizehints->flags |= PPosition;
1221 jsorg71 447 sizehints->min_width = sizehints->max_width = g_width;
1222     sizehints->min_height = sizehints->max_height = g_height;
1223 jsorg71 450 XSetWMNormalHints(g_display, g_wnd, sizehints);
1224 jsorg71 100 XFree(sizehints);
1225     }
1226    
1227 astrand 651 if (g_embed_wnd)
1228     {
1229     XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1230     }
1231 stargo 636
1232 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1233 jdmeijer 905 VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1234 matthewc 121
1235 jsorg71 447 if (g_sendmotion)
1236 matthewc 121 input_mask |= PointerMotionMask;
1237 jsorg71 450 if (g_ownbackstore)
1238 matthewc 121 input_mask |= ExposureMask;
1239 jsorg71 450 if (g_fullscreen || g_grab_keyboard)
1240 matthewc 250 input_mask |= EnterWindowMask;
1241 jsorg71 450 if (g_grab_keyboard)
1242 jsorg71 257 input_mask |= LeaveWindowMask;
1243 jsorg71 100
1244 jsorg71 450 if (g_IM != NULL)
1245 matthewc 188 {
1246 jsorg71 450 g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1247 astrand 456 XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1248 matthewc 188
1249 jsorg71 450 if ((g_IC != NULL)
1250     && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1251 matthewc 188 input_mask |= ic_input_mask;
1252     }
1253    
1254 jsorg71 450 XSelectInput(g_display, g_wnd, input_mask);
1255     XMapWindow(g_display, g_wnd);
1256 jsorg71 100
1257 matthewc 208 /* wait for VisibilityNotify */
1258 astrand 196 do
1259     {
1260 jsorg71 450 XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1261 astrand 196 }
1262 matthewc 208 while (xevent.type != VisibilityNotify);
1263 jsorg71 688 g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1264 matthewc 123
1265 jsorg71 447 g_focused = False;
1266     g_mouse_in_wnd = False;
1267 jsorg71 257
1268 astrand 275 /* handle the WM_DELETE_WINDOW protocol */
1269 jsorg71 450 g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1270     g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1271     XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1272 astrand 275
1273 astrand 508 /* create invisible 1x1 cursor to be used as null cursor */
1274 stargo 576 if (g_null_cursor == NULL)
1275     g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1276 astrand 508
1277 matty 10 return True;
1278 matty 6 }
1279    
1280 matty 25 void
1281 n-ki 677 ui_resize_window()
1282     {
1283     XSizeHints *sizehints;
1284 jsorg71 708 Pixmap bs;
1285 n-ki 677
1286     sizehints = XAllocSizeHints();
1287     if (sizehints)
1288     {
1289     sizehints->flags = PMinSize | PMaxSize;
1290     sizehints->min_width = sizehints->max_width = g_width;
1291     sizehints->min_height = sizehints->max_height = g_height;
1292     XSetWMNormalHints(g_display, g_wnd, sizehints);
1293     XFree(sizehints);
1294     }
1295    
1296     if (!(g_fullscreen || g_embed_wnd))
1297     {
1298     XResizeWindow(g_display, g_wnd, g_width, g_height);
1299     }
1300 jsorg71 708
1301     /* create new backstore pixmap */
1302     if (g_backstore != 0)
1303     {
1304     bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1305     XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1306     XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1307     XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1308     XFreePixmap(g_display, g_backstore);
1309     g_backstore = bs;
1310     }
1311 n-ki 677 }
1312    
1313     void
1314 matthewc 192 ui_destroy_window(void)
1315 matty 6 {
1316 jsorg71 450 if (g_IC != NULL)
1317     XDestroyIC(g_IC);
1318 matty 31
1319 jsorg71 450 XDestroyWindow(g_display, g_wnd);
1320 matty 6 }
1321    
1322 jsorg71 100 void
1323 matthewc 192 xwin_toggle_fullscreen(void)
1324 jsorg71 100 {
1325 matthewc 188 Pixmap contents = 0;
1326 matthewc 123
1327 jsorg71 450 if (!g_ownbackstore)
1328 matthewc 188 {
1329     /* need to save contents of window */
1330 jsorg71 450 contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1331     XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1332 matthewc 188 }
1333    
1334     ui_destroy_window();
1335 jsorg71 447 g_fullscreen = !g_fullscreen;
1336 matthewc 188 ui_create_window();
1337 matthewc 123
1338 jsorg71 450 XDefineCursor(g_display, g_wnd, g_current_cursor);
1339 matthewc 188
1340 jsorg71 450 if (!g_ownbackstore)
1341 matthewc 188 {
1342 jsorg71 450 XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1343     XFreePixmap(g_display, contents);
1344 matthewc 188 }
1345 jsorg71 100 }
1346    
1347 astrand 988 static void
1348     handle_button_event(XEvent xevent, BOOL down)
1349     {
1350     uint16 button, flags = 0;
1351     g_last_gesturetime = xevent.xbutton.time;
1352     button = xkeymap_translate_button(xevent.xbutton.button);
1353     if (button == 0)
1354     return;
1355    
1356     if (down)
1357     flags = MOUSE_FLAG_DOWN;
1358    
1359     /* Stop moving window when button is released, regardless of cursor position */
1360     if (g_moving_wnd && (xevent.type == ButtonRelease))
1361     g_moving_wnd = False;
1362    
1363     /* If win_button_size is nonzero, enable single app mode */
1364     if (xevent.xbutton.y < g_win_button_size)
1365     {
1366     /* Check from right to left: */
1367     if (xevent.xbutton.x >= g_width - g_win_button_size)
1368     {
1369     /* The close button, continue */
1370     ;
1371     }
1372     else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1373     {
1374     /* The maximize/restore button. Do not send to
1375     server. It might be a good idea to change the
1376     cursor or give some other visible indication
1377     that rdesktop inhibited this click */
1378     if (xevent.type == ButtonPress)
1379     return;
1380     }
1381     else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1382     {
1383     /* The minimize button. Iconify window. */
1384     if (xevent.type == ButtonRelease)
1385     {
1386     /* Release the mouse button outside the minimize button, to prevent the
1387     actual minimazation to happen */
1388     rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1389     XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1390     return;
1391     }
1392     }
1393     else if (xevent.xbutton.x <= g_win_button_size)
1394     {
1395     /* The system menu. Ignore. */
1396     if (xevent.type == ButtonPress)
1397     return;
1398     }
1399     else
1400     {
1401     /* The title bar. */
1402     if (xevent.type == ButtonPress)
1403     {
1404 astrand 991 if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1405 astrand 988 {
1406     g_moving_wnd = True;
1407     g_move_x_offset = xevent.xbutton.x;
1408     g_move_y_offset = xevent.xbutton.y;
1409     }
1410     return;
1411     }
1412     }
1413     }
1414    
1415     rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1416     flags | button, xevent.xbutton.x, xevent.xbutton.y);
1417     }
1418    
1419 stargo 887 /* Process events in Xlib queue
1420 astrand 275 Returns 0 after user quit, 1 otherwise */
1421     static int
1422 matthewc 192 xwin_process_events(void)
1423 matty 9 {
1424 n-ki 54 XEvent xevent;
1425 matthewc 38 KeySym keysym;
1426 matty 10 uint32 ev_time;
1427 astrand 66 char str[256];
1428     Status status;
1429 stargo 887 int events = 0;
1430 matty 9
1431 stargo 887 while ((XPending(g_display) > 0) && events++ < 20)
1432 matty 9 {
1433 jsorg71 450 XNextEvent(g_display, &xevent);
1434 matthewc 123
1435 jsorg71 450 if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1436 astrand 66 {
1437 astrand 84 DEBUG_KBD(("Filtering event\n"));
1438 astrand 66 continue;
1439     }
1440    
1441 n-ki 54 switch (xevent.type)
1442 matty 9 {
1443 jsorg71 688 case VisibilityNotify:
1444     g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1445     break;
1446 astrand 275 case ClientMessage:
1447     /* the window manager told us to quit */
1448 jsorg71 450 if ((xevent.xclient.message_type == g_protocol_atom)
1449     && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1450 astrand 275 /* Quit */
1451     return 0;
1452     break;
1453    
1454 matty 9 case KeyPress:
1455 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
1456     if (g_IC != NULL)
1457 astrand 66 /* Multi_key compatible version */
1458     {
1459 jsorg71 450 XmbLookupString(g_IC,
1460 astrand 435 &xevent.xkey, str, sizeof(str), &keysym,
1461     &status);
1462 astrand 82 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1463 astrand 66 {
1464 astrand 82 error("XmbLookupString failed with status 0x%x\n",
1465     status);
1466 astrand 66 break;
1467     }
1468     }
1469     else
1470     {
1471     /* Plain old XLookupString */
1472 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1473 astrand 66 XLookupString((XKeyEvent *) & xevent,
1474 astrand 82 str, sizeof(str), &keysym, NULL);
1475 astrand 66 }
1476    
1477 astrand 949 DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1478 astrand 261 get_ksname(keysym)));
1479 astrand 66
1480 matthewc 203 ev_time = time(NULL);
1481     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1482 astrand 118 break;
1483    
1484 astrand 949 xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1485 astrand 976 ev_time, True, 0);
1486 astrand 66 break;
1487 matthewc 203
1488 astrand 66 case KeyRelease:
1489 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
1490 astrand 66 XLookupString((XKeyEvent *) & xevent, str,
1491     sizeof(str), &keysym, NULL);
1492 n-ki 52
1493 astrand 949 DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1494 matthewc 203 get_ksname(keysym)));
1495 n-ki 52
1496 matthewc 203 ev_time = time(NULL);
1497     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1498 astrand 118 break;
1499    
1500 astrand 949 xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1501 astrand 976 ev_time, False, 0);
1502 matty 9 break;
1503    
1504     case ButtonPress:
1505 astrand 988 handle_button_event(xevent, True);
1506     break;
1507 matty 9
1508     case ButtonRelease:
1509 astrand 988 handle_button_event(xevent, False);
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 jdmeijer 905 case MapNotify:
1603     rdp_send_client_window_status(1);
1604     break;
1605     case UnmapNotify:
1606     rdp_send_client_window_status(0);
1607     break;
1608 matty 9 }
1609     }
1610 astrand 275 /* Keep going */
1611     return 1;
1612 matty 9 }
1613    
1614 astrand 275 /* Returns 0 after user quit, 1 otherwise */
1615     int
1616 matty 33 ui_select(int rdp_socket)
1617     {
1618 stargo 606 int n;
1619 matthewc 474 fd_set rfds, wfds;
1620 n-ki 592 struct timeval tv;
1621     BOOL s_timeout = False;
1622 matty 33
1623     while (True)
1624     {
1625 stargo 606 n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1626 matthewc 121 /* Process any events already waiting */
1627 astrand 275 if (!xwin_process_events())
1628     /* User quit */
1629     return 0;
1630 astrand 119
1631 matty 33 FD_ZERO(&rfds);
1632 matthewc 474 FD_ZERO(&wfds);
1633 matty 33 FD_SET(rdp_socket, &rfds);
1634 jsorg71 450 FD_SET(g_x_socket, &rfds);
1635 matty 33
1636 matthewc 474 #ifdef WITH_RDPSND
1637     /* FIXME: there should be an API for registering fds */
1638 stargo 504 if (g_dsp_busy)
1639 matty 33 {
1640 matthewc 474 FD_SET(g_dsp_fd, &wfds);
1641 n-ki 592 n = (g_dsp_fd > n) ? g_dsp_fd : n;
1642 astrand 499 }
1643 matthewc 474 #endif
1644 n-ki 592 /* default timeout */
1645     tv.tv_sec = 60;
1646     tv.tv_usec = 0;
1647 matthewc 474
1648 n-ki 592 /* add redirection handles */
1649     rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1650    
1651     n++;
1652    
1653     switch (select(n, &rfds, &wfds, NULL, &tv))
1654 matthewc 474 {
1655 matty 33 case -1:
1656     error("select: %s\n", strerror(errno));
1657    
1658     case 0:
1659 stargo 795 /* Abort serial read calls */
1660     if (s_timeout)
1661     rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1662 matty 33 continue;
1663     }
1664    
1665 n-ki 592 rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
1666    
1667 stargo 754 if (FD_ISSET(rdp_socket, &rfds))
1668     return 1;
1669    
1670 matthewc 474 #ifdef WITH_RDPSND
1671 stargo 504 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1672 matthewc 474 wave_out_play();
1673     #endif
1674 matty 33 }
1675     }
1676    
1677     void
1678 matty 25 ui_move_pointer(int x, int y)
1679 matty 9 {
1680 jsorg71 450 XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1681 matty 9 }
1682    
1683 matty 25 HBITMAP
1684 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1685 matty 6 {
1686     XImage *image;
1687 matty 9 Pixmap bitmap;
1688 matty 28 uint8 *tdata;
1689 stargo 521 int bitmap_pad;
1690 matty 29
1691 stargo 521 if (g_server_bpp == 8)
1692     {
1693     bitmap_pad = 8;
1694     }
1695     else
1696     {
1697     bitmap_pad = g_bpp;
1698    
1699     if (g_bpp == 24)
1700     bitmap_pad = 32;
1701     }
1702    
1703 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1704     bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1705     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1706 stargo 521 (char *) tdata, width, height, bitmap_pad, 0);
1707 matty 6
1708 jsorg71 725 XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
1709 matty 9
1710     XFree(image);
1711 jsorg71 644 if (tdata != data)
1712 n-ki 279 xfree(tdata);
1713 matty 24 return (HBITMAP) bitmap;
1714 matty 6 }
1715    
1716 matty 25 void
1717 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1718 matty 6 {
1719 matty 10 XImage *image;
1720 matty 29 uint8 *tdata;
1721 stargo 521 int bitmap_pad;
1722    
1723     if (g_server_bpp == 8)
1724     {
1725     bitmap_pad = 8;
1726     }
1727     else
1728     {
1729     bitmap_pad = g_bpp;
1730    
1731     if (g_bpp == 24)
1732     bitmap_pad = 32;
1733     }
1734    
1735 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1736     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1737 stargo 521 (char *) tdata, width, height, bitmap_pad, 0);
1738 matty 28
1739 jsorg71 450 if (g_ownbackstore)
1740 matty 31 {
1741 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1742     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1743 matty 31 }
1744     else
1745     {
1746 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1747 matty 31 }
1748 matty 29
1749 matty 24 XFree(image);
1750 jsorg71 644 if (tdata != data)
1751 n-ki 279 xfree(tdata);
1752 matty 6 }
1753    
1754 matty 25 void
1755     ui_destroy_bitmap(HBITMAP bmp)
1756 matty 6 {
1757 jsorg71 450 XFreePixmap(g_display, (Pixmap) bmp);
1758 matty 10 }
1759    
1760 matty 25 HGLYPH
1761 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1762 matty 10 {
1763 matty 9 XImage *image;
1764     Pixmap bitmap;
1765     int scanline;
1766 matty 6
1767 matty 9 scanline = (width + 7) / 8;
1768 matty 6
1769 jsorg71 450 bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1770 jsorg71 725 if (g_create_glyph_gc == 0)
1771     g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1772 matty 9
1773 jsorg71 450 image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1774 astrand 73 width, height, 8, scanline);
1775 matty 23 image->byte_order = MSBFirst;
1776     image->bitmap_bit_order = MSBFirst;
1777     XInitImage(image);
1778    
1779 jsorg71 725 XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
1780 matty 29
1781 matty 9 XFree(image);
1782 astrand 64 return (HGLYPH) bitmap;
1783 matty 6 }
1784 matty 7
1785 matty 25 void
1786     ui_destroy_glyph(HGLYPH glyph)
1787 matty 7 {
1788 jsorg71 450 XFreePixmap(g_display, (Pixmap) glyph);
1789 matty 9 }
1790    
1791 matty 29 HCURSOR
1792 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1793     uint8 * andmask, uint8 * xormask)
1794 matty 9 {
1795 matty 29 HGLYPH maskglyph, cursorglyph;
1796     XColor bg, fg;
1797     Cursor xcursor;
1798     uint8 *cursor, *pcursor;
1799     uint8 *mask, *pmask;
1800     uint8 nextbit;
1801     int scanline, offset;
1802     int i, j;
1803    
1804     scanline = (width + 7) / 8;
1805     offset = scanline * height;
1806    
1807 forsberg 415 cursor = (uint8 *) xmalloc(offset);
1808 matty 29 memset(cursor, 0, offset);
1809    
1810 forsberg 415 mask = (uint8 *) xmalloc(offset);
1811 matty 29 memset(mask, 0, offset);
1812    
1813     /* approximate AND and XOR masks with a monochrome X pointer */
1814     for (i = 0; i < height; i++)
1815 matty 7 {
1816 matty 29 offset -= scanline;
1817     pcursor = &cursor[offset];
1818     pmask = &mask[offset];
1819    
1820     for (j = 0; j < scanline; j++)
1821 matty 28 {
1822 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1823     {
1824     if (xormask[0] || xormask[1] || xormask[2])
1825     {
1826     *pcursor |= (~(*andmask) & nextbit);
1827     *pmask |= nextbit;
1828     }
1829     else
1830     {
1831     *pcursor |= ((*andmask) & nextbit);
1832     *pmask |= (~(*andmask) & nextbit);
1833     }
1834    
1835     xormask += 3;
1836     }
1837    
1838     andmask++;
1839     pcursor++;
1840     pmask++;
1841 matty 28 }
1842 matty 7 }
1843 matty 29
1844     fg.red = fg.blue = fg.green = 0xffff;
1845     bg.red = bg.blue = bg.green = 0x0000;
1846     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1847    
1848     cursorglyph = ui_create_glyph(width, height, cursor);
1849     maskglyph = ui_create_glyph(width, height, mask);
1850    
1851 astrand 66 xcursor =
1852 jsorg71 450 XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1853 astrand 66 (Pixmap) maskglyph, &fg, &bg, x, y);
1854 astrand 64
1855 matty 29 ui_destroy_glyph(maskglyph);
1856     ui_destroy_glyph(cursorglyph);
1857     xfree(mask);
1858     xfree(cursor);
1859 astrand 64 return (HCURSOR) xcursor;
1860 matty 29 }
1861    
1862     void
1863     ui_set_cursor(HCURSOR cursor)
1864     {
1865 jsorg71 450 g_current_cursor = (Cursor) cursor;
1866     XDefineCursor(g_display, g_wnd, g_current_cursor);
1867 matty 29 }
1868    
1869     void
1870     ui_destroy_cursor(HCURSOR cursor)
1871     {
1872 jsorg71 450 XFreeCursor(g_display, (Cursor) cursor);
1873 matty 29 }
1874    
1875 astrand 508 void
1876     ui_set_null_cursor(void)
1877     {
1878     ui_set_cursor(g_null_cursor);
1879     }
1880    
1881 matty 29 #define MAKE_XCOLOR(xc,c) \
1882     (xc)->red = ((c)->red << 8) | (c)->red; \
1883     (xc)->green = ((c)->green << 8) | (c)->green; \
1884     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1885     (xc)->flags = DoRed | DoGreen | DoBlue;
1886    
1887 n-ki 279
1888 matty 29 HCOLOURMAP
1889 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1890 matty 29 {
1891     COLOURENTRY *entry;
1892     int i, ncolours = colours->ncolours;
1893 jsorg71 450 if (!g_owncolmap)
1894 matty 28 {
1895 jsorg71 450 uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1896 n-ki 279 XColor xentry;
1897     XColor xc_cache[256];
1898     uint32 colour;
1899     int colLookup = 256;
1900     for (i = 0; i < ncolours; i++)
1901 matty 28 {
1902 n-ki 279 entry = &colours->colours[i];
1903     MAKE_XCOLOR(&xentry, entry);
1904 matty 7
1905 jsorg71 450 if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1906 astrand 196 {
1907 n-ki 279 /* Allocation failed, find closest match. */
1908     int j = 256;
1909     int nMinDist = 3 * 256 * 256;
1910     long nDist = nMinDist;
1911 matty 28
1912 n-ki 279 /* only get the colors once */
1913     while (colLookup--)
1914 astrand 196 {
1915 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1916     xc_cache[colLookup].red = xc_cache[colLookup].green =
1917     xc_cache[colLookup].blue = 0;
1918     xc_cache[colLookup].flags = 0;
1919 jsorg71 450 XQueryColor(g_display,
1920     DefaultColormap(g_display,
1921     DefaultScreen(g_display)),
1922 n-ki 279 &xc_cache[colLookup]);
1923 n-ki 185 }
1924 n-ki 279 colLookup = 0;
1925    
1926     /* approximate the pixel */
1927     while (j--)
1928 astrand 196 {
1929 n-ki 279 if (xc_cache[j].flags)
1930     {
1931     nDist = ((long) (xc_cache[j].red >> 8) -
1932     (long) (xentry.red >> 8)) *
1933     ((long) (xc_cache[j].red >> 8) -
1934     (long) (xentry.red >> 8)) +
1935     ((long) (xc_cache[j].green >> 8) -
1936     (long) (xentry.green >> 8)) *
1937     ((long) (xc_cache[j].green >> 8) -
1938     (long) (xentry.green >> 8)) +
1939     ((long) (xc_cache[j].blue >> 8) -
1940     (long) (xentry.blue >> 8)) *
1941     ((long) (xc_cache[j].blue >> 8) -
1942     (long) (xentry.blue >> 8));
1943     }
1944     if (nDist < nMinDist)
1945     {
1946     nMinDist = nDist;
1947     xentry.pixel = j;
1948     }
1949 n-ki 185 }
1950     }
1951 n-ki 279 colour = xentry.pixel;
1952    
1953     /* update our cache */
1954     if (xentry.pixel < 256)
1955     {
1956     xc_cache[xentry.pixel].red = xentry.red;
1957     xc_cache[xentry.pixel].green = xentry.green;
1958     xc_cache[xentry.pixel].blue = xentry.blue;
1959    
1960     }
1961    
1962 matthewc 527 map[i] = colour;
1963 n-ki 185 }
1964 n-ki 279 return map;
1965     }
1966     else
1967     {
1968     XColor *xcolours, *xentry;
1969     Colormap map;
1970 matty 29
1971 forsberg 415 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1972 n-ki 279 for (i = 0; i < ncolours; i++)
1973 astrand 196 {
1974 n-ki 279 entry = &colours->colours[i];
1975     xentry = &xcolours[i];
1976     xentry->pixel = i;
1977     MAKE_XCOLOR(xentry, entry);
1978 matty 29 }
1979    
1980 jsorg71 450 map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1981     XStoreColors(g_display, map, xcolours, ncolours);
1982 n-ki 185
1983 n-ki 279 xfree(xcolours);
1984     return (HCOLOURMAP) map;
1985 matty 29 }
1986 matty 7 }
1987    
1988 matty 25 void
1989     ui_destroy_colourmap(HCOLOURMAP map)
1990 matty 7 {
1991 jsorg71 450 if (!g_owncolmap)
1992 n-ki 279 xfree(map);
1993     else
1994 jsorg71 450 XFreeColormap(g_display, (Colormap) map);
1995 matty 7 }
1996    
1997 matty 25 void
1998     ui_set_colourmap(HCOLOURMAP map)
1999 matty 7 {
2000 jsorg71 450 if (!g_owncolmap)
2001 astrand 448 {
2002 jsorg71 450 if (g_colmap)
2003     xfree(g_colmap);
2004 astrand 448
2005 jsorg71 450 g_colmap = (uint32 *) map;
2006 astrand 448 }
2007 n-ki 279 else
2008 jsorg71 450 XSetWindowColormap(g_display, g_wnd, (Colormap) map);
2009 matty 7 }
2010    
2011 matty 25 void
2012     ui_set_clip(int x, int y, int cx, int cy)
2013 matty 7 {
2014 matty 9 XRectangle rect;
2015 matty 7
2016 matty 9 rect.x = x;
2017     rect.y = y;
2018     rect.width = cx;
2019     rect.height = cy;
2020 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
2021 matty 9 }
2022 matty 7
2023 matty 25 void
2024 matthewc 192 ui_reset_clip(void)
2025 matty 9 {
2026     XRectangle rect;
2027    
2028     rect.x = 0;
2029     rect.y = 0;
2030 jsorg71 447 rect.width = g_width;
2031     rect.height = g_height;
2032 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
2033 matty 7 }
2034    
2035 matty 25 void
2036 matthewc 192 ui_bell(void)
2037 matty 10 {
2038 jsorg71 450 XBell(g_display, 0);
2039 matty 10 }
2040    
2041 matty 25 void
2042     ui_destblt(uint8 opcode,
2043     /* dest */ int x, int y, int cx, int cy)
2044 matty 9 {
2045 matty 29 SET_FUNCTION(opcode);
2046 matty 31 FILL_RECTANGLE(x, y, cx, cy);
2047 matty 29 RESET_FUNCTION(opcode);
2048 matty 9 }
2049    
2050 jsorg71 373 static uint8 hatch_patterns[] = {
2051 forsberg 415 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
2052     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
2053     0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
2054     0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
2055     0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
2056     0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
2057 jsorg71 373 };
2058    
2059 matty 25 void
2060     ui_patblt(uint8 opcode,
2061     /* dest */ int x, int y, int cx, int cy,
2062 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2063 matty 9 {
2064     Pixmap fill;
2065 jsorg71 59 uint8 i, ipattern[8];
2066 matty 9
2067 matty 29 SET_FUNCTION(opcode);
2068 matty 9
2069     switch (brush->style)
2070     {
2071 matty 24 case 0: /* Solid */
2072 matty 29 SET_FOREGROUND(fgcolour);
2073 jsorg71 680 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2074 matty 9 break;
2075    
2076 jsorg71 373 case 2: /* Hatch */
2077 forsberg 415 fill = (Pixmap) ui_create_glyph(8, 8,
2078     hatch_patterns + brush->pattern[0] * 8);
2079 astrand 487 SET_FOREGROUND(fgcolour);
2080     SET_BACKGROUND(bgcolour);
2081 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2082     XSetStipple(g_display, g_gc, fill);
2083     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2084 jsorg71 680 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2085 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
2086     XSetTSOrigin(g_display, g_gc, 0, 0);
2087 jsorg71 373 ui_destroy_glyph((HGLYPH) fill);
2088     break;
2089    
2090 matty 24 case 3: /* Pattern */
2091 jsorg71 59 for (i = 0; i != 8; i++)
2092     ipattern[7 - i] = brush->pattern[i];
2093     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2094 matty 29 SET_FOREGROUND(bgcolour);
2095     SET_BACKGROUND(fgcolour);
2096 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2097     XSetStipple(g_display, g_gc, fill);
2098     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2099 jsorg71 680 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2100 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
2101     XSetTSOrigin(g_display, g_gc, 0, 0);
2102 astrand 64 ui_destroy_glyph((HGLYPH) fill);
2103 matty 9 break;
2104    
2105     default:
2106 matty 30 unimpl("brush %d\n", brush->style);
2107 matty 9 }
2108 matty 29
2109     RESET_FUNCTION(opcode);
2110 jsorg71 680
2111     if (g_ownbackstore)
2112     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2113 matty 9 }
2114    
2115 matty 25 void
2116     ui_screenblt(uint8 opcode,
2117     /* dest */ int x, int y, int cx, int cy,
2118     /* src */ int srcx, int srcy)
2119 matty 9 {
2120 matty 29 SET_FUNCTION(opcode);
2121 jsorg71 450 if (g_ownbackstore)
2122 stargo 609 {
2123 jsorg71 688 if (g_Unobscured)
2124     {
2125     XCopyArea(g_display, g_wnd, 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     else
2130     {
2131     XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2132 astrand 691 XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
2133     y);
2134 jsorg71 688 }
2135 stargo 609 }
2136     else
2137     {
2138     XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2139     }
2140 matty 29 RESET_FUNCTION(opcode);
2141 matty 9 }
2142    
2143 matty 25 void
2144     ui_memblt(uint8 opcode,
2145     /* dest */ int x, int y, int cx, int cy,
2146     /* src */ HBITMAP src, int srcx, int srcy)
2147 matty 9 {
2148 matty 29 SET_FUNCTION(opcode);
2149 jsorg71 450 XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
2150     if (g_ownbackstore)
2151     XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
2152 matty 29 RESET_FUNCTION(opcode);
2153 matty 9 }
2154    
2155 matty 25 void
2156     ui_triblt(uint8 opcode,
2157     /* dest */ int x, int y, int cx, int cy,
2158     /* src */ HBITMAP src, int srcx, int srcy,
2159 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2160 matty 9 {
2161     /* This is potentially difficult to do in general. Until someone
2162 matty 10 comes up with a more efficient way of doing it I am using cases. */
2163 matty 9
2164     switch (opcode)
2165     {
2166 matty 24 case 0x69: /* PDSxxn */
2167 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
2168 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
2169 matty 16 break;
2170    
2171 matty 24 case 0xb8: /* PSDPxax */
2172 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
2173 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
2174 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
2175 matty 9 break;
2176    
2177 matty 29 case 0xc0: /* PSa */
2178 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2179 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
2180 matty 28 break;
2181    
2182 matty 9 default:
2183 matty 30 unimpl("triblt 0x%x\n", opcode);
2184 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
2185 matty 9 }
2186     }
2187    
2188 matty 25 void
2189     ui_line(uint8 opcode,
2190     /* dest */ int startx, int starty, int endx, int endy,
2191 astrand 64 /* pen */ PEN * pen)
2192 matty 9 {
2193 matty 29 SET_FUNCTION(opcode);
2194     SET_FOREGROUND(pen->colour);
2195 jsorg71 450 XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
2196     if (g_ownbackstore)
2197     XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
2198 matty 29 RESET_FUNCTION(opcode);
2199 matty 9 }
2200    
2201 matty 25 void
2202     ui_rect(
2203     /* dest */ int x, int y, int cx, int cy,
2204     /* brush */ int colour)
2205 matty 9 {
2206 matty 29 SET_FOREGROUND(colour);
2207 matty 31 FILL_RECTANGLE(x, y, cx, cy);
2208 matty 9 }
2209    
2210 jdmeijer 831 void
2211     ui_polygon(uint8 opcode,
2212     /* mode */ uint8 fillmode,
2213     /* dest */ POINT * point, int npoints,
2214     /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2215     {
2216     uint8 style, i, ipattern[8];
2217     Pixmap fill;
2218    
2219     SET_FUNCTION(opcode);
2220    
2221     switch (fillmode)
2222     {
2223     case ALTERNATE:
2224     XSetFillRule(g_display, g_gc, EvenOddRule);
2225     break;
2226     case WINDING:
2227     XSetFillRule(g_display, g_gc, WindingRule);
2228     break;
2229     default:
2230     unimpl("fill mode %d\n", fillmode);
2231     }
2232    
2233     if (brush)
2234     style = brush->style;
2235     else
2236     style = 0;
2237    
2238     switch (style)
2239     {
2240     case 0: /* Solid */
2241     SET_FOREGROUND(fgcolour);
2242     FILL_POLYGON((XPoint *) point, npoints);
2243     break;
2244    
2245     case 2: /* Hatch */
2246     fill = (Pixmap) ui_create_glyph(8, 8,
2247     hatch_patterns + brush->pattern[0] * 8);
2248     SET_FOREGROUND(fgcolour);
2249     SET_BACKGROUND(bgcolour);
2250     XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2251     XSetStipple(g_display, g_gc, fill);
2252     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2253     FILL_POLYGON((XPoint *) point, npoints);
2254     XSetFillStyle(g_display, g_gc, FillSolid);
2255     XSetTSOrigin(g_display, g_gc, 0, 0);
2256     ui_destroy_glyph((HGLYPH) fill);
2257     break;
2258    
2259     case 3: /* Pattern */
2260     for (i = 0; i != 8; i++)
2261     ipattern[7 - i] = brush->pattern[i];
2262     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2263     SET_FOREGROUND(bgcolour);
2264     SET_BACKGROUND(fgcolour);
2265     XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2266     XSetStipple(g_display, g_gc, fill);
2267     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2268     FILL_POLYGON((XPoint *) point, npoints);
2269     XSetFillStyle(g_display, g_gc, FillSolid);
2270     XSetTSOrigin(g_display, g_gc, 0, 0);
2271     ui_destroy_glyph((HGLYPH) fill);
2272     break;
2273    
2274     default:
2275     unimpl("brush %d\n", brush->style);
2276     }
2277    
2278     RESET_FUNCTION(opcode);
2279     }
2280    
2281     void
2282 jdmeijer 844 ui_polyline(uint8 opcode,
2283     /* dest */ POINT * points, int npoints,
2284     /* pen */ PEN * pen)
2285     {
2286     /* TODO: set join style */
2287     SET_FUNCTION(opcode);
2288     SET_FOREGROUND(pen->colour);
2289     XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2290     if (g_ownbackstore)
2291     XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2292     CoordModePrevious);
2293     RESET_FUNCTION(opcode);
2294     }
2295    
2296     void
2297 jdmeijer 831 ui_ellipse(uint8 opcode,
2298     /* mode */ uint8 fillmode,
2299     /* dest */ int x, int y, int cx, int cy,
2300     /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2301     {
2302     uint8 style, i, ipattern[8];
2303     Pixmap fill;
2304    
2305     SET_FUNCTION(opcode);
2306    
2307     if (brush)
2308     style = brush->style;
2309     else
2310     style = 0;
2311    
2312     switch (style)
2313     {
2314     case 0: /* Solid */
2315     SET_FOREGROUND(fgcolour);
2316     DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2317     break;
2318    
2319     case 2: /* Hatch */
2320     fill = (Pixmap) ui_create_glyph(8, 8,
2321     hatch_patterns + brush->pattern[0] * 8);
2322     SET_FOREGROUND(fgcolour);
2323     SET_BACKGROUND(bgcolour);
2324     XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2325     XSetStipple(g_display, g_gc, fill);
2326     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2327     DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2328     XSetFillStyle(g_display, g_gc, FillSolid);
2329     XSetTSOrigin(g_display, g_gc, 0, 0);
2330     ui_destroy_glyph((HGLYPH) fill);
2331     break;
2332    
2333     case 3: /* Pattern */
2334     for (i = 0; i != 8; i++)
2335     ipattern[7 - i] = brush->pattern[i];
2336     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2337     SET_FOREGROUND(bgcolour);
2338     SET_BACKGROUND(fgcolour);
2339     XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2340     XSetStipple(g_display, g_gc, fill);
2341     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2342     DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2343     XSetFillStyle(g_display, g_gc, FillSolid);
2344     XSetTSOrigin(g_display, g_gc, 0, 0);
2345     ui_destroy_glyph((HGLYPH) fill);
2346     break;
2347    
2348     default:
2349     unimpl("brush %d\n", brush->style);
2350     }
2351    
2352     RESET_FUNCTION(opcode);
2353     }
2354    
2355 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
2356 matty 25 void
2357     ui_draw_glyph(int mixmode,
2358     /* dest */ int x, int y, int cx, int cy,
2359 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
2360     int bgcolour, int fgcolour)
2361 matty 9 {
2362 matty 29 SET_FOREGROUND(fgcolour);
2363     SET_BACKGROUND(bgcolour);
2364 matty 9
2365 jsorg71 450 XSetFillStyle(g_display, g_gc,
2366 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2367 jsorg71 450 XSetStipple(g_display, g_gc, (Pixmap) glyph);
2368     XSetTSOrigin(g_display, g_gc, x, y);
2369 matty 9
2370 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2371 matty 9
2372 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
2373 matty 9 }
2374    
2375 mmihalik 49 #define DO_GLYPH(ttext,idx) \
2376     {\
2377     glyph = cache_get_font (font, ttext[idx]);\
2378     if (!(flags & TEXT2_IMPLICIT_X))\
2379 jsorg71 564 {\
2380     xyoffset = ttext[++idx];\
2381     if ((xyoffset & 0x80))\
2382 mmihalik 49 {\
2383 jsorg71 564 if (flags & TEXT2_VERTICAL)\
2384     y += ttext[idx+1] | (ttext[idx+2] << 8);\
2385 mmihalik 49 else\
2386 jsorg71 564 x += ttext[idx+1] | (ttext[idx+2] << 8);\
2387     idx += 2;\
2388 mmihalik 49 }\
2389 jsorg71 564 else\
2390 mmihalik 49 {\
2391 jsorg71 564 if (flags & TEXT2_VERTICAL)\
2392     y += xyoffset;\
2393     else\
2394     x += xyoffset;\
2395 mmihalik 49 }\
2396 jsorg71 564 }\
2397     if (glyph != NULL)\
2398     {\
2399     x1 = x + glyph->offset;\
2400     y1 = y + glyph->baseline;\
2401     XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2402     XSetTSOrigin(g_display, g_gc, x1, y1);\
2403     FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2404     if (flags & TEXT2_IMPLICIT_X)\
2405     x += glyph->width;\
2406     }\
2407 mmihalik 49 }
2408    
2409 matty 25 void
2410 jdmeijer 843 ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y,
2411 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
2412 jdmeijer 843 int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2413     int bgcolour, int fgcolour, uint8 * text, uint8 length)
2414 matty 9 {
2415 jdmeijer 843 /* TODO: use brush appropriately */
2416    
2417 matty 10 FONTGLYPH *glyph;
2418 jsorg71 564 int i, j, xyoffset, x1, y1;
2419 mmihalik 49 DATABLOB *entry;
2420 matty 9
2421 matty 29 SET_FOREGROUND(bgcolour);
2422 matty 28
2423 astrand 620 /* Sometimes, the boxcx value is something really large, like
2424     32691. This makes XCopyArea fail with Xvnc. The code below
2425     is a quick fix. */
2426     if (boxx + boxcx > g_width)
2427     boxcx = g_width - boxx;
2428    
2429 matty 9 if (boxcx > 1)
2430 matty 31 {
2431 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2432 matty 31 }
2433 matty 17 else if (mixmode == MIX_OPAQUE)
2434 matty 31 {
2435 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2436 matty 31 }
2437 matty 9
2438 jsorg71 564 SET_FOREGROUND(fgcolour);
2439     SET_BACKGROUND(bgcolour);
2440     XSetFillStyle(g_display, g_gc, FillStippled);
2441    
2442 matty 9 /* Paint text, character by character */
2443 astrand 64 for (i = 0; i < length;)
2444     {
2445     switch (text[i])
2446     {
2447     case 0xff:
2448 astrand 1029 if (i + 3 > length)
2449 astrand 64 {
2450 astrand 1029 /* short command, skip */
2451     i = length = 0;
2452     break;
2453 astrand 64 }
2454 astrand 1029 cache_put_text(text[i + 1], text, text[i + 2]);
2455     i += 3;
2456     length -= i;
2457 astrand 64 /* this will move pointer from start to first character after FF command */
2458 astrand 1029 text = &(text[i]);
2459 astrand 64 i = 0;
2460 mmihalik 49 break;
2461 matty 9
2462 astrand 64 case 0xfe:
2463 astrand 1029 if (i + 3 > length)
2464     {
2465     /* short command, skip */
2466     i = length = 0;
2467     break;
2468     }
2469 astrand 64 entry = cache_get_text(text[i + 1]);
2470     if (entry != NULL)
2471     {
2472     if ((((uint8 *) (entry->data))[1] ==
2473 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
2474 astrand 64 {
2475     if (flags & TEXT2_VERTICAL)
2476     y += text[i + 2];
2477     else
2478     x += text[i + 2];
2479     }
2480     for (j = 0; j < entry->size; j++)
2481 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
2482 matthewc 44 }
2483 astrand 1029 i += 3;
2484 jsorg71 286 length -= i;
2485     /* this will move pointer from start to first character after FE command */
2486     text = &(text[i]);
2487     i = 0;
2488 astrand 64 break;
2489 matty 17
2490 astrand 64 default:
2491     DO_GLYPH(text, i);
2492     i++;
2493     break;
2494 matty 29 }
2495 mmihalik 49 }
2496 jsorg71 564
2497     XSetFillStyle(g_display, g_gc, FillSolid);
2498    
2499 jsorg71 450 if (g_ownbackstore)
2500 jsorg71 278 {
2501     if (boxcx > 1)
2502 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2503 jsorg71 278 boxy, boxcx, boxcy, boxx, boxy);
2504     else
2505 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2506 jsorg71 278 clipy, clipcx, clipcy, clipx, clipy);
2507     }
2508 matty 9 }
2509    
2510 matty 25 void
2511     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
2512 matty 9 {
2513 matty 28 Pixmap pix;
2514 matty 9 XImage *image;
2515    
2516 jsorg71 450 if (g_ownbackstore)
2517 matty 31 {
2518 jsorg71 450 image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
2519 matty 31 }
2520     else
2521     {
2522 jsorg71 450 pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2523     XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
2524     image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2525     XFreePixmap(g_display, pix);
2526 matty 31 }
2527 matty 28
2528 jsorg71 450 offset *= g_bpp / 8;
2529     cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
2530 matty 28
2531     XDestroyImage(image);
2532 matty 9 }
2533    
2534 matty 25 void
2535     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
2536 matty 9 {
2537     XImage *image;
2538 matty 10 uint8 *data;
2539 matty 9
2540 jsorg71 450 offset *= g_bpp / 8;
2541     data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2542 matty 10 if (data == NULL)
2543     return;
2544 matty 29
2545 jsorg71 450 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2546     (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
2547 matty 29
2548 jsorg71 450 if (g_ownbackstore)
2549 matty 31 {
2550 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2551     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2552 matty 31 }
2553     else
2554     {
2555 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2556 matty 31 }
2557    
2558 matty 9 XFree(image);
2559     }
2560 jsorg71 713
2561     /* these do nothing here but are used in uiports */
2562     void
2563     ui_begin_update(void)
2564     {
2565     }
2566    
2567     void
2568     ui_end_update(void)
2569     {
2570     }

  ViewVC Help
Powered by ViewVC 1.1.26