/[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 991 - (hide annotations)
Fri Aug 26 07:01:02 2005 UTC (18 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 56893 byte(s)
Disable moving in single-app mode when window is occupying entire
workarea.

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

  ViewVC Help
Powered by ViewVC 1.1.26