/[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 87 - (hide annotations)
Sat Aug 3 22:28:05 2002 UTC (21 years, 9 months ago) by jsorg71
File MIME type: text/plain
File size: 25267 byte(s)
clear window upon startup so cached data is not viewed on screen from up19-7-5

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     VisibilityChangeMask;
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     rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
535 astrand 82 KBD_FLAG_DOWN | KBD_FLAG_UP, SCANCODE_CHAR_LCTRL, 0);
536 astrand 76 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
537 astrand 82 KBD_FLAG_DOWN | KBD_FLAG_UP, SCANCODE_CHAR_LALT, 0);
538 astrand 76 /* fall through */
539 matty 28 case LeaveNotify:
540 astrand 76 if (grab_keyboard)
541     XUngrabKeyboard(display, CurrentTime);
542 matty 28 break;
543 matty 31
544     case Expose:
545     XCopyArea(display, backstore, wnd, gc,
546 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
547 astrand 64 xevent.xexpose.width,
548     xevent.xexpose.height,
549 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
550 matty 31 break;
551 matty 9 }
552     }
553     }
554    
555 matty 25 void
556 matty 33 ui_select(int rdp_socket)
557     {
558 astrand 64 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
559 matty 33 fd_set rfds;
560    
561     FD_ZERO(&rfds);
562    
563     while (True)
564     {
565     FD_ZERO(&rfds);
566     FD_SET(rdp_socket, &rfds);
567 matthewc 53 if (display != NULL)
568     {
569     FD_SET(x_socket, &rfds);
570     XFlush(display);
571     }
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(x_socket, &rfds))
583     xwin_process_events();
584    
585     if (FD_ISSET(rdp_socket, &rfds))
586     return;
587     }
588     }
589    
590     void
591 matty 25 ui_move_pointer(int x, int y)
592 matty 9 {
593 matty 10 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
594 matty 9 }
595    
596 matty 25 HBITMAP
597 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
598 matty 6 {
599     XImage *image;
600 matty 9 Pixmap bitmap;
601 matty 28 uint8 *tdata;
602 matty 29
603 matty 33 tdata = (owncolmap ? data : translate_image(width, height, data));
604 matty 28 bitmap = XCreatePixmap(display, wnd, width, height, depth);
605 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
606     (char *) tdata, width, height, 8, 0);
607 matty 6
608 matty 28 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
609 matty 9
610     XFree(image);
611 matty 29 if (!owncolmap)
612 matty 28 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 matty 33 tdata = (owncolmap ? data : 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 matty 29 if (!owncolmap)
638 matty 28 xfree(tdata);
639 matty 6 }
640    
641 matty 25 void
642     ui_destroy_bitmap(HBITMAP bmp)
643 matty 6 {
644 astrand 64 XFreePixmap(display, (Pixmap) bmp);
645 matty 10 }
646    
647 matty 25 HGLYPH
648 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
649 matty 10 {
650 matty 9 XImage *image;
651     Pixmap bitmap;
652     int scanline;
653     GC gc;
654 matty 6
655 matty 9 scanline = (width + 7) / 8;
656 matty 6
657 matty 10 bitmap = XCreatePixmap(display, wnd, width, height, 1);
658     gc = XCreateGC(display, bitmap, 0, NULL);
659 matty 9
660 astrand 77 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
661 astrand 73 width, height, 8, scanline);
662 matty 23 image->byte_order = MSBFirst;
663     image->bitmap_bit_order = MSBFirst;
664     XInitImage(image);
665    
666 matty 10 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
667 matty 29
668 matty 9 XFree(image);
669 matty 10 XFreeGC(display, gc);
670 astrand 64 return (HGLYPH) bitmap;
671 matty 6 }
672 matty 7
673 matty 25 void
674     ui_destroy_glyph(HGLYPH glyph)
675 matty 7 {
676 astrand 64 XFreePixmap(display, (Pixmap) glyph);
677 matty 9 }
678    
679 matty 29 HCURSOR
680 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
681     uint8 * andmask, uint8 * xormask)
682 matty 9 {
683 matty 29 HGLYPH maskglyph, cursorglyph;
684     XColor bg, fg;
685     Cursor xcursor;
686     uint8 *cursor, *pcursor;
687     uint8 *mask, *pmask;
688     uint8 nextbit;
689     int scanline, offset;
690     int i, j;
691    
692     scanline = (width + 7) / 8;
693     offset = scanline * height;
694    
695     cursor = xmalloc(offset);
696     memset(cursor, 0, offset);
697    
698     mask = xmalloc(offset);
699     memset(mask, 0, offset);
700    
701     /* approximate AND and XOR masks with a monochrome X pointer */
702     for (i = 0; i < height; i++)
703 matty 7 {
704 matty 29 offset -= scanline;
705     pcursor = &cursor[offset];
706     pmask = &mask[offset];
707    
708     for (j = 0; j < scanline; j++)
709 matty 28 {
710 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
711     {
712     if (xormask[0] || xormask[1] || xormask[2])
713     {
714     *pcursor |= (~(*andmask) & nextbit);
715     *pmask |= nextbit;
716     }
717     else
718     {
719     *pcursor |= ((*andmask) & nextbit);
720     *pmask |= (~(*andmask) & nextbit);
721     }
722    
723     xormask += 3;
724     }
725    
726     andmask++;
727     pcursor++;
728     pmask++;
729 matty 28 }
730 matty 7 }
731 matty 29
732     fg.red = fg.blue = fg.green = 0xffff;
733     bg.red = bg.blue = bg.green = 0x0000;
734     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
735    
736     cursorglyph = ui_create_glyph(width, height, cursor);
737     maskglyph = ui_create_glyph(width, height, mask);
738    
739 astrand 66 xcursor =
740     XCreatePixmapCursor(display, (Pixmap) cursorglyph,
741     (Pixmap) maskglyph, &fg, &bg, x, y);
742 astrand 64
743 matty 29 ui_destroy_glyph(maskglyph);
744     ui_destroy_glyph(cursorglyph);
745     xfree(mask);
746     xfree(cursor);
747 astrand 64 return (HCURSOR) xcursor;
748 matty 29 }
749    
750     void
751     ui_set_cursor(HCURSOR cursor)
752     {
753 astrand 64 XDefineCursor(display, wnd, (Cursor) 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    
774     if (owncolmap)
775 matty 28 {
776     XColor *xcolours, *xentry;
777     Colormap map;
778 matty 29
779 matty 28 xcolours = xmalloc(sizeof(XColor) * ncolours);
780     for (i = 0; i < ncolours; i++)
781     {
782     entry = &colours->colours[i];
783     xentry = &xcolours[i];
784     xentry->pixel = i;
785 matty 29 MAKE_XCOLOR(xentry, entry);
786 matty 28 }
787 matty 7
788 matty 28 map = XCreateColormap(display, wnd, visual, AllocAll);
789     XStoreColors(display, map, xcolours, ncolours);
790    
791     xfree(xcolours);
792 astrand 64 return (HCOLOURMAP) map;
793 matty 28 }
794 matty 29 else
795     {
796     uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
797     XColor xentry;
798 matty 33 uint32 colour;
799 matty 29
800     for (i = 0; i < ncolours; i++)
801     {
802     entry = &colours->colours[i];
803     MAKE_XCOLOR(&xentry, entry);
804    
805     if (XAllocColor(display, xcolmap, &xentry) != 0)
806 matty 34 colour = xentry.pixel;
807 matty 29 else
808 matty 34 colour = white;
809 matty 33
810     /* byte swap here to make translate_image faster */
811     map[i] = translate_colour(colour);
812 matty 29 }
813    
814     return map;
815     }
816 matty 7 }
817    
818 matty 25 void
819     ui_destroy_colourmap(HCOLOURMAP map)
820 matty 7 {
821 matty 29 if (owncolmap)
822 astrand 64 XFreeColormap(display, (Colormap) map);
823 matty 29 else
824     xfree(map);
825 matty 7 }
826    
827 matty 25 void
828     ui_set_colourmap(HCOLOURMAP map)
829 matty 7 {
830 matty 29 if (owncolmap)
831 astrand 64 XSetWindowColormap(display, wnd, (Colormap) map);
832 matty 29 else
833 matty 28 colmap = map;
834 matty 7 }
835    
836 matty 25 void
837     ui_set_clip(int x, int y, int cx, int cy)
838 matty 7 {
839 matty 9 XRectangle rect;
840 matty 7
841 matty 9 rect.x = x;
842     rect.y = y;
843     rect.width = cx;
844     rect.height = cy;
845 matty 10 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
846 matty 9 }
847 matty 7
848 matty 25 void
849     ui_reset_clip()
850 matty 9 {
851     XRectangle rect;
852    
853     rect.x = 0;
854     rect.y = 0;
855 matty 10 rect.width = width;
856     rect.height = height;
857     XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
858 matty 7 }
859    
860 matty 25 void
861     ui_bell()
862 matty 10 {
863     XBell(display, 0);
864     }
865    
866 matty 25 void
867     ui_destblt(uint8 opcode,
868     /* dest */ int x, int y, int cx, int cy)
869 matty 9 {
870 matty 29 SET_FUNCTION(opcode);
871 matty 31 FILL_RECTANGLE(x, y, cx, cy);
872 matty 29 RESET_FUNCTION(opcode);
873 matty 9 }
874    
875 matty 25 void
876     ui_patblt(uint8 opcode,
877     /* dest */ int x, int y, int cx, int cy,
878 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
879 matty 9 {
880     Pixmap fill;
881 jsorg71 59 uint8 i, ipattern[8];
882 matty 9
883 matty 29 SET_FUNCTION(opcode);
884 matty 9
885     switch (brush->style)
886     {
887 matty 24 case 0: /* Solid */
888 matty 29 SET_FOREGROUND(fgcolour);
889 matty 31 FILL_RECTANGLE(x, y, cx, cy);
890 matty 9 break;
891    
892 matty 24 case 3: /* Pattern */
893 jsorg71 59 for (i = 0; i != 8; i++)
894     ipattern[7 - i] = brush->pattern[i];
895     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
896 matty 9
897 matty 29 SET_FOREGROUND(bgcolour);
898     SET_BACKGROUND(fgcolour);
899     XSetFillStyle(display, gc, FillOpaqueStippled);
900     XSetStipple(display, gc, fill);
901 astrand 82 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
902 matty 9
903 matty 31 FILL_RECTANGLE(x, y, cx, cy);
904 matty 9
905 matty 29 XSetFillStyle(display, gc, FillSolid);
906 jsorg71 80 XSetTSOrigin(display, gc, 0, 0);
907 astrand 64 ui_destroy_glyph((HGLYPH) fill);
908 matty 9 break;
909    
910     default:
911 matty 30 unimpl("brush %d\n", brush->style);
912 matty 9 }
913 matty 29
914     RESET_FUNCTION(opcode);
915 matty 9 }
916    
917 matty 25 void
918     ui_screenblt(uint8 opcode,
919     /* dest */ int x, int y, int cx, int cy,
920     /* src */ int srcx, int srcy)
921 matty 9 {
922 matty 29 SET_FUNCTION(opcode);
923 matty 24 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
924 matty 31 if (ownbackstore)
925 astrand 82 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
926 matty 29 RESET_FUNCTION(opcode);
927 matty 9 }
928    
929 matty 25 void
930     ui_memblt(uint8 opcode,
931     /* dest */ int x, int y, int cx, int cy,
932     /* src */ HBITMAP src, int srcx, int srcy)
933 matty 9 {
934 matty 29 SET_FUNCTION(opcode);
935 astrand 64 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
936 matty 31 if (ownbackstore)
937 astrand 82 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
938 matty 29 RESET_FUNCTION(opcode);
939 matty 9 }
940    
941 matty 25 void
942     ui_triblt(uint8 opcode,
943     /* dest */ int x, int y, int cx, int cy,
944     /* src */ HBITMAP src, int srcx, int srcy,
945 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
946 matty 9 {
947     /* This is potentially difficult to do in general. Until someone
948 matty 10 comes up with a more efficient way of doing it I am using cases. */
949 matty 9
950     switch (opcode)
951     {
952 matty 24 case 0x69: /* PDSxxn */
953 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
954 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
955 matty 16 break;
956    
957 matty 24 case 0xb8: /* PSDPxax */
958 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
959 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
960 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
961 matty 9 break;
962    
963 matty 29 case 0xc0: /* PSa */
964 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
965 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
966 matty 28 break;
967    
968 matty 9 default:
969 matty 30 unimpl("triblt 0x%x\n", opcode);
970 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
971 matty 9 }
972     }
973    
974 matty 25 void
975     ui_line(uint8 opcode,
976     /* dest */ int startx, int starty, int endx, int endy,
977 astrand 64 /* pen */ PEN * pen)
978 matty 9 {
979 matty 29 SET_FUNCTION(opcode);
980     SET_FOREGROUND(pen->colour);
981 matty 10 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
982 matty 31 if (ownbackstore)
983     XDrawLine(display, backstore, gc, startx, starty, endx, endy);
984 matty 29 RESET_FUNCTION(opcode);
985 matty 9 }
986    
987 matty 25 void
988     ui_rect(
989     /* dest */ int x, int y, int cx, int cy,
990     /* brush */ int colour)
991 matty 9 {
992 matty 29 SET_FOREGROUND(colour);
993 matty 31 FILL_RECTANGLE(x, y, cx, cy);
994 matty 9 }
995    
996 matty 25 void
997     ui_draw_glyph(int mixmode,
998     /* dest */ int x, int y, int cx, int cy,
999 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1000     int bgcolour, int fgcolour)
1001 matty 9 {
1002 matty 29 SET_FOREGROUND(fgcolour);
1003     SET_BACKGROUND(bgcolour);
1004 matty 9
1005 astrand 66 XSetFillStyle(display, gc,
1006 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1007 astrand 64 XSetStipple(display, gc, (Pixmap) glyph);
1008 matty 29 XSetTSOrigin(display, gc, x, y);
1009 matty 9
1010 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1011 matty 9
1012 matty 29 XSetFillStyle(display, gc, FillSolid);
1013 matty 9 }
1014    
1015 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1016     {\
1017     glyph = cache_get_font (font, ttext[idx]);\
1018     if (!(flags & TEXT2_IMPLICIT_X))\
1019     {\
1020     xyoffset = ttext[++idx];\
1021     if ((xyoffset & 0x80))\
1022     {\
1023     if (flags & TEXT2_VERTICAL) \
1024 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1025 mmihalik 49 else\
1026 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1027     idx += 2;\
1028 mmihalik 49 }\
1029     else\
1030     {\
1031     if (flags & TEXT2_VERTICAL) \
1032     y += xyoffset;\
1033     else\
1034     x += xyoffset;\
1035     }\
1036     }\
1037     if (glyph != NULL)\
1038     {\
1039     ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1040     y + (short) glyph->baseline,\
1041     glyph->width, glyph->height,\
1042     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1043     if (flags & TEXT2_IMPLICIT_X)\
1044     x += glyph->width;\
1045     }\
1046     }
1047    
1048 matty 25 void
1049     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1050 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1051     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1052 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1053 matty 9 {
1054 matty 10 FONTGLYPH *glyph;
1055 mmihalik 49 int i, j, xyoffset;
1056     DATABLOB *entry;
1057 matty 9
1058 matty 29 SET_FOREGROUND(bgcolour);
1059 matty 28
1060 matty 9 if (boxcx > 1)
1061 matty 31 {
1062     FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1063     }
1064 matty 17 else if (mixmode == MIX_OPAQUE)
1065 matty 31 {
1066     FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1067     }
1068 matty 9
1069     /* Paint text, character by character */
1070 astrand 64 for (i = 0; i < length;)
1071     {
1072     switch (text[i])
1073     {
1074     case 0xff:
1075     if (i + 2 < length)
1076 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1077 astrand 64 else
1078     {
1079     error("this shouldn't be happening\n");
1080     break;
1081     }
1082     /* this will move pointer from start to first character after FF command */
1083     length -= i + 3;
1084     text = &(text[i + 3]);
1085     i = 0;
1086 mmihalik 49 break;
1087 matty 9
1088 astrand 64 case 0xfe:
1089     entry = cache_get_text(text[i + 1]);
1090     if (entry != NULL)
1091     {
1092     if ((((uint8 *) (entry->data))[1] ==
1093 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1094 astrand 64 {
1095     if (flags & TEXT2_VERTICAL)
1096     y += text[i + 2];
1097     else
1098     x += text[i + 2];
1099     }
1100     if (i + 2 < length)
1101     i += 3;
1102 mmihalik 49 else
1103 astrand 64 i += 2;
1104     length -= i;
1105     /* this will move pointer from start to first character after FE command */
1106     text = &(text[i]);
1107     i = 0;
1108     for (j = 0; j < entry->size; j++)
1109 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1110 matthewc 44 }
1111 astrand 64 break;
1112 matty 17
1113 astrand 64 default:
1114     DO_GLYPH(text, i);
1115     i++;
1116     break;
1117 matty 29 }
1118 mmihalik 49 }
1119 matty 28
1120 matty 9
1121     }
1122    
1123 matty 25 void
1124     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1125 matty 9 {
1126 matty 28 Pixmap pix;
1127 matty 9 XImage *image;
1128    
1129 matty 31 if (ownbackstore)
1130     {
1131 astrand 82 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1132 matty 31 }
1133     else
1134     {
1135     pix = XCreatePixmap(display, wnd, cx, cy, depth);
1136     XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1137 astrand 82 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1138 matty 31 XFreePixmap(display, pix);
1139     }
1140 matty 28
1141 astrand 64 offset *= bpp / 8;
1142 astrand 82 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1143 matty 28
1144     XDestroyImage(image);
1145 matty 9 }
1146    
1147 matty 25 void
1148     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1149 matty 9 {
1150     XImage *image;
1151 matty 10 uint8 *data;
1152 matty 9
1153 astrand 64 offset *= bpp / 8;
1154     data = cache_get_desktop(offset, cx, cy, bpp / 8);
1155 matty 10 if (data == NULL)
1156     return;
1157 matty 29
1158 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1159 astrand 82 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1160 matty 29
1161 matty 31 if (ownbackstore)
1162     {
1163     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1164     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1165     }
1166     else
1167     {
1168     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1169     }
1170    
1171 matty 9 XFree(image);
1172     }

  ViewVC Help
Powered by ViewVC 1.1.26