/[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

Annotation of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 52 - (hide annotations)
Fri Apr 26 08:22:39 2002 UTC (22 years ago) by n-ki
File MIME type: text/plain
File size: 26873 byte(s)
adds support for accessx, makes it possible for people with disabilities to use rdesktop. Relies on XKB. Sync problem with changed modifiers on focus in not fixed yet...

1 matty 6 /*
2     rdesktop: A Remote Desktop Protocol client.
3 matthewc 38 User interface services - X Window System
4 matty 30 Copyright (C) Matthew Chapman 1999-2001
5 n-ki 52
6 matty 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 n-ki 52
11 matty 6 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 n-ki 52
16 matty 6 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 matty 10 #include <X11/Xlib.h>
22 matty 28 #include <X11/Xutil.h>
23 n-ki 52 #include <X11/XKBlib.h>
24 matty 10 #include <time.h>
25 matty 33 #include <errno.h>
26 matty 10 #include "rdesktop.h"
27 matty 6
28 matthewc 38 extern char keymapname[16];
29     extern int keylayout;
30 matty 10 extern int width;
31     extern int height;
32 matty 29 extern BOOL sendmotion;
33 matty 28 extern BOOL fullscreen;
34 matty 10
35 matthewc 50 Display *display;
36 n-ki 52 XkbDescPtr xkb;
37 matty 33 static int x_socket;
38 matty 10 static Window wnd;
39     static GC gc;
40     static Visual *visual;
41 matty 29 static int depth;
42     static int bpp;
43    
44 matty 33 /* endianness */
45     static BOOL host_be;
46     static BOOL xserver_be;
47    
48     /* software backing store */
49 matty 31 static BOOL ownbackstore;
50     static Pixmap backstore;
51    
52 n-ki 52 /* needed to keep track of the modifiers */
53     static unsigned int key_modifier_state = 0;
54     static unsigned int key_down_state = 0;
55    
56     #define DShift1Mask (1<<0)
57     #define DShift2Mask (1<<1)
58     #define DControl1Mask (1<<2)
59     #define DControl2Mask (1<<3)
60     #define DMod1Mask (1<<4)
61     #define DMod2Mask (1<<5)
62    
63 matty 31 #define FILL_RECTANGLE(x,y,cx,cy)\
64     { \
65     XFillRectangle(display, wnd, gc, x, y, cx, cy); \
66     if (ownbackstore) \
67     XFillRectangle(display, backstore, gc, x, y, cx, cy); \
68     }
69    
70 matty 33 /* colour maps */
71 matty 29 static BOOL owncolmap;
72     static Colormap xcolmap;
73     static uint32 white;
74 matty 28 static uint32 *colmap;
75 matty 10
76 matty 33 #define TRANSLATE(col) ( owncolmap ? col : translate_colour(colmap[col]) )
77 matty 29 #define SET_FOREGROUND(col) XSetForeground(display, gc, TRANSLATE(col));
78     #define SET_BACKGROUND(col) XSetBackground(display, gc, TRANSLATE(col));
79 matty 28
80     static int rop2_map[] = {
81     GXclear, /* 0 */
82     GXnor, /* DPon */
83     GXandInverted, /* DPna */
84     GXcopyInverted, /* Pn */
85     GXandReverse, /* PDna */
86     GXinvert, /* Dn */
87     GXxor, /* DPx */
88     GXnand, /* DPan */
89     GXand, /* DPa */
90     GXequiv, /* DPxn */
91     GXnoop, /* D */
92     GXorInverted, /* DPno */
93     GXcopy, /* P */
94     GXorReverse, /* PDno */
95     GXor, /* DPo */
96     GXset /* 1 */
97     };
98    
99 matty 29 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
100     #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
101    
102 n-ki 52 void xwin_release_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode);
103     void xwin_press_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode);
104    
105 matty 28 static void
106 matty 29 translate8(uint8 *data, uint8 *out, uint8 *end)
107 matty 28 {
108 matty 29 while (out < end)
109     *(out++) = (uint8)colmap[*(data++)];
110     }
111 matty 28
112 matty 29 static void
113     translate16(uint8 *data, uint16 *out, uint16 *end)
114     {
115     while (out < end)
116     *(out++) = (uint16)colmap[*(data++)];
117     }
118    
119 matty 33 /* little endian - conversion happens when colourmap is built */
120 matty 29 static void
121     translate24(uint8 *data, uint8 *out, uint8 *end)
122     {
123     uint32 value;
124    
125     while (out < end)
126 matty 28 {
127 matty 29 value = colmap[*(data++)];
128     *(out++) = value;
129     *(out++) = value >> 8;
130     *(out++) = value >> 16;
131 matty 28 }
132     }
133    
134     static void
135 matty 29 translate32(uint8 *data, uint32 *out, uint32 *end)
136 matty 28 {
137 matty 29 while (out < end)
138     *(out++) = colmap[*(data++)];
139 matty 28 }
140    
141 matty 29 static uint8 *
142 matty 33 translate_image(int width, int height, uint8 *data)
143 matty 28 {
144 matty 29 int size = width * height * bpp/8;
145     uint8 *out = xmalloc(size);
146     uint8 *end = out + size;
147    
148     switch (bpp)
149     {
150     case 8:
151     translate8(data, out, end);
152     break;
153    
154     case 16:
155     translate16(data, (uint16 *)out, (uint16 *)end);
156     break;
157    
158     case 24:
159     translate24(data, out, end);
160     break;
161    
162     case 32:
163     translate32(data, (uint32 *)out, (uint32 *)end);
164     break;
165     }
166    
167     return out;
168 matty 28 }
169    
170 matty 35 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
171     #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
172     #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
173     x = (x << 16) | (x >> 16); }
174 matty 29
175 matty 33 static uint32
176     translate_colour(uint32 colour)
177     {
178     switch (bpp)
179     {
180     case 16:
181     if (host_be != xserver_be)
182     BSWAP16(colour);
183     break;
184 matty 29
185 matty 33 case 24:
186     if (xserver_be)
187     BSWAP24(colour);
188     break;
189    
190     case 32:
191     if (host_be != xserver_be)
192     BSWAP32(colour);
193     break;
194     }
195    
196     return colour;
197     }
198    
199 matty 25 BOOL
200     ui_create_window(char *title)
201 matty 6 {
202 matty 9 XSetWindowAttributes attribs;
203 matty 28 XClassHint *classhints;
204     XSizeHints *sizehints;
205 matty 10 unsigned long input_mask;
206 matty 28 XPixmapFormatValues *pfm;
207 matty 29 Screen *screen;
208 matty 33 uint16 test;
209 matty 29 int i;
210 n-ki 52
211     int xkb_minor, xkb_major;
212     int xkb_event, xkb_error, xkb_reason;
213 matty 6
214 n-ki 52 /* compare compiletime libs with runtime libs. */
215     xkb_major = XkbMajorVersion;
216     xkb_minor = XkbMinorVersion;
217     if( XkbLibraryVersion( &xkb_major, &xkb_minor ) == False )
218     {
219     error("please re-compile rdesktop\ncompile time version of xkb is not compatible with\nyour runtime version of the library\n");
220     return False;
221     }
222    
223    
224     /* XKB is the 'new' keyboard handler in x.. ( the xkb code in Xfree86 originates from SGI, years 1993 and 1995 from what I could tell. )
225     * it makes it possible for people with disabilities to use rdesktop, stickykeys, bouncekeys etc. VERY MUCH useful.
226     * XFree86 has had support for it since it's earliest incarnation. I believe it is a reasonable dependency.
227     */
228     display = XkbOpenDisplay( NULL, &xkb_event, &xkb_error, &xkb_major, &xkb_minor, &xkb_reason );
229     switch(xkb_reason)
230     {
231     case XkbOD_BadLibraryVersion:
232     error("XkbOD_BadLibraryVersion: XKB extensions in server and the library rdesktop is linked against aren't compatible with each other.\n");
233     break;
234     case XkbOD_ConnectionRefused:
235     error("XkbOD_ConnectionRefused\n");
236     break;
237     case XkbOD_BadServerVersion:
238     error("XkbOD_BadServerVersion\n");
239     break;
240     case XkbOD_NonXkbServer:
241     error("XkbOD_NonXkbServer: XKB extension not present in server\nupdate your X server.\n");
242     break;
243     case XkbOD_Success:
244     DEBUG("XkbOD_Success: Connection established with display\n");
245     break;
246     }
247    
248 matty 6 if (display == NULL)
249 matty 21 {
250 matty 30 error("Failed to open display\n");
251 matty 10 return False;
252 matty 21 }
253 matty 6
254 matty 33 x_socket = ConnectionNumber(display);
255 matty 29 screen = DefaultScreenOfDisplay(display);
256     visual = DefaultVisualOfScreen(screen);
257     depth = DefaultDepthOfScreen(screen);
258 n-ki 52
259 matty 29 pfm = XListPixmapFormats(display, &i);
260 matty 28 if (pfm != NULL)
261     {
262 matty 29 /* Use maximum bpp for this depth - this is generally
263     desirable, e.g. 24 bits->32 bits. */
264     while (i--)
265 matty 28 {
266 matty 29 if ((pfm[i].depth == depth)
267     && (pfm[i].bits_per_pixel > bpp))
268 matty 28 {
269 matty 29 bpp = pfm[i].bits_per_pixel;
270 matty 28 }
271     }
272     XFree(pfm);
273     }
274 matty 10
275 matty 28 if (bpp < 8)
276 matty 10 {
277 matty 30 error("Less than 8 bpp not currently supported.\n");
278 matty 10 XCloseDisplay(display);
279     return False;
280     }
281    
282 matty 29 if (depth <= 8)
283     owncolmap = True;
284     else
285     xcolmap = DefaultColormapOfScreen(screen);
286 matty 6
287 matty 33 test = 1;
288     host_be = !(BOOL)(*(uint8 *)(&test));
289     xserver_be = (ImageByteOrder(display) == MSBFirst);
290    
291 matty 29 white = WhitePixelOfScreen(screen);
292     attribs.background_pixel = BlackPixelOfScreen(screen);
293     attribs.backing_store = DoesBackingStore(screen);
294 matty 28
295 matty 29 if (attribs.backing_store == NotUseful)
296 matty 31 ownbackstore = True;
297 matty 29
298 matty 28 if (fullscreen)
299     {
300     attribs.override_redirect = True;
301 matty 29 width = WidthOfScreen(screen);
302     height = HeightOfScreen(screen);
303 matty 28 }
304     else
305     {
306     attribs.override_redirect = False;
307     }
308    
309 matty 30 width = (width + 3) & ~3; /* make width a multiple of 32 bits */
310 matty 29
311     wnd = XCreateWindow(display, RootWindowOfScreen(screen),
312 matty 28 0, 0, width, height, 0, CopyFromParent,
313     InputOutput, CopyFromParent,
314     CWBackingStore | CWBackPixel | CWOverrideRedirect,
315     &attribs);
316 matty 9
317 matty 10 XStoreName(display, wnd, title);
318 matty 6
319 matty 28 classhints = XAllocClassHint();
320     if (classhints != NULL)
321     {
322 matty 29 classhints->res_name = classhints->res_class = "rdesktop";
323 matty 28 XSetClassHint(display, wnd, classhints);
324     XFree(classhints);
325     }
326    
327     sizehints = XAllocSizeHints();
328     if (sizehints)
329     {
330 matty 29 sizehints->flags = PMinSize | PMaxSize;
331     sizehints->min_width = sizehints->max_width = width;
332     sizehints->min_height = sizehints->max_height = height;
333 matty 28 XSetWMNormalHints(display, wnd, sizehints);
334     XFree(sizehints);
335     }
336    
337 matthewc 50 xkeymap_init();
338 matthewc 38
339 n-ki 52 input_mask = KeyPressMask | KeyReleaseMask |
340     ButtonPressMask | ButtonReleaseMask |
341     EnterWindowMask | LeaveWindowMask | KeymapStateMask;
342 matty 29 if (sendmotion)
343 matty 10 input_mask |= PointerMotionMask;
344 matty 6
345 matty 31 if (ownbackstore)
346     input_mask |= ExposureMask;
347    
348 matty 10 XSelectInput(display, wnd, input_mask);
349     gc = XCreateGC(display, wnd, 0, NULL);
350 matty 7
351 matty 31 if (ownbackstore)
352     backstore = XCreatePixmap(display, wnd, width, height, depth);
353    
354 matty 28 XMapWindow(display, wnd);
355 n-ki 52
356     /* TODO: error texts... make them friendly. */
357     xkb = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd);
358     if ((int)xkb == BadAlloc || xkb == NULL)
359     {
360     error( "XkbGetKeyboard failed.\n");
361     exit(0);
362     }
363    
364     /* TODO: error texts... make them friendly. */
365     if( XkbSelectEvents(display, xkb->device_spec, XkbAllEventsMask, XkbAllEventsMask) == False )
366     {
367     error( "XkbSelectEvents failed.\n");
368     exit(0);
369     }
370    
371 matty 10 return True;
372 matty 6 }
373    
374 matty 25 void
375     ui_destroy_window()
376 matty 6 {
377 n-ki 52 if( xkb != NULL )
378     XkbFreeKeyboard(xkb, XkbAllControlsMask, True);
379    
380 matty 31 if (ownbackstore)
381     XFreePixmap(display, backstore);
382    
383 matty 10 XFreeGC(display, gc);
384     XDestroyWindow(display, wnd);
385     XCloseDisplay(display);
386 matty 28 display = NULL;
387 matty 6 }
388    
389 matty 33 static void
390     xwin_process_events()
391 matty 9 {
392 n-ki 52 XkbEvent xkbevent;
393    
394 matthewc 38 KeySym keysym;
395 matty 9 uint8 scancode;
396 matthewc 50 uint16 button, flags;
397 matty 10 uint32 ev_time;
398 n-ki 52 uint32 tmpmods;
399 matty 9
400 matty 10 if (display == NULL)
401 matty 9 return;
402    
403 n-ki 52 while (XCheckMaskEvent(display, ~0, &xkbevent.core))
404 matty 9 {
405 matty 10 ev_time = time(NULL);
406 matthewc 50 flags = 0;
407 matty 10
408 n-ki 52 switch (xkbevent.type)
409 matty 9 {
410 n-ki 52 case KeymapNotify:
411     /* TODO:
412     * read modifier status at focus in, and update the local masks, and the other end as well..
413     * if not, we may get out of sync.
414     * xkbevent.core.xkeymap.key_vector
415     * char key_vector[32];
416     */
417     break;
418    
419 matthewc 50 case KeyRelease:
420     flags = KBD_FLAG_DOWN | KBD_FLAG_UP;
421     /* fall through */
422    
423 matty 9 case KeyPress:
424 n-ki 52 if( XkbTranslateKeyCode(xkb, xkbevent.core.xkey.keycode, xkbevent.core.xkey.state, &tmpmods, &keysym) == False )
425 matty 9 break;
426 n-ki 52 scancode = xkeymap_translate_key(keysym, xkbevent.core.xkey.keycode, &flags);
427 matty 9
428 n-ki 52 if (scancode == 0 )
429     break;
430    
431     /* keep track of the modifiers -- needed for stickykeys... */
432     if( xkbevent.type == KeyPress )
433     xwin_press_modifiers( &xkbevent.core.xkey, ev_time, scancode );
434    
435 matthewc 50 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, flags, scancode, 0);
436 n-ki 52
437     if( xkbevent.type == KeyRelease )
438     xwin_release_modifiers( &xkbevent.core.xkey, ev_time, scancode );
439    
440 matty 9 break;
441    
442     case ButtonPress:
443 matthewc 50 flags = MOUSE_FLAG_DOWN;
444     /* fall through */
445 matty 9
446     case ButtonRelease:
447 n-ki 52 button = xkeymap_translate_button(xkbevent.core.xbutton.button);
448 matty 9 if (button == 0)
449     break;
450    
451 matty 10 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
452 matthewc 50 flags | button,
453 n-ki 52 xkbevent.core.xbutton.x,
454     xkbevent.core.xbutton.y);
455 matty 10 break;
456    
457     case MotionNotify:
458     rdp_send_input(ev_time, RDP_INPUT_MOUSE,
459 matty 24 MOUSE_FLAG_MOVE,
460 n-ki 52 xkbevent.core.xmotion.x,
461     xkbevent.core.xmotion.y);
462 matty 28 break;
463    
464     case EnterNotify:
465 matty 29 XGrabKeyboard(display, wnd, True, GrabModeAsync,
466     GrabModeAsync, CurrentTime);
467 matty 28 break;
468    
469     case LeaveNotify:
470 matty 29 XUngrabKeyboard(display, CurrentTime);
471 matty 28 break;
472 matty 31
473     case Expose:
474     XCopyArea(display, backstore, wnd, gc,
475 n-ki 52 xkbevent.core.xexpose.x, xkbevent.core.xexpose.y,
476     xkbevent.core.xexpose.width, xkbevent.core.xexpose.height,
477     xkbevent.core.xexpose.x, xkbevent.core.xexpose.y);
478 matty 31 break;
479 matty 9 }
480     }
481     }
482    
483 matty 25 void
484 n-ki 52 xwin_release_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode)
485     {
486     switch (scancode) {
487     case 0x2a:
488     key_down_state &= ~DShift1Mask;
489     break;
490     case 0x36:
491     key_down_state &= ~DShift2Mask;
492     break;
493     case 0x1d:
494     key_down_state &= ~DControl1Mask;
495     break;
496     case 0x9d:
497     key_down_state &= ~DControl2Mask;
498     break;
499     case 0x38:
500     key_down_state &= ~DMod1Mask;
501     break;
502     case 0xb8:
503     key_down_state &= ~DMod2Mask;
504     break;
505     }
506    
507     if( !(ShiftMask & ev->state) && (key_down_state & DShift1Mask))
508     {
509     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a, 0);
510     key_down_state &= ~DShift1Mask;
511    
512     }
513    
514     if( !(ControlMask & ev->state) && (key_down_state & DControl1Mask))
515     {
516     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d, 0);
517     key_down_state &= ~DControl1Mask;
518    
519     }
520    
521     if( !(Mod1Mask & ev->state) && (key_down_state & DMod1Mask))
522     {
523     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38, 0);
524     key_down_state &= ~DMod1Mask;
525    
526     }
527    
528     if( !(Mod2Mask & ev->state) && (key_down_state & DMod2Mask))
529     {
530     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8, 0);
531     key_down_state &= ~DMod2Mask;
532     }
533     }
534    
535    
536     void
537     xwin_press_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode)
538     {
539     key_modifier_state = ev->state;
540    
541     switch (scancode) {
542     case 0x2a:
543     key_down_state |= DShift1Mask;
544     break;
545     case 0x36:
546     key_down_state |= DShift2Mask;
547     break;
548     case 0x1d:
549     key_down_state |= DControl1Mask;
550     break;
551     case 0x9d:
552     key_down_state |= DControl2Mask;
553     break;
554     case 0x38:
555     key_down_state |= DMod1Mask;
556     break;
557     case 0xb8:
558     key_down_state |= DMod2Mask;
559     break;
560     }
561    
562     if( (ShiftMask & ev->state) && !((key_down_state & DShift1Mask) || (key_down_state & DShift2Mask)))
563     {
564     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x2a, 0);
565     key_down_state |= DShift1Mask;
566    
567     }
568    
569     if( (ControlMask & ev->state) && !((key_down_state & DControl1Mask) || (key_down_state & DControl2Mask)))
570     {
571     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x1d, 0);
572     key_down_state |= DControl1Mask;
573    
574     }
575    
576     if( (Mod1Mask & ev->state) && !(key_down_state & DMod1Mask))
577     {
578     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x38, 0);
579     key_down_state |= DMod1Mask;
580    
581     }
582    
583     if( (Mod2Mask & ev->state) && !(key_down_state & DMod2Mask))
584     {
585     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0xb8, 0);
586     key_down_state |= DMod2Mask;
587    
588     }
589     }
590    
591     void
592 matty 33 ui_select(int rdp_socket)
593     {
594     int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;
595     fd_set rfds;
596    
597     XFlush(display);
598    
599     FD_ZERO(&rfds);
600    
601     while (True)
602     {
603     FD_ZERO(&rfds);
604     FD_SET(rdp_socket, &rfds);
605     FD_SET(x_socket, &rfds);
606    
607     switch (select(n, &rfds, NULL, NULL, NULL))
608     {
609     case -1:
610     error("select: %s\n", strerror(errno));
611    
612     case 0:
613     continue;
614     }
615    
616     if (FD_ISSET(x_socket, &rfds))
617     xwin_process_events();
618    
619     if (FD_ISSET(rdp_socket, &rfds))
620     return;
621     }
622     }
623    
624     void
625 matty 25 ui_move_pointer(int x, int y)
626 matty 9 {
627 matty 10 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
628 matty 9 }
629    
630 matty 25 HBITMAP
631     ui_create_bitmap(int width, int height, uint8 *data)
632 matty 6 {
633     XImage *image;
634 matty 9 Pixmap bitmap;
635 matty 28 uint8 *tdata;
636 matty 29
637 matty 33 tdata = (owncolmap ? data : translate_image(width, height, data));
638 matty 28 bitmap = XCreatePixmap(display, wnd, width, height, depth);
639 matty 29 image = XCreateImage(display, visual, depth, ZPixmap,
640     0, tdata, width, height, 8, 0);
641 matty 6
642 matty 28 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
643 matty 9
644     XFree(image);
645 matty 29 if (!owncolmap)
646 matty 28 xfree(tdata);
647 matty 24 return (HBITMAP) bitmap;
648 matty 6 }
649    
650 matty 25 void
651     ui_paint_bitmap(int x, int y, int cx, int cy,
652     int width, int height, uint8 *data)
653 matty 6 {
654 matty 10 XImage *image;
655 matty 29 uint8 *tdata;
656 matty 10
657 matty 33 tdata = (owncolmap ? data : translate_image(width, height, data));
658 matty 29 image = XCreateImage(display, visual, depth, ZPixmap,
659     0, tdata, width, height, 8, 0);
660 matty 28
661 matty 31 if (ownbackstore)
662     {
663     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
664     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
665     }
666     else
667     {
668     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
669     }
670 matty 29
671 matty 24 XFree(image);
672 matty 29 if (!owncolmap)
673 matty 28 xfree(tdata);
674 matty 6 }
675    
676 matty 25 void
677     ui_destroy_bitmap(HBITMAP bmp)
678 matty 6 {
679 matty 29 XFreePixmap(display, (Pixmap)bmp);
680 matty 10 }
681    
682 matty 25 HGLYPH
683     ui_create_glyph(int width, int height, uint8 *data)
684 matty 10 {
685 matty 9 XImage *image;
686     Pixmap bitmap;
687     int scanline;
688     GC gc;
689 matty 6
690 matty 9 scanline = (width + 7) / 8;
691 matty 6
692 matty 10 bitmap = XCreatePixmap(display, wnd, width, height, 1);
693     gc = XCreateGC(display, bitmap, 0, NULL);
694 matty 9
695 matty 10 image = XCreateImage(display, visual, 1, ZPixmap, 0,
696 matty 24 data, width, height, 8, scanline);
697 matty 23 image->byte_order = MSBFirst;
698     image->bitmap_bit_order = MSBFirst;
699     XInitImage(image);
700    
701 matty 10 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
702 matty 29
703 matty 9 XFree(image);
704 matty 10 XFreeGC(display, gc);
705 matty 29 return (HGLYPH)bitmap;
706 matty 6 }
707 matty 7
708 matty 25 void
709     ui_destroy_glyph(HGLYPH glyph)
710 matty 7 {
711 matty 29 XFreePixmap(display, (Pixmap)glyph);
712 matty 9 }
713    
714 matty 29 HCURSOR
715     ui_create_cursor(unsigned int x, unsigned int y, int width,
716     int height, uint8 *andmask, uint8 *xormask)
717 matty 9 {
718 matty 29 HGLYPH maskglyph, cursorglyph;
719     XColor bg, fg;
720     Cursor xcursor;
721     uint8 *cursor, *pcursor;
722     uint8 *mask, *pmask;
723     uint8 nextbit;
724     int scanline, offset;
725     int i, j;
726    
727     scanline = (width + 7) / 8;
728     offset = scanline * height;
729    
730     cursor = xmalloc(offset);
731     memset(cursor, 0, offset);
732    
733     mask = xmalloc(offset);
734     memset(mask, 0, offset);
735    
736     /* approximate AND and XOR masks with a monochrome X pointer */
737     for (i = 0; i < height; i++)
738 matty 7 {
739 matty 29 offset -= scanline;
740     pcursor = &cursor[offset];
741     pmask = &mask[offset];
742    
743     for (j = 0; j < scanline; j++)
744 matty 28 {
745 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
746     {
747     if (xormask[0] || xormask[1] || xormask[2])
748     {
749     *pcursor |= (~(*andmask) & nextbit);
750     *pmask |= nextbit;
751     }
752     else
753     {
754     *pcursor |= ((*andmask) & nextbit);
755     *pmask |= (~(*andmask) & nextbit);
756     }
757    
758     xormask += 3;
759     }
760    
761     andmask++;
762     pcursor++;
763     pmask++;
764 matty 28 }
765 matty 7 }
766 matty 29
767     fg.red = fg.blue = fg.green = 0xffff;
768     bg.red = bg.blue = bg.green = 0x0000;
769     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
770    
771     cursorglyph = ui_create_glyph(width, height, cursor);
772     maskglyph = ui_create_glyph(width, height, mask);
773    
774     xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,
775     (Pixmap)maskglyph, &fg, &bg, x, y);
776    
777     ui_destroy_glyph(maskglyph);
778     ui_destroy_glyph(cursorglyph);
779     xfree(mask);
780     xfree(cursor);
781     return (HCURSOR)xcursor;
782     }
783    
784     void
785     ui_set_cursor(HCURSOR cursor)
786     {
787     XDefineCursor(display, wnd, (Cursor)cursor);
788     }
789    
790     void
791     ui_destroy_cursor(HCURSOR cursor)
792     {
793     XFreeCursor(display, (Cursor)cursor);
794     }
795    
796     #define MAKE_XCOLOR(xc,c) \
797     (xc)->red = ((c)->red << 8) | (c)->red; \
798     (xc)->green = ((c)->green << 8) | (c)->green; \
799     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
800     (xc)->flags = DoRed | DoGreen | DoBlue;
801    
802     HCOLOURMAP
803     ui_create_colourmap(COLOURMAP *colours)
804     {
805     COLOURENTRY *entry;
806     int i, ncolours = colours->ncolours;
807    
808     if (owncolmap)
809 matty 28 {
810     XColor *xcolours, *xentry;
811     Colormap map;
812 matty 29
813 matty 28 xcolours = xmalloc(sizeof(XColor) * ncolours);
814     for (i = 0; i < ncolours; i++)
815     {
816     entry = &colours->colours[i];
817     xentry = &xcolours[i];
818     xentry->pixel = i;
819 matty 29 MAKE_XCOLOR(xentry, entry);
820 matty 28 }
821 matty 7
822 matty 28 map = XCreateColormap(display, wnd, visual, AllocAll);
823     XStoreColors(display, map, xcolours, ncolours);
824    
825     xfree(xcolours);
826 matty 29 return (HCOLOURMAP)map;
827 matty 28 }
828 matty 29 else
829     {
830     uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
831     XColor xentry;
832 matty 33 uint32 colour;
833 matty 29
834     for (i = 0; i < ncolours; i++)
835     {
836     entry = &colours->colours[i];
837     MAKE_XCOLOR(&xentry, entry);
838    
839     if (XAllocColor(display, xcolmap, &xentry) != 0)
840 matty 34 colour = xentry.pixel;
841 matty 29 else
842 matty 34 colour = white;
843 matty 33
844     /* byte swap here to make translate_image faster */
845     map[i] = translate_colour(colour);
846 matty 29 }
847    
848     return map;
849     }
850 matty 7 }
851    
852 matty 25 void
853     ui_destroy_colourmap(HCOLOURMAP map)
854 matty 7 {
855 matty 29 if (owncolmap)
856     XFreeColormap(display, (Colormap)map);
857     else
858     xfree(map);
859 matty 7 }
860    
861 matty 25 void
862     ui_set_colourmap(HCOLOURMAP map)
863 matty 7 {
864 matty 29 if (owncolmap)
865     XSetWindowColormap(display, wnd, (Colormap)map);
866     else
867 matty 28 colmap = map;
868 matty 7 }
869    
870 matty 25 void
871     ui_set_clip(int x, int y, int cx, int cy)
872 matty 7 {
873 matty 9 XRectangle rect;
874 matty 7
875 matty 9 rect.x = x;
876     rect.y = y;
877     rect.width = cx;
878     rect.height = cy;
879 matty 10 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
880 matty 9 }
881 matty 7
882 matty 25 void
883     ui_reset_clip()
884 matty 9 {
885     XRectangle rect;
886    
887     rect.x = 0;
888     rect.y = 0;
889 matty 10 rect.width = width;
890     rect.height = height;
891     XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
892 matty 7 }
893    
894 matty 25 void
895     ui_bell()
896 matty 10 {
897     XBell(display, 0);
898     }
899    
900 matty 25 void
901     ui_destblt(uint8 opcode,
902     /* dest */ int x, int y, int cx, int cy)
903 matty 9 {
904 matty 29 SET_FUNCTION(opcode);
905 matty 31 FILL_RECTANGLE(x, y, cx, cy);
906 matty 29 RESET_FUNCTION(opcode);
907 matty 9 }
908    
909 matty 25 void
910     ui_patblt(uint8 opcode,
911     /* dest */ int x, int y, int cx, int cy,
912     /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
913 matty 9 {
914     Pixmap fill;
915    
916 matty 29 SET_FUNCTION(opcode);
917 matty 9
918     switch (brush->style)
919     {
920 matty 24 case 0: /* Solid */
921 matty 29 SET_FOREGROUND(fgcolour);
922 matty 31 FILL_RECTANGLE(x, y, cx, cy);
923 matty 9 break;
924    
925 matty 24 case 3: /* Pattern */
926 matty 29 fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);
927 matty 9
928 matty 29 SET_FOREGROUND(bgcolour);
929     SET_BACKGROUND(fgcolour);
930     XSetFillStyle(display, gc, FillOpaqueStippled);
931     XSetStipple(display, gc, fill);
932     XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
933 matty 9
934 matty 31 FILL_RECTANGLE(x, y, cx, cy);
935 matty 9
936 matty 29 XSetFillStyle(display, gc, FillSolid);
937     ui_destroy_glyph((HGLYPH)fill);
938 matty 9 break;
939    
940     default:
941 matty 30 unimpl("brush %d\n", brush->style);
942 matty 9 }
943 matty 29
944     RESET_FUNCTION(opcode);
945 matty 9 }
946    
947 matty 25 void
948     ui_screenblt(uint8 opcode,
949     /* dest */ int x, int y, int cx, int cy,
950     /* src */ int srcx, int srcy)
951 matty 9 {
952 matty 29 SET_FUNCTION(opcode);
953 matty 24 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
954 matty 31 if (ownbackstore)
955     XCopyArea(display, backstore, backstore, gc, srcx, srcy,
956     cx, cy, x, y);
957 matty 29 RESET_FUNCTION(opcode);
958 matty 9 }
959    
960 matty 25 void
961     ui_memblt(uint8 opcode,
962     /* dest */ int x, int y, int cx, int cy,
963     /* src */ HBITMAP src, int srcx, int srcy)
964 matty 9 {
965 matty 29 SET_FUNCTION(opcode);
966     XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);
967 matty 31 if (ownbackstore)
968     XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,
969     cx, cy, x, y);
970 matty 29 RESET_FUNCTION(opcode);
971 matty 9 }
972    
973 matty 25 void
974     ui_triblt(uint8 opcode,
975     /* dest */ int x, int y, int cx, int cy,
976     /* src */ HBITMAP src, int srcx, int srcy,
977     /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
978 matty 9 {
979     /* This is potentially difficult to do in general. Until someone
980 matty 10 comes up with a more efficient way of doing it I am using cases. */
981 matty 9
982     switch (opcode)
983     {
984 matty 24 case 0x69: /* PDSxxn */
985 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
986     ui_patblt(ROP2_NXOR, x, y, cx, cy,
987 matty 24 brush, bgcolour, fgcolour);
988 matty 16 break;
989    
990 matty 24 case 0xb8: /* PSDPxax */
991 matty 10 ui_patblt(ROP2_XOR, x, y, cx, cy,
992 matty 24 brush, bgcolour, fgcolour);
993 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
994 matty 10 ui_patblt(ROP2_XOR, x, y, cx, cy,
995 matty 24 brush, bgcolour, fgcolour);
996 matty 9 break;
997    
998 matty 29 case 0xc0: /* PSa */
999 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1000     ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
1001     fgcolour);
1002     break;
1003    
1004 matty 9 default:
1005 matty 30 unimpl("triblt 0x%x\n", opcode);
1006 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1007 matty 9 }
1008     }
1009    
1010 matty 25 void
1011     ui_line(uint8 opcode,
1012     /* dest */ int startx, int starty, int endx, int endy,
1013     /* pen */ PEN *pen)
1014 matty 9 {
1015 matty 29 SET_FUNCTION(opcode);
1016     SET_FOREGROUND(pen->colour);
1017 matty 10 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1018 matty 31 if (ownbackstore)
1019     XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1020 matty 29 RESET_FUNCTION(opcode);
1021 matty 9 }
1022    
1023 matty 25 void
1024     ui_rect(
1025     /* dest */ int x, int y, int cx, int cy,
1026     /* brush */ int colour)
1027 matty 9 {
1028 matty 29 SET_FOREGROUND(colour);
1029 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1030 matty 9 }
1031    
1032 matty 25 void
1033     ui_draw_glyph(int mixmode,
1034     /* dest */ int x, int y, int cx, int cy,
1035     /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,
1036     int fgcolour)
1037 matty 9 {
1038 matty 29 SET_FOREGROUND(fgcolour);
1039     SET_BACKGROUND(bgcolour);
1040 matty 9
1041 matty 29 XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)
1042     ? FillStippled : FillOpaqueStippled);
1043     XSetStipple(display, gc, (Pixmap)glyph);
1044     XSetTSOrigin(display, gc, x, y);
1045 matty 9
1046 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1047 matty 9
1048 matty 29 XSetFillStyle(display, gc, FillSolid);
1049 matty 9 }
1050    
1051 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1052     {\
1053     glyph = cache_get_font (font, ttext[idx]);\
1054     if (!(flags & TEXT2_IMPLICIT_X))\
1055     {\
1056     xyoffset = ttext[++idx];\
1057     if ((xyoffset & 0x80))\
1058     {\
1059     if (flags & TEXT2_VERTICAL) \
1060     y += ttext[++idx] | (ttext[++idx] << 8);\
1061     else\
1062     x += ttext[++idx] | (ttext[++idx] << 8);\
1063     }\
1064     else\
1065     {\
1066     if (flags & TEXT2_VERTICAL) \
1067     y += xyoffset;\
1068     else\
1069     x += xyoffset;\
1070     }\
1071     }\
1072     if (glyph != NULL)\
1073     {\
1074     ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1075     y + (short) glyph->baseline,\
1076     glyph->width, glyph->height,\
1077     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1078     if (flags & TEXT2_IMPLICIT_X)\
1079     x += glyph->width;\
1080     }\
1081     }
1082    
1083 matty 25 void
1084     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1085 mmihalik 49 int clipx, int clipy, int clipcx, int clipcy, int boxx,
1086     int boxy, int boxcx, int boxcy, int bgcolour,
1087     int fgcolour, uint8 * text, uint8 length)
1088 matty 9 {
1089 matty 10 FONTGLYPH *glyph;
1090 mmihalik 49 int i, j, xyoffset;
1091     DATABLOB *entry;
1092 matty 9
1093 matty 29 SET_FOREGROUND(bgcolour);
1094 matty 28
1095 matty 9 if (boxcx > 1)
1096 matty 31 {
1097     FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1098     }
1099 matty 17 else if (mixmode == MIX_OPAQUE)
1100 matty 31 {
1101     FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1102     }
1103 matty 9
1104     /* Paint text, character by character */
1105 mmihalik 49 for (i = 0; i < length;) {
1106     switch (text[i]) {
1107     case 0xff:
1108     if (i + 2 < length)
1109     cache_put_text(text[i + 1], text, text[i + 2]);
1110     else {
1111     error("this shouldn't be happening\n");
1112     break;
1113     }
1114     /* this will move pointer from start to first character after FF command */
1115     length -= i + 3;
1116     text = &(text[i + 3]);
1117     i = 0;
1118     break;
1119 matty 9
1120 mmihalik 49 case 0xfe:
1121     entry = cache_get_text(text[i + 1]);
1122     if (entry != NULL) {
1123     if ((((uint8 *) (entry->data))[1] == 0)
1124     && (!(flags & TEXT2_IMPLICIT_X))) {
1125 n-ki 52 if (flags & TEXT2_VERTICAL)
1126 mmihalik 49 y += text[i + 2];
1127     else
1128     x += text[i + 2];
1129 matthewc 44 }
1130 mmihalik 49 if (i + 2 < length)
1131     i += 3;
1132 matthewc 44 else
1133 mmihalik 49 i += 2;
1134 n-ki 52 length -= i;
1135 mmihalik 49 /* this will move pointer from start to first character after FE command */
1136     text = &(text[i]);
1137     i = 0;
1138     for (j = 0; j < entry->size; j++)
1139     DO_GLYPH(((uint8 *) (entry->data)), j);
1140 matthewc 44 }
1141 mmihalik 49 break;
1142 matty 17
1143 mmihalik 49 default:
1144     DO_GLYPH(text, i);
1145     i++;
1146     break;
1147 matty 29 }
1148 mmihalik 49 }
1149 matty 28
1150 matty 9
1151     }
1152    
1153 matty 25 void
1154     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1155 matty 9 {
1156 matty 28 Pixmap pix;
1157 matty 9 XImage *image;
1158    
1159 matty 31 if (ownbackstore)
1160     {
1161     image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
1162     ZPixmap);
1163     }
1164     else
1165     {
1166     pix = XCreatePixmap(display, wnd, cx, cy, depth);
1167     XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1168     image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,
1169     ZPixmap);
1170     XFreePixmap(display, pix);
1171     }
1172 matty 28
1173     offset *= bpp/8;
1174     cache_put_desktop(offset, cx, cy, image->bytes_per_line,
1175 matty 36 bpp/8, (uint8 *)image->data);
1176 matty 28
1177     XDestroyImage(image);
1178 matty 9 }
1179    
1180 matty 25 void
1181     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1182 matty 9 {
1183     XImage *image;
1184 matty 10 uint8 *data;
1185 matty 9
1186 matty 28 offset *= bpp/8;
1187     data = cache_get_desktop(offset, cx, cy, bpp/8);
1188 matty 10 if (data == NULL)
1189     return;
1190 matty 29
1191     image = XCreateImage(display, visual, depth, ZPixmap,
1192 matty 28 0, data, cx, cy, BitmapPad(display),
1193     cx * bpp/8);
1194 matty 29
1195 matty 31 if (ownbackstore)
1196     {
1197     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1198     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1199     }
1200     else
1201     {
1202     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1203     }
1204    
1205 matty 9 XFree(image);
1206     }

  ViewVC Help
Powered by ViewVC 1.1.26