lyx_mirror/development/Win32/hidecmd.c

204 lines
5.0 KiB
C
Raw Normal View History

/* -*- C -*- */
/**
* \file hidecmd.c
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author hasherfrog
* \author Bo Peng
* \author Enrico Forestieri
*
* Full author contact details are available in file CREDITS.
*/
/**
* 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 [VAR=val ...] [<params>]
* where:
* VAR=val set VAR=val (multiple settings may be specified)
* <params> parameters for the real lyx executable
*
* 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>
#ifdef _MSC_VER
//
// 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.
//
// do not link to default libraries
#pragma comment(linker,"/NODEFAULTLIB")
// unite code and data section (make the program smaller)
#pragma comment(linker,"/MERGE:.rdata=.text")
// open code section for writing
#pragma comment(linker,"/SECTION:.text,EWR")
// redefine an entry point of the executable
// Must be used, if entry point 'void NewWinMain(void)' is used,
// instead of the standart 'int WINAPI WinMain(HINSTANCE hInst, ...)'
#pragma comment(linker,"/ENTRY:NewWinMain")
void NewWinMain(void)
#else // mingw/gcc uses this entry point
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszCmd, int nCmd)
#endif
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD exitcode = 0;
char delim = ' ';
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();
// the name of the executable to be launched
// (must be in the same directory)
char * lyxc = "lyxc.exe";
// When using GetCommandLine(), command name is included
// but the full path may be missing, so skip it.
if (*cmdLine == '\"') {
delim = '\"';
cmdLine++;
}
while (*cmdLine != delim && *cmdLine != 0)
cmdLine++;
if (*cmdLine == delim)
cmdLine++;
// skip over ' ' or '\t'
while (*cmdLine != 0 && (*cmdLine == ' ' || *cmdLine == '\t'))
cmdLine++;
// 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))
{
if (*cmdLine == '\"')
inquote = 1 - inquote;
if (var && *cmdLine == '=' && !inquote)
val = cmd + i;
if (i < sizeof(cmd))
cmd[i++] = *cmdLine;
else
err = 1;
cmdLine++;
}
if (var && val && !err) {
*val++ = '\0'; // mark end of var
if (*val == '\"') { // account for quoted val
++val;
--i;
}
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'))
cmdLine++;
}
if (i < sizeof(cmd) - 1) {
// finish quoting the entire command
cmd[i++] = '\"';
cmd[i] = '\0';
} else
err = 1;
if (err) {
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));
val = (char *) &si;
for (i = 0; i < sizeof(si); ++i)
val[i] = 0x00;
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
if (CreateProcess(NULL, cmd,
NULL, NULL, FALSE, CREATE_NEW_CONSOLE,
NULL, NULL, &si, &pi))
{
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
else
exitcode = GetLastError();
/* terminate this */
ExitProcess(exitcode);
}