/[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 499 - (hide annotations)
Wed Oct 15 14:01:32 2003 UTC (20 years, 7 months ago) by astrand
File MIME type: text/plain
File size: 41848 byte(s)
Fixed indentation

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

  ViewVC Help
Powered by ViewVC 1.1.26