/[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 318 - (hide annotations)
Mon Feb 10 12:58:51 2003 UTC (21 years, 3 months ago) by astrand
File MIME type: text/plain
File size: 35543 byte(s)
Indent fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26