/[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 185 - (hide annotations)
Wed Sep 18 12:13:08 2002 UTC (21 years, 8 months ago) by n-ki
File MIME type: text/plain
File size: 26637 byte(s)
Owncolmap removed in favour of more intelligent color allocation.

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

  ViewVC Help
Powered by ViewVC 1.1.26