mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-09-06 18:54:30 +00:00
322 lines
7.7 KiB
C
322 lines
7.7 KiB
C
|
/*
|
|||
|
File: ThingFiles.c
|
|||
|
|
|||
|
Copyright: <EFBFBD> 1991-1993 by Apple Computer, Inc., all rights reserved.
|
|||
|
|
|||
|
Change History (most recent first):
|
|||
|
|
|||
|
<SM4> 8/5/93 JDR integrate Component Mgr from Reality
|
|||
|
<8> 6/13/93 JDR Rolled in the ComponentMgr sources from QuickTime 1.6.
|
|||
|
<7> 5/29/92 DCL Included TextUtils.h. RelString moved there for the New Inside
|
|||
|
Mac.
|
|||
|
<6> 12/12/91 DTY #1018054: If _HomeResFile returns 0 in _FSSpecFromResource, use
|
|||
|
the file reference number in SysMap instead.
|
|||
|
<5> 12/6/91 YK Removed System6 conditionals. Object compare identical to <4>.
|
|||
|
<4> 12/5/91 YK Rolled in QuickTime GM:
|
|||
|
<3> 11/6/91 YK Corrected comments. I misunderstood revision number.
|
|||
|
<2> 11/6/91 YK Replaced code with System 7 trap. Added code for 'thng' in
|
|||
|
System file. Removed unnecessary include statement.
|
|||
|
|
|||
|
<3> 5/18/91 dvb Thing->Component
|
|||
|
<2> 5/2/91 BAL Updated to latest think headers
|
|||
|
<1> 3/28/91 BAL first checked in
|
|||
|
|
|||
|
To Do:
|
|||
|
*/
|
|||
|
|
|||
|
#include <Files.h>
|
|||
|
#include <Resources.h>
|
|||
|
#include <Memory.h>
|
|||
|
#include <SysEqu.h>
|
|||
|
#include <TextUtils.h>
|
|||
|
#include <Errors.h>
|
|||
|
#include <Icons.h>
|
|||
|
|
|||
|
#include "PrivateThingManager.h"
|
|||
|
|
|||
|
|
|||
|
OSErr GrowRTFileTable(short growCount);
|
|||
|
|
|||
|
OSErr _FSSpecFromResource( Handle h, FSSpec *fileSpec )
|
|||
|
{
|
|||
|
OSErr error = 0;
|
|||
|
FCBPBRec anFCB;
|
|||
|
Str255 fName;
|
|||
|
short fref;
|
|||
|
|
|||
|
fref = HomeResFile( h );
|
|||
|
if (fref < 0) return ResError();
|
|||
|
|
|||
|
if (fref == 0) // <6> Convert a reference number
|
|||
|
fref = *(short *)SysMap; // <6> of 0 to the system files<65> refNum.
|
|||
|
|
|||
|
anFCB.ioCompletion = 0;
|
|||
|
anFCB.ioVRefNum = 0;
|
|||
|
anFCB.ioRefNum = fref;
|
|||
|
anFCB.ioFCBIndx = 0;
|
|||
|
fName[0] = 0;
|
|||
|
anFCB.ioNamePtr = (StringPtr)fName;
|
|||
|
|
|||
|
if (error = PBGetFCBInfoSync( &anFCB )) goto bail;
|
|||
|
|
|||
|
error = FSMakeFSSpec( anFCB.ioFCBVRefNum, anFCB.ioFCBParID, anFCB.ioNamePtr, fileSpec);
|
|||
|
|
|||
|
bail:
|
|||
|
return (error);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Boolean FSSpecEqual( register FSSpec *fileSpecA, register FSSpec *fileSpecB )
|
|||
|
{
|
|||
|
return ((fileSpecA->vRefNum == fileSpecB->vRefNum)
|
|||
|
&& (fileSpecA->parID == fileSpecB->parID)
|
|||
|
&& !RelString(fileSpecA->name,fileSpecB->name,false,true));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
short AddComponentFSSpec( FSSpec *fspec )
|
|||
|
{
|
|||
|
register rtFile *rtFileList = ComponentManagerGlobals->rtFileTable;
|
|||
|
register short i, empty = -1;
|
|||
|
register short count = ComponentManagerGlobals->rtFileTotalCount;
|
|||
|
HParamBlockRec pb;
|
|||
|
OSErr err = -1;
|
|||
|
|
|||
|
// get the file's id
|
|||
|
pb.fidParam.ioNamePtr = fspec->name;
|
|||
|
pb.fidParam.ioVRefNum = fspec->vRefNum;
|
|||
|
pb.fidParam.ioSrcDirID = fspec->parID;
|
|||
|
err = PBCreateFileIDRefSync(&pb);
|
|||
|
if (err == fidExists) err = noErr;
|
|||
|
|
|||
|
/* first check to see if it's already there */
|
|||
|
|
|||
|
for (i=0; i<count; i++) {
|
|||
|
if (rtFileList->referenceCount) /* is this spot in use? */
|
|||
|
{
|
|||
|
if (rtFileList->vRefNum == 0)
|
|||
|
{
|
|||
|
// this entry contains an FSSpec handle, not a file id
|
|||
|
if ( FSSpecEqual(*(FSSpec **)rtFileList->fileID, fspec) )
|
|||
|
{
|
|||
|
foundIndex:
|
|||
|
rtFileList->referenceCount++;
|
|||
|
return i;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// this entry contains a file id
|
|||
|
if ((fspec->vRefNum == rtFileList->vRefNum) &&
|
|||
|
(pb.fidParam.ioFileID == rtFileList->fileID))
|
|||
|
goto foundIndex;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
empty = i;
|
|||
|
rtFileList++;
|
|||
|
}
|
|||
|
|
|||
|
/* didn't find it so add it to an empty spot */
|
|||
|
|
|||
|
if (empty < 0) {
|
|||
|
// need to grow the table. no empty spot was available.
|
|||
|
if (GrowRTFileTable( kComponentFileAllocationSize ))
|
|||
|
return empty; /* error: could not allocate a file entry */
|
|||
|
|
|||
|
empty = ComponentManagerGlobals->rtFileTotalCount - 1; // last entry should always be free
|
|||
|
}
|
|||
|
|
|||
|
rtFileList = ComponentManagerGlobals->rtFileTable + empty;
|
|||
|
if (err) {
|
|||
|
// need to make a copy of the FSSpec and save it away
|
|||
|
rtFileList->fileID = (Handle)NewHandleSys(0);
|
|||
|
if (rtFileList->fileID) {
|
|||
|
PtrAndHand((Ptr)fspec, (Handle)rtFileList->fileID, sizeof(FSSpec));
|
|||
|
if (MemError() == noErr) {
|
|||
|
rtFileList->vRefNum = 0;
|
|||
|
goto rememberFile;
|
|||
|
}
|
|||
|
}
|
|||
|
empty = -1;
|
|||
|
}
|
|||
|
else {
|
|||
|
// just save away the file id
|
|||
|
rtFileList->vRefNum = fspec->vRefNum;
|
|||
|
rtFileList->fileID = pb.fidParam.ioFileID;
|
|||
|
rememberFile:
|
|||
|
rtFileList->referenceCount = 1;
|
|||
|
ComponentManagerGlobals->rtFileUsedCount++;
|
|||
|
}
|
|||
|
|
|||
|
return empty;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
OSErr GrowRTFileTable( short growCount )
|
|||
|
/*
|
|||
|
* Grow the table of registered thing files.
|
|||
|
*/
|
|||
|
{
|
|||
|
register rtFile *aTable;
|
|||
|
rtFile *oldTable, *newTable;
|
|||
|
long oldTableSize;
|
|||
|
|
|||
|
oldTableSize = ComponentManagerGlobals->rtFileTotalCount * sizeof(rtFile);
|
|||
|
oldTable = ComponentManagerGlobals->rtFileTable;
|
|||
|
newTable = aTable = (rtFile *)NewPtrSysClear( oldTableSize + (long)growCount * sizeof(rtFile));
|
|||
|
if (!aTable)
|
|||
|
return MemError();
|
|||
|
|
|||
|
BlockMove((Ptr)oldTable, (Ptr)aTable, oldTableSize);
|
|||
|
|
|||
|
ComponentManagerGlobals->rtFileTable = newTable; /* begin using new table */
|
|||
|
ComponentManagerGlobals->rtFileTotalCount += growCount;
|
|||
|
if (oldTable)
|
|||
|
DisposPtr((Ptr)oldTable); /* dump the old one */
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
rtFileNum AddComponentResFile( Handle h )
|
|||
|
{
|
|||
|
FSSpec fspec;
|
|||
|
|
|||
|
if (_FSSpecFromResource( h, &fspec ))
|
|||
|
return -1;
|
|||
|
|
|||
|
return AddComponentFSSpec(&fspec);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
OSErr RemoveComponentResFile( rtFileNum fn )
|
|||
|
{
|
|||
|
register rtFile *rtFileList;
|
|||
|
|
|||
|
/* first check to see if it's a valid file number */
|
|||
|
|
|||
|
if ((fn < 0) || (fn >= ComponentManagerGlobals->rtFileTotalCount))
|
|||
|
return -1;
|
|||
|
|
|||
|
rtFileList = ComponentManagerGlobals->rtFileTable + fn;
|
|||
|
if (!--rtFileList->referenceCount)
|
|||
|
{
|
|||
|
// since the reference count went to zero, this spot is free
|
|||
|
if (rtFileList->vRefNum == 0)
|
|||
|
{
|
|||
|
// the file id was really a handle to an FSSpec, so toss it
|
|||
|
DisposHandle((Handle)rtFileList->fileID);
|
|||
|
}
|
|||
|
ComponentManagerGlobals->rtFileUsedCount--;
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
typedef struct getIconRecord {
|
|||
|
Component c;
|
|||
|
short resID;
|
|||
|
} getIconRecord;
|
|||
|
|
|||
|
static pascal OSErr GetIconFromResource(ResType theType, Handle *theIcon, getIconRecord *refCon)
|
|||
|
{
|
|||
|
OSErr err;
|
|||
|
Handle h;
|
|||
|
|
|||
|
if (!refCon->resID)
|
|||
|
h = nil; // no icon suite, but fake it for the 1-bit icon case
|
|||
|
else {
|
|||
|
h = Get1Resource(theType, refCon->resID);
|
|||
|
err = ResError();
|
|||
|
}
|
|||
|
if (!h || (err == -192)) {
|
|||
|
if (theType == 'ICN#') {
|
|||
|
// just get the old style component icon instead
|
|||
|
Handle h = NewHandle(128);
|
|||
|
|
|||
|
GetComponentInfo(refCon->c, nil, nil, nil, h);
|
|||
|
if (!h || !*h)
|
|||
|
DisposHandle(h);
|
|||
|
else
|
|||
|
*theIcon = h;
|
|||
|
}
|
|||
|
return noErr;
|
|||
|
}
|
|||
|
if (err) return err;
|
|||
|
|
|||
|
LoadResource(h);
|
|||
|
if (err = ResError()) return err;
|
|||
|
|
|||
|
DetachResource(h);
|
|||
|
if (err = ResError()) return err;
|
|||
|
|
|||
|
*theIcon = h;
|
|||
|
HNoPurge(*theIcon);
|
|||
|
|
|||
|
return noErr;
|
|||
|
}
|
|||
|
|
|||
|
pascal OSErr __GetComponentIconSuite(Component aComponent, Handle *iconSuite)
|
|||
|
{
|
|||
|
register RegisteredComponent *rt;
|
|||
|
OSErr err;
|
|||
|
short resref = -1;
|
|||
|
short saveRes;
|
|||
|
short suiteID = 0;
|
|||
|
getIconRecord refCon;
|
|||
|
|
|||
|
*iconSuite = nil;
|
|||
|
|
|||
|
if( ! (rt = ValidComponent(aComponent)) )
|
|||
|
return invalidComponentID; /* error : not a valid component ID */
|
|||
|
|
|||
|
if (rt->rtFlags & rtfHasIconSuite) {
|
|||
|
Handle h;
|
|||
|
ComponentResourceExtension *cre;
|
|||
|
|
|||
|
// open the thing's resource file
|
|||
|
saveRes = CurResFile();
|
|||
|
resref = OpenComponentResFile(aComponent);
|
|||
|
if (resref == -1)
|
|||
|
return resNotFound;
|
|||
|
|
|||
|
// get the thing resource which points to the suite
|
|||
|
h = Get1Resource(rt->rtResourceType, rt->rtResourceID);
|
|||
|
if (err = ResError()) goto bail;
|
|||
|
LoadResource(h);
|
|||
|
if (err = ResError()) goto bail;
|
|||
|
|
|||
|
cre = (ComponentResourceExtension *)((long)*h + sizeof(ComponentResource));
|
|||
|
suiteID = cre->componentIconFamily;
|
|||
|
|
|||
|
ReleaseResource(h); // we're done with this
|
|||
|
}
|
|||
|
|
|||
|
// use the Icon Suite Manager stuff to load up the icon suite (can't use GetIconSuite
|
|||
|
// because it won't detach the resources for us)
|
|||
|
err = NewIconSuite(iconSuite);
|
|||
|
if (err) goto bail;
|
|||
|
|
|||
|
refCon.resID = suiteID;
|
|||
|
refCon.c = aComponent;
|
|||
|
err = ForEachIconDo(*iconSuite, -1, (IconAction)GetIconFromResource, &refCon);
|
|||
|
|
|||
|
bail:
|
|||
|
if (resref != -1) {
|
|||
|
CloseComponentResFile(resref);
|
|||
|
UseResFile(saveRes);
|
|||
|
}
|
|||
|
|
|||
|
if (err && *iconSuite) {
|
|||
|
DisposeIconSuite(*iconSuite, true);
|
|||
|
*iconSuite = nil;
|
|||
|
}
|
|||
|
|
|||
|
return err;
|
|||
|
}
|
|||
|
|