~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to ica/x11/x11vnc/screen.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20080617134654-2y5m7ki93r5c1ysf
Tags: upstream-1.0.9~rc3
ImportĀ upstreamĀ versionĀ 1.0.9~rc3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -- screen.c -- */
 
2
 
 
3
#include "x11vnc.h"
 
4
#include "xevents.h"
 
5
#include "xwrappers.h"
 
6
#include "xinerama.h"
 
7
#include "xdamage.h"
 
8
#include "win_utils.h"
 
9
#include "cleanup.h"
 
10
#include "userinput.h"
 
11
#include "scan.h"
 
12
#include "user.h"
 
13
#include "rates.h"
 
14
#include "pointer.h"
 
15
#include "keyboard.h"
 
16
#include "cursor.h"
 
17
#include "connections.h"
 
18
#include "remote.h"
 
19
#include "unixpw.h"
 
20
#include "sslcmds.h"
 
21
#include "sslhelper.h"
 
22
#include "v4l.h"
 
23
#include "linuxfb.h"
 
24
#include "macosx.h"
 
25
#include "macosxCG.h"
 
26
#include "avahi.h"
 
27
#include "solid.h"
 
28
#include "inet.h"
 
29
 
 
30
#include <rfb/rfbclient.h>
 
31
 
 
32
void set_greyscale_colormap(void);
 
33
void set_hi240_colormap(void);
 
34
void unset_colormap(void);
 
35
void set_colormap(int reset);
 
36
void set_nofb_params(int restore);
 
37
void set_raw_fb_params(int restore);
 
38
void do_new_fb(int reset_mem);
 
39
void free_old_fb(void);
 
40
void check_padded_fb(void);
 
41
void install_padded_fb(char *geom);
 
42
XImage *initialize_xdisplay_fb(void);
 
43
void parse_scale_string(char *str, double *factor, int *scaling, int *blend,
 
44
    int *nomult4, int *pad, int *interpolate, int *numer, int *denom);
 
45
int parse_rotate_string(char *str, int *mode);
 
46
int scale_round(int len, double fac);
 
47
void initialize_screen(int *argc, char **argv, XImage *fb);
 
48
void set_vnc_desktop_name(void);
 
49
void announce(int lport, int ssl, char *iface);
 
50
 
 
51
#if 0
 
52
char *vnc_reflect_guess(char *str, char **raw_fb_addr);
 
53
void vnc_reflect_process_client(void);
 
54
rfbBool vnc_reflect_send_pointer(int x, int y, int mask);
 
55
rfbBool vnc_reflect_send_key(uint32_t key, rfbBool down);
 
56
rfbBool vnc_reflect_send_cuttext(char *str, int len);
 
57
#endif
 
58
 
 
59
static void debug_colormap(XImage *fb);
 
60
static void set_visual(char *str);
 
61
static void nofb_hook(rfbClientPtr cl);
 
62
static void remove_fake_fb(void);
 
63
static void install_fake_fb(int w, int h, int bpp);
 
64
static void initialize_snap_fb(void);
 
65
XImage *initialize_raw_fb(int);
 
66
static void initialize_clipshift(void);
 
67
static int wait_until_mapped(Window win);
 
68
static void setup_scaling(int *width_in, int *height_in);
 
69
 
 
70
int rawfb_reset = -1;
 
71
int rawfb_dev_video = 0;
 
72
int rawfb_vnc_reflect = 0;
 
73
 
 
74
/*
 
75
 * X11 and rfb display/screen related routines
 
76
 */
 
77
 
 
78
/*
 
79
 * Some handling of 8bpp PseudoColor colormaps.  Called for initializing
 
80
 * the clients and dynamically if -flashcmap is specified.
 
81
 */
 
82
#define NCOLOR 256
 
83
 
 
84
void set_greyscale_colormap(void) {
 
85
        int i;
 
86
        if (! screen) {
 
87
                return;
 
88
        }
 
89
        if (screen->colourMap.data.shorts) {
 
90
                free(screen->colourMap.data.shorts);
 
91
                screen->colourMap.data.shorts = NULL;
 
92
        }
 
93
 
 
94
if (0) fprintf(stderr, "set_greyscale_colormap: %s\n", raw_fb_pixfmt);
 
95
        screen->colourMap.count = NCOLOR;
 
96
        screen->serverFormat.trueColour = FALSE;
 
97
        screen->colourMap.is16 = TRUE;
 
98
        screen->colourMap.data.shorts = (unsigned short *)
 
99
                malloc(3*sizeof(unsigned short) * NCOLOR);
 
100
 
 
101
        for(i = 0; i < NCOLOR; i++) {
 
102
                unsigned short lvl = i * 256;
 
103
 
 
104
                screen->colourMap.data.shorts[i*3+0] = lvl;
 
105
                screen->colourMap.data.shorts[i*3+1] = lvl;
 
106
                screen->colourMap.data.shorts[i*3+2] = lvl;
 
107
        }
 
108
 
 
109
        rfbSetClientColourMaps(screen, 0, NCOLOR);
 
110
}
 
111
 
 
112
/* this is specific to bttv rf tuner card */
 
113
void set_hi240_colormap(void) {
 
114
        int i;
 
115
        if (! screen) {
 
116
                return;
 
117
        }
 
118
if (0) fprintf(stderr, "set_hi240_colormap: %s\n", raw_fb_pixfmt);
 
119
        if (screen->colourMap.data.shorts) {
 
120
                free(screen->colourMap.data.shorts);
 
121
                screen->colourMap.data.shorts = NULL;
 
122
        }
 
123
 
 
124
        screen->colourMap.count = 256;
 
125
        screen->serverFormat.trueColour = FALSE;
 
126
        screen->colourMap.is16 = TRUE;
 
127
        screen->colourMap.data.shorts = (unsigned short *)
 
128
                calloc(3*sizeof(unsigned short) * 256, 1);
 
129
 
 
130
        for(i = 0; i < 225; i++) {
 
131
                int r, g, b;
 
132
 
 
133
                r = ( (i/5) % 5 ) * 255.0 / 4 + 0.5;
 
134
                g = ( (i/25)    ) * 255.0 / 8 + 0.5;
 
135
                b = ( i % 5     ) * 255.0 / 4 + 0.5;
 
136
 
 
137
                screen->colourMap.data.shorts[(i+16)*3+0] = (unsigned short) (r * 256);
 
138
                screen->colourMap.data.shorts[(i+16)*3+1] = (unsigned short) (g * 256);
 
139
                screen->colourMap.data.shorts[(i+16)*3+2] = (unsigned short) (b * 256);
 
140
        }
 
141
 
 
142
        rfbSetClientColourMaps(screen, 0, 256);
 
143
}
 
144
void unset_colormap(void) {
 
145
        if (! screen) {
 
146
                return;
 
147
        }
 
148
        if (screen->colourMap.data.shorts) {
 
149
                free(screen->colourMap.data.shorts);
 
150
                screen->colourMap.data.shorts = NULL;
 
151
        }
 
152
        screen->serverFormat.trueColour = TRUE;
 
153
if (0) fprintf(stderr, "unset_colormap: %s\n", raw_fb_pixfmt);
 
154
}
 
155
 
 
156
void set_colormap(int reset) {
 
157
#if NO_X11
 
158
        if (!reset) {}
 
159
        return;
 
160
#else
 
161
        static int init = 1;
 
162
        static XColor color[NCOLOR], prev[NCOLOR];
 
163
        Colormap cmap;
 
164
        Visual *vis;
 
165
        int i, ncells, diffs = 0;
 
166
 
 
167
        if (reset) {
 
168
                init = 1;
 
169
                if (screen->colourMap.data.shorts) {
 
170
                        free(screen->colourMap.data.shorts);
 
171
                        screen->colourMap.data.shorts = NULL;
 
172
                }
 
173
        }
 
174
if (0) fprintf(stderr, "unset_colormap: %d\n", reset);
 
175
 
 
176
        if (init) {
 
177
                screen->colourMap.count = NCOLOR;
 
178
                screen->serverFormat.trueColour = FALSE;
 
179
                screen->colourMap.is16 = TRUE;
 
180
                screen->colourMap.data.shorts = (unsigned short *)
 
181
                        malloc(3*sizeof(unsigned short) * NCOLOR);
 
182
        }
 
183
 
 
184
        for (i=0; i < NCOLOR; i++) {
 
185
                prev[i].red   = color[i].red;
 
186
                prev[i].green = color[i].green;
 
187
                prev[i].blue  = color[i].blue;
 
188
        }
 
189
 
 
190
        RAWFB_RET_VOID
 
191
 
 
192
        X_LOCK;
 
193
 
 
194
        cmap = DefaultColormap(dpy, scr);
 
195
        ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr));
 
196
        vis = default_visual;
 
197
 
 
198
        if (subwin) {
 
199
                XWindowAttributes attr;
 
200
 
 
201
                if (XGetWindowAttributes(dpy, window, &attr)) {
 
202
                        cmap = attr.colormap;
 
203
                        vis = attr.visual;
 
204
                        ncells = vis->map_entries;
 
205
                }
 
206
        }
 
207
 
 
208
        if (ncells != NCOLOR) {
 
209
                if (init && ! quiet) {
 
210
                        rfbLog("set_colormap: number of cells is %d "
 
211
                            "instead of %d.\n", ncells, NCOLOR);
 
212
                }
 
213
                if (! shift_cmap) {
 
214
                        screen->colourMap.count = ncells;
 
215
                }
 
216
        }
 
217
 
 
218
        if (flash_cmap && ! init) {
 
219
                XWindowAttributes attr;
 
220
                Window c;
 
221
                int tries = 0;
 
222
 
 
223
                c = window;
 
224
                while (c && tries++ < 16) {
 
225
                        c = query_pointer(c);
 
226
                        if (valid_window(c, &attr, 0)) {
 
227
                                if (attr.colormap && attr.map_installed) {
 
228
                                        cmap = attr.colormap;
 
229
                                        vis = attr.visual;
 
230
                                        ncells = vis->map_entries;
 
231
                                        break;
 
232
                                }
 
233
                        } else {
 
234
                                break;
 
235
                        }
 
236
                }
 
237
        }
 
238
        if (ncells > NCOLOR && ! quiet) {
 
239
                rfbLog("set_colormap: big problem: ncells=%d > %d\n",
 
240
                    ncells, NCOLOR);
 
241
        }
 
242
 
 
243
        if (vis->class == TrueColor || vis->class == DirectColor) {
 
244
                /*
 
245
                 * Kludge to make 8bpp TrueColor & DirectColor be like
 
246
                 * the StaticColor map.  The ncells = 8 is "8 per subfield"
 
247
                 * mentioned in xdpyinfo.  Looks OK... perhaps fortuitously.
 
248
                 */
 
249
                if (ncells == 8 && ! shift_cmap) {
 
250
                        ncells = NCOLOR;
 
251
                }
 
252
        }
 
253
 
 
254
        for (i=0; i < ncells; i++) {
 
255
                color[i].pixel = i;
 
256
                color[i].pad = 0;
 
257
        }
 
258
 
 
259
        XQueryColors(dpy, cmap, color, ncells);
 
260
 
 
261
        X_UNLOCK;
 
262
 
 
263
        for(i = ncells - 1; i >= 0; i--) {
 
264
                int k = i + shift_cmap;
 
265
 
 
266
                screen->colourMap.data.shorts[i*3+0] = color[i].red;
 
267
                screen->colourMap.data.shorts[i*3+1] = color[i].green;
 
268
                screen->colourMap.data.shorts[i*3+2] = color[i].blue;
 
269
 
 
270
                if (prev[i].red   != color[i].red ||
 
271
                    prev[i].green != color[i].green || 
 
272
                    prev[i].blue  != color[i].blue ) {
 
273
                        diffs++;
 
274
                }
 
275
 
 
276
                if (shift_cmap && k >= 0 && k < NCOLOR) {
 
277
                        /* kludge to copy the colors to higher pixel values */
 
278
                        screen->colourMap.data.shorts[k*3+0] = color[i].red;
 
279
                        screen->colourMap.data.shorts[k*3+1] = color[i].green;
 
280
                        screen->colourMap.data.shorts[k*3+2] = color[i].blue;
 
281
                }
 
282
        }
 
283
 
 
284
        if (diffs && ! init) {
 
285
                if (! all_clients_initialized()) {
 
286
                        rfbLog("set_colormap: warning: sending cmap "
 
287
                            "with uninitialized clients.\n");
 
288
                }
 
289
                if (shift_cmap) {
 
290
                        rfbSetClientColourMaps(screen, 0, NCOLOR);
 
291
                } else {
 
292
                        rfbSetClientColourMaps(screen, 0, ncells);
 
293
                }
 
294
        }
 
295
 
 
296
        init = 0;
 
297
#endif  /* NO_X11 */
 
298
}
 
299
 
 
300
static void debug_colormap(XImage *fb) {
 
301
        static int debug_cmap = -1;
 
302
        int i, k, histo[NCOLOR];
 
303
 
 
304
        if (debug_cmap < 0) {
 
305
                if (getenv("DEBUG_CMAP") != NULL) {
 
306
                        debug_cmap = 1;
 
307
                } else {
 
308
                        debug_cmap = 0;
 
309
                }
 
310
        }
 
311
        if (! debug_cmap) {
 
312
                return;
 
313
        }
 
314
        if (! fb) {
 
315
                return;
 
316
        }
 
317
        if (fb->bits_per_pixel > 8) {
 
318
                return;
 
319
        }
 
320
 
 
321
        for (i=0; i < NCOLOR; i++) {
 
322
                histo[i] = 0;
 
323
        }
 
324
        for (k = 0; k < fb->width * fb->height; k++) {
 
325
                unsigned char n;
 
326
                char c = *(fb->data + k);
 
327
 
 
328
                n = (unsigned char) c;
 
329
                histo[n]++;
 
330
        }
 
331
        fprintf(stderr, "\nColormap histogram for current screen contents:\n");
 
332
        for (i=0; i < NCOLOR; i++) {
 
333
                unsigned short r = screen->colourMap.data.shorts[i*3+0];
 
334
                unsigned short g = screen->colourMap.data.shorts[i*3+1];
 
335
                unsigned short b = screen->colourMap.data.shorts[i*3+2];
 
336
 
 
337
                fprintf(stderr, "   %03d: %7d %04x/%04x/%04x", i, histo[i],
 
338
                    r, g, b);
 
339
                if ((i+1) % 2 == 0)  {
 
340
                        fprintf(stderr, "\n");
 
341
                }
 
342
        }
 
343
        fprintf(stderr, "\n");
 
344
}
 
345
 
 
346
/*
 
347
 * Experimental mode to force the visual of the window instead of querying
 
348
 * it.  Used for testing, overriding some rare cases (win2vnc), and for
 
349
 * -overlay .  Input string can be a decimal or 0x hex or something like
 
350
 * TrueColor or TrueColor:24 to force a depth as well.
 
351
 *
 
352
 * visual_id and possibly visual_depth are set.
 
353
 */
 
354
static void set_visual(char *str) {
 
355
#if NO_X11
 
356
        RAWFB_RET_VOID
 
357
        if (!str) {}
 
358
        return;
 
359
#else
 
360
        int vis, vdepth, defdepth;
 
361
        XVisualInfo vinfo;
 
362
        char *p, *vstring = strdup(str);
 
363
 
 
364
        RAWFB_RET_VOID
 
365
 
 
366
        defdepth = DefaultDepth(dpy, scr);
 
367
        visual_id = (VisualID) 0;
 
368
        visual_depth = 0;
 
369
 
 
370
        if (!strcmp(vstring, "ignore") || !strcmp(vstring, "default")
 
371
            || !strcmp(vstring, "")) {
 
372
                free(vstring);
 
373
                return;
 
374
        }
 
375
 
 
376
        /* set visual depth */
 
377
        if ((p = strchr(vstring, ':')) != NULL) {
 
378
                visual_depth = atoi(p+1);
 
379
                *p = '\0';
 
380
                vdepth = visual_depth;
 
381
        } else {
 
382
                vdepth = defdepth; 
 
383
        }
 
384
        if (! quiet) {
 
385
                fprintf(stderr, "\nVisual Info:\n");
 
386
                fprintf(stderr, " set_visual(\"%s\")\n", str);
 
387
                fprintf(stderr, " visual_depth: %d\n", vdepth);
 
388
        }
 
389
 
 
390
        /* set visual id number */
 
391
        if (strcmp(vstring, "StaticGray") == 0) {
 
392
                vis = StaticGray;
 
393
        } else if (strcmp(vstring, "GrayScale") == 0) {
 
394
                vis = GrayScale;
 
395
        } else if (strcmp(vstring, "StaticColor") == 0) {
 
396
                vis = StaticColor;
 
397
        } else if (strcmp(vstring, "PseudoColor") == 0) {
 
398
                vis = PseudoColor;
 
399
        } else if (strcmp(vstring, "TrueColor") == 0) {
 
400
                vis = TrueColor;
 
401
        } else if (strcmp(vstring, "DirectColor") == 0) {
 
402
                vis = DirectColor;
 
403
        } else {
 
404
                unsigned int v_in;
 
405
                if (sscanf(vstring, "0x%x", &v_in) != 1) {
 
406
                        if (sscanf(vstring, "%u", &v_in) == 1) {
 
407
                                visual_id = (VisualID) v_in;
 
408
                                return;
 
409
                        }
 
410
                        rfbLogEnable(1);
 
411
                        rfbLog("invalid -visual arg: %s\n", vstring);
 
412
                        X_UNLOCK;
 
413
                        clean_up_exit(1);
 
414
                }
 
415
                visual_id = (VisualID) v_in;
 
416
                free(vstring);
 
417
                return;
 
418
        }
 
419
 
 
420
        if (! quiet) fprintf(stderr, " visual: %d\n", vis);
 
421
        if (XMatchVisualInfo(dpy, scr, visual_depth, vis, &vinfo)) {
 
422
                ;
 
423
        } else if (XMatchVisualInfo(dpy, scr, defdepth, vis, &vinfo)) {
 
424
                ;
 
425
        } else {
 
426
                rfbLogEnable(1);
 
427
                rfbLog("could not find visual: %s\n", vstring);
 
428
                X_UNLOCK;
 
429
                clean_up_exit(1);
 
430
        }
 
431
        free(vstring);
 
432
 
 
433
        /* set numerical visual id. */
 
434
        visual_id = vinfo.visualid;
 
435
#endif  /* NO_X11 */
 
436
}
 
437
 
 
438
void set_nofb_params(int restore) {
 
439
        static int first = 1;
 
440
        static int save[100];
 
441
        static char *scroll = NULL;
 
442
        int i = 0;
 
443
 
 
444
        if (first) {
 
445
                first = 0;
 
446
                save[i++] = use_xfixes;
 
447
                save[i++] = use_xdamage;
 
448
                save[i++] = use_xrecord;
 
449
                save[i++] = wireframe;
 
450
                save[i++] = use_solid_bg;
 
451
                save[i++] = overlay;
 
452
                save[i++] = overlay_cursor;
 
453
                save[i++] = using_shm;
 
454
                save[i++] = single_copytile;
 
455
                save[i++] = take_naps;
 
456
                save[i++] = measure_speeds;
 
457
                save[i++] = grab_buster;
 
458
                save[i++] = show_cursor;
 
459
                save[i++] = cursor_shape_updates;
 
460
                save[i++] = cursor_pos_updates;
 
461
                save[i++] = ncache;
 
462
 
 
463
                scroll = scroll_copyrect;
 
464
        }
 
465
        if (restore) {
 
466
                i = 0;
 
467
                use_xfixes            = save[i++];
 
468
                use_xdamage           = save[i++];
 
469
                use_xrecord           = save[i++];
 
470
                wireframe             = save[i++];
 
471
                use_solid_bg          = save[i++];
 
472
                overlay               = save[i++];
 
473
                overlay_cursor        = save[i++];
 
474
                using_shm             = save[i++];
 
475
                single_copytile       = save[i++];
 
476
                take_naps             = save[i++];
 
477
                measure_speeds        = save[i++];
 
478
                grab_buster           = save[i++];
 
479
                show_cursor           = save[i++];
 
480
                cursor_shape_updates  = save[i++];
 
481
                cursor_pos_updates    = save[i++];
 
482
                ncache                = save[i++];
 
483
 
 
484
                scroll_copyrect = scroll;
 
485
 
 
486
                if (cursor_shape_updates) {
 
487
                        restore_cursor_shape_updates(screen);
 
488
                }
 
489
                initialize_cursors_mode();
 
490
 
 
491
                return;
 
492
        }
 
493
 
 
494
        use_xfixes = 0;
 
495
        use_xdamage = 0;
 
496
        use_xrecord = 0;
 
497
        wireframe = 0;
 
498
 
 
499
        use_solid_bg = 0;
 
500
        overlay = 0;
 
501
        overlay_cursor = 0;
 
502
 
 
503
        using_shm = 0;
 
504
        single_copytile = 1;
 
505
 
 
506
        take_naps = 0;
 
507
        measure_speeds = 0;
 
508
 
 
509
        /* got_grab_buster? */
 
510
        grab_buster = 0;
 
511
 
 
512
        show_cursor = 0;
 
513
        show_multiple_cursors = 0;
 
514
        cursor_shape_updates = 0;
 
515
        if (! got_cursorpos) {
 
516
                cursor_pos_updates = 0;
 
517
        }
 
518
 
 
519
        ncache = 0;
 
520
 
 
521
        scroll_copyrect = "never";
 
522
 
 
523
        if (! quiet) {
 
524
                rfbLog("disabling: xfixes, xdamage, solid, overlay, shm,\n");
 
525
                rfbLog("  wireframe, scrollcopyrect, ncache,\n");
 
526
                rfbLog("  noonetile, nap, cursor, %scursorshape\n",
 
527
                    got_cursorpos ? "" : "cursorpos, " );
 
528
                rfbLog("  in -nofb mode.\n");
 
529
        }
 
530
}
 
531
 
 
532
static char *raw_fb_orig_dpy = NULL;
 
533
 
 
534
void set_raw_fb_params(int restore) {
 
535
        static int first = 1;
 
536
        static int vo0, us0, sm0, ws0, wp0, wc0, wb0, na0, tn0;  
 
537
        static int xr0, xrm0, sb0, re0;
 
538
        static char *mc0;
 
539
 
 
540
        /*
 
541
         * set turn off a bunch of parameters not compatible with 
 
542
         * -rawfb mode: 1) ignoring the X server 2) ignoring user input. 
 
543
         */
 
544
        
 
545
        if (first) {
 
546
                /* at least save the initial settings... */
 
547
                vo0 = view_only;
 
548
                ws0 = watch_selection;
 
549
                wp0 = watch_primary;
 
550
                wc0 = watch_clipboard;
 
551
                wb0 = watch_bell;
 
552
                na0 = no_autorepeat;
 
553
                sb0 = use_solid_bg;
 
554
 
 
555
                us0 = use_snapfb;
 
556
                sm0 = using_shm;
 
557
                tn0 = take_naps;
 
558
                xr0 = xrandr;
 
559
                xrm0 = xrandr_maybe;
 
560
                re0 = noxrecord;
 
561
                mc0 = multiple_cursors_mode;
 
562
 
 
563
                first = 0;
 
564
        }
 
565
 
 
566
        if (restore) {
 
567
                view_only = vo0;
 
568
                watch_selection = ws0;
 
569
                watch_primary = wp0;
 
570
                watch_clipboard = wc0;
 
571
                watch_bell = wb0;
 
572
                no_autorepeat = na0;
 
573
                use_solid_bg = sb0;
 
574
 
 
575
                use_snapfb = us0;
 
576
                using_shm = sm0;
 
577
                take_naps = tn0;
 
578
                xrandr = xr0;
 
579
                xrandr_maybe = xrm0;
 
580
                noxrecord = re0;
 
581
                multiple_cursors_mode = mc0;
 
582
 
 
583
                if (! dpy && raw_fb_orig_dpy) {
 
584
                        dpy = XOpenDisplay_wr(raw_fb_orig_dpy);
 
585
                        if (dpy) {
 
586
                                if (! quiet) rfbLog("reopened DISPLAY: %s\n",
 
587
                                    raw_fb_orig_dpy);
 
588
                                scr = DefaultScreen(dpy);
 
589
                                rootwin = RootWindow(dpy, scr);
 
590
                                check_xevents(1);
 
591
                        } else {
 
592
                                if (! quiet) rfbLog("WARNING: failed to reopen "
 
593
                                    "DISPLAY: %s\n", raw_fb_orig_dpy);
 
594
                        }
 
595
                }
 
596
                return;
 
597
        }
 
598
 
 
599
        if (verbose) {
 
600
                rfbLog("set_raw_fb_params: modifying settings for "
 
601
                    "-rawfb mode.\n");
 
602
        }
 
603
 
 
604
        if (got_noviewonly) {
 
605
                /*
 
606
                 * The user input parameters are not unset under
 
607
                 * -noviewonly... this usage should be very rare
 
608
                 * (i.e. rawfb but also send user input to the X
 
609
                 * display, most likely using /dev/fb0 for some reason...)
 
610
                 */
 
611
                if (verbose) {
 
612
                   rfbLog("rawfb: -noviewonly mode: still sending mouse and\n");
 
613
                   rfbLog("rawfb:   keyboard input to the X DISPLAY!!\n");
 
614
                }
 
615
        } else {
 
616
                /* Normal case: */
 
617
#if 0
 
618
                if (! view_only && ! pipeinput_str) {
 
619
                        if (! quiet) rfbLog("  rawfb: setting view_only\n");
 
620
                        view_only = 1;
 
621
                }
 
622
#endif
 
623
                if (raw_fb_str && strstr(raw_fb_str, "vnc") == raw_fb_str) {
 
624
                        ;
 
625
                } else if (watch_selection) {
 
626
                        if (verbose) rfbLog("  rawfb: turning off "
 
627
                            "watch_selection\n");
 
628
                        watch_selection = 0;
 
629
                }
 
630
                if (watch_primary) {
 
631
                        if (verbose) rfbLog("  rawfb: turning off "
 
632
                            "watch_primary\n");
 
633
                        watch_primary = 0;
 
634
                }
 
635
                if (watch_clipboard) {
 
636
                        if (verbose) rfbLog("  rawfb: turning off "
 
637
                            "watch_clipboard\n");
 
638
                        watch_clipboard = 0;
 
639
                }
 
640
                if (watch_bell) {
 
641
                        if (verbose) rfbLog("  rawfb: turning off watch_bell\n");
 
642
                        watch_bell = 0;
 
643
                }
 
644
                if (no_autorepeat) {
 
645
                        if (verbose) rfbLog("  rawfb: turning off "
 
646
                            "no_autorepeat\n");
 
647
                        no_autorepeat = 0;
 
648
                }
 
649
                if (use_solid_bg) {
 
650
                        if (verbose) rfbLog("  rawfb: turning off "
 
651
                            "use_solid_bg\n");
 
652
                        use_solid_bg = 0;
 
653
                }
 
654
#ifndef MACOSX
 
655
                if (raw_fb_str && strstr(raw_fb_str, "vnc") == raw_fb_str) {
 
656
                        ;
 
657
                } else {
 
658
                        multiple_cursors_mode = strdup("arrow");
 
659
                }
 
660
#endif
 
661
        }
 
662
        if (using_shm) {
 
663
                if (verbose) rfbLog("  rawfb: turning off using_shm\n");
 
664
                using_shm = 0;
 
665
        }
 
666
        if (take_naps) {
 
667
                if (verbose) rfbLog("  rawfb: turning off take_naps\n");
 
668
                take_naps = 0;
 
669
        }
 
670
        if (xrandr) {
 
671
                if (verbose) rfbLog("  rawfb: turning off xrandr\n");
 
672
                xrandr = 0;
 
673
        }
 
674
        if (xrandr_maybe) {
 
675
                if (verbose) rfbLog("  rawfb: turning off xrandr_maybe\n");
 
676
                xrandr_maybe = 0;
 
677
        }
 
678
        if (! noxrecord) {
 
679
                if (verbose) rfbLog("  rawfb: turning off xrecord\n");
 
680
                noxrecord = 1;
 
681
        }
 
682
}
 
683
 
 
684
/*
 
685
 * Presumably under -nofb the clients will never request the framebuffer.
 
686
 * However, we have gotten such a request... so let's just give them
 
687
 * the current view on the display.  n.b. x2vnc and perhaps win2vnc
 
688
 * requests a 1x1 pixel for some workaround so sadly this evidently
 
689
 * nearly always happens.
 
690
 */
 
691
static void nofb_hook(rfbClientPtr cl) {
 
692
        XImage *fb;
 
693
        XImage raw;
 
694
 
 
695
        rfbLog("framebuffer requested in -nofb mode by client %s\n", cl->host);
 
696
        /* ignore xrandr */
 
697
 
 
698
        if (raw_fb && ! dpy) {
 
699
                fb = &raw;
 
700
                fb->data = (char *)malloc(32);
 
701
        } else {
 
702
                int use_real_ximage = 0;
 
703
                if (use_real_ximage) {
 
704
                        fb = XGetImage_wr(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes, ZPixmap);
 
705
                } else {
 
706
                        fb = &raw;
 
707
                        fb->data = (char *) calloc(dpy_x*dpy_y*bpp/8, 1);
 
708
                }
 
709
        }
 
710
        main_fb = fb->data;
 
711
        rfb_fb = main_fb;
 
712
        screen->frameBuffer = rfb_fb;
 
713
        screen->displayHook = NULL;
 
714
}
 
715
 
 
716
void free_old_fb(void) {
 
717
        char *fbs[16];
 
718
        int i, j, nfb = 0, db = 0; 
 
719
 
 
720
        fbs[nfb++] = main_fb;           main_fb = NULL;
 
721
        fbs[nfb++] = rfb_fb;            rfb_fb = NULL;
 
722
        fbs[nfb++] = cmap8to24_fb;      cmap8to24_fb = NULL;
 
723
        fbs[nfb++] = snap_fb;           snap_fb = NULL;
 
724
        fbs[nfb++] = rot_fb;            rot_fb = NULL;
 
725
        fbs[nfb++] = raw_fb;            raw_fb = NULL;
 
726
 
 
727
        for (i=0; i < nfb; i++) {
 
728
                char *fb = fbs[i];
 
729
                int freeit = 1;
 
730
                if (! fb || fb < (char *) 0x10) {
 
731
                        continue;
 
732
                }
 
733
                for (j=0; j < i; j++) {
 
734
                        if (fb == fbs[j]) {
 
735
                                freeit = 0;
 
736
                                break;
 
737
                        }
 
738
                }
 
739
                if (freeit) {
 
740
                        if (db) fprintf(stderr, "free: %i %p\n", i, fb);
 
741
                        free(fb);
 
742
                } else {
 
743
                        if (db) fprintf(stderr, "skip: %i %p\n", i, fb);
 
744
                }
 
745
        }
 
746
}
 
747
 
 
748
void do_new_fb(int reset_mem) {
 
749
        XImage *fb;
 
750
 
 
751
        /* for threaded we really should lock libvncserver out. */
 
752
        if (use_threads) {
 
753
                rfbLog("warning: changing framebuffers while threaded may\n");
 
754
                rfbLog(" not work, do not use -threads if problems arise.\n");
 
755
        }
 
756
 
 
757
        if (reset_mem == 1) {
 
758
                /* reset_mem == 2 is a hack for changing users... */
 
759
                clean_shm(0);
 
760
                free_tiles();
 
761
        }
 
762
 
 
763
        free_old_fb();
 
764
 
 
765
        fb = initialize_xdisplay_fb();
 
766
 
 
767
        initialize_screen(NULL, NULL, fb);
 
768
 
 
769
        if (reset_mem) {
 
770
                initialize_tiles();
 
771
                initialize_blackouts_and_xinerama();
 
772
                initialize_polling_images();
 
773
        }
 
774
        if (ncache) {
 
775
                check_ncache(1, 0);
 
776
        }
 
777
}
 
778
 
 
779
static void remove_fake_fb(void) {
 
780
        if (! screen) {
 
781
                return;
 
782
        }
 
783
        rfbLog("removing fake fb: 0x%x\n", fake_fb);
 
784
 
 
785
        do_new_fb(1);
 
786
 
 
787
        /*
 
788
         * fake_fb is freed in do_new_fb(), but we set to NULL here to
 
789
         * indicate it is gone.
 
790
         */
 
791
        fake_fb = NULL;
 
792
}
 
793
 
 
794
static void install_fake_fb(int w, int h, int bpp) {
 
795
        int bpc;
 
796
        if (! screen) {
 
797
                return;
 
798
        }
 
799
        if (fake_fb) {
 
800
                free(fake_fb);
 
801
        }
 
802
        fake_fb = (char *) calloc(w*h*bpp/8, 1);
 
803
        if (! fake_fb) {
 
804
                rfbLog("could not create fake fb: %dx%d %d\n", w, h, bpp);
 
805
                return;
 
806
        }
 
807
        bpc = guess_bits_per_color(bpp);
 
808
        rfbLog("installing fake fb: %dx%d %d\n", w, h, bpp);
 
809
        rfbLog("rfbNewFramebuffer(0x%x, 0x%x, %d, %d, %d, %d, %d)\n",
 
810
            screen, fake_fb, w, h, bpc, 1, bpp/8);
 
811
 
 
812
        rfbNewFramebuffer(screen, fake_fb, w, h, bpc, 1, bpp/8);
 
813
}
 
814
 
 
815
void check_padded_fb(void) {
 
816
        if (! fake_fb) {
 
817
                return;
 
818
        }
 
819
        if (unixpw_in_progress) return;
 
820
 
 
821
        if (time(NULL) > pad_geometry_time+1 && all_clients_initialized()) {
 
822
                remove_fake_fb();
 
823
        }
 
824
}
 
825
 
 
826
void install_padded_fb(char *geom) {
 
827
        int w, h;
 
828
        int ok = 1;
 
829
        if (! geom || *geom == '\0') {
 
830
                ok = 0;
 
831
        } else if (sscanf(geom, "%dx%d", &w, &h) != 2)  {
 
832
                ok = 0;
 
833
        }
 
834
        w = nabs(w);
 
835
        h = nabs(h);
 
836
 
 
837
        if (w < 5) w = 5;
 
838
        if (h < 5) h = 5;
 
839
 
 
840
        if (!ok) {
 
841
                rfbLog("skipping invalid pad geometry: '%s'\n", NONUL(geom));
 
842
                return;
 
843
        }
 
844
        install_fake_fb(w, h, bpp);
 
845
        pad_geometry_time = time(NULL);
 
846
}
 
847
 
 
848
static void initialize_snap_fb(void) {
 
849
        RAWFB_RET_VOID
 
850
        if (snap_fb) {
 
851
                free(snap_fb);
 
852
        }
 
853
        snap = XGetImage_wr(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes,
 
854
            ZPixmap);
 
855
        snap_fb = snap->data;
 
856
}
 
857
 
 
858
#if 0
 
859
static rfbClient* client = NULL;
 
860
 
 
861
void vnc_reflect_bell(rfbClient *cl) {
 
862
        if (cl) {}
 
863
        if (sound_bell) {
 
864
                if (unixpw_in_progress) {
 
865
                        return;
 
866
                }
 
867
                if (! all_clients_initialized()) {
 
868
                        rfbLog("vnc_reflect_bell: not sending bell: "
 
869
                            "uninitialized clients\n");
 
870
                } else {
 
871
                        if (screen && client_count) {
 
872
                                rfbSendBell(screen);
 
873
                        }
 
874
                }
 
875
        }
 
876
}
 
877
 
 
878
void vnc_reflect_recv_cuttext(rfbClient *cl, const char *str, int len) {
 
879
        if (cl) {}
 
880
        if (unixpw_in_progress) {
 
881
                return;
 
882
        }
 
883
        if (! watch_selection) {
 
884
                return;
 
885
        }
 
886
        if (! all_clients_initialized()) {
 
887
                rfbLog("vnc_reflect_recv_cuttext: no send: uninitialized clients\n");
 
888
                return; /* some clients initializing, cannot send */ 
 
889
        }
 
890
        rfbSendServerCutText(screen, (char *)str, len);
 
891
}
 
892
 
 
893
void vnc_reflect_got_update(rfbClient *cl, int x, int y, int w, int h) {
 
894
        if (cl) {}
 
895
        if (use_xdamage) {
 
896
                static int first = 1;
 
897
                if (first) {
 
898
                        collect_non_X_xdamage(-1, -1, -1, -1, 0);
 
899
                        first = 0;
 
900
                }
 
901
                collect_non_X_xdamage(x, y, w, h, 1);
 
902
        }
 
903
}
 
904
 
 
905
void vnc_reflect_got_cursorshape(rfbClient *cl, int xhot, int yhot, int width, int height, int bytesPerPixel) {
 
906
        static int serial = 1;
 
907
        int i, j;
 
908
        char *pixels = NULL;
 
909
        unsigned long r, g, b;
 
910
        unsigned int ui = 0;
 
911
        unsigned long red_mask, green_mask, blue_mask;
 
912
 
 
913
        if (cl) {}
 
914
        if (unixpw_in_progress) {
 
915
                return;
 
916
        }
 
917
        if (! all_clients_initialized()) {
 
918
                rfbLog("vnc_reflect_got_copyshape: no send: uninitialized clients\n");
 
919
                return; /* some clients initializing, cannot send */ 
 
920
        }
 
921
        if (! client->rcSource) {
 
922
                return;
 
923
        }
 
924
        if (bytesPerPixel != 1 && bytesPerPixel != 2 && bytesPerPixel != 4) {
 
925
                return;
 
926
        }
 
927
 
 
928
        red_mask   = (client->format.redMax   << client->format.redShift);
 
929
        green_mask = (client->format.greenMax << client->format.greenShift);
 
930
        blue_mask  = (client->format.blueMax  << client->format.blueShift);
 
931
 
 
932
        pixels = (char *)malloc(4*width*height);
 
933
        for (j=0; j<height; j++) {
 
934
                for (i=0; i<width; i++) {
 
935
                        unsigned int* uip;
 
936
                        unsigned char* uic;
 
937
                        int m;
 
938
                        if (bytesPerPixel == 1) {
 
939
                                unsigned char* p = (unsigned char *) client->rcSource;
 
940
                                ui = (unsigned long) *(p + j * width + i);
 
941
                        } else if (bytesPerPixel == 2) {
 
942
                                unsigned short* p = (unsigned short *) client->rcSource;
 
943
                                ui = (unsigned long) *(p + j * width + i);
 
944
                        } else if (bytesPerPixel == 4) {
 
945
                                unsigned int* p = (unsigned int *) client->rcSource;
 
946
                                ui = (unsigned long) *(p + j * width + i);
 
947
                        }
 
948
                        r = (red_mask   & ui) >> client->format.redShift;
 
949
                        g = (green_mask & ui) >> client->format.greenShift;
 
950
                        b = (blue_mask  & ui) >> client->format.blueShift;
 
951
 
 
952
                        r = (255 * r) / client->format.redMax;
 
953
                        g = (255 * g) / client->format.greenMax;
 
954
                        b = (255 * b) / client->format.blueMax;
 
955
 
 
956
                        ui = (r << 16 | g << 8 | b << 0) ;
 
957
 
 
958
                        uic = (unsigned char *)client->rcMask;
 
959
                        m = (int) *(uic + j * width + i);
 
960
                        if (m) {
 
961
                                ui |= 0xff000000;
 
962
                        }
 
963
                        uip = (unsigned int *)pixels;
 
964
                        *(uip + j * width + i) = ui;
 
965
                }
 
966
        }
 
967
 
 
968
        store_cursor(serial++, (unsigned long*) pixels, width, height, 32, xhot, yhot);
 
969
        free(pixels);
 
970
        set_cursor(cursor_x, cursor_y, get_which_cursor());
 
971
}
 
972
 
 
973
void vnc_reflect_got_copyrect(rfbClient *cl, int src_x, int src_y, int w, int h, int dest_x, int dest_y) {
 
974
        sraRegionPtr reg;
 
975
        int dx, dy, rc = -1;
 
976
        static int last_dx = 0, last_dy = 0;
 
977
        if (cl) {}
 
978
        if (unixpw_in_progress) {
 
979
                return;
 
980
        }
 
981
        if (! all_clients_initialized()) {
 
982
                rfbLog("vnc_reflect_got_copyrect: no send: uninitialized clients\n");
 
983
                return; /* some clients initializing, cannot send */ 
 
984
        }
 
985
        dx = dest_x - src_x;
 
986
        dy = dest_y - src_y;
 
987
        if (dx != last_dx || dy != last_dy) {
 
988
                rc = fb_push_wait(0.05, FB_COPY|FB_MOD);
 
989
        }
 
990
        if (0) fprintf(stderr, "vnc_reflect_got_copyrect: %dx%d+%d+%d   %d %d  rc=%d\n", dest_x, dest_y, w, h, dx, dy, rc);
 
991
        reg = sraRgnCreateRect(dest_x, dest_y, dest_x + w, dest_y + h);
 
992
        do_copyregion(reg, dx, dy, 0);
 
993
        sraRgnDestroy(reg);
 
994
 
 
995
        last_dx = dx;
 
996
        last_dy = dy;
 
997
}
 
998
 
 
999
rfbBool vnc_reflect_resize(rfbClient *cl)  {
 
1000
        static int first = 1;
 
1001
        if(cl->frameBuffer) {
 
1002
                free(cl->frameBuffer);
 
1003
        }
 
1004
        cl->frameBuffer= malloc(cl->width * cl->height * cl->format.bitsPerPixel/8);
 
1005
        if (!first) {
 
1006
                do_new_fb(1);
 
1007
        }
 
1008
        first = 0;
 
1009
        return cl->frameBuffer ? TRUE : FALSE;
 
1010
}
 
1011
 
 
1012
char *vnc_reflect_guess(char *str, char **raw_fb_addr) {
 
1013
 
 
1014
        static int first = 1;
 
1015
        char *hp = str + strlen("vnc:");
 
1016
        char *at = NULL;
 
1017
        int argc = 0, i;
 
1018
        char *argv[16];
 
1019
        char str2[256];
 
1020
        char *str0 = strdup(str);
 
1021
 
 
1022
        if (client == NULL) {
 
1023
                client = rfbGetClient(8, 3, 4);
 
1024
        }
 
1025
 
 
1026
        rfbLog("rawfb: %s\n", str);
 
1027
 
 
1028
        at = strchr(hp, '@');
 
1029
        if (at) {
 
1030
                *at = '\0';
 
1031
                at++;
 
1032
        }
 
1033
 
 
1034
        client->appData.useRemoteCursor = TRUE;
 
1035
        client->Bell = vnc_reflect_bell;
 
1036
        client->GotXCutText = vnc_reflect_recv_cuttext;
 
1037
        client->GotCopyRect = vnc_reflect_got_copyrect;
 
1038
        client->GotCursorShape = vnc_reflect_got_cursorshape;
 
1039
        client->MallocFrameBuffer = vnc_reflect_resize;
 
1040
        client->canHandleNewFBSize = TRUE;
 
1041
        client->GotFrameBufferUpdate = vnc_reflect_got_update;
 
1042
 
 
1043
        if (first) {
 
1044
                argv[argc++] = "x11vnc_rawfb_vnc";
 
1045
                if (strstr(hp, "listen") == hp) {
 
1046
                        char *q = strchr(hp, ':');
 
1047
                        argv[argc++] = strdup("-listen");
 
1048
                        if (q) {
 
1049
                                client->listenPort = atoi(q+1);
 
1050
                        } else {
 
1051
                                client->listenPort = LISTEN_PORT_OFFSET;
 
1052
                        }
 
1053
                } else {
 
1054
                        argv[argc++] = strdup(hp);
 
1055
                }
 
1056
 
 
1057
                if (! rfbInitClient(client, &argc, argv)) {
 
1058
                        rfbLog("vnc_reflector failed for: %s\n", str0);
 
1059
                        clean_up_exit(1);
 
1060
                }
 
1061
        }
 
1062
 
 
1063
        if (at) {
 
1064
                sprintf(str2, "map:/dev/null@%s", at);
 
1065
        } else {
 
1066
                unsigned long red_mask, green_mask, blue_mask;
 
1067
                red_mask   = (client->format.redMax   << client->format.redShift);
 
1068
                green_mask = (client->format.greenMax << client->format.greenShift);
 
1069
                blue_mask  = (client->format.blueMax  << client->format.blueShift);
 
1070
                sprintf(str2, "map:/dev/null@%dx%dx%d:0x%lx/0x%lx/0x%lx",
 
1071
                    client->width, client->height, client->format.bitsPerPixel,
 
1072
                    red_mask, green_mask, blue_mask);
 
1073
        }
 
1074
        *raw_fb_addr = (char *) client->frameBuffer;
 
1075
        free(str0);
 
1076
 
 
1077
        if (first) {
 
1078
                setup_cursors_and_push();
 
1079
 
 
1080
                for (i=0; i<10; i++) {
 
1081
                        vnc_reflect_process_client();
 
1082
                }
 
1083
        }
 
1084
        first = 0;
 
1085
 
 
1086
        return strdup(str2);
 
1087
}
 
1088
 
 
1089
rfbBool vnc_reflect_send_pointer(int x, int y, int mask) {
 
1090
        int rc;
 
1091
        if (mask >= 0) {
 
1092
                got_user_input++;
 
1093
                got_pointer_input++;
 
1094
                last_pointer_time = time(NULL);
 
1095
        }
 
1096
 
 
1097
        if (cursor_x != x || cursor_y != y) {
 
1098
                last_pointer_motion_time = dnow();
 
1099
        }
 
1100
 
 
1101
        cursor_x = x;
 
1102
        cursor_y = y;
 
1103
 
 
1104
        /* record the x, y position for the rfb screen as well. */
 
1105
        cursor_position(x, y);
 
1106
 
 
1107
        /* change the cursor shape if necessary */
 
1108
        rc = set_cursor(x, y, get_which_cursor());
 
1109
        cursor_changes += rc;
 
1110
 
 
1111
        return SendPointerEvent(client, x, y, mask);
 
1112
}
 
1113
 
 
1114
rfbBool vnc_reflect_send_key(uint32_t key, rfbBool down) {
 
1115
        return SendKeyEvent(client, key, down);
 
1116
}
 
1117
 
 
1118
rfbBool vnc_reflect_send_cuttext(char *str, int len) {
 
1119
        return SendClientCutText(client, str, len);
 
1120
}
 
1121
 
 
1122
void vnc_reflect_process_client(void) {
 
1123
        int num;
 
1124
        if (client == NULL) {
 
1125
                return;
 
1126
        }
 
1127
        num = WaitForMessage(client, 1000);
 
1128
        if (num > 0) {
 
1129
                if (!HandleRFBServerMessage(client)) {
 
1130
                        rfbLog("vnc_reflect_process_client: read failure to server\n");
 
1131
                        shut_down = 1;
 
1132
                }
 
1133
        }
 
1134
}
 
1135
#endif
 
1136
 
 
1137
#define RAWFB_MMAP 1
 
1138
#define RAWFB_FILE 2
 
1139
#define RAWFB_SHM  3
 
1140
 
 
1141
XImage *initialize_raw_fb(int reset) {
 
1142
        char *str, *q;
 
1143
        int w, h, b, shmid = 0;
 
1144
        unsigned long rm = 0, gm = 0, bm = 0, tm;
 
1145
        static XImage ximage_struct;    /* n.b.: not (XImage *) */
 
1146
        static XImage ximage_struct_snap;
 
1147
        int closedpy = 1, i, m, db = 0;
 
1148
        int do_macosx = 0;
 
1149
        int do_reflect = 0;
 
1150
        char *unlink_me = NULL;
 
1151
 
 
1152
        static char *last_file = NULL;
 
1153
        static int last_mode = 0;
 
1154
 
 
1155
        if (reset && last_mode) {
 
1156
                int fd;
 
1157
                if (last_mode != RAWFB_MMAP && last_mode != RAWFB_FILE) {
 
1158
                        return NULL;
 
1159
                }
 
1160
                if (last_mode == RAWFB_MMAP) {
 
1161
                        munmap(raw_fb_addr, raw_fb_mmap);
 
1162
                }
 
1163
                if (raw_fb_fd >= 0) {
 
1164
                        close(raw_fb_fd);
 
1165
                }
 
1166
                raw_fb_fd = -1;
 
1167
if (db) fprintf(stderr, "initialize_raw_fb reset\n");
 
1168
                        
 
1169
                fd = -1;
 
1170
                if (rawfb_dev_video) {
 
1171
                        fd = open(last_file, O_RDWR);
 
1172
                }
 
1173
                if (fd < 0) {
 
1174
                        fd = open(last_file, O_RDONLY);
 
1175
                }
 
1176
                if (fd < 0) {
 
1177
                        rfbLogEnable(1);
 
1178
                        rfbLog("failed to rawfb file: %s\n", last_file);
 
1179
                        rfbLogPerror("open");
 
1180
                        clean_up_exit(1);
 
1181
                }
 
1182
                raw_fb_fd = fd;
 
1183
                if (last_mode == RAWFB_MMAP) {
 
1184
                        raw_fb_addr = mmap(0, raw_fb_mmap, PROT_READ,
 
1185
                            MAP_SHARED, fd, 0);
 
1186
 
 
1187
                        if (raw_fb_addr == MAP_FAILED || raw_fb_addr == NULL) {
 
1188
                                rfbLogEnable(1);
 
1189
                                rfbLog("failed to mmap file: %s\n", last_file);
 
1190
                                rfbLog("   raw_fb_addr: %p\n", raw_fb_addr);
 
1191
                                rfbLogPerror("mmap");
 
1192
                                clean_up_exit(1);
 
1193
                        }
 
1194
                }
 
1195
                return NULL;
 
1196
        }
 
1197
 
 
1198
#ifdef MACOSX
 
1199
        if (raw_fb_addr != NULL && macosx_console && raw_fb_addr == macosx_get_fb_addr()) {
 
1200
                raw_fb_addr = NULL;
 
1201
        }
 
1202
#endif
 
1203
        
 
1204
        if (raw_fb_addr || raw_fb_seek) {
 
1205
                if (raw_fb_shm) {
 
1206
                        shmdt(raw_fb_addr);
 
1207
#if LIBVNCSERVER_HAVE_MMAP
 
1208
                } else if (raw_fb_mmap) {
 
1209
                        munmap(raw_fb_addr, raw_fb_mmap);
 
1210
                        if (raw_fb_fd >= 0) {
 
1211
                                close(raw_fb_fd);
 
1212
                        }
 
1213
                        raw_fb_fd = -1;
 
1214
#endif
 
1215
                } else if (raw_fb_seek) {
 
1216
                        if (raw_fb_fd >= 0) {
 
1217
                                close(raw_fb_fd);
 
1218
                        }
 
1219
                        raw_fb_fd = -1;
 
1220
                }
 
1221
                raw_fb_addr = NULL;
 
1222
                raw_fb_mmap = 0;
 
1223
                raw_fb_seek = 0;
 
1224
        }
 
1225
        if (! raw_fb_str) {
 
1226
                return NULL;
 
1227
        }
 
1228
 
 
1229
        /* testing aliases */
 
1230
        if (!strcasecmp(raw_fb_str, "NULL") || !strcasecmp(raw_fb_str, "ZERO")
 
1231
            || !strcasecmp(raw_fb_str, "NONE")) {
 
1232
                raw_fb_str = strdup("map:/dev/zero@640x480x32");
 
1233
        } else if (!strcasecmp(raw_fb_str, "NULLBIG") || !strcasecmp(raw_fb_str, "NONEBIG")) {
 
1234
                raw_fb_str = strdup("map:/dev/zero@1024x768x32");
 
1235
        }
 
1236
        if (!strcasecmp(raw_fb_str, "RAND")) {
 
1237
                raw_fb_str = strdup("file:/dev/urandom@128x128x16");
 
1238
        } else if (!strcasecmp(raw_fb_str, "RANDBIG")) {
 
1239
                raw_fb_str = strdup("file:/dev/urandom@640x480x16");
 
1240
        } else if (!strcasecmp(raw_fb_str, "RANDHUGE")) {
 
1241
                raw_fb_str = strdup("file:/dev/urandom@1024x768x16");
 
1242
        }
 
1243
        if (strstr(raw_fb_str, "solid=") == raw_fb_str) {
 
1244
                char *n = raw_fb_str + strlen("solid=");
 
1245
                char tmp[] = "/tmp/solid.XXXXXX";
 
1246
                char str[100];
 
1247
                unsigned int vals[1024], val;
 
1248
                int x, y, fd, w = 1024, h = 768;
 
1249
                if (strstr(n, "0x")) {
 
1250
                        if (sscanf(n, "0x%x", &val) != 1) {
 
1251
                                val = 0;
 
1252
                        }
 
1253
                }
 
1254
                if (val == 0) {
 
1255
                        val = get_pixel(n);
 
1256
                }
 
1257
                if (val == 0) {
 
1258
                        val = 0xFF00FF;
 
1259
                }
 
1260
                fd = mkstemp(tmp);
 
1261
                for (y = 0; y < h; y++) {
 
1262
                        for (x = 0; x < w; x++) {
 
1263
                                vals[x] = val;
 
1264
                        }
 
1265
                        write(fd, (char *)vals, 4 * w);
 
1266
                }
 
1267
                close(fd);
 
1268
                fd = open(tmp, O_WRONLY);
 
1269
                unlink_me = strdup(tmp);
 
1270
                sprintf(str, "map:%s@%dx%dx32", tmp, w, h);
 
1271
                raw_fb_str = strdup(str);
 
1272
        } else if (strstr(raw_fb_str, "swirl") == raw_fb_str) {
 
1273
                char tmp[] = "/tmp/solid.XXXXXX";
 
1274
                char str[100];
 
1275
                unsigned int val[1024];
 
1276
                unsigned int c1, c2, c3, c4;
 
1277
                int x, y, fd, w = 1024, h = 768;
 
1278
                fd = mkstemp(tmp);
 
1279
                for (y = 0; y < h; y++) {
 
1280
                        for (x = 0; x < w; x++) {
 
1281
                                c1 = 0;
 
1282
                                c2 = ((x+y)*128)/(w+h);
 
1283
                                c3 = (x*128)/w;
 
1284
                                c4 = (y*256)/h;
 
1285
                                val[x] = (c1 << 24) | (c2 << 16) | (c3 << 8) | (c4 << 0);
 
1286
                        }
 
1287
                        write(fd, (char *)val, 4 * w);
 
1288
                }
 
1289
                close(fd);
 
1290
                fd = open(tmp, O_WRONLY);
 
1291
                unlink_me = strdup(tmp);
 
1292
                sprintf(str, "map:%s@%dx%dx32", tmp, w, h);
 
1293
                raw_fb_str = strdup(str);
 
1294
        }
 
1295
 
 
1296
 
 
1297
        if ( (q = strstr(raw_fb_str, "setup:")) == raw_fb_str) {
 
1298
                FILE *pipe;
 
1299
                char line[1024], *t;
 
1300
 
 
1301
                set_child_info();
 
1302
                q += strlen("setup:");
 
1303
                /* rawfb-setup */
 
1304
                if (no_external_cmds || !cmd_ok("rawfb-setup")) {
 
1305
                        rfbLogEnable(1);
 
1306
                        rfbLog("cannot run external commands in -nocmds "
 
1307
                            "mode:\n");
 
1308
                        rfbLog("   \"%s\"\n", q);
 
1309
                        rfbLog("   exiting.\n");
 
1310
                        clean_up_exit(1);
 
1311
                }
 
1312
                rfbLog("running command to setup rawfb: %s\n", q);
 
1313
                close_exec_fds();
 
1314
                pipe = popen(q, "r");
 
1315
                if (! pipe) {
 
1316
                        rfbLogEnable(1);
 
1317
                        rfbLog("popen of setup command failed.\n");
 
1318
                        rfbLogPerror("popen");
 
1319
                        clean_up_exit(1);
 
1320
                }
 
1321
                line[0] = '\0';
 
1322
                if (fgets(line, 1024, pipe) == NULL) {
 
1323
                        rfbLogEnable(1);
 
1324
                        rfbLog("read of setup command failed.\n");
 
1325
                        clean_up_exit(1);
 
1326
                }
 
1327
                pclose(pipe);
 
1328
                str = strdup(line);
 
1329
                t = str;
 
1330
                while (*t != '\0') {
 
1331
                        if (*t == '\n') {
 
1332
                                *t = '\0';
 
1333
                        }
 
1334
                        t++;
 
1335
                }
 
1336
                rfbLog("setup command returned: %s\n", str);
 
1337
 
 
1338
        } else {
 
1339
                str = strdup(raw_fb_str);
 
1340
        }
 
1341
        if (str[0] == '+') {
 
1342
                char *t = strdup(str+1);
 
1343
                free(str);
 
1344
                str = t;
 
1345
                closedpy = 0;
 
1346
                if (! window) {
 
1347
                        window = rootwin;
 
1348
                }
 
1349
        }
 
1350
 
 
1351
        raw_fb_shm = 0;
 
1352
        raw_fb_mmap = 0;
 
1353
        raw_fb_seek = 0;
 
1354
        raw_fb_fd = -1;
 
1355
        raw_fb_addr = NULL;
 
1356
        raw_fb_offset = 0;
 
1357
        raw_fb_bytes_per_line = 0;
 
1358
/*      rawfb_vnc_reflect = 0;*/
 
1359
 
 
1360
        last_mode = 0;
 
1361
        if (last_file) {
 
1362
                free(last_file);
 
1363
                last_file = NULL;
 
1364
        }
 
1365
        if (strstr(str, "Video") == str) {
 
1366
                if (pipeinput_str != NULL) {
 
1367
                        free(pipeinput_str);
 
1368
                }
 
1369
                pipeinput_str = strdup("VID");
 
1370
                initialize_pipeinput();
 
1371
                str[0] = 'v';
 
1372
        }
 
1373
 
 
1374
        if (strstr(str, "video") == str || strstr(str, "/dev/video") == str) {
 
1375
                char *str2 = v4l_guess(str, &raw_fb_fd);
 
1376
                if (str2 == NULL) {
 
1377
                        rfbLog("v4l_guess failed for: %s\n", str);
 
1378
                        clean_up_exit(1);
 
1379
                }
 
1380
                str = str2;
 
1381
                rfbLog("v4l_guess returned: %s\n", str);
 
1382
                rawfb_dev_video = 1;
 
1383
        } else if (strstr(str, "dev/video")) {
 
1384
                rawfb_dev_video = 1;
 
1385
        } else if (strstr(str, "console") == str || strstr(str, "fb") == str ||
 
1386
            strstr(str, "/dev/fb") == str) {
 
1387
                char *str2 = console_guess(str, &raw_fb_fd);
 
1388
                if (str2 == NULL) {
 
1389
                        rfbLog("console_guess failed for: %s\n", str);
 
1390
                        clean_up_exit(1);
 
1391
                }
 
1392
                str = str2;
 
1393
                rfbLog("console_guess returned: %s\n", str);
 
1394
#if 0
 
1395
        } else if (strstr(str, "vnc:") == str) {
 
1396
                char *str2 = vnc_reflect_guess(str, &raw_fb_addr);
 
1397
 
 
1398
                rawfb_vnc_reflect = 1;
 
1399
                do_reflect = 1;
 
1400
 
 
1401
                str = str2;
 
1402
                rfbLog("vnc_reflector set rawfb str to: %s\n", str);
 
1403
                if (pipeinput_str == NULL) {
 
1404
                        pipeinput_str = strdup("VNC");
 
1405
                }
 
1406
                initialize_pipeinput();
 
1407
#endif
 
1408
        }
 
1409
        if (closedpy && !view_only && got_noviewonly) {
 
1410
                rfbLog("not closing X DISPLAY under -noviewonly option.\n");
 
1411
                closedpy = 0;
 
1412
                if (! window) {
 
1413
                        window = rootwin;
 
1414
                }
 
1415
        }
 
1416
 
 
1417
        if (! raw_fb_orig_dpy && dpy) {
 
1418
                raw_fb_orig_dpy = strdup(DisplayString(dpy));
 
1419
        }
 
1420
#ifndef BOLDLY_CLOSE_DISPLAY
 
1421
#define BOLDLY_CLOSE_DISPLAY 1
 
1422
#endif
 
1423
#if BOLDLY_CLOSE_DISPLAY
 
1424
        if (closedpy) {
 
1425
                if (dpy) {
 
1426
                        rfbLog("closing X DISPLAY: %s in rawfb mode.\n",
 
1427
                            DisplayString(dpy));
 
1428
                        XCloseDisplay_wr(dpy);  /* yow! */
 
1429
                }
 
1430
                dpy = NULL;
 
1431
        }
 
1432
#endif
 
1433
 
 
1434
        /*
 
1435
         * -rawfb shm:163938442@640x480x32:ff/ff00/ff0000+3000
 
1436
         * -rawfb map:/path/to/file@640x480x32:ff/ff00/ff0000
 
1437
         * -rawfb file:/path/to/file@640x480x32:ff/ff00/ff0000
 
1438
         */
 
1439
 
 
1440
 
 
1441
        /* +O offset */
 
1442
        if ((q = strrchr(str, '+')) != NULL) {
 
1443
                if (sscanf(q, "+%d", &raw_fb_offset) == 1) {
 
1444
                        *q = '\0';
 
1445
                } else {
 
1446
                        raw_fb_offset = 0;
 
1447
                }
 
1448
        }
 
1449
        /* :R/G/B masks */
 
1450
        if ((q = strrchr(str, ':')) != NULL) {
 
1451
                if (sscanf(q, ":%lx/%lx/%lx", &rm, &gm, &bm) == 3) {
 
1452
                        *q = '\0';
 
1453
                } else if (sscanf(q, ":0x%lx/0x%lx/0x%lx", &rm, &gm, &bm)== 3) {
 
1454
                        *q = '\0';
 
1455
                } else if (sscanf(q, ":%lu/%lu/%lu", &rm, &gm, &bm) == 3) {
 
1456
                        *q = '\0';
 
1457
                } else {
 
1458
                        rm = 0;
 
1459
                        gm = 0;
 
1460
                        bm = 0;
 
1461
                }
 
1462
        }
 
1463
        if ((q = strrchr(str, '@')) == NULL) {
 
1464
                rfbLogEnable(1);
 
1465
                rfbLog("invalid rawfb str: %s\n", str);
 
1466
                clean_up_exit(1);
 
1467
        }
 
1468
 
 
1469
        if (strrchr(q, '-')) {
 
1470
                char *q2 = strrchr(q, '-');
 
1471
                raw_fb_bytes_per_line = atoi(q2+1);
 
1472
                *q2 = '\0';
 
1473
        }
 
1474
        /* @WxHxB */
 
1475
        if (sscanf(q, "@%dx%dx%d", &w, &h, &b) != 3) {
 
1476
                rfbLogEnable(1);
 
1477
                rfbLog("invalid rawfb str: %s\n", str);
 
1478
                clean_up_exit(1);
 
1479
        }
 
1480
        *q = '\0';
 
1481
 
 
1482
        dpy_x = wdpy_x = w;
 
1483
        dpy_y = wdpy_y = h;
 
1484
        off_x = 0;
 
1485
        off_y = 0;
 
1486
 
 
1487
        if (rawfb_dev_video) {
 
1488
                if (b == 24) {
 
1489
                        rfbLog("enabling -24to32 for 24bpp video\n");
 
1490
                        xform24to32 = 1;
 
1491
                } else {
 
1492
                        if (xform24to32) {
 
1493
                                rfbLog("disabling -24to32 for 24bpp video\n");
 
1494
                        }
 
1495
                        xform24to32 = 0;
 
1496
                }
 
1497
        }
 
1498
 
 
1499
        if (xform24to32) {
 
1500
                if (b != 24) {
 
1501
                        rfbLog("warning: -24to32 mode and bpp=%d\n", b);
 
1502
                }
 
1503
                b = 32;
 
1504
        }
 
1505
        if (strstr(str, "snap:") == str) {
 
1506
                use_snapfb = 1;
 
1507
                str[0] = 'f'; str[1] = 'i'; str[2] = 'l'; str[3] = 'e';
 
1508
        }
 
1509
 
 
1510
        if (strstr(str, "shm:") != str && strstr(str, "mmap:") != str &&
 
1511
            strstr(str, "map:") != str && strstr(str, "file:") != str) {
 
1512
                /* hmmm, not following directions, see if map: applies */
 
1513
                struct stat sbuf;
 
1514
                if (stat(str, &sbuf) == 0) {
 
1515
                        char *new;
 
1516
                        int len = strlen("map:") + strlen(str) + 1;
 
1517
                        rfbLog("no type prefix: %s\n", raw_fb_str);
 
1518
                        rfbLog("  but file exists, so assuming: map:%s\n",
 
1519
                            raw_fb_str);
 
1520
                        new = (char *) malloc(len);
 
1521
                        strcpy(new, "map:");
 
1522
                        strcat(new, str);
 
1523
                        free(str);
 
1524
                        str = new;
 
1525
                }
 
1526
        }
 
1527
 
 
1528
        if (sscanf(str, "shm:%d", &shmid) == 1) {
 
1529
                /* shm:N */
 
1530
#if LIBVNCSERVER_HAVE_XSHM
 
1531
                raw_fb_addr = (char *) shmat(shmid, 0, SHM_RDONLY);
 
1532
                if (! raw_fb_addr) {
 
1533
                        rfbLogEnable(1);
 
1534
                        rfbLog("failed to attach to shm: %d, %s\n", shmid, str);
 
1535
                        rfbLogPerror("shmat");
 
1536
                        clean_up_exit(1);
 
1537
                }
 
1538
                raw_fb_shm = 1;
 
1539
                rfbLog("rawfb: shm: %d W: %d H: %d B: %d addr: %p\n",
 
1540
                    shmid, w, h, b, raw_fb_addr);
 
1541
                last_mode = RAWFB_SHM;
 
1542
#else
 
1543
                rfbLogEnable(1);
 
1544
                rfbLog("x11vnc was compiled without shm support.\n");
 
1545
                rfbLogPerror("shmat");
 
1546
                clean_up_exit(1);
 
1547
#endif
 
1548
        } else if (strstr(str, "map:") == str || strstr(str, "mmap:") == str
 
1549
            || strstr(str, "file:") == str) {
 
1550
                /* map:/path/... or file:/path  */
 
1551
                int fd, do_mmap = 1, size;
 
1552
                struct stat sbuf;
 
1553
 
 
1554
                if (*str == 'f') {
 
1555
                        do_mmap = 0;
 
1556
                }
 
1557
                q = strchr(str, ':');
 
1558
                q++;
 
1559
 
 
1560
                macosx_console = 0;
 
1561
                if (strstr(q, "macosx:") == q) {
 
1562
                        /* mmap:macosx:/dev/null@... */
 
1563
                        q += strlen("macosx:");                 
 
1564
                        do_macosx = 1;
 
1565
                        do_mmap = 0;
 
1566
                        macosx_console = 1;
 
1567
                }
 
1568
 
 
1569
                last_file = strdup(q);
 
1570
 
 
1571
                fd = raw_fb_fd;
 
1572
                if (fd < 0 && rawfb_dev_video) {
 
1573
                        fd = open(q, O_RDWR);
 
1574
                }
 
1575
                if (fd < 0) {
 
1576
                        fd = open(q, O_RDONLY);
 
1577
                }
 
1578
                if (fd < 0) {
 
1579
                        rfbLogEnable(1);
 
1580
                        rfbLog("failed to open file: %s, %s\n", q, str);
 
1581
                        rfbLogPerror("open");
 
1582
                        clean_up_exit(1);
 
1583
                }
 
1584
                raw_fb_fd = fd;
 
1585
 
 
1586
                if (xform24to32) {
 
1587
                        size = w*h*24/8 + raw_fb_offset;
 
1588
                } else {
 
1589
                        size = w*h*b/8 + raw_fb_offset;
 
1590
                }
 
1591
                if (fstat(fd, &sbuf) == 0) {
 
1592
                        if (S_ISREG(sbuf.st_mode)) {
 
1593
                                if (0) size = sbuf.st_size;
 
1594
                        } else {
 
1595
                                rfbLog("raw fb is non-regular file: %s\n", q);
 
1596
                        }
 
1597
                }
 
1598
 
 
1599
                if (do_macosx) {
 
1600
                        raw_fb_addr = macosx_get_fb_addr();
 
1601
                        raw_fb_mmap = size;
 
1602
                        rfbLog("rawfb: macosx fb: %s\n", q);
 
1603
                        rfbLog("   w: %d h: %d b: %d addr: %p sz: %d\n", w, h,
 
1604
                            b, raw_fb_addr, size);
 
1605
                        last_mode = 0;
 
1606
                } else if (do_reflect) {
 
1607
                        raw_fb_mmap = size;
 
1608
                        rfbLog("rawfb: vnc fb: %s\n", q);
 
1609
                        rfbLog("   w: %d h: %d b: %d addr: %p sz: %d\n", w, h,
 
1610
                            b, raw_fb_addr, size);
 
1611
                        last_mode = 0;
 
1612
 
 
1613
                } else if (do_mmap) {
 
1614
#if LIBVNCSERVER_HAVE_MMAP
 
1615
                        raw_fb_addr = mmap(0, size, PROT_READ, MAP_SHARED,
 
1616
                            fd, 0);
 
1617
 
 
1618
                        if (raw_fb_addr == MAP_FAILED || raw_fb_addr == NULL) {
 
1619
                                rfbLogEnable(1);
 
1620
                                rfbLog("failed to mmap file: %s, %s\n", q, str);
 
1621
                                rfbLog("   raw_fb_addr: %p\n", raw_fb_addr);
 
1622
                                rfbLogPerror("mmap");
 
1623
                                clean_up_exit(1);
 
1624
                        }
 
1625
                        raw_fb_mmap = size;
 
1626
 
 
1627
                        rfbLog("rawfb: mmap file: %s\n", q);
 
1628
                        rfbLog("   w: %d h: %d b: %d addr: %p sz: %d\n", w, h,
 
1629
                            b, raw_fb_addr, size);
 
1630
                        last_mode = RAWFB_MMAP;
 
1631
#else
 
1632
                        rfbLog("mmap(2) not supported on system, using"
 
1633
                            " slower lseek(2)\n");
 
1634
                        raw_fb_seek = size;
 
1635
                        last_mode = RAWFB_FILE;
 
1636
#endif
 
1637
                } else {
 
1638
                        raw_fb_seek = size;
 
1639
                        last_mode = RAWFB_FILE;
 
1640
 
 
1641
                        rfbLog("rawfb: seek file: %s\n", q);
 
1642
                        rfbLog("   W: %d H: %d B: %d sz: %d\n", w, h, b, size);
 
1643
                }
 
1644
        } else {
 
1645
                rfbLogEnable(1);
 
1646
                rfbLog("invalid rawfb str: %s\n", str);
 
1647
                clean_up_exit(1);
 
1648
        }
 
1649
 
 
1650
        if (unlink_me) {
 
1651
                unlink(unlink_me);
 
1652
        }
 
1653
 
 
1654
        if (! raw_fb_image) {
 
1655
                raw_fb_image = &ximage_struct;
 
1656
        }
 
1657
 
 
1658
        initialize_clipshift();
 
1659
 
 
1660
        if (raw_fb_bytes_per_line == 0) {
 
1661
                raw_fb_bytes_per_line = dpy_x*b/8;
 
1662
 
 
1663
                /*
 
1664
                 * Put cases here were we can determine that
 
1665
                 * raw_bytes_per_line != dpy_x*b/8
 
1666
                 */
 
1667
#ifdef MACOSX
 
1668
                if (do_macosx) {
 
1669
                        raw_fb_bytes_per_line = macosxCG_CGDisplayBytesPerRow();
 
1670
                }
 
1671
#endif
 
1672
        }
 
1673
 
 
1674
        raw_fb_image->bytes_per_line = dpy_x * b/8;
 
1675
        raw_fb = (char *) malloc(dpy_y * dpy_x * b/8);
 
1676
        raw_fb_image->data = raw_fb;
 
1677
        raw_fb_image->format = ZPixmap;
 
1678
        raw_fb_image->width  = dpy_x;
 
1679
        raw_fb_image->height = dpy_y;
 
1680
        raw_fb_image->bits_per_pixel = b;
 
1681
        raw_fb_image->bitmap_unit = -1;
 
1682
 
 
1683
 
 
1684
        if (use_snapfb && (raw_fb_seek || raw_fb_mmap)) {
 
1685
                int b_use = b;
 
1686
                if (snap_fb) {
 
1687
                        free(snap_fb);
 
1688
                }
 
1689
                if (b_use == 32 && xform24to32) {
 
1690
                        /*
 
1691
                         * The actual framebuffer (e.g. mapped addr) and
 
1692
                         * snap fb must be the same bpp.  E.g. both 24bpp.
 
1693
                         * Reading FROM snap to utility image will be
 
1694
                         * transformed 24->32 in copy_raw_fb_24_to_32.
 
1695
                         *
 
1696
                         * addr -> snap -> (scanline, fullscreen, ...)
 
1697
                         */
 
1698
                        b_use = 24;
 
1699
                        raw_fb_bytes_per_line = dpy_x * b_use/8;
 
1700
                }
 
1701
                snap_fb = (char *) malloc(dpy_y * dpy_x * b_use/8);
 
1702
                snap = &ximage_struct_snap;
 
1703
                snap->data = snap_fb;
 
1704
                snap->format = ZPixmap;
 
1705
                snap->width  = dpy_x;
 
1706
                snap->height = dpy_y;
 
1707
                snap->bits_per_pixel = b_use;
 
1708
                snap->bytes_per_line = dpy_x * b_use/8;
 
1709
                snap->bitmap_unit = -1;
 
1710
        }
 
1711
 
 
1712
        if (rm == 0 && gm == 0 && bm == 0) {
 
1713
                /* guess masks... */
 
1714
                if (b == 24 || b == 32) {
 
1715
                        rm = 0xff0000;
 
1716
                        gm = 0x00ff00;
 
1717
                        bm = 0x0000ff;
 
1718
                } else if (b == 16) {
 
1719
                        rm = 0xf800;
 
1720
                        gm = 0x07e0;
 
1721
                        bm = 0x001f;
 
1722
                } else if (b == 8) {
 
1723
                        rm = 0x07;
 
1724
                        gm = 0x38;
 
1725
                        bm = 0xc0;
 
1726
                }
 
1727
        }
 
1728
        /* we can fake -flipbyteorder to some degree... */
 
1729
        if (flip_byte_order) {
 
1730
                if (b == 24 || b == 32) {
 
1731
                        tm = rm;
 
1732
                        rm = bm;
 
1733
                        bm = tm;
 
1734
                } else if (b == 16) {
 
1735
                        unsigned short s1, s2;
 
1736
                        s1 = (unsigned short) rm;
 
1737
                        s2 = ((0xff & s1) << 8) | ((0xff00 & s1) >> 8);
 
1738
                        rm = (unsigned long) s2;
 
1739
                        s1 = (unsigned short) gm;
 
1740
                        s2 = ((0xff & s1) << 8) | ((0xff00 & s1) >> 8);
 
1741
                        gm = (unsigned long) s2;
 
1742
                        s1 = (unsigned short) bm;
 
1743
                        s2 = ((0xff & s1) << 8) | ((0xff00 & s1) >> 8);
 
1744
                        bm = (unsigned long) s2;
 
1745
                }
 
1746
        }
 
1747
 
 
1748
 
 
1749
        raw_fb_image->red_mask = rm;
 
1750
        raw_fb_image->green_mask = gm;
 
1751
        raw_fb_image->blue_mask = bm;
 
1752
 
 
1753
        raw_fb_image->depth = 0;
 
1754
        m = 1;
 
1755
        for (i=0; i<32; i++)  {
 
1756
                if (rm & m) {
 
1757
                        raw_fb_image->depth++;
 
1758
                }
 
1759
                if (gm & m) {
 
1760
                        raw_fb_image->depth++;
 
1761
                }
 
1762
                if (bm & m) {
 
1763
                        raw_fb_image->depth++;
 
1764
                }
 
1765
                m = m << 1;
 
1766
        }
 
1767
        if (! raw_fb_image->depth) { 
 
1768
                raw_fb_image->depth = (b == 32) ? 24 : b;
 
1769
        }
 
1770
 
 
1771
        depth = raw_fb_image->depth;
 
1772
 
 
1773
        if (raw_fb_image->depth == 15) {
 
1774
                /* unresolved bug with RGB555... */
 
1775
                depth++;
 
1776
        }
 
1777
 
 
1778
        if (clipshift) {
 
1779
                memset(raw_fb, 0xff, dpy_y * raw_fb_image->bytes_per_line);
 
1780
        } else if (raw_fb_addr && ! xform24to32) {
 
1781
                memcpy(raw_fb, raw_fb_addr + raw_fb_offset, dpy_y * raw_fb_image->bytes_per_line);
 
1782
        } else {
 
1783
                memset(raw_fb, 0xff, dpy_y * raw_fb_image->bytes_per_line);
 
1784
        }
 
1785
 
 
1786
        if (verbose) {
 
1787
                
 
1788
                rfbLog("\n");
 
1789
                rfbLog("rawfb:  raw_fb  %p\n", raw_fb);
 
1790
                rfbLog("        format  %d\n", raw_fb_image->format);
 
1791
                rfbLog("        width   %d\n", raw_fb_image->width);
 
1792
                rfbLog("        height  %d\n", raw_fb_image->height);
 
1793
                rfbLog("        bpp     %d\n", raw_fb_image->bits_per_pixel);
 
1794
                rfbLog("        depth   %d\n", raw_fb_image->depth);
 
1795
                rfbLog("        bpl     %d\n", raw_fb_image->bytes_per_line);
 
1796
                if (use_snapfb && snap_fb) {
 
1797
                        rfbLog("        snap_fb %p\n", snap_fb);
 
1798
                }
 
1799
        }
 
1800
 
 
1801
        free(str);
 
1802
 
 
1803
        return raw_fb_image;
 
1804
}
 
1805
 
 
1806
static void initialize_clipshift(void) {
 
1807
        clipshift = 0;
 
1808
        cdpy_x = cdpy_y = coff_x = coff_y = 0;
 
1809
        if (clip_str) {
 
1810
                int w, h, x, y, bad = 0;
 
1811
                if (parse_geom(clip_str, &w, &h, &x, &y, wdpy_x, wdpy_y)) {
 
1812
                        if (x < 0) {
 
1813
                                x = 0;
 
1814
                        }
 
1815
                        if (y < 0) {
 
1816
                                y = 0;
 
1817
                        }
 
1818
                        if (x + w > wdpy_x) {
 
1819
                                w = wdpy_x - x;
 
1820
                        }
 
1821
                        if (y + h > wdpy_y) {
 
1822
                                h = wdpy_y - y;
 
1823
                        }
 
1824
                        if (w <= 0 || h <= 0) {
 
1825
                                bad = 1;
 
1826
                        }
 
1827
                } else {
 
1828
                        bad = 1;
 
1829
                }
 
1830
                if (bad) {
 
1831
                        rfbLog("skipping invalid -clip WxH+X+Y: %s\n",
 
1832
                            clip_str); 
 
1833
                } else {
 
1834
                        /* OK, change geom behind everyone's back... */
 
1835
                        cdpy_x = w;
 
1836
                        cdpy_y = h;
 
1837
                        coff_x = x;
 
1838
                        coff_y = y;
 
1839
 
 
1840
                        clipshift = 1;
 
1841
 
 
1842
                        dpy_x = cdpy_x;
 
1843
                        dpy_y = cdpy_y;
 
1844
                }
 
1845
        }
 
1846
}
 
1847
 
 
1848
static int wait_until_mapped(Window win) {
 
1849
#if NO_X11
 
1850
        if (!win) {}
 
1851
        return 0;
 
1852
#else
 
1853
        int ms = 50, waittime = 30;
 
1854
        time_t start = time(NULL);
 
1855
        XWindowAttributes attr;
 
1856
 
 
1857
        while (1) {
 
1858
                if (! valid_window(win, NULL, 0)) {
 
1859
                        if (time(NULL) > start + waittime) {
 
1860
                                break;
 
1861
                        }
 
1862
                        usleep(ms * 1000);
 
1863
                        continue;
 
1864
                }
 
1865
                if (dpy && ! XGetWindowAttributes(dpy, win, &attr)) {
 
1866
                        return 0;
 
1867
                }
 
1868
                if (attr.map_state == IsViewable) {
 
1869
                        return 1;
 
1870
                }
 
1871
                usleep(ms * 1000);
 
1872
        }
 
1873
        return 0;
 
1874
#endif  /* NO_X11 */
 
1875
}
 
1876
 
 
1877
/*
 
1878
 * initialize a fb for the X display
 
1879
 */
 
1880
XImage *initialize_xdisplay_fb(void) {
 
1881
#if NO_X11
 
1882
        if (raw_fb_str) {
 
1883
                return initialize_raw_fb(0);
 
1884
        }
 
1885
        return NULL;
 
1886
#else
 
1887
        XImage *fb;
 
1888
        char *vis_str = visual_str;
 
1889
        int try = 0, subwin_tries = 3;
 
1890
        XErrorHandler old_handler = NULL;
 
1891
        int subwin_bs;
 
1892
 
 
1893
        if (raw_fb_str) {
 
1894
                return initialize_raw_fb(0);
 
1895
        }
 
1896
 
 
1897
        X_LOCK;
 
1898
        if (subwin) {
 
1899
                if (subwin_wait_mapped) {
 
1900
                        wait_until_mapped(subwin);
 
1901
                }
 
1902
                if (!valid_window((Window) subwin, NULL, 0)) {
 
1903
                        rfbLogEnable(1);
 
1904
                        rfbLog("invalid sub-window: 0x%lx\n", subwin);
 
1905
                        X_UNLOCK;
 
1906
                        clean_up_exit(1);
 
1907
                }
 
1908
        }
 
1909
        
 
1910
        if (overlay) {
 
1911
                /* 
 
1912
                 * ideally we'd like to not have to cook up the
 
1913
                 * visual variables but rather let it all come out
 
1914
                 * of XReadScreen(), however there is no way to get
 
1915
                 * a default visual out of it, so we pretend -visual
 
1916
                 * TrueColor:NN was supplied with NN usually 24.
 
1917
                 */
 
1918
                char str[32];
 
1919
                Window twin = subwin ? subwin : rootwin;
 
1920
                XImage *xi;
 
1921
 
 
1922
                xi = xreadscreen(dpy, twin, 0, 0, 8, 8, False);
 
1923
                sprintf(str, "TrueColor:%d", xi->depth);
 
1924
                if (xi->depth != 24 && ! quiet) {
 
1925
                        rfbLog("warning: overlay image has depth %d "
 
1926
                            "instead of 24.\n", xi->depth);
 
1927
                }
 
1928
                XDestroyImage(xi);
 
1929
                if (visual_str != NULL && ! quiet) {
 
1930
                        rfbLog("warning: replacing '-visual %s' by '%s' "
 
1931
                            "for use with -overlay\n", visual_str, str);
 
1932
                }
 
1933
                vis_str = strdup(str);
 
1934
        }
 
1935
 
 
1936
        if (xform24to32) {
 
1937
                if (DefaultDepth(dpy, scr) == 24) {
 
1938
                        vis_str = strdup("TrueColor:32");
 
1939
                        rfbLog("initialize_xdisplay_fb: vis_str set to: %s ",
 
1940
                            vis_str);
 
1941
                        visual_id = (VisualID) 0;
 
1942
                        visual_depth = 0;
 
1943
                        set_visual_str_to_something = 1;
 
1944
                }
 
1945
        }
 
1946
 
 
1947
        if (vis_str != NULL) {
 
1948
                set_visual(vis_str);
 
1949
                if (vis_str != visual_str) {
 
1950
                        free(vis_str);
 
1951
                }
 
1952
        }
 
1953
if (0) fprintf(stderr, "vis_str %s\n", vis_str ? vis_str : "notset");
 
1954
 
 
1955
        /* set up parameters for subwin or non-subwin cases: */
 
1956
 
 
1957
        if (! subwin) {
 
1958
                /* full screen */
 
1959
                window = rootwin;
 
1960
                dpy_x = wdpy_x = DisplayWidth(dpy, scr);
 
1961
                dpy_y = wdpy_y = DisplayHeight(dpy, scr);
 
1962
                off_x = 0;
 
1963
                off_y = 0;
 
1964
                /* this may be overridden via visual_id below */
 
1965
                default_visual = DefaultVisual(dpy, scr);
 
1966
        } else {
 
1967
                /* single window */
 
1968
                XWindowAttributes attr;
 
1969
 
 
1970
                window = (Window) subwin;
 
1971
                if (! XGetWindowAttributes(dpy, window, &attr)) {
 
1972
                        rfbLogEnable(1);
 
1973
                        rfbLog("invalid window: 0x%lx\n", window);
 
1974
                        X_UNLOCK;
 
1975
                        clean_up_exit(1);
 
1976
                }
 
1977
                dpy_x = wdpy_x = attr.width;
 
1978
                dpy_y = wdpy_y = attr.height;
 
1979
 
 
1980
                subwin_bs = attr.backing_store;
 
1981
 
 
1982
                /* this may be overridden via visual_id below */
 
1983
                default_visual = attr.visual;
 
1984
 
 
1985
                X_UNLOCK;
 
1986
                set_offset();
 
1987
                X_LOCK;
 
1988
        }
 
1989
 
 
1990
        initialize_clipshift();
 
1991
 
 
1992
        /* initialize depth to reasonable value, visual_id may override */
 
1993
        depth = DefaultDepth(dpy, scr);
 
1994
 
 
1995
if (0) fprintf(stderr, "DefaultDepth: %d  visial_id: %d\n", depth, (int) visual_id);
 
1996
 
 
1997
        if (visual_id) {
 
1998
                int n;
 
1999
                XVisualInfo vinfo_tmpl, *vinfo;
 
2000
 
 
2001
                /*
 
2002
                 * we are in here from -visual or -overlay options
 
2003
                 * visual_id and visual_depth were set in set_visual().
 
2004
                 */
 
2005
 
 
2006
                vinfo_tmpl.visualid = visual_id; 
 
2007
                vinfo = XGetVisualInfo(dpy, VisualIDMask, &vinfo_tmpl, &n);
 
2008
                if (vinfo == NULL || n == 0) {
 
2009
                        rfbLogEnable(1);
 
2010
                        rfbLog("could not match visual_id: 0x%x\n",
 
2011
                            (int) visual_id);
 
2012
                        X_UNLOCK;
 
2013
                        clean_up_exit(1);
 
2014
                }
 
2015
                default_visual = vinfo->visual;
 
2016
                depth = vinfo->depth;
 
2017
                if (visual_depth) {
 
2018
                        /* force it from -visual MooColor:NN */
 
2019
                        depth = visual_depth;
 
2020
                }
 
2021
                if (! quiet) {
 
2022
                        fprintf(stderr, " initialize_xdisplay_fb()\n");
 
2023
                        fprintf(stderr, " Visual*:    %p\n",
 
2024
                            (void *) vinfo->visual);
 
2025
                        fprintf(stderr, " visualid:   0x%x\n",
 
2026
                            (int) vinfo->visualid);
 
2027
                        fprintf(stderr, " screen:     %d\n", vinfo->screen);
 
2028
                        fprintf(stderr, " depth:      %d\n", vinfo->depth);
 
2029
                        fprintf(stderr, " class:      %d\n", vinfo->class);
 
2030
                        fprintf(stderr, " red_mask:   0x%08lx  %s\n",
 
2031
                            vinfo->red_mask, bitprint(vinfo->red_mask, 32));
 
2032
                        fprintf(stderr, " green_mask: 0x%08lx  %s\n",
 
2033
                            vinfo->green_mask, bitprint(vinfo->green_mask, 32));
 
2034
                        fprintf(stderr, " blue_mask:  0x%08lx  %s\n",
 
2035
                            vinfo->blue_mask, bitprint(vinfo->blue_mask, 32));
 
2036
                        fprintf(stderr, " cmap_size:  %d\n",
 
2037
                            vinfo->colormap_size);
 
2038
                        fprintf(stderr, " bits b/rgb: %d\n",
 
2039
                            vinfo->bits_per_rgb);
 
2040
                        fprintf(stderr, "\n");
 
2041
                }
 
2042
                XFree_wr(vinfo);
 
2043
        }
 
2044
 
 
2045
        if (! quiet) {
 
2046
                rfbLog("Default visual ID: 0x%x\n",
 
2047
                    (int) XVisualIDFromVisual(default_visual));
 
2048
        }
 
2049
 
 
2050
        again:
 
2051
        if (subwin) {
 
2052
                int shift = 0;
 
2053
                int subwin_x, subwin_y;
 
2054
                int disp_x = DisplayWidth(dpy, scr);
 
2055
                int disp_y = DisplayHeight(dpy, scr);
 
2056
                Window twin;
 
2057
                /* subwins can be a dicey if they are changing size... */
 
2058
                trapped_xerror = 0;
 
2059
                old_handler = XSetErrorHandler(trap_xerror);
 
2060
                XTranslateCoordinates(dpy, window, rootwin, 0, 0, &subwin_x,
 
2061
                    &subwin_y, &twin);
 
2062
 
 
2063
                if (subwin_x + wdpy_x > disp_x) {
 
2064
                        shift = 1;
 
2065
                        subwin_x = disp_x - wdpy_x - 3;
 
2066
                }
 
2067
                if (subwin_y + wdpy_y > disp_y) {
 
2068
                        shift = 1;
 
2069
                        subwin_y = disp_y - wdpy_y - 3;
 
2070
                }
 
2071
                if (subwin_x < 0) {
 
2072
                        shift = 1;
 
2073
                        subwin_x = 1;
 
2074
                }
 
2075
                if (subwin_y < 0) {
 
2076
                        shift = 1;
 
2077
                        subwin_y = 1;
 
2078
                }
 
2079
 
 
2080
                if (shift) {
 
2081
                        XMoveWindow(dpy, window, subwin_x, subwin_y);
 
2082
                }
 
2083
                XMapRaised(dpy, window);
 
2084
                XRaiseWindow(dpy, window);
 
2085
                XFlush_wr(dpy);
 
2086
        }
 
2087
        try++;
 
2088
 
 
2089
        if (nofb) {
 
2090
                /* 
 
2091
                 * For -nofb we do not allocate the framebuffer, so we
 
2092
                 * can save a few MB of memory. 
 
2093
                 */
 
2094
                fb = XCreateImage_wr(dpy, default_visual, depth, ZPixmap,
 
2095
                    0, NULL, dpy_x, dpy_y, BitmapPad(dpy), 0);
 
2096
 
 
2097
        } else if (visual_id) {
 
2098
                /*
 
2099
                 * we need to call XCreateImage to supply the visual
 
2100
                 */
 
2101
                fb = XCreateImage_wr(dpy, default_visual, depth, ZPixmap,
 
2102
                    0, NULL, dpy_x, dpy_y, BitmapPad(dpy), 0);
 
2103
                fb->data = (char *) malloc(fb->bytes_per_line * fb->height);
 
2104
 
 
2105
        } else {
 
2106
                fb = XGetImage_wr(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes,
 
2107
                    ZPixmap);
 
2108
                if (! quiet) {
 
2109
                        rfbLog("Read initial data from X display into"
 
2110
                            " framebuffer.\n");
 
2111
                }
 
2112
        }
 
2113
 
 
2114
        if (subwin) {
 
2115
                XSetErrorHandler(old_handler);
 
2116
                if (trapped_xerror) {
 
2117
                    rfbLog("trapped GetImage at SUBWIN creation.\n");
 
2118
                    if (try < subwin_tries) {
 
2119
                        usleep(250 * 1000);
 
2120
                        if (!get_window_size(window, &wdpy_x, &wdpy_y)) {
 
2121
                                rfbLogEnable(1);
 
2122
                                rfbLog("could not get size of subwin "
 
2123
                                    "0x%lx\n", subwin);
 
2124
                                X_UNLOCK;
 
2125
                                clean_up_exit(1);
 
2126
                        }
 
2127
                        goto again;
 
2128
                    }
 
2129
                }
 
2130
                trapped_xerror = 0;
 
2131
 
 
2132
        } else if (! fb && try == 1) {
 
2133
                /* try once more */
 
2134
                usleep(250 * 1000);
 
2135
                goto again;
 
2136
        }
 
2137
        if (use_snapfb) {
 
2138
                initialize_snap_fb();
 
2139
        }
 
2140
        X_UNLOCK;
 
2141
 
 
2142
        if (fb->bits_per_pixel == 24 && ! quiet) {
 
2143
                rfbLog("warning: 24 bpp may have poor performance.\n");
 
2144
        }
 
2145
        return fb;
 
2146
#endif  /* NO_X11 */
 
2147
}
 
2148
 
 
2149
void parse_scale_string(char *str, double *factor, int *scaling, int *blend,
 
2150
    int *nomult4, int *pad, int *interpolate, int *numer, int *denom) {
 
2151
 
 
2152
        int m, n;
 
2153
        char *p, *tstr;
 
2154
        double f;
 
2155
 
 
2156
        *factor = 1.0;
 
2157
        *scaling = 0;
 
2158
        *blend = 1;
 
2159
        *nomult4 = 0;
 
2160
        *pad = 0;
 
2161
        *interpolate = 0;
 
2162
        *numer = 0, *denom = 0;
 
2163
 
 
2164
        if (str == NULL || str[0] == '\0') {
 
2165
                return;
 
2166
        }
 
2167
        tstr = strdup(str);
 
2168
        
 
2169
        if ( (p = strchr(tstr, ':')) != NULL) {
 
2170
                /* options */
 
2171
                if (strstr(p+1, "nb") != NULL) {
 
2172
                        *blend = 0;
 
2173
                }
 
2174
                if (strstr(p+1, "fb") != NULL) {
 
2175
                        *blend = 2;
 
2176
                }
 
2177
                if (strstr(p+1, "n4") != NULL) {
 
2178
                        *nomult4 = 1;
 
2179
                }
 
2180
                if (strstr(p+1, "in") != NULL) {
 
2181
                        *interpolate = 1;
 
2182
                }
 
2183
                if (strstr(p+1, "pad") != NULL) {
 
2184
                        *pad = 1;
 
2185
                }
 
2186
                if (strstr(p+1, "nocr") != NULL) {
 
2187
                        /* global */
 
2188
                        scaling_copyrect = 0;
 
2189
                } else if (strstr(p+1, "cr") != NULL) {
 
2190
                        /* global */
 
2191
                        scaling_copyrect = 1;
 
2192
                }
 
2193
                *p = '\0';
 
2194
        }
 
2195
        if (strchr(tstr, '.') != NULL) {
 
2196
                double test, diff, eps = 1.0e-7;
 
2197
                if (sscanf(tstr, "%lf", &f) != 1) {
 
2198
                        rfbLogEnable(1);
 
2199
                        rfbLog("invalid -scale arg: %s\n", tstr);
 
2200
                        clean_up_exit(1);
 
2201
                }
 
2202
                *factor = (double) f;
 
2203
                /* look for common fractions from small ints: */
 
2204
                for (n=2; n<=10; n++) {
 
2205
                        for (m=1; m<n; m++) {
 
2206
                                test = ((double) m)/ n;
 
2207
                                diff = *factor - test;
 
2208
                                if (-eps < diff && diff < eps) {
 
2209
                                        *numer = m;
 
2210
                                        *denom = n;
 
2211
                                        break;
 
2212
                                
 
2213
                                }
 
2214
                        }
 
2215
                        if (*denom) {
 
2216
                                break;
 
2217
                        }
 
2218
                }
 
2219
                if (*factor < 0.01) {
 
2220
                        rfbLogEnable(1);
 
2221
                        rfbLog("-scale factor too small: %f\n", scale_fac);
 
2222
                        clean_up_exit(1);
 
2223
                }
 
2224
        } else {
 
2225
                if (sscanf(tstr, "%d/%d", &m, &n) != 2) {
 
2226
                        if (sscanf(tstr, "%d", &m) != 1) {
 
2227
                                rfbLogEnable(1);
 
2228
                                rfbLog("invalid -scale arg: %s\n", tstr);
 
2229
                                clean_up_exit(1);
 
2230
                        } else {
 
2231
                                /* e.g. -scale 1 or -scale 2 */
 
2232
                                n = 1;
 
2233
                        }
 
2234
                }
 
2235
                if (n <= 0 || m <=0) {
 
2236
                        rfbLogEnable(1);
 
2237
                        rfbLog("invalid -scale arg: %s\n", tstr);
 
2238
                        clean_up_exit(1);
 
2239
                }
 
2240
                *factor = ((double) m)/ n;
 
2241
                if (*factor < 0.01) {
 
2242
                        rfbLogEnable(1);
 
2243
                        rfbLog("-scale factor too small: %f\n", *factor);
 
2244
                        clean_up_exit(1);
 
2245
                }
 
2246
                *numer = m;
 
2247
                *denom = n;
 
2248
        }
 
2249
        if (*factor == 1.0) {
 
2250
                if (! quiet) {
 
2251
                        rfbLog("scaling disabled for factor %f\n", *factor);
 
2252
                }
 
2253
        } else {
 
2254
                *scaling = 1;
 
2255
        }
 
2256
        free(tstr);
 
2257
}
 
2258
 
 
2259
int parse_rotate_string(char *str, int *mode) {
 
2260
        int m = ROTATE_NONE;
 
2261
        if (str == NULL || !strcmp(str, "") || !strcmp(str, "0")) {
 
2262
                m = ROTATE_NONE;
 
2263
        } else if (!strcmp(str, "x")) {
 
2264
                m = ROTATE_X;
 
2265
        } else if (!strcmp(str, "y")) {
 
2266
                m = ROTATE_Y;
 
2267
        } else if (!strcmp(str, "xy") || !strcmp(str, "yx") ||
 
2268
            !strcmp(str,"+180") || !strcmp(str,"-180") || !strcmp(str,"180")) {
 
2269
                m = ROTATE_XY;
 
2270
        } else if (!strcmp(str, "+90") || !strcmp(str, "90")) {
 
2271
                m = ROTATE_90;
 
2272
        } else if (!strcmp(str, "+90x") || !strcmp(str, "90x")) {
 
2273
                m = ROTATE_90X;
 
2274
        } else if (!strcmp(str, "+90y") || !strcmp(str, "90y")) {
 
2275
                m = ROTATE_90Y;
 
2276
        } else if (!strcmp(str, "-90") || !strcmp(str, "270") ||
 
2277
            !strcmp(str, "+270")) {
 
2278
                m = ROTATE_270;
 
2279
        } else {
 
2280
                rfbLog("invalid -rotate mode: %s\n", str);
 
2281
        }
 
2282
        if (mode) {
 
2283
                *mode = m;
 
2284
        }
 
2285
        return m;
 
2286
}
 
2287
 
 
2288
int scale_round(int len, double fac) {
 
2289
        double eps = 0.000001;
 
2290
        
 
2291
        len = (int) (len * fac + eps);
 
2292
        if (len < 1) {
 
2293
                len = 1;
 
2294
        }
 
2295
        return len;
 
2296
}
 
2297
 
 
2298
static void setup_scaling(int *width_in, int *height_in) {
 
2299
        int width  = *width_in;
 
2300
        int height = *height_in;
 
2301
 
 
2302
        parse_scale_string(scale_str, &scale_fac, &scaling, &scaling_blend,
 
2303
            &scaling_nomult4, &scaling_pad, &scaling_interpolate,
 
2304
            &scale_numer, &scale_denom);
 
2305
 
 
2306
        if (scaling) {
 
2307
                width  = scale_round(width,  scale_fac);
 
2308
                height = scale_round(height, scale_fac);
 
2309
                if (scale_denom && scaling_pad) {
 
2310
                        /* it is not clear this padding is useful anymore */
 
2311
                        rfbLog("width  %% denom: %d %% %d = %d\n", width,
 
2312
                            scale_denom, width  % scale_denom);
 
2313
                        rfbLog("height %% denom: %d %% %d = %d\n", height,
 
2314
                            scale_denom, height % scale_denom);
 
2315
                        if (width % scale_denom != 0) {
 
2316
                                int w = width;
 
2317
                                w += scale_denom - (w % scale_denom);
 
2318
                                if (!scaling_nomult4 && w % 4 != 0) {
 
2319
                                        /* need to make mult of 4 as well */
 
2320
                                        int c = 0;      
 
2321
                                        while (w % 4 != 0 && c++ <= 5) {
 
2322
                                                w += scale_denom;
 
2323
                                        }
 
2324
                                }
 
2325
                                width = w;
 
2326
                                rfbLog("padded width  to: %d (mult of %d%s\n",
 
2327
                                    width, scale_denom, !scaling_nomult4 ?
 
2328
                                    " and 4)" : ")");
 
2329
                        }
 
2330
                        if (height % scale_denom != 0) {
 
2331
                                height += scale_denom - (height % scale_denom);
 
2332
                                rfbLog("padded height to: %d (mult of %d)\n",
 
2333
                                    height, scale_denom);
 
2334
                        }
 
2335
                }
 
2336
                if (!scaling_nomult4 && width % 4 != 0 && width > 2) {
 
2337
                        /* reset width to be multiple of 4 */
 
2338
                        int width0 = width;
 
2339
                        if ((width+1) % 4 == 0) {
 
2340
                                width = width+1;
 
2341
                        } else if ((width-1) % 4 == 0) {
 
2342
                                width = width-1;
 
2343
                        } else if ((width+2) % 4 == 0) {
 
2344
                                width = width+2;
 
2345
                        }
 
2346
                        rfbLog("reset scaled width %d -> %d to be a multiple of"
 
2347
                            " 4 (to\n", width0, width);
 
2348
                        rfbLog("make vncviewers happy). use -scale m/n:n4 to "
 
2349
                            "disable.\n");
 
2350
                }
 
2351
                scaled_x = width;
 
2352
                scaled_y = height;
 
2353
 
 
2354
                *width_in  = width;
 
2355
                *height_in = height;
 
2356
        }
 
2357
}
 
2358
 
 
2359
static void setup_rotating(void) {
 
2360
        char *rs = rotating_str;
 
2361
 
 
2362
        rotating_cursors = 1;
 
2363
        if (rs && strstr(rs, "nc:") == rs) {
 
2364
                rs += strlen("nc:");
 
2365
                rotating_cursors = 0;
 
2366
        }
 
2367
 
 
2368
        rotating = parse_rotate_string(rs, NULL);
 
2369
        if (! rotating) {
 
2370
                rotating_cursors = 0;
 
2371
        }
 
2372
 
 
2373
        if (rotating == ROTATE_90  || rotating == ROTATE_90X ||
 
2374
            rotating == ROTATE_90Y || rotating == ROTATE_270) {
 
2375
                rotating_same = 0;
 
2376
        } else {
 
2377
                rotating_same = 1;
 
2378
        }
 
2379
}
 
2380
 
 
2381
static rfbBool set_xlate_wrapper(rfbClientPtr cl) {
 
2382
        static int first = 1;
 
2383
        if (first) {
 
2384
                first = 0;
 
2385
        } else if (ncache) {
 
2386
                int save = ncache_xrootpmap;
 
2387
                rfbLog("set_xlate_wrapper: clearing -ncache for new pixel format.\n");
 
2388
                ncache_xrootpmap = 0;
 
2389
                check_ncache(1, 0);
 
2390
                ncache_xrootpmap = save;
 
2391
        }
 
2392
        return rfbSetTranslateFunction(cl);     
 
2393
}
 
2394
 
 
2395
/*
 
2396
 * initialize the rfb framebuffer/screen
 
2397
 */
 
2398
void initialize_screen(int *argc, char **argv, XImage *fb) {
 
2399
        int have_masks = 0;
 
2400
        int width  = fb->width;
 
2401
        int height = fb->height;
 
2402
        int create_screen = screen ? 0 : 1;
 
2403
        int bits_per_color;
 
2404
        int fb_bpp, fb_Bpl, fb_depth;
 
2405
        
 
2406
        bpp = fb->bits_per_pixel;
 
2407
 
 
2408
        fb_bpp   = (int) fb->bits_per_pixel;
 
2409
        fb_Bpl   = (int) fb->bytes_per_line;
 
2410
        fb_depth = (int) fb->depth;
 
2411
 
 
2412
        rfbLog("initialize_screen: fb_depth/fb_bpp/fb_Bpl %d/%d/%d\n", fb_depth,
 
2413
            fb_bpp, fb_Bpl);
 
2414
 
 
2415
        main_bytes_per_line = fb->bytes_per_line;
 
2416
 
 
2417
        if (cmap8to24) {
 
2418
                if (raw_fb) {
 
2419
                        if (!quiet) rfbLog("disabling -8to24 mode"
 
2420
                            " in raw_fb mode.\n");
 
2421
                        cmap8to24 = 0;
 
2422
                } else if (depth == 24) {
 
2423
                        if (fb_bpp != 32)  {
 
2424
                                if (!quiet) rfbLog("disabling -8to24 mode:"
 
2425
                                    " bpp != 32 with depth == 24\n");
 
2426
                                cmap8to24 = 0;
 
2427
                        }
 
2428
                } else if (depth == 8) {
 
2429
                        /* need to cook up the screen fb to be depth 24 */
 
2430
                        fb_bpp = 32;
 
2431
                        fb_depth = 24;
 
2432
                } else {
 
2433
                        if (!quiet) rfbLog("disabling -8to24 mode:"
 
2434
                            " default depth not 24 or 8\n");
 
2435
                        cmap8to24 = 0;
 
2436
                }
 
2437
        }
 
2438
 
 
2439
        setup_scaling(&width, &height);
 
2440
 
 
2441
        if (scaling) {
 
2442
                rfbLog("scaling screen: %dx%d -> %dx%d  scale_fac=%.5f\n",
 
2443
                    fb->width, fb->height, scaled_x, scaled_y, scale_fac);
 
2444
 
 
2445
                rfb_bytes_per_line = (main_bytes_per_line / fb->width) * width;
 
2446
        } else {
 
2447
                rfb_bytes_per_line = main_bytes_per_line;
 
2448
        }
 
2449
 
 
2450
        setup_rotating();
 
2451
 
 
2452
        if (rotating) {
 
2453
                if (! rotating_same) {
 
2454
                        int t, b = main_bytes_per_line / fb->width;
 
2455
                        if (scaling) {
 
2456
                                rot_bytes_per_line = b * height;
 
2457
                        } else {
 
2458
                                rot_bytes_per_line = b * fb->height;
 
2459
                        }
 
2460
                        t = width;
 
2461
                        width = height;         /* The big swap... */
 
2462
                        height = t;
 
2463
                } else {
 
2464
                        rot_bytes_per_line = rfb_bytes_per_line;
 
2465
                }
 
2466
        }
 
2467
 
 
2468
#ifndef NO_NCACHE
 
2469
        if (ncache > 0 && !nofb) {
 
2470
# ifdef MACOSX
 
2471
                if (! raw_fb_str || macosx_console) {
 
2472
# else
 
2473
                if (! raw_fb_str) {
 
2474
# endif
 
2475
                        
 
2476
                        char *new_fb;
 
2477
                        int sz = fb->height * fb->bytes_per_line;
 
2478
                        int ns = 1+ncache;
 
2479
 
 
2480
                        if (ncache_xrootpmap) {
 
2481
                                ns++;
 
2482
                        }
 
2483
 
 
2484
                        new_fb = (char *) calloc((size_t) (sz * ns), 1);
 
2485
                        if (fb->data) {
 
2486
                                memcpy(new_fb, fb->data, sz);
 
2487
                                free(fb->data);
 
2488
                        }
 
2489
                        fb->data = new_fb;
 
2490
                        fb->height *= (ns);
 
2491
                        height *= (ns);
 
2492
                        ncache0 = ncache;
 
2493
                }
 
2494
        }
 
2495
#endif
 
2496
 
 
2497
        if (cmap8to24 && depth == 8) {
 
2498
                rfb_bytes_per_line *= 4;
 
2499
                rot_bytes_per_line *= 4;
 
2500
        }
 
2501
 
 
2502
        /*
 
2503
         * These are just hints wrt pixel format just to let
 
2504
         * rfbGetScreen/rfbNewFramebuffer proceed with reasonable
 
2505
         * defaults.  We manually set them in painful detail below.
 
2506
         */
 
2507
        bits_per_color = guess_bits_per_color(fb_bpp);
 
2508
 
 
2509
        /* n.b. samplesPerPixel (set = 1 here) seems to be unused. */
 
2510
        if (create_screen) {
 
2511
                if (use_openssl) {
 
2512
                        openssl_init(0);
 
2513
                } else if (use_stunnel) {
 
2514
                        setup_stunnel(0, argc, argv);
 
2515
                }
 
2516
                screen = rfbGetScreen(argc, argv, width, height,
 
2517
                    bits_per_color, 1, fb_bpp/8);
 
2518
                if (screen && http_dir) {
 
2519
                        http_connections(1);
 
2520
                }
 
2521
        } else {
 
2522
                /* set set frameBuffer member below. */
 
2523
                rfbLog("rfbNewFramebuffer(0x%x, 0x%x, %d, %d, %d, %d, %d)\n",
 
2524
                    screen, NULL, width, height, bits_per_color, 1, fb_bpp/8);
 
2525
 
 
2526
                /* these are probably overwritten, but just to be safe: */
 
2527
                screen->bitsPerPixel = fb_bpp;
 
2528
                screen->depth = fb_depth;
 
2529
 
 
2530
                rfbNewFramebuffer(screen, NULL, width, height,
 
2531
                    bits_per_color, 1, (int) fb_bpp/8);
 
2532
        }
 
2533
        if (! screen) {
 
2534
                int i;
 
2535
                rfbLogEnable(1);
 
2536
                rfbLog("\n");
 
2537
                rfbLog("failed to create rfb screen.\n");
 
2538
                for (i=0; i< *argc; i++)  {
 
2539
                        rfbLog("\t[%d]  %s\n", i, argv[i]);
 
2540
                }
 
2541
                clean_up_exit(1);
 
2542
        }
 
2543
 
 
2544
        if (create_screen && *argc != 1) {
 
2545
                int i;
 
2546
                rfbLogEnable(1);
 
2547
                rfbLog("*** unrecognized option(s) ***\n");
 
2548
                for (i=1; i< *argc; i++)  {
 
2549
                        rfbLog("\t[%d]  %s\n", i, argv[i]);
 
2550
                }
 
2551
                rfbLog("For a list of options run: x11vnc -opts\n");
 
2552
                rfbLog("or for the full help: x11vnc -help\n");
 
2553
                rfbLog("\n");
 
2554
                rfbLog("Here is a list of removed or obsolete"
 
2555
                    " options:\n");
 
2556
                rfbLog("\n");
 
2557
                rfbLog("removed: -hints, -nohints\n");
 
2558
                rfbLog("removed: -cursorposall\n");
 
2559
                rfbLog("removed: -nofilexfer, now the default.\n");
 
2560
                rfbLog("\n");
 
2561
                rfbLog("renamed: -old_copytile, use -onetile\n");
 
2562
                rfbLog("renamed: -mouse,   use -cursor\n");
 
2563
                rfbLog("renamed: -mouseX,  use -cursor X\n");
 
2564
                rfbLog("renamed: -X,       use -cursor X\n");
 
2565
                rfbLog("renamed: -nomouse, use -nocursor\n");
 
2566
                rfbLog("renamed: -old_pointer, use -pointer_mode 1\n");
 
2567
        
 
2568
                clean_up_exit(1);
 
2569
        }
 
2570
 
 
2571
        /* set up format from scratch: */
 
2572
        if (rotating && ! rotating_same) {
 
2573
                screen->paddedWidthInBytes = rot_bytes_per_line;
 
2574
        } else {
 
2575
                screen->paddedWidthInBytes = rfb_bytes_per_line;
 
2576
        }
 
2577
        screen->serverFormat.bitsPerPixel = fb_bpp;
 
2578
        screen->serverFormat.depth = fb_depth;
 
2579
        screen->serverFormat.trueColour = TRUE;
 
2580
 
 
2581
        screen->serverFormat.redShift   = 0;
 
2582
        screen->serverFormat.greenShift = 0;
 
2583
        screen->serverFormat.blueShift  = 0;
 
2584
        screen->serverFormat.redMax     = 0;
 
2585
        screen->serverFormat.greenMax   = 0;
 
2586
        screen->serverFormat.blueMax    = 0;
 
2587
 
 
2588
        /* these main_* formats are used generally. */
 
2589
        main_red_shift   = 0;
 
2590
        main_green_shift = 0;
 
2591
        main_blue_shift  = 0;
 
2592
        main_red_max     = 0;
 
2593
        main_green_max   = 0;
 
2594
        main_blue_max    = 0;
 
2595
        main_red_mask    = fb->red_mask;
 
2596
        main_green_mask  = fb->green_mask;
 
2597
        main_blue_mask   = fb->blue_mask;
 
2598
 
 
2599
        have_masks = ((fb->red_mask|fb->green_mask|fb->blue_mask) != 0);
 
2600
        if (force_indexed_color) {
 
2601
                have_masks = 0;
 
2602
        }
 
2603
 
 
2604
        if (cmap8to24 && depth == 8 && dpy) {
 
2605
                XVisualInfo vinfo;
 
2606
                vinfo.red_mask = 0;
 
2607
                vinfo.green_mask = 0;
 
2608
                vinfo.blue_mask = 0;
 
2609
                /* more cooking up... */
 
2610
                have_masks = 2;
 
2611
                /* need to fetch TrueColor visual */
 
2612
                X_LOCK;
 
2613
                if (dpy
 
2614
#if !NO_X11
 
2615
                    && XMatchVisualInfo(dpy, scr, 24, TrueColor, &vinfo)
 
2616
#endif
 
2617
                    ) {
 
2618
                        main_red_mask   = vinfo.red_mask;
 
2619
                        main_green_mask = vinfo.green_mask;
 
2620
                        main_blue_mask  = vinfo.blue_mask;
 
2621
                } else if (fb->byte_order == LSBFirst) {
 
2622
                        main_red_mask   = 0x00ff0000;
 
2623
                        main_green_mask = 0x0000ff00;
 
2624
                        main_blue_mask  = 0x000000ff;
 
2625
                } else {
 
2626
                        main_red_mask   = 0x000000ff;
 
2627
                        main_green_mask = 0x0000ff00;
 
2628
                        main_blue_mask  = 0x00ff0000;
 
2629
                }
 
2630
                X_UNLOCK;
 
2631
        }
 
2632
 
 
2633
        if (raw_fb_str && raw_fb_pixfmt) {
 
2634
                char *fmt = strdup(raw_fb_pixfmt);
 
2635
                uppercase(fmt);
 
2636
                if (strstr(fmt, "GREY")) {
 
2637
                        set_greyscale_colormap();
 
2638
                } else if (strstr(fmt, "HI240")) {
 
2639
                        set_hi240_colormap();
 
2640
                } else {
 
2641
                        unset_colormap();
 
2642
                }
 
2643
                free(fmt);
 
2644
        }
 
2645
 
 
2646
        if (! have_masks && screen->serverFormat.bitsPerPixel == 8
 
2647
            && dpy && CellsOfScreen(ScreenOfDisplay(dpy, scr))) {
 
2648
                /* indexed color */
 
2649
                if (!quiet) {
 
2650
                        rfbLog("\n");
 
2651
                        rfbLog("X display %s is 8bpp indexed color\n",
 
2652
                            DisplayString(dpy));
 
2653
                        if (! flash_cmap && ! overlay) {
 
2654
                                rfbLog("\n");
 
2655
                                rfbLog("In 8bpp PseudoColor mode if you "
 
2656
                                    "experience color\n");
 
2657
                                rfbLog("problems you may want to enable "
 
2658
                                    "following the\n");
 
2659
                                rfbLog("changing colormap by using the "
 
2660
                                    "-flashcmap option.\n");
 
2661
                                rfbLog("\n");
 
2662
                        }
 
2663
                }
 
2664
                screen->serverFormat.trueColour = FALSE;
 
2665
                indexed_color = 1;
 
2666
                set_colormap(1);
 
2667
                debug_colormap(fb);
 
2668
        } else {
 
2669
                /* 
 
2670
                 * general case, we call it truecolor, but could be direct
 
2671
                 * color, static color, etc....
 
2672
                 */
 
2673
                if (! quiet) {
 
2674
                        if (raw_fb) {
 
2675
                                rfbLog("\n");
 
2676
                                rfbLog("Raw fb at addr %p is %dbpp depth=%d "
 
2677
                                    "true color\n", raw_fb_addr,
 
2678
                                    fb_bpp, fb_depth);
 
2679
                        } else if (! dpy) {
 
2680
                                ;
 
2681
                        } else if (have_masks == 2) {
 
2682
                                rfbLog("\n");
 
2683
                                rfbLog("X display %s is %dbpp depth=%d indexed "
 
2684
                                    "color (-8to24 mode)\n", DisplayString(dpy),
 
2685
                                    fb->bits_per_pixel, fb->depth);
 
2686
                        } else {
 
2687
                                rfbLog("\n");
 
2688
                                rfbLog("X display %s is %dbpp depth=%d true "
 
2689
                                    "color\n", DisplayString(dpy),
 
2690
                                    fb_bpp, fb_depth);
 
2691
                        }
 
2692
                }
 
2693
 
 
2694
                indexed_color = 0;
 
2695
 
 
2696
                /* convert masks to bit shifts and max # colors */
 
2697
                if (main_red_mask) {
 
2698
                        while (! (main_red_mask
 
2699
                            & (1 << screen->serverFormat.redShift))) {
 
2700
                                    screen->serverFormat.redShift++;
 
2701
                        }
 
2702
                }
 
2703
                if (main_green_mask) {
 
2704
                        while (! (main_green_mask
 
2705
                            & (1 << screen->serverFormat.greenShift))) {
 
2706
                                    screen->serverFormat.greenShift++;
 
2707
                        }
 
2708
                }
 
2709
                if (main_blue_mask) {
 
2710
                        while (! (main_blue_mask
 
2711
                            & (1 << screen->serverFormat.blueShift))) {
 
2712
                                    screen->serverFormat.blueShift++;
 
2713
                        }
 
2714
                }
 
2715
                screen->serverFormat.redMax
 
2716
                    = main_red_mask   >> screen->serverFormat.redShift;
 
2717
                screen->serverFormat.greenMax
 
2718
                    = main_green_mask >> screen->serverFormat.greenShift;
 
2719
                screen->serverFormat.blueMax
 
2720
                    = main_blue_mask  >> screen->serverFormat.blueShift;
 
2721
 
 
2722
                main_red_max     = screen->serverFormat.redMax;
 
2723
                main_green_max   = screen->serverFormat.greenMax;
 
2724
                main_blue_max    = screen->serverFormat.blueMax;
 
2725
 
 
2726
                main_red_shift   = screen->serverFormat.redShift;
 
2727
                main_green_shift = screen->serverFormat.greenShift;
 
2728
                main_blue_shift  = screen->serverFormat.blueShift;
 
2729
        }
 
2730
 
 
2731
#if !SMALL_FOOTPRINT
 
2732
        if (verbose) {
 
2733
                fprintf(stderr, "\n");
 
2734
                fprintf(stderr, "FrameBuffer Info:\n");
 
2735
                fprintf(stderr, " width:            %d\n", fb->width);
 
2736
                fprintf(stderr, " height:           %d\n", fb->height);
 
2737
                fprintf(stderr, " scaled_width:     %d\n", width);
 
2738
                fprintf(stderr, " scaled_height:    %d\n", height);
 
2739
                fprintf(stderr, " indexed_color:    %d\n", indexed_color);
 
2740
                fprintf(stderr, " bits_per_pixel:   %d\n", fb->bits_per_pixel);
 
2741
                fprintf(stderr, " depth:            %d\n", fb->depth);
 
2742
                fprintf(stderr, " red_mask:   0x%08lx  %s\n", fb->red_mask,
 
2743
                    bitprint(fb->red_mask, 32));
 
2744
                fprintf(stderr, " green_mask: 0x%08lx  %s\n", fb->green_mask,
 
2745
                    bitprint(fb->green_mask, 32));
 
2746
                fprintf(stderr, " blue_mask:  0x%08lx  %s\n", fb->blue_mask,
 
2747
                    bitprint(fb->blue_mask, 32));
 
2748
                if (cmap8to24) {
 
2749
                        fprintf(stderr, " 8to24 info:\n");
 
2750
                        fprintf(stderr, " fb_bpp:           %d\n", fb_bpp);
 
2751
                        fprintf(stderr, " fb_depth:         %d\n", fb_depth);
 
2752
                        fprintf(stderr, " red_mask:   0x%08lx  %s\n", main_red_mask,
 
2753
                            bitprint(main_red_mask, 32));
 
2754
                        fprintf(stderr, " green_mask: 0x%08lx  %s\n", main_green_mask,
 
2755
                            bitprint(main_green_mask, 32));
 
2756
                        fprintf(stderr, " blue_mask:  0x%08lx  %s\n", main_blue_mask,
 
2757
                            bitprint(main_blue_mask, 32));
 
2758
                }
 
2759
                fprintf(stderr, " red:   max: %3d  shift: %2d\n",
 
2760
                        main_red_max, main_red_shift);
 
2761
                fprintf(stderr, " green: max: %3d  shift: %2d\n",
 
2762
                        main_green_max, main_green_shift);
 
2763
                fprintf(stderr, " blue:  max: %3d  shift: %2d\n",
 
2764
                        main_blue_max, main_blue_shift);
 
2765
                fprintf(stderr, " mainfb_bytes_per_line: %d\n",
 
2766
                        main_bytes_per_line);
 
2767
                fprintf(stderr, " rfb_fb_bytes_per_line: %d\n",
 
2768
                        rfb_bytes_per_line);
 
2769
                fprintf(stderr, " rot_fb_bytes_per_line: %d\n",
 
2770
                        rot_bytes_per_line);
 
2771
                fprintf(stderr, " raw_fb_bytes_per_line: %d\n",
 
2772
                        raw_fb_bytes_per_line);
 
2773
                switch(fb->format) {
 
2774
                case XYBitmap:
 
2775
                        fprintf(stderr, " format:     XYBitmap\n"); break;
 
2776
                case XYPixmap:
 
2777
                        fprintf(stderr, " format:     XYPixmap\n"); break;
 
2778
                case ZPixmap:
 
2779
                        fprintf(stderr, " format:     ZPixmap\n"); break;
 
2780
                default:
 
2781
                        fprintf(stderr, " format:     %d\n", fb->format); break;
 
2782
                }
 
2783
                switch(fb->byte_order) {
 
2784
                case LSBFirst:
 
2785
                        fprintf(stderr, " byte_order: LSBFirst\n"); break;
 
2786
                case MSBFirst:
 
2787
                        fprintf(stderr, " byte_order: MSBFirst\n"); break;
 
2788
                default:
 
2789
                        fprintf(stderr, " byte_order: %d\n", fb->byte_order);
 
2790
                        break;
 
2791
                }
 
2792
                fprintf(stderr, " bitmap_pad:  %d\n", fb->bitmap_pad);
 
2793
                fprintf(stderr, " bitmap_unit: %d\n", fb->bitmap_unit);
 
2794
                switch(fb->bitmap_bit_order) {
 
2795
                case LSBFirst:
 
2796
                        fprintf(stderr, " bitmap_bit_order: LSBFirst\n"); break;
 
2797
                case MSBFirst:
 
2798
                        fprintf(stderr, " bitmap_bit_order: MSBFirst\n"); break;
 
2799
                default:
 
2800
                        fprintf(stderr, " bitmap_bit_order: %d\n",
 
2801
                        fb->bitmap_bit_order); break;
 
2802
                }
 
2803
        }
 
2804
        if (overlay && ! quiet) {
 
2805
                rfbLog("\n");
 
2806
                rfbLog("Overlay mode enabled:  If you experience color\n");
 
2807
                rfbLog("problems when popup menus are on the screen, try\n");
 
2808
                rfbLog("disabling SaveUnders in your X server, one way is\n");
 
2809
                rfbLog("to start the X server with the '-su' option, e.g.:\n");
 
2810
                rfbLog("Xsun -su ... see Xserver(1), xinit(1) for more info.\n");
 
2811
                rfbLog("\n");
 
2812
        }
 
2813
#endif
 
2814
        /* nofb is for pointer/keyboard only handling.  */
 
2815
        if (nofb) {
 
2816
                main_fb = NULL;
 
2817
                rfb_fb = main_fb;
 
2818
                cmap8to24_fb = NULL;
 
2819
                rot_fb = NULL;
 
2820
                screen->displayHook = nofb_hook;
 
2821
        } else {
 
2822
                main_fb = fb->data;
 
2823
                rfb_fb = NULL;
 
2824
                cmap8to24_fb = NULL;
 
2825
                rot_fb = NULL;
 
2826
 
 
2827
                if (cmap8to24) {
 
2828
                        int n = main_bytes_per_line * fb->height;
 
2829
                        if (depth == 8) {
 
2830
                                n *= 4;
 
2831
                        }
 
2832
                        cmap8to24_fb = (char *) malloc(n);
 
2833
                        memset(cmap8to24_fb, 0, n);
 
2834
                }
 
2835
 
 
2836
                if (rotating) {
 
2837
                        int n = rot_bytes_per_line * height;
 
2838
                        rot_fb = (char *) malloc(n);
 
2839
                        memset(rot_fb, 0, n);
 
2840
                }
 
2841
 
 
2842
                if (scaling) {
 
2843
                        int n = rfb_bytes_per_line * height;
 
2844
 
 
2845
                        if (rotating && ! rotating_same) {
 
2846
                                n = rot_bytes_per_line * height;
 
2847
                        }
 
2848
 
 
2849
                        rfb_fb = (char *) malloc(n);
 
2850
                        memset(rfb_fb, 0, n);
 
2851
 
 
2852
                } else if (cmap8to24) {
 
2853
                        rfb_fb = cmap8to24_fb;  
 
2854
                } else {
 
2855
                        rfb_fb = main_fb;
 
2856
                }
 
2857
        }
 
2858
        if (rot_fb) {
 
2859
                screen->frameBuffer = rot_fb;
 
2860
        } else {
 
2861
                screen->frameBuffer = rfb_fb;
 
2862
        }
 
2863
        if (verbose) {
 
2864
                fprintf(stderr, " rfb_fb:      %p\n", rfb_fb);
 
2865
                fprintf(stderr, " main_fb:     %p\n", main_fb);
 
2866
                fprintf(stderr, " 8to24_fb:    %p\n", cmap8to24_fb);
 
2867
                fprintf(stderr, " rot_fb:      %p\n", rot_fb);
 
2868
                fprintf(stderr, " snap_fb:     %p\n", snap_fb);
 
2869
                fprintf(stderr, " raw_fb:      %p\n", raw_fb);
 
2870
                fprintf(stderr, " fake_fb:     %p\n", fake_fb);
 
2871
                fprintf(stderr, "\n");
 
2872
        }
 
2873
 
 
2874
        /* may need, bpp, main_red_max, etc. */
 
2875
        parse_wireframe();
 
2876
        parse_scroll_copyrect();
 
2877
 
 
2878
        setup_cursors_and_push();
 
2879
 
 
2880
        if (scaling || rotating || cmap8to24) {
 
2881
                mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
 
2882
        }
 
2883
 
 
2884
        if (! create_screen) {
 
2885
                rfbClientIteratorPtr iter;
 
2886
                rfbClientPtr cl;
 
2887
 
 
2888
                /* 
 
2889
                 * since bits_per_color above may have been approximate,
 
2890
                 * try to reset the individual translation tables...
 
2891
                 * we do not seem to need this with rfbGetScreen()...
 
2892
                 */
 
2893
                if (!quiet) rfbLog("calling setTranslateFunction()...\n");
 
2894
                iter = rfbGetClientIterator(screen);
 
2895
                while ((cl = rfbClientIteratorNext(iter)) != NULL) {
 
2896
                        screen->setTranslateFunction(cl);
 
2897
                }
 
2898
                rfbReleaseClientIterator(iter);
 
2899
                if (!quiet) rfbLog("  done.\n");
 
2900
                do_copy_screen = 1;
 
2901
                
 
2902
                /* done for framebuffer change case */
 
2903
                return;
 
2904
        }
 
2905
 
 
2906
        /*
 
2907
         * the rest is screen server initialization, etc, only needed
 
2908
         * at screen creation time.
 
2909
         */
 
2910
 
 
2911
        /* event callbacks: */
 
2912
        screen->newClientHook = new_client;
 
2913
        screen->kbdAddEvent = keyboard;
 
2914
        screen->ptrAddEvent = pointer;
 
2915
        screen->setXCutText = xcut_receive;
 
2916
        screen->setTranslateFunction = set_xlate_wrapper;
 
2917
 
 
2918
        screen->kbdReleaseAllKeys = kbd_release_all_keys; 
 
2919
        screen->setSingleWindow = set_single_window; 
 
2920
        screen->setServerInput = set_server_input; 
 
2921
        screen->setTextChat = set_text_chat; 
 
2922
        screen->getFileTransferPermission = get_file_transfer_permitted; 
 
2923
 
 
2924
        /* called from inetd, we need to treat stdio as our socket */
 
2925
        if (inetd && use_openssl) {
 
2926
                /* accept_openssl() called later */
 
2927
                screen->port = 0;
 
2928
        } else if (inetd) {
 
2929
                int fd = dup(0);
 
2930
                if (fd < 0) {
 
2931
                        rfbLogEnable(1);
 
2932
                        rfbErr("dup(0) = %d failed.\n", fd);
 
2933
                        rfbLogPerror("dup");
 
2934
                        clean_up_exit(1);
 
2935
                }
 
2936
                fclose(stdin);
 
2937
                fclose(stdout);
 
2938
                /* we keep stderr for logging */
 
2939
                screen->inetdSock = fd;
 
2940
                screen->port = 0;
 
2941
 
 
2942
        } else if (! got_rfbport && auto_port > 0) {
 
2943
                int lport = find_free_port(auto_port, auto_port+200);
 
2944
                screen->autoPort = FALSE;
 
2945
                screen->port = lport;
 
2946
        } else if (! got_rfbport) {
 
2947
                screen->autoPort = TRUE;
 
2948
        } else if (got_rfbport && got_rfbport_val == 0) {
 
2949
                screen->autoPort = FALSE;
 
2950
                screen->port = 0;
 
2951
        }
 
2952
 
 
2953
        if (! got_nevershared && ! got_alwaysshared) {
 
2954
                if (shared) {
 
2955
                        screen->alwaysShared = TRUE;
 
2956
                } else {
 
2957
                        screen->neverShared = TRUE;
 
2958
                }
 
2959
                screen->dontDisconnect = TRUE;
 
2960
        }
 
2961
        if (! got_deferupdate) {
 
2962
                screen->deferUpdateTime = defer_update;
 
2963
        }
 
2964
 
 
2965
        rfbInitServer(screen);
 
2966
 
 
2967
        if (use_openssl) {
 
2968
                openssl_port();
 
2969
                if (https_port_num >= 0) {
 
2970
                        https_port();
 
2971
                }
 
2972
        }
 
2973
 
 
2974
        install_passwds();
 
2975
}
 
2976
 
 
2977
#define DO_AVAHI \
 
2978
        if (avahi) { \
 
2979
                avahi_initialise(); \
 
2980
                avahi_advertise(vnc_desktop_name, host, lport); \
 
2981
                usleep(1000*1000); \
 
2982
        }
 
2983
 
 
2984
void announce(int lport, int ssl, char *iface) {
 
2985
        
 
2986
        char *host = this_host();
 
2987
        char *tvdt;
 
2988
 
 
2989
        if (! ssl) {
 
2990
                tvdt = "The VNC desktop is:     ";
 
2991
        } else {
 
2992
                tvdt = "The SSL VNC desktop is: ";
 
2993
        }
 
2994
 
 
2995
        if (iface != NULL && *iface != '\0' && strcmp(iface, "any")) {
 
2996
                host = iface;
 
2997
        }
 
2998
        if (host != NULL) {
 
2999
                /* note that vncviewer special cases 5900-5999 */
 
3000
                int sz = 256;
 
3001
                if (inetd) {
 
3002
                        ;       /* should not occur (port) */
 
3003
                } else if (quiet) {
 
3004
                        if (lport >= 5900) {
 
3005
                                snprintf(vnc_desktop_name, sz, "%s:%d",
 
3006
                                    host, lport - 5900);
 
3007
                                DO_AVAHI
 
3008
                                fprintf(stderr, "\n%s %s\n", tvdt,
 
3009
                                    vnc_desktop_name);
 
3010
                        } else {
 
3011
                                snprintf(vnc_desktop_name, sz, "%s:%d",
 
3012
                                    host, lport);
 
3013
                                DO_AVAHI
 
3014
                                fprintf(stderr, "\n%s %s\n", tvdt,
 
3015
                                    vnc_desktop_name);
 
3016
                        }
 
3017
                } else if (lport >= 5900) {
 
3018
                        snprintf(vnc_desktop_name, sz, "%s:%d",
 
3019
                            host, lport - 5900);
 
3020
                        DO_AVAHI
 
3021
                        fprintf(stderr, "\n%s %s\n", tvdt, vnc_desktop_name);
 
3022
                        if (lport >= 6000) {
 
3023
                                rfbLog("possible aliases:  %s:%d, "
 
3024
                                    "%s::%d\n", host, lport,
 
3025
                                    host, lport);
 
3026
                        }
 
3027
                } else {
 
3028
                        snprintf(vnc_desktop_name, sz, "%s:%d",
 
3029
                            host, lport);
 
3030
                        DO_AVAHI
 
3031
                        fprintf(stderr, "\n%s %s\n", tvdt, vnc_desktop_name);
 
3032
                        rfbLog("possible alias:    %s::%d\n",
 
3033
                            host, lport);
 
3034
                }
 
3035
        }
 
3036
}
 
3037
 
 
3038
static void announce_http(int lport, int ssl, char *iface) {
 
3039
        
 
3040
        char *host = this_host();
 
3041
        char *jvu;
 
3042
 
 
3043
        if (ssl == 1) {
 
3044
                jvu = "Java SSL viewer URL:     https";
 
3045
        } else if (ssl == 2) {
 
3046
                jvu = "Java SSL viewer URL:     http";
 
3047
        } else {
 
3048
                jvu = "Java viewer URL:         http";
 
3049
        }
 
3050
 
 
3051
        if (iface != NULL && *iface != '\0' && strcmp(iface, "any")) {
 
3052
                host = iface;
 
3053
        }
 
3054
        if (host != NULL) {
 
3055
                if (! inetd) {
 
3056
                        fprintf(stderr, "%s://%s:%d/\n", jvu, host, lport);
 
3057
                }
 
3058
        }
 
3059
}
 
3060
 
 
3061
void set_vnc_desktop_name(void) {
 
3062
        sprintf(vnc_desktop_name, "unknown");
 
3063
        if (inetd) {
 
3064
                sprintf(vnc_desktop_name, "%s/inetd-no-further-clients",
 
3065
                    this_host());
 
3066
        }
 
3067
        if (screen->port) {
 
3068
 
 
3069
                if (! quiet) {
 
3070
                        if (screen->httpListenSock > -1 && screen->httpPort) {
 
3071
                                rfbLog("\n");
 
3072
                                rfbLog("The URLs printed out below ('Java ... viewer URL') can\n");
 
3073
                                rfbLog("be used for Java enabled Web browser connections.\n");
 
3074
                                if (use_openssl || stunnel_port) {
 
3075
                                        rfbLog("Here are some additional possibilities:\n");
 
3076
                                        rfbLog("\n");
 
3077
                                        rfbLog("https://host:port/proxy.vnc (MUST be used if Web Proxy used)\n");
 
3078
                                        rfbLog("\n");
 
3079
                                        rfbLog("https://host:port/ultra.vnc (Use UltraVNC Java Viewer)\n");
 
3080
                                        rfbLog("https://host:port/ultraproxy.vnc (Web Proxy with UltraVNC)\n");
 
3081
                                        rfbLog("https://host:port/ultrasigned.vnc (Signed UltraVNC Filexfer)\n");
 
3082
                                        rfbLog("\n");
 
3083
                                        rfbLog("Where you replace \"host:port\" with that printed below, or\n");
 
3084
                                        rfbLog("whatever is needed to reach the host e.g. Internet IP number\n");
 
3085
                                }
 
3086
                        }
 
3087
                        rfbLog("\n");
 
3088
                }
 
3089
 
 
3090
                if (use_openssl) {
 
3091
                        announce(screen->port, 1, listen_str);
 
3092
                } else {
 
3093
                        announce(screen->port, 0, listen_str);
 
3094
                }
 
3095
                if (stunnel_port) {
 
3096
                        announce(stunnel_port, 1, NULL);
 
3097
                }
 
3098
                if (screen->httpListenSock > -1 && screen->httpPort) {
 
3099
                        if (use_openssl) {
 
3100
                                announce_http(screen->port, 1, listen_str);
 
3101
                                if (https_port_num >= 0) {
 
3102
                                        announce_http(https_port_num, 1,
 
3103
                                            listen_str);
 
3104
                                }
 
3105
                                announce_http(screen->httpPort, 2, listen_str);
 
3106
                        } else if (use_stunnel) {
 
3107
                                announce_http(screen->httpPort, 2, listen_str);
 
3108
                        } else {
 
3109
                                announce_http(screen->httpPort, 0, listen_str);
 
3110
                        }
 
3111
                }
 
3112
                
 
3113
                fflush(stderr); 
 
3114
                if (inetd) {
 
3115
                        ;       /* should not occur (port != 0) */
 
3116
                } else {
 
3117
                        fprintf(stdout, "PORT=%d\n", screen->port);
 
3118
                        if (stunnel_port) {
 
3119
                                fprintf(stdout, "SSLPORT=%d\n", stunnel_port);
 
3120
                        } else if (use_openssl) {
 
3121
                                fprintf(stdout, "SSLPORT=%d\n", screen->port);
 
3122
                        }
 
3123
                        fflush(stdout); 
 
3124
                        if (flagfile) {
 
3125
                                FILE *flag = fopen(flagfile, "w");
 
3126
                                if (flag) {
 
3127
                                        fprintf(flag, "PORT=%d\n",screen->port);
 
3128
                                        if (stunnel_port) {
 
3129
                                                fprintf(flag, "SSL_PORT=%d\n",
 
3130
                                                    stunnel_port);
 
3131
                                        }
 
3132
                                        fflush(flag);   
 
3133
                                        fclose(flag);
 
3134
                                } else {
 
3135
                                        rfbLog("could not open flag file: %s\n",
 
3136
                                            flagfile);
 
3137
                                }
 
3138
                        }
 
3139
                }
 
3140
                fflush(stdout); 
 
3141
        }
 
3142
}
 
3143
 
 
3144