/[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

Contents of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 188 - (show annotations)
Tue Sep 24 06:09:09 2002 UTC (21 years, 7 months ago) by matthewc
File MIME type: text/plain
File size: 26266 byte(s)
Reinstate a cleaned-up version of the old xwin_toggle_fullscreen - I indeed
can't get it working reliably with all window managers without creating a
new window.
Move remaining non-window dependant code into ui_init/ui_deinit so that
xwin_toggle_fullscreen can do ui_destroy_window/ui_create_window.

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

  ViewVC Help
Powered by ViewVC 1.1.26