/[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 69 - (hide annotations)
Sat Jul 27 22:35:38 2002 UTC (21 years, 9 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 24461 byte(s)
Added "localstate" support to keymapping: Send local modifier state. This fixes problems with Shift-Home etc

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

  ViewVC Help
Powered by ViewVC 1.1.26