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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 192 - (hide annotations)
Tue Sep 24 07:59:14 2002 UTC (21 years, 8 months ago) by matthewc
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 26226 byte(s)
foo function() -> foo function(void) to conform to ANSI C.

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

  ViewVC Help
Powered by ViewVC 1.1.26