{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
{ }
{ GENERIC EVENTS }
{ ``````````````````````````` }
{ }
{ A Generic Utilities unit, for use by any program.
Copyright İ by David Sinclair, 1990 2001.
I am releasing these units to the Pascal community. Feel free to use them in whole or part in your Pascal programs.
You are also welcome to modify these units to suit your needs. If you wish to re-distribute the sources with your changes,
please clearly indicate that you have changed them. In all cases, you must leave these comments and the copyright notice intact.
If you use a significant portion of these units, I would appreciate acknowledgement in your About dialog and/or documentation,
e.g. ³Dejal Generic Utilities copyright İ by David Sinclair, 1990 - 2001.²
Iıd appreciate it if you also e-mail me at if you find these units useful. If you have any questions about
these units, you can e-mail me at that address and I will do my best to help, time permitting. However, these units are provided
³as is² and I do not guarantee their reliablity or suitability for any particular purpose.
These units have been used extensively in my Dejal shareware and freeware products over the years. Most of the code was written
many years ago, and the code and style may not be optimal in all cases, but unless otherwise noted all routines have been used
in released software, so should work as described.
Please visit and try out Dejal QuickEncrypt and/or my other shareware products. If you want to show
your appreciation for these units financially, registrations for my shareware are always welcome! Or you can make a donation to
me via my online order form: .
I hope you find these units useful, and good luck in your Pascal endeavors!
- David Sinclair, Dejal
}
{ * * * }
{ UNIT HISTORY: (Reverse chronology) }
{ }
{ Start finish dates: Comments / changes: }
{ }
{ 27 October 2001 Public release as source code.
5 January 2001 Added the EventGetCurrentProcessFileSpec routine.
25 April 1998 Added the EventOptionDown routine.
16 March 1997 Added the eventOpenDocumentAE and made }
{ eventOpenApplication generic. }
{ 9 March 1997 Added the eventGotRequiredParams function. }
{ 27 January 1997 Added the eventSendOpenURLAE function. }
{ 9 November 1994 Dusted off this old unit as a place to keep useful }
{ low-level or high-level event code, including }
{ Apple event stuff. Also added the }
{ eventSendOpenSelectionAE function. }
{ 20 December 1991 First public release, in library form. }
{ 30 March 1991 Added eventCapsDown. }
{ 23 February 1991 Started the unit off by copying the }
{ eventAnyQueued routine from my old }
{ Generic Utilities file. }
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
UNIT genEvents;
INTERFACE
USES
genToolbox, genNumerics, genStrings;
CONST
kSpacebarKeyCode = $31;
kCommandKeyCode = $37;
kShiftKeyCode = $38;
kCapsLockKeyCode = $39;
kOptionKeyCode = $3A;
kControlKeyCode = $3B;
noAppFound = '';
noBrowserErr = 9701;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION eventAnyQueued: boolean;
FUNCTION eventCapsDown: boolean;
FUNCTION EventOptionDown: Boolean;
FUNCTION EventKeyIsDown(keyCode: Integer): Boolean;
FUNCTION eventGotRequiredParams (anAppleEvent: AppleEvent): OSErr;
FUNCTION EventGetCurrentProcessFileSpec(VAR procSpec: FSSpec): OSErr;
FUNCTION eventSendOpenSelectionAE (fileSpec: FSSpec): osErr;
FUNCTION eventBringFinderToFront: OSErr;
FUNCTION eventBringAppToFront (creator: OSType): OSErr;
FUNCTION eventOpenApplication (creatorsRsrcID: Integer; VAR creator: OSType): OSErr;
FUNCTION eventSendOpenURLAE (creatorsRsrcID: Integer; theURL: Str255): OSErr;
FUNCTION eventSendOpenDocumentAE (creator: OSType; fileSpec: FSSpec): OSErr;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
IMPLEMENTATION
USES
UGenericNumerics;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION eventAnyQueued: boolean;
{ Look through the event queue (low-mem global) }
{ Converted from C by David Sinclair, 5 August 1991. }
VAR
more, any: boolean;
evt: evQElPtr;
BEGIN
more:= true;
any:= false;
evt:= evQElPtr(getEvQHdr^.qHead);
IF evt = NIL THEN
more:= false;
WHILE more DO
BEGIN
IF (evt = NIL) OR (evt = evQElPtr(getEvQHdr^.qTail)) THEN
more:= false;
IF evt^.evtQWhat <> nullEvent THEN
BEGIN
any:= true;
more:= false
END
END;
eventAnyQueued:= any
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
PROCEDURE DebugFindKeyMap;
{Reads the keyboard and finds which key was held down. Call this using the debugger to find out what number to use
with the GetKeys result.}
{Written by David Sinclair, 25 April 1998.}
VAR
theKeyMap: KeyMap;
index: Integer;
BEGIN
GetKeys(theKeyMap);
index:= 1;
WHILE (index < 500) & NOT BitTst(@theKeyMap, index) DO
index:= index+1;
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION eventCapsDown: boolean;
{ Reads the keyboard and returns true if the Caps Lock key is down (pressed). }
{ Written by David Sinclair, 30 March 1991. }
{ NOTE: Ordering of KeyMap bits in Lisa Pascalıs packed array of boolean defines the }
{ high order bit in a byte as bit 7 and the low order bit as bit 0. Therefore, key number 57 }
{ (CAPS LOCK) corresponds to bit 62 in the KeyMap, when viewing the high order bit in }
{ the array as 0 and the low order bit 127. }
CONST
capsLockKey = 62;
VAR
theKeyMap: keyMap;
BEGIN
getKeys(theKeyMap);
eventCapsDown:= bitTst(@theKeyMap, capsLockKey)
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION EventOptionDown: Boolean;
{Reads the keyboard and returns true if the Option key is down (pressed).}
{Written by David Sinclair, 25 April 1998.}
CONST
kOptionKey = 61;
VAR
theKeyMap: KeyMap;
BEGIN
GetKeys(theKeyMap);
EventOptionDown:= BitTst(@theKeyMap, kOptionKey)
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
(* ĥĥ This routine uses the method suggested by THINK Reference... but it isnıt necessary for Pascal!
FUNCTION EventKeyIsDown(keyCode: Integer): Boolean;
{Given a key code, this returns True if that key is down, otherwise False. See THINK Referenceıs
Keyboard Layouts (linked from the GetKeys page) for details of key code values. Several
constants are also available, including kSpacebarKeyCode, kOptionKeyCode, etc.}
VAR
theKeyMap: PACKED ARRAY[0..15] OF SignedByte;
theByte: SignedByte;
theBit: Integer;
BEGIN
GetKeys(KeyMap(theKeyMap));
theByte:= theKeyMap[keyCode DIV 8];
theBit:= (keyCode MOD 8);
EventKeyIsDown:= BTST(theByte,theBit)
END;
*)
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION EventKeyIsDown(keyCode: Integer): Boolean;
{Given a key code, this returns True if that key is down, otherwise False. See THINK Referenceıs
Keyboard Layouts (linked from the GetKeys page) for details of key code values. Several
constants are also available, including kSpacebarKeyCode, kOptionKeyCode, etc.}
VAR
theKeyMap: KeyMap;
BEGIN
GetKeys(theKeyMap);
EventKeyIsDown:= theKeyMap[keyCode]
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION eventGotRequiredParams (anAppleEvent: AppleEvent): OSErr;
{ Checks for a keyMissedKeywordAttr attribute. }
{ From Inside Macintosh volume VI, p647-8. Typed in by David Sinclair, 25 }
{ October 1991; made generic, 9 March 1997. }
VAR
returnedType: descType;
actualSize: size;
myErr: osErr;
BEGIN
myErr:= AEGetAttributePtr(anAppleEvent, keyMissedKeywordAttr, typeWildCard, returnedType, NIL, 0, actualSize);
IF myErr = errAEDescNotFound THEN { You got all the required parameters }
myErr:= noErr
ELSE IF myErr = noErr THEN { You missed a required parameter }
myErr:= errAEEventNotHandled; { Else the call to AEGetAttributePtr failed }
eventGotRequiredParams:= myErr
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION EventGetCurrentProcessFileSpec(VAR procSpec: FSSpec): OSErr;
{This returns the fileSpec of the currently running application.}
VAR
tempInfo: ProcessInfoRec;
psn: ProcessSerialNumber;
err: OSErr;
BEGIN
err:= GetCurrentProcess(psn);
ZeroData(@tempInfo,SizeOf(tempInfo));
tempInfo.processInfoLength:= SizeOf(ProcessInfoRec);
tempInfo.processAppSpec:= @procSpec;
IF err=NoErr THEN
err:= GetProcessInformation(psn,tempInfo);
EventGetCurrentProcessFileSpec:= err
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION findAProcess (creatorToFind, typeToFind: osType; {}
VAR processSN: ProcessSerialNumber): osErr;
{ This runs through the process list looking for the indicated application. Used by }
{ sendOpenSelectionAE, below. }
{ Written by C.K. Haun of Apple Developer Tech Support; converted from C to Pascal }
{ and modified by David Sinclair, 9 November 1994. }
VAR
tempInfo: ProcessInfoRec;
procSpec: FSSpec;
processName: str31;
myErr: osErr;
BEGIN
myErr:= noErr;
{ Nul out the PSN so we're starting at the beginning of the list: }
processSN.lowLongOfPSN:= kNoProcess;
processSN.highLongOfPSN:= kNoProcess;
{ Initialize the process information record: }
tempInfo.processInfoLength:= sizeOf(ProcessInfoRec);
tempInfo.processName:= @processName;
tempInfo.processAppSpec:= @procSpec;
{ Loop through all the processes until we }
{ 1) find the process we want, or }
{ 2) error out because of some reason (usually, no more processes): }
REPEAT
myErr:= GetNextProcess(processSN);
IF myErr = noErr THEN
myErr:= GetProcessInformation(processSN, tempInfo);
UNTIL ((tempInfo.processSignature = creatorToFind) & (tempInfo.processType = longint(typeToFind))) | (myErr <> noErr);
findAProcess:= myErr
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION eventSendOpenSelectionAE (fileSpec: FSSpec): osErr;
{ Causes the Finder to open the specified file (which may be a document or }
{ application). From the sample code comments: This routine will ³send a Finder }
{ OpenSelection event. A Finder OpenSelection allows you to have the Finder }
{ launch an Application, or open a document, which will of course cause the owning }
{ Application to launch and open that document. Kinda just like the user had }
{ double-clicked on the file from a Finder window.² }
{ Written by C.K. Haun of Apple Developer Tech Support; converted from C to Pascal }
{ and modified by David Sinclair, 9 November 1994. }
CONST
aeSelectionKeyword = 'fsel';
aeOpenSelection = 'sope';
kSystemCreator = 'MACS';
kFinderType = 'FNDR';
VAR
aeEvent, replyEvent: AppleEvent; { The event to create & the reply (ignored) }
myAddressDesc, aeDirDesc, listElem: AEDesc; { Some descriptors Iıll need }
dirSpec: FSSpec; { FSSpec for the parentı directory of }
{ the file Iım opening }
fileList: AEDesc; { My list }
process: ProcessSerialNumber; { This will hold the process serial }
{ number of the Finder }
DirAlias, FileAlias: AliasHandle; { Some aliases }
PROCEDURE checkResult (err: osErr);
{ Subroutine to check if an error occured, and exit with the error code if so. }
BEGIN
IF err <> noErr THEN
BEGIN
eventSendOpenSelectionAE:= err;
exit(eventSendOpenSelectionAE);
exitToShell { Paranoia }
END
END;
BEGIN
{ Go find the Finderıs process information, please: }
checkResult(findAProcess(kSystemCreator, kFinderType, process));
{ Create an address descriptor so the AppleEvent manager knows where to send }
{ this event: }
checkResult(AECreateDesc(typeProcessSerialNumber, @process, sizeOf(process), myAddressDesc));
{ Create the empty FinderEvent: }
{ Itıs a Finder FNDRı, Open Selection sopeı event }
checkResult(AECreateAppleEvent(kFinderType, aeOpenSelection, myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID, aeEvent));
{ Make a FSSpec for the parent folder (see the OpenSeletion description in the }
{ AE Registry) using the information in the document FSSpec: }
checkResult(FSMakeFSSpec(fileSpec.vRefNum, fileSpec.parID, null, dirSpec));
checkResult(NewAlias(NIL, dirSpec, DirAlias));
{ Create alias for file: }
checkResult(NewAlias(NIL, fileSpec, FileAlias));
{ Create the file list: }
checkResult(AECreateList(NIL, 0, false, fileList));
{ Create the folder descriptor: }
HLock(Handle(DirAlias));
checkResult(AECreateDesc(typeAlias, ptr(DirAlias^), GetHandleSize(Handle(DirAlias)), aeDirDesc));
HUnlock(Handle(DirAlias));
DisposeHandle(Handle(DirAlias));
{ Put the Directory Desc in the event as the direct object: }
checkResult(AEPutParamDesc(aeEvent, keyDirectObject, aeDirDesc));
{ Done with the desc, kill it: }
checkResult(AEDisposeDesc(aeDirDesc));
{ Create the file descriptor and add to aliasList: }
HLock(Handle(FileAlias));
checkResult(AECreateDesc(typeAlias, ptr(FileAlias^), GetHandleSize(Handle(FileAlias)), listElem));
HLock(Handle(FileAlias));
DisposeHandle(Handle(FileAlias));
checkResult(AEPutDesc(fileList, 0, listElem));
checkResult(AEDisposeDesc(listElem));
{ Add the file alias list to the event: }
checkResult(AEPutParamDesc(aeEvent, aeSelectionKeyword, fileList));
checkResult(AEDisposeDesc(fileList));
{ And now send the event! }
checkResult(AESend(aeEvent, replyEvent, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout, NIL, NIL));
{ And kill the memory used: }
checkResult(AEDisposeDesc(aeEvent));
eventSendOpenSelectionAE:= noErr { If an error occurred, it wouldnıt }
END; { have reached here }
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION eventBringFinderToFront: OSErr;
{ Causes the Finder to be brought to the front when WaitNextEvent is next called. }
{ Written by David Sinclair, 17 August 1995. }
CONST
kSystemCreator = 'MACS';
kFinderType = 'FNDR';
VAR
process: ProcessSerialNumber; { The process seria number of the Finder }
err: OSErr;
BEGIN
err:= findAProcess(kSystemCreator, kFinderType, process);
IF err = NoErr THEN
err:= SetFrontProcess(process);
eventBringFinderToFront:= err
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION eventBringAppToFront (creator: OSType): OSErr;
{ Causes the specified application to be brought to the front when WaitNextEvent is next called, }
{ if it is currently running. If not, an error is returned. }
{ Written by David Sinclair, 27 January 1997. }
VAR
psn: ProcessSerialNumber;
err: OSErr;
BEGIN
err:= FindAProcess(creator, 'APPL', psn);
IF err = noErr THEN
err:= SetFrontProcess(psn);
eventBringAppToFront:= err
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION SearchVolForApp (vRef: Integer; creatorsHdl: OSTypeHandle; searchCreator: OSType; {}
numCreators: Longint; VAR fileSpec: FSSpec; VAR creator: OSType): OSErr;
{ Searches the specified volume for one of the specified applications. Only called by }
{ eventOpenApplication, below. }
VAR
i: Integer;
dPB: DTPBRec;
refNum: Integer;
filename: Str255;
fndrInfo: FInfo;
err: OSErr;
BEGIN
filename:= null;
creator:= noAppFound;
dPB.ioNamePtr:= @filename;
dPB.ioVRefNum:= vRef;
err:= PBDTGetPath(@dPB);
IF err = noErr THEN
BEGIN
refNum:= dPB.ioDTRefNum;
dPB.ioNamePtr:= @filename;
i:= 0;
WHILE (creator = noAppFound) & (i < numCreators) DO
BEGIN
i:= i + 1;
dPB.ioIndex:= 0; { Want the one with the latest creation date }
IF creatorsHdl = NIL THEN
dPB.ioFileCreator:= searchCreator
ELSE
dPB.ioFileCreator:= creatorsHdl^^[i];
err:= PBDTGetAPPLSync(@dPB); { Look for the creator in the desktop database }
IF err = noErr THEN
BEGIN
{ We got the application info, but it is possible that the application has been deleted without the desktop }
{ file being updated. Check to see that the file is still there: }
err:= HGetFInfo(vRef, dPB.ioAPPLParID, filename, fndrInfo);
IF err = noErr THEN
err:= FSMakeFSSpec(vRef, dPB.ioAPPLParID, filename, fileSpec);
IF err = noErr THEN
creator:= dPB.ioFileCreator;
END;
END;
END;
IF err = afpItemNotFound THEN { Not found on this volume }
err:= noErr;
SearchVolForApp:= err
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION eventOpenApplication (creatorsRsrcID: Integer; VAR creator: OSType): OSErr;
{ Finds and opens an application, and returns its creator, or the constant noAppFound if one canıt be }
{ found. The currently running applications are checked first, then if it isnıt running, the desktop }
{ database is scanned for the latest version of the app. Pass the ID of an App#ı resource containing a }
{ list of creator types, or zero to use a creator specified in the creator parameter. If a valid ID is passed, }
{ creator need not be initialised. }
CONST
appListRsrcType = 'App#';
timeoutTicks = 15*60; {Timeout after 15 seconds}
VAR
creatorsHdl: OSTypeHandle;
searchCreator: OSType;
i: Integer;
numCreators: Longint;
fileSpec: FSSpec;
filename: Str31;
vPB: ParamBlockRec;
theEvent: EventRecord;
startTicks: Longint;
ignored: Boolean;
err: OSErr;
BEGIN
err:= noErr;
searchCreator:= creator;
creator:= noAppFound;
creatorsHdl:= NIL;
numCreators:= 1;
IF creatorsRsrcID > 0 THEN
err:= numGetResource(creatorsHdl, appListRsrcType, creatorsRsrcID);
IF err = noErr THEN
BEGIN
IF creatorsHdl <> NIL THEN
BEGIN
numBlindLockHandle(creatorsHdl);
numCreators:= GetHandleSize(Handle(creatorsHdl)) DIV 4;
END;
i:= 0;
WHILE (creator = noAppFound) & (i < numCreators) DO { Search the running processes for one we know about }
BEGIN
i:= i + 1;
IF creatorsHdl <> NIL THEN
searchCreator:= creatorsHdl^^[i];
err:= eventBringAppToFront(searchCreator);
IF err = noErr THEN
creator:= searchCreator;
END;
IF creator = noAppFound THEN { No applications currently running, so search the disks for one to launch }
BEGIN
filename:= null;
vPB.ioVolIndex:= 1;
vPB.ioNamePtr:= @filename;
REPEAT
err:= PBGetVInfoSync(@vPB);
IF err = noErr THEN
err:= SearchVolForApp(vPB.ioVRefNum, creatorsHdl, searchCreator, numCreators, fileSpec, creator);
IF (err = noErr) & (creator <> noAppFound) THEN BEGIN
err:= eventSendOpenSelectionAE(fileSpec);
startTicks:= TickCount;
IF err=noErr THEN REPEAT
ignored:= WaitNextEvent(keyUpMask, theEvent, 120, NIL); { Give the application some time to start up }
UNTIL (eventBringAppToFront(searchCreator)=noErr) | (TickCount > (startTicks+timeoutTicks));
END;
vPB.ioVolIndex:= vPB.ioVolIndex + 1;
UNTIL (err <> noErr) | (creator <> noAppFound);
END;
IF err = nsvErr THEN { Out of volumes to search, havenıt found any applications }
err:= noErr;
IF creatorsHdl <> NIL THEN
numDisposeHandle(creatorsHdl);
END;
eventOpenApplication:= err
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION eventSendOpenURLAE (creatorsRsrcID: Integer; theURL: Str255): OSErr;
{ Sends the OpenURL AE to whatever browser the user uses: it first searches for an open browser, }
{ then if not found, it searches the desktop database. Returns noBrowserErr if no browser could be }
{ found, or some other error value. Note: this routine requires an App#ı resource, containing }
{ creators of known browsers. If you pass zero for creatorsRsrcID, only Netscape will be recognised. }
{ Written by David Sinclair, 27 January 1997. }
VAR
gurlEvt: AppleEvent;
replyEvt: AppleEvent;
creatorDesc: AEAddressDesc;
urlDesc: AEDesc;
creator: OSType;
PROCEDURE CheckResult (err: osErr);
BEGIN
IF err <> noErr THEN
BEGIN
eventSendOpenURLAE:= err;
Exit(eventSendOpenURLAE);
ExitToShell { Paranoia }
END
END;
BEGIN
creator:= 'MOSS';
CheckResult(eventOpenApplication(creatorsRsrcID, creator));
IF creator = noAppFound THEN
CheckResult(noBrowserErr);
CheckResult(AECreateDesc(typeApplSignature, @creator, SizeOf(creator), creatorDesc));
CheckResult(AECreateDesc(typeChar, @theURL[1], Length(theURL), urlDesc));
IF creator = 'MOS!' THEN { NCSA Mosaic has its own ideas for AE URLs }
CheckResult(AECreateAppleEvent('mos!', 'ourl', creatorDesc, kAutoGenerateReturnID, kAnyTransactionID, gurlEvt))
ELSE
CheckResult(AECreateAppleEvent('GURL', 'GURL', creatorDesc, kAutoGenerateReturnID, kAnyTransactionID, gurlEvt));
CheckResult(AEDisposeDesc(creatorDesc));
CheckResult(AEPutParamDesc(gurlEvt, keyDirectObject, urlDesc));
CheckResult(AEDisposeDesc(urlDesc));
CheckResult(AESend(gurlEvt, replyEvt, kAEWaitReply + kAECanInteract + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout, NIL, NIL));
CheckResult(AEDisposeDesc(gurlEvt));
CheckResult(AEDisposeDesc(replyEvt));
eventSendOpenURLAE:= noErr { If an error occurred, it wouldnıt have reached here }
END;
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
FUNCTION eventSendOpenDocumentAE (creator: OSType; fileSpec: FSSpec): OSErr;
{ Passes the specified fileSpec to the specified application. The application is opened first, if necessary }
{ (via eventOpenApplication). Use eventSendOpenSelectionAE instead of this for normal documents, }
{ but this routine can be used where the file has a different creator than the creator parameter, e.g. to }
{ simulate dropping another application on an app, or a foreign document type. }
{ Written by David Sinclair, 16 March 1997, based on the eventSendOpenSelectionAE routine. }
CONST
aeSelectionKeyword = 'fsel';
kAppType = 'APPL';
VAR
aeEvent, replyEvent: AppleEvent; { The event to create & the reply (ignored) }
myAddressDesc, listElem: AEDesc; { Some descriptors Iıll need }
fileList: AEDesc; { My list }
process: ProcessSerialNumber; { This will hold the process serial number of the application }
FileAlias: AliasHandle; { An alias of the file }
PROCEDURE checkResult (err: OSErr);
{ Subroutine to check if an error occured, and exit with the error code if so. }
BEGIN
IF err <> noErr THEN
BEGIN
eventSendOpenDocumentAE:= err;
exit(eventSendOpenDocumentAE);
ExitToShell { Paranoia }
END
END;
BEGIN
{ Open the application first: }
CheckResult(eventOpenApplication(0, creator));
{ Go find the appıs process information, please: }
CheckResult(FindAProcess(creator, kAppType, process));
{ Create an address descriptor so the AppleEvent manager knows where to send }
{ this event: }
CheckResult(AECreateDesc(typeProcessSerialNumber, @process, SizeOf(process), myAddressDesc));
{ Create the empty Apple event: }
CheckResult(AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID, aeEvent));
{ Create alias for file: }
CheckResult(NewAlias(NIL, fileSpec, FileAlias));
{ Create the file list: }
CheckResult(AECreateList(NIL, 0, false, fileList));
{ Create the file descriptor and add to aliasList: }
HLock(Handle(FileAlias));
CheckResult(AECreateDesc(typeAlias, Ptr(FileAlias^), GetHandleSize(Handle(FileAlias)), listElem));
HLock(Handle(FileAlias));
DisposeHandle(Handle(FileAlias));
CheckResult(AEPutDesc(fileList, 0, listElem));
CheckResult(AEDisposeDesc(listElem));
{ Add the file alias list to the event: }
CheckResult(AEPutParamDesc(aeEvent, keyDirectObject, fileList));
CheckResult(AEDisposeDesc(fileList));
{ And now send the event! }
CheckResult(AESend(aeEvent, replyEvent, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout, NIL, NIL));
{ And kill the memory used: }
CheckResult(AEDisposeDesc(aeEvent));
eventSendOpenDocumentAE:= noErr { If an error occurred, it wouldnıt }
END; { have reached here }
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
{--------------------------------|--------------------------------------------------------------------|---------------------------------------------------------|------------------------}
END.