/[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 101 - (hide annotations)
Mon Aug 26 17:12:43 2002 UTC (21 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 27316 byte(s)
Indent fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26