Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
MoreFinderEvents.cp
// |
// MoreFinderEvents 1.0 |
// ==================== |
// |
// an AppleEvents package for non-scriptable versions of Finder |
// |
// by Pete Gontier, Apple Macintosh Developer Technical Support |
// |
// Copyright (c) 1996 Apple Computer, Inc., All Rights Reserved. |
// |
// Complaints and kudos to: <gurgle@apple.com> |
// |
// Thanks to Jon Pugh for 'FinderEvents.p' XCMD and code review |
// of this package. |
// |
// INTRODUCTION |
// ============ |
// |
// The AppleEvents API is icky and you probably don't relish the |
// idea of developing an intimate relationship with it. And you |
// don't feel your application should yet require the scriptable |
// Finder, which first shipped in System 7.5. Yet you still want |
// to make Finder do backflips and cartwheels. |
// |
// Enter MoreFinderEvents. |
// |
// This package provides you with a painless API for sending some |
// of the more simple forms of the FinderEvents, which have been |
// with us since System 7.0.0. With this API you can copy a |
// file or open a control panel or empty the trash or any of |
// several other things usually done by Finder at the user's |
// request. |
// |
// THEORY OF OPERATION |
// =================== |
// |
// There's nothing terribly tricky here. We're just using the |
// AppleEvents API along with some simple C++ code to make it |
// a little more palatable. The only thing worth noting is that |
// Finder doesn't use the AppleEvents API on its end. Apparently |
// the Finder which shipped with System 7.0.0 needed to feature- |
// freeze before the AppleEvent Manager, so it has its own code |
// for examining AppleEvents. Since the Finder code is tailored |
// specifically to support FinderEvents, it tends to get cranky |
// when fed data which is not absotively posilutely correct. |
// If you modify this library and Finder starts crashing, that's |
// probably why. |
// |
// BUILDING |
// ======== |
// |
// I wrote this library intermittently over a period of months with |
// with Metrowerks CodeWarrior CW7, CW8, and CW9. Consequently, |
// I don't know for certain whether it compiles with any other |
// compilers, although it's Universal Headers 2.0-savvy and should |
// work just fine. |
// |
// Note that despite the fact that this is C++ code, all entry |
// points (the function prototypes in "MoreFinderEvents.h") are |
// declared 'pascal', meaning you can call this code from C and |
// Pascal. There's no Pascal interface file for this library |
// at the moment primarily because to me an interface file would |
// imply that the author had ported "TestFinderEvents.c" to Pascal |
// to make sure the interface file worked. If someone wants to do |
// that and send me the results, I'll be more than happy to include |
// them in future versions of this package. |
// |
// KNOWN PROBLEMS |
// ============== |
// |
// [1] One of the following two things is true: |
// |
// [a] The handling of 'iconPosition' in |
// 'MFE_DragLow' is buggy. |
// |
// [b] Finder doesn't handle this parameter properly. |
// |
// The practical effect is that the icon lands in an unpredictable |
// position in the destination folder window. |
// |
// [2] Some FinderEvents result in Finder behavior which doesn't |
// work well unless Finder is the front application. For example, |
// you can submit a request to open the Page Setup dialog for a |
// given folder window and Finder will happily open the Printing |
// Manager and the appropriate dialog from the background. When |
// the user brings Finder forward, the dialog won't (always) update |
// properly. Bad. It's not clear what to do about this; some |
// developers would probably rather decide for themselves when to |
// bring Finder forward. I'd love to hear your feedback. |
// |
// [3] It's been suggested you're better off using the scriptable |
// Finder. It's said these older FinderEvents will go away |
// eventually. These things are true, so you should use the |
// scriptable Finder if it's available. See 'd e v e l o p' |
// magazine, issue 20, pages 65 to 78 for details. Does this |
// mean you'll have two chunks of code in your application? |
// Well... er... yes. Maybe someday I'll update this library so |
// that a single call will work regardless of the presence of |
// a scriptable Finder. Wouldn't that be cool? |
// |
// TO DO |
// ===== |
// |
// There are a few events defined in Chapter 8 of the AppleEvents |
// Registry for which I have not yet implemented glue. If you're |
// a squeaky wheel, I'll try to make sure you get some grease. |
// |
// move window |
// size window |
// zoom window |
// set view |
// |
// LEGAL NOTICE |
// ============ |
// |
// You may incorporate this sample code into your applications |
// without restriction. This sample code has been provided "AS |
// IS" and the responsibility for its operation is 100% yours. |
// You are not permitted to redistribute the source as "Apple |
// sample code" after having made changes. If you're going to |
// re-distribute the source, we require that you make it clear |
// in the source that the code was descended from Apple sample |
// code, but that you've made changes. |
// |
#define SystemSevenOrLater 1 |
#define OLDROUTINELOCATIONS 0 |
#define OLDROUTINENAMES 0 |
#include "MoreFinderEvents.h" |
#ifndef __AEREGISTRY__ |
# include <AERegistry.h> |
#endif |
#ifndef __APPLEEVENTS__ |
# include <AppleEvents.h> |
#endif |
#if PRAGMA_ALIGN_SUPPORTED |
# pragma push |
# pragma options align=mac68k |
#endif |
struct MFE_Window |
{ |
long fWindowType; |
DescType fAliasType; |
long fAliasLen; |
AliasRecord fAliasRecord; |
}; |
typedef MFE_Window *MFE_WindowP, **MFE_WindowH; |
struct FinderEvent : public AppleEvent |
{ |
OSErr fErr; |
AppleEvent fReply; |
AESendMode fSendMode; |
FinderEvent (AEEventClass,AEEventID); |
~FinderEvent (void); |
OSErr Send (void); |
}; |
#if PRAGMA_ALIGN_SUPPORTED |
# pragma pop |
#endif |
enum |
{ |
kCreatorCode_Finder = 'MACS', |
kCreatorCode_AtEase = 'mfdr' |
}; |
static pascal OSErr GetCreatorOfFinderLikeProcess (OSType *processSignature) |
{ |
OSErr err = noErr; |
ProcessSerialNumber psn = { kNoProcess, kNoProcess }; |
ProcessInfoRec pir = { sizeof (pir), nil }; |
*processSignature = 0; |
pir.processAppSpec = nil; |
for (;;) |
{ |
err = GetNextProcess (&psn); |
if (err) |
{ |
if (err == procNotFound) err = noErr; |
break; |
} |
err = GetProcessInformation (&psn,&pir); |
if (err) break; |
if (pir.processSignature == kCreatorCode_Finder || |
pir.processSignature == kCreatorCode_AtEase) |
{ |
*processSignature = pir.processSignature; |
break; |
} |
} |
return err; |
} |
///////////////////////////////////////////////////////////////////////////////// |
#pragma mark - |
/* |
// cheap 68K-only debugging tool |
static pascal asm void DisassembleAppleEvent (AEDesc *) |
{ |
MOVE.L (A7)+,A0 |
MOVE.L (A7)+,A1 |
PEA @1 |
DC.W 0xABFF |
JMP (A0) |
@1: DC.B "\p ; aevt rA1" |
} |
*/ |
OSErr FinderEvent::Send (void) |
{ |
return fErr = AESend (this,&fReply,fSendMode,kAENormalPriority,-1,nil,nil); |
} |
FinderEvent::FinderEvent (AEEventClass eventClass, AEEventID eventID) |
{ |
OSType finderLikeProcess; |
descriptorType = typeNull; |
dataHandle = nil; |
fReply.descriptorType = typeNull; |
fReply.dataHandle = nil; |
if (!(fErr = GetCreatorOfFinderLikeProcess (&finderLikeProcess))) |
{ |
AEAddressDesc address; |
if (!(fErr = AECreateDesc (typeApplSignature, &finderLikeProcess, |
sizeof (finderLikeProcess), &address))) |
{ |
OSErr err2 = noErr; |
fErr = AECreateAppleEvent (eventClass,eventID,&address, |
kAutoGenerateReturnID,kAnyTransactionID,this); |
err2 = AEDisposeDesc (&address); |
if (!fErr && !(fErr = err2)) |
{ |
fSendMode = kAENoReply | kAEAlwaysInteract | kAECanSwitchLayer; |
} |
} |
} |
} |
FinderEvent::~FinderEvent (void) |
{ |
if (dataHandle) |
fErr = AEDisposeDesc (this); |
if (fReply.dataHandle) |
fErr = AEDisposeDesc (&fReply); |
} |
///////////////////////////////////////////////////////////////////////////////// |
#pragma mark - |
static pascal OSErr MFE_Simple (AEEventID eventID) |
{ |
OSErr err = noErr; |
FinderEvent finderEvent (kAEFinderEvents,eventID); |
if (!(err = finderEvent.fErr)) |
err = finderEvent.Send ( ); |
return err; |
} |
static pascal OSErr MFE_HideSpecialWindow (OSType aliasUserType) |
{ |
OSErr err = noErr; |
FinderEvent finderEvent (kAEFinderEvents,kAEClose); |
if (!(err = finderEvent.fErr)) |
{ |
MFE_Window finderWindow; |
finderWindow.fWindowType = 0; |
finderWindow.fAliasType = 'find'; |
finderWindow.fAliasLen = 4; |
finderWindow.fAliasRecord.userType = aliasUserType; |
finderWindow.fAliasRecord.aliasSize = 0; |
if (!(err = AEPutParamPtr (&finderEvent, keyDirectObject, |
typeFinderWindow, &finderWindow, sizeof (finderWindow)))) |
err = finderEvent.Send ( ); |
} |
return err; |
} |
static pascal OSErr MFE_ShowSpecialWindow |
(AEEventClass eventClass, AEEventID eventID) |
{ |
FinderEvent finderEvent (eventClass,eventID); |
if (finderEvent.fErr) |
return finderEvent.fErr; |
else |
return finderEvent.Send ( ); |
} |
static pascal OSErr MFE_AddParentAlias |
(FinderEvent &finderEvent, const AliasRecord **aliasH) |
{ |
// |
// The goal here is to add a parent alias to 'finderEvent' as the direct |
// object as specified by the Apple Event Registry. If 'aliasH' is not a |
// volume, we add an alias of the parent of 'aliasH'. If 'aliasH' is a |
// volume, we want to add 'aliasH' itself as the container because lots |
// of events expect that bizarre behavior. We make a new alias to it |
// because we have no way of telling whether the incoming alias is a full |
// alias or not, and Finder demands one (and it tends to throw nasty |
// tantrums if it's not). |
// |
OSErr err = noErr; |
FSSpecPtr fssP = FSSpecPtr (NewPtr (sizeof (FSSpec))); |
if (!(err = MemError ( ))) |
{ |
if (!(err = ::HandToHand ((Handle *) &aliasH))) |
{ |
Boolean wasChanged; |
if (!(err = ResolveAlias (nil, AliasHandle (aliasH), fssP, |
&wasChanged))) // aliasH is a copy |
{ |
if (fssP->parID == fsRtParID || |
!(err = FSMakeFSSpec (fssP->vRefNum, fssP->parID, nil, fssP))) |
{ |
AliasHandle parentAlias; |
if (!(err = NewAlias (nil,fssP,&parentAlias))) |
{ |
HLock (Handle (parentAlias)); |
if (!(err = MemError ( ))) |
{ |
Size parentAliasSize = |
GetHandleSize (Handle (parentAlias)); |
if (!(err = MemError ( ))) |
err = AEPutParamPtr (&finderEvent, keyDirectObject, |
typeAlias, *parentAlias, parentAliasSize); |
} |
DisposeHandle (Handle (parentAlias)); |
} |
} |
} |
::DisposeHandle (Handle (aliasH)); |
if (!err) err = MemError ( ); |
} |
DisposePtr (Ptr (fssP)); |
if (!err) err = MemError ( ); |
} |
return err; |
} |
static pascal OSErr MFE_AddChildAlias |
(AEDescList &selection, const AliasRecord **aliasH) |
{ |
OSErr err = noErr; |
SInt8 hState = HGetState (Handle (aliasH)); |
if (!(err = MemError ( ))) |
{ |
HLock (Handle (aliasH)); |
if (!(err = MemError ( ))) |
{ |
Size aliasSize = GetHandleSize (Handle (aliasH)); |
if (!(err = MemError ( ))) |
{ |
err = AEPutPtr (&selection,0,typeAlias,*aliasH,aliasSize); |
} |
HSetState (Handle (aliasH), hState); |
} |
} |
return err; |
} |
static pascal OSErr MFE_SendSingleSelectionEvent |
(const AliasRecord **aliasH, AEEventID eventID) |
{ |
OSErr err = noErr; |
FinderEvent finderEvent (kAEFinderEvents,eventID); |
if (!(err = finderEvent.fErr)) |
{ |
if (!(err = MFE_AddParentAlias (finderEvent,aliasH))) |
{ |
AEDescList selection = { typeNull, nil }; |
if (!(err = AECreateList (nil,0,false,&selection))) |
{ |
if (!(err = MFE_AddChildAlias (selection,aliasH))) |
if (!(err = AEPutParamDesc (&finderEvent,keySelection, |
&selection))) |
err = finderEvent.Send ( ); |
AEDisposeDesc (&selection); |
} |
} |
} |
return err; |
} |
static pascal OSErr MFE_SendSingleFileEventViaHandle |
(Handle h, AEEventID eventID, DescType descType) |
{ |
OSErr err = noErr; |
FinderEvent finderEvent (kAEFinderEvents,eventID); |
if (!(err = finderEvent.fErr)) |
{ |
SInt8 hState = HGetState (h); |
if (!(err = MemError ( ))) |
{ |
HLock (h); |
if (!(err = MemError ( ))) |
{ |
Size size = GetHandleSize (h); |
if (!(err = MemError ( ))) |
if (!(err = AEPutParamPtr (&finderEvent, keyDirectObject, |
descType, *h, size))) |
err = finderEvent.Send ( ); |
HSetState (h, hState); |
if (!err) err = MemError ( ); |
} |
} |
} |
return err; |
} |
static pascal OSErr MFE_CreateFinderWindowHandle |
(const AliasRecord **aliasH, MFE_WindowH *fwhp, long windowType = 0) |
{ |
OSErr err = noErr; |
Size size = ::GetHandleSize (Handle (aliasH)); |
if (!(err = MemError ( ))) |
{ |
*fwhp = MFE_WindowH (NewHandle (size + sizeof (MFE_Window) - |
sizeof (AliasRecord))); |
if (!(err = MemError ( ))) |
{ |
MFE_Window finderWindow; |
finderWindow.fWindowType = windowType; |
finderWindow.fAliasRecord = **aliasH; |
finderWindow.fAliasType = typeAlias; |
finderWindow.fAliasLen = size; |
MFE_Window *finderWindowP = **fwhp; |
BlockMoveData (*aliasH,&(finderWindowP->fAliasRecord),size); |
*finderWindowP = finderWindow; |
} |
} |
return err; |
} |
static pascal OSErr MFE_SendSimpleFinderWindowEvent |
(const AliasRecord **aliasH, AEEventID eventID, long windowType = 0) |
{ |
OSErr err = noErr; |
MFE_WindowH finderWindowH = nil; |
if (!(err = MFE_CreateFinderWindowHandle (aliasH,&finderWindowH,windowType))) |
{ |
err = MFE_SendSingleFileEventViaHandle (Handle (finderWindowH), |
eventID, typeFinderWindow); |
DisposeHandle (Handle (finderWindowH)); |
if (!err) err = MemError ( ); |
} |
return err; |
} |
static pascal OSErr MFE_AddDestinationAlias |
(const AliasRecord **destAlias, FinderEvent &finderEvent) |
{ |
OSErr err = noErr; |
SInt8 destAliasState = HGetState (Handle (destAlias)); |
if (!(err = MemError ( ))) |
{ |
HLock (Handle (destAlias)); |
if (!(err = MemError ( ))) |
{ |
Size destAliasSize = GetHandleSize (Handle (destAlias)); |
if (!(err = MemError ( ))) |
err = AEPutParamPtr (&finderEvent, keyDirectObject, typeAlias, |
*destAlias, destAliasSize); |
HSetState (Handle (destAlias), destAliasState); |
if (!err) err = MemError ( ); |
} |
} |
return err; |
} |
static pascal OSErr MFE_ResolveAlias (const AliasRecord **aliasH, FSSpecPtr fssP) |
{ |
Boolean dontCare; |
short aliasCount = 1; |
const unsigned long rulesMask = kARMNoUI | kARMSearch; |
return MatchAlias (nil,rulesMask,AliasHandle(aliasH),&aliasCount, |
fssP,&dontCare,nil,nil); |
} |
typedef pascal OSErr (*vParamValidator) |
(const FSSpec &fssToDrag, const FSSpec &fssTarget); |
static pascal OSErr MFE_DragLow |
(AEEventID eventID, vParamValidator validateParams, |
const AliasRecord **aliasToDrag, const AliasRecord **destAlias) |
{ |
OSErr err = noErr; |
// |
// If we need to validate our inputs, allocate two FSSpec records |
// on the heap and resolve the parameter aliases. |
// |
if (validateParams) |
{ |
FSSpecPtr specToDragP = nil; |
FSSpecPtr specDestP = nil; |
do |
{ |
specToDragP = FSSpecPtr (NewPtr (sizeof (FSSpec))); |
err = MemError ( ); if (err) break; |
specDestP = FSSpecPtr (NewPtr (sizeof (FSSpec))); |
err = MemError ( ); if (err) break; |
err = MFE_ResolveAlias (aliasToDrag,specToDragP); |
if (err) break; |
err = MFE_ResolveAlias (destAlias,specDestP); |
if (err) break; |
err = validateParams (*specToDragP,*specDestP); |
} |
while (false); |
if (specToDragP) |
DisposePtr (Ptr (specToDragP)); |
if (specDestP) |
DisposePtr (Ptr (specDestP)); |
} |
// |
// If there were no errors validating our inputs, |
// build and send the event. |
// |
if (!err) |
{ |
AEDescList selection = { typeNull, nil }; |
do |
{ |
FinderEvent finderEvent (kAEFinderEvents,eventID); |
err = finderEvent.fErr; |
if (err) break; |
err = AECreateList (nil,0,false,&selection); |
if (err) break; |
err = MFE_AddChildAlias (selection,aliasToDrag); |
if (err) break; |
err = AEPutParamDesc (&finderEvent,keySelection,&selection); |
if (err) break; |
Point iconPosition = { 0,0 }; // no offset, thank you |
err = AEPutParamPtr (&finderEvent, keyMiscellaneous, typeLongInteger, |
&iconPosition, sizeof (iconPosition)); |
if (err) break; |
err = MFE_AddDestinationAlias (destAlias,finderEvent); |
if (err) break; |
err = finderEvent.Send ( ); |
} |
while (false); |
if (selection.dataHandle) |
AEDisposeDesc (&selection); |
} |
return err; |
} |
///////////////////////////////////////////////////////////////////////////////// |
#pragma mark - |
pascal OSErr MFE_PrintWindow (const AliasRecord **aliasH) |
{ |
return MFE_SendSimpleFinderWindowEvent (aliasH,kAEPrintWindow); |
} |
pascal OSErr MFE_PageSetup (const AliasRecord **aliasH) |
{ |
return MFE_SendSimpleFinderWindowEvent (aliasH,kAEPageSetup); |
} |
pascal OSErr MFE_CloseWindow (const AliasRecord **aliasH) |
{ |
return MFE_SendSimpleFinderWindowEvent (aliasH,kAEClose); |
} |
pascal OSErr MFE_CloseGetInfo (const AliasRecord **aliasH) |
{ |
return MFE_SendSimpleFinderWindowEvent (aliasH,kAEClose,kAEInfo); |
} |
pascal OSErr MFE_CloseSharing (const AliasRecord **aliasH) |
{ |
return MFE_SendSimpleFinderWindowEvent (aliasH,kAEClose,kAESharing); |
} |
pascal OSErr MFE_MakeAlias (const AliasRecord **aliasH) |
{ |
return MFE_SendSingleSelectionEvent (aliasH,kAEAliasSelection); |
} |
pascal OSErr MFE_Duplicate (const AliasRecord **aliasH) |
{ |
return MFE_SendSingleSelectionEvent (aliasH,kAEDuplicateSelection); |
} |
pascal OSErr MFE_OpenSelection (const AliasRecord **aliasH) |
{ |
return MFE_SendSingleSelectionEvent (aliasH,kAEOpenSelection); |
} |
pascal OSErr MFE_PrintSelection (const AliasRecord **aliasH) |
{ |
return MFE_SendSingleSelectionEvent (aliasH,kAEPrintSelection); |
} |
pascal OSErr MFE_OpenGetInfo (const AliasRecord **aliasH) |
{ |
return MFE_SendSingleSelectionEvent (aliasH,kAEGetInfoSelection); |
} |
pascal OSErr MFE_OpenSharing (const AliasRecord **aliasH) |
{ |
return MFE_SendSingleSelectionEvent (aliasH,kAEGetPrivilegeSelection); |
} |
pascal OSErr MFE_Reveal (const AliasRecord **aliasH) |
{ |
return MFE_SendSingleSelectionEvent (aliasH,kAERevealSelection); |
} |
pascal OSErr MFE_PutAway (const AliasRecord **aliasH) |
{ |
return MFE_SendSingleSelectionEvent (aliasH,kAEPutAwaySelection); |
} |
pascal OSErr MFE_UnmountVolume (short vRefNum) |
{ |
FSSpecPtr fssP = (FSSpecPtr) ::NewPtr (sizeof (*fssP)); |
OSErr err = ::MemError ( ); |
if (!err) |
{ |
if (!(err = FSMakeFSSpec (vRefNum, fsRtDirID, "\p", fssP))) |
{ |
AliasHandle aliasH = nil; |
OSErr err = NewAliasMinimal (fssP, &aliasH); |
if (!err) |
{ |
err = MFE_PutAway (aliasH); |
DisposeHandle (Handle (aliasH)); |
if (!err) err = MemError ( ); |
} |
} |
DisposePtr (Ptr (fssP)); |
if (!err) err = MemError ( ); |
} |
return err; |
} |
pascal OSErr MFE_ShowAbout (void) |
{ |
return MFE_ShowSpecialWindow (kCoreEventClass,kAEAbout); |
} |
pascal OSErr MFE_ShowClipboard (void) |
{ |
return MFE_ShowSpecialWindow (kAEFinderEvents,kAEShowClipboard); |
} |
pascal OSErr MFE_HideAbout (void) |
{ |
return MFE_HideSpecialWindow ('abot'); |
} |
pascal OSErr MFE_HideClipboard (void) |
{ |
return MFE_HideSpecialWindow ('clip'); |
} |
#pragma mark - |
pascal OSErr MFE_Sleep (void) |
{ |
return MFE_Simple (kAESleep); |
} |
pascal OSErr MFE_Restart (void) |
{ |
return MFE_Simple (kAERestart); |
} |
pascal OSErr MFE_ShutDown (void) |
{ |
return MFE_Simple (kAEShutDown); |
} |
pascal OSErr MFE_EmptyTrash (void) |
{ |
return MFE_Simple (kAEEmptyTrash); |
} |
#pragma mark - |
static pascal OSErr MFE_CopyParamValidator |
(const FSSpec &fssToDrag, const FSSpec &fssTarget) |
{ |
// |
// Finder does an infinite recursion when you attempt to |
// copy a file over itself. Here we test a file to be moved |
// against a potential destination directory. If they match, |
// we claim we were passed bogus parameters, which isn't a lie. |
// |
OSErr err = noErr; |
CInfoPBPtr cipbp = CInfoPBPtr (NewPtrClear (sizeof (*cipbp))); |
if (!(err = MemError ( ))) |
{ |
cipbp->dirInfo.ioDrDirID = fssTarget.parID; |
cipbp->dirInfo.ioVRefNum = fssTarget.vRefNum; |
cipbp->dirInfo.ioNamePtr = StringPtr (fssTarget.name); |
if (!(err = PBGetCatInfoSync (cipbp))) |
if (fssToDrag.parID == cipbp->dirInfo.ioDrDirID) |
err = paramErr; |
DisposePtr (Ptr (cipbp)); |
if (!err) err = MemError ( ); |
} |
return err; |
} |
static pascal OSErr MFE_MoveParamValidator |
(const FSSpec &fssToDrag, const FSSpec &fssTarget) |
{ |
// |
// Finder will happily attempt (and fail) to move something |
// to a different volume. The item gets moved to the directory |
// with the same ID on the source volume -- if it exists. |
// If it doesn't exist, we never hear about the problem and |
// nothing happens. |
// |
// Also: moving a file onto itself is dumb, so we call the copy |
// validator, which checks this for us. |
// |
OSErr err = noErr; |
if (fssToDrag.vRefNum != fssTarget.vRefNum) |
err = paramErr; |
else |
err = MFE_CopyParamValidator (fssToDrag,fssTarget); |
return err; |
} |
pascal OSErr MFE_Copy |
(const AliasRecord **aliasToDrag, const AliasRecord **destAlias) |
{ |
return MFE_DragLow (kAEDrag,MFE_CopyParamValidator,aliasToDrag,destAlias); |
} |
pascal OSErr MFE_Move |
(const AliasRecord **aliasToDrag, const AliasRecord **destAlias) |
{ |
return MFE_DragLow (kAEMove,MFE_MoveParamValidator,aliasToDrag,destAlias); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14