added Jump instruction for safe removal. this is a dead-end, because update events can't be gotten reliably.

This commit is contained in:
beard%netscape.com 1999-03-20 04:08:04 +00:00
Родитель 7684bc079c
Коммит 3ea5b551a6
1 изменённых файлов: 82 добавлений и 17 удалений

Просмотреть файл

@ -27,41 +27,106 @@
#include "jGNE.h" #include "jGNE.h"
#include <MixedMode.h> #include <MixedMode.h>
#include <Memory.h>
#include <LowMem.h> #include <LowMem.h>
#include <TextUtils.h>
/**
* A 68K jump vector.
*/
#pragma options align=mac68k
struct Jump {
unsigned short jmp;
UniversalProcPtr addr;
};
#pragma options align=reset
static void GNEFilter(EventRecord *event, Boolean* result); static void GNEFilter(EventRecord *event, Boolean* result);
static RoutineDescriptor theGNEFilterUPP = BUILD_ROUTINE_DESCRIPTOR(uppGetNextEventFilterProcInfo, GNEFilter); static RoutineDescriptor theGNEFilterDescriptor = BUILD_ROUTINE_DESCRIPTOR(uppGetNextEventFilterProcInfo, GNEFilter);
static GetNextEventFilterUPP theGetNextEventFilterUPP = NULL; static Jump* theGNEFilterJump;
static GetNextEventFilterUPP theOldGNEFilterUPP = NULL;
static EventFilterProcPtr theEventFilter = NULL; static EventFilterProcPtr theEventFilter = NULL;
static Str63 theAppName;
OSStatus InstallEventFilter(EventFilterProcPtr filter) OSStatus InstallEventFilter(EventFilterProcPtr filter)
{ {
theEventFilter = filter; if (theEventFilter == NULL) {
theEventFilter = filter;
// get previous event filter routine. // record the current application's name.
theGetNextEventFilterUPP = LMGetGNEFilter(); StringPtr currentAppName = LMGetCurApName();
LMSetGNEFilter(&theGNEFilterUPP); ::BlockMoveData(currentAppName, theAppName, 1 + currentAppName[0]);
return noErr; // allocate a jump vector in the System heap, so it will be retained after termination.
if (theGNEFilterJump == NULL) {
theGNEFilterJump = (Jump*) NewPtrSys(sizeof(Jump));
if (theGNEFilterJump == NULL)
return MemError();
theGNEFilterJump->jmp = 0x4EF9;
theGNEFilterJump->addr = &theGNEFilterDescriptor;
// get previous event filter routine.
theOldGNEFilterUPP = LMGetGNEFilter();
LMSetGNEFilter(GetNextEventFilterUPP(theGNEFilterJump));
} else {
// our previously allocated Jump is still installed, use it.
theOldGNEFilterUPP = theGNEFilterJump->addr;
theGNEFilterJump->addr = &theGNEFilterDescriptor;
}
return noErr;
}
return paramErr;
} }
OSStatus RemoveEventFilter() OSStatus RemoveEventFilter()
{ {
// should really check to see if somebody else has installed a filter proc as well. if (theEventFilter != NULL) {
LMSetGNEFilter(theGetNextEventFilterUPP); // It's only truly safe to remove our filter, if nobody else installed one after us.
theGetNextEventFilterUPP = NULL; if (LMGetGNEFilter() == GetNextEventFilterUPP(theGNEFilterJump)) {
theEventFilter = NULL; // can safely restore the old filter.
return noErr; LMSetGNEFilter(theOldGNEFilterUPP);
DisposePtr(Ptr(theGNEFilterJump));
theGNEFilterJump = NULL;
} else {
// modify the jump instruction to point to the previous filter.
theGNEFilterJump->addr = theOldGNEFilterUPP;
}
theOldGNEFilterUPP = NULL;
theEventFilter = NULL;
return noErr;
}
return paramErr;
} }
static void GNEFilter(EventRecord *event, Boolean* result) static void GNEFilter(EventRecord *event, Boolean* result)
{ {
// call next filter in chain first. // call next filter in chain first.
if (theGetNextEventFilterUPP) if (theOldGNEFilterUPP != NULL)
CallGetNextEventFilterProc(theGetNextEventFilterUPP, event, result); CallGetNextEventFilterProc(theOldGNEFilterUPP, event, result);
// now, let the filter proc have a crack at the event. // now, let the filter proc have a crack at the event.
if (*result) if (*result) {
*result = !theEventFilter(event); // only call the filter if called in the current application's context.
/* if (::EqualString(theAppName, LMGetCurApName(), true, true)) */
{
// prevent recursive calls to the filter.
static Boolean inFilter = false;
if (! inFilter) {
inFilter = true;
Boolean filteredEvent = theEventFilter(event);
if (filteredEvent) {
// consume the event by making it a nullEvent.
event->what = nullEvent;
*result = false;
}
inFilter = false;
}
}
}
} }