/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 487 - (hide annotations)
Mon Oct 13 12:34:15 2003 UTC (20 years, 7 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 41882 byte(s)
Corrected SET_FOREGROUND/SET_BACKGROUND in Hatch handling routine.
This should be done according to patch 688390, and feels right,
although I basically have no idea of what I'm doing :-)

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

  ViewVC Help
Powered by ViewVC 1.1.26