/[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 508 - (hide annotations)
Wed Oct 22 10:55:11 2003 UTC (20 years, 7 months ago) by astrand
File MIME type: text/plain
File size: 42411 byte(s)
Applied null cursor patch from jeroen@oldambt7.com

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

  ViewVC Help
Powered by ViewVC 1.1.26