/[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 498 - (hide annotations)
Tue Oct 14 12:05:27 2003 UTC (20 years, 7 months ago) by astrand
File MIME type: text/plain
File size: 41883 byte(s)
xkeymap_init must be before using g_enable_compose.

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 matthewc 207 Copyright (C) Matthew Chapman 1999-2002
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 matty 10 #include <time.h>
24 matty 33 #include <errno.h>
25 matty 10 #include "rdesktop.h"
26 forsberg 415 #include "xproto.h"
27 matty 6
28 jsorg71 447 extern int g_width;
29     extern int g_height;
30     extern BOOL g_sendmotion;
31     extern BOOL g_fullscreen;
32 jsorg71 450 extern BOOL g_grab_keyboard;
33     extern BOOL g_hide_decorations;
34     extern char g_title[];
35 jsorg71 438 extern int g_server_bpp;
36 jsorg71 450 extern int g_win_button_size;
37 matty 10
38 jsorg71 450 Display *g_display;
39     Time g_last_gesturetime;
40     static int g_x_socket;
41     static Screen *g_screen;
42     Window g_wnd;
43 matthewc 481 BOOL g_enable_compose = False;
44 jsorg71 450 static GC g_gc;
45     static Visual *g_visual;
46     static int g_depth;
47     static int g_bpp;
48     static XIM g_IM;
49     static XIC g_IC;
50     static XModifierKeymap *g_mod_map;
51     static Cursor g_current_cursor;
52     static Atom g_protocol_atom, g_kill_atom;
53 matthewc 481 static BOOL g_focused;
54     static BOOL g_mouse_in_wnd;
55 matty 29
56 matty 33 /* endianness */
57 jsorg71 450 static BOOL g_host_be;
58     static BOOL g_xserver_be;
59 matty 33
60     /* software backing store */
61 jsorg71 450 static BOOL g_ownbackstore;
62     static Pixmap g_backstore;
63 matty 31
64 astrand 342 /* Moving in single app mode */
65 jsorg71 450 static BOOL g_moving_wnd;
66     static int g_move_x_offset = 0;
67     static int g_move_y_offset = 0;
68 astrand 342
69 matthewc 474 #ifdef WITH_RDPSND
70     extern int g_dsp_fd;
71     extern BOOL g_dsp_busy;
72     #endif
73    
74 astrand 262 /* MWM decorations */
75     #define MWM_HINTS_DECORATIONS (1L << 1)
76     #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
77     typedef struct
78     {
79 matthewc 301 uint32 flags;
80     uint32 functions;
81     uint32 decorations;
82     sint32 inputMode;
83     uint32 status;
84 astrand 262 }
85     PropMotifWmHints;
86    
87 jsorg71 316 typedef struct
88     {
89     uint32 red;
90     uint32 green;
91     uint32 blue;
92     }
93     PixelColour;
94 astrand 262
95 forsberg 415
96 matty 31 #define FILL_RECTANGLE(x,y,cx,cy)\
97     { \
98 jsorg71 450 XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
99     if (g_ownbackstore) \
100     XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
101 matty 31 }
102    
103 matthewc 296 #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
104 jsorg71 281 { \
105 jsorg71 450 XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
106 jsorg71 281 }
107    
108 matty 33 /* colour maps */
109 jsorg71 450 BOOL g_owncolmap = False;
110     static Colormap g_xcolmap;
111     static uint32 *g_colmap = NULL;
112 matty 10
113 jsorg71 450 #define TRANSLATE(col) ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : translate_colour(g_colmap[col]) )
114     #define SET_FOREGROUND(col) XSetForeground(g_display, g_gc, TRANSLATE(col));
115     #define SET_BACKGROUND(col) XSetBackground(g_display, g_gc, TRANSLATE(col));
116 matty 28
117     static int rop2_map[] = {
118     GXclear, /* 0 */
119     GXnor, /* DPon */
120     GXandInverted, /* DPna */
121     GXcopyInverted, /* Pn */
122     GXandReverse, /* PDna */
123     GXinvert, /* Dn */
124     GXxor, /* DPx */
125     GXnand, /* DPan */
126     GXand, /* DPa */
127     GXequiv, /* DPxn */
128     GXnoop, /* D */
129     GXorInverted, /* DPno */
130     GXcopy, /* P */
131     GXorReverse, /* PDno */
132     GXor, /* DPo */
133     GXset /* 1 */
134     };
135    
136 jsorg71 450 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
137     #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
138 matty 29
139 astrand 319 static void
140 astrand 262 mwm_hide_decorations(void)
141     {
142     PropMotifWmHints motif_hints;
143     Atom hintsatom;
144    
145     /* setup the property */
146     motif_hints.flags = MWM_HINTS_DECORATIONS;
147     motif_hints.decorations = 0;
148    
149     /* get the atom for the property */
150 jsorg71 450 hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
151 astrand 262 if (!hintsatom)
152     {
153 matthewc 297 warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
154 astrand 262 return;
155     }
156    
157 jsorg71 450 XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
158 astrand 262 (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
159     }
160    
161 astrand 319 static PixelColour
162 jsorg71 316 split_colour15(uint32 colour)
163 jsorg71 311 {
164 jsorg71 316 PixelColour rv;
165     rv.red = (colour & 0x7c00) >> 10;
166     rv.red = (rv.red * 0xff) / 0x1f;
167     rv.green = (colour & 0x03e0) >> 5;
168     rv.green = (rv.green * 0xff) / 0x1f;
169     rv.blue = (colour & 0x1f);
170     rv.blue = (rv.blue * 0xff) / 0x1f;
171     return rv;
172 jsorg71 311 }
173    
174 astrand 319 static PixelColour
175 jsorg71 316 split_colour16(uint32 colour)
176 jsorg71 311 {
177 jsorg71 316 PixelColour rv;
178     rv.red = (colour & 0xf800) >> 11;
179     rv.red = (rv.red * 0xff) / 0x1f;
180     rv.green = (colour & 0x07e0) >> 5;
181     rv.green = (rv.green * 0xff) / 0x3f;
182     rv.blue = (colour & 0x001f);
183     rv.blue = (rv.blue * 0xff) / 0x1f;
184     return rv;
185 jsorg71 311 }
186    
187 astrand 319 static PixelColour
188 jsorg71 316 split_colour24(uint32 colour)
189 jsorg71 311 {
190 jsorg71 316 PixelColour rv;
191     rv.blue = (colour & 0xff0000) >> 16;
192     rv.green = (colour & 0xff00) >> 8;
193     rv.red = (colour & 0xff);
194     return rv;
195 jsorg71 311 }
196    
197 astrand 319 static uint32
198 astrand 318 make_colour16(PixelColour pc)
199 jsorg71 316 {
200     pc.red = (pc.red * 0x1f) / 0xff;
201     pc.green = (pc.green * 0x3f) / 0xff;
202     pc.blue = (pc.blue * 0x1f) / 0xff;
203     return (pc.red << 11) | (pc.green << 5) | pc.blue;
204     }
205    
206 astrand 319 static uint32
207 astrand 318 make_colour24(PixelColour pc)
208 jsorg71 316 {
209 jsorg71 472 if (g_xserver_be)
210     {
211     return pc.red | (pc.green << 8) | (pc.blue << 16);
212     }
213     else
214     {
215     return (pc.red << 16) | (pc.green << 8) | pc.blue;
216     }
217 jsorg71 316 }
218    
219 astrand 319 static uint32
220 astrand 318 make_colour32(PixelColour pc)
221 jsorg71 316 {
222 jsorg71 472 if (g_xserver_be)
223     {
224     return pc.red | (pc.green << 8) | (pc.blue << 16);
225     }
226     else
227     {
228     return (pc.red << 16) | (pc.green << 8) | pc.blue;
229     }
230 jsorg71 316 }
231    
232 jsorg71 311 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
233     #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
234     #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
235     x = (x << 16) | (x >> 16); }
236    
237     static uint32
238     translate_colour(uint32 colour)
239     {
240 jsorg71 438 switch (g_server_bpp)
241 jsorg71 311 {
242 jsorg71 316 case 15:
243 jsorg71 450 switch (g_bpp)
244 jsorg71 316 {
245     case 16:
246     colour = make_colour16(split_colour15(colour));
247     break;
248     case 24:
249     colour = make_colour24(split_colour15(colour));
250     break;
251     case 32:
252     colour = make_colour32(split_colour15(colour));
253     break;
254     }
255     break;
256 jsorg71 311 case 16:
257 jsorg71 450 switch (g_bpp)
258 jsorg71 311 {
259     case 16:
260     break;
261     case 24:
262 jsorg71 316 colour = make_colour24(split_colour16(colour));
263 jsorg71 311 break;
264     case 32:
265 jsorg71 316 colour = make_colour32(split_colour16(colour));
266 jsorg71 311 break;
267     }
268     break;
269     case 24:
270 jsorg71 450 switch (g_bpp)
271 jsorg71 311 {
272 jsorg71 316 case 16:
273     colour = make_colour16(split_colour24(colour));
274     break;
275 jsorg71 311 case 24:
276     break;
277     case 32:
278 jsorg71 316 colour = make_colour32(split_colour24(colour));
279 jsorg71 311 break;
280     }
281     break;
282     }
283     return colour;
284     }
285    
286 matty 28 static void
287 jsorg71 311 translate8to8(uint8 * data, uint8 * out, uint8 * end)
288 matty 28 {
289 matty 29 while (out < end)
290 jsorg71 450 *(out++) = (uint8) g_colmap[*(data++)];
291 matty 29 }
292 matty 28
293 matty 29 static void
294 jsorg71 311 translate8to16(uint8 * data, uint16 * out, uint16 * end)
295 matty 29 {
296     while (out < end)
297 jsorg71 450 *(out++) = (uint16) g_colmap[*(data++)];
298 matty 29 }
299    
300 jsorg71 316 /* little endian - conversion happens when colourmap is built */
301 jsorg71 311 static void
302 jsorg71 316 translate8to24(uint8 * data, uint8 * out, uint8 * end)
303 jsorg71 311 {
304 jsorg71 316 uint32 value;
305    
306 jsorg71 311 while (out < end)
307 jsorg71 316 {
308 jsorg71 450 value = g_colmap[*(data++)];
309 jsorg71 316 *(out++) = value;
310     *(out++) = value >> 8;
311     *(out++) = value >> 16;
312     }
313 jsorg71 311 }
314    
315 matty 29 static void
316 jsorg71 316 translate8to32(uint8 * data, uint32 * out, uint32 * end)
317 matty 29 {
318 jsorg71 316 while (out < end)
319 jsorg71 450 *(out++) = g_colmap[*(data++)];
320 jsorg71 316 }
321    
322     /* todo the remaining translate function might need some big endian check ?? */
323    
324     static void
325 jsorg71 483 translate15to16(uint16 * data, uint8 * out, uint8 * end)
326 jsorg71 316 {
327 jsorg71 483 uint16 pixel;
328     uint16 value;
329    
330 jsorg71 316 while (out < end)
331 jsorg71 483 {
332     pixel = *(data++);
333    
334     if (g_host_be)
335     {
336     BSWAP16(pixel)
337     }
338    
339     value = make_colour16(split_colour15(pixel));
340    
341     if (g_xserver_be)
342     {
343     *(out++) = value >> 8;
344     *(out++) = value;
345     }
346     else
347     {
348     *(out++) = value;
349     *(out++) = value >> 8;
350     }
351     }
352 jsorg71 316 }
353    
354     static void
355     translate15to24(uint16 * data, uint8 * out, uint8 * end)
356     {
357 matty 29 uint32 value;
358 jsorg71 483 uint16 pixel;
359 matty 29
360     while (out < end)
361 matty 28 {
362 jsorg71 483 pixel = *(data++);
363    
364     if (g_host_be)
365     {
366     BSWAP16(pixel)
367     }
368    
369     value = make_colour24(split_colour15(pixel));
370     if (g_xserver_be)
371     {
372     *(out++) = value >> 16;
373     *(out++) = value >> 8;
374     *(out++) = value;
375     }
376     else
377     {
378     *(out++) = value;
379     *(out++) = value >> 8;
380     *(out++) = value >> 16;
381     }
382 matty 28 }
383     }
384    
385     static void
386 jsorg71 483 translate15to32(uint16 * data, uint8 * out, uint8 * end)
387 jsorg71 316 {
388 jsorg71 472 uint16 pixel;
389 jsorg71 483 uint32 value;
390 jsorg71 472
391 jsorg71 316 while (out < end)
392 jsorg71 472 {
393 jsorg71 483 pixel = *(data++);
394    
395 jsorg71 472 if (g_host_be)
396     {
397 jsorg71 483 BSWAP16(pixel);
398 jsorg71 472 }
399 jsorg71 483
400     value = make_colour32(split_colour15(pixel));
401    
402     if (g_xserver_be)
403     {
404     *(out++) = value >> 24;
405     *(out++) = value >> 16;
406     *(out++) = value >> 8;
407     *(out++) = value;
408     }
409 jsorg71 472 else
410     {
411 jsorg71 483 *(out++) = value;
412     *(out++) = value >> 8;
413     *(out++) = value >> 16;
414     *(out++) = value >> 24;
415 jsorg71 472 }
416     }
417 jsorg71 316 }
418    
419     static void
420     translate16to16(uint16 * data, uint16 * out, uint16 * end)
421     {
422 jsorg71 483 uint16 value;
423    
424     if (g_xserver_be)
425     {
426     while (out < end)
427     {
428     value = *data;
429     BSWAP16(value);
430     *out = value;
431     data++;
432     out++;
433     }
434    
435     }
436     else
437     {
438     while (out < end)
439     {
440     *out = *data;
441     out++;
442     data++;
443     }
444     }
445 jsorg71 316 }
446    
447    
448     static void
449 jsorg71 311 translate16to24(uint16 * data, uint8 * out, uint8 * end)
450 matty 28 {
451 jsorg71 311 uint32 value;
452 jsorg71 483 uint16 pixel;
453 jsorg71 311
454 matty 29 while (out < end)
455 jsorg71 311 {
456 jsorg71 483 pixel = *(data++);
457    
458     if (g_host_be)
459     {
460     BSWAP16(pixel)
461     }
462    
463     value = make_colour24(split_colour16(pixel));
464    
465     if (g_xserver_be)
466     {
467     *(out++) = value >> 16;
468     *(out++) = value >> 8;
469     *(out++) = value;
470     }
471     else
472     {
473     *(out++) = value;
474     *(out++) = value >> 8;
475     *(out++) = value >> 16;
476     }
477 jsorg71 311 }
478     }
479    
480     static void
481 jsorg71 483 translate16to32(uint16 * data, uint8 * out, uint8 * end)
482 jsorg71 311 {
483 jsorg71 472 uint16 pixel;
484 jsorg71 483 uint32 value;
485 jsorg71 472
486 jsorg71 311 while (out < end)
487 jsorg71 472 {
488 jsorg71 483 pixel = *(data++);
489    
490 jsorg71 472 if (g_host_be)
491     {
492 jsorg71 483 BSWAP16(pixel)
493 jsorg71 472 }
494 jsorg71 483
495     value = make_colour32(split_colour16(pixel));
496    
497     if (g_xserver_be)
498 jsorg71 472 {
499 jsorg71 483 *(out++) = value >> 24;
500     *(out++) = value >> 16;
501     *(out++) = value >> 8;
502     *(out++) = value;
503     }
504     else
505     {
506     *(out++) = value;
507     *(out++) = value >> 8;
508     *(out++) = value >> 16;
509     *(out++) = value >> 24;
510     }
511     }
512 matty 28 }
513    
514 jsorg71 311 static void
515 jsorg71 483 translate24to16(uint8 * data, uint8 * out, uint8 * end)
516 jsorg71 311 {
517 jsorg71 316 uint32 pixel = 0;
518 jsorg71 483 uint16 value;
519 jsorg71 311 while (out < end)
520 jsorg71 316 {
521     pixel = *(data++) << 16;
522     pixel |= *(data++) << 8;
523     pixel |= *(data++);
524 jsorg71 483
525     value = (uint16) make_colour16(split_colour24(pixel));
526    
527     if (g_xserver_be)
528     {
529     *(out++) = value >> 8;
530     *(out++) = value;
531     }
532     else
533     {
534     *(out++) = value;
535     *(out++) = value >> 8;
536     }
537 jsorg71 316 }
538 jsorg71 311 }
539    
540 jsorg71 316 static void
541     translate24to24(uint8 * data, uint8 * out, uint8 * end)
542     {
543     while (out < end)
544     {
545     *(out++) = (*(data++));
546     }
547     }
548    
549     static void
550 jsorg71 483 translate24to32(uint8 * data, uint8 * out, uint8 * end)
551 jsorg71 316 {
552     while (out < end)
553     {
554 jsorg71 483 if (g_xserver_be)
555 jsorg71 472 {
556 jsorg71 483 *(out++) = 0x00;
557     *(out++) = *(data++);
558     *(out++) = *(data++);
559     *(out++) = *(data++);
560 jsorg71 472 }
561     else
562     {
563 jsorg71 483 *(out++) = *(data++);
564     *(out++) = *(data++);
565     *(out++) = *(data++);
566     *(out++) = 0x00;
567 jsorg71 472 }
568 jsorg71 316 }
569     }
570    
571 matty 29 static uint8 *
572 astrand 64 translate_image(int width, int height, uint8 * data)
573 matty 28 {
574 jsorg71 450 int size = width * height * g_bpp / 8;
575 forsberg 415 uint8 *out = (uint8 *) xmalloc(size);
576 matty 29 uint8 *end = out + size;
577    
578 jsorg71 438 switch (g_server_bpp)
579 jsorg71 311 {
580 jsorg71 316 case 24:
581 jsorg71 450 switch (g_bpp)
582 jsorg71 316 {
583     case 32:
584 jsorg71 483 translate24to32(data, out, end);
585 jsorg71 316 break;
586     case 24:
587     translate24to24(data, out, end);
588     break;
589     case 16:
590 jsorg71 483 translate24to16(data, out, end);
591 jsorg71 316 break;
592     }
593 matty 29 break;
594     case 16:
595 jsorg71 450 switch (g_bpp)
596 jsorg71 316 {
597     case 32:
598 jsorg71 483 translate16to32((uint16 *) data, out, end);
599 jsorg71 316 break;
600     case 24:
601     translate16to24((uint16 *) data, out, end);
602     break;
603     case 16:
604 astrand 318 translate16to16((uint16 *) data, (uint16 *) out,
605     (uint16 *) end);
606 jsorg71 316 break;
607     }
608 matty 29 break;
609 jsorg71 316 case 15:
610 jsorg71 450 switch (g_bpp)
611 jsorg71 316 {
612     case 32:
613 jsorg71 483 translate15to32((uint16 *) data, out, end);
614 jsorg71 316 break;
615     case 24:
616     translate15to24((uint16 *) data, out, end);
617     break;
618     case 16:
619 jsorg71 483 translate15to16((uint16 *) data, out, end);
620 jsorg71 316 break;
621     }
622 matty 29 break;
623 jsorg71 316 case 8:
624 jsorg71 450 switch (g_bpp)
625 jsorg71 316 {
626     case 8:
627     translate8to8(data, out, end);
628     break;
629     case 16:
630     translate8to16(data, (uint16 *) out, (uint16 *) end);
631     break;
632     case 24:
633     translate8to24(data, out, end);
634     break;
635     case 32:
636     translate8to32(data, (uint32 *) out, (uint32 *) end);
637     break;
638     }
639 matty 29 break;
640     }
641     return out;
642 matty 28 }
643    
644 astrand 118 BOOL
645 matthewc 209 get_key_state(unsigned int state, uint32 keysym)
646 astrand 102 {
647 matthewc 203 int modifierpos, key, keysymMask = 0;
648 astrand 102 int offset;
649    
650 jsorg71 450 KeyCode keycode = XKeysymToKeycode(g_display, keysym);
651 astrand 102
652     if (keycode == NoSymbol)
653     return False;
654    
655     for (modifierpos = 0; modifierpos < 8; modifierpos++)
656     {
657 jsorg71 450 offset = g_mod_map->max_keypermod * modifierpos;
658 astrand 102
659 jsorg71 450 for (key = 0; key < g_mod_map->max_keypermod; key++)
660 astrand 102 {
661 jsorg71 450 if (g_mod_map->modifiermap[offset + key] == keycode)
662 matthewc 203 keysymMask |= 1 << modifierpos;
663 astrand 102 }
664     }
665    
666 matthewc 203 return (state & keysymMask) ? True : False;
667 astrand 102 }
668    
669 jsorg71 81 BOOL
670 matthewc 192 ui_init(void)
671 jsorg71 81 {
672 matthewc 121 XPixmapFormatValues *pfm;
673     uint16 test;
674     int i;
675    
676 jsorg71 450 g_display = XOpenDisplay(NULL);
677     if (g_display == NULL)
678 jsorg71 81 {
679 matthewc 210 error("Failed to open display: %s\n", XDisplayName(NULL));
680 jsorg71 81 return False;
681     }
682 matthewc 121
683 jsorg71 450 g_x_socket = ConnectionNumber(g_display);
684     g_screen = DefaultScreenOfDisplay(g_display);
685     g_visual = DefaultVisualOfScreen(g_screen);
686     g_depth = DefaultDepthOfScreen(g_screen);
687 matthewc 121
688 jsorg71 450 pfm = XListPixmapFormats(g_display, &i);
689 matthewc 121 if (pfm != NULL)
690     {
691     /* Use maximum bpp for this depth - this is generally
692     desirable, e.g. 24 bits->32 bits. */
693     while (i--)
694     {
695 jsorg71 450 if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
696 matthewc 121 {
697 jsorg71 450 g_bpp = pfm[i].bits_per_pixel;
698 matthewc 121 }
699     }
700     XFree(pfm);
701     }
702    
703 jsorg71 450 if (g_bpp < 8)
704 matthewc 121 {
705     error("Less than 8 bpp not currently supported.\n");
706 jsorg71 450 XCloseDisplay(g_display);
707 matthewc 121 return False;
708     }
709    
710 jsorg71 450 if (g_owncolmap != True)
711 n-ki 279 {
712 jsorg71 450 g_xcolmap = DefaultColormapOfScreen(g_screen);
713     if (g_depth <= 8)
714 matthewc 297 warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
715 n-ki 279 }
716    
717 jsorg71 450 g_gc = XCreateGC(g_display, RootWindowOfScreen(g_screen), 0, NULL);
718 matthewc 121
719 jsorg71 450 if (DoesBackingStore(g_screen) != Always)
720     g_ownbackstore = True;
721 matthewc 121
722     test = 1;
723 jsorg71 450 g_host_be = !(BOOL) (*(uint8 *) (&test));
724     g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
725 matthewc 121
726 jsorg71 447 if ((g_width == 0) || (g_height == 0))
727 astrand 263 {
728     /* Fetch geometry from _NET_WORKAREA */
729 matthewc 300 uint32 x, y, cx, cy;
730 astrand 263
731 matthewc 300 if (get_current_workarea(&x, &y, &cx, &cy) == 0)
732 astrand 263 {
733 jsorg71 447 g_width = cx;
734     g_height = cy;
735 matthewc 300 }
736     else
737     {
738 matthewc 297 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
739 jsorg71 447 g_width = 800;
740     g_height = 600;
741 astrand 263 }
742     }
743    
744 jsorg71 447 if (g_fullscreen)
745 jsorg71 81 {
746 jsorg71 450 g_width = WidthOfScreen(g_screen);
747     g_height = HeightOfScreen(g_screen);
748 jsorg71 81 }
749 matthewc 121
750 matthewc 160 /* make sure width is a multiple of 4 */
751 jsorg71 447 g_width = (g_width + 3) & ~3;
752 matthewc 160
753 jsorg71 450 if (g_ownbackstore)
754 matthewc 188 {
755 jsorg71 450 g_backstore =
756     XCreatePixmap(g_display, RootWindowOfScreen(g_screen), g_width, g_height,
757     g_depth);
758 matthewc 188
759     /* clear to prevent rubbish being exposed at startup */
760 jsorg71 450 XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
761     XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
762 matthewc 188 }
763    
764 jsorg71 450 g_mod_map = XGetModifierMapping(g_display);
765 matthewc 203
766 astrand 498 xkeymap_init();
767    
768 jsorg71 447 if (g_enable_compose)
769 jsorg71 450 g_IM = XOpenIM(g_display, NULL, NULL, NULL);
770 matthewc 188
771 matthewc 432 xclip_init();
772 jsorg71 316
773     /* todo take this out when high colour is done */
774 jsorg71 450 printf("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth);
775 jsorg71 316
776 jsorg71 81 return True;
777     }
778 astrand 66
779 matthewc 188 void
780 matthewc 192 ui_deinit(void)
781 matthewc 188 {
782 jsorg71 450 if (g_IM != NULL)
783     XCloseIM(g_IM);
784 matthewc 188
785 jsorg71 450 XFreeModifiermap(g_mod_map);
786 matthewc 203
787 jsorg71 450 if (g_ownbackstore)
788     XFreePixmap(g_display, g_backstore);
789 matthewc 188
790 jsorg71 450 XFreeGC(g_display, g_gc);
791     XCloseDisplay(g_display);
792     g_display = NULL;
793 matthewc 188 }
794    
795 matthewc 121 BOOL
796 matthewc 192 ui_create_window(void)
797 matty 6 {
798 matthewc 121 XSetWindowAttributes attribs;
799 matty 28 XClassHint *classhints;
800     XSizeHints *sizehints;
801 matthewc 188 int wndwidth, wndheight;
802 matthewc 432 long input_mask, ic_input_mask;
803 jsorg71 100 XEvent xevent;
804    
805 jsorg71 450 wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
806     wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
807 matthewc 188
808 jsorg71 450 attribs.background_pixel = BlackPixelOfScreen(g_screen);
809     attribs.backing_store = g_ownbackstore ? NotUseful : Always;
810 jsorg71 447 attribs.override_redirect = g_fullscreen;
811 matthewc 188
812 jsorg71 450 g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
813 astrand 456 0, CopyFromParent, InputOutput, CopyFromParent,
814     CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
815 jsorg71 100
816 jsorg71 450 XStoreName(g_display, g_wnd, g_title);
817 jsorg71 100
818 jsorg71 450 if (g_hide_decorations)
819 astrand 262 mwm_hide_decorations();
820    
821 jsorg71 100 classhints = XAllocClassHint();
822     if (classhints != NULL)
823     {
824     classhints->res_name = classhints->res_class = "rdesktop";
825 jsorg71 450 XSetClassHint(g_display, g_wnd, classhints);
826 jsorg71 100 XFree(classhints);
827     }
828    
829     sizehints = XAllocSizeHints();
830     if (sizehints)
831     {
832     sizehints->flags = PMinSize | PMaxSize;
833 jsorg71 447 sizehints->min_width = sizehints->max_width = g_width;
834     sizehints->min_height = sizehints->max_height = g_height;
835 jsorg71 450 XSetWMNormalHints(g_display, g_wnd, sizehints);
836 jsorg71 100 XFree(sizehints);
837     }
838    
839 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
840 jsorg71 257 VisibilityChangeMask | FocusChangeMask;
841 matthewc 121
842 jsorg71 447 if (g_sendmotion)
843 matthewc 121 input_mask |= PointerMotionMask;
844 jsorg71 450 if (g_ownbackstore)
845 matthewc 121 input_mask |= ExposureMask;
846 jsorg71 450 if (g_fullscreen || g_grab_keyboard)
847 matthewc 250 input_mask |= EnterWindowMask;
848 jsorg71 450 if (g_grab_keyboard)
849 jsorg71 257 input_mask |= LeaveWindowMask;
850 jsorg71 100
851 jsorg71 450 if (g_IM != NULL)
852 matthewc 188 {
853 jsorg71 450 g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
854 astrand 456 XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
855 matthewc 188
856 jsorg71 450 if ((g_IC != NULL)
857     && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
858 matthewc 188 input_mask |= ic_input_mask;
859     }
860    
861 jsorg71 450 XSelectInput(g_display, g_wnd, input_mask);
862     XMapWindow(g_display, g_wnd);
863 jsorg71 100
864 matthewc 208 /* wait for VisibilityNotify */
865 astrand 196 do
866     {
867 jsorg71 450 XMaskEvent(g_display, VisibilityChangeMask, &xevent);
868 astrand 196 }
869 matthewc 208 while (xevent.type != VisibilityNotify);
870 matthewc 123
871 jsorg71 447 g_focused = False;
872     g_mouse_in_wnd = False;
873 jsorg71 257
874 astrand 275 /* handle the WM_DELETE_WINDOW protocol */
875 jsorg71 450 g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
876     g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
877     XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
878 astrand 275
879 matty 10 return True;
880 matty 6 }
881    
882 matty 25 void
883 matthewc 192 ui_destroy_window(void)
884 matty 6 {
885 jsorg71 450 if (g_IC != NULL)
886     XDestroyIC(g_IC);
887 matty 31
888 jsorg71 450 XDestroyWindow(g_display, g_wnd);
889 matty 6 }
890    
891 jsorg71 100 void
892 matthewc 192 xwin_toggle_fullscreen(void)
893 jsorg71 100 {
894 matthewc 188 Pixmap contents = 0;
895 matthewc 123
896 jsorg71 450 if (!g_ownbackstore)
897 matthewc 188 {
898     /* need to save contents of window */
899 jsorg71 450 contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
900     XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
901 matthewc 188 }
902    
903     ui_destroy_window();
904 jsorg71 447 g_fullscreen = !g_fullscreen;
905 matthewc 188 ui_create_window();
906 matthewc 123
907 jsorg71 450 XDefineCursor(g_display, g_wnd, g_current_cursor);
908 matthewc 188
909 jsorg71 450 if (!g_ownbackstore)
910 matthewc 188 {
911 jsorg71 450 XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
912     XFreePixmap(g_display, contents);
913 matthewc 188 }
914 jsorg71 100 }
915    
916 jsorg71 447 /* Process all events in Xlib queue
917 astrand 275 Returns 0 after user quit, 1 otherwise */
918     static int
919 matthewc 192 xwin_process_events(void)
920 matty 9 {
921 n-ki 54 XEvent xevent;
922 matthewc 38 KeySym keysym;
923 matthewc 50 uint16 button, flags;
924 matty 10 uint32 ev_time;
925 astrand 66 key_translation tr;
926     char str[256];
927     Status status;
928 matthewc 203 unsigned int state;
929     Window wdummy;
930     int dummy;
931 matty 9
932 jsorg71 450 while (XPending(g_display) > 0)
933 matty 9 {
934 jsorg71 450 XNextEvent(g_display, &xevent);
935 matthewc 123
936 jsorg71 450 if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
937 astrand 66 {
938 astrand 84 DEBUG_KBD(("Filtering event\n"));
939 astrand 66 continue;
940     }
941    
942 matthewc 50 flags = 0;
943 matty 10
944 n-ki 54 switch (xevent.type)
945 matty 9 {
946 astrand 275 case ClientMessage:
947     /* the window manager told us to quit */
948 jsorg71 450 if ((xevent.xclient.message_type == g_protocol_atom)
949     && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
950 astrand 275 /* Quit */
951     return 0;
952     break;
953    
954 matty 9 case KeyPress:
955 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
956     if (g_IC != NULL)
957 astrand 66 /* Multi_key compatible version */
958     {
959 jsorg71 450 XmbLookupString(g_IC,
960 astrand 435 &xevent.xkey, str, sizeof(str), &keysym,
961     &status);
962 astrand 82 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
963 astrand 66 {
964 astrand 82 error("XmbLookupString failed with status 0x%x\n",
965     status);
966 astrand 66 break;
967     }
968     }
969     else
970     {
971     /* Plain old XLookupString */
972 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
973 astrand 66 XLookupString((XKeyEvent *) & xevent,
974 astrand 82 str, sizeof(str), &keysym, NULL);
975 astrand 66 }
976    
977 astrand 261 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
978     get_ksname(keysym)));
979 astrand 66
980 matthewc 203 ev_time = time(NULL);
981     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
982 astrand 118 break;
983    
984 astrand 66 tr = xkeymap_translate_key(keysym,
985 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
986 astrand 69
987 astrand 66 if (tr.scancode == 0)
988 n-ki 52 break;
989    
990 astrand 470 save_remote_modifiers(tr.scancode);
991 astrand 115 ensure_remote_modifiers(ev_time, tr);
992 astrand 449 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
993 astrand 470 restore_remote_modifiers(ev_time, tr.scancode);
994 astrand 115
995 astrand 66 break;
996 matthewc 203
997 astrand 66 case KeyRelease:
998 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
999 astrand 66 XLookupString((XKeyEvent *) & xevent, str,
1000     sizeof(str), &keysym, NULL);
1001 n-ki 52
1002 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1003 matthewc 203 get_ksname(keysym)));
1004 n-ki 52
1005 matthewc 203 ev_time = time(NULL);
1006     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1007 astrand 118 break;
1008    
1009 astrand 66 tr = xkeymap_translate_key(keysym,
1010 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
1011 astrand 66
1012     if (tr.scancode == 0)
1013     break;
1014    
1015 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
1016 matty 9 break;
1017    
1018     case ButtonPress:
1019 matthewc 50 flags = MOUSE_FLAG_DOWN;
1020     /* fall through */
1021 matty 9
1022     case ButtonRelease:
1023 jsorg71 450 g_last_gesturetime = xevent.xbutton.time;
1024 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
1025 matty 9 if (button == 0)
1026     break;
1027    
1028 astrand 328 /* If win_button_size is nonzero, enable single app mode */
1029 jsorg71 450 if (xevent.xbutton.y < g_win_button_size)
1030 astrand 328 {
1031 astrand 342 /* Stop moving window when button is released, regardless of cursor position */
1032 jsorg71 450 if (g_moving_wnd && (xevent.type == ButtonRelease))
1033     g_moving_wnd = False;
1034 astrand 332
1035 astrand 342 /* Check from right to left: */
1036    
1037 jsorg71 450 if (xevent.xbutton.x >= g_width - g_win_button_size)
1038 astrand 328 {
1039 astrand 331 /* The close button, continue */
1040 astrand 328 ;
1041     }
1042 astrand 456 else if (xevent.xbutton.x >=
1043     g_width - g_win_button_size * 2)
1044 astrand 328 {
1045     /* The maximize/restore button. Do not send to
1046     server. It might be a good idea to change the
1047 jsorg71 447 cursor or give some other visible indication
1048 astrand 328 that rdesktop inhibited this click */
1049     break;
1050     }
1051 astrand 456 else if (xevent.xbutton.x >=
1052     g_width - g_win_button_size * 3)
1053 astrand 328 {
1054     /* The minimize button. Iconify window. */
1055 jsorg71 450 XIconifyWindow(g_display, g_wnd,
1056     DefaultScreen(g_display));
1057 astrand 328 break;
1058     }
1059 jsorg71 450 else if (xevent.xbutton.x <= g_win_button_size)
1060 astrand 342 {
1061     /* The system menu. Ignore. */
1062     break;
1063     }
1064 astrand 332 else
1065     {
1066 astrand 342 /* The title bar. */
1067 jsorg71 447 if ((xevent.type == ButtonPress) && !g_fullscreen
1068 jsorg71 450 && g_hide_decorations)
1069 astrand 342 {
1070 jsorg71 450 g_moving_wnd = True;
1071     g_move_x_offset = xevent.xbutton.x;
1072     g_move_y_offset = xevent.xbutton.y;
1073 astrand 342 }
1074 astrand 332 break;
1075 astrand 342
1076 astrand 332 }
1077 astrand 328 }
1078    
1079 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1080 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
1081 matty 10 break;
1082    
1083     case MotionNotify:
1084 jsorg71 450 if (g_moving_wnd)
1085 astrand 342 {
1086 jsorg71 450 XMoveWindow(g_display, g_wnd,
1087     xevent.xmotion.x_root - g_move_x_offset,
1088     xevent.xmotion.y_root - g_move_y_offset);
1089 astrand 342 break;
1090     }
1091    
1092 jsorg71 447 if (g_fullscreen && !g_focused)
1093 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1094 jsorg71 288 CurrentTime);
1095 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1096 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1097 matty 28 break;
1098    
1099 matthewc 194 case FocusIn:
1100 jsorg71 257 if (xevent.xfocus.mode == NotifyGrab)
1101     break;
1102 jsorg71 447 g_focused = True;
1103 jsorg71 450 XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy,
1104 astrand 261 &dummy, &dummy, &state);
1105 matthewc 203 reset_modifier_keys(state);
1106 jsorg71 450 if (g_grab_keyboard && g_mouse_in_wnd)
1107     XGrabKeyboard(g_display, g_wnd, True,
1108 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
1109 matty 28 break;
1110    
1111 matthewc 194 case FocusOut:
1112 jsorg71 257 if (xevent.xfocus.mode == NotifyUngrab)
1113     break;
1114 jsorg71 447 g_focused = False;
1115 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
1116 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1117 matty 28 break;
1118 matty 31
1119 matthewc 250 case EnterNotify:
1120     /* we only register for this event when in fullscreen mode */
1121 jsorg71 257 /* or grab_keyboard */
1122 jsorg71 447 g_mouse_in_wnd = True;
1123     if (g_fullscreen)
1124 jsorg71 257 {
1125 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1126 astrand 261 CurrentTime);
1127 jsorg71 257 break;
1128     }
1129 jsorg71 447 if (g_focused)
1130 jsorg71 450 XGrabKeyboard(g_display, g_wnd, True,
1131 jsorg71 257 GrabModeAsync, GrabModeAsync, CurrentTime);
1132 matthewc 250 break;
1133    
1134 matthewc 253 case LeaveNotify:
1135 jsorg71 257 /* we only register for this event when grab_keyboard */
1136 jsorg71 447 g_mouse_in_wnd = False;
1137 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1138 matthewc 253 break;
1139    
1140 matty 31 case Expose:
1141 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1142 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
1143 astrand 64 xevent.xexpose.width,
1144     xevent.xexpose.height,
1145 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
1146 matty 31 break;
1147 astrand 119
1148     case MappingNotify:
1149     /* Refresh keyboard mapping if it has changed. This is important for
1150     Xvnc, since it allocates keycodes dynamically */
1151     if (xevent.xmapping.request == MappingKeyboard
1152     || xevent.xmapping.request == MappingModifier)
1153     XRefreshKeyboardMapping(&xevent.xmapping);
1154 matthewc 203
1155     if (xevent.xmapping.request == MappingModifier)
1156     {
1157 jsorg71 450 XFreeModifiermap(g_mod_map);
1158     g_mod_map = XGetModifierMapping(g_display);
1159 matthewc 203 }
1160 astrand 119 break;
1161 matthewc 432
1162 astrand 435 /* clipboard stuff */
1163 forsberg 415 case SelectionNotify:
1164 matthewc 432 xclip_handle_SelectionNotify(&xevent.xselection);
1165 forsberg 415 break;
1166     case SelectionRequest:
1167 matthewc 432 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1168 forsberg 415 break;
1169 matthewc 432 case SelectionClear:
1170     xclip_handle_SelectionClear();
1171     break;
1172 forsberg 415 case PropertyNotify:
1173 matthewc 432 xclip_handle_PropertyNotify(&xevent.xproperty);
1174 forsberg 415 break;
1175 matty 9 }
1176     }
1177 astrand 275 /* Keep going */
1178     return 1;
1179 matty 9 }
1180    
1181 astrand 275 /* Returns 0 after user quit, 1 otherwise */
1182     int
1183 matty 33 ui_select(int rdp_socket)
1184     {
1185 jsorg71 450 int n = (rdp_socket > g_x_socket) ? rdp_socket + 1 : g_x_socket + 1;
1186 matthewc 474 fd_set rfds, wfds;
1187 matty 33
1188     while (True)
1189     {
1190 matthewc 121 /* Process any events already waiting */
1191 astrand 275 if (!xwin_process_events())
1192     /* User quit */
1193     return 0;
1194 astrand 119
1195 matty 33 FD_ZERO(&rfds);
1196 matthewc 474 FD_ZERO(&wfds);
1197 matty 33 FD_SET(rdp_socket, &rfds);
1198 jsorg71 450 FD_SET(g_x_socket, &rfds);
1199 matty 33
1200 matthewc 474 #ifdef WITH_RDPSND
1201     /* FIXME: there should be an API for registering fds */
1202     if (g_dsp_busy)
1203 matty 33 {
1204 matthewc 474 FD_SET(g_dsp_fd, &wfds);
1205     n = (g_dsp_fd + 1 > n) ? g_dsp_fd + 1 : n;
1206     }
1207     #endif
1208    
1209     switch (select(n, &rfds, &wfds, NULL, NULL))
1210     {
1211 matty 33 case -1:
1212     error("select: %s\n", strerror(errno));
1213    
1214     case 0:
1215     continue;
1216     }
1217    
1218     if (FD_ISSET(rdp_socket, &rfds))
1219 astrand 275 return 1;
1220 matthewc 474
1221     #ifdef WITH_RDPSND
1222 matthewc 478 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1223 matthewc 474 wave_out_play();
1224     #endif
1225 matty 33 }
1226     }
1227    
1228     void
1229 matty 25 ui_move_pointer(int x, int y)
1230 matty 9 {
1231 jsorg71 450 XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1232 matty 9 }
1233    
1234 matty 25 HBITMAP
1235 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1236 matty 6 {
1237     XImage *image;
1238 matty 9 Pixmap bitmap;
1239 matty 28 uint8 *tdata;
1240 matty 29
1241 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1242     bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1243     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1244     (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1245 matty 6
1246 jsorg71 450 XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1247 matty 9
1248     XFree(image);
1249 jsorg71 450 if (!g_owncolmap)
1250 n-ki 279 xfree(tdata);
1251 matty 24 return (HBITMAP) bitmap;
1252 matty 6 }
1253    
1254 matty 25 void
1255 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1256 matty 6 {
1257 matty 10 XImage *image;
1258 matty 29 uint8 *tdata;
1259 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1260     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1261     (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1262 matty 28
1263 jsorg71 450 if (g_ownbackstore)
1264 matty 31 {
1265 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1266     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1267 matty 31 }
1268     else
1269     {
1270 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1271 matty 31 }
1272 matty 29
1273 matty 24 XFree(image);
1274 jsorg71 450 if (!g_owncolmap)
1275 n-ki 279 xfree(tdata);
1276 matty 6 }
1277    
1278 matty 25 void
1279     ui_destroy_bitmap(HBITMAP bmp)
1280 matty 6 {
1281 jsorg71 450 XFreePixmap(g_display, (Pixmap) bmp);
1282 matty 10 }
1283    
1284 matty 25 HGLYPH
1285 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1286 matty 10 {
1287 matty 9 XImage *image;
1288     Pixmap bitmap;
1289     int scanline;
1290     GC gc;
1291 matty 6
1292 matty 9 scanline = (width + 7) / 8;
1293 matty 6
1294 jsorg71 450 bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1295     gc = XCreateGC(g_display, bitmap, 0, NULL);
1296 matty 9
1297 jsorg71 450 image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1298 astrand 73 width, height, 8, scanline);
1299 matty 23 image->byte_order = MSBFirst;
1300     image->bitmap_bit_order = MSBFirst;
1301     XInitImage(image);
1302    
1303 jsorg71 450 XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1304 matty 29
1305 matty 9 XFree(image);
1306 jsorg71 450 XFreeGC(g_display, gc);
1307 astrand 64 return (HGLYPH) bitmap;
1308 matty 6 }
1309 matty 7
1310 matty 25 void
1311     ui_destroy_glyph(HGLYPH glyph)
1312 matty 7 {
1313 jsorg71 450 XFreePixmap(g_display, (Pixmap) glyph);
1314 matty 9 }
1315    
1316 matty 29 HCURSOR
1317 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1318     uint8 * andmask, uint8 * xormask)
1319 matty 9 {
1320 matty 29 HGLYPH maskglyph, cursorglyph;
1321     XColor bg, fg;
1322     Cursor xcursor;
1323     uint8 *cursor, *pcursor;
1324     uint8 *mask, *pmask;
1325     uint8 nextbit;
1326     int scanline, offset;
1327     int i, j;
1328    
1329     scanline = (width + 7) / 8;
1330     offset = scanline * height;
1331    
1332 forsberg 415 cursor = (uint8 *) xmalloc(offset);
1333 matty 29 memset(cursor, 0, offset);
1334    
1335 forsberg 415 mask = (uint8 *) xmalloc(offset);
1336 matty 29 memset(mask, 0, offset);
1337    
1338     /* approximate AND and XOR masks with a monochrome X pointer */
1339     for (i = 0; i < height; i++)
1340 matty 7 {
1341 matty 29 offset -= scanline;
1342     pcursor = &cursor[offset];
1343     pmask = &mask[offset];
1344    
1345     for (j = 0; j < scanline; j++)
1346 matty 28 {
1347 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1348     {
1349     if (xormask[0] || xormask[1] || xormask[2])
1350     {
1351     *pcursor |= (~(*andmask) & nextbit);
1352     *pmask |= nextbit;
1353     }
1354     else
1355     {
1356     *pcursor |= ((*andmask) & nextbit);
1357     *pmask |= (~(*andmask) & nextbit);
1358     }
1359    
1360     xormask += 3;
1361     }
1362    
1363     andmask++;
1364     pcursor++;
1365     pmask++;
1366 matty 28 }
1367 matty 7 }
1368 matty 29
1369     fg.red = fg.blue = fg.green = 0xffff;
1370     bg.red = bg.blue = bg.green = 0x0000;
1371     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1372    
1373     cursorglyph = ui_create_glyph(width, height, cursor);
1374     maskglyph = ui_create_glyph(width, height, mask);
1375    
1376 astrand 66 xcursor =
1377 jsorg71 450 XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1378 astrand 66 (Pixmap) maskglyph, &fg, &bg, x, y);
1379 astrand 64
1380 matty 29 ui_destroy_glyph(maskglyph);
1381     ui_destroy_glyph(cursorglyph);
1382     xfree(mask);
1383     xfree(cursor);
1384 astrand 64 return (HCURSOR) xcursor;
1385 matty 29 }
1386    
1387     void
1388     ui_set_cursor(HCURSOR cursor)
1389     {
1390 jsorg71 450 g_current_cursor = (Cursor) cursor;
1391     XDefineCursor(g_display, g_wnd, g_current_cursor);
1392 matty 29 }
1393    
1394     void
1395     ui_destroy_cursor(HCURSOR cursor)
1396     {
1397 jsorg71 450 XFreeCursor(g_display, (Cursor) cursor);
1398 matty 29 }
1399    
1400     #define MAKE_XCOLOR(xc,c) \
1401     (xc)->red = ((c)->red << 8) | (c)->red; \
1402     (xc)->green = ((c)->green << 8) | (c)->green; \
1403     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1404     (xc)->flags = DoRed | DoGreen | DoBlue;
1405    
1406 n-ki 279
1407 matty 29 HCOLOURMAP
1408 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1409 matty 29 {
1410     COLOURENTRY *entry;
1411     int i, ncolours = colours->ncolours;
1412 jsorg71 450 if (!g_owncolmap)
1413 matty 28 {
1414 jsorg71 450 uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1415 n-ki 279 XColor xentry;
1416     XColor xc_cache[256];
1417     uint32 colour;
1418     int colLookup = 256;
1419     for (i = 0; i < ncolours; i++)
1420 matty 28 {
1421 n-ki 279 entry = &colours->colours[i];
1422     MAKE_XCOLOR(&xentry, entry);
1423 matty 7
1424 jsorg71 450 if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1425 astrand 196 {
1426 n-ki 279 /* Allocation failed, find closest match. */
1427     int j = 256;
1428     int nMinDist = 3 * 256 * 256;
1429     long nDist = nMinDist;
1430 matty 28
1431 n-ki 279 /* only get the colors once */
1432     while (colLookup--)
1433 astrand 196 {
1434 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1435     xc_cache[colLookup].red = xc_cache[colLookup].green =
1436     xc_cache[colLookup].blue = 0;
1437     xc_cache[colLookup].flags = 0;
1438 jsorg71 450 XQueryColor(g_display,
1439     DefaultColormap(g_display,
1440     DefaultScreen(g_display)),
1441 n-ki 279 &xc_cache[colLookup]);
1442 n-ki 185 }
1443 n-ki 279 colLookup = 0;
1444    
1445     /* approximate the pixel */
1446     while (j--)
1447 astrand 196 {
1448 n-ki 279 if (xc_cache[j].flags)
1449     {
1450     nDist = ((long) (xc_cache[j].red >> 8) -
1451     (long) (xentry.red >> 8)) *
1452     ((long) (xc_cache[j].red >> 8) -
1453     (long) (xentry.red >> 8)) +
1454     ((long) (xc_cache[j].green >> 8) -
1455     (long) (xentry.green >> 8)) *
1456     ((long) (xc_cache[j].green >> 8) -
1457     (long) (xentry.green >> 8)) +
1458     ((long) (xc_cache[j].blue >> 8) -
1459     (long) (xentry.blue >> 8)) *
1460     ((long) (xc_cache[j].blue >> 8) -
1461     (long) (xentry.blue >> 8));
1462     }
1463     if (nDist < nMinDist)
1464     {
1465     nMinDist = nDist;
1466     xentry.pixel = j;
1467     }
1468 n-ki 185 }
1469     }
1470 n-ki 279 colour = xentry.pixel;
1471    
1472     /* update our cache */
1473     if (xentry.pixel < 256)
1474     {
1475     xc_cache[xentry.pixel].red = xentry.red;
1476     xc_cache[xentry.pixel].green = xentry.green;
1477     xc_cache[xentry.pixel].blue = xentry.blue;
1478    
1479     }
1480    
1481    
1482     /* byte swap here to make translate_image faster */
1483     map[i] = translate_colour(colour);
1484 n-ki 185 }
1485 n-ki 279 return map;
1486     }
1487     else
1488     {
1489     XColor *xcolours, *xentry;
1490     Colormap map;
1491 matty 29
1492 forsberg 415 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1493 n-ki 279 for (i = 0; i < ncolours; i++)
1494 astrand 196 {
1495 n-ki 279 entry = &colours->colours[i];
1496     xentry = &xcolours[i];
1497     xentry->pixel = i;
1498     MAKE_XCOLOR(xentry, entry);
1499 matty 29 }
1500    
1501 jsorg71 450 map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1502     XStoreColors(g_display, map, xcolours, ncolours);
1503 n-ki 185
1504 n-ki 279 xfree(xcolours);
1505     return (HCOLOURMAP) map;
1506 matty 29 }
1507 matty 7 }
1508    
1509 matty 25 void
1510     ui_destroy_colourmap(HCOLOURMAP map)
1511 matty 7 {
1512 jsorg71 450 if (!g_owncolmap)
1513 n-ki 279 xfree(map);
1514     else
1515 jsorg71 450 XFreeColormap(g_display, (Colormap) map);
1516 matty 7 }
1517    
1518 matty 25 void
1519     ui_set_colourmap(HCOLOURMAP map)
1520 matty 7 {
1521 jsorg71 450 if (!g_owncolmap)
1522 astrand 448 {
1523 jsorg71 450 if (g_colmap)
1524     xfree(g_colmap);
1525 astrand 448
1526 jsorg71 450 g_colmap = (uint32 *) map;
1527 astrand 448 }
1528 n-ki 279 else
1529 jsorg71 450 XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1530 matty 7 }
1531    
1532 matty 25 void
1533     ui_set_clip(int x, int y, int cx, int cy)
1534 matty 7 {
1535 matty 9 XRectangle rect;
1536 matty 7
1537 matty 9 rect.x = x;
1538     rect.y = y;
1539     rect.width = cx;
1540     rect.height = cy;
1541 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1542 matty 9 }
1543 matty 7
1544 matty 25 void
1545 matthewc 192 ui_reset_clip(void)
1546 matty 9 {
1547     XRectangle rect;
1548    
1549     rect.x = 0;
1550     rect.y = 0;
1551 jsorg71 447 rect.width = g_width;
1552     rect.height = g_height;
1553 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1554 matty 7 }
1555    
1556 matty 25 void
1557 matthewc 192 ui_bell(void)
1558 matty 10 {
1559 jsorg71 450 XBell(g_display, 0);
1560 matty 10 }
1561    
1562 matty 25 void
1563     ui_destblt(uint8 opcode,
1564     /* dest */ int x, int y, int cx, int cy)
1565 matty 9 {
1566 matty 29 SET_FUNCTION(opcode);
1567 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1568 matty 29 RESET_FUNCTION(opcode);
1569 matty 9 }
1570    
1571 jsorg71 373 static uint8 hatch_patterns[] = {
1572 forsberg 415 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1573     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1574     0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1575     0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1576     0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1577     0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
1578 jsorg71 373 };
1579    
1580 matty 25 void
1581     ui_patblt(uint8 opcode,
1582     /* dest */ int x, int y, int cx, int cy,
1583 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1584 matty 9 {
1585     Pixmap fill;
1586 jsorg71 59 uint8 i, ipattern[8];
1587 matty 9
1588 matty 29 SET_FUNCTION(opcode);
1589 matty 9
1590     switch (brush->style)
1591     {
1592 matty 24 case 0: /* Solid */
1593 matty 29 SET_FOREGROUND(fgcolour);
1594 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1595 matty 9 break;
1596    
1597 jsorg71 373 case 2: /* Hatch */
1598 forsberg 415 fill = (Pixmap) ui_create_glyph(8, 8,
1599     hatch_patterns + brush->pattern[0] * 8);
1600 astrand 487 SET_FOREGROUND(fgcolour);
1601     SET_BACKGROUND(bgcolour);
1602 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1603     XSetStipple(g_display, g_gc, fill);
1604     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1605 jsorg71 373 FILL_RECTANGLE(x, y, cx, cy);
1606 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1607     XSetTSOrigin(g_display, g_gc, 0, 0);
1608 jsorg71 373 ui_destroy_glyph((HGLYPH) fill);
1609     break;
1610    
1611 matty 24 case 3: /* Pattern */
1612 jsorg71 59 for (i = 0; i != 8; i++)
1613     ipattern[7 - i] = brush->pattern[i];
1614     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1615 matty 9
1616 matty 29 SET_FOREGROUND(bgcolour);
1617     SET_BACKGROUND(fgcolour);
1618 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1619     XSetStipple(g_display, g_gc, fill);
1620     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1621 matty 9
1622 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1623 matty 9
1624 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1625     XSetTSOrigin(g_display, g_gc, 0, 0);
1626 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1627 matty 9 break;
1628    
1629     default:
1630 matty 30 unimpl("brush %d\n", brush->style);
1631 matty 9 }
1632 matty 29
1633     RESET_FUNCTION(opcode);
1634 matty 9 }
1635    
1636 matty 25 void
1637     ui_screenblt(uint8 opcode,
1638     /* dest */ int x, int y, int cx, int cy,
1639     /* src */ int srcx, int srcy)
1640 matty 9 {
1641 matty 29 SET_FUNCTION(opcode);
1642 jsorg71 450 XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1643     if (g_ownbackstore)
1644     XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1645 matty 29 RESET_FUNCTION(opcode);
1646 matty 9 }
1647    
1648 matty 25 void
1649     ui_memblt(uint8 opcode,
1650     /* dest */ int x, int y, int cx, int cy,
1651     /* src */ HBITMAP src, int srcx, int srcy)
1652 matty 9 {
1653 matty 29 SET_FUNCTION(opcode);
1654 jsorg71 450 XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1655     if (g_ownbackstore)
1656     XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1657 matty 29 RESET_FUNCTION(opcode);
1658 matty 9 }
1659    
1660 matty 25 void
1661     ui_triblt(uint8 opcode,
1662     /* dest */ int x, int y, int cx, int cy,
1663     /* src */ HBITMAP src, int srcx, int srcy,
1664 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1665 matty 9 {
1666     /* This is potentially difficult to do in general. Until someone
1667 matty 10 comes up with a more efficient way of doing it I am using cases. */
1668 matty 9
1669     switch (opcode)
1670     {
1671 matty 24 case 0x69: /* PDSxxn */
1672 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1673 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1674 matty 16 break;
1675    
1676 matty 24 case 0xb8: /* PSDPxax */
1677 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1678 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1679 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1680 matty 9 break;
1681    
1682 matty 29 case 0xc0: /* PSa */
1683 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1684 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1685 matty 28 break;
1686    
1687 matty 9 default:
1688 matty 30 unimpl("triblt 0x%x\n", opcode);
1689 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1690 matty 9 }
1691     }
1692    
1693 matty 25 void
1694     ui_line(uint8 opcode,
1695     /* dest */ int startx, int starty, int endx, int endy,
1696 astrand 64 /* pen */ PEN * pen)
1697 matty 9 {
1698 matty 29 SET_FUNCTION(opcode);
1699     SET_FOREGROUND(pen->colour);
1700 jsorg71 450 XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1701     if (g_ownbackstore)
1702     XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1703 matty 29 RESET_FUNCTION(opcode);
1704 matty 9 }
1705    
1706 matty 25 void
1707     ui_rect(
1708     /* dest */ int x, int y, int cx, int cy,
1709     /* brush */ int colour)
1710 matty 9 {
1711 matty 29 SET_FOREGROUND(colour);
1712 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1713 matty 9 }
1714    
1715 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
1716 matty 25 void
1717     ui_draw_glyph(int mixmode,
1718     /* dest */ int x, int y, int cx, int cy,
1719 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1720     int bgcolour, int fgcolour)
1721 matty 9 {
1722 matty 29 SET_FOREGROUND(fgcolour);
1723     SET_BACKGROUND(bgcolour);
1724 matty 9
1725 jsorg71 450 XSetFillStyle(g_display, g_gc,
1726 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1727 jsorg71 450 XSetStipple(g_display, g_gc, (Pixmap) glyph);
1728     XSetTSOrigin(g_display, g_gc, x, y);
1729 matty 9
1730 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1731 matty 9
1732 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1733 matty 9 }
1734    
1735 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1736     {\
1737     glyph = cache_get_font (font, ttext[idx]);\
1738     if (!(flags & TEXT2_IMPLICIT_X))\
1739     {\
1740     xyoffset = ttext[++idx];\
1741     if ((xyoffset & 0x80))\
1742     {\
1743     if (flags & TEXT2_VERTICAL) \
1744 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1745 mmihalik 49 else\
1746 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1747     idx += 2;\
1748 mmihalik 49 }\
1749     else\
1750     {\
1751     if (flags & TEXT2_VERTICAL) \
1752     y += xyoffset;\
1753     else\
1754     x += xyoffset;\
1755     }\
1756     }\
1757     if (glyph != NULL)\
1758     {\
1759 matthewc 299 ui_draw_glyph (mixmode, x + glyph->offset,\
1760     y + glyph->baseline,\
1761 mmihalik 49 glyph->width, glyph->height,\
1762     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1763     if (flags & TEXT2_IMPLICIT_X)\
1764     x += glyph->width;\
1765     }\
1766     }
1767    
1768 matty 25 void
1769     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1770 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1771     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1772 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1773 matty 9 {
1774 matty 10 FONTGLYPH *glyph;
1775 mmihalik 49 int i, j, xyoffset;
1776     DATABLOB *entry;
1777 matty 9
1778 matty 29 SET_FOREGROUND(bgcolour);
1779 matty 28
1780 matty 9 if (boxcx > 1)
1781 matty 31 {
1782 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1783 matty 31 }
1784 matty 17 else if (mixmode == MIX_OPAQUE)
1785 matty 31 {
1786 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1787 matty 31 }
1788 matty 9
1789     /* Paint text, character by character */
1790 astrand 64 for (i = 0; i < length;)
1791     {
1792     switch (text[i])
1793     {
1794     case 0xff:
1795     if (i + 2 < length)
1796 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1797 astrand 64 else
1798     {
1799     error("this shouldn't be happening\n");
1800 astrand 265 exit(1);
1801 astrand 64 }
1802     /* this will move pointer from start to first character after FF command */
1803     length -= i + 3;
1804     text = &(text[i + 3]);
1805     i = 0;
1806 mmihalik 49 break;
1807 matty 9
1808 astrand 64 case 0xfe:
1809     entry = cache_get_text(text[i + 1]);
1810     if (entry != NULL)
1811     {
1812     if ((((uint8 *) (entry->data))[1] ==
1813 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1814 astrand 64 {
1815     if (flags & TEXT2_VERTICAL)
1816     y += text[i + 2];
1817     else
1818     x += text[i + 2];
1819     }
1820     for (j = 0; j < entry->size; j++)
1821 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1822 matthewc 44 }
1823 jsorg71 286 if (i + 2 < length)
1824     i += 3;
1825     else
1826     i += 2;
1827     length -= i;
1828     /* this will move pointer from start to first character after FE command */
1829     text = &(text[i]);
1830     i = 0;
1831 astrand 64 break;
1832 matty 17
1833 astrand 64 default:
1834     DO_GLYPH(text, i);
1835     i++;
1836     break;
1837 matty 29 }
1838 mmihalik 49 }
1839 jsorg71 450 if (g_ownbackstore)
1840 jsorg71 278 {
1841     if (boxcx > 1)
1842 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
1843 jsorg71 278 boxy, boxcx, boxcy, boxx, boxy);
1844     else
1845 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
1846 jsorg71 278 clipy, clipcx, clipcy, clipx, clipy);
1847     }
1848 matty 9 }
1849    
1850 matty 25 void
1851     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1852 matty 9 {
1853 matty 28 Pixmap pix;
1854 matty 9 XImage *image;
1855    
1856 jsorg71 450 if (g_ownbackstore)
1857 matty 31 {
1858 jsorg71 450 image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1859 matty 31 }
1860     else
1861     {
1862 jsorg71 450 pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
1863     XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
1864     image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1865     XFreePixmap(g_display, pix);
1866 matty 31 }
1867 matty 28
1868 jsorg71 450 offset *= g_bpp / 8;
1869     cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
1870 matty 28
1871     XDestroyImage(image);
1872 matty 9 }
1873    
1874 matty 25 void
1875     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1876 matty 9 {
1877     XImage *image;
1878 matty 10 uint8 *data;
1879 matty 9
1880 jsorg71 450 offset *= g_bpp / 8;
1881     data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
1882 matty 10 if (data == NULL)
1883     return;
1884 matty 29
1885 jsorg71 450 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1886     (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
1887 matty 29
1888 jsorg71 450 if (g_ownbackstore)
1889 matty 31 {
1890 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1891     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1892 matty 31 }
1893     else
1894     {
1895 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1896 matty 31 }
1897    
1898 matty 9 XFree(image);
1899     }

  ViewVC Help
Powered by ViewVC 1.1.26