SDL-1.2.14
[sdl_omap.git] / src / main / win32 / SDL_win32_main.c
1 /*
2     SDL_main.c, placed in the public domain by Sam Lantinga  4/13/98
3
4     The WinMain function -- calls your program's main() function
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9
10 #define WIN32_LEAN_AND_MEAN
11 #include <windows.h>
12
13 #ifdef _WIN32_WCE
14 # define DIR_SEPERATOR TEXT("\\")
15 # undef _getcwd
16 # define _getcwd(str,len)       wcscpy(str,TEXT(""))
17 # define setbuf(f,b)
18 # define setvbuf(w,x,y,z)
19 # define fopen          _wfopen
20 # define freopen        _wfreopen
21 # define remove(x)      DeleteFile(x)
22 #else
23 # define DIR_SEPERATOR TEXT("/")
24 # include <direct.h>
25 #endif
26
27 /* Include the SDL main definition header */
28 #include "SDL.h"
29 #include "SDL_main.h"
30
31 #ifdef main
32 # ifndef _WIN32_WCE_EMULATION
33 #  undef main
34 # endif /* _WIN32_WCE_EMULATION */
35 #endif /* main */
36
37 /* The standard output files */
38 #define STDOUT_FILE     TEXT("stdout.txt")
39 #define STDERR_FILE     TEXT("stderr.txt")
40
41 /* Set a variable to tell if the stdio redirect has been enabled. */
42 static int stdioRedirectEnabled = 0;
43
44 #ifdef _WIN32_WCE
45   static wchar_t stdoutPath[MAX_PATH];
46   static wchar_t stderrPath[MAX_PATH];
47 #else
48   static char stdoutPath[MAX_PATH];
49   static char stderrPath[MAX_PATH];
50 #endif
51
52 #if defined(_WIN32_WCE) && _WIN32_WCE < 300
53 /* seems to be undefined in Win CE although in online help */
54 #define isspace(a) (((CHAR)a == ' ') || ((CHAR)a == '\t'))
55 #endif /* _WIN32_WCE < 300 */
56
57 static void UnEscapeQuotes( char *arg )
58 {
59         char *last = NULL;
60
61         while( *arg ) {
62                 if( *arg == '"' && *last == '\\' ) {
63                         char *c_curr = arg;
64                         char *c_last = last;
65
66                         while( *c_curr ) {
67                                 *c_last = *c_curr;
68                                 c_last = c_curr;
69                                 c_curr++;
70                         }
71                         *c_last = '\0';
72                 }
73                 last = arg;
74                 arg++;
75         }
76 }
77
78 /* Parse a command line buffer into arguments */
79 static int ParseCommandLine(char *cmdline, char **argv)
80 {
81         char *bufp;
82         char *lastp = NULL;
83         int argc, last_argc;
84
85         argc = last_argc = 0;
86         for ( bufp = cmdline; *bufp; ) {
87                 /* Skip leading whitespace */
88                 while ( isspace(*bufp) ) {
89                         ++bufp;
90                 }
91                 /* Skip over argument */
92                 if ( *bufp == '"' ) {
93                         ++bufp;
94                         if ( *bufp ) {
95                                 if ( argv ) {
96                                         argv[argc] = bufp;
97                                 }
98                                 ++argc;
99                         }
100                         /* Skip over word */
101                         while ( *bufp && ( *bufp != '"' || *lastp == '\\' ) ) {
102                                 lastp = bufp;
103                                 ++bufp;
104                         }
105                 } else {
106                         if ( *bufp ) {
107                                 if ( argv ) {
108                                         argv[argc] = bufp;
109                                 }
110                                 ++argc;
111                         }
112                         /* Skip over word */
113                         while ( *bufp && ! isspace(*bufp) ) {
114                                 ++bufp;
115                         }
116                 }
117                 if ( *bufp ) {
118                         if ( argv ) {
119                                 *bufp = '\0';
120                         }
121                         ++bufp;
122                 }
123
124                 /* Strip out \ from \" sequences */
125                 if( argv && last_argc != argc ) {
126                         UnEscapeQuotes( argv[last_argc] );      
127                 }
128                 last_argc = argc;       
129         }
130         if ( argv ) {
131                 argv[argc] = NULL;
132         }
133         return(argc);
134 }
135
136 /* Show an error message */
137 static void ShowError(const char *title, const char *message)
138 {
139 /* If USE_MESSAGEBOX is defined, you need to link with user32.lib */
140 #ifdef USE_MESSAGEBOX
141         MessageBox(NULL, message, title, MB_ICONEXCLAMATION|MB_OK);
142 #else
143         fprintf(stderr, "%s: %s\n", title, message);
144 #endif
145 }
146
147 /* Pop up an out of memory message, returns to Windows */
148 static BOOL OutOfMemory(void)
149 {
150         ShowError("Fatal Error", "Out of memory - aborting");
151         return FALSE;
152 }
153
154 /* SDL_Quit() shouldn't be used with atexit() directly because
155    calling conventions may differ... */
156 static void cleanup(void)
157 {
158         SDL_Quit();
159 }
160
161 /* Remove the output files if there was no output written */
162 static void cleanup_output(void) {
163         FILE *file;
164         int empty;
165
166         /* Flush the output in case anything is queued */
167         fclose(stdout);
168         fclose(stderr);
169
170         /* Without redirection we're done */
171         if (!stdioRedirectEnabled) {
172                 return;
173         }
174
175         /* See if the files have any output in them */
176         if ( stdoutPath[0] ) {
177                 file = fopen(stdoutPath, TEXT("rb"));
178                 if ( file ) {
179                         empty = (fgetc(file) == EOF) ? 1 : 0;
180                         fclose(file);
181                         if ( empty ) {
182                                 remove(stdoutPath);
183                         }
184                 }
185         }
186         if ( stderrPath[0] ) {
187                 file = fopen(stderrPath, TEXT("rb"));
188                 if ( file ) {
189                         empty = (fgetc(file) == EOF) ? 1 : 0;
190                         fclose(file);
191                         if ( empty ) {
192                                 remove(stderrPath);
193                         }
194                 }
195         }
196 }
197
198 /* Redirect the output (stdout and stderr) to a file */
199 static void redirect_output(void)
200 {
201         DWORD pathlen;
202 #ifdef _WIN32_WCE
203         wchar_t path[MAX_PATH];
204 #else
205         char path[MAX_PATH];
206 #endif
207         FILE *newfp;
208
209         pathlen = GetModuleFileName(NULL, path, SDL_arraysize(path));
210         while ( pathlen > 0 && path[pathlen] != '\\' ) {
211                 --pathlen;
212         }
213         path[pathlen] = '\0';
214
215 #ifdef _WIN32_WCE
216         wcsncpy( stdoutPath, path, SDL_arraysize(stdoutPath) );
217         wcsncat( stdoutPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) );
218 #else
219         SDL_strlcpy( stdoutPath, path, SDL_arraysize(stdoutPath) );
220         SDL_strlcat( stdoutPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) );
221 #endif
222     
223         /* Redirect standard input and standard output */
224         newfp = freopen(stdoutPath, TEXT("w"), stdout);
225
226 #ifndef _WIN32_WCE
227         if ( newfp == NULL ) {  /* This happens on NT */
228 #if !defined(stdout)
229                 stdout = fopen(stdoutPath, TEXT("w"));
230 #else
231                 newfp = fopen(stdoutPath, TEXT("w"));
232                 if ( newfp ) {
233                         *stdout = *newfp;
234                 }
235 #endif
236         }
237 #endif /* _WIN32_WCE */
238
239 #ifdef _WIN32_WCE
240         wcsncpy( stderrPath, path, SDL_arraysize(stdoutPath) );
241         wcsncat( stderrPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) );
242 #else
243         SDL_strlcpy( stderrPath, path, SDL_arraysize(stderrPath) );
244         SDL_strlcat( stderrPath, DIR_SEPERATOR STDERR_FILE, SDL_arraysize(stderrPath) );
245 #endif
246
247         newfp = freopen(stderrPath, TEXT("w"), stderr);
248 #ifndef _WIN32_WCE
249         if ( newfp == NULL ) {  /* This happens on NT */
250 #if !defined(stderr)
251                 stderr = fopen(stderrPath, TEXT("w"));
252 #else
253                 newfp = fopen(stderrPath, TEXT("w"));
254                 if ( newfp ) {
255                         *stderr = *newfp;
256                 }
257 #endif
258         }
259 #endif /* _WIN32_WCE */
260
261         setvbuf(stdout, NULL, _IOLBF, BUFSIZ);  /* Line buffered */
262         setbuf(stderr, NULL);                   /* No buffering */
263         stdioRedirectEnabled = 1;
264 }
265
266 #if defined(_MSC_VER) && !defined(_WIN32_WCE)
267 /* The VC++ compiler needs main defined */
268 #define console_main main
269 #endif
270
271 /* This is where execution begins [console apps] */
272 int console_main(int argc, char *argv[])
273 {
274         size_t n;
275         char *bufp, *appname;
276         int status;
277
278         /* Get the class name from argv[0] */
279         appname = argv[0];
280         if ( (bufp=SDL_strrchr(argv[0], '\\')) != NULL ) {
281                 appname = bufp+1;
282         } else
283         if ( (bufp=SDL_strrchr(argv[0], '/')) != NULL ) {
284                 appname = bufp+1;
285         }
286
287         if ( (bufp=SDL_strrchr(appname, '.')) == NULL )
288                 n = SDL_strlen(appname);
289         else
290                 n = (bufp-appname);
291
292         bufp = SDL_stack_alloc(char, n+1);
293         if ( bufp == NULL ) {
294                 return OutOfMemory();
295         }
296         SDL_strlcpy(bufp, appname, n+1);
297         appname = bufp;
298
299         /* Load SDL dynamic link library */
300         if ( SDL_Init(SDL_INIT_NOPARACHUTE) < 0 ) {
301                 ShowError("WinMain() error", SDL_GetError());
302                 return(FALSE);
303         }
304         atexit(cleanup_output);
305         atexit(cleanup);
306
307         /* Sam:
308            We still need to pass in the application handle so that
309            DirectInput will initialize properly when SDL_RegisterApp()
310            is called later in the video initialization.
311          */
312         SDL_SetModuleHandle(GetModuleHandle(NULL));
313
314         /* Run the application main() code */
315         status = SDL_main(argc, argv);
316
317         /* Exit cleanly, calling atexit() functions */
318         exit(status);
319
320         /* Hush little compiler, don't you cry... */
321         return 0;
322 }
323
324 /* This is where execution begins [windowed apps] */
325 #ifdef _WIN32_WCE
326 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int sw)
327 #else
328 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
329 #endif
330 {
331         HINSTANCE handle;
332         char **argv;
333         int argc;
334         char *cmdline;
335         char *env_str;
336 #ifdef _WIN32_WCE
337         wchar_t *bufp;
338         int nLen;
339 #else
340         char *bufp;
341         size_t nLen;
342 #endif
343
344         /* Start up DDHELP.EXE before opening any files, so DDHELP doesn't
345            keep them open.  This is a hack.. hopefully it will be fixed 
346            someday.  DDHELP.EXE starts up the first time DDRAW.DLL is loaded.
347          */
348         handle = LoadLibrary(TEXT("DDRAW.DLL"));
349         if ( handle != NULL ) {
350                 FreeLibrary(handle);
351         }
352
353         /* Check for stdio redirect settings and do the redirection */
354         if ((env_str = SDL_getenv("SDL_STDIO_REDIRECT"))) {
355                 if (SDL_atoi(env_str)) {
356                         redirect_output();
357                 }
358         }
359 #ifndef NO_STDIO_REDIRECT
360         else {
361                 redirect_output();
362         }
363 #endif
364
365 #ifdef _WIN32_WCE
366         nLen = wcslen(szCmdLine)+128+1;
367         bufp = SDL_stack_alloc(wchar_t, nLen*2);
368         wcscpy (bufp, TEXT("\""));
369         GetModuleFileName(NULL, bufp+1, 128-3);
370         wcscpy (bufp+wcslen(bufp), TEXT("\" "));
371         wcsncpy(bufp+wcslen(bufp), szCmdLine,nLen-wcslen(bufp));
372         nLen = wcslen(bufp)+1;
373         cmdline = SDL_stack_alloc(char, nLen);
374         if ( cmdline == NULL ) {
375                 return OutOfMemory();
376         }
377         WideCharToMultiByte(CP_ACP, 0, bufp, -1, cmdline, nLen, NULL, NULL);
378 #else
379         /* Grab the command line */
380         bufp = GetCommandLine();
381         nLen = SDL_strlen(bufp)+1;
382         cmdline = SDL_stack_alloc(char, nLen);
383         if ( cmdline == NULL ) {
384                 return OutOfMemory();
385         }
386         SDL_strlcpy(cmdline, bufp, nLen);
387 #endif
388
389         /* Parse it into argv and argc */
390         argc = ParseCommandLine(cmdline, NULL);
391         argv = SDL_stack_alloc(char*, argc+1);
392         if ( argv == NULL ) {
393                 return OutOfMemory();
394         }
395         ParseCommandLine(cmdline, argv);
396
397         /* Run the main program (after a little SDL initialization) */
398         console_main(argc, argv);
399
400         /* Hush little compiler, don't you cry... */
401         return 0;
402 }