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

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

  ViewVC Help
Powered by ViewVC 1.1.26