/[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 190 - (show annotations)
Tue Sep 24 07:33:17 2002 UTC (21 years, 7 months ago) by matthewc
File MIME type: text/plain
File size: 26194 byte(s)
Make no translation messages DEBUG_KBD.
Clean up includes, fix a few compile warnings, avoid rdesktop.h depending
on X (at the expense of KeySym -> uint32 - maybe in the future we need a
better proto scheme).

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

  ViewVC Help
Powered by ViewVC 1.1.26