/[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 28 - (show annotations)
Wed Jun 20 13:54:48 2001 UTC (22 years, 11 months ago) by matty
File MIME type: text/plain
File size: 27484 byte(s)
Merges from pl19-6-5.

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 User interface services - X-Windows
4 Copyright (C) Matthew Chapman 1999-2000
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 motion;
29 extern BOOL grab_keyboard;
30 extern BOOL fullscreen;
31 extern int private_colormap;
32
33 static int bpp;
34 static int depth;
35 static Display *display;
36 static Window wnd;
37 static GC gc;
38 static Visual *visual;
39 static uint32 *colmap;
40
41 #define Ctrans(col) ( private_colormap ? col : colmap[col])
42
43 #define L_ENDIAN
44 int screen_msbfirst = 0;
45
46 static uint8 *translate(int width, int height, uint8 *data);
47
48 static int rop2_map[] = {
49 GXclear, /* 0 */
50 GXnor, /* DPon */
51 GXandInverted, /* DPna */
52 GXcopyInverted, /* Pn */
53 GXandReverse, /* PDna */
54 GXinvert, /* Dn */
55 GXxor, /* DPx */
56 GXnand, /* DPan */
57 GXand, /* DPa */
58 GXequiv, /* DPxn */
59 GXnoop, /* D */
60 GXorInverted, /* DPno */
61 GXcopy, /* P */
62 GXorReverse, /* PDno */
63 GXor, /* DPo */
64 GXset /* 1 */
65 };
66
67 static void
68 xwin_set_function(uint8 rop2)
69 {
70 static uint8 last_rop2 = ROP2_COPY;
71
72 if (last_rop2 != rop2)
73 {
74 XSetFunction(display, gc, rop2_map[rop2]);
75 last_rop2 = rop2;
76 }
77 }
78
79 static void
80 xwin_grab_keyboard()
81 {
82 XGrabKeyboard(display, wnd, True, GrabModeAsync, GrabModeAsync,
83 CurrentTime);
84 }
85
86 static void
87 xwin_ungrab_keyboard()
88 {
89 XUngrabKeyboard(display, CurrentTime);
90 }
91
92 BOOL
93 ui_create_window(char *title)
94 {
95 XSetWindowAttributes attribs;
96 XClassHint *classhints;
97 XSizeHints *sizehints;
98 unsigned long input_mask;
99 XPixmapFormatValues *pfm;
100 int count;
101
102 display = XOpenDisplay(NULL);
103 if (display == NULL)
104 {
105 ERROR("Failed to open display\n");
106 return False;
107 }
108
109 visual = DefaultVisual(display, DefaultScreen(display));
110 depth = DefaultDepth(display, DefaultScreen(display));
111 pfm = XListPixmapFormats(display, &count);
112 if (pfm != NULL)
113 {
114 while (count--)
115 {
116 if ((pfm + count)->depth == depth
117 && (pfm + count)->bits_per_pixel > bpp)
118 {
119 bpp = (pfm + count)->bits_per_pixel;
120 }
121 }
122 XFree(pfm);
123 }
124
125 if (bpp < 8)
126 {
127 ERROR("Less than 8 bpp not currently supported.\n");
128 XCloseDisplay(display);
129 return False;
130 }
131
132 width &= ~3; /* make width nicely divisible */
133
134 attribs.background_pixel = BlackPixel(display, DefaultScreen(display));
135 attribs.backing_store = Always;
136
137 if (fullscreen)
138 {
139 attribs.override_redirect = True;
140 width = WidthOfScreen(DefaultScreenOfDisplay(display));
141 height = HeightOfScreen(DefaultScreenOfDisplay(display));
142 XSetInputFocus(display, PointerRoot, RevertToPointerRoot,
143 CurrentTime);
144 }
145 else
146 {
147 attribs.override_redirect = False;
148 }
149
150 wnd = XCreateWindow(display, DefaultRootWindow(display),
151 0, 0, width, height, 0, CopyFromParent,
152 InputOutput, CopyFromParent,
153 CWBackingStore | CWBackPixel | CWOverrideRedirect,
154 &attribs);
155
156 XStoreName(display, wnd, title);
157
158 classhints = XAllocClassHint();
159 if (classhints != NULL)
160
161 {
162 classhints->res_name = "rdesktop";
163 classhints->res_class = "rdesktop";
164 XSetClassHint(display, wnd, classhints);
165 XFree(classhints);
166 }
167
168 sizehints = XAllocSizeHints();
169 if (sizehints)
170 {
171 sizehints->flags =
172 PPosition | PSize | PMinSize | PMaxSize | PBaseSize;
173 sizehints->min_width = width;
174 sizehints->max_width = width;
175 sizehints->min_height = height;
176 sizehints->max_height = height;
177 sizehints->base_width = width;
178 sizehints->base_height = height;
179 XSetWMNormalHints(display, wnd, sizehints);
180 XFree(sizehints);
181 }
182
183 input_mask = KeyPressMask | KeyReleaseMask;
184 input_mask |= ButtonPressMask | ButtonReleaseMask;
185 if (motion)
186 input_mask |= PointerMotionMask;
187 if (grab_keyboard)
188 input_mask |= EnterWindowMask | LeaveWindowMask;
189
190 XSelectInput(display, wnd, input_mask);
191 gc = XCreateGC(display, wnd, 0, NULL);
192
193 XMapWindow(display, wnd);
194 return True;
195 }
196
197 void
198 ui_destroy_window()
199 {
200 XFreeGC(display, gc);
201 XDestroyWindow(display, wnd);
202 XCloseDisplay(display);
203 display = NULL;
204 }
205
206 static uint8
207 xwin_translate_key(unsigned long key)
208 {
209 DEBUG("KEY(code=0x%lx)\n", key);
210
211 if ((key > 8) && (key <= 0x60))
212 return (key - 8);
213
214 switch (key)
215 {
216 case 0x61: /* home */
217 return 0x47 | 0x80;
218 case 0x62: /* up arrow */
219 return 0x48 | 0x80;
220 case 0x63: /* page up */
221 return 0x49 | 0x80;
222 case 0x64: /* left arrow */
223 return 0x4b | 0x80;
224 case 0x66: /* right arrow */
225 return 0x4d | 0x80;
226 case 0x67: /* end */
227 return 0x4f | 0x80;
228 case 0x68: /* down arrow */
229 return 0x50 | 0x80;
230 case 0x69: /* page down */
231 return 0x51 | 0x80;
232 case 0x6a: /* insert */
233 return 0x52 | 0x80;
234 case 0x6b: /* delete */
235 return 0x53 | 0x80;
236 case 0x6c: /* keypad enter */
237 return 0x1c | 0x80;
238 case 0x6d: /* right ctrl */
239 return 0x1d | 0x80;
240 case 0x6f: /* ctrl - print screen */
241 return 0x37 | 0x80;
242 case 0x70: /* keypad '/' */
243 return 0x35 | 0x80;
244 case 0x71: /* right alt */
245 return 0x38 | 0x80;
246 case 0x72: /* ctrl break */
247 return 0x46 | 0x80;
248 case 0x73: /* left window key */
249 return 0xff; /* real scancode is 5b */
250 case 0x74: /* right window key */
251 return 0xff; /* real scancode is 5c */
252 case 0x75: /* menu key */
253 return 0x5d | 0x80;
254 }
255
256 return 0;
257 }
258
259 static uint16
260 xwin_translate_mouse(unsigned long button)
261 {
262 switch (button)
263 {
264 case Button1: /* left */
265 return MOUSE_FLAG_BUTTON1;
266 case Button2: /* middle */
267 return MOUSE_FLAG_BUTTON3;
268 case Button3: /* right */
269 return MOUSE_FLAG_BUTTON2;
270 }
271
272 return 0;
273 }
274
275 void
276 ui_process_events()
277 {
278 XEvent event;
279 uint8 scancode;
280 uint16 button;
281 uint32 ev_time;
282
283 if (display == NULL)
284 return;
285
286 while (XCheckWindowEvent(display, wnd, ~0, &event))
287 {
288 ev_time = time(NULL);
289
290 switch (event.type)
291 {
292 case KeyPress:
293 scancode = xwin_translate_key(event.xkey.keycode);
294 if (scancode == 0)
295 break;
296
297 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,
298 scancode, 0);
299 break;
300
301 case KeyRelease:
302 scancode = xwin_translate_key(event.xkey.keycode);
303 if (scancode == 0)
304 break;
305
306 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
307 KBD_FLAG_DOWN | KBD_FLAG_UP,
308 scancode, 0);
309 break;
310
311 case ButtonPress:
312 button = xwin_translate_mouse(event.xbutton.button);
313 if (button == 0)
314 break;
315
316 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
317 button | MOUSE_FLAG_DOWN,
318 event.xbutton.x,
319 event.xbutton.y);
320 break;
321
322 case ButtonRelease:
323 button = xwin_translate_mouse(event.xbutton.button);
324 if (button == 0)
325 break;
326
327 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
328 button,
329 event.xbutton.x,
330 event.xbutton.y);
331 break;
332
333 case MotionNotify:
334 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
335 MOUSE_FLAG_MOVE,
336 event.xmotion.x,
337 event.xmotion.y);
338 break;
339
340 case EnterNotify:
341 if (grab_keyboard)
342 xwin_grab_keyboard();
343 break;
344
345 case LeaveNotify:
346 if (grab_keyboard)
347 xwin_ungrab_keyboard();
348 break;
349 }
350 }
351 }
352
353 void
354 ui_move_pointer(int x, int y)
355 {
356 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
357 }
358
359 HBITMAP
360 ui_create_bitmap(int width, int height, uint8 *data)
361 {
362 XImage *image;
363 Pixmap bitmap;
364 uint8 *tdata;
365 tdata = (private_colormap ? data : translate(width, height, data));
366 bitmap = XCreatePixmap(display, wnd, width, height, depth);
367 image =
368 XCreateImage(display, visual,
369 depth, ZPixmap,
370 0, tdata, width, height, BitmapPad(display), 0);
371
372 xwin_set_function(ROP2_COPY);
373 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
374
375 XFree(image);
376 if (!private_colormap)
377 xfree(tdata);
378 return (HBITMAP) bitmap;
379 }
380
381 void
382 ui_paint_bitmap(int x, int y, int cx, int cy,
383 int width, int height, uint8 *data)
384 {
385 XImage *image;
386 uint8 *tdata =
387 (private_colormap ? data : translate(width, height, data));
388 image =
389 XCreateImage(display, visual, depth, ZPixmap, 0, tdata, width,
390 height, BitmapPad(display), 0);
391
392 xwin_set_function(ROP2_COPY);
393
394 /* Window */
395 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
396 XFree(image);
397 if (!private_colormap)
398 xfree(tdata);
399 }
400
401 void
402 ui_destroy_bitmap(HBITMAP bmp)
403 {
404 XFreePixmap(display, (Pixmap) bmp);
405 }
406
407 HCURSOR
408 ui_create_cursor(unsigned int x, unsigned int y, int width,
409 int height, uint8 *mask, uint8 *data)
410 {
411 XImage *imagecursor;
412 XImage *imagemask;
413 Pixmap maskbitmap, cursorbitmap;
414 Cursor cursor;
415 XColor bg, fg;
416 GC lgc;
417 int i, x1, y1, scanlinelen;
418 uint8 *cdata, *cmask;
419 uint8 c;
420 cdata = (uint8 *) malloc(sizeof(uint8) * width * height);
421 if (!cdata)
422 return NULL;
423 scanlinelen = (width + 7) >> 3;
424 cmask = (uint8 *) malloc(sizeof(uint8) * scanlinelen * height);
425 if (!cmask)
426 {
427 free(cdata);
428 return NULL;
429 }
430 i = (height - 1) * scanlinelen;
431
432 if (!screen_msbfirst)
433 {
434 while (i >= 0)
435 {
436 for (x1 = 0; x1 < scanlinelen; x1++)
437 {
438 c = *(mask++);
439 cmask[i + x1] =
440 ((c & 0x1) << 7) | ((c & 0x2) << 5) |
441 ((c & 0x4) << 3) | ((c & 0x8) << 1) |
442 ((c & 0x10) >> 1) | ((c & 0x20) >> 3)
443 | ((c & 0x40) >> 5) | ((c & 0x80) >>
444 7);
445 }
446 i -= scanlinelen;
447 }
448 }
449 else
450 {
451 while (i >= 0)
452 {
453 for (x1 = 0; x1 < scanlinelen; x1++)
454 {
455 cmask[i + x1] = *(mask++);
456 }
457 i -= scanlinelen;
458 }
459 }
460
461
462 fg.red = 0;
463 fg.blue = 0;
464 fg.green = 0;
465 fg.flags = DoRed | DoBlue | DoGreen;
466 bg.red = 65535;
467 bg.blue = 65535;
468 bg.green = 65535;
469 bg.flags = DoRed | DoBlue | DoGreen;
470 maskbitmap = XCreatePixmap(display, wnd, width, height, 1);
471 cursorbitmap = XCreatePixmap(display, wnd, width, height, 1);
472 lgc = XCreateGC(display, maskbitmap, 0, NULL);
473 XSetFunction(display, lgc, GXcopy);
474 imagemask =
475 XCreateImage(display, visual, 1, XYBitmap, 0, cmask, width,
476 height, 8, 0);
477 imagecursor =
478 XCreateImage(display, visual, 1, XYBitmap, 0, cdata, width,
479 height, 8, 0);
480 for (y1 = height - 1; y1 >= 0; y1--)
481 for (x1 = 0; x1 < width; x1++)
482 {
483 if (data[0] >= 0x80 || data[1] >= 0x80
484 || data[2] >= 0x80)
485 if (XGetPixel(imagemask, x1, y1))
486
487 {
488 XPutPixel(imagecursor, x1, y1, 0);
489 XPutPixel(imagemask, x1, y1, 0); /* mask is blank for text cursor! */
490 }
491
492 else
493 XPutPixel(imagecursor, x1, y1, 1);
494
495 else
496 XPutPixel(imagecursor, x1, y1,
497 XGetPixel(imagemask, x1, y1));
498 data += 3;
499 }
500 XPutImage(display, maskbitmap, lgc, imagemask, 0, 0, 0, 0, width,
501 height);
502 XPutImage(display, cursorbitmap, lgc, imagecursor, 0, 0, 0, 0, width,
503 height); XFree(imagemask);
504 XFree(imagecursor);
505 free(cmask);
506 free(cdata);
507 XFreeGC(display, lgc);
508 cursor =
509 XCreatePixmapCursor(display, cursorbitmap, maskbitmap, &fg,
510 &bg, x, y);
511 XFreePixmap(display, maskbitmap);
512 XFreePixmap(display, cursorbitmap);
513 return (HCURSOR) cursor;
514 }
515
516 void
517 ui_set_cursor(HCURSOR cursor)
518 {
519 XDefineCursor(display, wnd, (Cursor) cursor);
520 }
521
522 void
523 ui_destroy_cursor(HCURSOR cursor)
524 {
525 XFreeCursor(display, (Cursor) cursor);
526 }
527
528 HGLYPH
529 ui_create_glyph(int width, int height, uint8 *data)
530 {
531 XImage *image;
532 Pixmap bitmap;
533 int scanline;
534 GC gc;
535
536 scanline = (width + 7) / 8;
537
538 bitmap = XCreatePixmap(display, wnd, width, height, 1);
539 gc = XCreateGC(display, bitmap, 0, NULL);
540
541 image = XCreateImage(display, visual, 1, ZPixmap, 0,
542 data, width, height, 8, scanline);
543 image->byte_order = MSBFirst;
544 image->bitmap_bit_order = MSBFirst;
545 XInitImage(image);
546
547 XSetFunction(display, gc, GXcopy);
548 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
549 XFree(image);
550 XFreeGC(display, gc);
551
552 return (HGLYPH) bitmap;
553 }
554
555 void
556 ui_destroy_glyph(HGLYPH glyph)
557 {
558 XFreePixmap(display, (Pixmap) glyph);
559 }
560
561 HCOLOURMAP
562 ui_create_colourmap(COLOURMAP *colours)
563 {
564 if (!private_colormap)
565 {
566 COLOURENTRY *entry;
567 int i, ncolours = colours->ncolours;
568 uint32 *nc = xmalloc(sizeof(*colmap) * ncolours);
569 for (i = 0; i < ncolours; i++)
570 {
571 XColor xc;
572 entry = &colours->colours[i];
573 xc.red = entry->red << 8;
574 xc.green = entry->green << 8;
575 xc.blue = entry->blue << 8;
576 XAllocColor(display,
577 DefaultColormap(display,
578 DefaultScreen(display)),
579 &xc);
580 /* XXX Check return value */
581 nc[i] = xc.pixel;
582 }
583 return nc;
584 }
585 else
586 {
587 COLOURENTRY *entry;
588 XColor *xcolours, *xentry;
589 Colormap map;
590 int i, ncolours = colours->ncolours;
591 xcolours = xmalloc(sizeof(XColor) * ncolours);
592 for (i = 0; i < ncolours; i++)
593 {
594 entry = &colours->colours[i];
595 xentry = &xcolours[i];
596
597 xentry->pixel = i;
598 xentry->red = entry->red << 8;
599 xentry->blue = entry->blue << 8;
600 xentry->green = entry->green << 8;
601 xentry->flags = DoRed | DoBlue | DoGreen;
602 }
603
604 map = XCreateColormap(display, wnd, visual, AllocAll);
605 XStoreColors(display, map, xcolours, ncolours);
606
607 xfree(xcolours);
608 return (HCOLOURMAP) map;
609 }
610 }
611
612 void
613 ui_destroy_colourmap(HCOLOURMAP map)
614 {
615 XFreeColormap(display, (Colormap) map);
616 }
617
618 void
619 ui_set_colourmap(HCOLOURMAP map)
620 {
621
622 /* XXX, change values of all pixels on the screen if the new colmap
623 * doesn't have the same values as the old one? */
624 if (!private_colormap)
625 colmap = map;
626 else
627 {
628 XSetWindowColormap(display, wnd, (Colormap) map);
629 if (fullscreen)
630 XInstallColormap(display, (Colormap) map);
631 }
632 }
633
634 void
635 ui_set_clip(int x, int y, int cx, int cy)
636 {
637 XRectangle rect;
638
639 rect.x = x;
640 rect.y = y;
641 rect.width = cx;
642 rect.height = cy;
643 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
644 }
645
646 void
647 ui_reset_clip()
648 {
649 XRectangle rect;
650
651 rect.x = 0;
652 rect.y = 0;
653 rect.width = width;
654 rect.height = height;
655 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
656 }
657
658 void
659 ui_bell()
660 {
661 XBell(display, 0);
662 }
663
664 void
665 ui_destblt(uint8 opcode,
666 /* dest */ int x, int y, int cx, int cy)
667 {
668 xwin_set_function(opcode);
669
670 XFillRectangle(display, wnd, gc, x, y, cx, cy);
671 }
672
673 void
674 ui_patblt(uint8 opcode,
675 /* dest */ int x, int y, int cx, int cy,
676 /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
677 {
678 Display *dpy = display;
679 Pixmap fill;
680 uint8 i, ipattern[8];
681
682 xwin_set_function(opcode);
683
684 switch (brush->style)
685 {
686 case 0: /* Solid */
687 XSetForeground(dpy, gc, Ctrans(fgcolour));
688 XFillRectangle(dpy, wnd, gc, x, y, cx, cy);
689 break;
690
691 case 3: /* Pattern */
692 for (i = 0; i != 8; i++)
693 ipattern[i] = ~brush->pattern[i];
694 fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
695
696 XSetForeground(dpy, gc, Ctrans(fgcolour));
697 XSetBackground(dpy, gc, Ctrans(bgcolour));
698 XSetFillStyle(dpy, gc, FillOpaqueStippled);
699 XSetStipple(dpy, gc, fill);
700
701 XFillRectangle(dpy, wnd, gc, x, y, cx, cy);
702
703 XSetFillStyle(dpy, gc, FillSolid);
704 ui_destroy_glyph((HGLYPH) fill);
705 break;
706
707 default:
708 NOTIMP("brush %d\n", brush->style);
709 }
710 }
711
712 void
713 ui_screenblt(uint8 opcode,
714 /* dest */ int x, int y, int cx, int cy,
715 /* src */ int srcx, int srcy)
716 {
717 xwin_set_function(opcode);
718
719 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
720 }
721
722 void
723 ui_memblt(uint8 opcode,
724 /* dest */ int x, int y, int cx, int cy,
725 /* src */ HBITMAP src, int srcx, int srcy)
726 {
727 xwin_set_function(opcode);
728
729 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
730 }
731
732 void
733 ui_triblt(uint8 opcode,
734 /* dest */ int x, int y, int cx, int cy,
735 /* src */ HBITMAP src, int srcx, int srcy,
736 /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
737 {
738 /* This is potentially difficult to do in general. Until someone
739 comes up with a more efficient way of doing it I am using cases. */
740
741 switch (opcode)
742 {
743 case 0x69: /* PDSxxn */
744 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
745 ui_patblt(ROP2_NXOR, x, y, cx, cy,
746 brush, bgcolour, fgcolour);
747 break;
748
749 case 0xb8: /* PSDPxax */
750 ui_patblt(ROP2_XOR, x, y, cx, cy,
751 brush, bgcolour, fgcolour);
752 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
753 ui_patblt(ROP2_XOR, x, y, cx, cy,
754 brush, bgcolour, fgcolour);
755 break;
756
757 case 0xc0:
758 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
759 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
760 fgcolour);
761 break;
762
763 default:
764 NOTIMP("triblt 0x%x\n", opcode);
765 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
766 }
767 }
768
769 void
770 ui_line(uint8 opcode,
771 /* dest */ int startx, int starty, int endx, int endy,
772 /* pen */ PEN *pen)
773 {
774 xwin_set_function(opcode);
775
776 XSetForeground(display, gc, Ctrans(pen->colour));
777 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
778 }
779
780 void
781 ui_rect(
782 /* dest */ int x, int y, int cx, int cy,
783 /* brush */ int colour)
784 {
785 xwin_set_function(ROP2_COPY);
786
787 XSetForeground(display, gc, Ctrans(colour));
788 XFillRectangle(display, wnd, gc, x, y, cx, cy);
789 }
790
791 void
792 ui_draw_glyph(int mixmode,
793 /* dest */ int x, int y, int cx, int cy,
794 /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,
795 int fgcolour)
796 {
797 Pixmap pixmap = (Pixmap) glyph;
798
799 xwin_set_function(ROP2_COPY);
800
801
802 XSetForeground(display, gc, Ctrans(fgcolour));
803 switch (mixmode)
804 {
805 case MIX_TRANSPARENT:
806 XSetStipple(display, gc, pixmap);
807 XSetFillStyle(display, gc, FillStippled);
808 XSetTSOrigin(display, gc, x, y);
809 XFillRectangle(display, wnd, gc, x, y, cx, cy);
810 XSetFillStyle(display, gc, FillSolid);
811 break;
812
813 case MIX_OPAQUE:
814 XSetBackground(display, gc, Ctrans(bgcolour));
815 /* XCopyPlane (display, pixmap, back_pixmap, back_gc, srcx, srcy, cx, cy, x, y, 1); */
816 XSetStipple(display, gc, pixmap);
817 XSetFillStyle(display, gc, FillOpaqueStippled);
818 XSetTSOrigin(display, gc, x, y);
819 XFillRectangle(display, wnd, gc, x, y, cx, cy);
820 XSetFillStyle(display, gc, FillSolid);
821 break;
822
823 default:
824 NOTIMP("mix %d\n", mixmode);
825 }
826 }
827
828 void
829 ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
830 int clipx, int clipy, int clipcx, int clipcy,
831 int boxx, int boxy, int boxcx, int boxcy,
832 int bgcolour, int fgcolour, uint8 *text, uint8 length)
833 {
834 FONTGLYPH *glyph;
835 int i, xyoffset;
836
837 xwin_set_function(ROP2_COPY);
838 XSetForeground(display, gc, Ctrans(bgcolour));
839
840 if (boxcx > 1)
841 XFillRectangle(display, wnd, gc, boxx, boxy, boxcx, boxcy);
842 else if (mixmode == MIX_OPAQUE)
843 XFillRectangle(display, wnd, gc, clipx, clipy, clipcx, clipcy);
844
845 /* Paint text, character by character */
846 for (i = 0; i < length; i++)
847 {
848 glyph = cache_get_font(font, text[i]);
849
850 if (!(flags & TEXT2_IMPLICIT_X))
851
852 {
853 xyoffset = text[++i];
854 if ((xyoffset & 0x80))
855 {
856 if (flags & 0x04) /* vertical text */
857 y += text[++i] | (text[++i] << 8);
858 else
859 x += text[++i] | (text[++i] << 8);
860 }
861 else
862 {
863 if (flags & 0x04) /* vertical text */
864 y += xyoffset;
865 else
866 x += xyoffset;
867 }
868
869 }
870 if (glyph != NULL)
871 {
872 ui_draw_glyph(mixmode, x + (short) glyph->offset,
873 y + (short) glyph->baseline,
874 glyph->width, glyph->height,
875 glyph->pixmap, 0, 0,
876 bgcolour, fgcolour);
877
878 if (flags & TEXT2_IMPLICIT_X)
879 x += glyph->width;
880 }
881 }
882 }
883
884 void
885 ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
886 {
887 Pixmap pix;
888 XImage *image;
889
890 pix = XCreatePixmap(display, wnd, cx, cy, depth);
891 xwin_set_function(ROP2_COPY);
892
893 XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
894 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
895
896 offset *= bpp/8;
897 cache_put_desktop(offset, cx, cy, image->bytes_per_line,
898 bpp/8, image->data);
899
900 XDestroyImage(image);
901 XFreePixmap(display, pix);
902 }
903
904 void
905 ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
906 {
907 XImage *image;
908 uint8 *data;
909
910 offset *= bpp/8;
911 data = cache_get_desktop(offset, cx, cy, bpp/8);
912 if (data == NULL)
913 return;
914 image =
915 XCreateImage(display, visual,
916 depth, ZPixmap,
917 0, data, cx, cy, BitmapPad(display),
918 cx * bpp/8);
919 xwin_set_function(ROP2_COPY);
920 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
921 XFree(image);
922 }
923
924 /* unroll defines, used to make the loops a bit more readable... */
925 #define unroll8Expr(uexp) uexp uexp uexp uexp uexp uexp uexp uexp
926 #define unroll8Lefts(uexp) case 7: uexp \
927 case 6: uexp \
928 case 5: uexp \
929 case 4: uexp \
930 case 3: uexp \
931 case 2: uexp \
932 case 1: uexp
933
934 static uint8 *
935 translate(int width, int height, uint8 *data)
936 {
937 uint32 i;
938 uint32 size = width * height;
939 uint8 *d2 = xmalloc(size * bpp/8);
940 uint8 *d3 = d2;
941 uint32 pix;
942 i = (size & ~0x7);
943
944 /* XXX: where are the bits swapped??? */
945 #ifdef L_ENDIAN /* little-endian */
946 /* big-endian screen */
947 if (screen_msbfirst)
948 {
949 switch (bpp)
950 {
951 case 32:
952 while (i)
953 {
954 unroll8Expr(pix = colmap[*data++];
955 *d3++ = pix >> 24;
956 *d3++ = pix >> 16;
957 *d3++ = pix >> 8;
958 *d3++ = pix;) i -= 8;
959 }
960 i = (size & 0x7);
961 if (i != 0)
962 switch (i)
963 {
964 unroll8Lefts(pix =
965 colmap
966 [*data++];
967 *d3++ =
968 pix >>
969 24;
970 *d3++ =
971 pix >>
972 16;
973 *d3++ =
974 pix >> 8;
975 *d3++ =
976 pix;)}
977 break;
978 case 24:
979 while (i)
980 {
981 unroll8Expr(pix = colmap[*data++];
982 *d3++ = pix >> 16;
983 *d3++ = pix >> 8;
984 *d3++ = pix;) i -= 8;
985 }
986 i = (size & 0x7);
987 if (i != 0)
988 switch (i)
989 {
990 unroll8Lefts(pix =
991 colmap
992 [*data++];
993 *d3++ =
994 pix >>
995 16;
996 *d3++ =
997 pix >> 8;
998 *d3++ =
999 pix;)}
1000 break;
1001 case 16:
1002 while (i)
1003 {
1004 unroll8Expr(pix = colmap[*data++];
1005 *d3++ = pix >> 8;
1006 *d3++ = pix;) i -= 8;
1007 }
1008 i = (size & 0x7);
1009 if (i != 0)
1010 switch (i)
1011 {
1012 unroll8Lefts(pix =
1013 colmap
1014 [*data++];
1015 *d3++ =
1016 pix >> 8;
1017 *d3++ =
1018 pix;)}
1019 break;
1020 case 8:
1021 while (i)
1022 {
1023 unroll8Expr(pix = colmap[*data++];
1024 *d3++ = pix;
1025 )i -= 8;
1026 }
1027 i = (size & 0x7);
1028 if (i != 0)
1029 switch (i)
1030 {
1031 unroll8Lefts(pix =
1032 colmap
1033 [*data++];
1034 *d3++ =
1035 pix;)}
1036 break;
1037 }
1038 }
1039 else
1040 { /* little-endian screen */
1041 switch (bpp)
1042 {
1043 case 32:
1044 while (i)
1045 {
1046 unroll8Expr(*((uint32 *) d3) =
1047 colmap[*data++];
1048 d3 += sizeof(uint32);
1049 )i -= 8;
1050 }
1051 i = (size & 0x7);
1052 if (i != 0)
1053 switch (i)
1054 {
1055 unroll8Lefts(*
1056 ((uint32
1057 *) d3)
1058 = colmap[*data++];
1059 d3 += sizeof(uint32);
1060 )}
1061 break;
1062 case 24:
1063 while (i)
1064 {
1065 unroll8Expr(pix = colmap[*data++];
1066 *d3++ = pix;
1067 *d3++ = pix >> 8;
1068 *d3++ = pix >> 16;
1069 )i -= 8;
1070 }
1071 i = (size & 0x7);
1072 if (i != 0)
1073 switch (i)
1074 {
1075 unroll8Lefts(pix =
1076 colmap
1077 [*data++];
1078 *d3++ =
1079 pix;
1080 *d3++ =
1081 pix >> 8;
1082 *d3++ =
1083 pix >>
1084 16;)}
1085 break;
1086 case 16:
1087 while (i)
1088 {
1089 unroll8Expr(pix = colmap[*data++];
1090 *d3++ = pix;
1091 *d3++ = pix >> 8;
1092 )i -= 8;
1093 }
1094 i = (size & 0x7);
1095 if (i != 0)
1096 switch (i)
1097 {
1098 unroll8Lefts(pix =
1099 colmap
1100 [*data++];
1101 *d3++ =
1102 pix;
1103 *d3++ =
1104 pix >> 8;
1105 )}
1106 break;
1107 case 8:
1108 while (i)
1109 {
1110 unroll8Expr(pix = colmap[*data++];
1111 *d3++ = pix;
1112 )i -= 8;
1113 }
1114 i = (size & 0x7);
1115 if (i != 0)
1116 switch (i)
1117 {
1118 unroll8Lefts(pix =
1119 colmap
1120 [*data++];
1121 *d3++ =
1122 pix;)}
1123 }
1124 }
1125
1126 #else /* bigendian-compiled */
1127 if (screen_msbfirst)
1128 {
1129 /* big-endian screen */
1130 switch (bpp)
1131 {
1132 case 32:
1133 while (i)
1134 {
1135 unroll8Expr(*((uint32 *) d3) =
1136 colmap[*data++];
1137 d3 += sizeof(uint32);
1138 )i -= 8;
1139 }
1140 i = (size & 0x7);
1141 if (i != 0)
1142 switch (i)
1143 {
1144 unroll8Lefts(*
1145 ((uint32
1146 *) d3)
1147 = colmap[*data++];
1148 d3 += sizeof(uint32);
1149 )}
1150 break;
1151 case 24:
1152 while (i)
1153 {
1154 unroll8Expr(pix = colmap[*data++];
1155 *d3++ = pix;
1156 *d3++ = pix >> 8;
1157 *d3++ = pix >> 16;
1158 )i -= 8;
1159 }
1160 i = (size & 0x7);
1161 if (i != 0)
1162 switch (i)
1163 {
1164 unroll8Lefts(pix =
1165 colmap
1166 [*data++];
1167 *d3++ =
1168 pix;
1169 *d3++ =
1170 pix >> 8;
1171 *d3++ =
1172 pix >>
1173 16;)}
1174 break;
1175 case 16:
1176 while (i)
1177 {
1178 unroll8Expr(pix = colmap[*data++];
1179 *d3++ = pix;
1180 *d3++ = pix >> 8;
1181 )i -= 8;
1182 }
1183 i = (size & 0x7);
1184 if (i != 0)
1185 switch (i)
1186 {
1187 unroll8Lefts(pix =
1188 colmap
1189 [*data++];
1190 *d3++ =
1191 pix;
1192 *d3++ =
1193 pix >> 8;
1194 )}
1195 break;
1196 case 8:
1197 while (i)
1198 {
1199 unroll8Expr(pix = colmap[*data++];
1200 *d3++ = pix;
1201 )i -= 8;
1202 }
1203 i = (size & 0x7);
1204 if (i != 0)
1205 switch (i)
1206 {
1207 unroll8Lefts(pix =
1208 colmap
1209 [*data++];
1210 *d3++ =
1211 pix;)}
1212 }
1213 }
1214 else
1215 {
1216 /* little-endian screen */
1217 switch (bpp)
1218 {
1219 case 32:
1220 while (i)
1221 {
1222 unroll8Expr(pix = colmap[*data++];
1223 *d3++ = pix;
1224 *d3++ = pix >> 8;
1225 *d3++ = pix >> 16;
1226 *d3++ = pix >> 24;
1227 )i -= 8;
1228 }
1229 i = (size & 0x7);
1230 if (i != 0)
1231 switch (i)
1232 {
1233 unroll8Lefts(pix =
1234 colmap
1235 [*data++];
1236 *d3++ =
1237 pix;
1238 *d3++ =
1239 pix >> 8;
1240 *d3++ =
1241 pix >>
1242 16;
1243 *d3++ =
1244 pix >>
1245 24;)}
1246 break;
1247 case 24:
1248 while (i)
1249 {
1250 unroll8Expr(pix = colmap[*data++];
1251 *d3++ = pix;
1252 *d3++ = pix >> 8;
1253 *d3++ = pix >> 16;
1254 )i -= 8;
1255 }
1256 i = (size & 0x7);
1257 if (i != 0)
1258 switch (i)
1259 {
1260 unroll8Lefts(pix =
1261 colmap
1262 [*data++];
1263 *d3++ =
1264 pix;
1265 *d3++ =
1266 pix >> 8;
1267 *d3++ =
1268 pix >>
1269 16;)}
1270 break;
1271 case 16:
1272 while (i)
1273 {
1274 unroll8Expr(pix = colmap[*data++];
1275 *d3++ = pix;
1276 *d3++ = pix >> 8;
1277 )i -= 8;
1278 }
1279 i = (size & 0x7);
1280 if (i != 0)
1281 switch (i)
1282 {
1283 unroll8Lefts(pix =
1284 colmap
1285 [*data++];
1286 *d3++ =
1287 pix;
1288 *d3++ =
1289 pix >> 8;
1290 )}
1291 break;
1292 case 8:
1293 while (i)
1294 {
1295 unroll8Expr(pix = colmap[*data++];
1296 *d3++ = pix;
1297 )i -= 8;
1298 }
1299 i = (size & 0x7);
1300 if (i != 0)
1301 switch (i)
1302 {
1303 unroll8Lefts(pix =
1304 colmap
1305 [*data++];
1306 *d3++ =
1307 pix;)}
1308 }
1309 }
1310 #endif
1311
1312 return d2;
1313 }

  ViewVC Help
Powered by ViewVC 1.1.26