/[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 196 - (show 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 /*
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 #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 Cursor current_cursor;
46
47 /* endianness */
48 static BOOL host_be;
49 static BOOL xserver_be;
50
51 /* software backing store */
52 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 /* colour maps */
63 static Colormap xcolmap;
64 static uint32 *colmap;
65
66 #define SET_FOREGROUND(col) XSetForeground(display, gc, translate_colour(colmap[col]));
67 #define SET_BACKGROUND(col) XSetBackground(display, gc, translate_colour(colmap[col]));
68
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 #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 static void
92 translate8(uint8 * data, uint8 * out, uint8 * end)
93 {
94 while (out < end)
95 *(out++) = (uint8) colmap[*(data++)];
96 }
97
98 static void
99 translate16(uint8 * data, uint16 * out, uint16 * end)
100 {
101 while (out < end)
102 *(out++) = (uint16) colmap[*(data++)];
103 }
104
105 /* little endian - conversion happens when colourmap is built */
106 static void
107 translate24(uint8 * data, uint8 * out, uint8 * end)
108 {
109 uint32 value;
110
111 while (out < end)
112 {
113 value = colmap[*(data++)];
114 *(out++) = value;
115 *(out++) = value >> 8;
116 *(out++) = value >> 16;
117 }
118 }
119
120 static void
121 translate32(uint8 * data, uint32 * out, uint32 * end)
122 {
123 while (out < end)
124 *(out++) = colmap[*(data++)];
125 }
126
127 static uint8 *
128 translate_image(int width, int height, uint8 * data)
129 {
130 int size = width * height * bpp / 8;
131 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 translate16(data, (uint16 *) out, (uint16 *) end);
142 break;
143
144 case 24:
145 translate24(data, out, end);
146 break;
147
148 case 32:
149 translate32(data, (uint32 *) out, (uint32 *) end);
150 break;
151 }
152
153 return out;
154 }
155
156 #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
161 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
171 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 BOOL
186 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 BOOL
220 ui_init(void)
221 {
222 XPixmapFormatValues *pfm;
223 uint16 test;
224 int i;
225
226 display = XOpenDisplay(NULL);
227 if (display == NULL)
228 {
229 error("Failed to open display\n");
230 return False;
231 }
232
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 xcolmap = DefaultColormapOfScreen(screen);
261 gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
262
263 if (DoesBackingStore(screen) != Always)
264 ownbackstore = True;
265
266 test = 1;
267 host_be = !(BOOL) (*(uint8 *) (&test));
268 xserver_be = (ImageByteOrder(display) == MSBFirst);
269
270 if (fullscreen)
271 {
272 width = WidthOfScreen(screen);
273 height = HeightOfScreen(screen);
274 }
275
276 /* make sure width is a multiple of 4 */
277 width = (width + 3) & ~3;
278
279 if (ownbackstore)
280 {
281 backstore =
282 XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
283
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 xkeymap_init();
293 return True;
294 }
295
296 void
297 ui_deinit(void)
298 {
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 BOOL
311 ui_create_window(void)
312 {
313 XSetWindowAttributes attribs;
314 XClassHint *classhints;
315 XSizeHints *sizehints;
316 int wndwidth, wndheight;
317 long input_mask, ic_input_mask;
318 XEvent xevent;
319
320 wndwidth = fullscreen ? WidthOfScreen(screen) : width;
321 wndheight = fullscreen ? HeightOfScreen(screen) : height;
322
323 attribs.background_pixel = BlackPixelOfScreen(screen);
324 attribs.backing_store = ownbackstore ? NotUseful : Always;
325 attribs.override_redirect = fullscreen;
326
327 wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
328 0, CopyFromParent, InputOutput, CopyFromParent,
329 CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
330
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 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
352 StructureNotifyMask | FocusChangeMask;
353
354 if (sendmotion)
355 input_mask |= PointerMotionMask;
356 if (ownbackstore)
357 input_mask |= ExposureMask;
358
359 if (IM != NULL)
360 {
361 IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
362 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
363
364 if ((IC != NULL)
365 && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
366 input_mask |= ic_input_mask;
367 }
368
369 XSelectInput(display, wnd, input_mask);
370 XMapWindow(display, wnd);
371
372 /* wait for MapNotify */
373 do
374 {
375 XMaskEvent(display, StructureNotifyMask, &xevent);
376 }
377 while (xevent.type != MapNotify);
378
379 if (fullscreen)
380 XSetInputFocus(display, wnd, RevertToPointerRoot, CurrentTime);
381
382 return True;
383 }
384
385 void
386 ui_destroy_window(void)
387 {
388 if (IC != NULL)
389 XDestroyIC(IC);
390
391 XDestroyWindow(display, wnd);
392 }
393
394 void
395 xwin_toggle_fullscreen(void)
396 {
397 Pixmap contents = 0;
398
399 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 fullscreen = !fullscreen;
408 ui_create_window();
409
410 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 }
418
419 /* Process all events in Xlib queue */
420 static void
421 xwin_process_events(void)
422 {
423 XEvent xevent;
424 KeySym keysym;
425 uint16 button, flags;
426 uint32 ev_time;
427 key_translation tr;
428 char *ksname = NULL;
429 char str[256];
430 Status status;
431
432 while (XPending(display) > 0)
433 {
434 XNextEvent(display, &xevent);
435
436 if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
437 {
438 DEBUG_KBD(("Filtering event\n"));
439 continue;
440 }
441
442 ev_time = time(NULL);
443 flags = 0;
444
445 switch (xevent.type)
446 {
447 case KeyPress:
448 if (IC != NULL)
449 /* Multi_key compatible version */
450 {
451 XmbLookupString(IC,
452 (XKeyPressedEvent *) &
453 xevent, str, sizeof(str), &keysym, &status);
454 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
455 {
456 error("XmbLookupString failed with status 0x%x\n",
457 status);
458 break;
459 }
460 }
461 else
462 {
463 /* Plain old XLookupString */
464 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
465 XLookupString((XKeyEvent *) & xevent,
466 str, sizeof(str), &keysym, NULL);
467 }
468
469 ksname = get_ksname(keysym);
470 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym, ksname));
471
472 if (handle_special_keys(keysym, ev_time, True))
473 break;
474
475 tr = xkeymap_translate_key(keysym,
476 xevent.xkey.keycode, xevent.xkey.state);
477
478 if (tr.scancode == 0)
479 break;
480
481 ensure_remote_modifiers(ev_time, tr);
482
483 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
484 break;
485 case KeyRelease:
486 XLookupString((XKeyEvent *) & xevent, str,
487 sizeof(str), &keysym, NULL);
488
489 ksname = get_ksname(keysym);
490 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
491 ksname));
492
493 if (handle_special_keys(keysym, ev_time, False))
494 break;
495
496 tr = xkeymap_translate_key(keysym,
497 xevent.xkey.keycode, xevent.xkey.state);
498
499 if (tr.scancode == 0)
500 break;
501
502 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
503 break;
504
505 case ButtonPress:
506 flags = MOUSE_FLAG_DOWN;
507 /* fall through */
508
509 case ButtonRelease:
510 button = xkeymap_translate_button(xevent.xbutton.button);
511 if (button == 0)
512 break;
513
514 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
515 flags | button, xevent.xbutton.x, xevent.xbutton.y);
516 break;
517
518 case MotionNotify:
519 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
520 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
521 break;
522
523 case FocusIn:
524 reset_modifier_keys();
525 if (grab_keyboard)
526 XGrabKeyboard(display, wnd, True,
527 GrabModeAsync, GrabModeAsync, CurrentTime);
528 break;
529
530 case FocusOut:
531 if (grab_keyboard)
532 XUngrabKeyboard(display, CurrentTime);
533 break;
534
535 case Expose:
536 XCopyArea(display, backstore, wnd, gc,
537 xevent.xexpose.x, xevent.xexpose.y,
538 xevent.xexpose.width,
539 xevent.xexpose.height,
540 xevent.xexpose.x, xevent.xexpose.y);
541 break;
542
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 }
552 }
553 }
554
555 void
556 ui_select(int rdp_socket)
557 {
558 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
559 fd_set rfds;
560
561 FD_ZERO(&rfds);
562
563 while (True)
564 {
565 /* Process any events already waiting */
566 xwin_process_events();
567
568 FD_ZERO(&rfds);
569 FD_SET(rdp_socket, &rfds);
570 FD_SET(x_socket, &rfds);
571
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 ui_move_pointer(int x, int y)
588 {
589 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
590 }
591
592 HBITMAP
593 ui_create_bitmap(int width, int height, uint8 * data)
594 {
595 XImage *image;
596 Pixmap bitmap;
597 uint8 *tdata;
598
599 tdata = translate_image(width, height, data);
600 bitmap = XCreatePixmap(display, wnd, width, height, depth);
601 image = XCreateImage(display, visual, depth, ZPixmap, 0,
602 (char *) tdata, width, height, 8, 0);
603
604 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
605
606 XFree(image);
607 xfree(tdata);
608 return (HBITMAP) bitmap;
609 }
610
611 void
612 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
613 {
614 XImage *image;
615 uint8 *tdata;
616
617 tdata = translate_image(width, height, data);
618 image = XCreateImage(display, visual, depth, ZPixmap, 0,
619 (char *) tdata, width, height, 8, 0);
620
621 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
631 XFree(image);
632 xfree(tdata);
633 }
634
635 void
636 ui_destroy_bitmap(HBITMAP bmp)
637 {
638 XFreePixmap(display, (Pixmap) bmp);
639 }
640
641 HGLYPH
642 ui_create_glyph(int width, int height, uint8 * data)
643 {
644 XImage *image;
645 Pixmap bitmap;
646 int scanline;
647 GC gc;
648
649 scanline = (width + 7) / 8;
650
651 bitmap = XCreatePixmap(display, wnd, width, height, 1);
652 gc = XCreateGC(display, bitmap, 0, NULL);
653
654 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
655 width, height, 8, scanline);
656 image->byte_order = MSBFirst;
657 image->bitmap_bit_order = MSBFirst;
658 XInitImage(image);
659
660 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
661
662 XFree(image);
663 XFreeGC(display, gc);
664 return (HGLYPH) bitmap;
665 }
666
667 void
668 ui_destroy_glyph(HGLYPH glyph)
669 {
670 XFreePixmap(display, (Pixmap) glyph);
671 }
672
673 HCURSOR
674 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
675 uint8 * andmask, uint8 * xormask)
676 {
677 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 {
698 offset -= scanline;
699 pcursor = &cursor[offset];
700 pmask = &mask[offset];
701
702 for (j = 0; j < scanline; j++)
703 {
704 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 }
724 }
725
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 xcursor =
734 XCreatePixmapCursor(display, (Pixmap) cursorglyph,
735 (Pixmap) maskglyph, &fg, &bg, x, y);
736
737 ui_destroy_glyph(maskglyph);
738 ui_destroy_glyph(cursorglyph);
739 xfree(mask);
740 xfree(cursor);
741 return (HCURSOR) xcursor;
742 }
743
744 void
745 ui_set_cursor(HCURSOR cursor)
746 {
747 current_cursor = (Cursor) cursor;
748 XDefineCursor(display, wnd, current_cursor);
749 }
750
751 void
752 ui_destroy_cursor(HCURSOR cursor)
753 {
754 XFreeCursor(display, (Cursor) cursor);
755 }
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 ui_create_colourmap(COLOURMAP * colours)
765 {
766 COLOURENTRY *entry;
767 int i, ncolours = colours->ncolours;
768 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 {
775 entry = &colours->colours[i];
776 MAKE_XCOLOR(&xentry, entry);
777
778 if (XAllocColor(display, xcolmap, &xentry) == 0)
779 {
780 /* Allocation failed, find closest match. */
781 int j = 256;
782 int nMinDist = 3 * 256 * 256;
783 long nDist = nMinDist;
784
785 /* only get the colors once */
786 while (colLookup--)
787 {
788 xc_cache[colLookup].pixel = colLookup;
789 xc_cache[colLookup].red = xc_cache[colLookup].green =
790 xc_cache[colLookup].blue = 0;
791 xc_cache[colLookup].flags = 0;
792 XQueryColor(display,
793 DefaultColormap(display, DefaultScreen(display)),
794 &xc_cache[colLookup]);
795 }
796 colLookup = 0;
797
798 /* approximate the pixel */
799 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 }
816 if (nDist < nMinDist)
817 {
818 nMinDist = nDist;
819 xentry.pixel = j;
820 }
821 }
822 }
823 colour = xentry.pixel;
824
825 /* update our cache */
826 if (xentry.pixel < 256)
827 {
828 xc_cache[xentry.pixel].red = xentry.red;
829 xc_cache[xentry.pixel].green = xentry.green;
830 xc_cache[xentry.pixel].blue = xentry.blue;
831
832 }
833
834
835 /* byte swap here to make translate_image faster */
836 map[i] = translate_colour(colour);
837 }
838
839 return map;
840 }
841
842 void
843 ui_destroy_colourmap(HCOLOURMAP map)
844 {
845 xfree(map);
846 }
847
848 void
849 ui_set_colourmap(HCOLOURMAP map)
850 {
851 colmap = map;
852 }
853
854 void
855 ui_set_clip(int x, int y, int cx, int cy)
856 {
857 XRectangle rect;
858
859 rect.x = x;
860 rect.y = y;
861 rect.width = cx;
862 rect.height = cy;
863 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
864 }
865
866 void
867 ui_reset_clip(void)
868 {
869 XRectangle rect;
870
871 rect.x = 0;
872 rect.y = 0;
873 rect.width = width;
874 rect.height = height;
875 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
876 }
877
878 void
879 ui_bell(void)
880 {
881 XBell(display, 0);
882 }
883
884 void
885 ui_destblt(uint8 opcode,
886 /* dest */ int x, int y, int cx, int cy)
887 {
888 SET_FUNCTION(opcode);
889 FILL_RECTANGLE(x, y, cx, cy);
890 RESET_FUNCTION(opcode);
891 }
892
893 void
894 ui_patblt(uint8 opcode,
895 /* dest */ int x, int y, int cx, int cy,
896 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
897 {
898 Pixmap fill;
899 uint8 i, ipattern[8];
900
901 SET_FUNCTION(opcode);
902
903 switch (brush->style)
904 {
905 case 0: /* Solid */
906 SET_FOREGROUND(fgcolour);
907 FILL_RECTANGLE(x, y, cx, cy);
908 break;
909
910 case 3: /* Pattern */
911 for (i = 0; i != 8; i++)
912 ipattern[7 - i] = brush->pattern[i];
913 fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
914
915 SET_FOREGROUND(bgcolour);
916 SET_BACKGROUND(fgcolour);
917 XSetFillStyle(display, gc, FillOpaqueStippled);
918 XSetStipple(display, gc, fill);
919 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
920
921 FILL_RECTANGLE(x, y, cx, cy);
922
923 XSetFillStyle(display, gc, FillSolid);
924 XSetTSOrigin(display, gc, 0, 0);
925 ui_destroy_glyph((HGLYPH) fill);
926 break;
927
928 default:
929 unimpl("brush %d\n", brush->style);
930 }
931
932 RESET_FUNCTION(opcode);
933 }
934
935 void
936 ui_screenblt(uint8 opcode,
937 /* dest */ int x, int y, int cx, int cy,
938 /* src */ int srcx, int srcy)
939 {
940 SET_FUNCTION(opcode);
941 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
942 if (ownbackstore)
943 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
944 RESET_FUNCTION(opcode);
945 }
946
947 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 {
952 SET_FUNCTION(opcode);
953 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
954 if (ownbackstore)
955 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
956 RESET_FUNCTION(opcode);
957 }
958
959 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 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
964 {
965 /* This is potentially difficult to do in general. Until someone
966 comes up with a more efficient way of doing it I am using cases. */
967
968 switch (opcode)
969 {
970 case 0x69: /* PDSxxn */
971 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
972 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
973 break;
974
975 case 0xb8: /* PSDPxax */
976 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
977 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
978 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
979 break;
980
981 case 0xc0: /* PSa */
982 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
983 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
984 break;
985
986 default:
987 unimpl("triblt 0x%x\n", opcode);
988 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
989 }
990 }
991
992 void
993 ui_line(uint8 opcode,
994 /* dest */ int startx, int starty, int endx, int endy,
995 /* pen */ PEN * pen)
996 {
997 SET_FUNCTION(opcode);
998 SET_FOREGROUND(pen->colour);
999 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1000 if (ownbackstore)
1001 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1002 RESET_FUNCTION(opcode);
1003 }
1004
1005 void
1006 ui_rect(
1007 /* dest */ int x, int y, int cx, int cy,
1008 /* brush */ int colour)
1009 {
1010 SET_FOREGROUND(colour);
1011 FILL_RECTANGLE(x, y, cx, cy);
1012 }
1013
1014 void
1015 ui_draw_glyph(int mixmode,
1016 /* dest */ int x, int y, int cx, int cy,
1017 /* src */ HGLYPH glyph, int srcx, int srcy,
1018 int bgcolour, int fgcolour)
1019 {
1020 SET_FOREGROUND(fgcolour);
1021 SET_BACKGROUND(bgcolour);
1022
1023 XSetFillStyle(display, gc,
1024 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1025 XSetStipple(display, gc, (Pixmap) glyph);
1026 XSetTSOrigin(display, gc, x, y);
1027
1028 FILL_RECTANGLE(x, y, cx, cy);
1029
1030 XSetFillStyle(display, gc, FillSolid);
1031 }
1032
1033 #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 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1043 else\
1044 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1045 idx += 2;\
1046 }\
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 void
1067 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1068 int clipx, int clipy, int clipcx, int clipcy,
1069 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1070 int fgcolour, uint8 * text, uint8 length)
1071 {
1072 FONTGLYPH *glyph;
1073 int i, j, xyoffset;
1074 DATABLOB *entry;
1075
1076 SET_FOREGROUND(bgcolour);
1077
1078 if (boxcx > 1)
1079 {
1080 FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1081 }
1082 else if (mixmode == MIX_OPAQUE)
1083 {
1084 FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1085 }
1086
1087 /* Paint text, character by character */
1088 for (i = 0; i < length;)
1089 {
1090 switch (text[i])
1091 {
1092 case 0xff:
1093 if (i + 2 < length)
1094 cache_put_text(text[i + 1], text, text[i + 2]);
1095 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 break;
1105
1106 case 0xfe:
1107 entry = cache_get_text(text[i + 1]);
1108 if (entry != NULL)
1109 {
1110 if ((((uint8 *) (entry->data))[1] ==
1111 0) && (!(flags & TEXT2_IMPLICIT_X)))
1112 {
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 else
1121 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 DO_GLYPH(((uint8 *) (entry->data)), j);
1128 }
1129 break;
1130
1131 default:
1132 DO_GLYPH(text, i);
1133 i++;
1134 break;
1135 }
1136 }
1137
1138
1139 }
1140
1141 void
1142 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1143 {
1144 Pixmap pix;
1145 XImage *image;
1146
1147 if (ownbackstore)
1148 {
1149 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1150 }
1151 else
1152 {
1153 pix = XCreatePixmap(display, wnd, cx, cy, depth);
1154 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1155 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1156 XFreePixmap(display, pix);
1157 }
1158
1159 offset *= bpp / 8;
1160 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1161
1162 XDestroyImage(image);
1163 }
1164
1165 void
1166 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1167 {
1168 XImage *image;
1169 uint8 *data;
1170
1171 offset *= bpp / 8;
1172 data = cache_get_desktop(offset, cx, cy, bpp / 8);
1173 if (data == NULL)
1174 return;
1175
1176 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1177 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1178
1179 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 XFree(image);
1190 }

  ViewVC Help
Powered by ViewVC 1.1.26