In MacOSX, when drag'n'dropping a document on an SDL app, or double-clicking a
authorRyan C. Gordon <icculus@icculus.org>
Thu, 11 Aug 2005 00:56:16 +0000
changeset 1113 39408f59a0f7
parent 1112 6ded3dd929f5
child 1114 242a35a85852
In MacOSX, when drag'n'dropping a document on an SDL app, or double-clicking a document associated with the app, the document(s) are passed to SDL_main() as if they were command line arguments. Otherwise, the command line is always empty and there is no way for the app to recover this information.
src/main/macosx/SDLMain.m
--- a/src/main/macosx/SDLMain.m	Wed Aug 10 14:30:53 2005 +0000
+++ b/src/main/macosx/SDLMain.m	Thu Aug 11 00:56:16 2005 +0000
@@ -32,6 +32,7 @@
 static int    gArgc;
 static char  **gArgv;
 static BOOL   gFinderLaunch;
+static BOOL   gCalledAppMainline = FALSE;
 
 static NSString *getApplicationName(void)
 {
@@ -226,6 +227,52 @@
 
 #endif
 
+
+/*
+ * Catch document open requests...this lets us notice files when the app
+ *  was launched by double-clicking a document, or when a document was
+ *  dragged/dropped on the app's icon. You need to have a
+ *  CFBundleDocumentsType section in your Info.plist to get this message,
+ *  apparently.
+ *
+ * Files are added to gArgv, so to the app, they'll look like command line
+ *  arguments. Previously, apps launched from the finder had nothing but
+ *  an argv[0].
+ *
+ * This message may be received multiple times to open several docs on launch.
+ *
+ * This message is ignored once the app's mainline has been called.
+ */
+- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
+{
+    if (gCalledAppMainline)  /* app has started, ignore this document. */
+        return FALSE;
+
+    unsigned buflen = [filename lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1;
+    char *arg = (char *) malloc(buflen);
+    if (arg == NULL)
+        return FALSE;
+
+    char **newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2));
+    if (newargv == NULL)
+    {
+        free(arg);
+        return FALSE;
+    }
+    gArgv = newargv;
+
+    BOOL rc = [filename getCString:arg maxLength:buflen encoding:NSUTF8StringEncoding];
+    if (!rc)
+        free(arg);
+    else
+    {
+        gArgv[gArgc++] = arg;
+        gArgv[gArgc] = NULL;
+    }
+    return rc;
+}
+
+
 /* Called when the internal event loop has just started running */
 - (void) applicationDidFinishLaunching: (NSNotification *) note
 {
@@ -240,6 +287,7 @@
 #endif
 
     /* Hand off to main application code */
+    gCalledAppMainline = TRUE;
     status = SDL_main (gArgc, gArgv);
 
     /* We're done, thank you for playing */
@@ -300,13 +348,19 @@
     /* Copy the arguments into a global variable */
     /* This is passed if we are launched by double-clicking */
     if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
+        gArgv = (char **) malloc(sizeof (char *) * 2);
+        gArgv[0] = argv[0];
+        gArgv[1] = NULL;
         gArgc = 1;
         gFinderLaunch = YES;
     } else {
+        int i;
         gArgc = argc;
+        gArgv = (char **) malloc(sizeof (char *) * (argc+1));
+        for (i = 0; i <= argc; i++)
+            gArgv[i] = argv[i];
         gFinderLaunch = NO;
     }
-    gArgv = argv;
 
 #if SDL_USE_NIB_FILE
     [SDLApplication poseAsClass:[NSApplication class]];