/[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 250 - (show annotations)
Sun Nov 3 12:33:02 2002 UTC (21 years, 6 months ago) by matthewc
File MIME type: text/plain
File size: 26523 byte(s)
Focus upon receiving EnterNotify in fullscreen mode (in lieu of window manager)

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

  ViewVC Help
Powered by ViewVC 1.1.26