/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 472 - (hide annotations)
Thu Sep 25 22:23:42 2003 UTC (20 years, 7 months ago) by jsorg71
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 40637 byte(s)
big edian support for 32 bpp xwindows, still need 16 and 24

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

  ViewVC Help
Powered by ViewVC 1.1.26