1/*
2
3Copyright 1993, 1998  The Open Group
4Copyright (C) Colin Harrison 2005-2008
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included
13in all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
19OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of The Open Group shall
24not be used in advertising or otherwise to promote the sale, use or
25other dealings in this Software without prior written authorization
26from The Open Group.
27
28*/
29
30#ifdef HAVE_XWIN_CONFIG_H
31#include <xwin-config.h>
32#endif
33
34#ifdef HAVE_SYS_UTSNAME_H
35#include <sys/utsname.h>
36#endif
37
38#include <../xfree86/common/xorgVersion.h>
39#include "win.h"
40#include "winconfig.h"
41#include "winmsg.h"
42#include "winmonitors.h"
43#include "winprefs.h"
44
45#include "winclipboard/winclipboard.h"
46
47/*
48 * Function prototypes
49 */
50
51void
52 winLogCommandLine(int argc, char *argv[]);
53
54void
55 winLogVersionInfo(void);
56
57/*
58 * Process arguments on the command line
59 */
60
61static int iLastScreen = -1;
62static winScreenInfo defaultScreenInfo;
63
64static void
65winInitializeScreenDefaults(void)
66{
67    DWORD dwWidth, dwHeight;
68    static Bool fInitializedScreenDefaults = FALSE;
69
70    /* Bail out early if default screen has already been initialized */
71    if (fInitializedScreenDefaults)
72        return;
73
74    /* Zero the memory used for storing the screen info */
75    memset(&defaultScreenInfo, 0, sizeof(winScreenInfo));
76
77    /* Get default width and height */
78    /*
79     * NOTE: These defaults will cause the window to cover only
80     * the primary monitor in the case that we have multiple monitors.
81     */
82    dwWidth = GetSystemMetrics(SM_CXSCREEN);
83    dwHeight = GetSystemMetrics(SM_CYSCREEN);
84
85    winErrorFVerb(2,
86                  "winInitializeScreenDefaults - primary monitor w %d h %d\n",
87                  (int) dwWidth, (int) dwHeight);
88
89    /* Set a default DPI, if no '-dpi' option was used */
90    if (monitorResolution == 0) {
91        HDC hdc = GetDC(NULL);
92
93        if (hdc) {
94            int dpiX = GetDeviceCaps(hdc, LOGPIXELSX);
95            int dpiY = GetDeviceCaps(hdc, LOGPIXELSY);
96
97            winErrorFVerb(2,
98                          "winInitializeScreenDefaults - native DPI x %d y %d\n",
99                          dpiX, dpiY);
100
101            monitorResolution = dpiY;
102            ReleaseDC(NULL, hdc);
103        }
104        else {
105            winErrorFVerb(1,
106                          "winInitializeScreenDefaults - Failed to retrieve native DPI, falling back to default of %d DPI\n",
107                          WIN_DEFAULT_DPI);
108            monitorResolution = WIN_DEFAULT_DPI;
109        }
110    }
111
112    defaultScreenInfo.iMonitor = 1;
113    defaultScreenInfo.hMonitor = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY);
114    defaultScreenInfo.dwWidth = dwWidth;
115    defaultScreenInfo.dwHeight = dwHeight;
116    defaultScreenInfo.dwUserWidth = dwWidth;
117    defaultScreenInfo.dwUserHeight = dwHeight;
118    defaultScreenInfo.fUserGaveHeightAndWidth =
119        WIN_DEFAULT_USER_GAVE_HEIGHT_AND_WIDTH;
120    defaultScreenInfo.fUserGavePosition = FALSE;
121    defaultScreenInfo.dwBPP = WIN_DEFAULT_BPP;
122    defaultScreenInfo.dwClipUpdatesNBoxes = WIN_DEFAULT_CLIP_UPDATES_NBOXES;
123#ifdef XWIN_EMULATEPSEUDO
124    defaultScreenInfo.fEmulatePseudo = WIN_DEFAULT_EMULATE_PSEUDO;
125#endif
126    defaultScreenInfo.dwRefreshRate = WIN_DEFAULT_REFRESH;
127    defaultScreenInfo.pfb = NULL;
128    defaultScreenInfo.fFullScreen = FALSE;
129    defaultScreenInfo.fDecoration = TRUE;
130    defaultScreenInfo.fRootless = FALSE;
131    defaultScreenInfo.fMultiWindow = FALSE;
132    defaultScreenInfo.fCompositeWM = TRUE;
133    defaultScreenInfo.fMultiMonitorOverride = FALSE;
134    defaultScreenInfo.fMultipleMonitors = FALSE;
135    defaultScreenInfo.fLessPointer = FALSE;
136    defaultScreenInfo.iResizeMode = resizeDefault;
137    defaultScreenInfo.fNoTrayIcon = FALSE;
138    defaultScreenInfo.iE3BTimeout = WIN_E3B_DEFAULT;
139    defaultScreenInfo.fUseWinKillKey = WIN_DEFAULT_WIN_KILL;
140    defaultScreenInfo.fUseUnixKillKey = WIN_DEFAULT_UNIX_KILL;
141    defaultScreenInfo.fIgnoreInput = FALSE;
142    defaultScreenInfo.fExplicitScreen = FALSE;
143    defaultScreenInfo.hIcon = (HICON)
144        LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_XWIN), IMAGE_ICON,
145                  GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0);
146    defaultScreenInfo.hIconSm = (HICON)
147        LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_XWIN), IMAGE_ICON,
148                  GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
149                  LR_DEFAULTSIZE);
150
151    /* Note that the default screen has been initialized */
152    fInitializedScreenDefaults = TRUE;
153}
154
155static void
156winInitializeScreen(int i)
157{
158    winErrorFVerb(3, "winInitializeScreen - %d\n", i);
159
160    /* Initialize default screen values, if needed */
161    winInitializeScreenDefaults();
162
163    /* Copy the default screen info */
164    g_ScreenInfo[i] = defaultScreenInfo;
165
166    /* Set the screen number */
167    g_ScreenInfo[i].dwScreen = i;
168}
169
170void
171winInitializeScreens(int maxscreens)
172{
173    int i;
174
175    winErrorFVerb(3, "winInitializeScreens - %i\n", maxscreens);
176
177    if (maxscreens > g_iNumScreens) {
178        /* Reallocate the memory for DDX-specific screen info */
179        g_ScreenInfo =
180            realloc(g_ScreenInfo, maxscreens * sizeof(winScreenInfo));
181
182        /* Set default values for any new screens */
183        for (i = g_iNumScreens; i < maxscreens; i++)
184            winInitializeScreen(i);
185
186        /* Keep a count of the number of screens */
187        g_iNumScreens = maxscreens;
188    }
189}
190
191/* See Porting Layer Definition - p. 57 */
192/*
193 * INPUT
194 * argv: pointer to an array of null-terminated strings, one for
195 *   each token in the X Server command line; the first token
196 *   is 'XWin.exe', or similar.
197 * argc: a count of the number of tokens stored in argv.
198 * i: a zero-based index into argv indicating the current token being
199 *   processed.
200 *
201 * OUTPUT
202 * return: return the number of tokens processed correctly.
203 *
204 * NOTE
205 * When looking for n tokens, check that i + n is less than argc.  Or,
206 *   you may check if i is greater than or equal to argc, in which case
207 *   you should display the UseMsg () and return 0.
208 */
209
210/* Check if enough arguments are given for the option */
211#define CHECK_ARGS(count) if (i + count >= argc) { UseMsg (); return 0; }
212
213/* Compare the current option with the string. */
214#define IS_OPTION(name) (strcmp (argv[i], name) == 0)
215
216int
217ddxProcessArgument(int argc, char *argv[], int i)
218{
219    static Bool s_fBeenHere = FALSE;
220    winScreenInfo *screenInfoPtr = NULL;
221
222    /* Initialize once */
223    if (!s_fBeenHere) {
224#ifdef DDXOSVERRORF
225        /*
226         * This initialises our hook into VErrorF () for catching log messages
227         * that are generated before OsInit () is called.
228         */
229        OsVendorVErrorFProc = OsVendorVErrorF;
230#endif
231
232        s_fBeenHere = TRUE;
233
234        /* Initialize only if option is not -help */
235        if (!IS_OPTION("-help") && !IS_OPTION("-h") && !IS_OPTION("--help") &&
236            !IS_OPTION("-version") && !IS_OPTION("--version")) {
237
238            /* Log the version information */
239            winLogVersionInfo();
240
241            /* Log the command line */
242            winLogCommandLine(argc, argv);
243
244            /*
245             * Initialize default screen settings.  We have to do this before
246             * OsVendorInit () gets called, otherwise we will overwrite
247             * settings changed by parameters such as -fullscreen, etc.
248             */
249            winErrorFVerb(3, "ddxProcessArgument - Initializing default "
250                          "screens\n");
251            winInitializeScreenDefaults();
252        }
253    }
254
255#if CYGDEBUG
256    winDebug("ddxProcessArgument - arg: %s\n", argv[i]);
257#endif
258
259    /*
260     * Look for the '-help' and similar options
261     */
262    if (IS_OPTION("-help") || IS_OPTION("-h") || IS_OPTION("--help")) {
263        /* Reset logfile. We don't need that helpmessage in the logfile */
264        g_pszLogFile = NULL;
265        g_fNoHelpMessageBox = TRUE;
266        UseMsg();
267        exit(0);
268        return 1;
269    }
270
271    if (IS_OPTION("-version") || IS_OPTION("--version")) {
272        /* Reset logfile. We don't need that versioninfo in the logfile */
273        g_pszLogFile = NULL;
274        winLogVersionInfo();
275        exit(0);
276        return 1;
277    }
278
279    /*
280     * Look for the '-screen scr_num [width height]' argument
281     */
282    if (IS_OPTION("-screen")) {
283        int iArgsProcessed = 1;
284        int nScreenNum;
285        int iWidth, iHeight, iX, iY;
286        int iMonitor;
287
288#if CYGDEBUG
289        winDebug("ddxProcessArgument - screen - argc: %d i: %d\n", argc, i);
290#endif
291
292        /* Display the usage message if the argument is malformed */
293        if (i + 1 >= argc) {
294            return 0;
295        }
296
297        /* Grab screen number */
298        nScreenNum = atoi(argv[i + 1]);
299
300        /* Validate the specified screen number */
301        if (nScreenNum < 0) {
302            ErrorF("ddxProcessArgument - screen - Invalid screen number %d\n",
303                   nScreenNum);
304            UseMsg();
305            return 0;
306        }
307
308        /*
309           Initialize default values for any new screens
310
311           Note that default values can't change after a -screen option is
312           seen, so it's safe to do this for each screen as it is introduced
313         */
314        winInitializeScreens(nScreenNum + 1);
315
316        /* look for @m where m is monitor number */
317        if (i + 2 < argc && 1 == sscanf(argv[i + 2], "@%d", (int *) &iMonitor)) {
318            struct GetMonitorInfoData data;
319
320            if (QueryMonitor(iMonitor, &data)) {
321                winErrorFVerb(2,
322                              "ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n",
323                              iMonitor);
324                iArgsProcessed = 3;
325                g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = FALSE;
326                g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
327                g_ScreenInfo[nScreenNum].iMonitor = iMonitor;
328                g_ScreenInfo[nScreenNum].hMonitor = data.monitorHandle;
329                g_ScreenInfo[nScreenNum].dwWidth = data.monitorWidth;
330                g_ScreenInfo[nScreenNum].dwHeight = data.monitorHeight;
331                g_ScreenInfo[nScreenNum].dwUserWidth = data.monitorWidth;
332                g_ScreenInfo[nScreenNum].dwUserHeight = data.monitorHeight;
333                g_ScreenInfo[nScreenNum].dwInitialX = data.monitorOffsetX;
334                g_ScreenInfo[nScreenNum].dwInitialY = data.monitorOffsetY;
335            }
336            else {
337                /* monitor does not exist, error out */
338                ErrorF
339                    ("ddxProcessArgument - screen - Invalid monitor number %d\n",
340                     iMonitor);
341                exit(1);
342                return 0;
343            }
344        }
345
346        /* Look for 'WxD' or 'W D' */
347        else if (i + 2 < argc
348                 && 2 == sscanf(argv[i + 2], "%dx%d",
349                                (int *) &iWidth, (int *) &iHeight)) {
350            winErrorFVerb(2,
351                          "ddxProcessArgument - screen - Found ``WxD'' arg\n");
352            iArgsProcessed = 3;
353            g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = TRUE;
354            g_ScreenInfo[nScreenNum].dwWidth = iWidth;
355            g_ScreenInfo[nScreenNum].dwHeight = iHeight;
356            g_ScreenInfo[nScreenNum].dwUserWidth = iWidth;
357            g_ScreenInfo[nScreenNum].dwUserHeight = iHeight;
358            /* Look for WxD+X+Y */
359            if (2 == sscanf(argv[i + 2], "%*dx%*d+%d+%d",
360                            (int *) &iX, (int *) &iY)) {
361                winErrorFVerb(2,
362                              "ddxProcessArgument - screen - Found ``X+Y'' arg\n");
363                g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
364                g_ScreenInfo[nScreenNum].dwInitialX = iX;
365                g_ScreenInfo[nScreenNum].dwInitialY = iY;
366
367                /* look for WxD+X+Y@m where m is monitor number. take X,Y to be offsets from monitor's root position */
368                if (1 == sscanf(argv[i + 2], "%*dx%*d+%*d+%*d@%d",
369                                (int *) &iMonitor)) {
370                    struct GetMonitorInfoData data;
371
372                    if (QueryMonitor(iMonitor, &data)) {
373                        g_ScreenInfo[nScreenNum].iMonitor = iMonitor;
374                        g_ScreenInfo[nScreenNum].hMonitor = data.monitorHandle;
375                        g_ScreenInfo[nScreenNum].dwInitialX +=
376                            data.monitorOffsetX;
377                        g_ScreenInfo[nScreenNum].dwInitialY +=
378                            data.monitorOffsetY;
379                    }
380                    else {
381                        /* monitor does not exist, error out */
382                        ErrorF
383                            ("ddxProcessArgument - screen - Invalid monitor number %d\n",
384                             iMonitor);
385                        exit(1);
386                        return 0;
387                    }
388                }
389            }
390
391            /* look for WxD@m where m is monitor number */
392            else if (1 == sscanf(argv[i + 2], "%*dx%*d@%d", (int *) &iMonitor)) {
393                struct GetMonitorInfoData data;
394
395                if (QueryMonitor(iMonitor, &data)) {
396                    winErrorFVerb(2,
397                                  "ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n",
398                                  iMonitor);
399                    g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
400                    g_ScreenInfo[nScreenNum].iMonitor = iMonitor;
401                    g_ScreenInfo[nScreenNum].hMonitor = data.monitorHandle;
402                    g_ScreenInfo[nScreenNum].dwInitialX = data.monitorOffsetX;
403                    g_ScreenInfo[nScreenNum].dwInitialY = data.monitorOffsetY;
404                }
405                else {
406                    /* monitor does not exist, error out */
407                    ErrorF
408                        ("ddxProcessArgument - screen - Invalid monitor number %d\n",
409                         iMonitor);
410                    exit(1);
411                    return 0;
412                }
413            }
414        }
415        else if (i + 3 < argc && 1 == sscanf(argv[i + 2], "%d", (int *) &iWidth)
416                 && 1 == sscanf(argv[i + 3], "%d", (int *) &iHeight)) {
417            winErrorFVerb(2,
418                          "ddxProcessArgument - screen - Found ``W D'' arg\n");
419            iArgsProcessed = 4;
420            g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = TRUE;
421            g_ScreenInfo[nScreenNum].dwWidth = iWidth;
422            g_ScreenInfo[nScreenNum].dwHeight = iHeight;
423            g_ScreenInfo[nScreenNum].dwUserWidth = iWidth;
424            g_ScreenInfo[nScreenNum].dwUserHeight = iHeight;
425            if (i + 5 < argc && 1 == sscanf(argv[i + 4], "%d", (int *) &iX)
426                && 1 == sscanf(argv[i + 5], "%d", (int *) &iY)) {
427                winErrorFVerb(2,
428                              "ddxProcessArgument - screen - Found ``X Y'' arg\n");
429                iArgsProcessed = 6;
430                g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
431                g_ScreenInfo[nScreenNum].dwInitialX = iX;
432                g_ScreenInfo[nScreenNum].dwInitialY = iY;
433            }
434        }
435        else {
436            winErrorFVerb(2,
437                          "ddxProcessArgument - screen - Did not find size arg. "
438                          "dwWidth: %d dwHeight: %d\n",
439                          (int) g_ScreenInfo[nScreenNum].dwWidth,
440                          (int) g_ScreenInfo[nScreenNum].dwHeight);
441            iArgsProcessed = 2;
442            g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = FALSE;
443        }
444
445        /* Flag that this screen was explicitly specified by the user */
446        g_ScreenInfo[nScreenNum].fExplicitScreen = TRUE;
447
448        /*
449         * Keep track of the last screen number seen, as parameters seen
450         * before a screen number apply to all screens, whereas parameters
451         * seen after a screen number apply to that screen number only.
452         */
453        iLastScreen = nScreenNum;
454
455        return iArgsProcessed;
456    }
457
458    /*
459     * Is this parameter attached to a screen or global?
460     *
461     * If the parameter is for all screens (appears before
462     * any -screen option), store it in the default screen
463     * info
464     *
465     * If the parameter is for a single screen (appears
466     * after a -screen option), store it in the screen info
467     * for that screen
468     *
469     */
470    if (iLastScreen == -1) {
471        screenInfoPtr = &defaultScreenInfo;
472    }
473    else {
474        screenInfoPtr = &(g_ScreenInfo[iLastScreen]);
475    }
476
477    /*
478     * Look for the '-engine n' argument
479     */
480    if (IS_OPTION("-engine")) {
481        DWORD dwEngine = 0;
482        CARD8 c8OnBits = 0;
483
484        /* Display the usage message if the argument is malformed */
485        if (++i >= argc) {
486            UseMsg();
487            return 0;
488        }
489
490        /* Grab the argument */
491        dwEngine = atoi(argv[i]);
492
493        /* Count the one bits in the engine argument */
494        c8OnBits = winCountBits(dwEngine);
495
496        /* Argument should only have a single bit on */
497        if (c8OnBits != 1) {
498            UseMsg();
499            return 0;
500        }
501
502        screenInfoPtr->dwEnginePreferred = dwEngine;
503
504        /* Indicate that we have processed the argument */
505        return 2;
506    }
507
508    /*
509     * Look for the '-fullscreen' argument
510     */
511    if (IS_OPTION("-fullscreen")) {
512        if (!screenInfoPtr->fMultiMonitorOverride)
513            screenInfoPtr->fMultipleMonitors = FALSE;
514        screenInfoPtr->fFullScreen = TRUE;
515
516        /* Indicate that we have processed this argument */
517        return 1;
518    }
519
520    /*
521     * Look for the '-lesspointer' argument
522     */
523    if (IS_OPTION("-lesspointer")) {
524        screenInfoPtr->fLessPointer = TRUE;
525
526        /* Indicate that we have processed this argument */
527        return 1;
528    }
529
530    /*
531     * Look for the '-nodecoration' argument
532     */
533    if (IS_OPTION("-nodecoration")) {
534        if (!screenInfoPtr->fMultiMonitorOverride)
535            screenInfoPtr->fMultipleMonitors = FALSE;
536        screenInfoPtr->fDecoration = FALSE;
537
538        /* Indicate that we have processed this argument */
539        return 1;
540    }
541
542    /*
543     * Look for the '-rootless' argument
544     */
545    if (IS_OPTION("-rootless")) {
546        if (!screenInfoPtr->fMultiMonitorOverride)
547            screenInfoPtr->fMultipleMonitors = FALSE;
548        screenInfoPtr->fRootless = TRUE;
549
550        /* Indicate that we have processed this argument */
551        return 1;
552    }
553
554    /*
555     * Look for the '-multiwindow' argument
556     */
557    if (IS_OPTION("-multiwindow")) {
558        if (!screenInfoPtr->fMultiMonitorOverride)
559            screenInfoPtr->fMultipleMonitors = TRUE;
560        screenInfoPtr->fMultiWindow = TRUE;
561
562        /* Indicate that we have processed this argument */
563        return 1;
564    }
565
566    /*
567     * Look for the '-compositewm' argument
568     */
569    if (IS_OPTION("-compositewm")) {
570        screenInfoPtr->fCompositeWM = TRUE;
571
572        /* Indicate that we have processed this argument */
573        return 1;
574    }
575    /*
576     * Look for the '-nocompositewm' argument
577     */
578    if (IS_OPTION("-nocompositewm")) {
579        screenInfoPtr->fCompositeWM = FALSE;
580
581        /* Indicate that we have processed this argument */
582        return 1;
583    }
584
585    /*
586     * Look for the '-compositealpha' argument
587     */
588    if (IS_OPTION("-compositealpha")) {
589        g_fCompositeAlpha = TRUE;
590
591        /* Indicate that we have processed this argument */
592        return 1;
593    }
594    /*
595     * Look for the '-nocompositealpha' argument
596     */
597    if (IS_OPTION("-nocompositealpha")) {
598        g_fCompositeAlpha  = FALSE;
599
600        /* Indicate that we have processed this argument */
601        return 1;
602    }
603
604    /*
605     * Look for the '-multiplemonitors' argument
606     */
607    if (IS_OPTION("-multiplemonitors")
608        || IS_OPTION("-multimonitors")) {
609        screenInfoPtr->fMultiMonitorOverride = TRUE;
610        screenInfoPtr->fMultipleMonitors = TRUE;
611
612        /* Indicate that we have processed this argument */
613        return 1;
614    }
615
616    /*
617     * Look for the '-nomultiplemonitors' argument
618     */
619    if (IS_OPTION("-nomultiplemonitors")
620        || IS_OPTION("-nomultimonitors")) {
621        screenInfoPtr->fMultiMonitorOverride = TRUE;
622        screenInfoPtr->fMultipleMonitors = FALSE;
623
624        /* Indicate that we have processed this argument */
625        return 1;
626    }
627
628    /*
629     * Look for the '-scrollbars' argument
630     */
631    if (IS_OPTION("-scrollbars")) {
632
633        screenInfoPtr->iResizeMode = resizeWithScrollbars;
634
635        /* Indicate that we have processed this argument */
636        return 1;
637    }
638
639    /*
640     * Look for the '-resize' argument
641     */
642    if (IS_OPTION("-resize") || IS_OPTION("-noresize") ||
643        (strncmp(argv[i], "-resize=", strlen("-resize=")) == 0)) {
644        winResizeMode mode;
645
646        if (IS_OPTION("-resize"))
647            mode = resizeWithRandr;
648        else if (IS_OPTION("-noresize"))
649            mode = resizeNotAllowed;
650        else if (strncmp(argv[i], "-resize=", strlen("-resize=")) == 0) {
651            char *option = argv[i] + strlen("-resize=");
652
653            if (strcmp(option, "randr") == 0)
654                mode = resizeWithRandr;
655            else if (strcmp(option, "scrollbars") == 0)
656                mode = resizeWithScrollbars;
657            else if (strcmp(option, "none") == 0)
658                mode = resizeNotAllowed;
659            else {
660                ErrorF("ddxProcessArgument - resize - Invalid resize mode %s\n",
661                       option);
662                return 0;
663            }
664        }
665        else {
666            ErrorF("ddxProcessArgument - resize - Invalid resize option %s\n",
667                   argv[i]);
668            return 0;
669        }
670
671        screenInfoPtr->iResizeMode = mode;
672
673        /* Indicate that we have processed this argument */
674        return 1;
675    }
676
677    /*
678     * Look for the '-clipboard' argument
679     */
680    if (IS_OPTION("-clipboard")) {
681        /* Now the default, we still accept the arg for backwards compatibility */
682        g_fClipboard = TRUE;
683
684        /* Indicate that we have processed this argument */
685        return 1;
686    }
687
688    /*
689     * Look for the '-noclipboard' argument
690     */
691    if (IS_OPTION("-noclipboard")) {
692        g_fClipboard = FALSE;
693
694        /* Indicate that we have processed this argument */
695        return 1;
696    }
697
698    /*
699     * Look for the '-primary' argument
700     */
701    if (IS_OPTION("-primary")) {
702        fPrimarySelection = TRUE;
703
704        /* Indicate that we have processed this argument */
705        return 1;
706    }
707
708    /*
709     * Look for the '-noprimary' argument
710     */
711    if (IS_OPTION("-noprimary")) {
712        fPrimarySelection = FALSE;
713
714        /* Indicate that we have processed this argument */
715        return 1;
716    }
717
718    /*
719     * Look for the '-ignoreinput' argument
720     */
721    if (IS_OPTION("-ignoreinput")) {
722        screenInfoPtr->fIgnoreInput = TRUE;
723
724        /* Indicate that we have processed this argument */
725        return 1;
726    }
727
728    /*
729     * Look for the '-emulate3buttons' argument
730     */
731    if (IS_OPTION("-emulate3buttons")) {
732        int iArgsProcessed = 1;
733        int iE3BTimeout = WIN_DEFAULT_E3B_TIME;
734
735        /* Grab the optional timeout value */
736        if (i + 1 < argc && 1 == sscanf(argv[i + 1], "%d", &iE3BTimeout)) {
737            /* Indicate that we have processed the next argument */
738            iArgsProcessed++;
739        }
740        else {
741            /*
742             * sscanf () won't modify iE3BTimeout if it doesn't find
743             * the specified format; however, I want to be explicit
744             * about setting the default timeout in such cases to
745             * prevent some programs (me) from getting confused.
746             */
747            iE3BTimeout = WIN_DEFAULT_E3B_TIME;
748        }
749
750        screenInfoPtr->iE3BTimeout = iE3BTimeout;
751
752        /* Indicate that we have processed this argument */
753        return iArgsProcessed;
754    }
755
756    /*
757     * Look for the '-noemulate3buttons' argument
758     */
759    if (IS_OPTION("-noemulate3buttons")) {
760        screenInfoPtr->iE3BTimeout = WIN_E3B_OFF;
761
762        /* Indicate that we have processed this argument */
763        return 1;
764    }
765
766    /*
767     * Look for the '-depth n' argument
768     */
769    if (IS_OPTION("-depth")) {
770        DWORD dwBPP = 0;
771
772        /* Display the usage message if the argument is malformed */
773        if (++i >= argc) {
774            UseMsg();
775            return 0;
776        }
777
778        /* Grab the argument */
779        dwBPP = atoi(argv[i]);
780
781        screenInfoPtr->dwBPP = dwBPP;
782
783        /* Indicate that we have processed the argument */
784        return 2;
785    }
786
787    /*
788     * Look for the '-refresh n' argument
789     */
790    if (IS_OPTION("-refresh")) {
791        DWORD dwRefreshRate = 0;
792
793        /* Display the usage message if the argument is malformed */
794        if (++i >= argc) {
795            UseMsg();
796            return 0;
797        }
798
799        /* Grab the argument */
800        dwRefreshRate = atoi(argv[i]);
801
802        screenInfoPtr->dwRefreshRate = dwRefreshRate;
803
804        /* Indicate that we have processed the argument */
805        return 2;
806    }
807
808    /*
809     * Look for the '-clipupdates num_boxes' argument
810     */
811    if (IS_OPTION("-clipupdates")) {
812        DWORD dwNumBoxes = 0;
813
814        /* Display the usage message if the argument is malformed */
815        if (++i >= argc) {
816            UseMsg();
817            return 0;
818        }
819
820        /* Grab the argument */
821        dwNumBoxes = atoi(argv[i]);
822
823        screenInfoPtr->dwClipUpdatesNBoxes = dwNumBoxes;
824
825        /* Indicate that we have processed the argument */
826        return 2;
827    }
828
829#ifdef XWIN_EMULATEPSEUDO
830    /*
831     * Look for the '-emulatepseudo' argument
832     */
833    if (IS_OPTION("-emulatepseudo")) {
834        screenInfoPtr->fEmulatePseudo = TRUE;
835
836        /* Indicate that we have processed this argument */
837        return 1;
838    }
839#endif
840
841    /*
842     * Look for the '-nowinkill' argument
843     */
844    if (IS_OPTION("-nowinkill")) {
845        screenInfoPtr->fUseWinKillKey = FALSE;
846
847        /* Indicate that we have processed this argument */
848        return 1;
849    }
850
851    /*
852     * Look for the '-winkill' argument
853     */
854    if (IS_OPTION("-winkill")) {
855        screenInfoPtr->fUseWinKillKey = TRUE;
856
857        /* Indicate that we have processed this argument */
858        return 1;
859    }
860
861    /*
862     * Look for the '-nounixkill' argument
863     */
864    if (IS_OPTION("-nounixkill")) {
865        screenInfoPtr->fUseUnixKillKey = FALSE;
866
867        /* Indicate that we have processed this argument */
868        return 1;
869    }
870
871    /*
872     * Look for the '-unixkill' argument
873     */
874    if (IS_OPTION("-unixkill")) {
875        screenInfoPtr->fUseUnixKillKey = TRUE;
876
877        /* Indicate that we have processed this argument */
878        return 1;
879    }
880
881    /*
882     * Look for the '-notrayicon' argument
883     */
884    if (IS_OPTION("-notrayicon")) {
885        screenInfoPtr->fNoTrayIcon = TRUE;
886
887        /* Indicate that we have processed this argument */
888        return 1;
889    }
890
891    /*
892     * Look for the '-trayicon' argument
893     */
894    if (IS_OPTION("-trayicon")) {
895        screenInfoPtr->fNoTrayIcon = FALSE;
896
897        /* Indicate that we have processed this argument */
898        return 1;
899    }
900
901    /*
902     * Look for the '-fp' argument
903     */
904    if (IS_OPTION("-fp")) {
905        CHECK_ARGS(1);
906        g_cmdline.fontPath = argv[++i];
907        return 0;               /* Let DIX parse this again */
908    }
909
910    /*
911     * Look for the '-query' argument
912     */
913    if (IS_OPTION("-query")) {
914        CHECK_ARGS(1);
915        g_fXdmcpEnabled = TRUE;
916        g_pszQueryHost = argv[++i];
917        return 0;               /* Let DIX parse this again */
918    }
919
920    /*
921     * Look for the '-auth' argument
922     */
923    if (IS_OPTION("-auth")) {
924        g_fAuthEnabled = TRUE;
925        return 0;               /* Let DIX parse this again */
926    }
927
928    /*
929     * Look for the '-indirect' or '-broadcast' arguments
930     */
931    if (IS_OPTION("-indirect")
932        || IS_OPTION("-broadcast")) {
933        g_fXdmcpEnabled = TRUE;
934        return 0;               /* Let DIX parse this again */
935    }
936
937    /*
938     * Look for the '-config' argument
939     */
940    if (IS_OPTION("-config")
941        || IS_OPTION("-xf86config")) {
942        CHECK_ARGS(1);
943#ifdef XWIN_XF86CONFIG
944        g_cmdline.configFile = argv[++i];
945#else
946        winMessageBoxF("The %s option is not supported in this "
947                       "release.\n"
948                       "Ignoring this option and continuing.\n",
949                       MB_ICONINFORMATION, argv[i]);
950#endif
951        return 2;
952    }
953
954    /*
955     * Look for the '-configdir' argument
956     */
957    if (IS_OPTION("-configdir")) {
958        CHECK_ARGS(1);
959#ifdef XWIN_XF86CONFIG
960        g_cmdline.configDir = argv[++i];
961#else
962        winMessageBoxF("The %s option is not supported in this "
963                       "release.\n"
964                       "Ignoring this option and continuing.\n",
965                       MB_ICONINFORMATION, argv[i]);
966#endif
967        return 2;
968    }
969
970    /*
971     * Look for the '-keyboard' argument
972     */
973    if (IS_OPTION("-keyboard")) {
974#ifdef XWIN_XF86CONFIG
975        CHECK_ARGS(1);
976        g_cmdline.keyboard = argv[++i];
977#else
978        winMessageBoxF("The -keyboard option is not supported in this "
979                       "release.\n"
980                       "Ignoring this option and continuing.\n",
981                       MB_ICONINFORMATION);
982#endif
983        return 2;
984    }
985
986    /*
987     * Look for the '-logfile' argument
988     */
989    if (IS_OPTION("-logfile")) {
990        CHECK_ARGS(1);
991        g_pszLogFile = argv[++i];
992#ifdef RELOCATE_PROJECTROOT
993        g_fLogFileChanged = TRUE;
994#endif
995        return 2;
996    }
997
998    /*
999     * Look for the '-logverbose' argument
1000     */
1001    if (IS_OPTION("-logverbose")) {
1002        CHECK_ARGS(1);
1003        g_iLogVerbose = atoi(argv[++i]);
1004        return 2;
1005    }
1006
1007    if (IS_OPTION("-xkbrules")) {
1008        CHECK_ARGS(1);
1009        g_cmdline.xkbRules = argv[++i];
1010        return 2;
1011    }
1012    if (IS_OPTION("-xkbmodel")) {
1013        CHECK_ARGS(1);
1014        g_cmdline.xkbModel = argv[++i];
1015        return 2;
1016    }
1017    if (IS_OPTION("-xkblayout")) {
1018        CHECK_ARGS(1);
1019        g_cmdline.xkbLayout = argv[++i];
1020        return 2;
1021    }
1022    if (IS_OPTION("-xkbvariant")) {
1023        CHECK_ARGS(1);
1024        g_cmdline.xkbVariant = argv[++i];
1025        return 2;
1026    }
1027    if (IS_OPTION("-xkboptions")) {
1028        CHECK_ARGS(1);
1029        g_cmdline.xkbOptions = argv[++i];
1030        return 2;
1031    }
1032
1033    if (IS_OPTION("-keyhook")) {
1034        g_fKeyboardHookLL = TRUE;
1035        return 1;
1036    }
1037
1038    if (IS_OPTION("-nokeyhook")) {
1039        g_fKeyboardHookLL = FALSE;
1040        return 1;
1041    }
1042
1043    if (IS_OPTION("-swcursor")) {
1044        g_fSoftwareCursor = TRUE;
1045        return 1;
1046    }
1047
1048    if (IS_OPTION("-wgl")) {
1049        g_fNativeGl = TRUE;
1050        return 1;
1051    }
1052
1053    if (IS_OPTION("-nowgl")) {
1054        g_fNativeGl = FALSE;
1055        return 1;
1056    }
1057
1058    if (IS_OPTION("-hostintitle")) {
1059        g_fHostInTitle = TRUE;
1060        return 1;
1061    }
1062
1063    if (IS_OPTION("-nohostintitle")) {
1064        g_fHostInTitle = FALSE;
1065        return 1;
1066    }
1067
1068    if (IS_OPTION("-icon")) {
1069        char *iconspec;
1070        CHECK_ARGS(1);
1071        iconspec = argv[++i];
1072        screenInfoPtr->hIcon = LoadImageComma(iconspec, NULL,
1073                                              GetSystemMetrics(SM_CXICON),
1074                                              GetSystemMetrics(SM_CYICON),
1075                                              0);
1076        screenInfoPtr->hIconSm = LoadImageComma(iconspec, NULL,
1077                                                GetSystemMetrics(SM_CXSMICON),
1078                                                GetSystemMetrics(SM_CYSMICON),
1079                                                LR_DEFAULTSIZE);
1080        if ((screenInfoPtr->hIcon == NULL) ||
1081            (screenInfoPtr->hIconSm == NULL)) {
1082            ErrorF("ddxProcessArgument - icon - Invalid icon specification %s\n",
1083                   iconspec);
1084            exit(1);
1085        }
1086
1087        /* Indicate that we have processed the argument */
1088        return 2;
1089    }
1090
1091    return 0;
1092}
1093
1094/*
1095 * winLogCommandLine - Write entire command line to the log file
1096 */
1097
1098void
1099winLogCommandLine(int argc, char *argv[])
1100{
1101    int i;
1102    int iSize = 0;
1103    int iCurrLen = 0;
1104
1105#define CHARS_PER_LINE 60
1106
1107    /* Bail if command line has already been logged */
1108    if (g_pszCommandLine)
1109        return;
1110
1111    /* Count how much memory is needed for concatenated command line */
1112    for (i = 0, iCurrLen = 0; i < argc; ++i)
1113        if (argv[i]) {
1114            /* Adds two characters for lines that overflow */
1115            if ((strlen(argv[i]) < CHARS_PER_LINE
1116                 && iCurrLen + strlen(argv[i]) > CHARS_PER_LINE)
1117                || strlen(argv[i]) > CHARS_PER_LINE) {
1118                iCurrLen = 0;
1119                iSize += 2;
1120            }
1121
1122            /* Add space for item and trailing space */
1123            iSize += strlen(argv[i]) + 1;
1124
1125            /* Update current line length */
1126            iCurrLen += strlen(argv[i]);
1127        }
1128
1129    /* Allocate memory for concatenated command line */
1130    g_pszCommandLine = malloc(iSize + 1);
1131    if (!g_pszCommandLine)
1132        FatalError("winLogCommandLine - Could not allocate memory for "
1133                   "command line string.  Exiting.\n");
1134
1135    /* Set first character to concatenated command line to null */
1136    g_pszCommandLine[0] = '\0';
1137
1138    /* Loop through all args */
1139    for (i = 0, iCurrLen = 0; i < argc; ++i) {
1140        /* Add a character for lines that overflow */
1141        if ((strlen(argv[i]) < CHARS_PER_LINE
1142             && iCurrLen + strlen(argv[i]) > CHARS_PER_LINE)
1143            || strlen(argv[i]) > CHARS_PER_LINE) {
1144            iCurrLen = 0;
1145
1146            /* Add line break if it fits */
1147            strncat(g_pszCommandLine, "\n ", iSize - strlen(g_pszCommandLine));
1148        }
1149
1150        strncat(g_pszCommandLine, argv[i], iSize - strlen(g_pszCommandLine));
1151        strncat(g_pszCommandLine, " ", iSize - strlen(g_pszCommandLine));
1152
1153        /* Save new line length */
1154        iCurrLen += strlen(argv[i]);
1155    }
1156
1157    ErrorF("XWin was started with the following command line:\n\n"
1158           "%s\n\n", g_pszCommandLine);
1159}
1160
1161/*
1162 * winLogVersionInfo - Log version information
1163 */
1164
1165void
1166winLogVersionInfo(void)
1167{
1168    static Bool s_fBeenHere = FALSE;
1169
1170    if (s_fBeenHere)
1171        return;
1172    s_fBeenHere = TRUE;
1173
1174    ErrorF("Welcome to the XWin X Server\n");
1175    ErrorF("Vendor: %s\n", XVENDORNAME);
1176    ErrorF("Release: %d.%d.%d.%d\n", XORG_VERSION_MAJOR,
1177           XORG_VERSION_MINOR, XORG_VERSION_PATCH, XORG_VERSION_SNAP);
1178#ifdef HAVE_SYS_UTSNAME_H
1179    {
1180        struct utsname name;
1181
1182        if (uname(&name) >= 0) {
1183            ErrorF("OS: %s %s %s %s %s\n", name.sysname, name.nodename,
1184                   name.release, name.version, name.machine);
1185        }
1186    }
1187#endif
1188    winOS();
1189    if (strlen(BUILDERSTRING))
1190        ErrorF("%s\n", BUILDERSTRING);
1191    ErrorF("Contact: %s\n", BUILDERADDR);
1192    ErrorF("\n");
1193}
1194