/[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 66 - (hide annotations)
Thu Jul 18 18:28:12 2002 UTC (21 years, 10 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 24402 byte(s)
Merged new keysym-based keyboard handling (from alt. CVS repos)

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

  ViewVC Help
Powered by ViewVC 1.1.26