290 lines
6.0 KiB
C
290 lines
6.0 KiB
C
|
/*
|
||
|
*
|
||
|
* This is a simple module to allow the
|
||
|
* user to compile and execute an applescript
|
||
|
* which is passed in as a text item.
|
||
|
*
|
||
|
* Sean Hummel <seanh@prognet.com>
|
||
|
* 1/20/98
|
||
|
* RealNetworks
|
||
|
*
|
||
|
* Jay Painter <jpaint@serv.net> <jpaint@gimp.org> <jpaint@real.com>
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <Resources.h>
|
||
|
#include <Files.h>
|
||
|
#include <OSA.h>
|
||
|
#include <string.h>
|
||
|
#include "ScriptRunner.h"
|
||
|
#include <script.h>
|
||
|
#include <resources.h>
|
||
|
|
||
|
|
||
|
|
||
|
OSAError LoadScriptingComponent (ComponentInstance * scriptingComponent);
|
||
|
|
||
|
|
||
|
/*
|
||
|
* store the script as a compile script so that OSA
|
||
|
* components may load and execute the script easily
|
||
|
*/
|
||
|
OSAError
|
||
|
CompileAndSave (const char *text,
|
||
|
const char *outfile,
|
||
|
OSAActiveUPP proc,
|
||
|
AEDesc * result)
|
||
|
{
|
||
|
|
||
|
OSAError err2 = 0;
|
||
|
AEDesc theScript;
|
||
|
OSAID compiledScriptID = 0;
|
||
|
ComponentInstance scriptingComponent;
|
||
|
FSSpec outfilespec;
|
||
|
AEDesc theCompiledScript;
|
||
|
OSAID scriptid = kOSANullScript;
|
||
|
short saveres = 0;
|
||
|
|
||
|
|
||
|
|
||
|
/* Initialize theScript here because it is a struct */
|
||
|
theScript.dataHandle = NULL;
|
||
|
theCompiledScript.dataHandle = NULL;
|
||
|
|
||
|
|
||
|
/* open the component manager */
|
||
|
err2 = LoadScriptingComponent (&scriptingComponent);
|
||
|
if (err2)
|
||
|
return err2; /* <<< Fail quietly?? */
|
||
|
|
||
|
|
||
|
/* construct the AppleEvent Descriptor to contain the text of script */
|
||
|
AECreateDesc ('TEXT', text, strlen (text), &theScript);
|
||
|
|
||
|
err2 = OSACompile (scriptingComponent,
|
||
|
&theScript,
|
||
|
kOSAModeCompileIntoContext,
|
||
|
&scriptid);
|
||
|
if (err2)
|
||
|
{
|
||
|
OSAScriptError (scriptingComponent, kOSAErrorMessage, 'TEXT', result);
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
|
||
|
err2 = OSAStore (scriptingComponent,
|
||
|
scriptid,
|
||
|
typeOSAGenericStorage,
|
||
|
kOSAModeCompileIntoContext,
|
||
|
&theCompiledScript);
|
||
|
if (err2)
|
||
|
{
|
||
|
OSAScriptError (scriptingComponent, kOSAErrorMessage, 'TEXT', result);
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
|
||
|
c2pstr (outfile);
|
||
|
FSMakeFSSpec (0, 0, (StringPtr) outfile, &outfilespec);
|
||
|
p2cstr ((StringPtr) outfile);
|
||
|
|
||
|
FSpDelete (&outfilespec);
|
||
|
|
||
|
FSpCreateResFile (&outfilespec, 'ToyS', 'osas', smRoman);
|
||
|
|
||
|
saveres = CurResFile ();
|
||
|
|
||
|
if (saveres)
|
||
|
{
|
||
|
short myres = 0;
|
||
|
myres = FSpOpenResFile (&outfilespec, fsWrPerm);
|
||
|
|
||
|
UseResFile (myres);
|
||
|
AddResource (theCompiledScript.dataHandle, 'scpt', 128, "\p");
|
||
|
CloseResFile (myres);
|
||
|
UseResFile (saveres);
|
||
|
}
|
||
|
|
||
|
|
||
|
CleanUp:
|
||
|
|
||
|
if (theScript.dataHandle)
|
||
|
AEDisposeDesc (&theScript);
|
||
|
|
||
|
if (theCompiledScript.dataHandle)
|
||
|
AEDisposeDesc (&theCompiledScript);
|
||
|
|
||
|
if (scriptid)
|
||
|
OSADispose (scriptingComponent, scriptid);
|
||
|
|
||
|
if (scriptingComponent != 0)
|
||
|
CloseComponent (scriptingComponent);
|
||
|
|
||
|
|
||
|
return err2;
|
||
|
}
|
||
|
|
||
|
|
||
|
OSAError
|
||
|
CompileAndExecute (const char *text,
|
||
|
AEDesc * result,
|
||
|
OSAActiveUPP proc)
|
||
|
{
|
||
|
OSAError err2 = 0;
|
||
|
AEDesc theScript;
|
||
|
OSAID compiledScriptID = 0;
|
||
|
ComponentInstance scriptingComponent;
|
||
|
|
||
|
|
||
|
/* initialize theScript here because it is a struct */
|
||
|
theScript.dataHandle = NULL;
|
||
|
|
||
|
/* Open the component manager */
|
||
|
err2 = LoadScriptingComponent (&scriptingComponent);
|
||
|
if (err2)
|
||
|
return err2; /* <<< Fail quietly?? */
|
||
|
|
||
|
|
||
|
/* construct the AppleEvent Descriptor to contain the text of script */
|
||
|
AECreateDesc ('TEXT', text, strlen (text), &theScript);
|
||
|
|
||
|
|
||
|
err2 = OSASetActiveProc (scriptingComponent, proc, NULL);
|
||
|
if (err2)
|
||
|
goto CleanUp;
|
||
|
|
||
|
|
||
|
err2 = OSADoScript (scriptingComponent, &theScript, kOSANullScript, 'TEXT', 0, result);
|
||
|
if (err2)
|
||
|
{
|
||
|
OSAScriptError (scriptingComponent, kOSAErrorMessage, 'TEXT', result);
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
|
||
|
CleanUp:
|
||
|
|
||
|
if (theScript.dataHandle)
|
||
|
AEDisposeDesc (&theScript);
|
||
|
|
||
|
if (scriptingComponent != 0)
|
||
|
CloseComponent (scriptingComponent);
|
||
|
|
||
|
|
||
|
return err2;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* This routine reads in a saved script file and executes
|
||
|
* the script contained within (from a 'scpt' resource.)
|
||
|
*/
|
||
|
OSAError
|
||
|
ExecuteScriptFile (const char *theFilePath,
|
||
|
OSAActiveUPP proc,
|
||
|
AEDesc * result)
|
||
|
{
|
||
|
OSAError err2;
|
||
|
short resRefCon;
|
||
|
AEDesc theScript;
|
||
|
OSAID compiledScriptID, scriptResultID;
|
||
|
ComponentInstance scriptingComponent;
|
||
|
FSSpec theFile;
|
||
|
|
||
|
|
||
|
c2pstr (theFilePath);
|
||
|
FSMakeFSSpec (0, 0, (StringPtr) theFilePath, &theFile);
|
||
|
p2cstr ((StringPtr) theFilePath);
|
||
|
|
||
|
|
||
|
/* open a connection to the OSA */
|
||
|
err2 = LoadScriptingComponent (&scriptingComponent);
|
||
|
if (err2)
|
||
|
return err2; /* <<< Fail quietly?? */
|
||
|
|
||
|
|
||
|
err2 = OSASetActiveProc (scriptingComponent, proc, NULL);
|
||
|
if (err2)
|
||
|
goto error;
|
||
|
|
||
|
|
||
|
/* now, try and read in the script
|
||
|
* Open the script file and get the resource
|
||
|
*/
|
||
|
resRefCon = FSpOpenResFile (&theFile, fsRdPerm);
|
||
|
if (resRefCon == -1)
|
||
|
return ResError ();
|
||
|
|
||
|
theScript.dataHandle = Get1IndResource (typeOSAGenericStorage, 1);
|
||
|
|
||
|
if ((err2 = ResError ()) || (err2 = resNotFound, theScript.dataHandle == NULL))
|
||
|
{
|
||
|
CloseResFile (resRefCon);
|
||
|
return err2;
|
||
|
}
|
||
|
|
||
|
theScript.descriptorType = typeOSAGenericStorage;
|
||
|
DetachResource (theScript.dataHandle);
|
||
|
CloseResFile (resRefCon);
|
||
|
err2 = noErr;
|
||
|
|
||
|
|
||
|
/* give a copy of the script to AppleScript */
|
||
|
err2 = OSALoad (scriptingComponent,
|
||
|
&theScript,
|
||
|
0L,
|
||
|
&compiledScriptID);
|
||
|
if (err2)
|
||
|
goto error;
|
||
|
|
||
|
AEDisposeDesc (&theScript);
|
||
|
theScript.dataHandle = NULL;
|
||
|
|
||
|
|
||
|
err2 = OSAExecute (scriptingComponent,
|
||
|
compiledScriptID,
|
||
|
kOSANullScript,
|
||
|
0,
|
||
|
&scriptResultID);
|
||
|
|
||
|
if (compiledScriptID)
|
||
|
OSAScriptError (scriptingComponent, kOSAErrorMessage, 'TEXT', result);
|
||
|
|
||
|
if (err2)
|
||
|
goto error;
|
||
|
|
||
|
/* If there was an error, return it. If there was a result, return it. */
|
||
|
(void) OSADispose (scriptingComponent, compiledScriptID);
|
||
|
|
||
|
if (err2)
|
||
|
goto error;
|
||
|
else
|
||
|
goto done;
|
||
|
|
||
|
error:
|
||
|
if (theScript.dataHandle)
|
||
|
AEDisposeDesc (&theScript);
|
||
|
|
||
|
|
||
|
done:
|
||
|
|
||
|
|
||
|
return err2;
|
||
|
}
|
||
|
|
||
|
|
||
|
OSAError
|
||
|
LoadScriptingComponent (ComponentInstance * scriptingComponent)
|
||
|
{
|
||
|
OSAError err2;
|
||
|
|
||
|
/* Open a connection to the Open Scripting Architecture */
|
||
|
*scriptingComponent = OpenDefaultComponent (kOSAComponentType,
|
||
|
kOSAGenericScriptingComponentSubtype);
|
||
|
|
||
|
err2 = GetComponentInstanceError (*scriptingComponent);
|
||
|
|
||
|
return err2;
|
||
|
}
|