src/main/win32/SDL_main.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 05 Oct 2002 05:44:09 +0000
changeset 505 6b34c9dcf74c
parent 504 8c4a35e3c507
child 545 8406511f850e
permissions -rw-r--r--
*** empty log message ***
     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 <string.h>
     9 #include <ctype.h>
    10 #include <stdlib.h>
    11 
    12 #include <windows.h>
    13 #include <malloc.h>		/* For _alloca() */
    14 
    15 /* Include the SDL main definition header */
    16 #include "SDL.h"
    17 #include "SDL_main.h"
    18 #ifdef main
    19 #ifndef _WIN32_WCE_EMULATION
    20 #undef main
    21 #endif
    22 #endif
    23 
    24 /* Do we really not want stdio redirection with Windows CE? */
    25 #ifdef _WIN32_WCE
    26 #define NO_STDIO_REDIRECT
    27 #endif
    28 
    29 /* The standard output files */
    30 #define STDOUT_FILE	TEXT("stdout.txt")
    31 #define STDERR_FILE	TEXT("stderr.txt")
    32 
    33 #if defined(_WIN32_WCE) && _WIN32_WCE < 300
    34 /* seems to be undefined in Win CE although in online help */
    35 #define isspace(a) (((CHAR)a == ' ') || ((CHAR)a == '\t'))
    36 
    37 /* seems to be undefined in Win CE although in online help */
    38 char *strrchr(char *str, int c)
    39 {
    40 	char *p;
    41 
    42 	/* Skip to the end of the string */
    43 	p=str;
    44 	while (*p)
    45 		p++;
    46 
    47 	/* Look for the given character */
    48 	while ( (p >= str) && (*p != (CHAR)c) )
    49 		p--;
    50 
    51 	/* Return NULL if character not found */
    52 	if ( p < str ) {
    53 		p = NULL;
    54 	}
    55 	return p;
    56 }
    57 #endif /* _WIN32_WCE < 300 */
    58 
    59 /* Parse a command line buffer into arguments */
    60 static int ParseCommandLine(char *cmdline, char **argv)
    61 {
    62 	char *bufp;
    63 	int argc;
    64 
    65 	argc = 0;
    66 	for ( bufp = cmdline; *bufp; ) {
    67 		/* Skip leading whitespace */
    68 		while ( isspace(*bufp) ) {
    69 			++bufp;
    70 		}
    71 		/* Skip over argument */
    72 		if ( *bufp == '"' ) {
    73 			++bufp;
    74 			if ( *bufp ) {
    75 				if ( argv ) {
    76 					argv[argc] = bufp;
    77 				}
    78 				++argc;
    79 			}
    80 			/* Skip over word */
    81 			while ( *bufp && (*bufp != '"') ) {
    82 				++bufp;
    83 			}
    84 		} else {
    85 			if ( *bufp ) {
    86 				if ( argv ) {
    87 					argv[argc] = bufp;
    88 				}
    89 				++argc;
    90 			}
    91 			/* Skip over word */
    92 			while ( *bufp && ! isspace(*bufp) ) {
    93 				++bufp;
    94 			}
    95 		}
    96 		if ( *bufp ) {
    97 			if ( argv ) {
    98 				*bufp = '\0';
    99 			}
   100 			++bufp;
   101 		}
   102 	}
   103 	if ( argv ) {
   104 		argv[argc] = NULL;
   105 	}
   106 	return(argc);
   107 }
   108 
   109 /* Show an error message */
   110 static void ShowError(const char *title, const char *message)
   111 {
   112 /* If USE_MESSAGEBOX is defined, you need to link with user32.lib */
   113 #ifdef USE_MESSAGEBOX
   114 	MessageBox(NULL, message, title, MB_ICONEXCLAMATION|MB_OK);
   115 #else
   116 	fprintf(stderr, "%s: %s\n", title, message);
   117 #endif
   118 }
   119 
   120 /* Pop up an out of memory message, returns to Windows */
   121 static BOOL OutOfMemory(void)
   122 {
   123 	ShowError("Fatal Error", "Out of memory - aborting");
   124 	return FALSE;
   125 }
   126 
   127 /* Remove the output files if there was no output written */
   128 static void __cdecl cleanup_output(void)
   129 {
   130 #ifndef NO_STDIO_REDIRECT
   131 	FILE *file;
   132 	int empty;
   133 #endif
   134 
   135 	/* Flush the output in case anything is queued */
   136 	fclose(stdout);
   137 	fclose(stderr);
   138 
   139 #ifndef NO_STDIO_REDIRECT
   140 	/* See if the files have any output in them */
   141 	file = fopen(STDOUT_FILE, "rb");
   142 	if ( file ) {
   143 		empty = (fgetc(file) == EOF) ? 1 : 0;
   144 		fclose(file);
   145 		if ( empty ) {
   146 			remove(STDOUT_FILE);
   147 		}
   148 	}
   149 	file = fopen(STDERR_FILE, "rb");
   150 	if ( file ) {
   151 		empty = (fgetc(file) == EOF) ? 1 : 0;
   152 		fclose(file);
   153 		if ( empty ) {
   154 			remove(STDERR_FILE);
   155 		}
   156 	}
   157 #endif
   158 }
   159 
   160 #if defined(_MSC_VER) && !defined(_WIN32_WCE)
   161 /* The VC++ compiler needs main defined */
   162 #define console_main main
   163 #endif
   164 
   165 /* This is where execution begins [console apps] */
   166 int console_main(int argc, char *argv[])
   167 {
   168 	int n;
   169 	char *bufp, *appname;
   170 
   171 	/* Get the class name from argv[0] */
   172 	appname = argv[0];
   173 	if ( (bufp=strrchr(argv[0], '\\')) != NULL ) {
   174 		appname = bufp+1;
   175 	} else
   176 	if ( (bufp=strrchr(argv[0], '/')) != NULL ) {
   177 		appname = bufp+1;
   178 	}
   179 
   180 	if ( (bufp=strrchr(appname, '.')) == NULL )
   181 		n = strlen(appname);
   182 	else
   183 		n = (bufp-appname);
   184 
   185 	bufp = (char *)alloca(n+1);
   186 	if ( bufp == NULL ) {
   187 		return OutOfMemory();
   188 	}
   189 	strncpy(bufp, appname, n);
   190 	bufp[n] = '\0';
   191 	appname = bufp;
   192 
   193 	/* Load SDL dynamic link library */
   194 	if ( SDL_Init(SDL_INIT_NOPARACHUTE) < 0 ) {
   195 		ShowError("WinMain() error", SDL_GetError());
   196 		return(FALSE);
   197 	}
   198 	atexit(cleanup_output);
   199 	atexit(SDL_Quit);
   200 
   201 #ifndef DISABLE_VIDEO
   202 #if 0
   203 	/* Create and register our class *
   204 	   DJM: If we do this here, the user nevers gets a chance to
   205 	   putenv(SDL_WINDOWID).  This is already called later by
   206 	   the (DIB|DX5)_CreateWindow function, so it should be
   207 	   safe to comment it out here.
   208 	if ( SDL_RegisterApp(appname, CS_BYTEALIGNCLIENT, 
   209 	                     GetModuleHandle(NULL)) < 0 ) {
   210 		ShowError("WinMain() error", SDL_GetError());
   211 		exit(1);
   212 	}*/
   213 #else
   214 	/* Sam:
   215 	   We still need to pass in the application handle so that
   216 	   DirectInput will initialize properly when SDL_RegisterApp()
   217 	   is called later in the video initialization.
   218 	 */
   219 	SDL_SetModuleHandle(GetModuleHandle(NULL));
   220 #endif /* 0 */
   221 #endif /* !DISABLE_VIDEO */
   222 
   223 	/* Run the application main() code */
   224 	SDL_main(argc, argv);
   225 
   226 	/* Exit cleanly, calling atexit() functions */
   227 	exit(0);
   228 
   229 	/* Hush little compiler, don't you cry... */
   230 	return(0);
   231 }
   232 
   233 /* This is where execution begins [windowed apps] */
   234 #ifdef _WIN32_WCE
   235 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int sw)
   236 #else
   237 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
   238 #endif
   239 {
   240 	HINSTANCE handle;
   241 	char **argv;
   242 	int argc;
   243 	char *cmdline;
   244 #ifdef _WIN32_WCE
   245 	wchar_t *bufp;
   246 	int nLen;
   247 #else
   248 	char *bufp;
   249 #endif
   250 #ifndef NO_STDIO_REDIRECT
   251 	FILE *newfp;
   252 #endif
   253 
   254 	/* Start up DDHELP.EXE before opening any files, so DDHELP doesn't
   255 	   keep them open.  This is a hack.. hopefully it will be fixed 
   256 	   someday.  DDHELP.EXE starts up the first time DDRAW.DLL is loaded.
   257 	 */
   258 	handle = LoadLibrary(TEXT("DDRAW.DLL"));
   259 	if ( handle != NULL ) {
   260 		FreeLibrary(handle);
   261 	}
   262 
   263 #ifndef NO_STDIO_REDIRECT
   264 	/* Redirect standard input and standard output */
   265 	newfp = freopen(STDOUT_FILE, "w", stdout);
   266 	if ( newfp == NULL ) {	/* This happens on NT */
   267 #if !defined(stdout)
   268 		stdout = fopen(STDOUT_FILE, "w");
   269 #else
   270 		newfp = fopen(STDOUT_FILE, "w");
   271 		if ( newfp ) {
   272 			*stdout = *newfp;
   273 		}
   274 #endif
   275 	}
   276 	newfp = freopen(STDERR_FILE, "w", stderr);
   277 	if ( newfp == NULL ) {	/* This happens on NT */
   278 #if !defined(stderr)
   279 		stderr = fopen(STDERR_FILE, "w");
   280 #else
   281 		newfp = fopen(STDERR_FILE, "w");
   282 		if ( newfp ) {
   283 			*stderr = *newfp;
   284 		}
   285 #endif
   286 	}
   287 	setvbuf(stdout, NULL, _IOLBF, BUFSIZ);	/* Line buffered */
   288 	setbuf(stderr, NULL);			/* No buffering */
   289 #endif /* !NO_STDIO_REDIRECT */
   290 
   291 #ifdef _WIN32_WCE
   292 	nLen = wcslen(szCmdLine)+128+1;
   293 	bufp = (wchar_t *)alloca(nLen*2);
   294 	wcscpy (bufp, TEXT("\""));
   295 	GetModuleFileName(NULL, bufp+1, 128-3);
   296 	wcscpy (bufp+wcslen(bufp), TEXT("\" "));
   297 	wcsncpy(bufp+wcslen(bufp), szCmdLine,nLen-wcslen(bufp));
   298 	nLen = wcslen(bufp)+1;
   299 	cmdline = (char *)alloca(nLen);
   300 	if ( cmdline == NULL ) {
   301 		return OutOfMemory();
   302 	}
   303 	WideCharToMultiByte(CP_ACP, 0, bufp, -1, cmdline, nLen, NULL, NULL);
   304 #else
   305 	/* Grab the command line (use alloca() on Windows) */
   306 	bufp = GetCommandLine();
   307 	cmdline = (char *)alloca(strlen(bufp)+1);
   308 	if ( cmdline == NULL ) {
   309 		return OutOfMemory();
   310 	}
   311 	strcpy(cmdline, bufp);
   312 #endif
   313 
   314 	/* Parse it into argv and argc */
   315 	argc = ParseCommandLine(cmdline, NULL);
   316 	argv = (char **)alloca((argc+1)*(sizeof *argv));
   317 	if ( argv == NULL ) {
   318 		return OutOfMemory();
   319 	}
   320 	ParseCommandLine(cmdline, argv);
   321 
   322 	/* Run the main program (after a little SDL initialization) */
   323 	return(console_main(argc, argv));
   324 }