/[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 64 - (show annotations)
Thu Jul 18 16:38:31 2002 UTC (21 years, 10 months ago) by astrand
File MIME type: text/plain
File size: 29146 byte(s)
Fixed indentation with indent

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 <X11/XKBlib.h>
24 #include <time.h>
25 #include <errno.h>
26 #include "rdesktop.h"
27
28 extern char keymapname[16];
29 extern int keylayout;
30 extern int width;
31 extern int height;
32 extern BOOL sendmotion;
33 extern BOOL fullscreen;
34
35 Display *display;
36 XkbDescPtr xkb;
37 static int x_socket;
38 static Window wnd;
39 static GC gc;
40 static Visual *visual;
41 static int depth;
42 static int bpp;
43
44 /* endianness */
45 static BOOL host_be;
46 static BOOL xserver_be;
47
48 /* software backing store */
49 static BOOL ownbackstore;
50 static Pixmap backstore;
51
52 /* needed to keep track of the modifiers */
53 static unsigned int numlock_modifier_mask = 0;
54 static unsigned int key_down_state = 0;
55
56
57 #define DShift1Mask (1<<0)
58 #define DLockMask (1<<1)
59 #define DControl1Mask (1<<2)
60 #define DMod1Mask (1<<3)
61 #define DMod2Mask (1<<4)
62 #define DMod3Mask (1<<5)
63 #define DMod4Mask (1<<6)
64 #define DMod5Mask (1<<7)
65 #define DShift2Mask (1<<8)
66 #define DControl2Mask (1<<9)
67 #define DNumLockMask (1<<10)
68
69 #define FILL_RECTANGLE(x,y,cx,cy)\
70 { \
71 XFillRectangle(display, wnd, gc, x, y, cx, cy); \
72 if (ownbackstore) \
73 XFillRectangle(display, backstore, gc, x, y, cx, cy); \
74 }
75
76 /* colour maps */
77 static BOOL owncolmap;
78 static Colormap xcolmap;
79 static uint32 white;
80 static uint32 *colmap;
81
82 #define TRANSLATE(col) ( owncolmap ? col : translate_colour(colmap[col]) )
83 #define SET_FOREGROUND(col) XSetForeground(display, gc, TRANSLATE(col));
84 #define SET_BACKGROUND(col) XSetBackground(display, gc, TRANSLATE(col));
85
86 static int rop2_map[] = {
87 GXclear, /* 0 */
88 GXnor, /* DPon */
89 GXandInverted, /* DPna */
90 GXcopyInverted, /* Pn */
91 GXandReverse, /* PDna */
92 GXinvert, /* Dn */
93 GXxor, /* DPx */
94 GXnand, /* DPan */
95 GXand, /* DPa */
96 GXequiv, /* DPxn */
97 GXnoop, /* D */
98 GXorInverted, /* DPno */
99 GXcopy, /* P */
100 GXorReverse, /* PDno */
101 GXor, /* DPo */
102 GXset /* 1 */
103 };
104
105 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
106 #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
107
108 void xwin_get_numlock_mask();
109 void xwin_mod_update(uint32 state, uint32 ev_time);
110 void xwin_mod_release(uint32 state, uint32 ev_time, uint32 scancode);
111 void xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode);
112
113 static void
114 translate8(uint8 * data, uint8 * out, uint8 * end)
115 {
116 while (out < end)
117 *(out++) = (uint8) colmap[*(data++)];
118 }
119
120 static void
121 translate16(uint8 * data, uint16 * out, uint16 * end)
122 {
123 while (out < end)
124 *(out++) = (uint16) colmap[*(data++)];
125 }
126
127 /* little endian - conversion happens when colourmap is built */
128 static void
129 translate24(uint8 * data, uint8 * out, uint8 * end)
130 {
131 uint32 value;
132
133 while (out < end)
134 {
135 value = colmap[*(data++)];
136 *(out++) = value;
137 *(out++) = value >> 8;
138 *(out++) = value >> 16;
139 }
140 }
141
142 static void
143 translate32(uint8 * data, uint32 * out, uint32 * end)
144 {
145 while (out < end)
146 *(out++) = colmap[*(data++)];
147 }
148
149 static uint8 *
150 translate_image(int width, int height, uint8 * data)
151 {
152 int size = width * height * bpp / 8;
153 uint8 *out = xmalloc(size);
154 uint8 *end = out + size;
155
156 switch (bpp)
157 {
158 case 8:
159 translate8(data, out, end);
160 break;
161
162 case 16:
163 translate16(data, (uint16 *) out, (uint16 *) end);
164 break;
165
166 case 24:
167 translate24(data, out, end);
168 break;
169
170 case 32:
171 translate32(data, (uint32 *) out, (uint32 *) end);
172 break;
173 }
174
175 return out;
176 }
177
178 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
179 #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
180 #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
181 x = (x << 16) | (x >> 16); }
182
183 static uint32
184 translate_colour(uint32 colour)
185 {
186 switch (bpp)
187 {
188 case 16:
189 if (host_be != xserver_be)
190 BSWAP16(colour);
191 break;
192
193 case 24:
194 if (xserver_be)
195 BSWAP24(colour);
196 break;
197
198 case 32:
199 if (host_be != xserver_be)
200 BSWAP32(colour);
201 break;
202 }
203
204 return colour;
205 }
206
207 BOOL
208 ui_create_window(char *title)
209 {
210 XSetWindowAttributes attribs;
211 XClassHint *classhints;
212 XSizeHints *sizehints;
213 unsigned long input_mask;
214 XPixmapFormatValues *pfm;
215 Screen *screen;
216 uint16 test;
217 int i;
218
219 int xkb_minor, xkb_major;
220 int xkb_event, xkb_error, xkb_reason;
221
222 /* compare compiletime libs with runtime libs. */
223 xkb_major = XkbMajorVersion;
224 xkb_minor = XkbMinorVersion;
225 if (XkbLibraryVersion(&xkb_major, &xkb_minor) == False)
226 {
227 error("please re-compile rdesktop\ncompile time version of xkb is not compatible with\nyour runtime version of the library\n");
228 return False;
229 }
230
231
232 display =
233 XkbOpenDisplay(NULL, &xkb_event, &xkb_error, &xkb_major,
234 &xkb_minor, &xkb_reason);
235 switch (xkb_reason)
236 {
237 case XkbOD_BadLibraryVersion:
238 error("XkbOD_BadLibraryVersion: XKB extensions in server and the library rdesktop is linked against aren't compatible with each other.\n");
239 break;
240 case XkbOD_ConnectionRefused:
241 error("XkbOD_ConnectionRefused\n");
242 break;
243 case XkbOD_BadServerVersion:
244 error("XkbOD_BadServerVersion\n");
245 break;
246 case XkbOD_NonXkbServer:
247 error("XkbOD_NonXkbServer: XKB extension not present in server\nupdate your X server.\n");
248 break;
249 case XkbOD_Success:
250 DEBUG("XkbOD_Success: Connection established with display\n");
251 break;
252 }
253
254 if (display == NULL)
255 {
256 error("Failed to open display\n");
257 return False;
258 }
259
260 x_socket = ConnectionNumber(display);
261 screen = DefaultScreenOfDisplay(display);
262 visual = DefaultVisualOfScreen(screen);
263 depth = DefaultDepthOfScreen(screen);
264
265 pfm = XListPixmapFormats(display, &i);
266 if (pfm != NULL)
267 {
268 /* Use maximum bpp for this depth - this is generally
269 desirable, e.g. 24 bits->32 bits. */
270 while (i--)
271 {
272 if ((pfm[i].depth == depth)
273 && (pfm[i].bits_per_pixel > bpp))
274 {
275 bpp = pfm[i].bits_per_pixel;
276 }
277 }
278 XFree(pfm);
279 }
280
281 if (bpp < 8)
282 {
283 error("Less than 8 bpp not currently supported.\n");
284 XCloseDisplay(display);
285 return False;
286 }
287
288 if (depth <= 8)
289 owncolmap = True;
290 else
291 xcolmap = DefaultColormapOfScreen(screen);
292
293 test = 1;
294 host_be = !(BOOL) (*(uint8 *) (&test));
295 xserver_be = (ImageByteOrder(display) == MSBFirst);
296
297 white = WhitePixelOfScreen(screen);
298 attribs.background_pixel = BlackPixelOfScreen(screen);
299 attribs.backing_store = DoesBackingStore(screen);
300
301 if (attribs.backing_store == NotUseful)
302 ownbackstore = True;
303
304 if (fullscreen)
305 {
306 attribs.override_redirect = True;
307 width = WidthOfScreen(screen);
308 height = HeightOfScreen(screen);
309 }
310 else
311 {
312 attribs.override_redirect = False;
313 }
314
315 width = (width + 3) & ~3; /* make width a multiple of 32 bits */
316
317 wnd = XCreateWindow(display, RootWindowOfScreen(screen),
318 0, 0, width, height, 0, CopyFromParent,
319 InputOutput, CopyFromParent,
320 CWBackingStore | CWBackPixel | CWOverrideRedirect,
321 &attribs);
322
323 XStoreName(display, wnd, title);
324
325 classhints = XAllocClassHint();
326 if (classhints != NULL)
327 {
328 classhints->res_name = classhints->res_class = "rdesktop";
329 XSetClassHint(display, wnd, classhints);
330 XFree(classhints);
331 }
332
333 sizehints = XAllocSizeHints();
334 if (sizehints)
335 {
336 sizehints->flags = PMinSize | PMaxSize;
337 sizehints->min_width = sizehints->max_width = width;
338 sizehints->min_height = sizehints->max_height = height;
339 XSetWMNormalHints(display, wnd, sizehints);
340 XFree(sizehints);
341 }
342
343 xkeymap_init();
344
345 input_mask = KeyPressMask | KeyReleaseMask |
346 ButtonPressMask | ButtonReleaseMask |
347 EnterWindowMask | LeaveWindowMask;
348 if (sendmotion)
349 input_mask |= PointerMotionMask;
350
351 if (ownbackstore)
352 input_mask |= ExposureMask;
353
354 XSelectInput(display, wnd, input_mask);
355 gc = XCreateGC(display, wnd, 0, NULL);
356
357 if (ownbackstore)
358 backstore = XCreatePixmap(display, wnd, width, height, depth);
359
360 XMapWindow(display, wnd);
361
362 /* TODO: error texts... make them friendly. */
363 xkb = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);
364 if ((int) xkb == BadAlloc || xkb == NULL)
365 {
366 error("XkbGetKeyboard failed.\n");
367 exit(0);
368 }
369
370 /* TODO: error texts... make them friendly. */
371 if (XkbSelectEvents
372 (display, xkb->device_spec, XkbAllEventsMask,
373 XkbAllEventsMask) == False)
374 {
375 error("XkbSelectEvents failed.\n");
376 exit(0);
377 }
378
379 xwin_get_numlock_mask();
380
381 return True;
382 }
383
384 void
385 xwin_get_numlock_mask()
386 {
387 KeyCode numlockcode;
388 KeyCode *keycode;
389 XModifierKeymap *modmap;
390 int i, j;
391
392 /* Find out if numlock is already defined as a modifier key, and if so where */
393 numlockcode = XKeysymToKeycode(display, 0xFF7F); /* XF_Num_Lock = 0xFF7F */
394 if (numlockcode)
395 {
396 modmap = XGetModifierMapping(display);
397 if (modmap)
398 {
399 keycode = modmap->modifiermap;
400 for (i = 0; i < 8; i++)
401 for (j = modmap->max_keypermod; j--;)
402 {
403 if (*keycode == numlockcode)
404 {
405 numlock_modifier_mask =
406 (1 << i);
407 i = 8;
408 break;
409 }
410 keycode++;
411 }
412 if (!numlock_modifier_mask)
413 {
414 modmap->modifiermap[7 *
415 modmap->max_keypermod] =
416 numlockcode;
417 if (XSetModifierMapping(display, modmap) ==
418 MappingSuccess)
419 numlock_modifier_mask = (1 << 7);
420 else
421 printf("XSetModifierMapping failed!\n");
422 }
423 XFreeModifiermap(modmap);
424 }
425 }
426
427 if (!numlock_modifier_mask)
428 printf("WARNING: Failed to get a numlock modifier mapping.\n");
429
430 }
431
432 void
433 ui_destroy_window()
434 {
435 if (xkb != NULL)
436 XkbFreeKeyboard(xkb, XkbAllControlsMask, True);
437
438 if (ownbackstore)
439 XFreePixmap(display, backstore);
440
441 XFreeGC(display, gc);
442 XDestroyWindow(display, wnd);
443 XCloseDisplay(display);
444 display = NULL;
445 }
446
447 static void
448 xwin_process_events()
449 {
450 XEvent xevent;
451
452 KeySym keysym;
453 uint8 scancode;
454 uint16 button, flags;
455 uint32 ev_time;
456 uint32 tmpmods;
457
458 while (XCheckMaskEvent(display, ~0, &xevent))
459 {
460 ev_time = time(NULL);
461 flags = 0;
462
463 switch (xevent.type)
464 {
465 case KeyRelease:
466 flags = KBD_FLAG_DOWN | KBD_FLAG_UP;
467 /* fall through */
468 case KeyPress:
469 if (XkbTranslateKeyCode
470 (xkb, xevent.xkey.keycode,
471 xevent.xkey.state, &tmpmods,
472 &keysym) == False)
473 break;
474 scancode =
475 xkeymap_translate_key(keysym,
476 xevent.xkey.
477 keycode,
478 &flags);
479
480 if (scancode == 0)
481 break;
482
483 /* keep track of the modifiers -- needed for stickykeys... */
484 if (xevent.type == KeyPress)
485 xwin_mod_press(xevent.xkey.state,
486 ev_time, scancode);
487
488 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
489 flags, scancode, 0);
490
491 if (xevent.type == KeyRelease)
492 xwin_mod_release(xevent.xkey.state,
493 ev_time, scancode);
494
495 break;
496
497 case ButtonPress:
498 flags = MOUSE_FLAG_DOWN;
499 /* fall through */
500
501 case ButtonRelease:
502 button = xkeymap_translate_button(xevent.
503 xbutton.
504 button);
505 if (button == 0)
506 break;
507
508 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
509 flags | button,
510 xevent.xbutton.x,
511 xevent.xbutton.y);
512 break;
513
514 case MotionNotify:
515 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
516 MOUSE_FLAG_MOVE,
517 xevent.xmotion.x,
518 xevent.xmotion.y);
519 break;
520
521 case EnterNotify:
522 XGrabKeyboard(display, wnd, True,
523 GrabModeAsync, GrabModeAsync,
524 CurrentTime);
525
526 xwin_mod_update(xevent.xcrossing.state,
527 ev_time);
528 break;
529
530 case LeaveNotify:
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 }
543 }
544
545 void
546 xwin_mod_update(uint32 state, uint32 ev_time)
547 {
548 xwin_mod_press(state, ev_time, 0);
549 xwin_mod_release(state, ev_time, 0);
550 }
551
552 void
553 xwin_mod_release(uint32 state, uint32 ev_time, uint32 scancode)
554 {
555 switch (scancode)
556 {
557 case 0x2a:
558 key_down_state &= ~DShift1Mask;
559 break;
560 case 0x36:
561 key_down_state &= ~DShift2Mask;
562 break;
563 case 0x1d:
564 key_down_state &= ~DControl1Mask;
565 break;
566 case 0x9d:
567 key_down_state &= ~DControl2Mask;
568 break;
569 case 0x38:
570 key_down_state &= ~DMod1Mask;
571 break;
572 case 0xb8:
573 key_down_state &= ~DMod2Mask;
574 break;
575 }
576
577 if (!(numlock_modifier_mask & state)
578 && (key_down_state & DNumLockMask))
579 {
580 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x45, 0);
581 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
582 KBD_FLAG_DOWN | KBD_FLAG_UP, 0x45, 0);
583 key_down_state &= ~DNumLockMask;
584 }
585
586 if (!(LockMask & state) && (key_down_state & DLockMask))
587 {
588 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);
589 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
590 KBD_FLAG_DOWN | KBD_FLAG_UP, 0x3a, 0);
591 key_down_state &= ~DLockMask;
592
593 }
594
595
596 if (!(ShiftMask & state) && (key_down_state & DShift1Mask))
597 {
598 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a,
599 0);
600 key_down_state &= ~DShift1Mask;
601
602 }
603
604 if (!(ControlMask & state) && (key_down_state & DControl1Mask))
605 {
606 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d,
607 0);
608 key_down_state &= ~DControl1Mask;
609
610 }
611
612 if (!(Mod1Mask & state) && (key_down_state & DMod1Mask))
613 {
614 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38,
615 0);
616 key_down_state &= ~DMod1Mask;
617
618 }
619
620 if (!(Mod2Mask & state) && (key_down_state & DMod2Mask))
621 {
622 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8,
623 0);
624 key_down_state &= ~DMod2Mask;
625 }
626 }
627
628
629 void
630 xwin_mod_press(uint32 state, uint32 ev_time, uint32 scancode)
631 {
632
633 switch (scancode)
634 {
635 case 0x2a:
636 key_down_state |= DShift1Mask;
637 break;
638 case 0x36:
639 key_down_state |= DShift2Mask;
640 break;
641 case 0x1d:
642 key_down_state |= DControl1Mask;
643 break;
644 case 0x9d:
645 key_down_state |= DControl2Mask;
646 break;
647 case 0x3a:
648 key_down_state ^= DLockMask;
649 break;
650 case 0x45:
651 key_down_state ^= DNumLockMask;
652 break;
653 case 0x38:
654 key_down_state |= DMod1Mask;
655 break;
656 case 0xb8:
657 key_down_state |= DMod2Mask;
658 break;
659 }
660
661 if ((numlock_modifier_mask && state)
662 && !(key_down_state & DNumLockMask))
663 {
664 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x45, 0);
665 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
666 KBD_FLAG_DOWN | KBD_FLAG_UP, 0x45, 0);
667 key_down_state |= DNumLockMask;
668 }
669
670 if ((LockMask & state) && !(key_down_state & DLockMask))
671 {
672 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0, 0x3a, 0);
673 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
674 KBD_FLAG_DOWN | KBD_FLAG_UP, 0x3a, 0);
675 key_down_state |= DLockMask;
676
677 }
678
679
680 if ((ShiftMask & state)
681 && !((key_down_state & DShift1Mask)
682 || (key_down_state & DShift2Mask)))
683 {
684 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,
685 0x2a, 0);
686 key_down_state |= DShift1Mask;
687
688 }
689
690 if ((ControlMask & state)
691 && !((key_down_state & DControl1Mask)
692 || (key_down_state & DControl2Mask)))
693 {
694 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,
695 0x1d, 0);
696 key_down_state |= DControl1Mask;
697
698 }
699
700 if ((Mod1Mask & state) && !(key_down_state & DMod1Mask))
701 {
702 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,
703 0x38, 0);
704 key_down_state |= DMod1Mask;
705
706 }
707
708 if ((Mod2Mask & state) && !(key_down_state & DMod2Mask))
709 {
710 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN,
711 0xb8, 0);
712 key_down_state |= DMod2Mask;
713
714 }
715 }
716
717 void
718 ui_select(int rdp_socket)
719 {
720 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
721 fd_set rfds;
722
723 FD_ZERO(&rfds);
724
725 while (True)
726 {
727 FD_ZERO(&rfds);
728 FD_SET(rdp_socket, &rfds);
729 if (display != NULL)
730 {
731 FD_SET(x_socket, &rfds);
732 XFlush(display);
733 }
734
735 switch (select(n, &rfds, NULL, NULL, NULL))
736 {
737 case -1:
738 error("select: %s\n", strerror(errno));
739
740 case 0:
741 continue;
742 }
743
744 if (FD_ISSET(x_socket, &rfds))
745 xwin_process_events();
746
747 if (FD_ISSET(rdp_socket, &rfds))
748 return;
749 }
750 }
751
752 void
753 ui_move_pointer(int x, int y)
754 {
755 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
756 }
757
758 HBITMAP
759 ui_create_bitmap(int width, int height, uint8 * data)
760 {
761 XImage *image;
762 Pixmap bitmap;
763 uint8 *tdata;
764
765 tdata = (owncolmap ? data : translate_image(width, height, data));
766 bitmap = XCreatePixmap(display, wnd, width, height, depth);
767 image = XCreateImage(display, visual, depth, ZPixmap,
768 0, tdata, width, height, 8, 0);
769
770 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
771
772 XFree(image);
773 if (!owncolmap)
774 xfree(tdata);
775 return (HBITMAP) bitmap;
776 }
777
778 void
779 ui_paint_bitmap(int x, int y, int cx, int cy,
780 int width, int height, uint8 * data)
781 {
782 XImage *image;
783 uint8 *tdata;
784
785 tdata = (owncolmap ? data : translate_image(width, height, data));
786 image = XCreateImage(display, visual, depth, ZPixmap,
787 0, tdata, width, height, 8, 0);
788
789 if (ownbackstore)
790 {
791 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
792 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
793 }
794 else
795 {
796 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
797 }
798
799 XFree(image);
800 if (!owncolmap)
801 xfree(tdata);
802 }
803
804 void
805 ui_destroy_bitmap(HBITMAP bmp)
806 {
807 XFreePixmap(display, (Pixmap) bmp);
808 }
809
810 HGLYPH
811 ui_create_glyph(int width, int height, uint8 * data)
812 {
813 XImage *image;
814 Pixmap bitmap;
815 int scanline;
816 GC gc;
817
818 scanline = (width + 7) / 8;
819
820 bitmap = XCreatePixmap(display, wnd, width, height, 1);
821 gc = XCreateGC(display, bitmap, 0, NULL);
822
823 image = XCreateImage(display, visual, 1, ZPixmap, 0,
824 data, width, height, 8, scanline);
825 image->byte_order = MSBFirst;
826 image->bitmap_bit_order = MSBFirst;
827 XInitImage(image);
828
829 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
830
831 XFree(image);
832 XFreeGC(display, gc);
833 return (HGLYPH) bitmap;
834 }
835
836 void
837 ui_destroy_glyph(HGLYPH glyph)
838 {
839 XFreePixmap(display, (Pixmap) glyph);
840 }
841
842 HCURSOR
843 ui_create_cursor(unsigned int x, unsigned int y, int width,
844 int height, uint8 * andmask, uint8 * xormask)
845 {
846 HGLYPH maskglyph, cursorglyph;
847 XColor bg, fg;
848 Cursor xcursor;
849 uint8 *cursor, *pcursor;
850 uint8 *mask, *pmask;
851 uint8 nextbit;
852 int scanline, offset;
853 int i, j;
854
855 scanline = (width + 7) / 8;
856 offset = scanline * height;
857
858 cursor = xmalloc(offset);
859 memset(cursor, 0, offset);
860
861 mask = xmalloc(offset);
862 memset(mask, 0, offset);
863
864 /* approximate AND and XOR masks with a monochrome X pointer */
865 for (i = 0; i < height; i++)
866 {
867 offset -= scanline;
868 pcursor = &cursor[offset];
869 pmask = &mask[offset];
870
871 for (j = 0; j < scanline; j++)
872 {
873 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
874 {
875 if (xormask[0] || xormask[1] || xormask[2])
876 {
877 *pcursor |= (~(*andmask) & nextbit);
878 *pmask |= nextbit;
879 }
880 else
881 {
882 *pcursor |= ((*andmask) & nextbit);
883 *pmask |= (~(*andmask) & nextbit);
884 }
885
886 xormask += 3;
887 }
888
889 andmask++;
890 pcursor++;
891 pmask++;
892 }
893 }
894
895 fg.red = fg.blue = fg.green = 0xffff;
896 bg.red = bg.blue = bg.green = 0x0000;
897 fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
898
899 cursorglyph = ui_create_glyph(width, height, cursor);
900 maskglyph = ui_create_glyph(width, height, mask);
901
902 xcursor = XCreatePixmapCursor(display, (Pixmap) cursorglyph,
903 (Pixmap) maskglyph, &fg, &bg, x, y);
904
905 ui_destroy_glyph(maskglyph);
906 ui_destroy_glyph(cursorglyph);
907 xfree(mask);
908 xfree(cursor);
909 return (HCURSOR) xcursor;
910 }
911
912 void
913 ui_set_cursor(HCURSOR cursor)
914 {
915 XDefineCursor(display, wnd, (Cursor) cursor);
916 }
917
918 void
919 ui_destroy_cursor(HCURSOR cursor)
920 {
921 XFreeCursor(display, (Cursor) cursor);
922 }
923
924 #define MAKE_XCOLOR(xc,c) \
925 (xc)->red = ((c)->red << 8) | (c)->red; \
926 (xc)->green = ((c)->green << 8) | (c)->green; \
927 (xc)->blue = ((c)->blue << 8) | (c)->blue; \
928 (xc)->flags = DoRed | DoGreen | DoBlue;
929
930 HCOLOURMAP
931 ui_create_colourmap(COLOURMAP * colours)
932 {
933 COLOURENTRY *entry;
934 int i, ncolours = colours->ncolours;
935
936 if (owncolmap)
937 {
938 XColor *xcolours, *xentry;
939 Colormap map;
940
941 xcolours = xmalloc(sizeof(XColor) * ncolours);
942 for (i = 0; i < ncolours; i++)
943 {
944 entry = &colours->colours[i];
945 xentry = &xcolours[i];
946 xentry->pixel = i;
947 MAKE_XCOLOR(xentry, entry);
948 }
949
950 map = XCreateColormap(display, wnd, visual, AllocAll);
951 XStoreColors(display, map, xcolours, ncolours);
952
953 xfree(xcolours);
954 return (HCOLOURMAP) map;
955 }
956 else
957 {
958 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
959 XColor xentry;
960 uint32 colour;
961
962 for (i = 0; i < ncolours; i++)
963 {
964 entry = &colours->colours[i];
965 MAKE_XCOLOR(&xentry, entry);
966
967 if (XAllocColor(display, xcolmap, &xentry) != 0)
968 colour = xentry.pixel;
969 else
970 colour = white;
971
972 /* byte swap here to make translate_image faster */
973 map[i] = translate_colour(colour);
974 }
975
976 return map;
977 }
978 }
979
980 void
981 ui_destroy_colourmap(HCOLOURMAP map)
982 {
983 if (owncolmap)
984 XFreeColormap(display, (Colormap) map);
985 else
986 xfree(map);
987 }
988
989 void
990 ui_set_colourmap(HCOLOURMAP map)
991 {
992 if (owncolmap)
993 XSetWindowColormap(display, wnd, (Colormap) map);
994 else
995 colmap = map;
996 }
997
998 void
999 ui_set_clip(int x, int y, int cx, int cy)
1000 {
1001 XRectangle rect;
1002
1003 rect.x = x;
1004 rect.y = y;
1005 rect.width = cx;
1006 rect.height = cy;
1007 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1008 }
1009
1010 void
1011 ui_reset_clip()
1012 {
1013 XRectangle rect;
1014
1015 rect.x = 0;
1016 rect.y = 0;
1017 rect.width = width;
1018 rect.height = height;
1019 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1020 }
1021
1022 void
1023 ui_bell()
1024 {
1025 XBell(display, 0);
1026 }
1027
1028 void
1029 ui_destblt(uint8 opcode,
1030 /* dest */ int x, int y, int cx, int cy)
1031 {
1032 SET_FUNCTION(opcode);
1033 FILL_RECTANGLE(x, y, cx, cy);
1034 RESET_FUNCTION(opcode);
1035 }
1036
1037 void
1038 ui_patblt(uint8 opcode,
1039 /* dest */ int x, int y, int cx, int cy,
1040 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1041 {
1042 Pixmap fill;
1043 uint8 i, ipattern[8];
1044
1045 SET_FUNCTION(opcode);
1046
1047 switch (brush->style)
1048 {
1049 case 0: /* Solid */
1050 SET_FOREGROUND(fgcolour);
1051 FILL_RECTANGLE(x, y, cx, cy);
1052 break;
1053
1054 case 3: /* Pattern */
1055 for (i = 0; i != 8; i++)
1056 ipattern[7 - i] = brush->pattern[i];
1057 fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1058
1059 SET_FOREGROUND(bgcolour);
1060 SET_BACKGROUND(fgcolour);
1061 XSetFillStyle(display, gc, FillOpaqueStippled);
1062 XSetStipple(display, gc, fill);
1063 XSetTSOrigin(display, gc, brush->xorigin,
1064 brush->yorigin);
1065
1066 FILL_RECTANGLE(x, y, cx, cy);
1067
1068 XSetFillStyle(display, gc, FillSolid);
1069 ui_destroy_glyph((HGLYPH) fill);
1070 break;
1071
1072 default:
1073 unimpl("brush %d\n", brush->style);
1074 }
1075
1076 RESET_FUNCTION(opcode);
1077 }
1078
1079 void
1080 ui_screenblt(uint8 opcode,
1081 /* dest */ int x, int y, int cx, int cy,
1082 /* src */ int srcx, int srcy)
1083 {
1084 SET_FUNCTION(opcode);
1085 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1086 if (ownbackstore)
1087 XCopyArea(display, backstore, backstore, gc, srcx, srcy,
1088 cx, cy, x, y);
1089 RESET_FUNCTION(opcode);
1090 }
1091
1092 void
1093 ui_memblt(uint8 opcode,
1094 /* dest */ int x, int y, int cx, int cy,
1095 /* src */ HBITMAP src, int srcx, int srcy)
1096 {
1097 SET_FUNCTION(opcode);
1098 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1099 if (ownbackstore)
1100 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy,
1101 cx, cy, x, y);
1102 RESET_FUNCTION(opcode);
1103 }
1104
1105 void
1106 ui_triblt(uint8 opcode,
1107 /* dest */ int x, int y, int cx, int cy,
1108 /* src */ HBITMAP src, int srcx, int srcy,
1109 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1110 {
1111 /* This is potentially difficult to do in general. Until someone
1112 comes up with a more efficient way of doing it I am using cases. */
1113
1114 switch (opcode)
1115 {
1116 case 0x69: /* PDSxxn */
1117 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1118 ui_patblt(ROP2_NXOR, x, y, cx, cy,
1119 brush, bgcolour, fgcolour);
1120 break;
1121
1122 case 0xb8: /* PSDPxax */
1123 ui_patblt(ROP2_XOR, x, y, cx, cy,
1124 brush, bgcolour, fgcolour);
1125 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1126 ui_patblt(ROP2_XOR, x, y, cx, cy,
1127 brush, bgcolour, fgcolour);
1128 break;
1129
1130 case 0xc0: /* PSa */
1131 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1132 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
1133 fgcolour);
1134 break;
1135
1136 default:
1137 unimpl("triblt 0x%x\n", opcode);
1138 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1139 }
1140 }
1141
1142 void
1143 ui_line(uint8 opcode,
1144 /* dest */ int startx, int starty, int endx, int endy,
1145 /* pen */ PEN * pen)
1146 {
1147 SET_FUNCTION(opcode);
1148 SET_FOREGROUND(pen->colour);
1149 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1150 if (ownbackstore)
1151 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1152 RESET_FUNCTION(opcode);
1153 }
1154
1155 void
1156 ui_rect(
1157 /* dest */ int x, int y, int cx, int cy,
1158 /* brush */ int colour)
1159 {
1160 SET_FOREGROUND(colour);
1161 FILL_RECTANGLE(x, y, cx, cy);
1162 }
1163
1164 void
1165 ui_draw_glyph(int mixmode,
1166 /* dest */ int x, int y, int cx, int cy,
1167 /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,
1168 int fgcolour)
1169 {
1170 SET_FOREGROUND(fgcolour);
1171 SET_BACKGROUND(bgcolour);
1172
1173 XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)
1174 ? FillStippled : FillOpaqueStippled);
1175 XSetStipple(display, gc, (Pixmap) glyph);
1176 XSetTSOrigin(display, gc, x, y);
1177
1178 FILL_RECTANGLE(x, y, cx, cy);
1179
1180 XSetFillStyle(display, gc, FillSolid);
1181 }
1182
1183 #define DO_GLYPH(ttext,idx) \
1184 {\
1185 glyph = cache_get_font (font, ttext[idx]);\
1186 if (!(flags & TEXT2_IMPLICIT_X))\
1187 {\
1188 xyoffset = ttext[++idx];\
1189 if ((xyoffset & 0x80))\
1190 {\
1191 if (flags & TEXT2_VERTICAL) \
1192 y += ttext[++idx] | (ttext[++idx] << 8);\
1193 else\
1194 x += ttext[++idx] | (ttext[++idx] << 8);\
1195 }\
1196 else\
1197 {\
1198 if (flags & TEXT2_VERTICAL) \
1199 y += xyoffset;\
1200 else\
1201 x += xyoffset;\
1202 }\
1203 }\
1204 if (glyph != NULL)\
1205 {\
1206 ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1207 y + (short) glyph->baseline,\
1208 glyph->width, glyph->height,\
1209 glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1210 if (flags & TEXT2_IMPLICIT_X)\
1211 x += glyph->width;\
1212 }\
1213 }
1214
1215 void
1216 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1217 int clipx, int clipy, int clipcx, int clipcy, int boxx,
1218 int boxy, int boxcx, int boxcy, int bgcolour,
1219 int fgcolour, uint8 * text, uint8 length)
1220 {
1221 FONTGLYPH *glyph;
1222 int i, j, xyoffset;
1223 DATABLOB *entry;
1224
1225 SET_FOREGROUND(bgcolour);
1226
1227 if (boxcx > 1)
1228 {
1229 FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1230 }
1231 else if (mixmode == MIX_OPAQUE)
1232 {
1233 FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1234 }
1235
1236 /* Paint text, character by character */
1237 for (i = 0; i < length;)
1238 {
1239 switch (text[i])
1240 {
1241 case 0xff:
1242 if (i + 2 < length)
1243 cache_put_text(text[i + 1], text,
1244 text[i + 2]);
1245 else
1246 {
1247 error("this shouldn't be happening\n");
1248 break;
1249 }
1250 /* this will move pointer from start to first character after FF command */
1251 length -= i + 3;
1252 text = &(text[i + 3]);
1253 i = 0;
1254 break;
1255
1256 case 0xfe:
1257 entry = cache_get_text(text[i + 1]);
1258 if (entry != NULL)
1259 {
1260 if ((((uint8 *) (entry->data))[1] ==
1261 0)
1262 && (!(flags & TEXT2_IMPLICIT_X)))
1263 {
1264 if (flags & TEXT2_VERTICAL)
1265 y += text[i + 2];
1266 else
1267 x += text[i + 2];
1268 }
1269 if (i + 2 < length)
1270 i += 3;
1271 else
1272 i += 2;
1273 length -= i;
1274 /* this will move pointer from start to first character after FE command */
1275 text = &(text[i]);
1276 i = 0;
1277 for (j = 0; j < entry->size; j++)
1278 DO_GLYPH(((uint8 *) (entry->
1279 data)),
1280 j);
1281 }
1282 break;
1283
1284 default:
1285 DO_GLYPH(text, i);
1286 i++;
1287 break;
1288 }
1289 }
1290
1291
1292 }
1293
1294 void
1295 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1296 {
1297 Pixmap pix;
1298 XImage *image;
1299
1300 if (ownbackstore)
1301 {
1302 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
1303 ZPixmap);
1304 }
1305 else
1306 {
1307 pix = XCreatePixmap(display, wnd, cx, cy, depth);
1308 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1309 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,
1310 ZPixmap);
1311 XFreePixmap(display, pix);
1312 }
1313
1314 offset *= bpp / 8;
1315 cache_put_desktop(offset, cx, cy, image->bytes_per_line,
1316 bpp / 8, (uint8 *) image->data);
1317
1318 XDestroyImage(image);
1319 }
1320
1321 void
1322 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1323 {
1324 XImage *image;
1325 uint8 *data;
1326
1327 offset *= bpp / 8;
1328 data = cache_get_desktop(offset, cx, cy, bpp / 8);
1329 if (data == NULL)
1330 return;
1331
1332 image = XCreateImage(display, visual, depth, ZPixmap,
1333 0, data, cx, cy, BitmapPad(display),
1334 cx * bpp / 8);
1335
1336 if (ownbackstore)
1337 {
1338 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1339 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1340 }
1341 else
1342 {
1343 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1344 }
1345
1346 XFree(image);
1347 }

  ViewVC Help
Powered by ViewVC 1.1.26