/[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 188 - (hide annotations)
Tue Sep 24 06:09:09 2002 UTC (21 years, 7 months ago) by matthewc
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 26266 byte(s)
Reinstate a cleaned-up version of the old xwin_toggle_fullscreen - I indeed
can't get it working reliably with all window managers without creating a
new window.
Move remaining non-window dependant code into ui_init/ui_deinit so that
xwin_toggle_fullscreen can do ui_destroy_window/ui_create_window.

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

  ViewVC Help
Powered by ViewVC 1.1.26