mirror of https://github.com/python/cpython
309 lines
6.3 KiB
C
309 lines
6.3 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>
|
|
|
|
#ifdef TARGET_API_MAC_CARBON
|
|
static
|
|
p2cstr(StringPtr p)
|
|
{
|
|
unsigned char *c = p;
|
|
int len = c[0];
|
|
strncpy((char *)c+1, (char *)c, len);
|
|
c[len] = 0;
|
|
}
|
|
|
|
static c2pstr(const char *cc)
|
|
{
|
|
char *c = (char *)cc; /* Ouch */
|
|
int len = strlen(c);
|
|
|
|
if ( len > 255 ) len = 255;
|
|
strncpy(c, c+1, len);
|
|
c[0] = len;
|
|
}
|
|
#endif
|
|
|
|
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;
|
|
}
|