/[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 517 - (hide annotations)
Tue Oct 28 03:30:51 2003 UTC (20 years, 6 months ago) by matthewc
File MIME type: text/plain
File size: 42513 byte(s)
private colour map code only works for 8 bpp, disable otherwise
(from neoware)

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

  ViewVC Help
Powered by ViewVC 1.1.26