/[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 82 - (hide annotations)
Tue Jul 30 07:18:48 2002 UTC (21 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 24894 byte(s)
Changed max line length to 100

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 astrand 64
274 matty 33 x_socket = ConnectionNumber(display);
275 matty 29 screen = DefaultScreenOfDisplay(display);
276     visual = DefaultVisualOfScreen(screen);
277     depth = DefaultDepthOfScreen(screen);
278 astrand 64
279 matty 29 pfm = XListPixmapFormats(display, &i);
280 matty 28 if (pfm != NULL)
281     {
282 matty 29 /* Use maximum bpp for this depth - this is generally
283     desirable, e.g. 24 bits->32 bits. */
284     while (i--)
285 matty 28 {
286 astrand 82 if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
287 matty 28 {
288 matty 29 bpp = pfm[i].bits_per_pixel;
289 matty 28 }
290     }
291     XFree(pfm);
292     }
293 matty 10
294 matty 28 if (bpp < 8)
295 matty 10 {
296 matty 30 error("Less than 8 bpp not currently supported.\n");
297 matty 10 XCloseDisplay(display);
298     return False;
299     }
300    
301 matty 29 if (depth <= 8)
302     owncolmap = True;
303     else
304     xcolmap = DefaultColormapOfScreen(screen);
305 matty 6
306 matty 33 test = 1;
307 astrand 64 host_be = !(BOOL) (*(uint8 *) (&test));
308 matty 33 xserver_be = (ImageByteOrder(display) == MSBFirst);
309    
310 matty 29 white = WhitePixelOfScreen(screen);
311     attribs.background_pixel = BlackPixelOfScreen(screen);
312     attribs.backing_store = DoesBackingStore(screen);
313 matty 28
314 matty 29 if (attribs.backing_store == NotUseful)
315 matty 31 ownbackstore = True;
316 matty 29
317 matty 28 if (fullscreen)
318     {
319     attribs.override_redirect = True;
320 matty 29 width = WidthOfScreen(screen);
321     height = HeightOfScreen(screen);
322 matty 28 }
323     else
324     {
325     attribs.override_redirect = False;
326     }
327    
328 astrand 64 width = (width + 3) & ~3; /* make width a multiple of 32 bits */
329 matty 29
330     wnd = XCreateWindow(display, RootWindowOfScreen(screen),
331 matty 28 0, 0, width, height, 0, CopyFromParent,
332     InputOutput, CopyFromParent,
333 astrand 82 CWBackingStore | CWBackPixel | CWOverrideRedirect, &attribs);
334 matty 9
335 matty 10 XStoreName(display, wnd, title);
336 matty 6
337 matty 28 classhints = XAllocClassHint();
338     if (classhints != NULL)
339     {
340 matty 29 classhints->res_name = classhints->res_class = "rdesktop";
341 matty 28 XSetClassHint(display, wnd, classhints);
342     XFree(classhints);
343     }
344    
345     sizehints = XAllocSizeHints();
346     if (sizehints)
347     {
348 matty 29 sizehints->flags = PMinSize | PMaxSize;
349     sizehints->min_width = sizehints->max_width = width;
350     sizehints->min_height = sizehints->max_height = height;
351 matty 28 XSetWMNormalHints(display, wnd, sizehints);
352     XFree(sizehints);
353     }
354    
355 astrand 66 xkeymap_init2();
356 matthewc 38
357 astrand 82 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask;
358 astrand 76 if (grab_keyboard)
359     input_mask |= EnterWindowMask | LeaveWindowMask;
360 matty 29 if (sendmotion)
361 matty 10 input_mask |= PointerMotionMask;
362 matty 6
363 matty 31 if (ownbackstore)
364     input_mask |= ExposureMask;
365    
366 astrand 70 if (enable_compose)
367     input_mask |= init_inputmethod();
368 astrand 66
369 astrand 70 XSelectInput(display, wnd, input_mask);
370 astrand 66
371 matty 10 gc = XCreateGC(display, wnd, 0, NULL);
372 matty 7
373 matty 31 if (ownbackstore)
374     backstore = XCreatePixmap(display, wnd, width, height, depth);
375    
376 matty 28 XMapWindow(display, wnd);
377 n-ki 52
378 matty 10 return True;
379 matty 6 }
380    
381 matty 25 void
382     ui_destroy_window()
383 matty 6 {
384 matty 31 if (ownbackstore)
385     XFreePixmap(display, backstore);
386    
387 matty 10 XFreeGC(display, gc);
388 astrand 66
389     close_inputmethod();
390    
391 matty 10 XDestroyWindow(display, wnd);
392     XCloseDisplay(display);
393 matty 28 display = NULL;
394 matty 6 }
395    
396 matty 33 static void
397     xwin_process_events()
398 matty 9 {
399 n-ki 54 XEvent xevent;
400    
401 matthewc 38 KeySym keysym;
402 matthewc 50 uint16 button, flags;
403 matty 10 uint32 ev_time;
404 astrand 66 key_translation tr;
405     char *ksname = NULL;
406     char str[256];
407     Status status;
408 matty 9
409 astrand 66 /* Refresh keyboard mapping if it has changed. This is important for
410     Xvnc, since it allocates keycodes dynamically */
411     if (XCheckTypedEvent(display, MappingNotify, &xevent))
412     {
413     if (xevent.xmapping.request == MappingKeyboard
414     || xevent.xmapping.request == MappingModifier)
415     XRefreshKeyboardMapping(&xevent.xmapping);
416     }
417    
418 n-ki 54 while (XCheckMaskEvent(display, ~0, &xevent))
419 matty 9 {
420 astrand 70 if (enable_compose && (XFilterEvent(&xevent, None) == True))
421 astrand 66 {
422     DEBUG_KBD("Filtering event\n");
423     continue;
424     }
425    
426 matty 10 ev_time = time(NULL);
427 matthewc 50 flags = 0;
428 matty 10
429 n-ki 54 switch (xevent.type)
430 matty 9 {
431     case KeyPress:
432 astrand 66 if (IC != NULL)
433     /* Multi_key compatible version */
434     {
435     XmbLookupString(IC,
436     (XKeyPressedEvent *) &
437 astrand 82 xevent, str, sizeof(str), &keysym, &status);
438     if (!((status == XLookupKeySym) || (status == XLookupBoth)))
439 astrand 66 {
440 astrand 82 error("XmbLookupString failed with status 0x%x\n",
441     status);
442 astrand 66 break;
443     }
444     }
445     else
446     {
447     /* Plain old XLookupString */
448 astrand 82 DEBUG_KBD("No input context, using XLookupString\n");
449 astrand 66 XLookupString((XKeyEvent *) & xevent,
450 astrand 82 str, sizeof(str), &keysym, NULL);
451 astrand 66 }
452    
453     ksname = get_ksname(keysym);
454 astrand 82 DEBUG_KBD("\nKeyPress for (keysym 0x%lx, %s)\n", keysym, ksname);
455 astrand 66
456     if (inhibit_key(keysym))
457     {
458     DEBUG_KBD("Inhibiting key\n");
459 matty 9 break;
460 astrand 66 }
461 matty 9
462 astrand 66 tr = xkeymap_translate_key(keysym,
463 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
464 astrand 69
465 astrand 66 ensure_remote_modifiers(ev_time, tr);
466    
467     if (tr.scancode == 0)
468 n-ki 52 break;
469    
470 astrand 82 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
471 astrand 66 break;
472     case KeyRelease:
473     XLookupString((XKeyEvent *) & xevent, str,
474     sizeof(str), &keysym, NULL);
475 n-ki 52
476 astrand 66 ksname = get_ksname(keysym);
477 astrand 82 DEBUG_KBD("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym, ksname);
478 n-ki 52
479 astrand 66 if (inhibit_key(keysym))
480     break;
481 n-ki 52
482 astrand 66 tr = xkeymap_translate_key(keysym,
483 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
484 astrand 66
485     if (tr.scancode == 0)
486     break;
487    
488 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
489 matty 9 break;
490    
491     case ButtonPress:
492 matthewc 50 flags = MOUSE_FLAG_DOWN;
493     /* fall through */
494 matty 9
495     case ButtonRelease:
496 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
497 matty 9 if (button == 0)
498     break;
499    
500 matty 10 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
501 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
502 matty 10 break;
503    
504     case MotionNotify:
505     rdp_send_input(ev_time, RDP_INPUT_MOUSE,
506 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
507 matty 28 break;
508    
509 astrand 76 case FocusIn:
510     /* fall through */
511 matty 28 case EnterNotify:
512 astrand 76 if (grab_keyboard)
513     XGrabKeyboard(display, wnd, True,
514 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
515 matty 28 break;
516    
517 astrand 76 case FocusOut:
518     /* reset keys */
519     rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
520 astrand 82 KBD_FLAG_DOWN | KBD_FLAG_UP, SCANCODE_CHAR_LCTRL, 0);
521 astrand 76 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
522 astrand 82 KBD_FLAG_DOWN | KBD_FLAG_UP, SCANCODE_CHAR_LALT, 0);
523 astrand 76 /* fall through */
524 matty 28 case LeaveNotify:
525 astrand 76 if (grab_keyboard)
526     XUngrabKeyboard(display, CurrentTime);
527 matty 28 break;
528 matty 31
529     case Expose:
530     XCopyArea(display, backstore, wnd, gc,
531 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
532 astrand 64 xevent.xexpose.width,
533     xevent.xexpose.height,
534 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
535 matty 31 break;
536 matty 9 }
537     }
538     }
539    
540 matty 25 void
541 matty 33 ui_select(int rdp_socket)
542     {
543 astrand 64 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
544 matty 33 fd_set rfds;
545    
546     FD_ZERO(&rfds);
547    
548     while (True)
549     {
550     FD_ZERO(&rfds);
551     FD_SET(rdp_socket, &rfds);
552 matthewc 53 if (display != NULL)
553     {
554     FD_SET(x_socket, &rfds);
555     XFlush(display);
556     }
557 matty 33
558     switch (select(n, &rfds, NULL, NULL, NULL))
559     {
560     case -1:
561     error("select: %s\n", strerror(errno));
562    
563     case 0:
564     continue;
565     }
566    
567     if (FD_ISSET(x_socket, &rfds))
568     xwin_process_events();
569    
570     if (FD_ISSET(rdp_socket, &rfds))
571     return;
572     }
573     }
574    
575     void
576 matty 25 ui_move_pointer(int x, int y)
577 matty 9 {
578 matty 10 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
579 matty 9 }
580    
581 matty 25 HBITMAP
582 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
583 matty 6 {
584     XImage *image;
585 matty 9 Pixmap bitmap;
586 matty 28 uint8 *tdata;
587 matty 29
588 matty 33 tdata = (owncolmap ? data : translate_image(width, height, data));
589 matty 28 bitmap = XCreatePixmap(display, wnd, width, height, depth);
590 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
591     (char *) tdata, width, height, 8, 0);
592 matty 6
593 matty 28 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
594 matty 9
595     XFree(image);
596 matty 29 if (!owncolmap)
597 matty 28 xfree(tdata);
598 matty 24 return (HBITMAP) bitmap;
599 matty 6 }
600    
601 matty 25 void
602 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
603 matty 6 {
604 matty 10 XImage *image;
605 matty 29 uint8 *tdata;
606 matty 10
607 matty 33 tdata = (owncolmap ? data : translate_image(width, height, data));
608 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
609     (char *) tdata, width, height, 8, 0);
610 matty 28
611 matty 31 if (ownbackstore)
612     {
613     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
614     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
615     }
616     else
617     {
618     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
619     }
620 matty 29
621 matty 24 XFree(image);
622 matty 29 if (!owncolmap)
623 matty 28 xfree(tdata);
624 matty 6 }
625    
626 matty 25 void
627     ui_destroy_bitmap(HBITMAP bmp)
628 matty 6 {
629 astrand 64 XFreePixmap(display, (Pixmap) bmp);
630 matty 10 }
631    
632 matty 25 HGLYPH
633 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
634 matty 10 {
635 matty 9 XImage *image;
636     Pixmap bitmap;
637     int scanline;
638     GC gc;
639 matty 6
640 matty 9 scanline = (width + 7) / 8;
641 matty 6
642 matty 10 bitmap = XCreatePixmap(display, wnd, width, height, 1);
643     gc = XCreateGC(display, bitmap, 0, NULL);
644 matty 9
645 astrand 77 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
646 astrand 73 width, height, 8, scanline);
647 matty 23 image->byte_order = MSBFirst;
648     image->bitmap_bit_order = MSBFirst;
649     XInitImage(image);
650    
651 matty 10 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
652 matty 29
653 matty 9 XFree(image);
654 matty 10 XFreeGC(display, gc);
655 astrand 64 return (HGLYPH) bitmap;
656 matty 6 }
657 matty 7
658 matty 25 void
659     ui_destroy_glyph(HGLYPH glyph)
660 matty 7 {
661 astrand 64 XFreePixmap(display, (Pixmap) glyph);
662 matty 9 }
663    
664 matty 29 HCURSOR
665 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
666     uint8 * andmask, uint8 * xormask)
667 matty 9 {
668 matty 29 HGLYPH maskglyph, cursorglyph;
669     XColor bg, fg;
670     Cursor xcursor;
671     uint8 *cursor, *pcursor;
672     uint8 *mask, *pmask;
673     uint8 nextbit;
674     int scanline, offset;
675     int i, j;
676    
677     scanline = (width + 7) / 8;
678     offset = scanline * height;
679    
680     cursor = xmalloc(offset);
681     memset(cursor, 0, offset);
682    
683     mask = xmalloc(offset);
684     memset(mask, 0, offset);
685    
686     /* approximate AND and XOR masks with a monochrome X pointer */
687     for (i = 0; i < height; i++)
688 matty 7 {
689 matty 29 offset -= scanline;
690     pcursor = &cursor[offset];
691     pmask = &mask[offset];
692    
693     for (j = 0; j < scanline; j++)
694 matty 28 {
695 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
696     {
697     if (xormask[0] || xormask[1] || xormask[2])
698     {
699     *pcursor |= (~(*andmask) & nextbit);
700     *pmask |= nextbit;
701     }
702     else
703     {
704     *pcursor |= ((*andmask) & nextbit);
705     *pmask |= (~(*andmask) & nextbit);
706     }
707    
708     xormask += 3;
709     }
710    
711     andmask++;
712     pcursor++;
713     pmask++;
714 matty 28 }
715 matty 7 }
716 matty 29
717     fg.red = fg.blue = fg.green = 0xffff;
718     bg.red = bg.blue = bg.green = 0x0000;
719     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
720    
721     cursorglyph = ui_create_glyph(width, height, cursor);
722     maskglyph = ui_create_glyph(width, height, mask);
723    
724 astrand 66 xcursor =
725     XCreatePixmapCursor(display, (Pixmap) cursorglyph,
726     (Pixmap) maskglyph, &fg, &bg, x, y);
727 astrand 64
728 matty 29 ui_destroy_glyph(maskglyph);
729     ui_destroy_glyph(cursorglyph);
730     xfree(mask);
731     xfree(cursor);
732 astrand 64 return (HCURSOR) xcursor;
733 matty 29 }
734    
735     void
736     ui_set_cursor(HCURSOR cursor)
737     {
738 astrand 64 XDefineCursor(display, wnd, (Cursor) cursor);
739 matty 29 }
740    
741     void
742     ui_destroy_cursor(HCURSOR cursor)
743     {
744 astrand 64 XFreeCursor(display, (Cursor) cursor);
745 matty 29 }
746    
747     #define MAKE_XCOLOR(xc,c) \
748     (xc)->red = ((c)->red << 8) | (c)->red; \
749     (xc)->green = ((c)->green << 8) | (c)->green; \
750     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
751     (xc)->flags = DoRed | DoGreen | DoBlue;
752    
753     HCOLOURMAP
754 astrand 64 ui_create_colourmap(COLOURMAP * colours)
755 matty 29 {
756     COLOURENTRY *entry;
757     int i, ncolours = colours->ncolours;
758    
759     if (owncolmap)
760 matty 28 {
761     XColor *xcolours, *xentry;
762     Colormap map;
763 matty 29
764 matty 28 xcolours = xmalloc(sizeof(XColor) * ncolours);
765     for (i = 0; i < ncolours; i++)
766     {
767     entry = &colours->colours[i];
768     xentry = &xcolours[i];
769     xentry->pixel = i;
770 matty 29 MAKE_XCOLOR(xentry, entry);
771 matty 28 }
772 matty 7
773 matty 28 map = XCreateColormap(display, wnd, visual, AllocAll);
774     XStoreColors(display, map, xcolours, ncolours);
775    
776     xfree(xcolours);
777 astrand 64 return (HCOLOURMAP) map;
778 matty 28 }
779 matty 29 else
780     {
781     uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
782     XColor xentry;
783 matty 33 uint32 colour;
784 matty 29
785     for (i = 0; i < ncolours; i++)
786     {
787     entry = &colours->colours[i];
788     MAKE_XCOLOR(&xentry, entry);
789    
790     if (XAllocColor(display, xcolmap, &xentry) != 0)
791 matty 34 colour = xentry.pixel;
792 matty 29 else
793 matty 34 colour = white;
794 matty 33
795     /* byte swap here to make translate_image faster */
796     map[i] = translate_colour(colour);
797 matty 29 }
798    
799     return map;
800     }
801 matty 7 }
802    
803 matty 25 void
804     ui_destroy_colourmap(HCOLOURMAP map)
805 matty 7 {
806 matty 29 if (owncolmap)
807 astrand 64 XFreeColormap(display, (Colormap) map);
808 matty 29 else
809     xfree(map);
810 matty 7 }
811    
812 matty 25 void
813     ui_set_colourmap(HCOLOURMAP map)
814 matty 7 {
815 matty 29 if (owncolmap)
816 astrand 64 XSetWindowColormap(display, wnd, (Colormap) map);
817 matty 29 else
818 matty 28 colmap = map;
819 matty 7 }
820    
821 matty 25 void
822     ui_set_clip(int x, int y, int cx, int cy)
823 matty 7 {
824 matty 9 XRectangle rect;
825 matty 7
826 matty 9 rect.x = x;
827     rect.y = y;
828     rect.width = cx;
829     rect.height = cy;
830 matty 10 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
831 matty 9 }
832 matty 7
833 matty 25 void
834     ui_reset_clip()
835 matty 9 {
836     XRectangle rect;
837    
838     rect.x = 0;
839     rect.y = 0;
840 matty 10 rect.width = width;
841     rect.height = height;
842     XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
843 matty 7 }
844    
845 matty 25 void
846     ui_bell()
847 matty 10 {
848     XBell(display, 0);
849     }
850    
851 matty 25 void
852     ui_destblt(uint8 opcode,
853     /* dest */ int x, int y, int cx, int cy)
854 matty 9 {
855 matty 29 SET_FUNCTION(opcode);
856 matty 31 FILL_RECTANGLE(x, y, cx, cy);
857 matty 29 RESET_FUNCTION(opcode);
858 matty 9 }
859    
860 matty 25 void
861     ui_patblt(uint8 opcode,
862     /* dest */ int x, int y, int cx, int cy,
863 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
864 matty 9 {
865     Pixmap fill;
866 jsorg71 59 uint8 i, ipattern[8];
867 matty 9
868 matty 29 SET_FUNCTION(opcode);
869 matty 9
870     switch (brush->style)
871     {
872 matty 24 case 0: /* Solid */
873 matty 29 SET_FOREGROUND(fgcolour);
874 matty 31 FILL_RECTANGLE(x, y, cx, cy);
875 matty 9 break;
876    
877 matty 24 case 3: /* Pattern */
878 jsorg71 59 for (i = 0; i != 8; i++)
879     ipattern[7 - i] = brush->pattern[i];
880     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
881 matty 9
882 matty 29 SET_FOREGROUND(bgcolour);
883     SET_BACKGROUND(fgcolour);
884     XSetFillStyle(display, gc, FillOpaqueStippled);
885     XSetStipple(display, gc, fill);
886 astrand 82 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
887 matty 9
888 matty 31 FILL_RECTANGLE(x, y, cx, cy);
889 matty 9
890 matty 29 XSetFillStyle(display, gc, FillSolid);
891 jsorg71 80 XSetTSOrigin(display, gc, 0, 0);
892 astrand 64 ui_destroy_glyph((HGLYPH) fill);
893 matty 9 break;
894    
895     default:
896 matty 30 unimpl("brush %d\n", brush->style);
897 matty 9 }
898 matty 29
899     RESET_FUNCTION(opcode);
900 matty 9 }
901    
902 matty 25 void
903     ui_screenblt(uint8 opcode,
904     /* dest */ int x, int y, int cx, int cy,
905     /* src */ int srcx, int srcy)
906 matty 9 {
907 matty 29 SET_FUNCTION(opcode);
908 matty 24 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
909 matty 31 if (ownbackstore)
910 astrand 82 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
911 matty 29 RESET_FUNCTION(opcode);
912 matty 9 }
913    
914 matty 25 void
915     ui_memblt(uint8 opcode,
916     /* dest */ int x, int y, int cx, int cy,
917     /* src */ HBITMAP src, int srcx, int srcy)
918 matty 9 {
919 matty 29 SET_FUNCTION(opcode);
920 astrand 64 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
921 matty 31 if (ownbackstore)
922 astrand 82 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
923 matty 29 RESET_FUNCTION(opcode);
924 matty 9 }
925    
926 matty 25 void
927     ui_triblt(uint8 opcode,
928     /* dest */ int x, int y, int cx, int cy,
929     /* src */ HBITMAP src, int srcx, int srcy,
930 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
931 matty 9 {
932     /* This is potentially difficult to do in general. Until someone
933 matty 10 comes up with a more efficient way of doing it I am using cases. */
934 matty 9
935     switch (opcode)
936     {
937 matty 24 case 0x69: /* PDSxxn */
938 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
939 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
940 matty 16 break;
941    
942 matty 24 case 0xb8: /* PSDPxax */
943 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
944 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
945 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
946 matty 9 break;
947    
948 matty 29 case 0xc0: /* PSa */
949 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
950 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
951 matty 28 break;
952    
953 matty 9 default:
954 matty 30 unimpl("triblt 0x%x\n", opcode);
955 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
956 matty 9 }
957     }
958    
959 matty 25 void
960     ui_line(uint8 opcode,
961     /* dest */ int startx, int starty, int endx, int endy,
962 astrand 64 /* pen */ PEN * pen)
963 matty 9 {
964 matty 29 SET_FUNCTION(opcode);
965     SET_FOREGROUND(pen->colour);
966 matty 10 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
967 matty 31 if (ownbackstore)
968     XDrawLine(display, backstore, gc, startx, starty, endx, endy);
969 matty 29 RESET_FUNCTION(opcode);
970 matty 9 }
971    
972 matty 25 void
973     ui_rect(
974     /* dest */ int x, int y, int cx, int cy,
975     /* brush */ int colour)
976 matty 9 {
977 matty 29 SET_FOREGROUND(colour);
978 matty 31 FILL_RECTANGLE(x, y, cx, cy);
979 matty 9 }
980    
981 matty 25 void
982     ui_draw_glyph(int mixmode,
983     /* dest */ int x, int y, int cx, int cy,
984 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
985     int bgcolour, int fgcolour)
986 matty 9 {
987 matty 29 SET_FOREGROUND(fgcolour);
988     SET_BACKGROUND(bgcolour);
989 matty 9
990 astrand 66 XSetFillStyle(display, gc,
991 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
992 astrand 64 XSetStipple(display, gc, (Pixmap) glyph);
993 matty 29 XSetTSOrigin(display, gc, x, y);
994 matty 9
995 matty 31 FILL_RECTANGLE(x, y, cx, cy);
996 matty 9
997 matty 29 XSetFillStyle(display, gc, FillSolid);
998 matty 9 }
999    
1000 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1001     {\
1002     glyph = cache_get_font (font, ttext[idx]);\
1003     if (!(flags & TEXT2_IMPLICIT_X))\
1004     {\
1005     xyoffset = ttext[++idx];\
1006     if ((xyoffset & 0x80))\
1007     {\
1008     if (flags & TEXT2_VERTICAL) \
1009 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1010 mmihalik 49 else\
1011 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1012     idx += 2;\
1013 mmihalik 49 }\
1014     else\
1015     {\
1016     if (flags & TEXT2_VERTICAL) \
1017     y += xyoffset;\
1018     else\
1019     x += xyoffset;\
1020     }\
1021     }\
1022     if (glyph != NULL)\
1023     {\
1024     ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1025     y + (short) glyph->baseline,\
1026     glyph->width, glyph->height,\
1027     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1028     if (flags & TEXT2_IMPLICIT_X)\
1029     x += glyph->width;\
1030     }\
1031     }
1032    
1033 matty 25 void
1034     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1035 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1036     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1037 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1038 matty 9 {
1039 matty 10 FONTGLYPH *glyph;
1040 mmihalik 49 int i, j, xyoffset;
1041     DATABLOB *entry;
1042 matty 9
1043 matty 29 SET_FOREGROUND(bgcolour);
1044 matty 28
1045 matty 9 if (boxcx > 1)
1046 matty 31 {
1047     FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1048     }
1049 matty 17 else if (mixmode == MIX_OPAQUE)
1050 matty 31 {
1051     FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1052     }
1053 matty 9
1054     /* Paint text, character by character */
1055 astrand 64 for (i = 0; i < length;)
1056     {
1057     switch (text[i])
1058     {
1059     case 0xff:
1060     if (i + 2 < length)
1061 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1062 astrand 64 else
1063     {
1064     error("this shouldn't be happening\n");
1065     break;
1066     }
1067     /* this will move pointer from start to first character after FF command */
1068     length -= i + 3;
1069     text = &(text[i + 3]);
1070     i = 0;
1071 mmihalik 49 break;
1072 matty 9
1073 astrand 64 case 0xfe:
1074     entry = cache_get_text(text[i + 1]);
1075     if (entry != NULL)
1076     {
1077     if ((((uint8 *) (entry->data))[1] ==
1078 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1079 astrand 64 {
1080     if (flags & TEXT2_VERTICAL)
1081     y += text[i + 2];
1082     else
1083     x += text[i + 2];
1084     }
1085     if (i + 2 < length)
1086     i += 3;
1087 mmihalik 49 else
1088 astrand 64 i += 2;
1089     length -= i;
1090     /* this will move pointer from start to first character after FE command */
1091     text = &(text[i]);
1092     i = 0;
1093     for (j = 0; j < entry->size; j++)
1094 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1095 matthewc 44 }
1096 astrand 64 break;
1097 matty 17
1098 astrand 64 default:
1099     DO_GLYPH(text, i);
1100     i++;
1101     break;
1102 matty 29 }
1103 mmihalik 49 }
1104 matty 28
1105 matty 9
1106     }
1107    
1108 matty 25 void
1109     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1110 matty 9 {
1111 matty 28 Pixmap pix;
1112 matty 9 XImage *image;
1113    
1114 matty 31 if (ownbackstore)
1115     {
1116 astrand 82 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1117 matty 31 }
1118     else
1119     {
1120     pix = XCreatePixmap(display, wnd, cx, cy, depth);
1121     XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1122 astrand 82 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1123 matty 31 XFreePixmap(display, pix);
1124     }
1125 matty 28
1126 astrand 64 offset *= bpp / 8;
1127 astrand 82 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1128 matty 28
1129     XDestroyImage(image);
1130 matty 9 }
1131    
1132 matty 25 void
1133     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1134 matty 9 {
1135     XImage *image;
1136 matty 10 uint8 *data;
1137 matty 9
1138 astrand 64 offset *= bpp / 8;
1139     data = cache_get_desktop(offset, cx, cy, bpp / 8);
1140 matty 10 if (data == NULL)
1141     return;
1142 matty 29
1143 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1144 astrand 82 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1145 matty 29
1146 matty 31 if (ownbackstore)
1147     {
1148     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1149     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1150     }
1151     else
1152     {
1153     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1154     }
1155    
1156 matty 9 XFree(image);
1157     }

  ViewVC Help
Powered by ViewVC 1.1.26