diff options
-rw-r--r-- | Mac/Include/getapplbycreator.h | 4 | ||||
-rw-r--r-- | Mac/Modules/macfsmodule.c | 21 | ||||
-rw-r--r-- | Mac/Python/getapplbycreator.c | 128 |
3 files changed, 153 insertions, 0 deletions
diff --git a/Mac/Include/getapplbycreator.h b/Mac/Include/getapplbycreator.h new file mode 100644 index 0000000..4ff60fa --- /dev/null +++ b/Mac/Include/getapplbycreator.h @@ -0,0 +1,4 @@ +#include <Types.h> +#include <Files.h> + +extern OSErr FindApplicationFromCreator(OSType, FSSpecPtr); diff --git a/Mac/Modules/macfsmodule.c b/Mac/Modules/macfsmodule.c index 831fd65..91e63eb 100644 --- a/Mac/Modules/macfsmodule.c +++ b/Mac/Modules/macfsmodule.c @@ -34,6 +34,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include <LowMem.h> #include "nfullpath.h" +#include "getapplbycreator.h" #ifdef THINK_C #define FileFilterUPP FileFilterProcPtr @@ -895,6 +896,25 @@ mfs_FindFolder(self, args) } static object * +mfs_FindApplication(self, args) + object *self; /* Not used */ + object *args; +{ + OSErr err; + OSType which; + FSSpec fss; + + if (!newgetargs(args, "O&", PyMac_GetOSType, &which) ) + return NULL; + err = FindApplicationFromCreator(which, &fss); + if ( err ) { + PyErr_Mac(ErrorObject, err); + return NULL; + } + return (object *)newmfssobject(&fss); +} + +static object * mfs_FInfo(self, args) object *self; object *args; @@ -915,6 +935,7 @@ static struct methodlist mfs_methods[] = { {"RawFSSpec", mfs_RawFSSpec, 1}, {"RawAlias", mfs_RawAlias, 1}, {"FindFolder", mfs_FindFolder, 1}, + {"FindApplication", mfs_FindApplication, 1}, {"FInfo", mfs_FInfo, 1}, {NULL, NULL} /* sentinel */ diff --git a/Mac/Python/getapplbycreator.c b/Mac/Python/getapplbycreator.c new file mode 100644 index 0000000..3370f31 --- /dev/null +++ b/Mac/Python/getapplbycreator.c @@ -0,0 +1,128 @@ +/* +** FindApplicationFromCreator uses the Desktop Database to +** locate the creator application for the given document +** +** this routine will check the desktop database of all local +** disks, then the desktop databases of all server volumes +** (so up to two passes will be made) +** +** This code was created from FindApplicationFromDocument +** routine, origin unknown. +*/ + +#include <Types.h> +#include <Files.h> +#include <Errors.h> +#include "getapplbycreator.h" + + +OSErr FindApplicationFromCreator(OSType creator, + FSSpecPtr applicationFSSpecPtr) +{ + enum { localPass, remotePass, donePass } volumePass; + DTPBRec desktopParams; + HParamBlockRec hfsParams; + short volumeIndex; + Boolean foundFlag; + GetVolParmsInfoBuffer volumeInfoBuffer; + OSErr retCode; + +/* dkj 12/94 initialize flag to false (thanks to Peter Baral for pointing out this bug) */ + foundFlag = false; + + volumePass = localPass; + volumeIndex = 0; + + do { + /* + ** first, find the vRefNum of the volume whose Desktop Database + ** we're checking this time + */ + + volumeIndex++; + + /* convert the volumeIndex into a vRefNum */ + + hfsParams.volumeParam.ioNamePtr = nil; + hfsParams.volumeParam.ioVRefNum = 0; + hfsParams.volumeParam.ioVolIndex = volumeIndex; + retCode = PBHGetVInfoSync(&hfsParams); + + /* a nsvErr indicates that the current pass is over */ + if (retCode == nsvErr) goto SkipThisVolume; + if (retCode != noErr) goto Bail; + + /* + ** call GetVolParms to determine if this volume is a server + ** (a remote volume) + */ + + hfsParams.ioParam.ioBuffer = (Ptr) &volumeInfoBuffer; + hfsParams.ioParam.ioReqCount = sizeof(GetVolParmsInfoBuffer); + retCode = PBHGetVolParmsSync(&hfsParams); + if (retCode != noErr) goto Bail; + + /* + ** if the vMServerAdr field of the volume information buffer + ** is zero, this is a local volume; skip this volume + ** if it's local on a remote pass or remote on a local pass + */ + + if ((volumeInfoBuffer.vMServerAdr != 0) != + (volumePass == remotePass)) goto SkipThisVolume; + + /* okay, now we've found the vRefNum for our desktop database call */ + + desktopParams.ioVRefNum = hfsParams.volumeParam.ioVRefNum; + + /* + ** find the path refNum for the desktop database for + ** the volume we're interested in + */ + + desktopParams.ioNamePtr = nil; + + retCode = PBDTGetPath(&desktopParams); + if (retCode == noErr && desktopParams.ioDTRefNum != 0) { + + /* + ** use the GetAPPL call to find the preferred application + ** for opening any document with this one's creator + */ + + desktopParams.ioIndex = 0; + desktopParams.ioFileCreator = creator; + desktopParams.ioNamePtr = applicationFSSpecPtr->name; + retCode = PBDTGetAPPLSync(&desktopParams); + + if (retCode == noErr) { + /* + ** okay, found it; fill in the application file spec + ** and set the flag indicating we're done + */ + + applicationFSSpecPtr->parID = desktopParams.ioAPPLParID; + applicationFSSpecPtr->vRefNum = desktopParams.ioVRefNum; + foundFlag = true; + + } + } + + SkipThisVolume: + /* + ** if retCode indicates a no such volume error or if this + ** was the first pass, it's time to move on to the next pass + */ + + if (retCode == nsvErr) { + volumePass++; + volumeIndex = 0; + } + + } while (foundFlag == false && volumePass != donePass); + +Bail: + if (retCode == nsvErr) + return fnfErr; /* More logical than "No such volume" */ + return retCode; +} |