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
];
EventProcs: TYPE = LIST OF RECORD [proc: EventProc, filter: CD.Technology];
eventNameTable: RefTab.Ref ~ RefTab.Create[];
RegisterEventType:
PUBLIC
PROC [eventName:
REF]
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
BEGIN
ev: EventRegistration←NEW[EventRegistrationRep←[event: eventName]];
IF ~RefTab.Insert[eventNameTable, eventName, ev] THEN ev←NIL;
IF ev=NIL THEN ERROR CD.Error[doubleRegistration];
RETURN [ev]
END;
GetReg:
PROC [event:
REF]
RETURNS [ev: EventRegistration] =
BEGIN
WITH event
SELECT
FROM
ev: EventRegistration => RETURN [ev];
ENDCASE => {
WITH RefTab.Fetch[eventNameTable, event].val
SELECT
FROM
ev: EventRegistration => RETURN [ev];
ENDCASE => ERROR CD.Error[missingRegistration];
}
END;
RegisterEventProc:
PUBLIC
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
BEGIN
ev: EventRegistration ← GetReg[event];
--insert new proc at end!
--(then first registered procedures are called first)
--application procedures are called after ChipNDale kernel procedures
IF ev.eventProcs=NIL THEN ev.eventProcs←LIST[[proc, filter]]
ELSE
FOR l: EventProcs ← ev.eventProcs, l.rest DO
IF l.rest=NIL THEN {l.rest←LIST[[proc, filter]]; RETURN}
ENDLOOP
END;
ProcessEvent:
PUBLIC
PROC [ev: EventRegistration, design:
CD.Design, x:
REF←
NIL,
listenToDont: BOOL←FALSE]
RETURNS [dont: BOOL←FALSE] =
--called on certain events
--can be called only if the EventRegistration is known
BEGIN
IF ev#
NIL
THEN
FOR l: EventProcs ← ev.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[ev.event, design, x ! ABORTED => CONTINUE].dont;
IF dont AND listenToDont THEN RETURN;
ENDLOOP
END;
END.