CDEventsImpl.mesa
Copyright © 1983 by Xerox Corporation. All rights reserved.
by Christian Jacobi September 16, 1983 2:11 pm
last edited by Christian Jacobi March 21, 1986 2:22:52 pm PST
DIRECTORY
CDEvents,
CD,
RefTab;
CDEventsImpl: CEDAR MONITOR
IMPORTS CD, RefTab
EXPORTS CDEvents =
BEGIN
EventProc: TYPE = CDEvents.EventProc;
EventRegistration: TYPE = REF EventRegistrationRep;
EventRegistrationRep: PUBLIC TYPE = RECORD [
event: REF,
eventProcs: EventProcs←NIL,
reverse: BOOLFALSE,
continueOnAbort: BOOLTRUE
];
EventProcs: TYPE = LIST OF RECORD [proc: EventProc, filter: CD.Technology];
eventNameTable: RefTab.Ref ~ RefTab.Create[];
RegisterEventType: PUBLIC PROC [event: REF, reverse: BOOLFALSE, continueOnAbort: BOOLTRUE] RETURNS [EventRegistration] = {
--returns EventRegistration=NIL if eventName is already used.
--the EventRegistration is the key to call ProcessEvent
--if ATOM are used for eventName, include them manual in the list
--on file [ivy]<jacobi>ChipNDale>CDEvents-registration.txt
evr: EventRegistration ← NEW[EventRegistrationRep ← [event: event, reverse: reverse, continueOnAbort: continueOnAbort]];
IF ~RefTab.Insert[eventNameTable, event, evr] THEN ERROR CD.Error[doubleRegistration];
RETURN [evr]
};
GetReg: PROC [event: REF] RETURNS [EventRegistration] = {
WITH event SELECT FROM
evr: EventRegistration => RETURN [evr];
ENDCASE => {
WITH RefTab.Fetch[eventNameTable, event].val SELECT FROM
evr: EventRegistration => RETURN [evr];
ENDCASE => ERROR CD.Error[missingRegistration];
}
};
RegisterEventProc: PUBLIC ENTRY PROC [event: REF, proc: EventProc, filter: CD.Technology←NIL] = {
--registers a procedure which is called each time a specific event occurs
--the procedure might stop certain events with the dont result
--if filter#NIL, proc is only called if event occurs on design of technology=filter
--event must have been previously registered with RegisterEventType
ev: EventRegistration ← GetReg[event];
IF ev.eventProcs=NIL THEN ev.eventProcs←LIST[[proc, filter]]
ELSE IF ev.reverse THEN ev.eventProcs ← CONS[[proc, filter], ev.eventProcs]
ELSE
FOR l: EventProcs ← ev.eventProcs, l.rest DO
IF l.rest=NIL THEN {l.rest←LIST[[proc, filter]]; RETURN}
ENDLOOP
};
ProcessEvent: PUBLIC PROC [eventRegistration: EventRegistration, design: CD.Design, x: REFNIL, listenToDont: BOOLFALSE] RETURNS [dont: BOOLFALSE] = {
IF eventRegistration#NIL THEN
FOR l: EventProcs ← eventRegistration.eventProcs, l.rest WHILE l#NIL DO
IF l.first.filter#NIL AND
(design=NIL OR l.first.filter#design.technology) THEN LOOP;
dont ← l.first.proc[eventRegistration.event, design, x
! ABORTED => IF eventRegistration.continueOnAbort THEN CONTINUE].dont;
IF dont AND listenToDont THEN RETURN;
ENDLOOP
};
END.