*/
/**
- * 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] <filename> [<params>]
- * where: /w wait for program termination
- * /VAR=val set VAR=val
- * <filename> executable program
- * <params> program parameters
+ * hidecmd [VAR=val ...] [<params>]
+ * where:
+ * VAR=val set VAR=val (multiple settings may be specified)
+ * <params> 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 <process.h>
#include <windows.h>
-
-char * usage = "hidecmd [/w] [/VAR=val] <filename> [<params>]\n"
- " where: /w wait for program termination\n"
- " /VAR=val set VAR=val\n"
- " <filename> executable program\n"
- " <params> 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.
//
{
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++;
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 );
}