/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 844 - (hide annotations)
Thu Mar 10 22:48:15 2005 UTC (19 years, 2 months ago) by jdmeijer
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 56298 byte(s)
do polyline in a single ui operation: ui_polyline

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

  ViewVC Help
Powered by ViewVC 1.1.26