/[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 59 - (show annotations)
Sun Jul 14 04:20:25 2002 UTC (21 years, 10 months ago) by jsorg71
File MIME type: text/plain
File size: 28628 byte(s)
upside down pattern in patblt

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

  ViewVC Help
Powered by ViewVC 1.1.26