/[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 209 - (show annotations)
Wed Oct 2 13:51:16 2002 UTC (21 years, 7 months ago) by matthewc
File MIME type: text/plain
File size: 26366 byte(s)
Arguments to get_key_state the wrong way around.

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\n");
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
355 if (IM != NULL)
356 {
357 IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
358 XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
359
360 if ((IC != NULL)
361 && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
362 input_mask |= ic_input_mask;
363 }
364
365 XSelectInput(display, wnd, input_mask);
366 XMapWindow(display, wnd);
367
368 /* wait for VisibilityNotify */
369 do
370 {
371 XMaskEvent(display, VisibilityChangeMask, &xevent);
372 }
373 while (xevent.type != VisibilityNotify);
374
375 if (fullscreen)
376 XSetInputFocus(display, wnd, RevertToPointerRoot, CurrentTime);
377
378 return True;
379 }
380
381 void
382 ui_destroy_window(void)
383 {
384 if (IC != NULL)
385 XDestroyIC(IC);
386
387 XDestroyWindow(display, wnd);
388 }
389
390 void
391 xwin_toggle_fullscreen(void)
392 {
393 Pixmap contents = 0;
394
395 if (!ownbackstore)
396 {
397 /* need to save contents of window */
398 contents = XCreatePixmap(display, wnd, width, height, depth);
399 XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
400 }
401
402 ui_destroy_window();
403 fullscreen = !fullscreen;
404 ui_create_window();
405
406 XDefineCursor(display, wnd, current_cursor);
407
408 if (!ownbackstore)
409 {
410 XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
411 XFreePixmap(display, contents);
412 }
413 }
414
415 /* Process all events in Xlib queue */
416 static void
417 xwin_process_events(void)
418 {
419 XEvent xevent;
420 KeySym keysym;
421 uint16 button, flags;
422 uint32 ev_time;
423 key_translation tr;
424 char str[256];
425 Status status;
426 unsigned int state;
427 Window wdummy;
428 int dummy;
429
430 while (XPending(display) > 0)
431 {
432 XNextEvent(display, &xevent);
433
434 if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
435 {
436 DEBUG_KBD(("Filtering event\n"));
437 continue;
438 }
439
440 flags = 0;
441
442 switch (xevent.type)
443 {
444 case KeyPress:
445 if (IC != NULL)
446 /* Multi_key compatible version */
447 {
448 XmbLookupString(IC,
449 (XKeyPressedEvent *) &
450 xevent, str, sizeof(str), &keysym, &status);
451 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
452 {
453 error("XmbLookupString failed with status 0x%x\n",
454 status);
455 break;
456 }
457 }
458 else
459 {
460 /* Plain old XLookupString */
461 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
462 XLookupString((XKeyEvent *) & xevent,
463 str, sizeof(str), &keysym, NULL);
464 }
465
466 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym)));
467
468 ev_time = time(NULL);
469 if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
470 break;
471
472 tr = xkeymap_translate_key(keysym,
473 xevent.xkey.keycode, xevent.xkey.state);
474
475 if (tr.scancode == 0)
476 break;
477
478 ensure_remote_modifiers(ev_time, tr);
479
480 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
481 break;
482
483 case KeyRelease:
484 XLookupString((XKeyEvent *) & xevent, str,
485 sizeof(str), &keysym, NULL);
486
487 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
488 get_ksname(keysym)));
489
490 ev_time = time(NULL);
491 if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
492 break;
493
494 tr = xkeymap_translate_key(keysym,
495 xevent.xkey.keycode, xevent.xkey.state);
496
497 if (tr.scancode == 0)
498 break;
499
500 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
501 break;
502
503 case ButtonPress:
504 flags = MOUSE_FLAG_DOWN;
505 /* fall through */
506
507 case ButtonRelease:
508 button = xkeymap_translate_button(xevent.xbutton.button);
509 if (button == 0)
510 break;
511
512 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
513 flags | button, xevent.xbutton.x, xevent.xbutton.y);
514 break;
515
516 case MotionNotify:
517 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
518 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
519 break;
520
521 case FocusIn:
522 XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
523 reset_modifier_keys(state);
524 if (grab_keyboard)
525 XGrabKeyboard(display, wnd, True,
526 GrabModeAsync, GrabModeAsync, CurrentTime);
527 break;
528
529 case FocusOut:
530 if (xevent.xfocus.mode == NotifyWhileGrabbed)
531 XUngrabKeyboard(display, CurrentTime);
532 break;
533
534 case Expose:
535 XCopyArea(display, backstore, wnd, gc,
536 xevent.xexpose.x, xevent.xexpose.y,
537 xevent.xexpose.width,
538 xevent.xexpose.height,
539 xevent.xexpose.x, xevent.xexpose.y);
540 break;
541
542 case MappingNotify:
543 /* Refresh keyboard mapping if it has changed. This is important for
544 Xvnc, since it allocates keycodes dynamically */
545 if (xevent.xmapping.request == MappingKeyboard
546 || xevent.xmapping.request == MappingModifier)
547 XRefreshKeyboardMapping(&xevent.xmapping);
548
549 if (xevent.xmapping.request == MappingModifier)
550 {
551 XFreeModifiermap(mod_map);
552 mod_map = XGetModifierMapping(display);
553 }
554 break;
555
556 }
557 }
558 }
559
560 void
561 ui_select(int rdp_socket)
562 {
563 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
564 fd_set rfds;
565
566 FD_ZERO(&rfds);
567
568 while (True)
569 {
570 /* Process any events already waiting */
571 xwin_process_events();
572
573 FD_ZERO(&rfds);
574 FD_SET(rdp_socket, &rfds);
575 FD_SET(x_socket, &rfds);
576
577 switch (select(n, &rfds, NULL, NULL, NULL))
578 {
579 case -1:
580 error("select: %s\n", strerror(errno));
581
582 case 0:
583 continue;
584 }
585
586 if (FD_ISSET(rdp_socket, &rfds))
587 return;
588 }
589 }
590
591 void
592 ui_move_pointer(int x, int y)
593 {
594 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
595 }
596
597 HBITMAP
598 ui_create_bitmap(int width, int height, uint8 * data)
599 {
600 XImage *image;
601 Pixmap bitmap;
602 uint8 *tdata;
603
604 tdata = translate_image(width, height, data);
605 bitmap = XCreatePixmap(display, wnd, width, height, depth);
606 image = XCreateImage(display, visual, depth, ZPixmap, 0,
607 (char *) tdata, width, height, 8, 0);
608
609 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
610
611 XFree(image);
612 xfree(tdata);
613 return (HBITMAP) bitmap;
614 }
615
616 void
617 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
618 {
619 XImage *image;
620 uint8 *tdata;
621
622 tdata = translate_image(width, height, data);
623 image = XCreateImage(display, visual, depth, ZPixmap, 0,
624 (char *) tdata, width, height, 8, 0);
625
626 if (ownbackstore)
627 {
628 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
629 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
630 }
631 else
632 {
633 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
634 }
635
636 XFree(image);
637 xfree(tdata);
638 }
639
640 void
641 ui_destroy_bitmap(HBITMAP bmp)
642 {
643 XFreePixmap(display, (Pixmap) bmp);
644 }
645
646 HGLYPH
647 ui_create_glyph(int width, int height, uint8 * data)
648 {
649 XImage *image;
650 Pixmap bitmap;
651 int scanline;
652 GC gc;
653
654 scanline = (width + 7) / 8;
655
656 bitmap = XCreatePixmap(display, wnd, width, height, 1);
657 gc = XCreateGC(display, bitmap, 0, NULL);
658
659 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
660 width, height, 8, scanline);
661 image->byte_order = MSBFirst;
662 image->bitmap_bit_order = MSBFirst;
663 XInitImage(image);
664
665 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
666
667 XFree(image);
668 XFreeGC(display, gc);
669 return (HGLYPH) bitmap;
670 }
671
672 void
673 ui_destroy_glyph(HGLYPH glyph)
674 {
675 XFreePixmap(display, (Pixmap) glyph);
676 }
677
678 HCURSOR
679 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
680 uint8 * andmask, uint8 * xormask)
681 {
682 HGLYPH maskglyph, cursorglyph;
683 XColor bg, fg;
684 Cursor xcursor;
685 uint8 *cursor, *pcursor;
686 uint8 *mask, *pmask;
687 uint8 nextbit;
688 int scanline, offset;
689 int i, j;
690
691 scanline = (width + 7) / 8;
692 offset = scanline * height;
693
694 cursor = xmalloc(offset);
695 memset(cursor, 0, offset);
696
697 mask = xmalloc(offset);
698 memset(mask, 0, offset);
699
700 /* approximate AND and XOR masks with a monochrome X pointer */
701 for (i = 0; i < height; i++)
702 {
703 offset -= scanline;
704 pcursor = &cursor[offset];
705 pmask = &mask[offset];
706
707 for (j = 0; j < scanline; j++)
708 {
709 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
710 {
711 if (xormask[0] || xormask[1] || xormask[2])
712 {
713 *pcursor |= (~(*andmask) & nextbit);
714 *pmask |= nextbit;
715 }
716 else
717 {
718 *pcursor |= ((*andmask) & nextbit);
719 *pmask |= (~(*andmask) & nextbit);
720 }
721
722 xormask += 3;
723 }
724
725 andmask++;
726 pcursor++;
727 pmask++;
728 }
729 }
730
731 fg.red = fg.blue = fg.green = 0xffff;
732 bg.red = bg.blue = bg.green = 0x0000;
733 fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
734
735 cursorglyph = ui_create_glyph(width, height, cursor);
736 maskglyph = ui_create_glyph(width, height, mask);
737
738 xcursor =
739 XCreatePixmapCursor(display, (Pixmap) cursorglyph,
740 (Pixmap) maskglyph, &fg, &bg, x, y);
741
742 ui_destroy_glyph(maskglyph);
743 ui_destroy_glyph(cursorglyph);
744 xfree(mask);
745 xfree(cursor);
746 return (HCURSOR) xcursor;
747 }
748
749 void
750 ui_set_cursor(HCURSOR cursor)
751 {
752 current_cursor = (Cursor) cursor;
753 XDefineCursor(display, wnd, current_cursor);
754 }
755
756 void
757 ui_destroy_cursor(HCURSOR cursor)
758 {
759 XFreeCursor(display, (Cursor) cursor);
760 }
761
762 #define MAKE_XCOLOR(xc,c) \
763 (xc)->red = ((c)->red << 8) | (c)->red; \
764 (xc)->green = ((c)->green << 8) | (c)->green; \
765 (xc)->blue = ((c)->blue << 8) | (c)->blue; \
766 (xc)->flags = DoRed | DoGreen | DoBlue;
767
768 HCOLOURMAP
769 ui_create_colourmap(COLOURMAP * colours)
770 {
771 COLOURENTRY *entry;
772 int i, ncolours = colours->ncolours;
773 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
774 XColor xentry;
775 XColor xc_cache[256];
776 uint32 colour;
777 int colLookup = 256;
778 for (i = 0; i < ncolours; i++)
779 {
780 entry = &colours->colours[i];
781 MAKE_XCOLOR(&xentry, entry);
782
783 if (XAllocColor(display, xcolmap, &xentry) == 0)
784 {
785 /* Allocation failed, find closest match. */
786 int j = 256;
787 int nMinDist = 3 * 256 * 256;
788 long nDist = nMinDist;
789
790 /* only get the colors once */
791 while (colLookup--)
792 {
793 xc_cache[colLookup].pixel = colLookup;
794 xc_cache[colLookup].red = xc_cache[colLookup].green =
795 xc_cache[colLookup].blue = 0;
796 xc_cache[colLookup].flags = 0;
797 XQueryColor(display,
798 DefaultColormap(display, DefaultScreen(display)),
799 &xc_cache[colLookup]);
800 }
801 colLookup = 0;
802
803 /* approximate the pixel */
804 while (j--)
805 {
806 if (xc_cache[j].flags)
807 {
808 nDist = ((long) (xc_cache[j].red >> 8) -
809 (long) (xentry.red >> 8)) *
810 ((long) (xc_cache[j].red >> 8) -
811 (long) (xentry.red >> 8)) +
812 ((long) (xc_cache[j].green >> 8) -
813 (long) (xentry.green >> 8)) *
814 ((long) (xc_cache[j].green >> 8) -
815 (long) (xentry.green >> 8)) +
816 ((long) (xc_cache[j].blue >> 8) -
817 (long) (xentry.blue >> 8)) *
818 ((long) (xc_cache[j].blue >> 8) -
819 (long) (xentry.blue >> 8));
820 }
821 if (nDist < nMinDist)
822 {
823 nMinDist = nDist;
824 xentry.pixel = j;
825 }
826 }
827 }
828 colour = xentry.pixel;
829
830 /* update our cache */
831 if (xentry.pixel < 256)
832 {
833 xc_cache[xentry.pixel].red = xentry.red;
834 xc_cache[xentry.pixel].green = xentry.green;
835 xc_cache[xentry.pixel].blue = xentry.blue;
836
837 }
838
839
840 /* byte swap here to make translate_image faster */
841 map[i] = translate_colour(colour);
842 }
843
844 return map;
845 }
846
847 void
848 ui_destroy_colourmap(HCOLOURMAP map)
849 {
850 xfree(map);
851 }
852
853 void
854 ui_set_colourmap(HCOLOURMAP map)
855 {
856 colmap = map;
857 }
858
859 void
860 ui_set_clip(int x, int y, int cx, int cy)
861 {
862 XRectangle rect;
863
864 rect.x = x;
865 rect.y = y;
866 rect.width = cx;
867 rect.height = cy;
868 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
869 }
870
871 void
872 ui_reset_clip(void)
873 {
874 XRectangle rect;
875
876 rect.x = 0;
877 rect.y = 0;
878 rect.width = width;
879 rect.height = height;
880 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
881 }
882
883 void
884 ui_bell(void)
885 {
886 XBell(display, 0);
887 }
888
889 void
890 ui_destblt(uint8 opcode,
891 /* dest */ int x, int y, int cx, int cy)
892 {
893 SET_FUNCTION(opcode);
894 FILL_RECTANGLE(x, y, cx, cy);
895 RESET_FUNCTION(opcode);
896 }
897
898 void
899 ui_patblt(uint8 opcode,
900 /* dest */ int x, int y, int cx, int cy,
901 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
902 {
903 Pixmap fill;
904 uint8 i, ipattern[8];
905
906 SET_FUNCTION(opcode);
907
908 switch (brush->style)
909 {
910 case 0: /* Solid */
911 SET_FOREGROUND(fgcolour);
912 FILL_RECTANGLE(x, y, cx, cy);
913 break;
914
915 case 3: /* Pattern */
916 for (i = 0; i != 8; i++)
917 ipattern[7 - i] = brush->pattern[i];
918 fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
919
920 SET_FOREGROUND(bgcolour);
921 SET_BACKGROUND(fgcolour);
922 XSetFillStyle(display, gc, FillOpaqueStippled);
923 XSetStipple(display, gc, fill);
924 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
925
926 FILL_RECTANGLE(x, y, cx, cy);
927
928 XSetFillStyle(display, gc, FillSolid);
929 XSetTSOrigin(display, gc, 0, 0);
930 ui_destroy_glyph((HGLYPH) fill);
931 break;
932
933 default:
934 unimpl("brush %d\n", brush->style);
935 }
936
937 RESET_FUNCTION(opcode);
938 }
939
940 void
941 ui_screenblt(uint8 opcode,
942 /* dest */ int x, int y, int cx, int cy,
943 /* src */ int srcx, int srcy)
944 {
945 SET_FUNCTION(opcode);
946 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
947 if (ownbackstore)
948 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
949 RESET_FUNCTION(opcode);
950 }
951
952 void
953 ui_memblt(uint8 opcode,
954 /* dest */ int x, int y, int cx, int cy,
955 /* src */ HBITMAP src, int srcx, int srcy)
956 {
957 SET_FUNCTION(opcode);
958 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
959 if (ownbackstore)
960 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
961 RESET_FUNCTION(opcode);
962 }
963
964 void
965 ui_triblt(uint8 opcode,
966 /* dest */ int x, int y, int cx, int cy,
967 /* src */ HBITMAP src, int srcx, int srcy,
968 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
969 {
970 /* This is potentially difficult to do in general. Until someone
971 comes up with a more efficient way of doing it I am using cases. */
972
973 switch (opcode)
974 {
975 case 0x69: /* PDSxxn */
976 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
977 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
978 break;
979
980 case 0xb8: /* PSDPxax */
981 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
982 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
983 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
984 break;
985
986 case 0xc0: /* PSa */
987 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
988 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
989 break;
990
991 default:
992 unimpl("triblt 0x%x\n", opcode);
993 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
994 }
995 }
996
997 void
998 ui_line(uint8 opcode,
999 /* dest */ int startx, int starty, int endx, int endy,
1000 /* pen */ PEN * pen)
1001 {
1002 SET_FUNCTION(opcode);
1003 SET_FOREGROUND(pen->colour);
1004 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1005 if (ownbackstore)
1006 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1007 RESET_FUNCTION(opcode);
1008 }
1009
1010 void
1011 ui_rect(
1012 /* dest */ int x, int y, int cx, int cy,
1013 /* brush */ int colour)
1014 {
1015 SET_FOREGROUND(colour);
1016 FILL_RECTANGLE(x, y, cx, cy);
1017 }
1018
1019 void
1020 ui_draw_glyph(int mixmode,
1021 /* dest */ int x, int y, int cx, int cy,
1022 /* src */ HGLYPH glyph, int srcx, int srcy,
1023 int bgcolour, int fgcolour)
1024 {
1025 SET_FOREGROUND(fgcolour);
1026 SET_BACKGROUND(bgcolour);
1027
1028 XSetFillStyle(display, gc,
1029 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1030 XSetStipple(display, gc, (Pixmap) glyph);
1031 XSetTSOrigin(display, gc, x, y);
1032
1033 FILL_RECTANGLE(x, y, cx, cy);
1034
1035 XSetFillStyle(display, gc, FillSolid);
1036 }
1037
1038 #define DO_GLYPH(ttext,idx) \
1039 {\
1040 glyph = cache_get_font (font, ttext[idx]);\
1041 if (!(flags & TEXT2_IMPLICIT_X))\
1042 {\
1043 xyoffset = ttext[++idx];\
1044 if ((xyoffset & 0x80))\
1045 {\
1046 if (flags & TEXT2_VERTICAL) \
1047 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1048 else\
1049 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1050 idx += 2;\
1051 }\
1052 else\
1053 {\
1054 if (flags & TEXT2_VERTICAL) \
1055 y += xyoffset;\
1056 else\
1057 x += xyoffset;\
1058 }\
1059 }\
1060 if (glyph != NULL)\
1061 {\
1062 ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1063 y + (short) glyph->baseline,\
1064 glyph->width, glyph->height,\
1065 glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1066 if (flags & TEXT2_IMPLICIT_X)\
1067 x += glyph->width;\
1068 }\
1069 }
1070
1071 void
1072 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1073 int clipx, int clipy, int clipcx, int clipcy,
1074 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1075 int fgcolour, uint8 * text, uint8 length)
1076 {
1077 FONTGLYPH *glyph;
1078 int i, j, xyoffset;
1079 DATABLOB *entry;
1080
1081 SET_FOREGROUND(bgcolour);
1082
1083 if (boxcx > 1)
1084 {
1085 FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1086 }
1087 else if (mixmode == MIX_OPAQUE)
1088 {
1089 FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1090 }
1091
1092 /* Paint text, character by character */
1093 for (i = 0; i < length;)
1094 {
1095 switch (text[i])
1096 {
1097 case 0xff:
1098 if (i + 2 < length)
1099 cache_put_text(text[i + 1], text, text[i + 2]);
1100 else
1101 {
1102 error("this shouldn't be happening\n");
1103 break;
1104 }
1105 /* this will move pointer from start to first character after FF command */
1106 length -= i + 3;
1107 text = &(text[i + 3]);
1108 i = 0;
1109 break;
1110
1111 case 0xfe:
1112 entry = cache_get_text(text[i + 1]);
1113 if (entry != NULL)
1114 {
1115 if ((((uint8 *) (entry->data))[1] ==
1116 0) && (!(flags & TEXT2_IMPLICIT_X)))
1117 {
1118 if (flags & TEXT2_VERTICAL)
1119 y += text[i + 2];
1120 else
1121 x += text[i + 2];
1122 }
1123 if (i + 2 < length)
1124 i += 3;
1125 else
1126 i += 2;
1127 length -= i;
1128 /* this will move pointer from start to first character after FE command */
1129 text = &(text[i]);
1130 i = 0;
1131 for (j = 0; j < entry->size; j++)
1132 DO_GLYPH(((uint8 *) (entry->data)), j);
1133 }
1134 break;
1135
1136 default:
1137 DO_GLYPH(text, i);
1138 i++;
1139 break;
1140 }
1141 }
1142
1143
1144 }
1145
1146 void
1147 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1148 {
1149 Pixmap pix;
1150 XImage *image;
1151
1152 if (ownbackstore)
1153 {
1154 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1155 }
1156 else
1157 {
1158 pix = XCreatePixmap(display, wnd, cx, cy, depth);
1159 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1160 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1161 XFreePixmap(display, pix);
1162 }
1163
1164 offset *= bpp / 8;
1165 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1166
1167 XDestroyImage(image);
1168 }
1169
1170 void
1171 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1172 {
1173 XImage *image;
1174 uint8 *data;
1175
1176 offset *= bpp / 8;
1177 data = cache_get_desktop(offset, cx, cy, bpp / 8);
1178 if (data == NULL)
1179 return;
1180
1181 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1182 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1183
1184 if (ownbackstore)
1185 {
1186 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1187 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1188 }
1189 else
1190 {
1191 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1192 }
1193
1194 XFree(image);
1195 }

  ViewVC Help
Powered by ViewVC 1.1.26