/[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 50 - (show annotations)
Sat Apr 20 09:41:03 2002 UTC (22 years, 1 month ago) by matthewc
File MIME type: text/plain
File size: 21312 byte(s)
There is an extended key flag that we should be setting for extended keys.
(Originally fixed by Ben McKeegan <Ben.McKeegan@fitz.cam.ac.uk>)

Ran make proto.

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 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();
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, flags;
326 uint32 ev_time;
327
328 if (display == NULL)
329 return;
330
331 while (XCheckMaskEvent(display, ~0, &event))
332 {
333 ev_time = time(NULL);
334 flags = 0;
335
336 switch (event.type)
337 {
338 case KeyRelease:
339 flags = KBD_FLAG_DOWN | KBD_FLAG_UP;
340 /* fall through */
341
342 case KeyPress:
343 keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);
344 scancode = xkeymap_translate_key(keysym, event.xkey.keycode, &flags);
345 if (scancode == 0)
346 break;
347
348 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, flags, scancode, 0);
349 break;
350
351 case ButtonPress:
352 flags = MOUSE_FLAG_DOWN;
353 /* fall through */
354
355 case ButtonRelease:
356 button = xkeymap_translate_button(event.xbutton.button);
357 if (button == 0)
358 break;
359
360 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
361 flags | button,
362 event.xbutton.x,
363 event.xbutton.y);
364 break;
365
366 case MotionNotify:
367 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
368 MOUSE_FLAG_MOVE,
369 event.xmotion.x,
370 event.xmotion.y);
371 break;
372
373 case EnterNotify:
374 XGrabKeyboard(display, wnd, True, GrabModeAsync,
375 GrabModeAsync, CurrentTime);
376 break;
377
378 case LeaveNotify:
379 XUngrabKeyboard(display, CurrentTime);
380 break;
381
382 case Expose:
383 XCopyArea(display, backstore, wnd, gc,
384 event.xexpose.x, event.xexpose.y,
385 event.xexpose.width, event.xexpose.height,
386 event.xexpose.x, event.xexpose.y);
387 break;
388 }
389 }
390 }
391
392 void
393 ui_select(int rdp_socket)
394 {
395 int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;
396 fd_set rfds;
397
398 XFlush(display);
399
400 FD_ZERO(&rfds);
401
402 while (True)
403 {
404 FD_ZERO(&rfds);
405 FD_SET(rdp_socket, &rfds);
406 FD_SET(x_socket, &rfds);
407
408 switch (select(n, &rfds, NULL, NULL, NULL))
409 {
410 case -1:
411 error("select: %s\n", strerror(errno));
412
413 case 0:
414 continue;
415 }
416
417 if (FD_ISSET(x_socket, &rfds))
418 xwin_process_events();
419
420 if (FD_ISSET(rdp_socket, &rfds))
421 return;
422 }
423 }
424
425 void
426 ui_move_pointer(int x, int y)
427 {
428 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
429 }
430
431 HBITMAP
432 ui_create_bitmap(int width, int height, uint8 *data)
433 {
434 XImage *image;
435 Pixmap bitmap;
436 uint8 *tdata;
437
438 tdata = (owncolmap ? data : translate_image(width, height, data));
439 bitmap = XCreatePixmap(display, wnd, width, height, depth);
440 image = XCreateImage(display, visual, depth, ZPixmap,
441 0, tdata, width, height, 8, 0);
442
443 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
444
445 XFree(image);
446 if (!owncolmap)
447 xfree(tdata);
448 return (HBITMAP) bitmap;
449 }
450
451 void
452 ui_paint_bitmap(int x, int y, int cx, int cy,
453 int width, int height, uint8 *data)
454 {
455 XImage *image;
456 uint8 *tdata;
457
458 tdata = (owncolmap ? data : translate_image(width, height, data));
459 image = XCreateImage(display, visual, depth, ZPixmap,
460 0, tdata, width, height, 8, 0);
461
462 if (ownbackstore)
463 {
464 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
465 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
466 }
467 else
468 {
469 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
470 }
471
472 XFree(image);
473 if (!owncolmap)
474 xfree(tdata);
475 }
476
477 void
478 ui_destroy_bitmap(HBITMAP bmp)
479 {
480 XFreePixmap(display, (Pixmap)bmp);
481 }
482
483 HGLYPH
484 ui_create_glyph(int width, int height, uint8 *data)
485 {
486 XImage *image;
487 Pixmap bitmap;
488 int scanline;
489 GC gc;
490
491 scanline = (width + 7) / 8;
492
493 bitmap = XCreatePixmap(display, wnd, width, height, 1);
494 gc = XCreateGC(display, bitmap, 0, NULL);
495
496 image = XCreateImage(display, visual, 1, ZPixmap, 0,
497 data, width, height, 8, scanline);
498 image->byte_order = MSBFirst;
499 image->bitmap_bit_order = MSBFirst;
500 XInitImage(image);
501
502 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
503
504 XFree(image);
505 XFreeGC(display, gc);
506 return (HGLYPH)bitmap;
507 }
508
509 void
510 ui_destroy_glyph(HGLYPH glyph)
511 {
512 XFreePixmap(display, (Pixmap)glyph);
513 }
514
515 HCURSOR
516 ui_create_cursor(unsigned int x, unsigned int y, int width,
517 int height, uint8 *andmask, uint8 *xormask)
518 {
519 HGLYPH maskglyph, cursorglyph;
520 XColor bg, fg;
521 Cursor xcursor;
522 uint8 *cursor, *pcursor;
523 uint8 *mask, *pmask;
524 uint8 nextbit;
525 int scanline, offset;
526 int i, j;
527
528 scanline = (width + 7) / 8;
529 offset = scanline * height;
530
531 cursor = xmalloc(offset);
532 memset(cursor, 0, offset);
533
534 mask = xmalloc(offset);
535 memset(mask, 0, offset);
536
537 /* approximate AND and XOR masks with a monochrome X pointer */
538 for (i = 0; i < height; i++)
539 {
540 offset -= scanline;
541 pcursor = &cursor[offset];
542 pmask = &mask[offset];
543
544 for (j = 0; j < scanline; j++)
545 {
546 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
547 {
548 if (xormask[0] || xormask[1] || xormask[2])
549 {
550 *pcursor |= (~(*andmask) & nextbit);
551 *pmask |= nextbit;
552 }
553 else
554 {
555 *pcursor |= ((*andmask) & nextbit);
556 *pmask |= (~(*andmask) & nextbit);
557 }
558
559 xormask += 3;
560 }
561
562 andmask++;
563 pcursor++;
564 pmask++;
565 }
566 }
567
568 fg.red = fg.blue = fg.green = 0xffff;
569 bg.red = bg.blue = bg.green = 0x0000;
570 fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
571
572 cursorglyph = ui_create_glyph(width, height, cursor);
573 maskglyph = ui_create_glyph(width, height, mask);
574
575 xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,
576 (Pixmap)maskglyph, &fg, &bg, x, y);
577
578 ui_destroy_glyph(maskglyph);
579 ui_destroy_glyph(cursorglyph);
580 xfree(mask);
581 xfree(cursor);
582 return (HCURSOR)xcursor;
583 }
584
585 void
586 ui_set_cursor(HCURSOR cursor)
587 {
588 XDefineCursor(display, wnd, (Cursor)cursor);
589 }
590
591 void
592 ui_destroy_cursor(HCURSOR cursor)
593 {
594 XFreeCursor(display, (Cursor)cursor);
595 }
596
597 #define MAKE_XCOLOR(xc,c) \
598 (xc)->red = ((c)->red << 8) | (c)->red; \
599 (xc)->green = ((c)->green << 8) | (c)->green; \
600 (xc)->blue = ((c)->blue << 8) | (c)->blue; \
601 (xc)->flags = DoRed | DoGreen | DoBlue;
602
603 HCOLOURMAP
604 ui_create_colourmap(COLOURMAP *colours)
605 {
606 COLOURENTRY *entry;
607 int i, ncolours = colours->ncolours;
608
609 if (owncolmap)
610 {
611 XColor *xcolours, *xentry;
612 Colormap map;
613
614 xcolours = xmalloc(sizeof(XColor) * ncolours);
615 for (i = 0; i < ncolours; i++)
616 {
617 entry = &colours->colours[i];
618 xentry = &xcolours[i];
619 xentry->pixel = i;
620 MAKE_XCOLOR(xentry, entry);
621 }
622
623 map = XCreateColormap(display, wnd, visual, AllocAll);
624 XStoreColors(display, map, xcolours, ncolours);
625
626 xfree(xcolours);
627 return (HCOLOURMAP)map;
628 }
629 else
630 {
631 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
632 XColor xentry;
633 uint32 colour;
634
635 for (i = 0; i < ncolours; i++)
636 {
637 entry = &colours->colours[i];
638 MAKE_XCOLOR(&xentry, entry);
639
640 if (XAllocColor(display, xcolmap, &xentry) != 0)
641 colour = xentry.pixel;
642 else
643 colour = white;
644
645 /* byte swap here to make translate_image faster */
646 map[i] = translate_colour(colour);
647 }
648
649 return map;
650 }
651 }
652
653 void
654 ui_destroy_colourmap(HCOLOURMAP map)
655 {
656 if (owncolmap)
657 XFreeColormap(display, (Colormap)map);
658 else
659 xfree(map);
660 }
661
662 void
663 ui_set_colourmap(HCOLOURMAP map)
664 {
665 if (owncolmap)
666 XSetWindowColormap(display, wnd, (Colormap)map);
667 else
668 colmap = map;
669 }
670
671 void
672 ui_set_clip(int x, int y, int cx, int cy)
673 {
674 XRectangle rect;
675
676 rect.x = x;
677 rect.y = y;
678 rect.width = cx;
679 rect.height = cy;
680 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
681 }
682
683 void
684 ui_reset_clip()
685 {
686 XRectangle rect;
687
688 rect.x = 0;
689 rect.y = 0;
690 rect.width = width;
691 rect.height = height;
692 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
693 }
694
695 void
696 ui_bell()
697 {
698 XBell(display, 0);
699 }
700
701 void
702 ui_destblt(uint8 opcode,
703 /* dest */ int x, int y, int cx, int cy)
704 {
705 SET_FUNCTION(opcode);
706 FILL_RECTANGLE(x, y, cx, cy);
707 RESET_FUNCTION(opcode);
708 }
709
710 void
711 ui_patblt(uint8 opcode,
712 /* dest */ int x, int y, int cx, int cy,
713 /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
714 {
715 Pixmap fill;
716
717 SET_FUNCTION(opcode);
718
719 switch (brush->style)
720 {
721 case 0: /* Solid */
722 SET_FOREGROUND(fgcolour);
723 FILL_RECTANGLE(x, y, cx, cy);
724 break;
725
726 case 3: /* Pattern */
727 fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);
728
729 SET_FOREGROUND(bgcolour);
730 SET_BACKGROUND(fgcolour);
731 XSetFillStyle(display, gc, FillOpaqueStippled);
732 XSetStipple(display, gc, fill);
733 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
734
735 FILL_RECTANGLE(x, y, cx, cy);
736
737 XSetFillStyle(display, gc, FillSolid);
738 ui_destroy_glyph((HGLYPH)fill);
739 break;
740
741 default:
742 unimpl("brush %d\n", brush->style);
743 }
744
745 RESET_FUNCTION(opcode);
746 }
747
748 void
749 ui_screenblt(uint8 opcode,
750 /* dest */ int x, int y, int cx, int cy,
751 /* src */ int srcx, int srcy)
752 {
753 SET_FUNCTION(opcode);
754 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
755 if (ownbackstore)
756 XCopyArea(display, backstore, backstore, gc, srcx, srcy,
757 cx, cy, x, y);
758 RESET_FUNCTION(opcode);
759 }
760
761 void
762 ui_memblt(uint8 opcode,
763 /* dest */ int x, int y, int cx, int cy,
764 /* src */ HBITMAP src, int srcx, int srcy)
765 {
766 SET_FUNCTION(opcode);
767 XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);
768 if (ownbackstore)
769 XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,
770 cx, cy, x, y);
771 RESET_FUNCTION(opcode);
772 }
773
774 void
775 ui_triblt(uint8 opcode,
776 /* dest */ int x, int y, int cx, int cy,
777 /* src */ HBITMAP src, int srcx, int srcy,
778 /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
779 {
780 /* This is potentially difficult to do in general. Until someone
781 comes up with a more efficient way of doing it I am using cases. */
782
783 switch (opcode)
784 {
785 case 0x69: /* PDSxxn */
786 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
787 ui_patblt(ROP2_NXOR, x, y, cx, cy,
788 brush, bgcolour, fgcolour);
789 break;
790
791 case 0xb8: /* PSDPxax */
792 ui_patblt(ROP2_XOR, x, y, cx, cy,
793 brush, bgcolour, fgcolour);
794 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
795 ui_patblt(ROP2_XOR, x, y, cx, cy,
796 brush, bgcolour, fgcolour);
797 break;
798
799 case 0xc0: /* PSa */
800 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
801 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
802 fgcolour);
803 break;
804
805 default:
806 unimpl("triblt 0x%x\n", opcode);
807 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
808 }
809 }
810
811 void
812 ui_line(uint8 opcode,
813 /* dest */ int startx, int starty, int endx, int endy,
814 /* pen */ PEN *pen)
815 {
816 SET_FUNCTION(opcode);
817 SET_FOREGROUND(pen->colour);
818 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
819 if (ownbackstore)
820 XDrawLine(display, backstore, gc, startx, starty, endx, endy);
821 RESET_FUNCTION(opcode);
822 }
823
824 void
825 ui_rect(
826 /* dest */ int x, int y, int cx, int cy,
827 /* brush */ int colour)
828 {
829 SET_FOREGROUND(colour);
830 FILL_RECTANGLE(x, y, cx, cy);
831 }
832
833 void
834 ui_draw_glyph(int mixmode,
835 /* dest */ int x, int y, int cx, int cy,
836 /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,
837 int fgcolour)
838 {
839 SET_FOREGROUND(fgcolour);
840 SET_BACKGROUND(bgcolour);
841
842 XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)
843 ? FillStippled : FillOpaqueStippled);
844 XSetStipple(display, gc, (Pixmap)glyph);
845 XSetTSOrigin(display, gc, x, y);
846
847 FILL_RECTANGLE(x, y, cx, cy);
848
849 XSetFillStyle(display, gc, FillSolid);
850 }
851
852 #define DO_GLYPH(ttext,idx) \
853 {\
854 glyph = cache_get_font (font, ttext[idx]);\
855 if (!(flags & TEXT2_IMPLICIT_X))\
856 {\
857 xyoffset = ttext[++idx];\
858 if ((xyoffset & 0x80))\
859 {\
860 if (flags & TEXT2_VERTICAL) \
861 y += ttext[++idx] | (ttext[++idx] << 8);\
862 else\
863 x += ttext[++idx] | (ttext[++idx] << 8);\
864 }\
865 else\
866 {\
867 if (flags & TEXT2_VERTICAL) \
868 y += xyoffset;\
869 else\
870 x += xyoffset;\
871 }\
872 }\
873 if (glyph != NULL)\
874 {\
875 ui_draw_glyph (mixmode, x + (short) glyph->offset,\
876 y + (short) glyph->baseline,\
877 glyph->width, glyph->height,\
878 glyph->pixmap, 0, 0, bgcolour, fgcolour);\
879 if (flags & TEXT2_IMPLICIT_X)\
880 x += glyph->width;\
881 }\
882 }
883
884 void
885 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
886 int clipx, int clipy, int clipcx, int clipcy, int boxx,
887 int boxy, int boxcx, int boxcy, int bgcolour,
888 int fgcolour, uint8 * text, uint8 length)
889 {
890 FONTGLYPH *glyph;
891 int i, j, xyoffset;
892 DATABLOB *entry;
893
894 SET_FOREGROUND(bgcolour);
895
896 if (boxcx > 1)
897 {
898 FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
899 }
900 else if (mixmode == MIX_OPAQUE)
901 {
902 FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
903 }
904
905 /* Paint text, character by character */
906 for (i = 0; i < length;) {
907 switch (text[i]) {
908 case 0xff:
909 if (i + 2 < length)
910 cache_put_text(text[i + 1], text, text[i + 2]);
911 else {
912 error("this shouldn't be happening\n");
913 break;
914 }
915 /* this will move pointer from start to first character after FF command */
916 length -= i + 3;
917 text = &(text[i + 3]);
918 i = 0;
919 break;
920
921 case 0xfe:
922 entry = cache_get_text(text[i + 1]);
923 if (entry != NULL) {
924 if ((((uint8 *) (entry->data))[1] == 0)
925 && (!(flags & TEXT2_IMPLICIT_X))) {
926 if (flags & TEXT2_VERTICAL)
927 y += text[i + 2];
928 else
929 x += text[i + 2];
930 }
931 if (i + 2 < length)
932 i += 3;
933 else
934 i += 2;
935 length -= i;
936 /* this will move pointer from start to first character after FE command */
937 text = &(text[i]);
938 i = 0;
939 for (j = 0; j < entry->size; j++)
940 DO_GLYPH(((uint8 *) (entry->data)), j);
941 }
942 break;
943
944 default:
945 DO_GLYPH(text, i);
946 i++;
947 break;
948 }
949 }
950
951
952 }
953
954 void
955 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
956 {
957 Pixmap pix;
958 XImage *image;
959
960 if (ownbackstore)
961 {
962 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
963 ZPixmap);
964 }
965 else
966 {
967 pix = XCreatePixmap(display, wnd, cx, cy, depth);
968 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
969 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,
970 ZPixmap);
971 XFreePixmap(display, pix);
972 }
973
974 offset *= bpp/8;
975 cache_put_desktop(offset, cx, cy, image->bytes_per_line,
976 bpp/8, (uint8 *)image->data);
977
978 XDestroyImage(image);
979 }
980
981 void
982 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
983 {
984 XImage *image;
985 uint8 *data;
986
987 offset *= bpp/8;
988 data = cache_get_desktop(offset, cx, cy, bpp/8);
989 if (data == NULL)
990 return;
991
992 image = XCreateImage(display, visual, depth, ZPixmap,
993 0, data, cx, cy, BitmapPad(display),
994 cx * bpp/8);
995
996 if (ownbackstore)
997 {
998 XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
999 XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1000 }
1001 else
1002 {
1003 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1004 }
1005
1006 XFree(image);
1007 }

  ViewVC Help
Powered by ViewVC 1.1.26