/[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 70 - (hide annotations)
Sat Jul 27 23:09:32 2002 UTC (21 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 24505 byte(s)
Add support for enabling/disabling local compose handling. Compose support is now disabled per default

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

  ViewVC Help
Powered by ViewVC 1.1.26