/[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 261 - (hide annotations)
Mon Nov 18 15:35:41 2002 UTC (21 years, 5 months ago) by astrand
File MIME type: text/plain
File size: 27239 byte(s)
Indent fixes.

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

  ViewVC Help
Powered by ViewVC 1.1.26