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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 84 - (hide annotations)
Tue Jul 30 07:30:12 2002 UTC (21 years, 9 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 24912 byte(s)
Got rid of var-arg macros

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

  ViewVC Help
Powered by ViewVC 1.1.26