/[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 316 - (hide annotations)
Sun Feb 9 17:17:37 2003 UTC (21 years, 3 months ago) by jsorg71
File MIME type: text/plain
File size: 35515 byte(s)
15 and 24 bit server support

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

  ViewVC Help
Powered by ViewVC 1.1.26