boot3/ProcessMgr/PackageMgrPatches.c
Elliot Nunn 5b0f0cc134 Bring in CubeE sources
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.
2017-12-26 10:02:57 +08:00

247 lines
7.9 KiB
C

/*
File: PackageMgrPatches.c
Contains: Routines which patch the Package Manager traps.
Written by: Erich Ringewald
Copyright: © 1986-1992 by Apple Computer, Inc., all rights reserved.
Change History (most recent first):
<3> 3/31/92 DCL Include StandardFile. Because it was removed from Packages.h
<0> x/xx/86 ELR New Today.
*/
#include <types.h>
#include <memory.h>
#include <quickdraw.h>
#include <fonts.h>
#include <events.h>
#include <dialogs.h>
#include <desk.h>
#include <resources.h>
#include <osutils.h>
#include <packages.h>
#include <standardfile.h>
#include <retrace.h>
#include <menus.h>
#include <windows.h>
#include <files.h>
#include <toolutils.h>
#include <segload.h>
#include <AppleEventsInternal.h>
#include "Glue.h"
#include "Lomem.h"
#include "Data.h"
#include "SysMisc.h"
#include "Patches.h"
#include "Puppet.h"
/************************************************************************************
* Patch to SFGetFile/SFPGetFile (PACK3 selectors) for puppet string Open. This patch
* is reached after we have told the application that there was a mousedown in the menu
* bar, and then that the user selected the "OpenÉ" item from the menu. The application
* calls PACK3, which we patch to come here. Instead of the usual modal dialog, we
* just return a specification for the file being puppet Open'd. Of course, we have to
* go through the normal hoops, like checking the type list and calling the file filter.
* NOTE: This only works with the older-style SFGetFiles that employ a Working Directory.
* The newer FSSpec-based ones are not supported, since callers using them should also
* be AppleEvent-aware, and therefore never require puppet-stringing.
************************************************************************************/
/* Some function prototypes that should be in (yet another) header file */
OSErr FileIDToAppFile(AETFDescriptor *, AppFile *, short *, long *);
void NextListParam(AETFDescriptor **);
/* Function prototypes for the application routines called by the SFGetFile handler. */
typedef pascal short (*DialogHookPtr) (short item, Ptr theDialog);
typedef pascal Boolean (*FileFilterFncPtr) (FileParam *paramBlockPtr);
/* We truncate the file names we hand back, since they are generated by puppet master. */
#define MAX_SF_FNAME_LEN (63)
/* InTypeList. Check whether the puppet file is in the typelist given to SFGetFile. */
Boolean
InTypeList(long fType, SFTypeList *pSFTypeList, short numTypes)
{
/* count of zero means all types are OK */
if (numTypes == (-1))
return(true);
/* traverse the array until type matches or the count is exhausted */
while (--numTypes >= 0)
if ((*pSFTypeList)[numTypes] == fType)
return(true);
/* Ze count he eez tired */
return(false);
}
/* AcceptedByFileFilter. Call the filter, and return whether the file is OK. */
short
AcceptedByFileFilter(AppFile *pActiveDoc, Ptr fileFilterFnc)
{
CInfoPBRec myCInfoPBRec;
unsigned long olda5;
Boolean retval;
if (fileFilterFnc == nil)
return true;
/* Get catalog info required by the filter */
myCInfoPBRec.dirInfo.ioNamePtr = &pActiveDoc->fName;
myCInfoPBRec.dirInfo.ioVRefNum = pActiveDoc->vRefNum;
myCInfoPBRec.dirInfo.ioFDirIndex = 0;
myCInfoPBRec.dirInfo.ioDrDirID = 0;
if (PBGetCatInfo(&myCInfoPBRec, SyncHFS) != noErr)
return(false);
/* Filter returns whether should be filtered! Our return value has inverse sense. */
olda5 = CurrentA5SimpleSetup();
retval = (CALL_FNC_PTR(FileFilterFncPtr, fileFilterFnc, (&myCInfoPBRec)) == false);
A5SimpleRestore(olda5);
return(retval);
}
/* CopyWDToCurProc. Given an existing Working Directory refnum, open a new WD for the
* same directory. The new copy is needed because a) the puppet master might close the
* original, and b) WDs are tagged by HFS to the process that opened them, and
* closes them when the process goes away.
*/
void
CopyWDToCurProc(short wdRefNumSrc, WDPBRec *pWDPB)
{
pWDPB->ioVRefNum = wdRefNumSrc;
pWDPB->ioWDIndex = 0;
pWDPB->ioWDProcID = 0;
pWDPB->ioNamePtr = nil;
pWDPB->ioCompletion = nil;
PBGetWDInfo(pWDPB, SyncHFS);
pWDPB->ioVRefNum = pWDPB->ioWDVRefNum;
pWDPB->ioWDProcID = 0;
pWDPB->ioNamePtr = nil;
pWDPB->ioCompletion = nil;
(void) PBOpenWD(pWDPB, SyncHFS);
}
/* IsForcedOpen. The main patch to SFGetFile. If the call to SFGetFile is to get a
* puppet file opened, set up the puppet file specification. Returns whether this
* was done.
*/
Boolean
IsForcedOpen(Ptr fileFilterFnc, short numTypes, Ptr dlgHook, SFTypeList *pSFTypeList, SFReply *pSFReply, short dlgID)
{
AppFile *pActiveDoc;
EventListPtr activeInstrsPtr;
EventListHdl activeInstrsHdl;
EventRecord *pActiveEvent;
Boolean isForcedOpen;
PuppetVars *myPuppetVarsPtr;
MFmsgBlkPtr msgBlk;
WDPBRec wdpbRec;
AppFile appFile;
short theVol;
long theDir;
long strLengthPlus1;
DialogPtr pDialog;
unsigned long olda5;
isForcedOpen = false;
olda5 = ProcessMgrA5SimpleSetup();
if (InstrsQueueIsEmpty() == false)
if ((activeInstrsHdl = GetActiveInstrsHdl()) != nil)
{
HLock(activeInstrsHdl);
activeInstrsPtr = *activeInstrsHdl;
/* Since we really look at the instruction preceding the current one */
assert((unsigned long)activeInstrsPtr->offset >= (SIZEOF_EVENTLIST_HDR + sizeof(EventRecord)));
pActiveEvent = ((Ptr) activeInstrsPtr) + (unsigned long)activeInstrsPtr->offset;
pActiveEvent--;
if (*((char *)&pActiveEvent->what + 1) == app4Evt && (*((char *)&pActiveEvent->message) == instrOpen))
{
isForcedOpen = true;
/* Make pActiveDoc->vRefNum a valid WD for the current process. Copy
* it from current WD, or open it from translation vrefnum/dirid.
*/
myPuppetVarsPtr = &pCurrentProcess->p_puppetvars;
if ((msgBlk = myPuppetVarsPtr->puppetEppcMsgBlk) == nil)
{
pActiveDoc = ((Ptr) activeInstrsPtr) + (pActiveEvent->message & LO3BYTES);
CopyWDToCurProc(pActiveDoc->vRefNum, &wdpbRec);
}
else
{
pActiveDoc = nil;
if (FileIDToAppFile((AETFDescriptor *) (msgBlk->addrOfMsg), &appFile, &theVol, &theDir) == noErr)
{
NextListParam((AETFDescriptor **) &msgBlk->addrOfMsg);
wdpbRec.ioNamePtr = nil;
wdpbRec.ioVRefNum = theVol;
wdpbRec.ioWDProcID = 0;
wdpbRec.ioWDDirID = theDir;
wdpbRec.ioCompletion = nil;
(void) PBOpenWD(&wdpbRec, SyncHFS);
appFile.vRefNum = wdpbRec.ioVRefNum;
pActiveDoc = &appFile;
}
}
pSFReply->vRefNum = wdpbRec.ioVRefNum;
if ( (pActiveDoc != nil)
&& (InTypeList(pActiveDoc->fType, pSFTypeList, numTypes) && AcceptedByFileFilter(pActiveDoc, fileFilterFnc)) )
{
/* Call word dialog hook to clear r/o flag */
if (dlgHook != nil)
{
/* Fake out word <= 3.01 to not make the doc r/o by giving it an extra init call */
pDialog = GetNewDialog(dlgID, nil, (Ptr)(-1));
if (pDialog)
{
(void) CurrentA5SimpleSetup();
CALL_FNC_PTR(DialogHookPtr, dlgHook, (-1, pDialog));
(void) ProcessMgrA5SimpleSetup();
DisposDialog(pDialog);
}
}
pSFReply->good = true;
pSFReply->fType = pActiveDoc->fType;
pSFReply->version = pActiveDoc->versNum;
if ((strLengthPlus1 = Length(&(pActiveDoc->fName)) + 1) > (MAX_SF_FNAME_LEN + 1))
strLengthPlus1 = MAX_SF_FNAME_LEN + 1;
BlockMove(&pActiveDoc->fName, &pSFReply->fName, strLengthPlus1);
}
else
{
/* Tell sawdust-head that the PACK 3 failed */
pSFReply->good = false;
/* Shouldn't cancel, and needn't close WD, if the file translation failed */
if (pActiveDoc != nil)
{
/* Close the WD, if we opened it */
if (wdpbRec.ioWDCreated != 0)
PBCloseWD(&wdpbRec, SyncHFS);
/* Force back to offending instruction, then cancel */
activeInstrsPtr->offset -= sizeof(EventRecord);
CancelSwitchWithError();
}
}
}
HUnlock(activeInstrsHdl);
}
A5SimpleRestore(olda5);
return(isForcedOpen);
}