Solution code for sending high level events when the target application is scriptable:
//========================================
// Author: Cliff Huylebroeck
// ---------------------------
// Category: 68K code resources
// Project: BackEventsINIT
// File: BackEventsINIT.h
// Implemen: BackEventsINIT.cp
//========================================
#pragma once
int main();
bool Run();
void InstallPatches();
pascal Boolean New_GetNextEvent(EventMask mask,
EventRecord *event);
pascal Boolean New_WaitNextEvent(EventMask mask,
EventRecord *event,
UInt32 sleep,
RgnHandle mouseRgn);
void Dispatch(Boolean hasEvent,
EventRecord &event);
void Process_keyDown(EventRecord &event);
bool MakeAndSendAppleEvent(const AEAddressDesc &target);
//========================================
// Author: Cliff Huylebroeck
// ---------------------------
// Category: 68K code resources
// Project: BackEventsINIT
// File: BackEventsINIT.cp
//========================================
#include "BackEventsINIT.h"
// Rem: This extension stops working when you quit the target application.
// Rem: The next includes may not be precompiled
// because they contain inline assembler.
#include <A4Stuff.h>
#include <SetupA4.h>
// Rem: If I type F8 then the Finder must show the about window.
// F8.
const UInt8 bad_charCode=16;
const UInt8 bad_keyCode=100;
const UInt16 bad_modifiers=128;
typedef pascal Boolean (*GetNextEventProcPtr)(EventMask mask,
EventRecord *event);
typedef pascal Boolean (*WaitNextEventProcPtr)(EventMask mask,
EventRecord *event,
UInt32 sleep,
RgnHandle mouseRgn);
GetNextEventProcPtr old_GetNextEvent;
WaitNextEventProcPtr old_WaitNextEvent;
int main()
{
EnterCodeResource();
PrepareCallback();
const SInt16 iconID=Run() ? goodIconID : badIconID;
DrawINITIcon(iconID);
ExitCodeResource();
return 0;
}
bool Run()
{
// 1. Me.
Handle me;
if (!GetINITHandle(me))
{
return false;
}
// 2. Init.
old_GetNextEvent=nil;
old_WaitNextEvent=nil;
// 3. Patches.
InstallPatches();
return true;
}
void InstallPatches()
{
ProcPtr old_address;
ProcPtr new_address;
old_address=::GetToolTrapAddress(_GetNextEvent);
old_GetNextEvent=reinterpret_cast<GetNextEventProcPtr>(old_address);
new_address=reinterpret_cast<UniversalProcPtr>(New_GetNextEvent);
::SetToolTrapAddress(new_address,
_GetNextEvent);
old_address=::GetToolTrapAddress(_WaitNextEvent);
old_WaitNextEvent=reinterpret_cast<WaitNextEventProcPtr>(old_address);
new_address=reinterpret_cast<UniversalProcPtr>(New_WaitNextEvent);
::SetToolTrapAddress(new_address,
_WaitNextEvent);
}
pascal Boolean New_GetNextEvent(const EventMask mask,
EventRecord* const event)
{
Boolean hasEvent;
const SInt32 oldA4=SetUpA4();
hasEvent=old_GetNextEvent(mask,
event);
Dispatch(hasEvent,
*event);
RestoreA4(oldA4);
return hasEvent;
}
pascal Boolean New_WaitNextEvent(const EventMask mask,
EventRecord* const event,
const UInt32 sleep,
RgnHandle const mouseRgn)
{
Boolean hasEvent;
const SInt32 oldA4=SetUpA4();
hasEvent=old_WaitNextEvent(mask,
event,
sleep,
mouseRgn);
Dispatch(hasEvent,
*event);
RestoreA4(oldA4);
return hasEvent;
}
void Dispatch(const Boolean hasEvent,
EventRecord &event)
{
if (!hasEvent)
{
return;
}
switch (event.what)
{
case keyDown:
{
Process_keyDown(event);
break;
}
}
}
void Process_keyDown(EventRecord &event)
{
if (event.modifiers!=bad_modifiers)
{
return;
}
StringPtr const keyMap=reinterpret_cast<StringPtr>(&event.message);
UInt8 &keyCode=keyMap[2];
if (keyCode!=bad_keyCode)
{
return;
}
UInt8 &charCode=keyMap[3];
if (charCode!=bad_charCode)
{
return;
}
event.what=nullEvent;
const OSType finderCreator='MACS';
AEAddressDesc target;
OSErr err=::AECreateDesc(typeApplSignature,
&finderCreator,
sizeof(OSType),
&target);
if (err)
{
// Rem: Not much that we can do here.
return;
}
const bool ok=MakeAndSendAppleEvent(target);
err=::AEDisposeDesc(&target);
if (err)
{
// Rem: Not much that we can do here.
return;
}
if (!ok)
{
// Rem: Not much that we can do here.
return;
}
}
bool MakeAndSendAppleEvent(const AEAddressDesc &target)
{
AppleEvent appleEvent;
appleEvent.descriptorType=typeNull;
appleEvent.dataHandle=nil;
OSErr err=::AECreateAppleEvent(kCoreEventClass,
kAEAbout,
&target,
kAutoGenerateReturnID,
kAnyTransactionID,
&appleEvent);
if (err)
{
return false;
}
const OSErr err_send=::AESend(&appleEvent,
nil,
kAENoReply bitor kAEAlwaysInteract bitor kAECanSwitchLayer,
kAENormalPriority,
kAEDefaultTimeout,
nil,
nil);
err=::AEDisposeDesc(&appleEvent);
if (err)
{
return false;
}
if (err_send)
{
return false;
}
return true;
}
If you want to use this then I recommend to make a PPC version. Be aware that the extension stops working when you quit the target application.