/[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 36 - (show annotations)
Sat Sep 15 14:30:46 2001 UTC (22 years, 7 months ago) by matty
File MIME type: text/plain
File size: 21809 byte(s)
OSF1/Alpha build fixes.

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 User interface services - X-Windows
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
32 static Display *display;
33 static int x_socket;
34 static Window wnd;
35 static GC gc;
36 static Visual *visual;
37 static int depth;
38 static int bpp;
39
40 /* endianness */
41 static BOOL host_be;
42 static BOOL xserver_be;
43
44 /* software backing store */
45 static BOOL ownbackstore;
46 static Pixmap backstore;
47
48 #define FILL_RECTANGLE(x,y,cx,cy)\
49 { \
50 XFillRectangle(display, wnd, gc, x, y, cx, cy); \
51 if (ownbackstore) \
52 XFillRectangle(display, backstore, gc, x, y, cx, cy); \
53 }
54
55 /* colour maps */
56 static BOOL owncolmap;
57 static Colormap xcolmap;
58 static uint32 white;
59 static uint32 *colmap;
60
61 #define TRANSLATE(col) ( owncolmap ? col : translate_colour(colmap[col]) )
62 #define SET_FOREGROUND(col) XSetForeground(display, gc, TRANSLATE(col));
63 #define SET_BACKGROUND(col) XSetBackground(display, gc, TRANSLATE(col));
64
65 static int rop2_map[] = {
66 GXclear, /* 0 */
67 GXnor, /* DPon */
68 GXandInverted, /* DPna */
69 GXcopyInverted, /* Pn */
70 GXandReverse, /* PDna */
71 GXinvert, /* Dn */
72 GXxor, /* DPx */
73 GXnand, /* DPan */
74 GXand, /* DPa */
75 GXequiv, /* DPxn */
76 GXnoop, /* D */
77 GXorInverted, /* DPno */
78 GXcopy, /* P */
79 GXorReverse, /* PDno */
80 GXor, /* DPo */
81 GXset /* 1 */
82 };
83
84 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
85 #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
86
87 static void
88 translate8(uint8 *data, uint8 *out, uint8 *end)
89 {
90 while (out < end)
91 *(out++) = (uint8)colmap[*(data++)];
92 }
93
94 static void
95 translate16(uint8 *data, uint16 *out, uint16 *end)
96 {
97 while (out < end)
98 *(out++) = (uint16)colmap[*(data++)];
99 }
100
101 /* little endian - conversion happens when colourmap is built */
102 static void
103 translate24(uint8 *data, uint8 *out, uint8 *end)
104 {
105 uint32 value;
106
107 while (out < end)
108 {
109 value = colmap[*(data++)];
110 *(out++) = value;
111 *(out++) = value >> 8;
112 *(out++) = value >> 16;
113 }
114 }
115
116 static void
117 translate32(uint8 *data, uint32 *out, uint32 *end)
118 {
119 while (out < end)
120 *(out++) = colmap[*(data++)];
121 }
122
123 static uint8 *
124 translate_image(int width, int height, uint8 *data)
125 {
126 int size = width * height * bpp/8;
127 uint8 *out = xmalloc(size);
128 uint8 *end = out + size;
129
130 switch (bpp)
131 {
132 case 8:
133 translate8(data, out, end);
134 break;
135
136 case 16:
137 translate16(data, (uint16 *)out, (uint16 *)end);
138 break;
139
140 case 24:
141 translate24(data, out, end);
142 break;
143
144 case 32:
145 translate32(data, (uint32 *)out, (uint32 *)end);
146 break;
147 }
148
149 return out;
150 }
151
152 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
153 #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
154 #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
155 x = (x << 16) | (x >> 16); }
156
157 static uint32
158 translate_colour(uint32 colour)
159 {
160 switch (bpp)
161 {
162 case 16:
163 if (host_be != xserver_be)
164 BSWAP16(colour);
165 break;
166
167 case 24:
168 if (xserver_be)
169 BSWAP24(colour);
170 break;
171
172 case 32:
173 if (host_be != xserver_be)
174 BSWAP32(colour);
175 break;
176 }
177
178 return colour;
179 }
180
181 BOOL
182 ui_create_window(char *title)
183 {
184 XSetWindowAttributes attribs;
185 XClassHint *classhints;
186 XSizeHints *sizehints;
187 unsigned long input_mask;
188 XPixmapFormatValues *pfm;
189 Screen *screen;
190 uint16 test;
191 int i;
192
193 display = XOpenDisplay(NULL);
194 if (display == NULL)
195 {
196 error("Failed to open display\n");
197 return False;
198 }
199
200 x_socket = ConnectionNumber(display);
201 screen = DefaultScreenOfDisplay(display);
202 visual = DefaultVisualOfScreen(screen);
203 depth = DefaultDepthOfScreen(screen);
204
205 pfm = XListPixmapFormats(display, &i);
206 if (pfm != NULL)
207 {
208 /* Use maximum bpp for this depth - this is generally
209 desirable, e.g. 24 bits->32 bits. */
210 while (i--)
211 {
212 if ((pfm[i].depth == depth)
213 && (pfm[i].bits_per_pixel > bpp))
214 {
215 bpp = pfm[i].bits_per_pixel;
216 }
217 }
218 XFree(pfm);
219 }
220
221 if (bpp < 8)
222 {
223 error("Less than 8 bpp not currently supported.\n");
224 XCloseDisplay(display);
225 return False;
226 }
227
228 if (depth <= 8)
229 owncolmap = True;
230 else
231 xcolmap = DefaultColormapOfScreen(screen);
232
233 test = 1;
234 host_be = !(BOOL)(*(uint8 *)(&test));
235 xserver_be = (ImageByteOrder(display) == MSBFirst);
236
237 white = WhitePixelOfScreen(screen);
238 attribs.background_pixel = BlackPixelOfScreen(screen);
239 attribs.backing_store = DoesBackingStore(screen);
240
241 if (attribs.backing_store == NotUseful)
242 ownbackstore = True;
243
244 if (fullscreen)
245 {
246 attribs.override_redirect = True;
247 width = WidthOfScreen(screen);
248 height = HeightOfScreen(screen);
249 }
250 else
251 {
252 attribs.override_redirect = False;
253 }
254
255 width = (width + 3) & ~3; /* make width a multiple of 32 bits */
256
257 wnd = XCreateWindow(display, RootWindowOfScreen(screen),
258 0, 0, width, height, 0, CopyFromParent,
259 InputOutput, CopyFromParent,
260 CWBackingStore | CWBackPixel | CWOverrideRedirect,
261 &attribs);
262
263 XStoreName(display, wnd, title);
264
265 classhints = XAllocClassHint();
266 if (classhints != NULL)
267 {
268 classhints->res_name = classhints->res_class = "rdesktop";
269 XSetClassHint(display, wnd, classhints);
270 XFree(classhints);
271 }
272
273 sizehints = XAllocSizeHints();
274 if (sizehints)
275 {
276 sizehints->flags = PMinSize | PMaxSize;
277 sizehints->min_width = sizehints->max_width = width;
278 sizehints->min_height = sizehints->max_height = height;
279 XSetWMNormalHints(display, wnd, sizehints);
280 XFree(sizehints);
281 }
282
283 input_mask = KeyPressMask | KeyReleaseMask
284 | ButtonPressMask | ButtonReleaseMask
285 | EnterWindowMask | LeaveWindowMask;
286
287 if (sendmotion)
288 input_mask |= PointerMotionMask;
289
290 if (ownbackstore)
291 input_mask |= ExposureMask;
292
293 XSelectInput(display, wnd, input_mask);
294 gc = XCreateGC(display, wnd, 0, NULL);
295
296 if (ownbackstore)
297 backstore = XCreatePixmap(display, wnd, width, height, depth);
298
299 XMapWindow(display, wnd);
300 return True;
301 }
302
303 void
304 ui_destroy_window()
305 {
306 if (ownbackstore)
307 XFreePixmap(display, backstore);
308
309 XFreeGC(display, gc);
310 XDestroyWindow(display, wnd);
311 XCloseDisplay(display);
312 display = NULL;
313 }
314
315 static uint8
316 xwin_translate_key(unsigned long key)
317 {
318 DEBUG(("KEY(code=0x%lx)\n", key));
319
320 if ((key > 8) && (key <= 0x60))
321 return (key - 8);
322
323 switch (key)
324 {
325 case 0x61: /* home */
326 return 0x47 | 0x80;
327 case 0x62: /* up arrow */
328 return 0x48 | 0x80;
329 case 0x63: /* page up */
330 return 0x49 | 0x80;
331 case 0x64: /* left arrow */
332 return 0x4b | 0x80;
333 case 0x66: /* right arrow */
334 return 0x4d | 0x80;
335 case 0x67: /* end */
336 return 0x4f | 0x80;
337 case 0x68: /* down arrow */
338 return 0x50 | 0x80;
339 case 0x69: /* page down */
340 return 0x51 | 0x80;
341 case 0x6a: /* insert */
342 return 0x52 | 0x80;
343 case 0x6b: /* delete */
344 return 0x53 | 0x80;
345 case 0x6c: /* keypad enter */
346 return 0x1c | 0x80;
347 case 0x6d: /* right ctrl */
348 return 0x1d | 0x80;
349 case 0x6f: /* ctrl - print screen */
350 return 0x37 | 0x80;
351 case 0x70: /* keypad '/' */
352 return 0x35 | 0x80;
353 case 0x71: /* right alt */
354 return 0x38 | 0x80;
355 case 0x72: /* ctrl break */
356 return 0x46 | 0x80;
357 case 0x73: /* left window key */
358 return 0xff; /* real scancode is 5b */
359 case 0x74: /* right window key */
360 return 0xff; /* real scancode is 5c */
361 case 0x75: /* menu key */
362 return 0x5d | 0x80;
363 }
364
365 return 0;
366 }
367
368 static uint16
369 xwin_translate_mouse(unsigned long button)
370 {
371 switch (button)
372 {
373 case Button1: /* left */
374 return MOUSE_FLAG_BUTTON1;
375 case Button2: /* middle */
376 return MOUSE_FLAG_BUTTON3;
377 case Button3: /* right */
378 return MOUSE_FLAG_BUTTON2;
379 }
380
381 return 0;
382 }
383
384 static void
385 xwin_process_events()
386 {
387 XEvent event;
388 uint8 scancode;
389 uint16 button;
390 uint32 ev_time;
391
392 if (display == NULL)
393 return;
394
395 while (XCheckWindowEvent(display, wnd, ~0, &event))
396 {
397 ev_time = time(NULL);
398
399 switch (event.type)
400 {
401 case KeyPress:
402 scancode = xwin_translate_key(event.xkey.keycode);
403 if (scancode == 0)
404 break;
405
406 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,
407 scancode, 0);
408 break;
409
410 case KeyRelease:
411 scancode = xwin_translate_key(event.xkey.keycode);
412 if (scancode == 0)
413 break;
414
415 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
416 KBD_FLAG_DOWN | KBD_FLAG_UP,
417 scancode, 0);
418 break;
419
420 case ButtonPress:
421 button = xwin_translate_mouse(event.xbutton.button);
422 if (button == 0)
423 break;
424
425 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
426 button | MOUSE_FLAG_DOWN,
427 event.xbutton.x,
428 event.xbutton.y);
429 break;
430
431 case ButtonRelease:
432 button = xwin_translate_mouse(event.xbutton.button);
433 if (button == 0)
434 break;
435
436 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
437 button,
438 event.xbutton.x,
439 event.xbutton.y);
440 break;
441
442 case MotionNotify:
443 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
444 MOUSE_FLAG_MOVE,
445 event.xmotion.x,
446 event.xmotion.y);
447 break;
448
449 case EnterNotify:
450 XGrabKeyboard(display, wnd, True, GrabModeAsync,
451 GrabModeAsync, CurrentTime);
452 break;
453
454 case LeaveNotify:
455 XUngrabKeyboard(display, CurrentTime);
456 break;
457
458 case Expose:
459 XCopyArea(display, backstore, wnd, gc,
460 event.xexpose.x, event.xexpose.y,
461 event.xexpose.width, event.xexpose.height,
462 event.xexpose.x, event.xexpose.y);
463 break;
464 }
465 }
466 }
467
468 void
469 ui_select(int rdp_socket)
470 {
471 int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;
472 fd_set rfds;
473
474 XFlush(display);
475
476 FD_ZERO(&rfds);
477
478 while (True)
479 {
480 FD_ZERO(&rfds);
481 FD_SET(rdp_socket, &rfds);
482 FD_SET(x_socket, &rfds);
483
484 switch (select(n, &rfds, NULL, NULL, NULL))
485 {
486 case -1:
487 error("select: %s\n", strerror(errno));
488
489 case 0:
490 continue;
491 }
492
493 if (FD_ISSET(x_socket, &rfds))
494 xwin_process_events();
495
496 if (FD_ISSET(rdp_socket, &rfds))
497 return;
498 }
499 }
500
501 void
502 ui_move_pointer(int x, int y)
503 {
504 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
505 }
506
507 HBITMAP
508 ui_create_bitmap(int width, int height, uint8 *data)
509 {
510 XImage *image;
511 Pixmap bitmap;
512 uint8 *tdata;
513
514 tdata = (owncolmap ? data : translate_image(width, height, data));
515 bitmap = XCreatePixmap(display, wnd, width, height, depth);
516 image = XCreateImage(display, visual, depth, ZPixmap,
517 0, tdata, width, height, 8, 0);
518
519 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
520
521 XFree(image);
522 if (!owncolmap)
523 xfree(tdata);
524 return (HBITMAP) bitmap;
525 }
526
527 void
528 ui_paint_bitmap(int x, int y, int cx, int cy,
529 int width, int height, uint8 *data)
530 {
531 XImage *image;
532 uint8 *tdata;
533
534 tdata = (owncolmap ? data : translate_image(width, height, data));
535 image = XCreateImage(display, visual, depth, ZPixmap,
536 0, tdata, width, height, 8, 0);
537
538 if (ownbackstore)
539 {
540 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
541 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
542 }
543 else
544 {
545 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
546 }
547
548 XFree(image);
549 if (!owncolmap)
550 xfree(tdata);
551 }
552
553 void
554 ui_destroy_bitmap(HBITMAP bmp)
555 {
556 XFreePixmap(display, (Pixmap)bmp);
557 }
558
559 HGLYPH
560 ui_create_glyph(int width, int height, uint8 *data)
561 {
562 XImage *image;
563 Pixmap bitmap;
564 int scanline;
565 GC gc;
566
567 scanline = (width + 7) / 8;
568
569 bitmap = XCreatePixmap(display, wnd, width, height, 1);
570 gc = XCreateGC(display, bitmap, 0, NULL);
571
572 image = XCreateImage(display, visual, 1, ZPixmap, 0,
573 data, width, height, 8, scanline);
574 image->byte_order = MSBFirst;
575 image->bitmap_bit_order = MSBFirst;
576 XInitImage(image);
577
578 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
579
580 XFree(image);
581 XFreeGC(display, gc);
582 return (HGLYPH)bitmap;
583 }
584
585 void
586 ui_destroy_glyph(HGLYPH glyph)
587 {
588 XFreePixmap(display, (Pixmap)glyph);
589 }
590
591 HCURSOR
592 ui_create_cursor(unsigned int x, unsigned int y, int width,
593 int height, uint8 *andmask, uint8 *xormask)
594 {
595 HGLYPH maskglyph, cursorglyph;
596 XColor bg, fg;
597 Cursor xcursor;
598 uint8 *cursor, *pcursor;
599 uint8 *mask, *pmask;
600 uint8 nextbit;
601 int scanline, offset;
602 int i, j;
603
604 scanline = (width + 7) / 8;
605 offset = scanline * height;
606
607 cursor = xmalloc(offset);
608 memset(cursor, 0, offset);
609
610 mask = xmalloc(offset);
611 memset(mask, 0, offset);
612
613 /* approximate AND and XOR masks with a monochrome X pointer */
614 for (i = 0; i < height; i++)
615 {
616 offset -= scanline;
617 pcursor = &cursor[offset];
618 pmask = &mask[offset];
619
620 for (j = 0; j < scanline; j++)
621 {
622 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
623 {
624 if (xormask[0] || xormask[1] || xormask[2])
625 {
626 *pcursor |= (~(*andmask) & nextbit);
627 *pmask |= nextbit;
628 }
629 else
630 {
631 *pcursor |= ((*andmask) & nextbit);
632 *pmask |= (~(*andmask) & nextbit);
633 }
634
635 xormask += 3;
636 }
637
638 andmask++;
639 pcursor++;
640 pmask++;
641 }
642 }
643
644 fg.red = fg.blue = fg.green = 0xffff;
645 bg.red = bg.blue = bg.green = 0x0000;
646 fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
647
648 cursorglyph = ui_create_glyph(width, height, cursor);
649 maskglyph = ui_create_glyph(width, height, mask);
650
651 xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,
652 (Pixmap)maskglyph, &fg, &bg, x, y);
653
654 ui_destroy_glyph(maskglyph);
655 ui_destroy_glyph(cursorglyph);
656 xfree(mask);
657 xfree(cursor);
658 return (HCURSOR)xcursor;
659 }
660
661 void
662 ui_set_cursor(HCURSOR cursor)
663 {
664 XDefineCursor(display, wnd, (Cursor)cursor);
665 }
666
667 void
668 ui_destroy_cursor(HCURSOR cursor)
669 {
670 XFreeCursor(display, (Cursor)cursor);
671 }
672
673 #define MAKE_XCOLOR(xc,c) \
674 (xc)->red = ((c)->red << 8) | (c)->red; \
675 (xc)->green = ((c)->green << 8) | (c)->green; \
676 (xc)->blue = ((c)->blue << 8) | (c)->blue; \
677 (xc)->flags = DoRed | DoGreen | DoBlue;
678
679 HCOLOURMAP
680 ui_create_colourmap(COLOURMAP *colours)
681 {
682 COLOURENTRY *entry;
683 int i, ncolours = colours->ncolours;
684
685 if (owncolmap)
686 {
687 XColor *xcolours, *xentry;
688 Colormap map;
689
690 xcolours = xmalloc(sizeof(XColor) * ncolours);
691 for (i = 0; i < ncolours; i++)
692 {
693 entry = &colours->colours[i];
694 xentry = &xcolours[i];
695 xentry->pixel = i;
696 MAKE_XCOLOR(xentry, entry);
697 }
698
699 map = XCreateColormap(display, wnd, visual, AllocAll);
700 XStoreColors(display, map, xcolours, ncolours);
701
702 xfree(xcolours);
703 return (HCOLOURMAP)map;
704 }
705 else
706 {
707 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
708 XColor xentry;
709 uint32 colour;
710
711 for (i = 0; i < ncolours; i++)
712 {
713 entry = &colours->colours[i];
714 MAKE_XCOLOR(&xentry, entry);
715
716 if (XAllocColor(display, xcolmap, &xentry) != 0)
717 colour = xentry.pixel;
718 else
719 colour = white;
720
721 /* byte swap here to make translate_image faster */
722 map[i] = translate_colour(colour);
723 }
724
725 return map;
726 }
727 }
728
729 void
730 ui_destroy_colourmap(HCOLOURMAP map)
731 {
732 if (owncolmap)
733 XFreeColormap(display, (Colormap)map);
734 else
735 xfree(map);
736 }
737
738 void
739 ui_set_colourmap(HCOLOURMAP map)
740 {
741 if (owncolmap)
742 XSetWindowColormap(display, wnd, (Colormap)map);
743 else
744 colmap = map;
745 }
746
747 void
748 ui_set_clip(int x, int y, int cx, int cy)
749 {
750 XRectangle rect;
751
752 rect.x = x;
753 rect.y = y;
754 rect.width = cx;
755 rect.height = cy;
756 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
757 }
758
759 void
760 ui_reset_clip()
761 {
762 XRectangle rect;
763
764 rect.x = 0;
765 rect.y = 0;
766 rect.width = width;
767 rect.height = height;
768 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
769 }
770
771 void
772 ui_bell()
773 {
774 XBell(display, 0);
775 }
776
777 void
778 ui_destblt(uint8 opcode,
779 /* dest */ int x, int y, int cx, int cy)
780 {
781 SET_FUNCTION(opcode);
782 FILL_RECTANGLE(x, y, cx, cy);
783 RESET_FUNCTION(opcode);
784 }
785
786 void
787 ui_patblt(uint8 opcode,
788 /* dest */ int x, int y, int cx, int cy,
789 /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
790 {
791 Pixmap fill;
792
793 SET_FUNCTION(opcode);
794
795 switch (brush->style)
796 {
797 case 0: /* Solid */
798 SET_FOREGROUND(fgcolour);
799 FILL_RECTANGLE(x, y, cx, cy);
800 break;
801
802 case 3: /* Pattern */
803 fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);
804
805 SET_FOREGROUND(bgcolour);
806 SET_BACKGROUND(fgcolour);
807 XSetFillStyle(display, gc, FillOpaqueStippled);
808 XSetStipple(display, gc, fill);
809 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
810
811 FILL_RECTANGLE(x, y, cx, cy);
812
813 XSetFillStyle(display, gc, FillSolid);
814 ui_destroy_glyph((HGLYPH)fill);
815 break;
816
817 default:
818 unimpl("brush %d\n", brush->style);
819 }
820
821 RESET_FUNCTION(opcode);
822 }
823
824 void
825 ui_screenblt(uint8 opcode,
826 /* dest */ int x, int y, int cx, int cy,
827 /* src */ int srcx, int srcy)
828 {
829 SET_FUNCTION(opcode);
830 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
831 if (ownbackstore)
832 XCopyArea(display, backstore, backstore, gc, srcx, srcy,
833 cx, cy, x, y);
834 RESET_FUNCTION(opcode);
835 }
836
837 void
838 ui_memblt(uint8 opcode,
839 /* dest */ int x, int y, int cx, int cy,
840 /* src */ HBITMAP src, int srcx, int srcy)
841 {
842 SET_FUNCTION(opcode);
843 XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);
844 if (ownbackstore)
845 XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,
846 cx, cy, x, y);
847 RESET_FUNCTION(opcode);
848 }
849
850 void
851 ui_triblt(uint8 opcode,
852 /* dest */ int x, int y, int cx, int cy,
853 /* src */ HBITMAP src, int srcx, int srcy,
854 /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
855 {
856 /* This is potentially difficult to do in general. Until someone
857 comes up with a more efficient way of doing it I am using cases. */
858
859 switch (opcode)
860 {
861 case 0x69: /* PDSxxn */
862 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
863 ui_patblt(ROP2_NXOR, x, y, cx, cy,
864 brush, bgcolour, fgcolour);
865 break;
866
867 case 0xb8: /* PSDPxax */
868 ui_patblt(ROP2_XOR, x, y, cx, cy,
869 brush, bgcolour, fgcolour);
870 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
871 ui_patblt(ROP2_XOR, x, y, cx, cy,
872 brush, bgcolour, fgcolour);
873 break;
874
875 case 0xc0: /* PSa */
876 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
877 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
878 fgcolour);
879 break;
880
881 default:
882 unimpl("triblt 0x%x\n", opcode);
883 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
884 }
885 }
886
887 void
888 ui_line(uint8 opcode,
889 /* dest */ int startx, int starty, int endx, int endy,
890 /* pen */ PEN *pen)
891 {
892 SET_FUNCTION(opcode);
893 SET_FOREGROUND(pen->colour);
894 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
895 if (ownbackstore)
896 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
897 RESET_FUNCTION(opcode);
898 }
899
900 void
901 ui_rect(
902 /* dest */ int x, int y, int cx, int cy,
903 /* brush */ int colour)
904 {
905 SET_FOREGROUND(colour);
906 FILL_RECTANGLE(x, y, cx, cy);
907 }
908
909 void
910 ui_draw_glyph(int mixmode,
911 /* dest */ int x, int y, int cx, int cy,
912 /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,
913 int fgcolour)
914 {
915 SET_FOREGROUND(fgcolour);
916 SET_BACKGROUND(bgcolour);
917
918 XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)
919 ? FillStippled : FillOpaqueStippled);
920 XSetStipple(display, gc, (Pixmap)glyph);
921 XSetTSOrigin(display, gc, x, y);
922
923 FILL_RECTANGLE(x, y, cx, cy);
924
925 XSetFillStyle(display, gc, FillSolid);
926 }
927
928 void
929 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
930 int clipx, int clipy, int clipcx, int clipcy,
931 int boxx, int boxy, int boxcx, int boxcy,
932 int bgcolour, int fgcolour, uint8 *text, uint8 length)
933 {
934 FONTGLYPH *glyph;
935 int i, offset;
936
937 SET_FOREGROUND(bgcolour);
938
939 if (boxcx > 1)
940 {
941 FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
942 }
943 else if (mixmode == MIX_OPAQUE)
944 {
945 FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
946 }
947
948 /* Paint text, character by character */
949 for (i = 0; i < length; i++)
950 {
951 glyph = cache_get_font(font, text[i]);
952
953 if (!(flags & TEXT2_IMPLICIT_X))
954 {
955 offset = text[++i];
956 if (offset & 0x80)
957 offset = ((offset & 0x7f) << 8) | text[++i];
958
959 if (flags & TEXT2_VERTICAL)
960 y += offset;
961 else
962 x += offset;
963 }
964
965 if (glyph != NULL)
966 {
967 ui_draw_glyph(mixmode, x + (short) glyph->offset,
968 y + (short) glyph->baseline,
969 glyph->width, glyph->height,
970 glyph->pixmap, 0, 0,
971 bgcolour, fgcolour);
972
973 if (flags & TEXT2_IMPLICIT_X)
974 x += glyph->width;
975 }
976 }
977 }
978
979 void
980 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
981 {
982 Pixmap pix;
983 XImage *image;
984
985 if (ownbackstore)
986 {
987 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
988 ZPixmap);
989 }
990 else
991 {
992 pix = XCreatePixmap(display, wnd, cx, cy, depth);
993 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
994 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,
995 ZPixmap);
996 XFreePixmap(display, pix);
997 }
998
999 offset *= bpp/8;
1000 cache_put_desktop(offset, cx, cy, image->bytes_per_line,
1001 bpp/8, (uint8 *)image->data);
1002
1003 XDestroyImage(image);
1004 }
1005
1006 void
1007 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1008 {
1009 XImage *image;
1010 uint8 *data;
1011
1012 offset *= bpp/8;
1013 data = cache_get_desktop(offset, cx, cy, bpp/8);
1014 if (data == NULL)
1015 return;
1016
1017 image = XCreateImage(display, visual, depth, ZPixmap,
1018 0, data, cx, cy, BitmapPad(display),
1019 cx * bpp/8);
1020
1021 if (ownbackstore)
1022 {
1023 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1024 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1025 }
1026 else
1027 {
1028 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1029 }
1030
1031 XFree(image);
1032 }

  ViewVC Help
Powered by ViewVC 1.1.26