]> git.lyx.org Git - lyx.git/blob - development/Win32/hidecmd.c
Add development/Win32/hidecmd.c, which hides windows console window when starting lyx
[lyx.git] / development / Win32 / hidecmd.c
1 /* -*- C -*- */
2 /**
3  * \file hidecmd.c
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author hasherfrog
8  * \author Bo Peng
9  * \author Enrico Forestieri
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 /**
15  *  This utility function is used to start lyx under windows, but
16  *  hide the console window. It is adapted from program hidec at
17  *  http://www.msfn.org/board/index.php?showtopic=49184&mode=threaded
18  *
19  *  Usage: 
20  *      hidecmd [/w] [/VAR=val] <filename> [<params>]
21  *  where: /w            wait for program termination
22  *              /VAR=val        set VAR=val
23  *              <filename>  executable program
24  *              <params>        program parameters
25  *
26  *  How to built this program:
27  *  msvc:
28  *      cl.exe hidecmd.c /GA /O1 /link /subsystem:windows \
29  *         kernel32.lib advapi32.lib user32.lib libcmt.lib
30  *  mingw/gcc:
31  *      gcc -mno-cygwin -mwindows hidecmd.c -o hidecmd
32  *
33  */
34
35 #include <process.h>
36 #include <windows.h>
37
38
39 char * usage = "hidecmd [/w] [/VAR=val] <filename> [<params>]\n"
40         "  where: /w             wait for program termination\n"
41         "               /VAR=val        set VAR=val\n"
42         "               <filename>  executable program\n"
43         "               <params>        program parameters\n";
44
45 #ifdef _MSC_VER
46 //
47 // Using msvc, the following progma can reduce executable size from
48 // 44k to 6k. I am not sure if mingw/gcc can take advantage of them
49 // though.
50 //
51 // do not link to default libraries
52 #pragma comment(linker,"/NODEFAULTLIB")
53 // unite code and data section (make the program smaller)
54 #pragma comment(linker,"/MERGE:.rdata=.text")
55 // resolve record in section of code
56 #pragma comment(linker,"/SECTION:.text,EWR")
57 // the new entry point (the WinMain entry point is big)
58 #pragma comment(linker,"/ENTRY:NewWinMain")
59
60 void NewWinMain(void)
61 #else  // mingw/gcc uses this entry point
62 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszCmd, int nCmd)
63 #endif
64 {
65         STARTUPINFO si;
66         PROCESS_INFORMATION pi;
67         int bWait = 0;
68         DWORD exitcode = 0;
69         char delim = ' ';
70         char var[128];
71         char val[128];
72         int err = 0;
73         char * cmdLine = GetCommandLine();
74         int i;
75         // start and end of variable/value
76         char * s;
77         char * e;
78
79         // use GetCommandLine(), command name is included. Skip it
80         if (*cmdLine == '\"') {
81                 delim = '\"';
82                 cmdLine++;
83         }
84
85         while (*cmdLine != delim && *cmdLine != 0)
86                 cmdLine++;
87
88         if (*cmdLine == delim)
89                 cmdLine++;
90
91         // skip over ' ' or '\t'
92         while ((*cmdLine != 0) && ((*cmdLine == ' ') || (*cmdLine == '\t')))
93                 cmdLine++; 
94
95         while (*cmdLine == '/') {
96                 // /w or /W option
97                 if (((cmdLine[1] == 'w') || (cmdLine[1] == 'W')) &&
98                         (cmdLine[2] == ' '))
99                 {
100                         bWait = 1;
101                         cmdLine += 3;
102                 // environment variable
103                 } else {
104                         cmdLine++;
105
106                         // get var
107                         s = var;
108                         e = s + sizeof(var) - 1;
109                         
110                         while (*cmdLine != 0 && *cmdLine != '=') {
111                                 if (s < e) {
112                                         *s++ = *cmdLine++;
113                                 } else {
114                                         cmdLine++;
115                                         err = 1;
116                                 }
117                         }
118
119                         // get value
120                         *s = 0;
121                         if (*cmdLine == '=')
122                                 cmdLine++;
123
124                         delim = ' ';
125                         
126                         if (*cmdLine == '\"') {
127                                 delim = '\"';
128                                 cmdLine++;
129                         }
130
131                         s = val;
132                         e = s + sizeof(val) - 1;
133                         
134                         while (*cmdLine != delim && *cmdLine != 0) {
135                                 if (s < e) {
136                                         *s++ = *cmdLine++;
137                                 } else {
138                                         cmdLine++;
139                                         err = 1;
140                                 }
141                         }
142                         *s = 0;
143                         if (*cmdLine == delim)
144                                 cmdLine++;
145
146                         SetEnvironmentVariable(var, val);
147                         // MessageBox(0, val, var, 0);
148                 }
149
150                 // skip spaces
151                 while ((*cmdLine != 0) && ((*cmdLine == ' ') || (*cmdLine == '\t'))) 
152                         cmdLine++;
153         }
154
155         // report error if there is no parameter 
156         if (*cmdLine == 0)
157         {
158                 MessageBox(0, usage, "Error: Incorrect usage", 0);
159                 ExitProcess(0);
160         }
161         
162         if (err) {
163                 MessageBox(0, "One of the specified environment variables or its value is too long.", "Error: Variable name or value too long", 0);
164                 ExitProcess(0);
165         }
166
167         // create process with new console
168         // memset(&si, 0, sizeof(si));
169         s = (char *) &si;
170         for (i = 0; i < sizeof(si); ++i)
171                 s[i] = 0x00;
172         si.cb = sizeof(si);
173         si.dwFlags = STARTF_USESHOWWINDOW;
174         si.wShowWindow = SW_HIDE;
175         if (CreateProcess(NULL, cmdLine,
176                 NULL, NULL, FALSE, CREATE_NEW_CONSOLE,
177                 NULL, NULL, &si, &pi))
178         {
179                 if (bWait) 
180                         WaitForSingleObject(pi.hProcess, INFINITE);
181                 CloseHandle( pi.hProcess );
182                 CloseHandle( pi.hThread );
183         }
184         else
185                 exitcode = GetLastError();
186
187         /* terminate this */
188         ExitProcess(exitcode);
189 }