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

Legend:
Removed from v.28  
changed lines
  Added in v.709

  ViewVC Help
Powered by ViewVC 1.1.26