/[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 31 - (show annotations)
Sat Sep 15 03:16:05 2001 UTC (22 years, 8 months ago) by matty
File MIME type: text/plain
File size: 20304 byte(s)
Software backing store support.

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

  ViewVC Help
Powered by ViewVC 1.1.26