summaryrefslogtreecommitdiffstats
path: root/apps/plugins/sdl/src/main/macos/SDL_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/src/main/macos/SDL_main.c')
-rw-r--r--apps/plugins/sdl/src/main/macos/SDL_main.c610
1 files changed, 610 insertions, 0 deletions
diff --git a/apps/plugins/sdl/src/main/macos/SDL_main.c b/apps/plugins/sdl/src/main/macos/SDL_main.c
new file mode 100644
index 0000000000..ff1ffdca0d
--- /dev/null
+++ b/apps/plugins/sdl/src/main/macos/SDL_main.c
@@ -0,0 +1,610 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+
+/* This file takes care of command line argument parsing, and stdio redirection
+ in the MacOS environment. (stdio/stderr is *not* directed for Mach-O builds)
+ */
+
+#if defined(__APPLE__) && defined(__MACH__)
+#include <Carbon/Carbon.h>
+#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335)
+#include <Carbon.h>
+#else
+#include <Dialogs.h>
+#include <Fonts.h>
+#include <Events.h>
+#include <Resources.h>
+#include <Folders.h>
+#endif
+
+/* Include the SDL main definition header */
+#include "SDL.h"
+#include "SDL_main.h"
+#ifdef main
+#undef main
+#endif
+
+#if !(defined(__APPLE__) && defined(__MACH__))
+/* The standard output files */
+#define STDOUT_FILE "stdout.txt"
+#define STDERR_FILE "stderr.txt"
+#endif
+
+#if !defined(__MWERKS__) && !TARGET_API_MAC_CARBON
+ /* In MPW, the qd global has been removed from the libraries */
+ QDGlobals qd;
+#endif
+
+/* Structure for keeping prefs in 1 variable */
+typedef struct {
+ Str255 command_line;
+ Str255 video_driver_name;
+ Boolean output_to_file;
+} PrefsRecord;
+
+/* See if the command key is held down at startup */
+static Boolean CommandKeyIsDown(void)
+{
+ KeyMap theKeyMap;
+
+ GetKeys(theKeyMap);
+
+ if (((unsigned char *) theKeyMap)[6] & 0x80) {
+ return(true);
+ }
+ return(false);
+}
+
+#if !(defined(__APPLE__) && defined(__MACH__))
+
+/* Parse a command line buffer into arguments */
+static int ParseCommandLine(char *cmdline, char **argv)
+{
+ char *bufp;
+ int argc;
+
+ argc = 0;
+ for ( bufp = cmdline; *bufp; ) {
+ /* Skip leading whitespace */
+ while ( SDL_isspace(*bufp) ) {
+ ++bufp;
+ }
+ /* Skip over argument */
+ if ( *bufp == '"' ) {
+ ++bufp;
+ if ( *bufp ) {
+ if ( argv ) {
+ argv[argc] = bufp;
+ }
+ ++argc;
+ }
+ /* Skip over word */
+ while ( *bufp && (*bufp != '"') ) {
+ ++bufp;
+ }
+ } else {
+ if ( *bufp ) {
+ if ( argv ) {
+ argv[argc] = bufp;
+ }
+ ++argc;
+ }
+ /* Skip over word */
+ while ( *bufp && ! SDL_isspace(*bufp) ) {
+ ++bufp;
+ }
+ }
+ if ( *bufp ) {
+ if ( argv ) {
+ *bufp = '\0';
+ }
+ ++bufp;
+ }
+ }
+ if ( argv ) {
+ argv[argc] = NULL;
+ }
+ return(argc);
+}
+
+/* Remove the output files if there was no output written */
+static void cleanup_output(void)
+{
+ FILE *file;
+ int empty;
+
+ /* Flush the output in case anything is queued */
+ fclose(stdout);
+ fclose(stderr);
+
+ /* See if the files have any output in them */
+ file = fopen(STDOUT_FILE, "rb");
+ if ( file ) {
+ empty = (fgetc(file) == EOF) ? 1 : 0;
+ fclose(file);
+ if ( empty ) {
+ remove(STDOUT_FILE);
+ }
+ }
+ file = fopen(STDERR_FILE, "rb");
+ if ( file ) {
+ empty = (fgetc(file) == EOF) ? 1 : 0;
+ fclose(file);
+ if ( empty ) {
+ remove(STDERR_FILE);
+ }
+ }
+}
+
+#endif //!(defined(__APPLE__) && defined(__MACH__))
+
+static int getCurrentAppName (StrFileName name) {
+
+ ProcessSerialNumber process;
+ ProcessInfoRec process_info;
+ FSSpec process_fsp;
+
+ process.highLongOfPSN = 0;
+ process.lowLongOfPSN = kCurrentProcess;
+ process_info.processInfoLength = sizeof (process_info);
+ process_info.processName = NULL;
+ process_info.processAppSpec = &process_fsp;
+
+ if ( noErr != GetProcessInformation (&process, &process_info) )
+ return 0;
+
+ SDL_memcpy(name, process_fsp.name, process_fsp.name[0] + 1);
+ return 1;
+}
+
+static int getPrefsFile (FSSpec *prefs_fsp, int create) {
+
+ /* The prefs file name is the application name, possibly truncated, */
+ /* plus " Preferences */
+
+ #define SUFFIX " Preferences"
+ #define MAX_NAME 19 /* 31 - strlen (SUFFIX) */
+
+ short volume_ref_number;
+ long directory_id;
+ StrFileName prefs_name;
+ StrFileName app_name;
+
+ /* Get Preferences folder - works with Multiple Users */
+ if ( noErr != FindFolder ( kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder,
+ &volume_ref_number, &directory_id) )
+ exit (-1);
+
+ if ( ! getCurrentAppName (app_name) )
+ exit (-1);
+
+ /* Truncate if name is too long */
+ if (app_name[0] > MAX_NAME )
+ app_name[0] = MAX_NAME;
+
+ SDL_memcpy(prefs_name + 1, app_name + 1, app_name[0]);
+ SDL_memcpy(prefs_name + app_name[0] + 1, SUFFIX, strlen (SUFFIX));
+ prefs_name[0] = app_name[0] + strlen (SUFFIX);
+
+ /* Make the file spec for prefs file */
+ if ( noErr != FSMakeFSSpec (volume_ref_number, directory_id, prefs_name, prefs_fsp) ) {
+ if ( !create )
+ return 0;
+ else {
+ /* Create the prefs file */
+ SDL_memcpy(prefs_fsp->name, prefs_name, prefs_name[0] + 1);
+ prefs_fsp->parID = directory_id;
+ prefs_fsp->vRefNum = volume_ref_number;
+
+ FSpCreateResFile (prefs_fsp, 0x3f3f3f3f, 'pref', 0); // '????' parsed as trigraph
+
+ if ( noErr != ResError () )
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int readPrefsResource (PrefsRecord *prefs) {
+
+ Handle prefs_handle;
+
+ prefs_handle = Get1Resource( 'CLne', 128 );
+
+ if (prefs_handle != NULL) {
+ int offset = 0;
+// int j = 0;
+
+ HLock(prefs_handle);
+
+ /* Get command line string */
+ SDL_memcpy(prefs->command_line, *prefs_handle, (*prefs_handle)[0]+1);
+
+ /* Get video driver name */
+ offset += (*prefs_handle)[0] + 1;
+ SDL_memcpy(prefs->video_driver_name, *prefs_handle + offset, (*prefs_handle)[offset] + 1);
+
+ /* Get save-to-file option (1 or 0) */
+ offset += (*prefs_handle)[offset] + 1;
+ prefs->output_to_file = (*prefs_handle)[offset];
+
+ ReleaseResource( prefs_handle );
+
+ return ResError() == noErr;
+ }
+
+ return 0;
+}
+
+static int writePrefsResource (PrefsRecord *prefs, short resource_file) {
+
+ Handle prefs_handle;
+
+ UseResFile (resource_file);
+
+ prefs_handle = Get1Resource ( 'CLne', 128 );
+ if (prefs_handle != NULL)
+ RemoveResource (prefs_handle);
+
+ prefs_handle = NewHandle ( prefs->command_line[0] + prefs->video_driver_name[0] + 4 );
+ if (prefs_handle != NULL) {
+
+ int offset;
+
+ HLock (prefs_handle);
+
+ /* Command line text */
+ offset = 0;
+ SDL_memcpy(*prefs_handle, prefs->command_line, prefs->command_line[0] + 1);
+
+ /* Video driver name */
+ offset += prefs->command_line[0] + 1;
+ SDL_memcpy(*prefs_handle + offset, prefs->video_driver_name, prefs->video_driver_name[0] + 1);
+
+ /* Output-to-file option */
+ offset += prefs->video_driver_name[0] + 1;
+ *( *((char**)prefs_handle) + offset) = (char)prefs->output_to_file;
+ *( *((char**)prefs_handle) + offset + 1) = 0;
+
+ AddResource (prefs_handle, 'CLne', 128, "\pCommand Line");
+ WriteResource (prefs_handle);
+ UpdateResFile (resource_file);
+ DisposeHandle (prefs_handle);
+
+ return ResError() == noErr;
+ }
+
+ return 0;
+}
+
+static int readPreferences (PrefsRecord *prefs) {
+
+ int no_error = 1;
+ FSSpec prefs_fsp;
+
+ /* Check for prefs file first */
+ if ( getPrefsFile (&prefs_fsp, 0) ) {
+
+ short prefs_resource;
+
+ prefs_resource = FSpOpenResFile (&prefs_fsp, fsRdPerm);
+ if ( prefs_resource == -1 ) /* this shouldn't happen, but... */
+ return 0;
+
+ UseResFile (prefs_resource);
+ no_error = readPrefsResource (prefs);
+ CloseResFile (prefs_resource);
+ }
+
+ /* Fall back to application's resource fork (reading only, so this is safe) */
+ else {
+
+ no_error = readPrefsResource (prefs);
+ }
+
+ return no_error;
+}
+
+static int writePreferences (PrefsRecord *prefs) {
+
+ int no_error = 1;
+ FSSpec prefs_fsp;
+
+ /* Get prefs file, create if it doesn't exist */
+ if ( getPrefsFile (&prefs_fsp, 1) ) {
+
+ short prefs_resource;
+
+ prefs_resource = FSpOpenResFile (&prefs_fsp, fsRdWrPerm);
+ if (prefs_resource == -1)
+ return 0;
+ no_error = writePrefsResource (prefs, prefs_resource);
+ CloseResFile (prefs_resource);
+ }
+
+ return no_error;
+}
+
+/* This is where execution begins */
+int main(int argc, char *argv[])
+{
+
+#if !(defined(__APPLE__) && defined(__MACH__))
+#pragma unused(argc, argv)
+#endif
+
+#define DEFAULT_ARGS "\p" /* pascal string for default args */
+#define DEFAULT_VIDEO_DRIVER "\ptoolbox" /* pascal string for default video driver name */
+#define DEFAULT_OUTPUT_TO_FILE 1 /* 1 == output to file, 0 == no output */
+
+#define VIDEO_ID_DRAWSPROCKET 1 /* these correspond to popup menu choices */
+#define VIDEO_ID_TOOLBOX 2
+
+ PrefsRecord prefs = { DEFAULT_ARGS, DEFAULT_VIDEO_DRIVER, DEFAULT_OUTPUT_TO_FILE };
+
+#if !(defined(__APPLE__) && defined(__MACH__))
+ int nargs;
+ char **args;
+ char *commandLine;
+
+ StrFileName appNameText;
+#endif
+ int videodriver = VIDEO_ID_TOOLBOX;
+ int settingsChanged = 0;
+
+ long i;
+
+ /* Kyle's SDL command-line dialog code ... */
+#if !TARGET_API_MAC_CARBON
+ InitGraf (&qd.thePort);
+ InitFonts ();
+ InitWindows ();
+ InitMenus ();
+ InitDialogs (nil);
+#endif
+ InitCursor ();
+ FlushEvents(everyEvent,0);
+#if !TARGET_API_MAC_CARBON
+ MaxApplZone ();
+#endif
+ MoreMasters ();
+ MoreMasters ();
+#if 0
+ /* Intialize SDL, and put up a dialog if we fail */
+ if ( SDL_Init (0) < 0 ) {
+
+#define kErr_OK 1
+#define kErr_Text 2
+
+ DialogPtr errorDialog;
+ short dummyType;
+ Rect dummyRect;
+ Handle dummyHandle;
+ short itemHit;
+
+ errorDialog = GetNewDialog (1001, nil, (WindowPtr)-1);
+ if (errorDialog == NULL)
+ return -1;
+ DrawDialog (errorDialog);
+
+ GetDialogItem (errorDialog, kErr_Text, &dummyType, &dummyHandle, &dummyRect);
+ SetDialogItemText (dummyHandle, "\pError Initializing SDL");
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetDialogPort(errorDialog));
+#else
+ SetPort (errorDialog);
+#endif
+ do {
+ ModalDialog (nil, &itemHit);
+ } while (itemHit != kErr_OK);
+
+ DisposeDialog (errorDialog);
+ exit (-1);
+ }
+ atexit(cleanup_output);
+ atexit(SDL_Quit);
+#endif
+
+/* Set up SDL's QuickDraw environment */
+#if !TARGET_API_MAC_CARBON
+ SDL_InitQuickDraw(&qd);
+#endif
+
+ if ( readPreferences (&prefs) ) {
+
+ if (SDL_memcmp(prefs.video_driver_name+1, "DSp", 3) == 0)
+ videodriver = 1;
+ else if (SDL_memcmp(prefs.video_driver_name+1, "toolbox", 7) == 0)
+ videodriver = 2;
+ }
+
+ if ( CommandKeyIsDown() ) {
+
+#define kCL_OK 1
+#define kCL_Cancel 2
+#define kCL_Text 3
+#define kCL_File 4
+#define kCL_Video 6
+
+ DialogPtr commandDialog;
+ short dummyType;
+ Rect dummyRect;
+ Handle dummyHandle;
+ short itemHit;
+ #if TARGET_API_MAC_CARBON
+ ControlRef control;
+ #endif
+
+ /* Assume that they will change settings, rather than do exhaustive check */
+ settingsChanged = 1;
+
+ /* Create dialog and display it */
+ commandDialog = GetNewDialog (1000, nil, (WindowPtr)-1);
+ #if TARGET_API_MAC_CARBON
+ SetPort ( GetDialogPort(commandDialog) );
+ #else
+ SetPort (commandDialog);
+ #endif
+
+ /* Setup controls */
+ #if TARGET_API_MAC_CARBON
+ GetDialogItemAsControl(commandDialog, kCL_File, &control);
+ SetControlValue (control, prefs.output_to_file);
+ #else
+ GetDialogItem (commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */
+ SetControlValue ((ControlHandle)dummyHandle, prefs.output_to_file );
+ #endif
+
+ GetDialogItem (commandDialog, kCL_Text, &dummyType, &dummyHandle, &dummyRect);
+ SetDialogItemText (dummyHandle, prefs.command_line);
+
+ #if TARGET_API_MAC_CARBON
+ GetDialogItemAsControl(commandDialog, kCL_Video, &control);
+ SetControlValue (control, videodriver);
+ #else
+ GetDialogItem (commandDialog, kCL_Video, &dummyType, &dummyHandle, &dummyRect);
+ SetControlValue ((ControlRef)dummyHandle, videodriver);
+ #endif
+
+ SetDialogDefaultItem (commandDialog, kCL_OK);
+ SetDialogCancelItem (commandDialog, kCL_Cancel);
+
+ do {
+
+ ModalDialog(nil, &itemHit); /* wait for user response */
+
+ /* Toggle command-line output checkbox */
+ if ( itemHit == kCL_File ) {
+ #if TARGET_API_MAC_CARBON
+ GetDialogItemAsControl(commandDialog, kCL_File, &control);
+ SetControlValue (control, !GetControlValue(control));
+ #else
+ GetDialogItem(commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */
+ SetControlValue((ControlHandle)dummyHandle, !GetControlValue((ControlHandle)dummyHandle) );
+ #endif
+ }
+
+ } while (itemHit != kCL_OK && itemHit != kCL_Cancel);
+
+ /* Get control values, even if they did not change */
+ GetDialogItem (commandDialog, kCL_Text, &dummyType, &dummyHandle, &dummyRect); /* MJS */
+ GetDialogItemText (dummyHandle, prefs.command_line);
+
+ #if TARGET_API_MAC_CARBON
+ GetDialogItemAsControl(commandDialog, kCL_File, &control);
+ prefs.output_to_file = GetControlValue(control);
+ #else
+ GetDialogItem (commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */
+ prefs.output_to_file = GetControlValue ((ControlHandle)dummyHandle);
+ #endif
+
+ #if TARGET_API_MAC_CARBON
+ GetDialogItemAsControl(commandDialog, kCL_Video, &control);
+ videodriver = GetControlValue(control);
+ #else
+ GetDialogItem (commandDialog, kCL_Video, &dummyType, &dummyHandle, &dummyRect);
+ videodriver = GetControlValue ((ControlRef)dummyHandle);
+ #endif
+
+ DisposeDialog (commandDialog);
+
+ if (itemHit == kCL_Cancel ) {
+ exit (0);
+ }
+ }
+
+ /* Set pseudo-environment variables for video driver, update prefs */
+ switch ( videodriver ) {
+ case VIDEO_ID_DRAWSPROCKET:
+ SDL_putenv("SDL_VIDEODRIVER=DSp");
+ SDL_memcpy(prefs.video_driver_name, "\pDSp", 4);
+ break;
+ case VIDEO_ID_TOOLBOX:
+ SDL_putenv("SDL_VIDEODRIVER=toolbox");
+ SDL_memcpy(prefs.video_driver_name, "\ptoolbox", 8);
+ break;
+ }
+
+#if !(defined(__APPLE__) && defined(__MACH__))
+ /* Redirect standard I/O to files */
+ if ( prefs.output_to_file ) {
+ freopen (STDOUT_FILE, "w", stdout);
+ freopen (STDERR_FILE, "w", stderr);
+ } else {
+ fclose (stdout);
+ fclose (stderr);
+ }
+#endif
+
+ if (settingsChanged) {
+ /* Save the prefs, even if they might not have changed (but probably did) */
+ if ( ! writePreferences (&prefs) )
+ fprintf (stderr, "WARNING: Could not save preferences!\n");
+ }
+
+#if !(defined(__APPLE__) && defined(__MACH__))
+ appNameText[0] = 0;
+ getCurrentAppName (appNameText); /* check for error here ? */
+
+ commandLine = (char*) malloc (appNameText[0] + prefs.command_line[0] + 2);
+ if ( commandLine == NULL ) {
+ exit(-1);
+ }
+
+ /* Rather than rewrite ParseCommandLine method, let's replace */
+ /* any spaces in application name with underscores, */
+ /* so that the app name is only 1 argument */
+ for (i = 1; i < 1+appNameText[0]; i++)
+ if ( appNameText[i] == ' ' ) appNameText[i] = '_';
+
+ /* Copy app name & full command text to command-line C-string */
+ SDL_memcpy(commandLine, appNameText + 1, appNameText[0]);
+ commandLine[appNameText[0]] = ' ';
+ SDL_memcpy(commandLine + appNameText[0] + 1, prefs.command_line + 1, prefs.command_line[0]);
+ commandLine[ appNameText[0] + 1 + prefs.command_line[0] ] = '\0';
+
+ /* Parse C-string into argv and argc */
+ nargs = ParseCommandLine (commandLine, NULL);
+ args = (char **)malloc((nargs+1)*(sizeof *args));
+ if ( args == NULL ) {
+ exit(-1);
+ }
+ ParseCommandLine (commandLine, args);
+
+ /* Run the main application code */
+ SDL_main(nargs, args);
+ free (args);
+ free (commandLine);
+
+ /* Remove useless stdout.txt and stderr.txt */
+ cleanup_output ();
+#else // defined(__APPLE__) && defined(__MACH__)
+ SDL_main(argc, argv);
+#endif
+
+ /* Exit cleanly, calling atexit() functions */
+ exit (0);
+
+ /* Never reached, but keeps the compiler quiet */
+ return (0);
+}