/[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 53 - (hide annotations)
Tue May 28 11:48:55 2002 UTC (21 years, 11 months ago) by matthewc
File MIME type: text/plain
File size: 26873 byte(s)
Revert to old behaviour of connecting before creating the UI.
This is to stop the UI generating input before the connection is complete
(which causes connection failures).  The one difficulty is that ui_select
is now called before ui_create_window, which may cause problems for other
UIs - we may still need to change this in the future.

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 n-ki 52 while (XCheckMaskEvent(display, ~0, &xkbevent.core))
401 matty 9 {
402 matty 10 ev_time = time(NULL);
403 matthewc 50 flags = 0;
404 matty 10
405 n-ki 52 switch (xkbevent.type)
406 matty 9 {
407 n-ki 52 case KeymapNotify:
408     /* TODO:
409     * read modifier status at focus in, and update the local masks, and the other end as well..
410     * if not, we may get out of sync.
411     * xkbevent.core.xkeymap.key_vector
412     * char key_vector[32];
413     */
414     break;
415    
416 matthewc 50 case KeyRelease:
417     flags = KBD_FLAG_DOWN | KBD_FLAG_UP;
418     /* fall through */
419    
420 matty 9 case KeyPress:
421 n-ki 52 if( XkbTranslateKeyCode(xkb, xkbevent.core.xkey.keycode, xkbevent.core.xkey.state, &tmpmods, &keysym) == False )
422 matty 9 break;
423 n-ki 52 scancode = xkeymap_translate_key(keysym, xkbevent.core.xkey.keycode, &flags);
424 matty 9
425 n-ki 52 if (scancode == 0 )
426     break;
427    
428     /* keep track of the modifiers -- needed for stickykeys... */
429     if( xkbevent.type == KeyPress )
430     xwin_press_modifiers( &xkbevent.core.xkey, ev_time, scancode );
431    
432 matthewc 50 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, flags, scancode, 0);
433 n-ki 52
434     if( xkbevent.type == KeyRelease )
435     xwin_release_modifiers( &xkbevent.core.xkey, ev_time, scancode );
436    
437 matty 9 break;
438    
439     case ButtonPress:
440 matthewc 50 flags = MOUSE_FLAG_DOWN;
441     /* fall through */
442 matty 9
443     case ButtonRelease:
444 n-ki 52 button = xkeymap_translate_button(xkbevent.core.xbutton.button);
445 matty 9 if (button == 0)
446     break;
447    
448 matty 10 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
449 matthewc 50 flags | button,
450 n-ki 52 xkbevent.core.xbutton.x,
451     xkbevent.core.xbutton.y);
452 matty 10 break;
453    
454     case MotionNotify:
455     rdp_send_input(ev_time, RDP_INPUT_MOUSE,
456 matty 24 MOUSE_FLAG_MOVE,
457 n-ki 52 xkbevent.core.xmotion.x,
458     xkbevent.core.xmotion.y);
459 matty 28 break;
460    
461     case EnterNotify:
462 matty 29 XGrabKeyboard(display, wnd, True, GrabModeAsync,
463     GrabModeAsync, CurrentTime);
464 matty 28 break;
465    
466     case LeaveNotify:
467 matty 29 XUngrabKeyboard(display, CurrentTime);
468 matty 28 break;
469 matty 31
470     case Expose:
471     XCopyArea(display, backstore, wnd, gc,
472 n-ki 52 xkbevent.core.xexpose.x, xkbevent.core.xexpose.y,
473     xkbevent.core.xexpose.width, xkbevent.core.xexpose.height,
474     xkbevent.core.xexpose.x, xkbevent.core.xexpose.y);
475 matty 31 break;
476 matty 9 }
477     }
478     }
479    
480 matty 25 void
481 n-ki 52 xwin_release_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode)
482     {
483     switch (scancode) {
484     case 0x2a:
485     key_down_state &= ~DShift1Mask;
486     break;
487     case 0x36:
488     key_down_state &= ~DShift2Mask;
489     break;
490     case 0x1d:
491     key_down_state &= ~DControl1Mask;
492     break;
493     case 0x9d:
494     key_down_state &= ~DControl2Mask;
495     break;
496     case 0x38:
497     key_down_state &= ~DMod1Mask;
498     break;
499     case 0xb8:
500     key_down_state &= ~DMod2Mask;
501     break;
502     }
503    
504     if( !(ShiftMask & ev->state) && (key_down_state & DShift1Mask))
505     {
506     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x2a, 0);
507     key_down_state &= ~DShift1Mask;
508    
509     }
510    
511     if( !(ControlMask & ev->state) && (key_down_state & DControl1Mask))
512     {
513     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x1d, 0);
514     key_down_state &= ~DControl1Mask;
515    
516     }
517    
518     if( !(Mod1Mask & ev->state) && (key_down_state & DMod1Mask))
519     {
520     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0x38, 0);
521     key_down_state &= ~DMod1Mask;
522    
523     }
524    
525     if( !(Mod2Mask & ev->state) && (key_down_state & DMod2Mask))
526     {
527     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_UP, 0xb8, 0);
528     key_down_state &= ~DMod2Mask;
529     }
530     }
531    
532    
533     void
534     xwin_press_modifiers(XKeyEvent* ev, uint32 ev_time, uint32 scancode)
535     {
536     key_modifier_state = ev->state;
537    
538     switch (scancode) {
539     case 0x2a:
540     key_down_state |= DShift1Mask;
541     break;
542     case 0x36:
543     key_down_state |= DShift2Mask;
544     break;
545     case 0x1d:
546     key_down_state |= DControl1Mask;
547     break;
548     case 0x9d:
549     key_down_state |= DControl2Mask;
550     break;
551     case 0x38:
552     key_down_state |= DMod1Mask;
553     break;
554     case 0xb8:
555     key_down_state |= DMod2Mask;
556     break;
557     }
558    
559     if( (ShiftMask & ev->state) && !((key_down_state & DShift1Mask) || (key_down_state & DShift2Mask)))
560     {
561     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x2a, 0);
562     key_down_state |= DShift1Mask;
563    
564     }
565    
566     if( (ControlMask & ev->state) && !((key_down_state & DControl1Mask) || (key_down_state & DControl2Mask)))
567     {
568     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x1d, 0);
569     key_down_state |= DControl1Mask;
570    
571     }
572    
573     if( (Mod1Mask & ev->state) && !(key_down_state & DMod1Mask))
574     {
575     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0x38, 0);
576     key_down_state |= DMod1Mask;
577    
578     }
579    
580     if( (Mod2Mask & ev->state) && !(key_down_state & DMod2Mask))
581     {
582     rdp_send_input(ev_time, RDP_INPUT_SCANCODE, KBD_FLAG_DOWN, 0xb8, 0);
583     key_down_state |= DMod2Mask;
584    
585     }
586     }
587    
588     void
589 matty 33 ui_select(int rdp_socket)
590     {
591     int n = (rdp_socket > x_socket) ? rdp_socket+1 : x_socket+1;
592     fd_set rfds;
593    
594     FD_ZERO(&rfds);
595    
596     while (True)
597     {
598     FD_ZERO(&rfds);
599     FD_SET(rdp_socket, &rfds);
600 matthewc 53 if (display != NULL)
601     {
602     FD_SET(x_socket, &rfds);
603     XFlush(display);
604     }
605 matty 33
606     switch (select(n, &rfds, NULL, NULL, NULL))
607     {
608     case -1:
609     error("select: %s\n", strerror(errno));
610    
611     case 0:
612     continue;
613     }
614    
615     if (FD_ISSET(x_socket, &rfds))
616     xwin_process_events();
617    
618     if (FD_ISSET(rdp_socket, &rfds))
619     return;
620     }
621     }
622    
623     void
624 matty 25 ui_move_pointer(int x, int y)
625 matty 9 {
626 matty 10 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
627 matty 9 }
628    
629 matty 25 HBITMAP
630     ui_create_bitmap(int width, int height, uint8 *data)
631 matty 6 {
632     XImage *image;
633 matty 9 Pixmap bitmap;
634 matty 28 uint8 *tdata;
635 matty 29
636 matty 33 tdata = (owncolmap ? data : translate_image(width, height, data));
637 matty 28 bitmap = XCreatePixmap(display, wnd, width, height, depth);
638 matty 29 image = XCreateImage(display, visual, depth, ZPixmap,
639     0, tdata, width, height, 8, 0);
640 matty 6
641 matty 28 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
642 matty 9
643     XFree(image);
644 matty 29 if (!owncolmap)
645 matty 28 xfree(tdata);
646 matty 24 return (HBITMAP) bitmap;
647 matty 6 }
648    
649 matty 25 void
650     ui_paint_bitmap(int x, int y, int cx, int cy,
651     int width, int height, uint8 *data)
652 matty 6 {
653 matty 10 XImage *image;
654 matty 29 uint8 *tdata;
655 matty 10
656 matty 33 tdata = (owncolmap ? data : translate_image(width, height, data));
657 matty 29 image = XCreateImage(display, visual, depth, ZPixmap,
658     0, tdata, width, height, 8, 0);
659 matty 28
660 matty 31 if (ownbackstore)
661     {
662     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
663     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
664     }
665     else
666     {
667     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
668     }
669 matty 29
670 matty 24 XFree(image);
671 matty 29 if (!owncolmap)
672 matty 28 xfree(tdata);
673 matty 6 }
674    
675 matty 25 void
676     ui_destroy_bitmap(HBITMAP bmp)
677 matty 6 {
678 matty 29 XFreePixmap(display, (Pixmap)bmp);
679 matty 10 }
680    
681 matty 25 HGLYPH
682     ui_create_glyph(int width, int height, uint8 *data)
683 matty 10 {
684 matty 9 XImage *image;
685     Pixmap bitmap;
686     int scanline;
687     GC gc;
688 matty 6
689 matty 9 scanline = (width + 7) / 8;
690 matty 6
691 matty 10 bitmap = XCreatePixmap(display, wnd, width, height, 1);
692     gc = XCreateGC(display, bitmap, 0, NULL);
693 matty 9
694 matty 10 image = XCreateImage(display, visual, 1, ZPixmap, 0,
695 matty 24 data, width, height, 8, scanline);
696 matty 23 image->byte_order = MSBFirst;
697     image->bitmap_bit_order = MSBFirst;
698     XInitImage(image);
699    
700 matty 10 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
701 matty 29
702 matty 9 XFree(image);
703 matty 10 XFreeGC(display, gc);
704 matty 29 return (HGLYPH)bitmap;
705 matty 6 }
706 matty 7
707 matty 25 void
708     ui_destroy_glyph(HGLYPH glyph)
709 matty 7 {
710 matty 29 XFreePixmap(display, (Pixmap)glyph);
711 matty 9 }
712    
713 matty 29 HCURSOR
714     ui_create_cursor(unsigned int x, unsigned int y, int width,
715     int height, uint8 *andmask, uint8 *xormask)
716 matty 9 {
717 matty 29 HGLYPH maskglyph, cursorglyph;
718     XColor bg, fg;
719     Cursor xcursor;
720     uint8 *cursor, *pcursor;
721     uint8 *mask, *pmask;
722     uint8 nextbit;
723     int scanline, offset;
724     int i, j;
725    
726     scanline = (width + 7) / 8;
727     offset = scanline * height;
728    
729     cursor = xmalloc(offset);
730     memset(cursor, 0, offset);
731    
732     mask = xmalloc(offset);
733     memset(mask, 0, offset);
734    
735     /* approximate AND and XOR masks with a monochrome X pointer */
736     for (i = 0; i < height; i++)
737 matty 7 {
738 matty 29 offset -= scanline;
739     pcursor = &cursor[offset];
740     pmask = &mask[offset];
741    
742     for (j = 0; j < scanline; j++)
743 matty 28 {
744 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
745     {
746     if (xormask[0] || xormask[1] || xormask[2])
747     {
748     *pcursor |= (~(*andmask) & nextbit);
749     *pmask |= nextbit;
750     }
751     else
752     {
753     *pcursor |= ((*andmask) & nextbit);
754     *pmask |= (~(*andmask) & nextbit);
755     }
756    
757     xormask += 3;
758     }
759    
760     andmask++;
761     pcursor++;
762     pmask++;
763 matty 28 }
764 matty 7 }
765 matty 29
766     fg.red = fg.blue = fg.green = 0xffff;
767     bg.red = bg.blue = bg.green = 0x0000;
768     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
769    
770     cursorglyph = ui_create_glyph(width, height, cursor);
771     maskglyph = ui_create_glyph(width, height, mask);
772    
773     xcursor = XCreatePixmapCursor(display, (Pixmap)cursorglyph,
774     (Pixmap)maskglyph, &fg, &bg, x, y);
775    
776     ui_destroy_glyph(maskglyph);
777     ui_destroy_glyph(cursorglyph);
778     xfree(mask);
779     xfree(cursor);
780     return (HCURSOR)xcursor;
781     }
782    
783     void
784     ui_set_cursor(HCURSOR cursor)
785     {
786     XDefineCursor(display, wnd, (Cursor)cursor);
787     }
788    
789     void
790     ui_destroy_cursor(HCURSOR cursor)
791     {
792     XFreeCursor(display, (Cursor)cursor);
793     }
794    
795     #define MAKE_XCOLOR(xc,c) \
796     (xc)->red = ((c)->red << 8) | (c)->red; \
797     (xc)->green = ((c)->green << 8) | (c)->green; \
798     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
799     (xc)->flags = DoRed | DoGreen | DoBlue;
800    
801     HCOLOURMAP
802     ui_create_colourmap(COLOURMAP *colours)
803     {
804     COLOURENTRY *entry;
805     int i, ncolours = colours->ncolours;
806    
807     if (owncolmap)
808 matty 28 {
809     XColor *xcolours, *xentry;
810     Colormap map;
811 matty 29
812 matty 28 xcolours = xmalloc(sizeof(XColor) * ncolours);
813     for (i = 0; i < ncolours; i++)
814     {
815     entry = &colours->colours[i];
816     xentry = &xcolours[i];
817     xentry->pixel = i;
818 matty 29 MAKE_XCOLOR(xentry, entry);
819 matty 28 }
820 matty 7
821 matty 28 map = XCreateColormap(display, wnd, visual, AllocAll);
822     XStoreColors(display, map, xcolours, ncolours);
823    
824     xfree(xcolours);
825 matty 29 return (HCOLOURMAP)map;
826 matty 28 }
827 matty 29 else
828     {
829     uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
830     XColor xentry;
831 matty 33 uint32 colour;
832 matty 29
833     for (i = 0; i < ncolours; i++)
834     {
835     entry = &colours->colours[i];
836     MAKE_XCOLOR(&xentry, entry);
837    
838     if (XAllocColor(display, xcolmap, &xentry) != 0)
839 matty 34 colour = xentry.pixel;
840 matty 29 else
841 matty 34 colour = white;
842 matty 33
843     /* byte swap here to make translate_image faster */
844     map[i] = translate_colour(colour);
845 matty 29 }
846    
847     return map;
848     }
849 matty 7 }
850    
851 matty 25 void
852     ui_destroy_colourmap(HCOLOURMAP map)
853 matty 7 {
854 matty 29 if (owncolmap)
855     XFreeColormap(display, (Colormap)map);
856     else
857     xfree(map);
858 matty 7 }
859    
860 matty 25 void
861     ui_set_colourmap(HCOLOURMAP map)
862 matty 7 {
863 matty 29 if (owncolmap)
864     XSetWindowColormap(display, wnd, (Colormap)map);
865     else
866 matty 28 colmap = map;
867 matty 7 }
868    
869 matty 25 void
870     ui_set_clip(int x, int y, int cx, int cy)
871 matty 7 {
872 matty 9 XRectangle rect;
873 matty 7
874 matty 9 rect.x = x;
875     rect.y = y;
876     rect.width = cx;
877     rect.height = cy;
878 matty 10 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
879 matty 9 }
880 matty 7
881 matty 25 void
882     ui_reset_clip()
883 matty 9 {
884     XRectangle rect;
885    
886     rect.x = 0;
887     rect.y = 0;
888 matty 10 rect.width = width;
889     rect.height = height;
890     XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
891 matty 7 }
892    
893 matty 25 void
894     ui_bell()
895 matty 10 {
896     XBell(display, 0);
897     }
898    
899 matty 25 void
900     ui_destblt(uint8 opcode,
901     /* dest */ int x, int y, int cx, int cy)
902 matty 9 {
903 matty 29 SET_FUNCTION(opcode);
904 matty 31 FILL_RECTANGLE(x, y, cx, cy);
905 matty 29 RESET_FUNCTION(opcode);
906 matty 9 }
907    
908 matty 25 void
909     ui_patblt(uint8 opcode,
910     /* dest */ int x, int y, int cx, int cy,
911     /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
912 matty 9 {
913     Pixmap fill;
914    
915 matty 29 SET_FUNCTION(opcode);
916 matty 9
917     switch (brush->style)
918     {
919 matty 24 case 0: /* Solid */
920 matty 29 SET_FOREGROUND(fgcolour);
921 matty 31 FILL_RECTANGLE(x, y, cx, cy);
922 matty 9 break;
923    
924 matty 24 case 3: /* Pattern */
925 matty 29 fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);
926 matty 9
927 matty 29 SET_FOREGROUND(bgcolour);
928     SET_BACKGROUND(fgcolour);
929     XSetFillStyle(display, gc, FillOpaqueStippled);
930     XSetStipple(display, gc, fill);
931     XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
932 matty 9
933 matty 31 FILL_RECTANGLE(x, y, cx, cy);
934 matty 9
935 matty 29 XSetFillStyle(display, gc, FillSolid);
936     ui_destroy_glyph((HGLYPH)fill);
937 matty 9 break;
938    
939     default:
940 matty 30 unimpl("brush %d\n", brush->style);
941 matty 9 }
942 matty 29
943     RESET_FUNCTION(opcode);
944 matty 9 }
945    
946 matty 25 void
947     ui_screenblt(uint8 opcode,
948     /* dest */ int x, int y, int cx, int cy,
949     /* src */ int srcx, int srcy)
950 matty 9 {
951 matty 29 SET_FUNCTION(opcode);
952 matty 24 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
953 matty 31 if (ownbackstore)
954     XCopyArea(display, backstore, backstore, gc, srcx, srcy,
955     cx, cy, x, y);
956 matty 29 RESET_FUNCTION(opcode);
957 matty 9 }
958    
959 matty 25 void
960     ui_memblt(uint8 opcode,
961     /* dest */ int x, int y, int cx, int cy,
962     /* src */ HBITMAP src, int srcx, int srcy)
963 matty 9 {
964 matty 29 SET_FUNCTION(opcode);
965     XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy, cx, cy, x, y);
966 matty 31 if (ownbackstore)
967     XCopyArea(display, (Pixmap)src, backstore, gc, srcx, srcy,
968     cx, cy, x, y);
969 matty 29 RESET_FUNCTION(opcode);
970 matty 9 }
971    
972 matty 25 void
973     ui_triblt(uint8 opcode,
974     /* dest */ int x, int y, int cx, int cy,
975     /* src */ HBITMAP src, int srcx, int srcy,
976     /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
977 matty 9 {
978     /* This is potentially difficult to do in general. Until someone
979 matty 10 comes up with a more efficient way of doing it I am using cases. */
980 matty 9
981     switch (opcode)
982     {
983 matty 24 case 0x69: /* PDSxxn */
984 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
985     ui_patblt(ROP2_NXOR, x, y, cx, cy,
986 matty 24 brush, bgcolour, fgcolour);
987 matty 16 break;
988    
989 matty 24 case 0xb8: /* PSDPxax */
990 matty 10 ui_patblt(ROP2_XOR, x, y, cx, cy,
991 matty 24 brush, bgcolour, fgcolour);
992 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
993 matty 10 ui_patblt(ROP2_XOR, x, y, cx, cy,
994 matty 24 brush, bgcolour, fgcolour);
995 matty 9 break;
996    
997 matty 29 case 0xc0: /* PSa */
998 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
999     ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour,
1000     fgcolour);
1001     break;
1002    
1003 matty 9 default:
1004 matty 30 unimpl("triblt 0x%x\n", opcode);
1005 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1006 matty 9 }
1007     }
1008    
1009 matty 25 void
1010     ui_line(uint8 opcode,
1011     /* dest */ int startx, int starty, int endx, int endy,
1012     /* pen */ PEN *pen)
1013 matty 9 {
1014 matty 29 SET_FUNCTION(opcode);
1015     SET_FOREGROUND(pen->colour);
1016 matty 10 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1017 matty 31 if (ownbackstore)
1018     XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1019 matty 29 RESET_FUNCTION(opcode);
1020 matty 9 }
1021    
1022 matty 25 void
1023     ui_rect(
1024     /* dest */ int x, int y, int cx, int cy,
1025     /* brush */ int colour)
1026 matty 9 {
1027 matty 29 SET_FOREGROUND(colour);
1028 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1029 matty 9 }
1030    
1031 matty 25 void
1032     ui_draw_glyph(int mixmode,
1033     /* dest */ int x, int y, int cx, int cy,
1034     /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,
1035     int fgcolour)
1036 matty 9 {
1037 matty 29 SET_FOREGROUND(fgcolour);
1038     SET_BACKGROUND(bgcolour);
1039 matty 9
1040 matty 29 XSetFillStyle(display, gc, (mixmode == MIX_TRANSPARENT)
1041     ? FillStippled : FillOpaqueStippled);
1042     XSetStipple(display, gc, (Pixmap)glyph);
1043     XSetTSOrigin(display, gc, x, y);
1044 matty 9
1045 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1046 matty 9
1047 matty 29 XSetFillStyle(display, gc, FillSolid);
1048 matty 9 }
1049    
1050 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1051     {\
1052     glyph = cache_get_font (font, ttext[idx]);\
1053     if (!(flags & TEXT2_IMPLICIT_X))\
1054     {\
1055     xyoffset = ttext[++idx];\
1056     if ((xyoffset & 0x80))\
1057     {\
1058     if (flags & TEXT2_VERTICAL) \
1059     y += ttext[++idx] | (ttext[++idx] << 8);\
1060     else\
1061     x += ttext[++idx] | (ttext[++idx] << 8);\
1062     }\
1063     else\
1064     {\
1065     if (flags & TEXT2_VERTICAL) \
1066     y += xyoffset;\
1067     else\
1068     x += xyoffset;\
1069     }\
1070     }\
1071     if (glyph != NULL)\
1072     {\
1073     ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1074     y + (short) glyph->baseline,\
1075     glyph->width, glyph->height,\
1076     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1077     if (flags & TEXT2_IMPLICIT_X)\
1078     x += glyph->width;\
1079     }\
1080     }
1081    
1082 matty 25 void
1083     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1084 mmihalik 49 int clipx, int clipy, int clipcx, int clipcy, int boxx,
1085     int boxy, int boxcx, int boxcy, int bgcolour,
1086     int fgcolour, uint8 * text, uint8 length)
1087 matty 9 {
1088 matty 10 FONTGLYPH *glyph;
1089 mmihalik 49 int i, j, xyoffset;
1090     DATABLOB *entry;
1091 matty 9
1092 matty 29 SET_FOREGROUND(bgcolour);
1093 matty 28
1094 matty 9 if (boxcx > 1)
1095 matty 31 {
1096     FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1097     }
1098 matty 17 else if (mixmode == MIX_OPAQUE)
1099 matty 31 {
1100     FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1101     }
1102 matty 9
1103     /* Paint text, character by character */
1104 mmihalik 49 for (i = 0; i < length;) {
1105     switch (text[i]) {
1106     case 0xff:
1107     if (i + 2 < length)
1108     cache_put_text(text[i + 1], text, text[i + 2]);
1109     else {
1110     error("this shouldn't be happening\n");
1111     break;
1112     }
1113     /* this will move pointer from start to first character after FF command */
1114     length -= i + 3;
1115     text = &(text[i + 3]);
1116     i = 0;
1117     break;
1118 matty 9
1119 mmihalik 49 case 0xfe:
1120     entry = cache_get_text(text[i + 1]);
1121     if (entry != NULL) {
1122     if ((((uint8 *) (entry->data))[1] == 0)
1123     && (!(flags & TEXT2_IMPLICIT_X))) {
1124 n-ki 52 if (flags & TEXT2_VERTICAL)
1125 mmihalik 49 y += text[i + 2];
1126     else
1127     x += text[i + 2];
1128 matthewc 44 }
1129 mmihalik 49 if (i + 2 < length)
1130     i += 3;
1131 matthewc 44 else
1132 mmihalik 49 i += 2;
1133 n-ki 52 length -= i;
1134 mmihalik 49 /* this will move pointer from start to first character after FE command */
1135     text = &(text[i]);
1136     i = 0;
1137     for (j = 0; j < entry->size; j++)
1138     DO_GLYPH(((uint8 *) (entry->data)), j);
1139 matthewc 44 }
1140 mmihalik 49 break;
1141 matty 17
1142 mmihalik 49 default:
1143     DO_GLYPH(text, i);
1144     i++;
1145     break;
1146 matty 29 }
1147 mmihalik 49 }
1148 matty 28
1149 matty 9
1150     }
1151    
1152 matty 25 void
1153     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1154 matty 9 {
1155 matty 28 Pixmap pix;
1156 matty 9 XImage *image;
1157    
1158 matty 31 if (ownbackstore)
1159     {
1160     image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes,
1161     ZPixmap);
1162     }
1163     else
1164     {
1165     pix = XCreatePixmap(display, wnd, cx, cy, depth);
1166     XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1167     image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes,
1168     ZPixmap);
1169     XFreePixmap(display, pix);
1170     }
1171 matty 28
1172     offset *= bpp/8;
1173     cache_put_desktop(offset, cx, cy, image->bytes_per_line,
1174 matty 36 bpp/8, (uint8 *)image->data);
1175 matty 28
1176     XDestroyImage(image);
1177 matty 9 }
1178    
1179 matty 25 void
1180     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1181 matty 9 {
1182     XImage *image;
1183 matty 10 uint8 *data;
1184 matty 9
1185 matty 28 offset *= bpp/8;
1186     data = cache_get_desktop(offset, cx, cy, bpp/8);
1187 matty 10 if (data == NULL)
1188     return;
1189 matty 29
1190     image = XCreateImage(display, visual, depth, ZPixmap,
1191 matty 28 0, data, cx, cy, BitmapPad(display),
1192     cx * bpp/8);
1193 matty 29
1194 matty 31 if (ownbackstore)
1195     {
1196     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1197     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1198     }
1199     else
1200     {
1201     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1202     }
1203    
1204 matty 9 XFree(image);
1205     }

  ViewVC Help
Powered by ViewVC 1.1.26