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

Legend:
Removed from v.25  
changed lines
  Added in v.677

  ViewVC Help
Powered by ViewVC 1.1.26