From 60fa71373766537a7fe98305fedbb3f6441c72b1 Mon Sep 17 00:00:00 2001 From: Bo Peng Date: Thu, 27 Jul 2006 16:39:27 +0000 Subject: [PATCH] Update development/Win32/hidecmd.c, from Enrico Forestieri The usage of hidecmd.c is now 'lyx.exe [var=val] [other lyx options]' The realy console lyx.exe should be renamed to lyxc.exe. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@14502 a592a061-630c-0410-9148-cb99ea01b6c8 --- development/Win32/hidecmd.c | 188 +++++++++++++++++++----------------- 1 file changed, 100 insertions(+), 88 deletions(-) diff --git a/development/Win32/hidecmd.c b/development/Win32/hidecmd.c index ad9710ad47..19fcbafbf1 100644 --- a/development/Win32/hidecmd.c +++ b/development/Win32/hidecmd.c @@ -12,39 +12,34 @@ */ /** - * This utility function is used to start lyx under windows, but - * hide the console window. It is adapted from program hidec at + * This is a wrapper program to start lyx under windows hiding its + * console window. It is adapted from program hidec at * http://www.msfn.org/board/index.php?showtopic=49184&mode=threaded * + * This wrapper should be named lyx.exe and placed in the same directory + * as the real lyx executable which _must_ be renamed as lyxc.exe + * * Usage: - * hidecmd [/w] [/VAR=val] [] - * where: /w wait for program termination - * /VAR=val set VAR=val - * executable program - * program parameters + * hidecmd [VAR=val ...] [] + * where: + * VAR=val set VAR=val (multiple settings may be specified) + * parameters for the real lyx executable * - * How to built this program: - * msvc: - * cl.exe hidecmd.c /GA /O1 /link /subsystem:windows \ - * kernel32.lib advapi32.lib user32.lib libcmt.lib - * mingw/gcc: - * gcc -mno-cygwin -mwindows hidecmd.c -o hidecmd + * How to build this program: + * msvc: + * cl.exe hidecmd.c /GA /O1 /Felyx.exe /link /subsystem:windows \ + * kernel32.lib advapi32.lib user32.lib libcmt.lib + * mingw/gcc: + * gcc -mwindows hidecmd.c -o lyx.exe * */ #include #include - -char * usage = "hidecmd [/w] [/VAR=val] []\n" - " where: /w wait for program termination\n" - " /VAR=val set VAR=val\n" - " executable program\n" - " program parameters\n"; - #ifdef _MSC_VER // -// Using msvc, the following progma can reduce executable size from +// Using msvc, the following pragmas can reduce executable size from // 44k to 6k. I am not sure if mingw/gcc can take advantage of them // though. // @@ -64,19 +59,25 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszCmd, int nCmd) { STARTUPINFO si; PROCESS_INFORMATION pi; - int bWait = 0; DWORD exitcode = 0; char delim = ' '; - char var[128]; - char val[128]; + char * var; + char * val; + // two " are needed here: the first one quotes the entire + // command, the second one the executable name + char cmd[1024] = "cmd /c \"\""; + // i0 = strlen(cmd); + int i0 = 9; + int i; int err = 0; + int inquote; char * cmdLine = GetCommandLine(); - int i; - // start and end of variable/value - char * s; - char * e; + // the name of the executable to be launched + // (must be in the same directory) + char * lyxc = "lyxc.exe"; - // use GetCommandLine(), command name is included. Skip it + // When using GetCommandLine(), command name is included + // but the full path may be missing, so skip it. if (*cmdLine == '\"') { delim = '\"'; cmdLine++; @@ -89,95 +90,106 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszCmd, int nCmd) cmdLine++; // skip over ' ' or '\t' - while ((*cmdLine != 0) && ((*cmdLine == ' ') || (*cmdLine == '\t'))) + while (*cmdLine != 0 && (*cmdLine == ' ' || *cmdLine == '\t')) cmdLine++; - while (*cmdLine == '/') { - // /w or /W option - if (((cmdLine[1] == 'w') || (cmdLine[1] == 'W')) && - (cmdLine[2] == ' ')) + // Use GetModuleFileName() to get the path to lyxc.exe + GetModuleFileName(0, cmd + i0, sizeof(cmd) / 2); + + // substitute executable name + for (i = i0; cmd[i] != 0; ++i); + + for (--i; i >= i0 && cmd[i] != '\\' && cmd[i] != '/'; --i); + + for (++i; *lyxc && i < sizeof(cmd); ) + cmd[i++] = *lyxc++; + + // check whether lyxc.exe is there + cmd[i] = '\0'; + lyxc = cmd + i0; + if (GetFileAttributesA(lyxc) == 0xFFFFFFFF) { + exitcode = GetLastError(); + MessageBox(0, lyxc, "Error: cannot find the real LyX executable below", 0); + ExitProcess(exitcode); + } + + // it's there, so finish quoting filename + cmd[i++] = '\"'; + + // parse remainder of command line + while (*cmdLine != 0 && !err) { + if (i < sizeof(cmd)) + cmd[i++] = ' '; + else + err = 1; + + if ((*cmdLine >= 'A' && *cmdLine <= 'Z') || + (*cmdLine >= 'a' && *cmdLine <= 'z')) + var = cmd + i; + else + var = NULL; + + val = NULL; + inquote = 0; + while (!err && ((*cmdLine != 0 && *cmdLine != ' ' && + *cmdLine != '\t') || inquote)) { - bWait = 1; - cmdLine += 3; - // environment variable - } else { - cmdLine++; + if (*cmdLine == '\"') + inquote = 1 - inquote; - // get var - s = var; - e = s + sizeof(var) - 1; - - while (*cmdLine != 0 && *cmdLine != '=') { - if (s < e) { - *s++ = *cmdLine++; - } else { - cmdLine++; - err = 1; - } - } + if (var && *cmdLine == '=' && !inquote) + val = cmd + i; - // get value - *s = 0; - if (*cmdLine == '=') - cmdLine++; + if (i < sizeof(cmd)) + cmd[i++] = *cmdLine; + else + err = 1; - delim = ' '; - - if (*cmdLine == '\"') { - delim = '\"'; - cmdLine++; - } + cmdLine++; + } - s = val; - e = s + sizeof(val) - 1; - - while (*cmdLine != delim && *cmdLine != 0) { - if (s < e) { - *s++ = *cmdLine++; - } else { - cmdLine++; - err = 1; - } + if (var && val && !err) { + *val++ = '\0'; // mark end of var + if (*val == '\"') { // account for quoted val + ++val; + --i; } - *s = 0; - if (*cmdLine == delim) - cmdLine++; - + cmd[i] = '\0'; // mark end of val + i = var - cmd - 1; // reset pointer SetEnvironmentVariable(var, val); // MessageBox(0, val, var, 0); } // skip spaces - while ((*cmdLine != 0) && ((*cmdLine == ' ') || (*cmdLine == '\t'))) + while (*cmdLine != 0 && (*cmdLine == ' ' || *cmdLine == '\t')) cmdLine++; } - // report error if there is no parameter - if (*cmdLine == 0) - { - MessageBox(0, usage, "Error: Incorrect usage", 0); - ExitProcess(0); - } + if (i < sizeof(cmd) - 1) { + // finish quoting the entire command + cmd[i++] = '\"'; + cmd[i] = '\0'; + } else + err = 1; if (err) { - MessageBox(0, "One of the specified environment variables or its value is too long.", "Error: Variable name or value too long", 0); + MessageBox(0, "Please, use a shorter command line.", + "Error: command line is too long", 0); ExitProcess(0); } // create process with new console // memset(&si, 0, sizeof(si)); - s = (char *) &si; + val = (char *) &si; for (i = 0; i < sizeof(si); ++i) - s[i] = 0x00; + val[i] = 0x00; si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; - if (CreateProcess(NULL, cmdLine, + if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { - if (bWait) - WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); } -- 2.39.2