/[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 519 - (hide annotations)
Tue Oct 28 03:40:26 2003 UTC (20 years, 6 months ago) by matthewc
File MIME type: text/plain
File size: 42468 byte(s)
Convert bpp printf into DEBUG_RDP5 (perhaps not the ideal category but
it will do for now).

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

  ViewVC Help
Powered by ViewVC 1.1.26