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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 976 - (hide annotations)
Thu Aug 4 13:39:57 2005 UTC (18 years, 9 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 56471 byte(s)
Protection against recursive sequences

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

  ViewVC Help
Powered by ViewVC 1.1.26