/[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 203 - (hide annotations)
Thu Sep 26 14:04:30 2002 UTC (21 years, 7 months ago) by matthewc
File MIME type: text/plain
File size: 26350 byte(s)
Optimise get_key_state by caching the modifier map and the state
(this can probably still be improved in the future).
Only call time(NULL) for the events where it's needed.

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

  ViewVC Help
Powered by ViewVC 1.1.26