/[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 99 - (hide annotations)
Tue Aug 20 01:20:08 2002 UTC (21 years, 8 months ago) by jsorg71
File MIME type: text/plain
File size: 25472 byte(s)
focus out reset keys so some keys do not stick down

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

  ViewVC Help
Powered by ViewVC 1.1.26