mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-02-05 23:30:14 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
770 lines
23 KiB
OpenEdge ABL
770 lines
23 KiB
OpenEdge ABL
{
|
|
File: dpPubControlBlock.inc.p
|
|
|
|
Written by: Nick Kledzik
|
|
|
|
Copyright: © 1989-1990 by Apple Computer, Inc., all rights reserved.
|
|
|
|
This file is used in these builds: BigBang
|
|
|
|
Change History (most recent first):
|
|
|
|
<13> 2/11/91 ngk KSM,#B4-MTM-017: Fix initial edition folder to not be prefernece
|
|
folder
|
|
<12> 1/14/91 ngk <MM> fix GetLastÉ case if file is missing.
|
|
<11> 12/14/90 ngk <VL>In dpCreatePubCB it is now OK if dpPubSync returns fnfErr.
|
|
Update SaveOffContainer to use new FspXXX calls and handle
|
|
case of corrupted preference file. Simplified
|
|
RetreivedLastContainer by using ResolveAliasFile.
|
|
<10> 8/2/90 ngk Use DoNotPutInRegister
|
|
<9> 7/2/90 ngk New fields in PubCB. Call EqualString instead of SameBytes when
|
|
comparing files names to see if we already have a control block.
|
|
<8> 6/20/90 ngk Changed CanonicalFileSpec to FSSpec.
|
|
<7> 5/31/90 ngk Moved saving and restoring of last edition used to here. Now
|
|
save alias in preference folder instead of system. When
|
|
disposing of pubCB check if it is referenced by lastEditionUsed.
|
|
Change em globals to a pointer.
|
|
<6> 4/7/90 ngk Now dynamic arrays for app usage info. Use new failure handling.
|
|
<5> 3/10/90 ngk Change VolumeServices to VolumeAttributes. Changed RequestPubCB
|
|
to use dpSameBytes to compare file names intead of
|
|
IUEqualString.
|
|
<4> 1/8/90 ngk fixes
|
|
<2+> 1/6/90 ngk Fixed bug in dpRemoveAppsPubCBs
|
|
<2> 1/6/90 ngk Convert to BBS. Fixed bug in dpRemoveAppsPubCBs where edition
|
|
files were not being closed. Renamed routines
|
|
<1.9> 11/4/89 ngk Changed AppRefNum to be a handle to app's globals.
|
|
<¥1.8> 10/2/89 ngk Change PubSpec to EditionContainerSpec
|
|
<1.7> 9/18/89 ngk Changed FileSpec to FSSpec
|
|
<1.6> 9/7/89 ngk Added lastVolMod and lastDirMod to support way cool polling
|
|
<1.5> 8/29/89 ngk Fixed bug when using > 2 apps. Change openCount to IOCount
|
|
<1.4> 8/8/89 ngk Now use PubCBLinks for better list managment. qDebug ->
|
|
qRangeCheck shared -> volumeInfo
|
|
<1.3> 6/11/89 ngk Made better use of GetPubCBIndex
|
|
<1.2> 5/31/89 ngk Changed to use Alias manager instead of SofaLinks
|
|
<1.1> 5/29/89 ngk Changed PubCB to have a handle to usage info instead of the
|
|
PubCB being variable size. Factored usage changes into
|
|
dpPubCBbumpUsageCount
|
|
<1.0> 5/19/89 ngk Submitted for first time
|
|
|
|
To Do:
|
|
}
|
|
|
|
|
|
PROCEDURE dpSaveOffLastContainer; FORWARD;
|
|
|
|
|
|
{========================== low level ============================}
|
|
|
|
|
|
{
|
|
Return the head of PubCB linked list. Since head is a Ptr not a handle, return
|
|
the location of the pointer. If globals not allocated, return NIL.
|
|
}
|
|
{------------- dpGetPubCBListHeadNode -------------}
|
|
FUNCTION dpGetPubCBListHeadNode(VAR headNode: PubCBLinkHandle): OSErr;
|
|
VAR
|
|
emGlobalsPtr: EdtnMgrGlobalsPtrPtr;
|
|
BEGIN
|
|
emGlobalsPtr := dpGetGlobalsLocation;
|
|
headNode := PubCBLinkHandle(emGlobalsPtr);
|
|
IF emGlobalsPtr^ = NIL
|
|
THEN dpGetPubCBListHeadNode := editionMgrInitErr
|
|
ELSE dpGetPubCBListHeadNode := noErr;
|
|
END; { dpGetPubCBListHeadNode }
|
|
|
|
|
|
{
|
|
Creates a PubCB for 'editionFile' and puts it in the PubCB list. If
|
|
unsuccessful, it returns NIL and an error.
|
|
}
|
|
{------------- dpCreatePubCB -------------}
|
|
FUNCTION dpCreatePubCB(editionFile: FSSpec; VAR thePubCB: PubCBHandle):OSErr;
|
|
VAR
|
|
i: INTEGER;
|
|
usage: TotalAppUsageHandle;
|
|
aPubCB: PubCBLinkHandle;
|
|
headPubCB: PubCBLinkHandle;
|
|
foundAt: INTEGER;
|
|
foundPtr: Ptr;
|
|
syncErr: OSErr;
|
|
fi: FailInfo;
|
|
BEGIN
|
|
DoNotPutInRegister(@usage);
|
|
thePubCB := NIL;
|
|
usage := NIL;
|
|
|
|
{ set up failure handling }
|
|
IF isFailure(fi, dpCreatePubCB) THEN
|
|
BEGIN
|
|
IF thePubCB <> NIL THEN
|
|
BEGIN
|
|
DisposHandle(Handle(thePubCB));
|
|
thePubCB := NIL;
|
|
END;
|
|
IF usage <> NIL THEN
|
|
BEGIN
|
|
DisposHandle(Handle(usage));
|
|
END;
|
|
EXIT(dpCreatePubCB);
|
|
END; {if}
|
|
|
|
{ allocate relocatable block in the system heap }
|
|
thePubCB := PubCBHandle(NewHandleSysClear(SizeOf(PubCBRecord)));
|
|
FailOSErr(MemError);
|
|
|
|
FailOSErr(dpNewDynamicArray(SizeOf(TotalAppUsage), {headerSize}
|
|
SizeOf(EachAppsUsage), {slotSize}
|
|
kInitialApps, {initialSlots}
|
|
NewHandleSysClear, {MyNewHandle} {zeros memory}
|
|
DyanmicArrayHandle(usage))); {VAR arrayH}
|
|
(*
|
|
{ initialization of usage is not needed because NewHandleSysClear does all the work }
|
|
WITH usage^^ DO
|
|
BEGIN
|
|
totalUseCount := 0;
|
|
totalIOCount := 0;
|
|
FOR i := 1 TO kInitialApps DO
|
|
BEGIN
|
|
WITH appArray[i] DO
|
|
BEGIN
|
|
app := NIL;
|
|
useCount := 0;
|
|
IOCount := 0;
|
|
END; {with}
|
|
END; {for}
|
|
END; {with}
|
|
*)
|
|
|
|
WITH thePubCB^^ DO
|
|
BEGIN
|
|
{ initialize some fields, note: NewHandleSysClear already zeros out most fields }
|
|
usageInfo := usage;
|
|
{volumeInfo := 0;}
|
|
{pubCNodeID := 0;}
|
|
{lastVolMod := 0;}
|
|
{lastDirMod := 0;}
|
|
{oldPubCB := NIL;}
|
|
{publisherApp := NIL;}
|
|
{publisher := NIL;}
|
|
{publisherAlias := NIL;}
|
|
{publisherCount := 0;}
|
|
{publisherKind := 0;}
|
|
{fileMissing := FALSE;}
|
|
fileRefNum := kClosedFileRefNum;
|
|
openMode := dmNotOpen;
|
|
fileMark := kBadPosition;
|
|
{rangeLockStart := 0;}
|
|
{rangeLockLen := 0;}
|
|
{allocMap := NIL;}
|
|
{formats := NIL;}
|
|
{info.mdDate := 0;}
|
|
{info.crDate := 0;}
|
|
{info.fdCreator := ' ';}
|
|
{info.fdType := ' ';}
|
|
info.container.theFile := editionFile;
|
|
END; {with}
|
|
|
|
{ get initial info, OK if file is missing }
|
|
syncErr := dpPubSync(thePubCB);
|
|
IF syncErr <> noErr {&} THEN IF syncErr <> fnfErr THEN FailOSErr(syncErr);
|
|
|
|
|
|
{ insert into the sorted PubCB list }
|
|
{ the sort order is pubFile.vRefNum then pubFile.dirID }
|
|
{ that is, vRefNum=-3 is before vRefNum=-1 and dirID=0045 is before dirID=0167 }
|
|
{ note: this is done last so that a failure above will not have to fix the PubCB list }
|
|
|
|
FailOSErr(dpGetPubCBListHeadNode(headPubCB));
|
|
aPubCB := headPubCB^^.nextPubCB;
|
|
|
|
WHILE (aPubCB <> headPubCB)
|
|
& (PubCBHandle(aPubCB)^^.info.container.theFile.vRefNum < thePubCB^^.info.container.theFile.vRefNum)
|
|
DO aPubCB := aPubCB^^.nextPubCB;
|
|
|
|
IF (aPubCB <> headPubCB) {&} THEN IF (PubCBHandle(aPubCB)^^.info.container.theFile.vRefNum = thePubCB^^.info.container.theFile.vRefNum) THEN
|
|
BEGIN
|
|
WHILE (aPubCB <> headPubCB) & (PubCBHandle(aPubCB)^^.info.container.theFile.parID < thePubCB^^.info.container.theFile.parID)
|
|
DO aPubCB := aPubCB^^.nextPubCB;
|
|
END; {if}
|
|
|
|
{ at this point we want to insert thePubCB just before aPubCB }
|
|
WITH PubCBLinkHandle(thePubCB)^^ DO
|
|
BEGIN
|
|
nextPubCB := aPubCB;
|
|
prevPubCB := aPubCB^^.prevPubCB;
|
|
nextPubCB^^.prevPubCB := PubCBLinkHandle(thePubCB);
|
|
prevPubCB^^.nextPubCB := PubCBLinkHandle(thePubCB);
|
|
END; {with}
|
|
|
|
Success(fi);
|
|
END; { dpCreatePubCB }
|
|
|
|
|
|
{
|
|
Remove 'thePubCB' from the linked list and release the memory.
|
|
}
|
|
{------------- dpDisposePubCB -------------}
|
|
FUNCTION dpDisposePubCB(thePubCB: PubCBHandle): OSErr;
|
|
BEGIN
|
|
{ release usage information }
|
|
{$IFC qRangeCheck }
|
|
IF PubCBLinkHandle(thePubCB) = PubCBLinkHandle(dpGetGlobalsLocation^)
|
|
THEN DebugStr('dpDisposePubCB: Tried to delete PubCBHeadNode.');
|
|
WITH thePubCB^^.usageInfo^^ DO
|
|
BEGIN
|
|
IF totalUseCount <> 0
|
|
THEN DebugStr('dpDisposePubCB: TotalUseCount <> 0');
|
|
IF totalIOCount <> 0
|
|
THEN DebugStr('dpDisposePubCB: TotalIOCount <> 0');
|
|
END; {with}
|
|
{$ENDC }
|
|
DisposHandle(Handle(thePubCB^^.usageInfo));
|
|
|
|
{ remove it from the PubCB list }
|
|
WITH PubCBLinkHandle(thePubCB)^^ DO
|
|
BEGIN
|
|
nextPubCB^^.prevPubCB := prevPubCB;
|
|
prevPubCB^^.nextPubCB := nextPubCB;
|
|
END; {with}
|
|
|
|
{$IFC qRangeCheck }
|
|
{ do something if file is still open }
|
|
IF thePubCB^^.fileRefNum <> kClosedFileRefNum
|
|
THEN DebugStr('dpDisposePubCB: file not closed');
|
|
{$ENDC }
|
|
|
|
DisposHandle(Handle(thePubCB));
|
|
dpDisposePubCB := MemError;
|
|
END; { dpDisposePubCB }
|
|
|
|
|
|
|
|
{
|
|
Find the index for the Application 'me' within 'theUsageInfo'.
|
|
If 'me' does not have an index and 'canGrow' is true, then resize PubCB to
|
|
make room for an index for 'me'.
|
|
}
|
|
{------------- dpGetAppsUsagePtr -------------}
|
|
FUNCTION dpGetAppsUsagePtr(theUsageInfo: TotalAppUsageHandle; me: AppRefNum;
|
|
canAddEntry: BOOLEAN; VAR usagePtr: EachAppsUsagePtr): OSErr;
|
|
VAR
|
|
anOpenSlotPtr: EachAppsUsagePtr;
|
|
ignoreSlot: INTEGER;
|
|
ignoreSlotPtr: EachAppsUsagePtr;
|
|
slotToUse: INTEGER;
|
|
|
|
FUNCTION MatchAppRefNum( index: INTEGER; elemPtr: EachAppsUsagePtr): BOOLEAN;
|
|
BEGIN
|
|
{ found the slot if app refnum matches }
|
|
MatchAppRefNum := (elemPtr^.app = me);
|
|
|
|
{ while we are at it, record off an open slot }
|
|
IF elemPtr^.app = NIL THEN
|
|
BEGIN
|
|
slotToUse := index;
|
|
anOpenSlotPtr := elemPtr;
|
|
END;
|
|
END; { MatchAppRefNum }
|
|
|
|
BEGIN
|
|
anOpenSlotPtr := NIL;
|
|
IF NOT dpFindElement(DyanmicArrayHandle(theUsageInfo), SizeOf(TotalAppUsage), MatchAppRefNum, slotToUse, usagePtr) THEN
|
|
BEGIN
|
|
IF NOT canAddEntry THEN FailOSErr(memFullErr);
|
|
|
|
{ app does not have already have a slot, need to get one }
|
|
IF anOpenSlotPtr <> NIL THEN
|
|
BEGIN
|
|
usagePtr := anOpenSlotPtr;
|
|
END ELSE
|
|
BEGIN
|
|
|
|
{ no open slots, will need to grow the array }
|
|
FailOSErr(dpAddDynamicArrayEntry(DyanmicArrayHandle(theUsageInfo), SizeOf(TotalAppUsage), slotToUse, usagePtr));
|
|
END;
|
|
{ is a slot available, use it }
|
|
WITH usagePtr^ DO
|
|
BEGIN
|
|
app := me;
|
|
useCount := 0;
|
|
IOCount := 0;
|
|
END; {with}
|
|
END; {if}
|
|
|
|
dpGetAppsUsagePtr := noErr;
|
|
END; { dpGetAppsUsagePtr }
|
|
|
|
|
|
{========================== high level ============================}
|
|
|
|
|
|
{------------- dpRequestPubCB -------------}
|
|
FUNCTION dpRequestPubCB(editionFile: FSSpec; me: AppRefNum;
|
|
checkExisting, canAllocateNew: BOOLEAN;
|
|
VAR thePubCB: PubCBHandle): OSErr;
|
|
VAR
|
|
aPubCB: PubCBLinkHandle;
|
|
headPubCB: PubCBLinkHandle;
|
|
created: BOOLEAN;
|
|
fi: FailInfo;
|
|
BEGIN
|
|
DoNotPutInRegister(@created);
|
|
thePubCB := NIL;
|
|
created := FALSE;
|
|
|
|
{ set up failure handling }
|
|
IF IsFailure(fi, dpRequestPubCB) THEN
|
|
BEGIN
|
|
IF (thePubCB <> NIL) {&} THEN IF created
|
|
THEN IgnoreOSErr(dpDisposePubCB(thePubCB));
|
|
thePubCB := NIL;
|
|
EXIT(dpRequestPubCB);
|
|
END; {if}
|
|
|
|
FailOSErr(dpGetPubCBListHeadNode(headPubCB));
|
|
aPubCB := headPubCB;
|
|
|
|
{ search existing if OK }
|
|
IF checkExisting THEN
|
|
BEGIN
|
|
aPubCB := headPubCB^^.nextPubCB;
|
|
{ walk PubCB looking for matching container }
|
|
WHILE aPubCB <> headPubCB DO
|
|
BEGIN
|
|
WITH PubCBHandle(aPubCB)^^ DO
|
|
BEGIN
|
|
IF (info.container.theFile.vRefNum = editionFile.vRefNum)
|
|
{&} THEN IF (info.container.theFile.parID = editionFile.parID)
|
|
{&} THEN IF info.container.theFile.name[0] = editionFile.name[0]
|
|
{&} THEN IF EqualString(info.container.theFile.name, editionFile.name, {caseSens}FALSE, {diacSens}FALSE)
|
|
(*
|
|
dpSameBytes(@info.container.theFile.name[1],
|
|
@editionFile.name[1],
|
|
LENGTH(editionFile.name))
|
|
*)
|
|
THEN LEAVE; {while}
|
|
aPubCB := links.nextPubCB;
|
|
END; {with}
|
|
END; {while}
|
|
END; {if}
|
|
|
|
{ if one does not already exist }
|
|
IF aPubCB = headPubCB THEN
|
|
BEGIN
|
|
IF NOT canAllocateNew THEN FailOSErr(memFullErr);
|
|
{ and OK to create one }
|
|
FailOSErr(dpCreatePubCB(editionFile, thePubCB));
|
|
created := TRUE;
|
|
END ELSE
|
|
BEGIN
|
|
thePubCB := PubCBHandle(aPubCB);
|
|
created := FALSE;
|
|
END; {if}
|
|
|
|
{ mark that one more is using thePubCB }
|
|
FailOSErr(dpPubCBbumpUsageCount(thePubCB^^.usageInfo, me, kCanGrowUsage, 1, 0));
|
|
|
|
Success(fi);
|
|
END; { dpRequestPubCB }
|
|
|
|
|
|
|
|
{------------- dpReleasePubCB -------------}
|
|
FUNCTION dpReleasePubCB(thePubCB: PubCBHandle; me: AppRefNum): OSErr;
|
|
VAR
|
|
usageInfo: TotalAppUsageHandle;
|
|
emGlobals: EdtnMgrGlobalsPtr;
|
|
BEGIN
|
|
usageInfo := thePubCB^^.usageInfo;
|
|
|
|
FailOSErr(dpPubCBbumpUsageCount(usageInfo, me, NOT kCanGrowUsage, -1, 0));
|
|
|
|
IF usageInfo^^.totalUseCount = 0 THEN
|
|
BEGIN
|
|
{ if file still open because of slop, close it }
|
|
IF thePubCB^^.openMode <> dmNotOpen THEN
|
|
BEGIN
|
|
{$IFC qRangeCheck}
|
|
IF usageInfo^^.totalIOCount <> 0
|
|
THEN DebugStr('dpReleasePubCB: I/O not completed.');
|
|
{$ENDC}
|
|
FailOSErr(dpPubCloseFile(thePubCB, NOT kFlush));
|
|
END;
|
|
|
|
{ if last edition used is this, then mark that need to use alias }
|
|
emGlobals := dpGetGlobalsLocation^;
|
|
IF emGlobals^.lastEditionUsed = thePubCB THEN
|
|
BEGIN
|
|
dpSaveOffLastContainer;
|
|
emGlobals^.lastEditionUsed := NIL;
|
|
END;
|
|
|
|
FailOSErr(dpDisposePubCB(thePubCB));
|
|
END;
|
|
|
|
dpReleasePubCB := noErr;
|
|
END; { dpReleasePubCB }
|
|
|
|
|
|
|
|
{------------- dpPubCBbumpUsageCount -------------}
|
|
FUNCTION dpPubCBbumpUsageCount(usageInfo: TotalAppUsageHandle;
|
|
whichApp: AppRefNum; canGrowUsage: BOOLEAN;
|
|
bumpUseCount,bumpIOCount: INTEGER):OSErr;
|
|
VAR
|
|
appUseCountPtr: EachAppsUsagePtr;
|
|
BEGIN
|
|
FailOSErr(dpGetAppsUsagePtr(usageInfo, whichApp, canGrowUsage, appUseCountPtr));
|
|
|
|
{ bump individual count for app }
|
|
WITH appUseCountPtr^ DO
|
|
BEGIN
|
|
useCount := useCount + bumpUseCount;
|
|
IOCount := IOCount + bumpIOCount;
|
|
END;
|
|
|
|
{ bump total count of all apps }
|
|
WITH usageInfo^^ DO
|
|
BEGIN
|
|
totalUseCount := totalUseCount + bumpUseCount;
|
|
totalIOCount := totalIOCount + bumpIOCount;
|
|
END;
|
|
|
|
{$IFC qRangeCheck }
|
|
WITH appUseCountPtr^ DO
|
|
BEGIN
|
|
IF useCount < 0
|
|
THEN DebugStr('dpPubCBbumpUsageCount: UseCount < 0');
|
|
IF IOCount < 0
|
|
THEN DebugStr('dpPubCBbumpUsageCount: IOCount < 0');
|
|
IF IOCount > UseCount
|
|
THEN DebugStr('dpPubCBbumpUsageCount: IOCount > UseCount');
|
|
IF (useCount = 0) & (IOCount <> 0)
|
|
THEN DebugStr('dpPubCBbumpUsageCount: IOCount <> 0');
|
|
END; {with}
|
|
{$ENDC }
|
|
|
|
dpPubCBbumpUsageCount := noErr;
|
|
END; { dpPubCBbumpUsageCount }
|
|
|
|
|
|
|
|
{------------- dpRemoveAppsPubCBs -------------}
|
|
{ this is only used by patch of ExitToShell to clean up a crashed App }
|
|
PROCEDURE dpRemoveAppsPubCBs(whichApp: AppRefNum);
|
|
VAR
|
|
aPubCB: PubCBLinkHandle;
|
|
aNextPubCB: PubCBLinkHandle;
|
|
headPubCB: PubCBLinkHandle;
|
|
appUseCountPtr: EachAppsUsagePtr;
|
|
thisAppIOCount: INTEGER;
|
|
thisAppUseCount: INTEGER;
|
|
ignore: OSErr;
|
|
totalOtherIOCount: INTEGER;
|
|
usageInfo: TotalAppUsageHandle;
|
|
fi: FailInfo;
|
|
usagePtrErr: OSErr;
|
|
BEGIN
|
|
{ walk PubCB looking for PubCBs in use by 'whichApp' }
|
|
IF dpGetPubCBListHeadNode(headPubCB) <> noErr THEN EXIT(dpRemoveAppsPubCBs);
|
|
aPubCB := headPubCB^^.nextPubCB;
|
|
WHILE aPubCB <> headPubCB DO
|
|
BEGIN
|
|
aNextPubCB := aPubCB^^.nextPubCB;
|
|
usageInfo := PubCBHandle(aPubCB)^^.usageInfo;
|
|
|
|
{ see if aPubCB used by this app }
|
|
{ catch any failures properly }
|
|
IF NOT IsFailure(fi, usagePtrErr) THEN
|
|
BEGIN
|
|
FailOSErr(dpGetAppsUsagePtr(usageInfo, whichApp, NOT kCanGrowUsage, appUseCountPtr));
|
|
Success(fi);
|
|
END;
|
|
IF usagePtrErr = noErr THEN
|
|
BEGIN
|
|
{ mark PubCB not longer used by this App }
|
|
WITH appUseCountPtr^ DO
|
|
BEGIN
|
|
{$IFC qRangeCheck }
|
|
IF app <> whichApp THEN DebugStr('dpRemoveAppsPubCBs: dpGetAppsUsagePtr blew it');
|
|
{$ENDC }
|
|
thisAppIOCount := IOCount;
|
|
thisAppUseCount := useCount;
|
|
app := NIL;
|
|
useCount := 0;
|
|
IOCount := 0;
|
|
END;
|
|
|
|
WITH usageInfo^^ DO
|
|
BEGIN
|
|
totalIOCount := totalIOCount - thisAppIOCount;
|
|
totalUseCount := totalUseCount - thisAppUseCount;
|
|
END;
|
|
|
|
{ if this app used to have *the*publisher then free it }
|
|
IF PubCBHandle(aPubCB)^^.publisherApp = whichApp THEN
|
|
BEGIN
|
|
WITH PubCBHandle(aPubCB)^^ DO
|
|
BEGIN
|
|
publisherApp := NIL;
|
|
publisher := NIL;
|
|
END; {with}
|
|
END; {if}
|
|
|
|
{##? change to call bottleNecks }
|
|
{ if no one is suppose to be doing IO, terminate any IO that is set up }
|
|
IF (usageInfo^^.totalIOCount = 0)
|
|
{&} THEN IF (PubCBHandle(aPubCB)^^.allocMap <> NIL) THEN
|
|
BEGIN
|
|
{ ignore failures }
|
|
IF NOT IsFailure(fi, ignore) THEN
|
|
BEGIN
|
|
FailOSErr(dpPubReleaseMap(PubCBHandle(aPubCB)));
|
|
Success(fi);
|
|
END;
|
|
{## maybe delete file, if open for new edition? }
|
|
END;
|
|
|
|
{##? change to call bottleNecks }
|
|
{ if no one is suppose to have the file open and it is, then close it }
|
|
IF (usageInfo^^.totalIOCount = 0)
|
|
{&} THEN IF (PubCBHandle(aPubCB)^^.publisher = NIL)
|
|
{&} THEN IF (PubCBHandle(aPubCB)^^.fileRefNum <> kClosedFileRefNum) THEN
|
|
BEGIN
|
|
{ ignore failures }
|
|
IF NOT IsFailure(fi, ignore) THEN
|
|
BEGIN
|
|
FailOSErr(dpPubCloseFile(PubCBHandle(aPubCB), NOT kFlush));
|
|
Success(fi);
|
|
END;
|
|
END;
|
|
|
|
{ If no other app is using the controlBlock, then remove it }
|
|
IF usageInfo^^.totalUseCount = 0 THEN
|
|
BEGIN
|
|
{ ignore failures }
|
|
IF NOT IsFailure(fi, ignore) THEN
|
|
BEGIN
|
|
FailOSErr(dpDisposePubCB(PubCBHandle(aPubCB)));
|
|
Success(fi);
|
|
END;
|
|
END;
|
|
|
|
END; {if}
|
|
aPubCB := aNextPubCB;
|
|
END; {while}
|
|
|
|
END; { dpRemoveAppsPubCBs }
|
|
|
|
|
|
|
|
|
|
{========================== preferences ============================}
|
|
|
|
(*
|
|
{ In systemn 7.0 parts are not supported. So, we just put an alias to edition
|
|
file in preference file. When we do support parts, we should append a
|
|
ContainerQualifier on the end of the alias record.
|
|
}
|
|
|
|
TYPE
|
|
pContainerQualifier = ^ContainerQualifier;
|
|
ContainerQualifier = RECORD
|
|
thePart: LONGINT;
|
|
thePartName: Str31;
|
|
END;
|
|
*)
|
|
|
|
|
|
|
|
{------------- dpGetPreferenceFile -------------}
|
|
PROCEDURE dpGetPreferenceFile(VAR prefFile: FSSpec);
|
|
BEGIN
|
|
{ get preference file from preference folder }
|
|
{### assumes string and folder exist }
|
|
{$PUSH} {$R-}
|
|
prefFile.name := GetString(rLastEditionUsedString)^^;
|
|
IF FindFolder(kOnSystemDisk, kPreferencesFolderType, {createFolder}TRUE, prefFile.vRefNum, prefFile.parID) <> noErr THEN;
|
|
{$POP}
|
|
END; { dpGetPreferenceFile }
|
|
|
|
|
|
|
|
{------------- dpRetreivedLastContainer -------------}
|
|
PROCEDURE dpRetreivedLastContainer(VAR lastEdition: EditionContainerSpec);
|
|
VAR
|
|
prefFile: FSSpec;
|
|
targetIsFolder: BOOLEAN;
|
|
wasAliased: BOOLEAN;
|
|
fndrInfo: FInfo;
|
|
resolveErr: OSErr;
|
|
BEGIN
|
|
{ make up a default last edition, in case alias fails }
|
|
WITH lastEdition.theFile DO
|
|
BEGIN
|
|
vRefNum := -1 * pInteger(SFSaveDisk)^;
|
|
parID := pLongint(CurDirStore)^;
|
|
name := '';
|
|
END; {with}
|
|
lastEdition.theFileScript := LoWrd(GetEnvirons(smSysScript));
|
|
lastEdition.thePart := kPartsNotUsed;
|
|
lastEdition.thePartName := '';
|
|
lastEdition.thePartScript := lastEdition.theFileScript;
|
|
|
|
{ get preference file spec }
|
|
dpGetPreferenceFile(prefFile);
|
|
|
|
{ if preference file exists, use it }
|
|
IF FSpGetFInfo(prefFile, fndrInfo) = noErr THEN
|
|
BEGIN
|
|
{ resolve it to last edition used, use it if found }
|
|
resolveErr := ResolveAliasFile(prefFile, {resolveAliasChains}FALSE, targetIsFolder, wasAliased);
|
|
IF (resolveErr = noErr) OR (resolveErr = fnfErr)
|
|
THEN BlockMove(@prefFile, @lastEdition.theFile, SizeOf(FSSpec)); { lastEdition.theFile := prefFile }
|
|
END; {if}
|
|
|
|
{ when we support parts, we will not be able to use ResolveAliasFile }
|
|
{ because we will need to get to ContainerQualifier at end of alias. }
|
|
END; { dpRetreivedLastContainer }
|
|
|
|
|
|
|
|
|
|
|
|
{------------- dpSaveOffLastContainer -------------}
|
|
PROCEDURE dpSaveOffLastContainer;
|
|
VAR
|
|
saveRes: Integer;
|
|
lastEdition: EditionContainerSpec;
|
|
lastUsedAlias: AliasHandle;
|
|
wasChanged: BOOLEAN;
|
|
ignore: OSErr;
|
|
thePubCB: PubCBHandle;
|
|
prefFile: FSSpec;
|
|
prefResFile: INTEGER;
|
|
fi: FailInfo;
|
|
|
|
PROCEDURE dpSetAliasBitAndType(VAR PBC: CInfoPBRec);
|
|
CONST
|
|
kAliasFlag = $8000;
|
|
BEGIN
|
|
PBC.ioFlFndrInfo.fdFlags := bOr(PBC.ioFlFndrInfo.fdFlags, kAliasFlag);
|
|
WITH thePubCB^^.info DO
|
|
BEGIN
|
|
PBC.ioFlFndrInfo.fdCreator := fdCreator;
|
|
PBC.ioFlFndrInfo.fdType := fdType;
|
|
END; {with}
|
|
END; { SetAliasBit }
|
|
|
|
LABEL 999; { use this to save duplication of code to clean up, between failure handler and end of proc }
|
|
|
|
BEGIN
|
|
thePubCB := dpGetGlobalsLocation^^.lastEditionUsed;
|
|
HLock(Handle(thePubCB));
|
|
saveRes := CurResFile;
|
|
|
|
{ open the preferences file }
|
|
dpGetPreferenceFile(prefFile);
|
|
prefResFile := FSpOpenResFile(prefFile, {permissions}0);
|
|
|
|
{ handle initial case where preference file does not exist or is corrupt }
|
|
IF prefResFile = -1 THEN
|
|
BEGIN
|
|
{ delete corrupted one, or do nothing }
|
|
IgnoreOSErr(FSpDelete(prefFile));
|
|
|
|
{ make a new one with no type or creator }
|
|
FSpCreateResFile(prefFile, ' ', ' ', smSystemScript);
|
|
|
|
{ open it }
|
|
prefResFile := FSpOpenResFile(prefFile, {permissions}0);
|
|
END; {if}
|
|
|
|
{ set up failure handling }
|
|
IF isFailure(fi, ignore)
|
|
THEN GOTO 999;
|
|
|
|
{ if preference file is around then use it }
|
|
IF prefResFile <> -1 THEN
|
|
BEGIN
|
|
{ now update the type and creator }
|
|
IgnoreOSErr(dpTweakCatInfo(prefFile, dpSetAliasBitAndType));
|
|
|
|
{ get the alias record pointing to last edition used }
|
|
lastUsedAlias := AliasHandle(Get1Resource(rAliasType, rLastEditionAliasID));
|
|
|
|
IF lastUsedAlias = NIL THEN
|
|
BEGIN
|
|
{ first time through? create a new alias resource }
|
|
FailOSErr(NewAlias(NIL, thePubCB^^.info.container.theFile, lastUsedAlias));
|
|
AddResource(Handle(lastUsedAlias), rAliasType, rLastEditionAliasID, '');
|
|
END ELSE
|
|
BEGIN
|
|
{ update existing alias resource }
|
|
FailOSErr(UpdateAlias(NIL, thePubCB^^.info.container.theFile, lastUsedAlias, wasChanged));
|
|
END;
|
|
|
|
(*
|
|
{ when we support parts, add the container qualifier to the end of the alias }
|
|
SetHandleSize(Handle(lastUsedAlias), lastUsedAlias^^.aliasSize + SizeOf(ContainerQualifier));
|
|
IF MemError = noErr THEN
|
|
BEGIN
|
|
subPartPtr := pContainerQualifier(pLongint(lastUsedAlias)^ + lastUsedAlias^^.aliasSize);
|
|
subPartPtr^.thePart := lastEdition.thePart;
|
|
{$PUSH} {$R-}
|
|
subPartPtr^.thePartName := lastEdition.thePartName;
|
|
{$POP}
|
|
END; {if}
|
|
*)
|
|
|
|
{ flush changes to disk }
|
|
ChangedResource(Handle(lastUsedAlias));
|
|
END; {if}
|
|
|
|
Success(fi);
|
|
999:
|
|
IF prefResFile <> -1
|
|
THEN CloseResFile(prefResFile);
|
|
HUnLock(Handle(thePubCB));
|
|
UseResFile(saveRes);
|
|
END; { dpSaveOffLastContainer }
|
|
|
|
|
|
|
|
{------------- dp_GetLastEditionContainerUsed -------------}
|
|
FUNCTION dp_GetLastEditionContainerUsed(VAR container: EditionContainerSpec): OSErr;
|
|
VAR
|
|
fndrInfo: FInfo;
|
|
infoErr: OSErr;
|
|
lastPubCB: PubCBHandle;
|
|
BEGIN
|
|
dp_GetLastEditionContainerUsed := noErr;
|
|
|
|
{ get last pub from globals }
|
|
lastPubCB := dpGetGlobalsLocation^^.lastEditionUsed;
|
|
IF lastPubCB <> NIL
|
|
THEN BlockMove(@lastPubCB^^.info.container, @container, SizeOf(EditionContainerSpec)) { container := lastPubCB^^.info.container }
|
|
ELSE dpRetreivedLastContainer(container);
|
|
|
|
{ check that file really exists }
|
|
WITH container.theFile DO
|
|
BEGIN
|
|
infoErr := FSpGetFInfo(container.theFile, fndrInfo);
|
|
IF infoErr <> noErr THEN
|
|
BEGIN
|
|
{ if file does not exist, then don't return it }
|
|
name := '';
|
|
dp_GetLastEditionContainerUsed := fnfErr;
|
|
|
|
{ if folder or volume does not exist, then use current app SF location }
|
|
IF infoErr <> fnfErr THEN
|
|
BEGIN
|
|
vRefNum := -1 * pInteger(SFSaveDisk)^;
|
|
parID := pLongint(CurDirStore)^;
|
|
END;
|
|
END;
|
|
END; {with}
|
|
|
|
END; { dp_GetLastEditionContainerUsed }
|
|
|