/[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 38 - (show annotations)
Thu Apr 4 12:04:33 2002 UTC (22 years ago) by matthewc
File MIME type: text/plain
File size: 20574 byte(s)
Committing my keymap work - unlike the version in the unified patches,
this one uses external keymap files (which are my preference).

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

  ViewVC Help
Powered by ViewVC 1.1.26