/[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 500 - (hide annotations)
Wed Oct 15 14:32:43 2003 UTC (20 years, 7 months ago) by astrand
File MIME type: text/plain
File size: 42036 byte(s)
Support for specifying geometry in terms of percent of whole screen

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

  ViewVC Help
Powered by ViewVC 1.1.26