/[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 81 - (hide annotations)
Tue Jul 30 01:57:39 2002 UTC (21 years, 9 months ago) by jsorg71
File MIME type: text/plain
File size: 25281 byte(s)
added ui_init for pre connect inits like fullscreen

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

  ViewVC Help
Powered by ViewVC 1.1.26