/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

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

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26