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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 24 by matty, Sat Jan 6 03:12:10 2001 UTC revision 609 by stargo, Mon Feb 16 20:28:09 2004 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X-Windows     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2002
5      
6     This program is free software; you can redistribute it and/or modify     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     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     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include <X11/Xlib.h>  #include <X11/Xlib.h>
22    #include <X11/Xutil.h>
23    #include <unistd.h>
24    #include <sys/time.h>
25  #include <time.h>  #include <time.h>
26    #include <errno.h>
27    #include <strings.h>
28  #include "rdesktop.h"  #include "rdesktop.h"
29    #include "xproto.h"
30    
31    extern int g_width;
32    extern int g_height;
33    extern BOOL g_sendmotion;
34    extern BOOL g_fullscreen;
35    extern BOOL g_grab_keyboard;
36    extern BOOL g_hide_decorations;
37    extern char g_title[];
38    extern int g_server_bpp;
39    extern int g_win_button_size;
40    
41    Display *g_display;
42    Time g_last_gesturetime;
43    static int g_x_socket;
44    static Screen *g_screen;
45    Window g_wnd;
46    BOOL g_enable_compose = False;
47    static GC g_gc = NULL;
48    static Visual *g_visual;
49    static int g_depth;
50    static int g_bpp;
51    static XIM g_IM;
52    static XIC g_IC;
53    static XModifierKeymap *g_mod_map;
54    static Cursor g_current_cursor;
55    static HCURSOR g_null_cursor = NULL;
56    static Atom g_protocol_atom, g_kill_atom;
57    static BOOL g_focused;
58    static BOOL g_mouse_in_wnd;
59    
60    /* endianness */
61    static BOOL g_host_be;
62    static BOOL g_xserver_be;
63    static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
64    static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
65    
66    /* software backing store */
67    BOOL g_ownbackstore = True;     /* We can't rely on external BackingStore */
68    static Pixmap g_backstore = 0;
69    
70    /* Moving in single app mode */
71    static BOOL g_moving_wnd;
72    static int g_move_x_offset = 0;
73    static int g_move_y_offset = 0;
74    
75    #ifdef WITH_RDPSND
76    extern int g_dsp_fd;
77    extern BOOL g_dsp_busy;
78    extern BOOL g_rdpsnd;
79    #endif
80    
81    /* MWM decorations */
82    #define MWM_HINTS_DECORATIONS   (1L << 1)
83    #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
84    typedef struct
85    {
86            uint32 flags;
87            uint32 functions;
88            uint32 decorations;
89            sint32 inputMode;
90            uint32 status;
91    }
92    PropMotifWmHints;
93    
94    typedef struct
95    {
96            uint32 red;
97            uint32 green;
98            uint32 blue;
99    }
100    PixelColour;
101    
102    
103    #define FILL_RECTANGLE(x,y,cx,cy)\
104    { \
105            XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
106            if (g_ownbackstore) \
107                    XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
108    }
109    
110    #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
111    { \
112            XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
113    }
114    
115    /* colour maps */
116    BOOL g_owncolmap = False;
117    static Colormap g_xcolmap;
118    static uint32 *g_colmap = NULL;
119    
120    #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
121    #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
122    #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
123    
124    static int rop2_map[] = {
125            GXclear,                /* 0 */
126            GXnor,                  /* DPon */
127            GXandInverted,          /* DPna */
128            GXcopyInverted,         /* Pn */
129            GXandReverse,           /* PDna */
130            GXinvert,               /* Dn */
131            GXxor,                  /* DPx */
132            GXnand,                 /* DPan */
133            GXand,                  /* DPa */
134            GXequiv,                /* DPxn */
135            GXnoop,                 /* D */
136            GXorInverted,           /* DPno */
137            GXcopy,                 /* P */
138            GXorReverse,            /* PDno */
139            GXor,                   /* DPo */
140            GXset                   /* 1 */
141    };
142    
143  extern int width;  #define SET_FUNCTION(rop2)      { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
144  extern int height;  #define RESET_FUNCTION(rop2)    { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
 extern BOOL motion;  
   
 static Display *display;  
 static Window wnd;  
 static GC gc;  
 static Visual *visual;  
 static XIM IM;  
145    
146  BOOL ui_create_window(char *title)  static void
147    mwm_hide_decorations(void)
148  {  {
149          Screen *screen;          PropMotifWmHints motif_hints;
150          XSetWindowAttributes attribs;          Atom hintsatom;
         unsigned long input_mask;  
         int i;  
151    
152          display = XOpenDisplay(NULL);          /* setup the property */
153          if (display == NULL)          motif_hints.flags = MWM_HINTS_DECORATIONS;
154            motif_hints.decorations = 0;
155    
156            /* get the atom for the property */
157            hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
158            if (!hintsatom)
159          {          {
160                  ERROR("Failed to open display\n");                  warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
161                  return False;                  return;
162          }          }
163    
164          /* Check the screen supports 8-bit depth. */          XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
165          screen = DefaultScreenOfDisplay(display);                          (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
166          for (i = 0; i < screen->ndepths; i++)  }
167                  if (screen->depths[i].depth == 8)  
168    static PixelColour
169    split_colour15(uint32 colour)
170    {
171            PixelColour rv;
172            rv.red = (colour & 0x7c00) >> 10;
173            rv.red = (rv.red * 0xff) / 0x1f;
174            rv.green = (colour & 0x03e0) >> 5;
175            rv.green = (rv.green * 0xff) / 0x1f;
176            rv.blue = (colour & 0x1f);
177            rv.blue = (rv.blue * 0xff) / 0x1f;
178            return rv;
179    }
180    
181    static PixelColour
182    split_colour16(uint32 colour)
183    {
184            PixelColour rv;
185            rv.red = (colour & 0xf800) >> 11;
186            rv.red = (rv.red * 0xff) / 0x1f;
187            rv.green = (colour & 0x07e0) >> 5;
188            rv.green = (rv.green * 0xff) / 0x3f;
189            rv.blue = (colour & 0x001f);
190            rv.blue = (rv.blue * 0xff) / 0x1f;
191            return rv;
192    }
193    
194    static PixelColour
195    split_colour24(uint32 colour)
196    {
197            PixelColour rv;
198            rv.blue = (colour & 0xff0000) >> 16;
199            rv.green = (colour & 0xff00) >> 8;
200            rv.red = (colour & 0xff);
201            return rv;
202    }
203    
204    static uint32
205    make_colour(PixelColour pc)
206    {
207            return (((pc.red >> g_red_shift_r) << g_red_shift_l)
208                    | ((pc.green >> g_green_shift_r) << g_green_shift_l)
209                    | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l));
210    }
211    
212    #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
213    #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
214    #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
215                            x = (x << 16) | (x >> 16); }
216    
217    static uint32
218    translate_colour(uint32 colour)
219    {
220            PixelColour pc;
221            switch (g_server_bpp)
222            {
223                    case 15:
224                            pc = split_colour15(colour);
225                          break;                          break;
226                    case 16:
227                            pc = split_colour16(colour);
228                            break;
229                    case 24:
230                            pc = split_colour24(colour);
231                            break;
232            }
233            return make_colour(pc);
234    }
235    
236    static void
237    translate8to8(uint8 * data, uint8 * out, uint8 * end)
238    {
239            while (out < end)
240                    *(out++) = (uint8) g_colmap[*(data++)];
241    }
242    
243    static void
244    translate8to16(uint8 * data, uint8 * out, uint8 * end)
245    {
246            uint16 value;
247    
248            while (out < end)
249            {
250                    value = (uint16) g_colmap[*(data++)];
251    
252                    if (g_xserver_be)
253                    {
254                            *(out++) = value >> 8;
255                            *(out++) = value;
256                    }
257                    else
258                    {
259                            *(out++) = value;
260                            *(out++) = value >> 8;
261                    }
262            }
263    }
264    
265    /* little endian - conversion happens when colourmap is built */
266    static void
267    translate8to24(uint8 * data, uint8 * out, uint8 * end)
268    {
269            uint32 value;
270    
271            while (out < end)
272            {
273                    value = g_colmap[*(data++)];
274    
275                    if (g_xserver_be)
276                    {
277                            *(out++) = value >> 16;
278                            *(out++) = value >> 8;
279                            *(out++) = value;
280                    }
281                    else
282                    {
283                            *(out++) = value;
284                            *(out++) = value >> 8;
285                            *(out++) = value >> 16;
286                    }
287            }
288    }
289    
290    static void
291    translate8to32(uint8 * data, uint8 * out, uint8 * end)
292    {
293            uint32 value;
294    
295            while (out < end)
296            {
297                    value = g_colmap[*(data++)];
298    
299                    if (g_xserver_be)
300                    {
301                            *(out++) = value >> 24;
302                            *(out++) = value >> 16;
303                            *(out++) = value >> 8;
304                            *(out++) = value;
305                    }
306                    else
307                    {
308                            *(out++) = value;
309                            *(out++) = value >> 8;
310                            *(out++) = value >> 16;
311                            *(out++) = value >> 24;
312                    }
313            }
314    }
315    
316    static void
317    translate15to16(uint16 * data, uint8 * out, uint8 * end)
318    {
319            uint16 pixel;
320            uint16 value;
321    
322            while (out < end)
323            {
324                    pixel = *(data++);
325    
326                    if (g_host_be)
327                    {
328                            BSWAP16(pixel);
329                    }
330    
331                    value = make_colour(split_colour15(pixel));
332    
333                    if (g_xserver_be)
334                    {
335                            *(out++) = value >> 8;
336                            *(out++) = value;
337                    }
338                    else
339                    {
340                            *(out++) = value;
341                            *(out++) = value >> 8;
342                    }
343            }
344    }
345    
346    static void
347    translate15to24(uint16 * data, uint8 * out, uint8 * end)
348    {
349            uint32 value;
350            uint16 pixel;
351    
352            while (out < end)
353            {
354                    pixel = *(data++);
355    
356          if (i >= screen->ndepths)                  if (g_host_be)
357                    {
358                            BSWAP16(pixel);
359                    }
360    
361                    value = make_colour(split_colour15(pixel));
362                    if (g_xserver_be)
363                    {
364                            *(out++) = value >> 16;
365                            *(out++) = value >> 8;
366                            *(out++) = value;
367                    }
368                    else
369                    {
370                            *(out++) = value;
371                            *(out++) = value >> 8;
372                            *(out++) = value >> 16;
373                    }
374            }
375    }
376    
377    static void
378    translate15to32(uint16 * data, uint8 * out, uint8 * end)
379    {
380            uint16 pixel;
381            uint32 value;
382    
383            while (out < end)
384            {
385                    pixel = *(data++);
386    
387                    if (g_host_be)
388                    {
389                            BSWAP16(pixel);
390                    }
391    
392                    value = make_colour(split_colour15(pixel));
393    
394                    if (g_xserver_be)
395                    {
396                            *(out++) = value >> 24;
397                            *(out++) = value >> 16;
398                            *(out++) = value >> 8;
399                            *(out++) = value;
400                    }
401                    else
402                    {
403                            *(out++) = value;
404                            *(out++) = value >> 8;
405                            *(out++) = value >> 16;
406                            *(out++) = value >> 24;
407                    }
408            }
409    }
410    
411    static void
412    translate16to16(uint16 * data, uint8 * out, uint8 * end)
413    {
414            uint16 pixel;
415            uint16 value;
416    
417            while (out < end)
418          {          {
419                  ERROR("8-bit depth required (in this version).\n");                  pixel = *(data++);
420                  XCloseDisplay(display);  
421                    if (g_host_be)
422                    {
423                            BSWAP16(pixel);
424                    }
425    
426                    value = make_colour(split_colour16(pixel));
427    
428                    if (g_xserver_be)
429                    {
430                            *(out++) = value >> 8;
431                            *(out++) = value;
432                    }
433                    else
434                    {
435                            *(out++) = value;
436                            *(out++) = value >> 8;
437                    }
438            }
439    }
440    
441    static void
442    translate16to24(uint16 * data, uint8 * out, uint8 * end)
443    {
444            uint32 value;
445            uint16 pixel;
446    
447            while (out < end)
448            {
449                    pixel = *(data++);
450    
451                    if (g_host_be)
452                    {
453                            BSWAP16(pixel);
454                    }
455    
456                    value = make_colour(split_colour16(pixel));
457    
458                    if (g_xserver_be)
459                    {
460                            *(out++) = value >> 16;
461                            *(out++) = value >> 8;
462                            *(out++) = value;
463                    }
464                    else
465                    {
466                            *(out++) = value;
467                            *(out++) = value >> 8;
468                            *(out++) = value >> 16;
469                    }
470            }
471    }
472    
473    static void
474    translate16to32(uint16 * data, uint8 * out, uint8 * end)
475    {
476            uint16 pixel;
477            uint32 value;
478    
479            while (out < end)
480            {
481                    pixel = *(data++);
482    
483                    if (g_host_be)
484                    {
485                            BSWAP16(pixel);
486                    }
487    
488                    value = make_colour(split_colour16(pixel));
489    
490                    if (g_xserver_be)
491                    {
492                            *(out++) = value >> 24;
493                            *(out++) = value >> 16;
494                            *(out++) = value >> 8;
495                            *(out++) = value;
496                    }
497                    else
498                    {
499                            *(out++) = value;
500                            *(out++) = value >> 8;
501                            *(out++) = value >> 16;
502                            *(out++) = value >> 24;
503                    }
504            }
505    }
506    
507    static void
508    translate24to16(uint8 * data, uint8 * out, uint8 * end)
509    {
510            uint32 pixel = 0;
511            uint16 value;
512            while (out < end)
513            {
514                    pixel = *(data++) << 16;
515                    pixel |= *(data++) << 8;
516                    pixel |= *(data++);
517    
518                    value = (uint16) make_colour(split_colour24(pixel));
519    
520                    if (g_xserver_be)
521                    {
522                            *(out++) = value >> 8;
523                            *(out++) = value;
524                    }
525                    else
526                    {
527                            *(out++) = value;
528                            *(out++) = value >> 8;
529                    }
530            }
531    }
532    
533    static void
534    translate24to24(uint8 * data, uint8 * out, uint8 * end)
535    {
536            uint32 pixel;
537            uint32 value;
538    
539            while (out < end)
540            {
541                    pixel = *(data++) << 16;
542                    pixel |= *(data++) << 8;
543                    pixel |= *(data++);
544    
545                    value = make_colour(split_colour24(pixel));
546    
547                    if (g_xserver_be)
548                    {
549                            *(out++) = value >> 16;
550                            *(out++) = value >> 8;
551                            *(out++) = value;
552                    }
553                    else
554                    {
555                            *(out++) = value;
556                            *(out++) = value >> 8;
557                            *(out++) = value >> 16;
558                    }
559            }
560    }
561    
562    static void
563    translate24to32(uint8 * data, uint8 * out, uint8 * end)
564    {
565            uint32 pixel;
566            uint32 value;
567    
568            while (out < end)
569            {
570                    pixel = *(data++) << 16;
571                    pixel |= *(data++) << 8;
572                    pixel |= *(data++);
573    
574                    value = make_colour(split_colour24(pixel));
575    
576                    if (g_xserver_be)
577                    {
578                            *(out++) = value >> 24;
579                            *(out++) = value >> 16;
580                            *(out++) = value >> 8;
581                            *(out++) = value;
582                    }
583                    else
584                    {
585                            *(out++) = value;
586                            *(out++) = value >> 8;
587                            *(out++) = value >> 16;
588                            *(out++) = value >> 24;
589                    }
590            }
591    }
592    
593    static uint8 *
594    translate_image(int width, int height, uint8 * data)
595    {
596            int size = width * height * g_bpp / 8;
597            uint8 *out = (uint8 *) xmalloc(size);
598            uint8 *end = out + size;
599    
600            switch (g_server_bpp)
601            {
602                    case 24:
603                            switch (g_bpp)
604                            {
605                                    case 32:
606                                            translate24to32(data, out, end);
607                                            break;
608                                    case 24:
609                                            translate24to24(data, out, end);
610                                            break;
611                                    case 16:
612                                            translate24to16(data, out, end);
613                                            break;
614                            }
615                            break;
616                    case 16:
617                            switch (g_bpp)
618                            {
619                                    case 32:
620                                            translate16to32((uint16 *) data, out, end);
621                                            break;
622                                    case 24:
623                                            translate16to24((uint16 *) data, out, end);
624                                            break;
625                                    case 16:
626                                            translate16to16((uint16 *) data, out, end);
627                                            break;
628                            }
629                            break;
630                    case 15:
631                            switch (g_bpp)
632                            {
633                                    case 32:
634                                            translate15to32((uint16 *) data, out, end);
635                                            break;
636                                    case 24:
637                                            translate15to24((uint16 *) data, out, end);
638                                            break;
639                                    case 16:
640                                            translate15to16((uint16 *) data, out, end);
641                                            break;
642                            }
643                            break;
644                    case 8:
645                            switch (g_bpp)
646                            {
647                                    case 8:
648                                            translate8to8(data, out, end);
649                                            break;
650                                    case 16:
651                                            translate8to16(data, out, end);
652                                            break;
653                                    case 24:
654                                            translate8to24(data, out, end);
655                                            break;
656                                    case 32:
657                                            translate8to32(data, out, end);
658                                            break;
659                            }
660                            break;
661            }
662            return out;
663    }
664    
665    BOOL
666    get_key_state(unsigned int state, uint32 keysym)
667    {
668            int modifierpos, key, keysymMask = 0;
669            int offset;
670    
671            KeyCode keycode = XKeysymToKeycode(g_display, keysym);
672    
673            if (keycode == NoSymbol)
674                  return False;                  return False;
675    
676            for (modifierpos = 0; modifierpos < 8; modifierpos++)
677            {
678                    offset = g_mod_map->max_keypermod * modifierpos;
679    
680                    for (key = 0; key < g_mod_map->max_keypermod; key++)
681                    {
682                            if (g_mod_map->modifiermap[offset + key] == keycode)
683                                    keysymMask |= 1 << modifierpos;
684                    }
685          }          }
686    
687          visual = DefaultVisual(display, DefaultScreen(display));          return (state & keysymMask) ? True : False;
688    }
689    
690          attribs.background_pixel =  static void
691                  BlackPixel(display, DefaultScreen(display));  calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
692          attribs.backing_store = Always;  {
693          wnd = XCreateWindow(display, DefaultRootWindow(display),          *shift_l = ffs(mask) - 1;
694                              0, 0, width, height, 0, 8, InputOutput, visual,          mask >>= *shift_l;
695                              CWBackingStore | CWBackPixel, &attribs);          *shift_r = 8 - ffs(mask & ~(mask >> 1));
696    }
697          XStoreName(display, wnd, title);  
698          XMapWindow(display, wnd);  BOOL
699    ui_init(void)
700          input_mask = KeyPressMask | KeyReleaseMask;  {
701          input_mask |= ButtonPressMask | ButtonReleaseMask;          XVisualInfo vi;
702          if (motion)          XPixmapFormatValues *pfm;
703                  input_mask |= PointerMotionMask;          uint16 test;
704            int i, screen_num, nvisuals;
705            XVisualInfo *vmatches = NULL;
706            XVisualInfo template;
707            Bool TrueColorVisual = False;
708    
709            g_display = XOpenDisplay(NULL);
710            if (g_display == NULL)
711            {
712                    error("Failed to open display: %s\n", XDisplayName(NULL));
713                    return False;
714            }
715    
716          XSelectInput(display, wnd, input_mask);          screen_num = DefaultScreen(g_display);
717          gc = XCreateGC(display, wnd, 0, NULL);          g_x_socket = ConnectionNumber(g_display);
718            g_screen = ScreenOfDisplay(g_display, screen_num);
719            g_depth = DefaultDepthOfScreen(g_screen);
720    
721            /* Search for best TrueColor depth */
722            template.class = TrueColor;
723            vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);
724    
725            nvisuals--;
726            while (nvisuals >= 0)
727            {
728                    if ((vmatches + nvisuals)->depth > g_depth)
729                    {
730                            g_depth = (vmatches + nvisuals)->depth;
731                    }
732                    nvisuals--;
733                    TrueColorVisual = True;
734            }
735    
736            if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))
737            {
738                    /* we use a colourmap, so the default visual should do */
739                    g_visual = DefaultVisualOfScreen(g_screen);
740                    g_depth = DefaultDepthOfScreen(g_screen);
741    
742                    /* Do not allocate colours on a TrueColor visual */
743                    if (g_visual->class == TrueColor)
744                    {
745                            g_owncolmap = False;
746                    }
747            }
748            else
749            {
750                    /* need a truecolour visual */
751                    if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))
752                    {
753                            error("The display does not support true colour - high colour support unavailable.\n");
754                            return False;
755                    }
756    
757                    g_visual = vi.visual;
758                    g_owncolmap = False;
759                    calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);
760                    calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);
761                    calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);
762            }
763    
764            pfm = XListPixmapFormats(g_display, &i);
765            if (pfm != NULL)
766            {
767                    /* Use maximum bpp for this depth - this is generally
768                       desirable, e.g. 24 bits->32 bits. */
769                    while (i--)
770                    {
771                            if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
772                            {
773                                    g_bpp = pfm[i].bits_per_pixel;
774                            }
775                    }
776                    XFree(pfm);
777            }
778    
779            if (g_bpp < 8)
780            {
781                    error("Less than 8 bpp not currently supported.\n");
782                    XCloseDisplay(g_display);
783                    return False;
784            }
785    
786            if (!g_owncolmap)
787            {
788                    g_xcolmap =
789                            XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
790                                            AllocNone);
791                    if (g_depth <= 8)
792                            warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
793            }
794    
795            if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
796            {
797                    warning("External BackingStore not available, using internal\n");
798                    g_ownbackstore = True;
799            }
800    
801            test = 1;
802            g_host_be = !(BOOL) (*(uint8 *) (&test));
803            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
804    
805            /*
806             * Determine desktop size
807             */
808            if (g_fullscreen)
809            {
810                    g_width = WidthOfScreen(g_screen);
811                    g_height = HeightOfScreen(g_screen);
812            }
813            else if (g_width < 0)
814            {
815                    /* Percent of screen */
816                    g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
817                    g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
818            }
819            else if (g_width == 0)
820            {
821                    /* Fetch geometry from _NET_WORKAREA */
822                    uint32 x, y, cx, cy;
823    
824                    if (get_current_workarea(&x, &y, &cx, &cy) == 0)
825                    {
826                            g_width = cx;
827                            g_height = cy;
828                    }
829                    else
830                    {
831                            warning("Failed to get workarea: probably your window manager does not support extended hints\n");
832                            g_width = 800;
833                            g_height = 600;
834                    }
835            }
836    
837            /* make sure width is a multiple of 4 */
838            g_width = (g_width + 3) & ~3;
839    
840            g_mod_map = XGetModifierMapping(g_display);
841    
842            xkeymap_init();
843    
844            if (g_enable_compose)
845                    g_IM = XOpenIM(g_display, NULL, NULL, NULL);
846    
847            xclip_init();
848    
849            DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));
850    
         IM = XOpenIM(display, NULL, NULL, NULL);  
851          return True;          return True;
852  }  }
853    
854  void ui_destroy_window()  void
855    ui_deinit(void)
856  {  {
857          XCloseIM(IM);          if (g_IM != NULL)
858          XFreeGC(display, gc);                  XCloseIM(g_IM);
859          XDestroyWindow(display, wnd);  
860          XCloseDisplay(display);          if (g_null_cursor != NULL)
861                    ui_destroy_cursor(g_null_cursor);
862    
863            XFreeModifiermap(g_mod_map);
864    
865            if (g_ownbackstore)
866                    XFreePixmap(g_display, g_backstore);
867    
868            XFreeGC(g_display, g_gc);
869            XCloseDisplay(g_display);
870            g_display = NULL;
871  }  }
872    
873  static uint8 xwin_translate_key(unsigned long key)  BOOL
874    ui_create_window(void)
875  {  {
876          DEBUG("KEY(code=0x%lx)\n", key);          uint8 null_pointer_mask[1] = { 0x80 };
877            uint8 null_pointer_data[4] = { 0x00, 0x00, 0x00, 0x00 };
878            XSetWindowAttributes attribs;
879            XClassHint *classhints;
880            XSizeHints *sizehints;
881            int wndwidth, wndheight;
882            long input_mask, ic_input_mask;
883            XEvent xevent;
884    
885            wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
886            wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
887    
888            attribs.background_pixel = BlackPixelOfScreen(g_screen);
889            attribs.border_pixel = WhitePixelOfScreen(g_screen);
890            attribs.backing_store = g_ownbackstore ? NotUseful : Always;
891            attribs.override_redirect = g_fullscreen;
892            attribs.colormap = g_xcolmap;
893    
894            g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
895                                  0, g_depth, InputOutput, g_visual,
896                                  CWBackPixel | CWBackingStore | CWOverrideRedirect |
897                                  CWColormap | CWBorderPixel, &attribs);
898    
899            if (g_gc == NULL)
900                    g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
901    
902            if ((g_ownbackstore) && (g_backstore == 0))
903            {
904                    g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
905    
906                    /* clear to prevent rubbish being exposed at startup */
907                    XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
908                    XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
909            }
910    
911            XStoreName(g_display, g_wnd, g_title);
912    
913            if (g_hide_decorations)
914                    mwm_hide_decorations();
915    
916          if ((key > 8) && (key <= 0x60))          classhints = XAllocClassHint();
917                  return (key - 8);          if (classhints != NULL)
918            {
919                    classhints->res_name = classhints->res_class = "rdesktop";
920                    XSetClassHint(g_display, g_wnd, classhints);
921                    XFree(classhints);
922            }
923    
924          switch (key)          sizehints = XAllocSizeHints();
925            if (sizehints)
926          {          {
927                  case 0x62:      /* left arrow */                  sizehints->flags = PMinSize | PMaxSize;
928                          return 0x48;                  sizehints->min_width = sizehints->max_width = g_width;
929                  case 0x64:      /* up arrow */                  sizehints->min_height = sizehints->max_height = g_height;
930                          return 0x4b;                  XSetWMNormalHints(g_display, g_wnd, sizehints);
931                  case 0x66:      /* down arrow */                  XFree(sizehints);
                         return 0x4d;  
                 case 0x68:      /* right arrow */  
                         return 0x50;  
                 case 0x73:      /* Windows key */  
                         DEBUG("CHECKPOINT\n");  
932          }          }
933    
934          return 0;          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
935                    VisibilityChangeMask | FocusChangeMask;
936    
937            if (g_sendmotion)
938                    input_mask |= PointerMotionMask;
939            if (g_ownbackstore)
940                    input_mask |= ExposureMask;
941            if (g_fullscreen || g_grab_keyboard)
942                    input_mask |= EnterWindowMask;
943            if (g_grab_keyboard)
944                    input_mask |= LeaveWindowMask;
945    
946            if (g_IM != NULL)
947            {
948                    g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
949                                     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
950    
951                    if ((g_IC != NULL)
952                        && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
953                            input_mask |= ic_input_mask;
954            }
955    
956            XSelectInput(g_display, g_wnd, input_mask);
957            XMapWindow(g_display, g_wnd);
958    
959            /* wait for VisibilityNotify */
960            do
961            {
962                    XMaskEvent(g_display, VisibilityChangeMask, &xevent);
963            }
964            while (xevent.type != VisibilityNotify);
965    
966            g_focused = False;
967            g_mouse_in_wnd = False;
968    
969            /* handle the WM_DELETE_WINDOW protocol */
970            g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
971            g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
972            XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
973    
974            /* create invisible 1x1 cursor to be used as null cursor */
975            if (g_null_cursor == NULL)
976                    g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
977    
978            return True;
979  }  }
980    
981  static uint16 xwin_translate_mouse(unsigned long button)  void
982    ui_destroy_window(void)
983  {  {
984          switch (button)          if (g_IC != NULL)
985                    XDestroyIC(g_IC);
986    
987            XDestroyWindow(g_display, g_wnd);
988    }
989    
990    void
991    xwin_toggle_fullscreen(void)
992    {
993            Pixmap contents = 0;
994    
995            if (!g_ownbackstore)
996          {          {
997                  case Button1:   /* left */                  /* need to save contents of window */
998                          return MOUSE_FLAG_BUTTON1;                  contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
999                  case Button2:   /* middle */                  XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
                         return MOUSE_FLAG_BUTTON3;  
                 case Button3:   /* right */  
                         return MOUSE_FLAG_BUTTON2;  
1000          }          }
1001    
1002          return 0;          ui_destroy_window();
1003            g_fullscreen = !g_fullscreen;
1004            ui_create_window();
1005    
1006            XDefineCursor(g_display, g_wnd, g_current_cursor);
1007    
1008            if (!g_ownbackstore)
1009            {
1010                    XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1011                    XFreePixmap(g_display, contents);
1012            }
1013  }  }
1014    
1015  void ui_process_events()  /* Process all events in Xlib queue
1016  {     Returns 0 after user quit, 1 otherwise */
1017          XEvent event;  static int
1018          uint8 scancode;  xwin_process_events(void)
1019          uint16 button;  {
1020            XEvent xevent;
1021            KeySym keysym;
1022            uint16 button, flags;
1023          uint32 ev_time;          uint32 ev_time;
1024            key_translation tr;
1025            char str[256];
1026            Status status;
1027    
1028          if (display == NULL)          while (XPending(g_display) > 0)
                 return;  
   
         while (XCheckWindowEvent(display, wnd, 0xffffffff, &event))  
1029          {          {
1030                  ev_time = time(NULL);                  XNextEvent(g_display, &xevent);
1031    
1032                  switch (event.type)                  if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1033                  {                  {
1034                            DEBUG_KBD(("Filtering event\n"));
1035                            continue;
1036                    }
1037    
1038                    flags = 0;
1039    
1040                    switch (xevent.type)
1041                    {
1042                            case ClientMessage:
1043                                    /* the window manager told us to quit */
1044                                    if ((xevent.xclient.message_type == g_protocol_atom)
1045                                        && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1046                                            /* Quit */
1047                                            return 0;
1048                                    break;
1049    
1050                          case KeyPress:                          case KeyPress:
1051                                  scancode =                                  g_last_gesturetime = xevent.xkey.time;
1052                                          xwin_translate_key(event.xkey.                                  if (g_IC != NULL)
1053                                                             keycode);                                          /* Multi_key compatible version */
1054                                  if (scancode == 0)                                  {
1055                                            XmbLookupString(g_IC,
1056                                                            &xevent.xkey, str, sizeof(str), &keysym,
1057                                                            &status);
1058                                            if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1059                                            {
1060                                                    error("XmbLookupString failed with status 0x%x\n",
1061                                                          status);
1062                                                    break;
1063                                            }
1064                                    }
1065                                    else
1066                                    {
1067                                            /* Plain old XLookupString */
1068                                            DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1069                                            XLookupString((XKeyEvent *) & xevent,
1070                                                          str, sizeof(str), &keysym, NULL);
1071                                    }
1072    
1073                                    DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1074                                               get_ksname(keysym)));
1075    
1076                                    ev_time = time(NULL);
1077                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1078                                          break;                                          break;
1079    
1080                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,                                  tr = xkeymap_translate_key(keysym,
1081                                                 scancode, 0);                                                             xevent.xkey.keycode, xevent.xkey.state);
1082    
1083                                    if (tr.scancode == 0)
1084                                            break;
1085    
1086                                    save_remote_modifiers(tr.scancode);
1087                                    ensure_remote_modifiers(ev_time, tr);
1088                                    rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1089                                    restore_remote_modifiers(ev_time, tr.scancode);
1090    
1091                                  break;                                  break;
1092    
1093                          case KeyRelease:                          case KeyRelease:
1094                                  scancode =                                  g_last_gesturetime = xevent.xkey.time;
1095                                          xwin_translate_key(event.xkey.                                  XLookupString((XKeyEvent *) & xevent, str,
1096                                                             keycode);                                                sizeof(str), &keysym, NULL);
1097                                  if (scancode == 0)  
1098                                    DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1099                                               get_ksname(keysym)));
1100    
1101                                    ev_time = time(NULL);
1102                                    if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1103                                            break;
1104    
1105                                    tr = xkeymap_translate_key(keysym,
1106                                                               xevent.xkey.keycode, xevent.xkey.state);
1107    
1108                                    if (tr.scancode == 0)
1109                                          break;                                          break;
1110    
1111                                  rdp_send_input(ev_time, RDP_INPUT_SCANCODE,                                  rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
                                                KBD_FLAG_DOWN | KBD_FLAG_UP,  
                                                scancode, 0);  
1112                                  break;                                  break;
1113    
1114                          case ButtonPress:                          case ButtonPress:
1115                                  button =                                  flags = MOUSE_FLAG_DOWN;
1116                                          xwin_translate_mouse(event.xbutton.                                  /* fall through */
                                                              button);  
1117    
1118                            case ButtonRelease:
1119                                    g_last_gesturetime = xevent.xbutton.time;
1120                                    button = xkeymap_translate_button(xevent.xbutton.button);
1121                                  if (button == 0)                                  if (button == 0)
1122                                          break;                                          break;
1123    
1124                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* If win_button_size is nonzero, enable single app mode */
1125                                                 button | MOUSE_FLAG_DOWN,                                  if (xevent.xbutton.y < g_win_button_size)
1126                                                 event.xbutton.x,                                  {
1127                                                 event.xbutton.y);                                          /* Stop moving window when button is released, regardless of cursor position */
1128                                            if (g_moving_wnd && (xevent.type == ButtonRelease))
1129                                                    g_moving_wnd = False;
1130    
1131                                            /*  Check from right to left: */
1132    
1133                                            if (xevent.xbutton.x >= g_width - g_win_button_size)
1134                                            {
1135                                                    /* The close button, continue */
1136                                                    ;
1137                                            }
1138                                            else if (xevent.xbutton.x >=
1139                                                     g_width - g_win_button_size * 2)
1140                                            {
1141                                                    /* The maximize/restore button. Do not send to
1142                                                       server.  It might be a good idea to change the
1143                                                       cursor or give some other visible indication
1144                                                       that rdesktop inhibited this click */
1145                                                    break;
1146                                            }
1147                                            else if (xevent.xbutton.x >=
1148                                                     g_width - g_win_button_size * 3)
1149                                            {
1150                                                    /* The minimize button. Iconify window. */
1151                                                    XIconifyWindow(g_display, g_wnd,
1152                                                                   DefaultScreen(g_display));
1153                                                    break;
1154                                            }
1155                                            else if (xevent.xbutton.x <= g_win_button_size)
1156                                            {
1157                                                    /* The system menu. Ignore. */
1158                                                    break;
1159                                            }
1160                                            else
1161                                            {
1162                                                    /* The title bar. */
1163                                                    if ((xevent.type == ButtonPress) && !g_fullscreen
1164                                                        && g_hide_decorations)
1165                                                    {
1166                                                            g_moving_wnd = True;
1167                                                            g_move_x_offset = xevent.xbutton.x;
1168                                                            g_move_y_offset = xevent.xbutton.y;
1169                                                    }
1170                                                    break;
1171    
1172                                            }
1173                                    }
1174    
1175                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1176                                                   flags | button, xevent.xbutton.x, xevent.xbutton.y);
1177                                    break;
1178    
1179                            case MotionNotify:
1180                                    if (g_moving_wnd)
1181                                    {
1182                                            XMoveWindow(g_display, g_wnd,
1183                                                        xevent.xmotion.x_root - g_move_x_offset,
1184                                                        xevent.xmotion.y_root - g_move_y_offset);
1185                                            break;
1186                                    }
1187    
1188                                    if (g_fullscreen && !g_focused)
1189                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1190                                                           CurrentTime);
1191                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1192                                                   MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1193                                  break;                                  break;
1194    
1195                          case ButtonRelease:                          case FocusIn:
1196                                  button =                                  if (xevent.xfocus.mode == NotifyGrab)
                                         xwin_translate_mouse(event.xbutton.  
                                                              button);  
                                 if (button == 0)  
1197                                          break;                                          break;
1198                                    g_focused = True;
1199                                    reset_modifier_keys();
1200                                    if (g_grab_keyboard && g_mouse_in_wnd)
1201                                            XGrabKeyboard(g_display, g_wnd, True,
1202                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1203                                    break;
1204    
1205                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                          case FocusOut:
1206                                                 button,                                  if (xevent.xfocus.mode == NotifyUngrab)
1207                                                 event.xbutton.x,                                          break;
1208                                                 event.xbutton.y);                                  g_focused = False;
1209                                    if (xevent.xfocus.mode == NotifyWhileGrabbed)
1210                                            XUngrabKeyboard(g_display, CurrentTime);
1211                                  break;                                  break;
1212    
1213                          case MotionNotify:                          case EnterNotify:
1214                                  rdp_send_input(ev_time, RDP_INPUT_MOUSE,                                  /* we only register for this event when in fullscreen mode */
1215                                                 MOUSE_FLAG_MOVE,                                  /* or grab_keyboard */
1216                                                 event.xmotion.x,                                  g_mouse_in_wnd = True;
1217                                                 event.xmotion.y);                                  if (g_fullscreen)
1218                                    {
1219                                            XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1220                                                           CurrentTime);
1221                                            break;
1222                                    }
1223                                    if (g_focused)
1224                                            XGrabKeyboard(g_display, g_wnd, True,
1225                                                          GrabModeAsync, GrabModeAsync, CurrentTime);
1226                                    break;
1227    
1228                            case LeaveNotify:
1229                                    /* we only register for this event when grab_keyboard */
1230                                    g_mouse_in_wnd = False;
1231                                    XUngrabKeyboard(g_display, CurrentTime);
1232                                    break;
1233    
1234                            case Expose:
1235                                    XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1236                                              xevent.xexpose.x, xevent.xexpose.y,
1237                                              xevent.xexpose.width,
1238                                              xevent.xexpose.height,
1239                                              xevent.xexpose.x, xevent.xexpose.y);
1240                                    break;
1241    
1242                            case MappingNotify:
1243                                    /* Refresh keyboard mapping if it has changed. This is important for
1244                                       Xvnc, since it allocates keycodes dynamically */
1245                                    if (xevent.xmapping.request == MappingKeyboard
1246                                        || xevent.xmapping.request == MappingModifier)
1247                                            XRefreshKeyboardMapping(&xevent.xmapping);
1248    
1249                                    if (xevent.xmapping.request == MappingModifier)
1250                                    {
1251                                            XFreeModifiermap(g_mod_map);
1252                                            g_mod_map = XGetModifierMapping(g_display);
1253                                    }
1254                                    break;
1255    
1256                                    /* clipboard stuff */
1257                            case SelectionNotify:
1258                                    xclip_handle_SelectionNotify(&xevent.xselection);
1259                                    break;
1260                            case SelectionRequest:
1261                                    xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1262                                    break;
1263                            case SelectionClear:
1264                                    xclip_handle_SelectionClear();
1265                                    break;
1266                            case PropertyNotify:
1267                                    xclip_handle_PropertyNotify(&xevent.xproperty);
1268                                    break;
1269                  }                  }
1270          }          }
1271            /* Keep going */
1272            return 1;
1273  }  }
1274    
1275  void ui_move_pointer(int x, int y)  /* Returns 0 after user quit, 1 otherwise */
1276    int
1277    ui_select(int rdp_socket)
1278  {  {
1279          XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);          int n;
1280            fd_set rfds, wfds;
1281            struct timeval tv;
1282            BOOL s_timeout = False;
1283    
1284            while (True)
1285            {
1286                    n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1287                    /* Process any events already waiting */
1288                    if (!xwin_process_events())
1289                            /* User quit */
1290                            return 0;
1291    
1292                    FD_ZERO(&rfds);
1293                    FD_ZERO(&wfds);
1294                    FD_SET(rdp_socket, &rfds);
1295                    FD_SET(g_x_socket, &rfds);
1296    
1297    #ifdef WITH_RDPSND
1298                    /* FIXME: there should be an API for registering fds */
1299                    if (g_dsp_busy)
1300                    {
1301                            FD_SET(g_dsp_fd, &wfds);
1302                            n = (g_dsp_fd > n) ? g_dsp_fd : n;
1303                    }
1304    #endif
1305                    /* default timeout */
1306                    tv.tv_sec = 60;
1307                    tv.tv_usec = 0;
1308    
1309                    /* add redirection handles */
1310                    rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1311    
1312                    n++;
1313    
1314                    switch (select(n, &rfds, &wfds, NULL, &tv))
1315                    {
1316                            case -1:
1317                                    error("select: %s\n", strerror(errno));
1318    
1319                            case 0:
1320                                    /* TODO: if tv.tv_sec just times out
1321                                     * we will segfault.
1322                                     * FIXME:
1323                                     */
1324                                    //s_timeout = True;
1325                                    //rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1326                                    continue;
1327                    }
1328    
1329                    rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
1330    
1331                    if (FD_ISSET(rdp_socket, &rfds))
1332                            return 1;
1333    
1334    #ifdef WITH_RDPSND
1335                    if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1336                            wave_out_play();
1337    #endif
1338            }
1339    }
1340    
1341    void
1342    ui_move_pointer(int x, int y)
1343    {
1344            XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1345  }  }
1346    
1347  HBITMAP ui_create_bitmap(int width, int height, uint8 *data)  HBITMAP
1348    ui_create_bitmap(int width, int height, uint8 * data)
1349  {  {
1350          XImage *image;          XImage *image;
1351          Pixmap bitmap;          Pixmap bitmap;
1352            uint8 *tdata;
1353            int bitmap_pad;
1354    
1355            if (g_server_bpp == 8)
1356            {
1357                    bitmap_pad = 8;
1358            }
1359            else
1360            {
1361                    bitmap_pad = g_bpp;
1362    
1363          bitmap = XCreatePixmap(display, wnd, width, height, 8);                  if (g_bpp == 24)
1364                            bitmap_pad = 32;
1365            }
1366    
1367          image = XCreateImage(display, visual, 8, ZPixmap, 0,          tdata = (g_owncolmap ? data : translate_image(width, height, data));
1368                               data, width, height, 8, width);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1369          XSetFunction(display, gc, GXcopy);          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1370          XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);                               (char *) tdata, width, height, bitmap_pad, 0);
         XFree(image);  
1371    
1372            XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1373    
1374            XFree(image);
1375            if (!g_owncolmap)
1376                    xfree(tdata);
1377          return (HBITMAP) bitmap;          return (HBITMAP) bitmap;
1378  }  }
1379    
1380  void ui_paint_bitmap(int x, int y, int cx, int cy,  void
1381                       int width, int height, uint8 *data)  ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1382  {  {
1383          XImage *image;          XImage *image;
1384            uint8 *tdata;
1385            int bitmap_pad;
1386    
1387            if (g_server_bpp == 8)
1388            {
1389                    bitmap_pad = 8;
1390            }
1391            else
1392            {
1393                    bitmap_pad = g_bpp;
1394    
1395                    if (g_bpp == 24)
1396                            bitmap_pad = 32;
1397            }
1398    
1399            tdata = (g_owncolmap ? data : translate_image(width, height, data));
1400            image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1401                                 (char *) tdata, width, height, bitmap_pad, 0);
1402    
1403            if (g_ownbackstore)
1404            {
1405                    XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1406                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1407            }
1408            else
1409            {
1410                    XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1411            }
1412    
         image = XCreateImage(display, visual, 8, ZPixmap, 0,  
                              data, width, height, 8, width);  
         XSetFunction(display, gc, GXcopy);  
         XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);  
1413          XFree(image);          XFree(image);
1414            if (!g_owncolmap)
1415                    xfree(tdata);
1416  }  }
1417    
1418  void ui_destroy_bitmap(HBITMAP bmp)  void
1419    ui_destroy_bitmap(HBITMAP bmp)
1420  {  {
1421          XFreePixmap(display, (Pixmap) bmp);          XFreePixmap(g_display, (Pixmap) bmp);
1422  }  }
1423    
1424  HGLYPH ui_create_glyph(int width, int height, uint8 *data)  HGLYPH
1425    ui_create_glyph(int width, int height, uint8 * data)
1426  {  {
1427          XImage *image;          XImage *image;
1428          Pixmap bitmap;          Pixmap bitmap;
# Line 252  HGLYPH ui_create_glyph(int width, int he Line 1431  HGLYPH ui_create_glyph(int width, int he
1431    
1432          scanline = (width + 7) / 8;          scanline = (width + 7) / 8;
1433    
1434          bitmap = XCreatePixmap(display, wnd, width, height, 1);          bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1435          gc = XCreateGC(display, bitmap, 0, NULL);          gc = XCreateGC(g_display, bitmap, 0, NULL);
1436    
1437          image = XCreateImage(display, visual, 1, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1438                               data, width, height, 8, scanline);                               width, height, 8, scanline);
1439          image->byte_order = MSBFirst;          image->byte_order = MSBFirst;
1440          image->bitmap_bit_order = MSBFirst;          image->bitmap_bit_order = MSBFirst;
1441          XInitImage(image);          XInitImage(image);
1442    
1443          XSetFunction(display, gc, GXcopy);          XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
         XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);  
         XFree(image);  
         XFreeGC(display, gc);  
1444    
1445            XFree(image);
1446            XFreeGC(g_display, gc);
1447          return (HGLYPH) bitmap;          return (HGLYPH) bitmap;
1448  }  }
1449    
1450  void ui_destroy_glyph(HGLYPH glyph)  void
1451    ui_destroy_glyph(HGLYPH glyph)
1452    {
1453            XFreePixmap(g_display, (Pixmap) glyph);
1454    }
1455    
1456    HCURSOR
1457    ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1458                     uint8 * andmask, uint8 * xormask)
1459    {
1460            HGLYPH maskglyph, cursorglyph;
1461            XColor bg, fg;
1462            Cursor xcursor;
1463            uint8 *cursor, *pcursor;
1464            uint8 *mask, *pmask;
1465            uint8 nextbit;
1466            int scanline, offset;
1467            int i, j;
1468    
1469            scanline = (width + 7) / 8;
1470            offset = scanline * height;
1471    
1472            cursor = (uint8 *) xmalloc(offset);
1473            memset(cursor, 0, offset);
1474    
1475            mask = (uint8 *) xmalloc(offset);
1476            memset(mask, 0, offset);
1477    
1478            /* approximate AND and XOR masks with a monochrome X pointer */
1479            for (i = 0; i < height; i++)
1480            {
1481                    offset -= scanline;
1482                    pcursor = &cursor[offset];
1483                    pmask = &mask[offset];
1484    
1485                    for (j = 0; j < scanline; j++)
1486                    {
1487                            for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1488                            {
1489                                    if (xormask[0] || xormask[1] || xormask[2])
1490                                    {
1491                                            *pcursor |= (~(*andmask) & nextbit);
1492                                            *pmask |= nextbit;
1493                                    }
1494                                    else
1495                                    {
1496                                            *pcursor |= ((*andmask) & nextbit);
1497                                            *pmask |= (~(*andmask) & nextbit);
1498                                    }
1499    
1500                                    xormask += 3;
1501                            }
1502    
1503                            andmask++;
1504                            pcursor++;
1505                            pmask++;
1506                    }
1507            }
1508    
1509            fg.red = fg.blue = fg.green = 0xffff;
1510            bg.red = bg.blue = bg.green = 0x0000;
1511            fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1512    
1513            cursorglyph = ui_create_glyph(width, height, cursor);
1514            maskglyph = ui_create_glyph(width, height, mask);
1515    
1516            xcursor =
1517                    XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1518                                        (Pixmap) maskglyph, &fg, &bg, x, y);
1519    
1520            ui_destroy_glyph(maskglyph);
1521            ui_destroy_glyph(cursorglyph);
1522            xfree(mask);
1523            xfree(cursor);
1524            return (HCURSOR) xcursor;
1525    }
1526    
1527    void
1528    ui_set_cursor(HCURSOR cursor)
1529    {
1530            g_current_cursor = (Cursor) cursor;
1531            XDefineCursor(g_display, g_wnd, g_current_cursor);
1532    }
1533    
1534    void
1535    ui_destroy_cursor(HCURSOR cursor)
1536  {  {
1537          XFreePixmap(display, (Pixmap) glyph);          XFreeCursor(g_display, (Cursor) cursor);
1538  }  }
1539    
1540  HCOLOURMAP ui_create_colourmap(COLOURMAP *colours)  void
1541    ui_set_null_cursor(void)
1542    {
1543            ui_set_cursor(g_null_cursor);
1544    }
1545    
1546    #define MAKE_XCOLOR(xc,c) \
1547                    (xc)->red   = ((c)->red   << 8) | (c)->red; \
1548                    (xc)->green = ((c)->green << 8) | (c)->green; \
1549                    (xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
1550                    (xc)->flags = DoRed | DoGreen | DoBlue;
1551    
1552    
1553    HCOLOURMAP
1554    ui_create_colourmap(COLOURMAP * colours)
1555  {  {
1556          COLOURENTRY *entry;          COLOURENTRY *entry;
         XColor *xcolours, *xentry;  
         Colormap map;  
1557          int i, ncolours = colours->ncolours;          int i, ncolours = colours->ncolours;
1558            if (!g_owncolmap)
         xcolours = xmalloc(sizeof(XColor) * ncolours);  
         for (i = 0; i < ncolours; i++)  
1559          {          {
1560                  entry = &colours->colours[i];                  uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1561                  xentry = &xcolours[i];                  XColor xentry;
1562                    XColor xc_cache[256];
1563                    uint32 colour;
1564                    int colLookup = 256;
1565                    for (i = 0; i < ncolours; i++)
1566                    {
1567                            entry = &colours->colours[i];
1568                            MAKE_XCOLOR(&xentry, entry);
1569    
1570                            if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1571                            {
1572                                    /* Allocation failed, find closest match. */
1573                                    int j = 256;
1574                                    int nMinDist = 3 * 256 * 256;
1575                                    long nDist = nMinDist;
1576    
1577                                    /* only get the colors once */
1578                                    while (colLookup--)
1579                                    {
1580                                            xc_cache[colLookup].pixel = colLookup;
1581                                            xc_cache[colLookup].red = xc_cache[colLookup].green =
1582                                                    xc_cache[colLookup].blue = 0;
1583                                            xc_cache[colLookup].flags = 0;
1584                                            XQueryColor(g_display,
1585                                                        DefaultColormap(g_display,
1586                                                                        DefaultScreen(g_display)),
1587                                                        &xc_cache[colLookup]);
1588                                    }
1589                                    colLookup = 0;
1590    
1591                                    /* approximate the pixel */
1592                                    while (j--)
1593                                    {
1594                                            if (xc_cache[j].flags)
1595                                            {
1596                                                    nDist = ((long) (xc_cache[j].red >> 8) -
1597                                                             (long) (xentry.red >> 8)) *
1598                                                            ((long) (xc_cache[j].red >> 8) -
1599                                                             (long) (xentry.red >> 8)) +
1600                                                            ((long) (xc_cache[j].green >> 8) -
1601                                                             (long) (xentry.green >> 8)) *
1602                                                            ((long) (xc_cache[j].green >> 8) -
1603                                                             (long) (xentry.green >> 8)) +
1604                                                            ((long) (xc_cache[j].blue >> 8) -
1605                                                             (long) (xentry.blue >> 8)) *
1606                                                            ((long) (xc_cache[j].blue >> 8) -
1607                                                             (long) (xentry.blue >> 8));
1608                                            }
1609                                            if (nDist < nMinDist)
1610                                            {
1611                                                    nMinDist = nDist;
1612                                                    xentry.pixel = j;
1613                                            }
1614                                    }
1615                            }
1616                            colour = xentry.pixel;
1617    
1618                            /* update our cache */
1619                            if (xentry.pixel < 256)
1620                            {
1621                                    xc_cache[xentry.pixel].red = xentry.red;
1622                                    xc_cache[xentry.pixel].green = xentry.green;
1623                                    xc_cache[xentry.pixel].blue = xentry.blue;
1624    
1625                            }
1626    
1627                  xentry->pixel = i;                          map[i] = colour;
1628                  xentry->red = entry->red << 8;                  }
1629                  xentry->blue = entry->blue << 8;                  return map;
                 xentry->green = entry->green << 8;  
                 xentry->flags = DoRed | DoBlue | DoGreen;  
1630          }          }
1631            else
1632            {
1633                    XColor *xcolours, *xentry;
1634                    Colormap map;
1635    
1636                    xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1637                    for (i = 0; i < ncolours; i++)
1638                    {
1639                            entry = &colours->colours[i];
1640                            xentry = &xcolours[i];
1641                            xentry->pixel = i;
1642                            MAKE_XCOLOR(xentry, entry);
1643                    }
1644    
1645          map = XCreateColormap(display, wnd, visual, AllocAll);                  map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1646          XStoreColors(display, map, xcolours, ncolours);                  XStoreColors(g_display, map, xcolours, ncolours);
1647    
1648          xfree(xcolours);                  xfree(xcolours);
1649          return (HCOLOURMAP) map;                  return (HCOLOURMAP) map;
1650            }
1651  }  }
1652    
1653  void ui_destroy_colourmap(HCOLOURMAP map)  void
1654    ui_destroy_colourmap(HCOLOURMAP map)
1655  {  {
1656          XFreeColormap(display, (Colormap) map);          if (!g_owncolmap)
1657                    xfree(map);
1658            else
1659                    XFreeColormap(g_display, (Colormap) map);
1660  }  }
1661    
1662  void ui_set_colourmap(HCOLOURMAP map)  void
1663    ui_set_colourmap(HCOLOURMAP map)
1664  {  {
1665          XSetWindowColormap(display, wnd, (Colormap) map);          if (!g_owncolmap)
1666            {
1667                    if (g_colmap)
1668                            xfree(g_colmap);
1669    
1670                    g_colmap = (uint32 *) map;
1671            }
1672            else
1673                    XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1674  }  }
1675    
1676  void ui_set_clip(int x, int y, int cx, int cy)  void
1677    ui_set_clip(int x, int y, int cx, int cy)
1678  {  {
1679          XRectangle rect;          XRectangle rect;
1680    
# Line 319  void ui_set_clip(int x, int y, int cx, i Line 1682  void ui_set_clip(int x, int y, int cx, i
1682          rect.y = y;          rect.y = y;
1683          rect.width = cx;          rect.width = cx;
1684          rect.height = cy;          rect.height = cy;
1685          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1686  }  }
1687    
1688  void ui_reset_clip()  void
1689    ui_reset_clip(void)
1690  {  {
1691          XRectangle rect;          XRectangle rect;
1692    
1693          rect.x = 0;          rect.x = 0;
1694          rect.y = 0;          rect.y = 0;
1695          rect.width = width;          rect.width = g_width;
1696          rect.height = height;          rect.height = g_height;
1697          XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);          XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1698  }  }
1699    
1700  void ui_bell()  void
1701    ui_bell(void)
1702  {  {
1703          XBell(display, 0);          XBell(g_display, 0);
1704  }  }
1705    
1706  static int rop2_map[] = {  void
1707          GXclear,                /* 0 */  ui_destblt(uint8 opcode,
1708          GXnor,                  /* DPon */             /* dest */ int x, int y, int cx, int cy)
         GXandInverted,          /* DPna */  
         GXcopyInverted,         /* Pn */  
         GXandReverse,           /* PDna */  
         GXinvert,               /* Dn */  
         GXxor,                  /* DPx */  
         GXnand,                 /* DPan */  
         GXand,                  /* DPa */  
         GXequiv,                /* DPxn */  
         GXnoop,                 /* D */  
         GXorInverted,           /* DPno */  
         GXcopy,                 /* P */  
         GXorReverse,            /* PDno */  
         GXor,                   /* DPo */  
         GXset                   /* 1 */  
 };  
   
 static void xwin_set_function(uint8 rop2)  
1709  {  {
1710          XSetFunction(display, gc, rop2_map[rop2]);          SET_FUNCTION(opcode);
1711            FILL_RECTANGLE(x, y, cx, cy);
1712            RESET_FUNCTION(opcode);
1713  }  }
1714    
1715  void ui_destblt(uint8 opcode,  static uint8 hatch_patterns[] = {
1716                  /* dest */ int x, int y, int cx, int cy)          0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1717  {          0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1718          xwin_set_function(opcode);          0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1719            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1720          XFillRectangle(display, wnd, gc, x, y, cx, cy);          0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1721  }          0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81  /* 5 - bsDiagCross */
1722    };
1723    
1724  void ui_patblt(uint8 opcode,  void
1725                 /* dest */ int x, int y, int cx, int cy,  ui_patblt(uint8 opcode,
1726                 /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* dest */ int x, int y, int cx, int cy,
1727              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1728  {  {
         Display *dpy = display;  
1729          Pixmap fill;          Pixmap fill;
1730            uint8 i, ipattern[8];
1731    
1732          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1733    
1734          switch (brush->style)          switch (brush->style)
1735          {          {
1736                  case 0: /* Solid */                  case 0: /* Solid */
1737                          XSetForeground(dpy, gc, fgcolour);                          SET_FOREGROUND(fgcolour);
1738                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1739                          break;                          break;
1740    
1741                  case 3: /* Pattern */                  case 2: /* Hatch */
1742                          fill = (Pixmap) ui_create_glyph(8, 8, brush->pattern);                          fill = (Pixmap) ui_create_glyph(8, 8,
1743                                                            hatch_patterns + brush->pattern[0] * 8);
1744                            SET_FOREGROUND(fgcolour);
1745                            SET_BACKGROUND(bgcolour);
1746                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1747                            XSetStipple(g_display, g_gc, fill);
1748                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1749                            FILL_RECTANGLE(x, y, cx, cy);
1750                            XSetFillStyle(g_display, g_gc, FillSolid);
1751                            XSetTSOrigin(g_display, g_gc, 0, 0);
1752                            ui_destroy_glyph((HGLYPH) fill);
1753                            break;
1754    
1755                          XSetForeground(dpy, gc, fgcolour);                  case 3: /* Pattern */
1756                          XSetBackground(dpy, gc, bgcolour);                          for (i = 0; i != 8; i++)
1757                          XSetFillStyle(dpy, gc, FillOpaqueStippled);                                  ipattern[7 - i] = brush->pattern[i];
1758                          XSetStipple(dpy, gc, fill);                          fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1759    
1760                            SET_FOREGROUND(bgcolour);
1761                            SET_BACKGROUND(fgcolour);
1762                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1763                            XSetStipple(g_display, g_gc, fill);
1764                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1765    
1766                          XFillRectangle(dpy, wnd, gc, x, y, cx, cy);                          FILL_RECTANGLE(x, y, cx, cy);
1767    
1768                          XSetFillStyle(dpy, gc, FillSolid);                          XSetFillStyle(g_display, g_gc, FillSolid);
1769                            XSetTSOrigin(g_display, g_gc, 0, 0);
1770                          ui_destroy_glyph((HGLYPH) fill);                          ui_destroy_glyph((HGLYPH) fill);
1771                          break;                          break;
1772    
1773                  default:                  default:
1774                          NOTIMP("brush %d\n", brush->style);                          unimpl("brush %d\n", brush->style);
1775          }          }
 }  
1776    
1777  void ui_screenblt(uint8 opcode,          RESET_FUNCTION(opcode);
                   /* dest */ int x, int y, int cx, int cy,  
                   /* src */ int srcx, int srcy)  
 {  
         xwin_set_function(opcode);  
   
         XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);  
1778  }  }
1779    
1780  void ui_memblt(uint8 opcode,  void
1781                 /* dest */ int x, int y, int cx, int cy,  ui_screenblt(uint8 opcode,
1782                 /* src */ HBITMAP src, int srcx, int srcy)               /* dest */ int x, int y, int cx, int cy,
1783                 /* src */ int srcx, int srcy)
1784  {  {
1785          xwin_set_function(opcode);          SET_FUNCTION(opcode);
1786            if (g_ownbackstore)
1787          XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);          {
1788                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1789                    XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1790            }
1791            else
1792            {
1793                    XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1794            }
1795            RESET_FUNCTION(opcode);
1796  }  }
1797    
1798  void ui_triblt(uint8 opcode,  void
1799                 /* dest */ int x, int y, int cx, int cy,  ui_memblt(uint8 opcode,
1800                 /* src */ HBITMAP src, int srcx, int srcy,            /* dest */ int x, int y, int cx, int cy,
1801                 /* brush */ BRUSH *brush, int bgcolour, int fgcolour)            /* src */ HBITMAP src, int srcx, int srcy)
1802    {
1803            SET_FUNCTION(opcode);
1804            XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1805            if (g_ownbackstore)
1806                    XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1807            RESET_FUNCTION(opcode);
1808    }
1809    
1810    void
1811    ui_triblt(uint8 opcode,
1812              /* dest */ int x, int y, int cx, int cy,
1813              /* src */ HBITMAP src, int srcx, int srcy,
1814              /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1815  {  {
1816          /* This is potentially difficult to do in general. Until someone          /* This is potentially difficult to do in general. Until someone
1817             comes up with a more efficient way of doing it I am using cases. */             comes up with a more efficient way of doing it I am using cases. */
# Line 435  void ui_triblt(uint8 opcode, Line 1820  void ui_triblt(uint8 opcode,
1820          {          {
1821                  case 0x69:      /* PDSxxn */                  case 0x69:      /* PDSxxn */
1822                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1823                          ui_patblt(ROP2_NXOR, x, y, cx, cy,                          ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1824                          break;                          break;
1825    
1826                  case 0xb8:      /* PSDPxax */                  case 0xb8:      /* PSDPxax */
1827                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
                                   brush, bgcolour, fgcolour);  
1828                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1829                          ui_patblt(ROP2_XOR, x, y, cx, cy,                          ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1830                                    brush, bgcolour, fgcolour);                          break;
1831    
1832                    case 0xc0:      /* PSa */
1833                            ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1834                            ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1835                          break;                          break;
1836    
1837                  default:                  default:
1838                          NOTIMP("triblt 0x%x\n", opcode);                          unimpl("triblt 0x%x\n", opcode);
1839                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);                          ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1840          }          }
1841  }  }
1842    
1843  void ui_line(uint8 opcode,  void
1844               /* dest */ int startx, int starty, int endx, int endy,  ui_line(uint8 opcode,
1845               /* pen */ PEN *pen)          /* dest */ int startx, int starty, int endx, int endy,
1846  {          /* pen */ PEN * pen)
1847          xwin_set_function(opcode);  {
1848            SET_FUNCTION(opcode);
1849          XSetForeground(display, gc, pen->colour);          SET_FOREGROUND(pen->colour);
1850          XDrawLine(display, wnd, gc, startx, starty, endx, endy);          XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1851            if (g_ownbackstore)
1852                    XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1853            RESET_FUNCTION(opcode);
1854  }  }
1855    
1856  void ui_rect(  void
1857                      /* dest */ int x, int y, int cx, int cy,  ui_rect(
1858                      /* brush */ int colour)                 /* dest */ int x, int y, int cx, int cy,
1859                   /* brush */ int colour)
1860  {  {
1861          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(colour);
1862            FILL_RECTANGLE(x, y, cx, cy);
         XSetForeground(display, gc, colour);  
         XFillRectangle(display, wnd, gc, x, y, cx, cy);  
1863  }  }
1864    
1865  void ui_draw_glyph(int mixmode,  /* warning, this function only draws on wnd or backstore, not both */
1866                     /* dest */ int x, int y, int cx, int cy,  void
1867                     /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour,  ui_draw_glyph(int mixmode,
1868                     int fgcolour)                /* dest */ int x, int y, int cx, int cy,
1869  {                /* src */ HGLYPH glyph, int srcx, int srcy,
1870          Pixmap pixmap = (Pixmap) glyph;                int bgcolour, int fgcolour)
1871    {
1872          xwin_set_function(ROP2_COPY);          SET_FOREGROUND(fgcolour);
1873            SET_BACKGROUND(bgcolour);
1874          XSetForeground(display, gc, fgcolour);  
1875            XSetFillStyle(g_display, g_gc,
1876          switch (mixmode)                        (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1877          {          XSetStipple(g_display, g_gc, (Pixmap) glyph);
1878                  case MIX_TRANSPARENT:          XSetTSOrigin(g_display, g_gc, x, y);
1879                          XSetStipple(display, gc, pixmap);  
1880                          XSetFillStyle(display, gc, FillStippled);          FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1881                          XSetTSOrigin(display, gc, x, y);  
1882                          XFillRectangle(display, wnd, gc, x, y, cx, cy);          XSetFillStyle(g_display, g_gc, FillSolid);
1883                          XSetFillStyle(display, gc, FillSolid);  }
1884                          break;  
1885    #define DO_GLYPH(ttext,idx) \
1886                  case MIX_OPAQUE:  {\
1887                          XSetBackground(display, gc, bgcolour);    glyph = cache_get_font (font, ttext[idx]);\
1888                          XCopyPlane(display, pixmap, wnd, gc,    if (!(flags & TEXT2_IMPLICIT_X))\
1889                                     srcx, srcy, cx, cy, x, y, 1);    {\
1890                          break;      xyoffset = ttext[++idx];\
1891        if ((xyoffset & 0x80))\
1892                  default:      {\
1893                          NOTIMP("mix %d\n", mixmode);        if (flags & TEXT2_VERTICAL)\
1894          }          y += ttext[idx+1] | (ttext[idx+2] << 8);\
1895  }        else\
1896            x += ttext[idx+1] | (ttext[idx+2] << 8);\
1897  void ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,        idx += 2;\
1898                    int clipx, int clipy, int clipcx, int clipcy,      }\
1899                    int boxx, int boxy, int boxcx, int boxcy,      else\
1900                    int bgcolour, int fgcolour, uint8 *text, uint8 length)      {\
1901          if (flags & TEXT2_VERTICAL)\
1902            y += xyoffset;\
1903          else\
1904            x += xyoffset;\
1905        }\
1906      }\
1907      if (glyph != NULL)\
1908      {\
1909        x1 = x + glyph->offset;\
1910        y1 = y + glyph->baseline;\
1911        XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
1912        XSetTSOrigin(g_display, g_gc, x1, y1);\
1913        FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
1914        if (flags & TEXT2_IMPLICIT_X)\
1915          x += glyph->width;\
1916      }\
1917    }
1918    
1919    void
1920    ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1921                 int clipx, int clipy, int clipcx, int clipcy,
1922                 int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1923                 int fgcolour, uint8 * text, uint8 length)
1924  {  {
1925          FONTGLYPH *glyph;          FONTGLYPH *glyph;
1926          int i;          int i, j, xyoffset, x1, y1;
1927            DATABLOB *entry;
1928    
1929            SET_FOREGROUND(bgcolour);
1930    
1931          if (boxcx > 1)          if (boxcx > 1)
1932          {          {
1933                  ui_rect(boxx, boxy, boxcx, boxcy, bgcolour);                  FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1934          }          }
1935          else if (mixmode == MIX_OPAQUE)          else if (mixmode == MIX_OPAQUE)
1936          {          {
1937                  ui_rect(clipx, clipy, clipcx, clipcy, bgcolour);                  FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1938          }          }
1939    
1940            SET_FOREGROUND(fgcolour);
1941            SET_BACKGROUND(bgcolour);
1942            XSetFillStyle(g_display, g_gc, FillStippled);
1943    
1944          /* Paint text, character by character */          /* Paint text, character by character */
1945          for (i = 0; i < length; i++)          for (i = 0; i < length;)
1946          {          {
1947                  glyph = cache_get_font(font, text[i]);                  switch (text[i])
   
                 if (!(flags & TEXT2_IMPLICIT_X))  
                         x += text[++i];  
   
                 if (glyph != NULL)  
1948                  {                  {
1949                          ui_draw_glyph(mixmode, x + (short) glyph->offset,                          case 0xff:
1950                                        y + (short) glyph->baseline,                                  if (i + 2 < length)
1951                                        glyph->width, glyph->height,                                          cache_put_text(text[i + 1], text, text[i + 2]);
1952                                        glyph->pixmap, 0, 0,                                  else
1953                                        bgcolour, fgcolour);                                  {
1954                                            error("this shouldn't be happening\n");
1955                                            exit(1);
1956                                    }
1957                                    /* this will move pointer from start to first character after FF command */
1958                                    length -= i + 3;
1959                                    text = &(text[i + 3]);
1960                                    i = 0;
1961                                    break;
1962    
1963                          if (flags & TEXT2_IMPLICIT_X)                          case 0xfe:
1964                                  x += glyph->width;                                  entry = cache_get_text(text[i + 1]);
1965                                    if (entry != NULL)
1966                                    {
1967                                            if ((((uint8 *) (entry->data))[1] ==
1968                                                 0) && (!(flags & TEXT2_IMPLICIT_X)))
1969                                            {
1970                                                    if (flags & TEXT2_VERTICAL)
1971                                                            y += text[i + 2];
1972                                                    else
1973                                                            x += text[i + 2];
1974                                            }
1975                                            for (j = 0; j < entry->size; j++)
1976                                                    DO_GLYPH(((uint8 *) (entry->data)), j);
1977                                    }
1978                                    if (i + 2 < length)
1979                                            i += 3;
1980                                    else
1981                                            i += 2;
1982                                    length -= i;
1983                                    /* this will move pointer from start to first character after FE command */
1984                                    text = &(text[i]);
1985                                    i = 0;
1986                                    break;
1987    
1988                            default:
1989                                    DO_GLYPH(text, i);
1990                                    i++;
1991                                    break;
1992                  }                  }
1993          }          }
1994    
1995            XSetFillStyle(g_display, g_gc, FillSolid);
1996    
1997            if (g_ownbackstore)
1998            {
1999                    if (boxcx > 1)
2000                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2001                                      boxy, boxcx, boxcy, boxx, boxy);
2002                    else
2003                            XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2004                                      clipy, clipcx, clipcy, clipx, clipy);
2005            }
2006  }  }
2007    
2008  void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)  void
2009    ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
2010  {  {
2011            Pixmap pix;
2012          XImage *image;          XImage *image;
2013    
2014          image = XGetImage(display, wnd, x, y, cx, cy, 0xffffffff, ZPixmap);          if (g_ownbackstore)
2015          cache_put_desktop(offset, cx, cy, image->bytes_per_line, image->data);          {
2016          XFree(image->data);                  image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
2017          XFree(image);          }
2018            else
2019            {
2020                    pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2021                    XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
2022                    image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2023                    XFreePixmap(g_display, pix);
2024            }
2025    
2026            offset *= g_bpp / 8;
2027            cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
2028    
2029            XDestroyImage(image);
2030  }  }
2031    
2032  void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)  void
2033    ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
2034  {  {
2035          XImage *image;          XImage *image;
2036          uint8 *data;          uint8 *data;
2037    
2038          data = cache_get_desktop(offset, cx, cy);          offset *= g_bpp / 8;
2039            data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2040          if (data == NULL)          if (data == NULL)
2041                  return;                  return;
2042    
2043          image = XCreateImage(display, visual, 8, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2044                               data, cx, cy, 32, cx);                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
2045          XSetFunction(display, gc, GXcopy);  
2046          XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);          if (g_ownbackstore)
2047            {
2048                    XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2049                    XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2050            }
2051            else
2052            {
2053                    XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2054            }
2055    
2056          XFree(image);          XFree(image);
2057  }  }

Legend:
Removed from v.24  
changed lines
  Added in v.609

  ViewVC Help
Powered by ViewVC 1.1.26