/[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 311 - (hide annotations)
Wed Feb 5 14:16:33 2003 UTC (21 years, 3 months ago) by jsorg71
File MIME type: text/plain
File size: 32322 byte(s)
support for > 16 bit clients with 16 bit server

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

  ViewVC Help
Powered by ViewVC 1.1.26