~ubuntu-branches/debian/stretch/rdesktop/stretch

« back to all changes in this revision

Viewing changes to xwin.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Johnston
  • Date: 2004-02-04 17:52:26 UTC
  • Revision ID: james.westby@ubuntu.com-20040204175226-87kz4bzs1nimji68
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- c-basic-offset: 8 -*-
 
2
   rdesktop: A Remote Desktop Protocol client.
 
3
   User interface services - X Window System
 
4
   Copyright (C) Matthew Chapman 1999-2002
 
5
 
 
6
   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
 
8
   the Free Software Foundation; either version 2 of the License, or
 
9
   (at your option) any later version.
 
10
 
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program; if not, write to the Free Software
 
18
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
*/
 
20
 
 
21
#include <X11/Xlib.h>
 
22
#include <X11/Xutil.h>
 
23
#include <unistd.h>
 
24
#include <time.h>
 
25
#include <errno.h>
 
26
#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
static void
 
291
translate8to32(uint8 * data, uint8 * out, uint8 * end)
 
292
{
 
293
        uint32 value;
 
294
 
 
295
        while (out < end)
 
296
        {
 
297
                value = g_colmap[*(data++)];
 
298
 
 
299
                if (g_xserver_be)
 
300
                {
 
301
                        *(out++) = value >> 24;
 
302
                        *(out++) = value >> 16;
 
303
                        *(out++) = value >> 8;
 
304
                        *(out++) = value;
 
305
                }
 
306
                else
 
307
                {
 
308
                        *(out++) = value;
 
309
                        *(out++) = value >> 8;
 
310
                        *(out++) = value >> 16;
 
311
                        *(out++) = value >> 24;
 
312
                }
 
313
        }
 
314
}
 
315
 
 
316
static void
 
317
translate15to16(uint16 * data, uint8 * out, uint8 * end)
 
318
{
 
319
        uint16 pixel;
 
320
        uint16 value;
 
321
 
 
322
        while (out < end)
 
323
        {
 
324
                pixel = *(data++);
 
325
 
 
326
                if (g_host_be)
 
327
                {
 
328
                        BSWAP16(pixel);
 
329
                }
 
330
 
 
331
                value = make_colour(split_colour15(pixel));
 
332
 
 
333
                if (g_xserver_be)
 
334
                {
 
335
                        *(out++) = value >> 8;
 
336
                        *(out++) = value;
 
337
                }
 
338
                else
 
339
                {
 
340
                        *(out++) = value;
 
341
                        *(out++) = value >> 8;
 
342
                }
 
343
        }
 
344
}
 
345
 
 
346
static void
 
347
translate15to24(uint16 * data, uint8 * out, uint8 * end)
 
348
{
 
349
        uint32 value;
 
350
        uint16 pixel;
 
351
 
 
352
        while (out < end)
 
353
        {
 
354
                pixel = *(data++);
 
355
 
 
356
                if (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
 
666
get_key_state(unsigned int state, uint32 keysym)
 
667
{
 
668
        int modifierpos, key, keysymMask = 0;
 
669
        int offset;
 
670
 
 
671
        KeyCode keycode = XKeysymToKeycode(g_display, keysym);
 
672
 
 
673
        if (keycode == NoSymbol)
 
674
                return False;
 
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
static void
 
691
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: %s\n", XDisplayName(NULL));
 
713
                return False;
 
714
        }
 
715
 
 
716
        screen_num = DefaultScreen(g_display);
 
717
        g_x_socket = ConnectionNumber(g_display);
 
718
        g_screen = ScreenOfDisplay(g_display, screen_num);
 
719
        g_depth = DefaultDepthOfScreen(g_screen);
 
720
 
 
721
        /* Search for best TrueColor depth */
 
722
        template.class = TrueColor;
 
723
        vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);
 
724
 
 
725
        nvisuals--;
 
726
        while (nvisuals >= 0)
 
727
        {
 
728
                if ((vmatches + nvisuals)->depth > g_depth)
 
729
                {
 
730
                        g_depth = (vmatches + nvisuals)->depth;
 
731
                }
 
732
                nvisuals--;
 
733
                TrueColorVisual = True;
 
734
        }
 
735
 
 
736
        if ((g_server_bpp == 8) && ((! TrueColorVisual) || (g_depth <= 8)))
 
737
        {
 
738
                /* we use a colourmap, so the default visual should do */
 
739
                g_visual = DefaultVisualOfScreen(g_screen);
 
740
                g_depth = DefaultDepthOfScreen(g_screen);
 
741
 
 
742
                /* Do not allocate colours on a TrueColor visual */
 
743
                if (g_visual->class == TrueColor)
 
744
                {
 
745
                        g_owncolmap = False;
 
746
                }
 
747
        }
 
748
        else
 
749
        {
 
750
                /* need a truecolour visual */
 
751
                if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))
 
752
                {
 
753
                        error("The display does not support true colour - high colour support unavailable.\n");
 
754
                        return False;
 
755
                }
 
756
 
 
757
                g_visual = vi.visual;
 
758
                g_owncolmap = False;
 
759
                calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);
 
760
                calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);
 
761
                calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);
 
762
        }
 
763
 
 
764
        pfm = XListPixmapFormats(g_display, &i);
 
765
        if (pfm != NULL)
 
766
        {
 
767
                /* Use maximum bpp for this depth - this is generally
 
768
                   desirable, e.g. 24 bits->32 bits. */
 
769
                while (i--)
 
770
                {
 
771
                        if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
 
772
                        {
 
773
                                g_bpp = pfm[i].bits_per_pixel;
 
774
                        }
 
775
                }
 
776
                XFree(pfm);
 
777
        }
 
778
 
 
779
        if (g_bpp < 8)
 
780
        {
 
781
                error("Less than 8 bpp not currently supported.\n");
 
782
                XCloseDisplay(g_display);
 
783
                return False;
 
784
        }
 
785
 
 
786
        if (!g_owncolmap)
 
787
        {
 
788
                g_xcolmap = 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
        if (DoesBackingStore(g_screen) != Always)
 
794
                g_ownbackstore = True;
 
795
 
 
796
        test = 1;
 
797
        g_host_be = !(BOOL) (*(uint8 *) (&test));
 
798
        g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
 
799
 
 
800
        /*
 
801
         * Determine desktop size
 
802
         */
 
803
        if (g_fullscreen)
 
804
        {
 
805
                g_width = WidthOfScreen(g_screen);
 
806
                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
        DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));
 
845
 
 
846
        return True;
 
847
}
 
848
 
 
849
void
 
850
ui_deinit(void)
 
851
{
 
852
        if (g_IM != NULL)
 
853
                XCloseIM(g_IM);
 
854
 
 
855
        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
BOOL
 
866
ui_create_window(void)
 
867
{
 
868
        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 ( ! g_gc_initialized )
 
892
        {
 
893
                g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
 
894
                g_gc_initialized = True;
 
895
        }
 
896
 
 
897
        if ((g_ownbackstore) && (! g_backstore_initialized))
 
898
        {
 
899
                g_backstore =
 
900
                        XCreatePixmap(g_display, g_wnd, g_width, g_height,
 
901
                                      g_depth);
 
902
 
 
903
                /* clear to prevent rubbish being exposed at startup */
 
904
                XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
 
905
                XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
 
906
                g_backstore_initialized = True;
 
907
        }
 
908
 
 
909
        XStoreName(g_display, g_wnd, g_title);
 
910
 
 
911
        if (g_hide_decorations)
 
912
                mwm_hide_decorations();
 
913
 
 
914
        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
                g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
 
947
                                 XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
 
948
 
 
949
                if ((g_IC != NULL)
 
950
                    && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
 
951
                        input_mask |= ic_input_mask;
 
952
        }
 
953
 
 
954
        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
 
979
ui_destroy_window(void)
 
980
{
 
981
        if (g_IC != NULL)
 
982
                XDestroyIC(g_IC);
 
983
 
 
984
        XDestroyWindow(g_display, g_wnd);
 
985
}
 
986
 
 
987
void
 
988
xwin_toggle_fullscreen(void)
 
989
{
 
990
        Pixmap contents = 0;
 
991
 
 
992
        if (!g_ownbackstore)
 
993
        {
 
994
                /* 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
        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:
 
1048
                                g_last_gesturetime = xevent.xkey.time;
 
1049
                                if (g_IC != NULL)
 
1050
                                        /* Multi_key compatible version */
 
1051
                                {
 
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;
 
1082
 
 
1083
                                save_remote_modifiers(tr.scancode);
 
1084
                                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;
 
1089
 
 
1090
                        case KeyRelease:
 
1091
                                g_last_gesturetime = xevent.xkey.time;
 
1092
                                XLookupString((XKeyEvent *) & xevent, str,
 
1093
                                              sizeof(str), &keysym, NULL);
 
1094
 
 
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;
 
1101
 
 
1102
                                tr = xkeymap_translate_key(keysym,
 
1103
                                                           xevent.xkey.keycode, xevent.xkey.state);
 
1104
 
 
1105
                                if (tr.scancode == 0)
 
1106
                                        break;
 
1107
 
 
1108
                                rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
 
1109
                                break;
 
1110
 
 
1111
                        case ButtonPress:
 
1112
                                flags = MOUSE_FLAG_DOWN;
 
1113
                                /* fall through */
 
1114
 
 
1115
                        case ButtonRelease:
 
1116
                                g_last_gesturetime = xevent.xbutton.time;
 
1117
                                button = xkeymap_translate_button(xevent.xbutton.button);
 
1118
                                if (button == 0)
 
1119
                                        break;
 
1120
 
 
1121
                                /* If win_button_size is nonzero, enable single app mode */
 
1122
                                if (xevent.xbutton.y < g_win_button_size)
 
1123
                                {
 
1124
                                        /* 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;
 
1175
 
 
1176
                        case MotionNotify:
 
1177
                                if (g_moving_wnd)
 
1178
                                {
 
1179
                                        XMoveWindow(g_display, g_wnd,
 
1180
                                                    xevent.xmotion.x_root - g_move_x_offset,
 
1181
                                                    xevent.xmotion.y_root - g_move_y_offset);
 
1182
                                        break;
 
1183
                                }
 
1184
 
 
1185
                                if (g_fullscreen && !g_focused)
 
1186
                                        XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
 
1187
                                                       CurrentTime);
 
1188
                                rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
 
1189
                                               MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
 
1190
                                break;
 
1191
 
 
1192
                        case FocusIn:
 
1193
                                if (xevent.xfocus.mode == NotifyGrab)
 
1194
                                        break;
 
1195
                                g_focused = True;
 
1196
                                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
 
1320
ui_move_pointer(int x, int y)
 
1321
{
 
1322
        XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
 
1323
}
 
1324
 
 
1325
HBITMAP
 
1326
ui_create_bitmap(int width, int height, uint8 * data)
 
1327
{
 
1328
        XImage *image;
 
1329
        Pixmap bitmap;
 
1330
        uint8 *tdata;
 
1331
        int bitmap_pad;
 
1332
 
 
1333
        if (g_server_bpp == 8)
 
1334
        {
 
1335
                bitmap_pad = 8;
 
1336
        }
 
1337
        else
 
1338
        {
 
1339
                bitmap_pad = g_bpp;
 
1340
 
 
1341
                if (g_bpp == 24)
 
1342
                        bitmap_pad = 32;
 
1343
        }
 
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;
 
1356
}
 
1357
 
 
1358
void
 
1359
ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
 
1360
{
 
1361
        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
 
 
1391
        XFree(image);
 
1392
        if (!g_owncolmap)
 
1393
                xfree(tdata);
 
1394
}
 
1395
 
 
1396
void
 
1397
ui_destroy_bitmap(HBITMAP bmp)
 
1398
{
 
1399
        XFreePixmap(g_display, (Pixmap) bmp);
 
1400
}
 
1401
 
 
1402
HGLYPH
 
1403
ui_create_glyph(int width, int height, uint8 * data)
 
1404
{
 
1405
        XImage *image;
 
1406
        Pixmap bitmap;
 
1407
        int scanline;
 
1408
        GC gc;
 
1409
 
 
1410
        scanline = (width + 7) / 8;
 
1411
 
 
1412
        bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
 
1413
        gc = XCreateGC(g_display, bitmap, 0, NULL);
 
1414
 
 
1415
        image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
 
1416
                             width, height, 8, scanline);
 
1417
        image->byte_order = MSBFirst;
 
1418
        image->bitmap_bit_order = MSBFirst;
 
1419
        XInitImage(image);
 
1420
 
 
1421
        XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
 
1422
 
 
1423
        XFree(image);
 
1424
        XFreeGC(g_display, gc);
 
1425
        return (HGLYPH) bitmap;
 
1426
}
 
1427
 
 
1428
void
 
1429
ui_destroy_glyph(HGLYPH glyph)
 
1430
{
 
1431
        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
 
1532
ui_create_colourmap(COLOURMAP * colours)
 
1533
{
 
1534
        COLOURENTRY *entry;
 
1535
        int i, ncolours = colours->ncolours;
 
1536
        if (!g_owncolmap)
 
1537
        {
 
1538
                uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
 
1539
                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
                        }
 
1604
 
 
1605
                        map[i] = colour;
 
1606
                }
 
1607
                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(g_display, g_wnd, g_visual, AllocAll);
 
1624
                XStoreColors(g_display, map, xcolours, ncolours);
 
1625
 
 
1626
                xfree(xcolours);
 
1627
                return (HCOLOURMAP) map;
 
1628
        }
 
1629
}
 
1630
 
 
1631
void
 
1632
ui_destroy_colourmap(HCOLOURMAP map)
 
1633
{
 
1634
        if (!g_owncolmap)
 
1635
                xfree(map);
 
1636
        else
 
1637
                XFreeColormap(g_display, (Colormap) map);
 
1638
}
 
1639
 
 
1640
void
 
1641
ui_set_colourmap(HCOLOURMAP map)
 
1642
{
 
1643
        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
 
1655
ui_set_clip(int x, int y, int cx, int cy)
 
1656
{
 
1657
        XRectangle rect;
 
1658
 
 
1659
        rect.x = x;
 
1660
        rect.y = y;
 
1661
        rect.width = cx;
 
1662
        rect.height = cy;
 
1663
        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
 
1664
}
 
1665
 
 
1666
void
 
1667
ui_reset_clip(void)
 
1668
{
 
1669
        XRectangle rect;
 
1670
 
 
1671
        rect.x = 0;
 
1672
        rect.y = 0;
 
1673
        rect.width = g_width;
 
1674
        rect.height = g_height;
 
1675
        XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
 
1676
}
 
1677
 
 
1678
void
 
1679
ui_bell(void)
 
1680
{
 
1681
        XBell(g_display, 0);
 
1682
}
 
1683
 
 
1684
void
 
1685
ui_destblt(uint8 opcode,
 
1686
           /* dest */ int x, int y, int cx, int cy)
 
1687
{
 
1688
        SET_FUNCTION(opcode);
 
1689
        FILL_RECTANGLE(x, y, cx, cy);
 
1690
        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
 
1703
ui_patblt(uint8 opcode,
 
1704
          /* dest */ int x, int y, int cx, int cy,
 
1705
          /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
 
1706
{
 
1707
        Pixmap fill;
 
1708
        uint8 i, ipattern[8];
 
1709
 
 
1710
        SET_FUNCTION(opcode);
 
1711
 
 
1712
        switch (brush->style)
 
1713
        {
 
1714
                case 0: /* Solid */
 
1715
                        SET_FOREGROUND(fgcolour);
 
1716
                        FILL_RECTANGLE(x, y, cx, cy);
 
1717
                        break;
 
1718
 
 
1719
                case 2: /* Hatch */
 
1720
                        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
                case 3: /* Pattern */
 
1734
                        for (i = 0; i != 8; i++)
 
1735
                                ipattern[7 - i] = brush->pattern[i];
 
1736
                        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
                        FILL_RECTANGLE(x, y, cx, cy);
 
1745
 
 
1746
                        XSetFillStyle(g_display, g_gc, FillSolid);
 
1747
                        XSetTSOrigin(g_display, g_gc, 0, 0);
 
1748
                        ui_destroy_glyph((HGLYPH) fill);
 
1749
                        break;
 
1750
 
 
1751
                default:
 
1752
                        unimpl("brush %d\n", brush->style);
 
1753
        }
 
1754
 
 
1755
        RESET_FUNCTION(opcode);
 
1756
}
 
1757
 
 
1758
void
 
1759
ui_screenblt(uint8 opcode,
 
1760
             /* dest */ int x, int y, int cx, int cy,
 
1761
             /* src */ int srcx, int srcy)
 
1762
{
 
1763
        SET_FUNCTION(opcode);
 
1764
        XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
 
1765
        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
 
1771
ui_memblt(uint8 opcode,
 
1772
          /* dest */ int x, int y, int cx, int cy,
 
1773
          /* src */ HBITMAP src, int srcx, int srcy)
 
1774
{
 
1775
        SET_FUNCTION(opcode);
 
1776
        XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
 
1777
        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
 
1783
ui_triblt(uint8 opcode,
 
1784
          /* dest */ int x, int y, int cx, int cy,
 
1785
          /* src */ HBITMAP src, int srcx, int srcy,
 
1786
          /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
 
1787
{
 
1788
        /* 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. */
 
1790
 
 
1791
        switch (opcode)
 
1792
        {
 
1793
                case 0x69:      /* PDSxxn */
 
1794
                        ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
 
1795
                        ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
 
1796
                        break;
 
1797
 
 
1798
                case 0xb8:      /* PSDPxax */
 
1799
                        ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
 
1800
                        ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
 
1801
                        ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
 
1802
                        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;
 
1808
 
 
1809
                default:
 
1810
                        unimpl("triblt 0x%x\n", opcode);
 
1811
                        ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
 
1812
        }
 
1813
}
 
1814
 
 
1815
void
 
1816
ui_line(uint8 opcode,
 
1817
        /* dest */ int startx, int starty, int endx, int endy,
 
1818
        /* pen */ PEN * pen)
 
1819
{
 
1820
        SET_FUNCTION(opcode);
 
1821
        SET_FOREGROUND(pen->colour);
 
1822
        XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
 
1823
        if (g_ownbackstore)
 
1824
                XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
 
1825
        RESET_FUNCTION(opcode);
 
1826
}
 
1827
 
 
1828
void
 
1829
ui_rect(
 
1830
               /* dest */ int x, int y, int cx, int cy,
 
1831
               /* brush */ int colour)
 
1832
{
 
1833
        SET_FOREGROUND(colour);
 
1834
        FILL_RECTANGLE(x, y, cx, cy);
 
1835
}
 
1836
 
 
1837
/* warning, this function only draws on wnd or backstore, not both */
 
1838
void
 
1839
ui_draw_glyph(int mixmode,
 
1840
              /* dest */ int x, int y, int cx, int cy,
 
1841
              /* src */ HGLYPH glyph, int srcx, int srcy,
 
1842
              int bgcolour, int fgcolour)
 
1843
{
 
1844
        SET_FOREGROUND(fgcolour);
 
1845
        SET_BACKGROUND(bgcolour);
 
1846
 
 
1847
        XSetFillStyle(g_display, g_gc,
 
1848
                      (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
 
1849
        XSetStipple(g_display, g_gc, (Pixmap) glyph);
 
1850
        XSetTSOrigin(g_display, g_gc, x, y);
 
1851
 
 
1852
        FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
 
1853
 
 
1854
        XSetFillStyle(g_display, g_gc, FillSolid);
 
1855
}
 
1856
 
 
1857
#define DO_GLYPH(ttext,idx) \
 
1858
{\
 
1859
  glyph = cache_get_font (font, ttext[idx]);\
 
1860
  if (!(flags & TEXT2_IMPLICIT_X))\
 
1861
  {\
 
1862
    xyoffset = ttext[++idx];\
 
1863
    if ((xyoffset & 0x80))\
 
1864
    {\
 
1865
      if (flags & TEXT2_VERTICAL)\
 
1866
        y += ttext[idx+1] | (ttext[idx+2] << 8);\
 
1867
      else\
 
1868
        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
 
1892
ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
 
1893
             int clipx, int clipy, int clipcx, int clipcy,
 
1894
             int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
 
1895
             int fgcolour, uint8 * text, uint8 length)
 
1896
{
 
1897
        FONTGLYPH *glyph;
 
1898
        int i, j, xyoffset, x1, y1;
 
1899
        DATABLOB *entry;
 
1900
 
 
1901
        SET_FOREGROUND(bgcolour);
 
1902
 
 
1903
        if (boxcx > 1)
 
1904
        {
 
1905
                FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
 
1906
        }
 
1907
        else if (mixmode == MIX_OPAQUE)
 
1908
        {
 
1909
                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 */
 
1917
        for (i = 0; i < length;)
 
1918
        {
 
1919
                switch (text[i])
 
1920
                {
 
1921
                        case 0xff:
 
1922
                                if (i + 2 < length)
 
1923
                                        cache_put_text(text[i + 1], text, text[i + 2]);
 
1924
                                else
 
1925
                                {
 
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
                        default:
 
1961
                                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
 
1981
ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
 
1982
{
 
1983
        Pixmap pix;
 
1984
        XImage *image;
 
1985
 
 
1986
        if (g_ownbackstore)
 
1987
        {
 
1988
                image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
 
1989
        }
 
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
 
2005
ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
 
2006
{
 
2007
        XImage *image;
 
2008
        uint8 *data;
 
2009
 
 
2010
        offset *= g_bpp / 8;
 
2011
        data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
 
2012
        if (data == NULL)
 
2013
                return;
 
2014
 
 
2015
        image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
 
2016
                             (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
 
2017
 
 
2018
        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);
 
2029
}