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

  ViewVC Help
Powered by ViewVC 1.1.26