[Indigo]<Rosemary>Release>Rosemary2.DF=>RoseEventsImpl.Mesa
Last Edited by: Spreitzer, May 1, 1984 4:14:26 pm PDT
DIRECTORY Atom, IO, List, RoseEvents, RoseTypes;
RoseEventsImpl:
CEDAR
PROGRAM
IMPORTS Atom, IO, List
EXPORTS RoseEvents, RoseTypes =
BEGIN OPEN RoseTypes;
Error: PUBLIC ERROR [msg: ROPE, data: REF ANY ← NIL] = CODE;
Warning: PUBLIC SIGNAL [msg: ROPE, data: REF ANY ← NIL] = CODE;
Stop: PUBLIC SIGNAL [msg: ROPE, data: REF ANY ← NIL] = CODE;
watchersKey: ATOM ← Atom.MakeAtom["Spreitzer January 6, 1984 8:07 pm"];
AddWatcher:
PUBLIC
PROC [event:
ATOM, watcher: Watcher, watched:
REF
ANY ←
NIL] =
BEGIN
wll: AList;
wl: WatcherList;
IF watched #
NIL
THEN
WITH watched
SELECT
FROM
node: Node => {
Add: PROC [priority: Priority] = {node.watchers[priority] ← CONS[watcher, node.watchers[priority]]};
SELECT event
FROM
$ChangeEarly => Add[high];
$ChangeLate => Add[ordinary];
ENDCASE =>
BEGIN
wl ← NARROW[List.Assoc[key: event, aList: node.props]];
wl ← CONS[watcher, wl];
node.props ← List.PutAssoc[key: event, val: wl, aList: node.props];
END;
RETURN};
cell: Cell => {
SELECT event
FROM
$Schedule => {
IF cell.type = Shadow
THEN
ERROR Error[
IO.PutFR["Cell %g not Real",
IO.rope[cell.name]]];
cell.realCellStuff.schedWatchers ← CONS[watcher, cell.realCellStuff.schedWatchers]};
$Eval => {
IF cell.type = Shadow
THEN
ERROR Error[
IO.PutFR["Cell %g not Real",
IO.rope[cell.name]]];
cell.realCellStuff.evalWatchers ← CONS[watcher, cell.realCellStuff.evalWatchers]};
ENDCASE =>
BEGIN
wl ← NARROW[List.Assoc[key: event, aList: cell.props]];
wl ← CONS[watcher, wl];
cell.props ← List.PutAssoc[key: event, val: wl, aList: cell.props];
END;
RETURN};
ENDCASE;
wll ← NARROW[Atom.GetProp[atom: event, prop: watchersKey]];
wl ← NARROW[List.Assoc[key: watched, aList: wll]];
wl ← CONS[watcher, wl];
wll ← List.PutAssoc[key: watched, val: wl, aList: wll];
Atom.PutProp[atom: event, prop: watchersKey, val: wll];
END;
RemoveWatcher:
PUBLIC
PROC [event:
ATOM, watcher: Watcher, watched:
REF
ANY ←
NIL] =
BEGIN
wll: AList;
wl: WatcherList;
IF watched #
NIL
THEN
WITH watched
SELECT
FROM
node: Node => {
Sub: PROC [priority: Priority] = {node.watchers[priority] ← FilterWatcher[watcher, node.watchers[priority]]};
SELECT event
FROM
$ChangeEarly => Sub[high];
$ChangeLate => Sub[ordinary];
ENDCASE =>
BEGIN
wl ← NARROW[List.Assoc[key: event, aList: node.props]];
wl ← FilterWatcher[watcher, wl];
node.props ← List.PutAssoc[key: event, val: wl, aList: node.props];
END;
RETURN};
cell: Cell => {
SELECT event
FROM
$Schedule => {cell.realCellStuff.schedWatchers ← FilterWatcher[watcher, cell.realCellStuff.schedWatchers]};
$Eval => {cell.realCellStuff.evalWatchers ← FilterWatcher[watcher, cell.realCellStuff.evalWatchers]};
ENDCASE =>
BEGIN
wl ← NARROW[List.Assoc[key: event, aList: cell.props]];
wl ← FilterWatcher[watcher, wl];
cell.props ← List.PutAssoc[key: event, val: wl, aList: cell.props];
END;
RETURN};
ENDCASE;
wll ← NARROW[Atom.GetProp[atom: event, prop: watchersKey]];
wl ← NARROW[List.Assoc[key: watched, aList: wll]];
wl ← FilterWatcher[watcher, wl];
wll ← List.PutAssoc[key: watched, val: wl, aList: wll];
Atom.PutProp[atom: event, prop: watchersKey, val: wll];
END;
FilterWatcher:
PROC [watcher: Watcher, watchers: WatcherList]
RETURNS [ohne: WatcherList] =
BEGIN
cur, prev: WatcherList ← NIL;
ohne ← watchers;
FOR cur ← watchers, cur.rest
WHILE cur #
NIL
DO
IF cur.first = watcher
THEN
{IF prev = NIL THEN ohne ← cur.rest ELSE prev.rest ← cur.rest;
RETURN};
prev ← cur;
ENDLOOP;
END;
Notify:
PUBLIC
PROC [event:
ATOM, watched:
REF
ANY ←
NIL, handleAborted:
BOOLEAN ←
FALSE, arg:
REF
ANY ←
NIL] =
BEGIN
GetWatchers:
PROC
RETURNS [wl: WatcherList] =
BEGIN
wll: AList;
IF watched #
NIL
THEN
WITH watched
SELECT
FROM
node: Node => {
SELECT event
FROM
$ChangeEarly => RETURN [node.watchers[high]];
$ChangeLate => RETURN [node.watchers[ordinary]];
ENDCASE => RETURN [NARROW[List.Assoc[key: event, aList: node.props]]]};
cell: Cell => {
SELECT event
FROM
$Schedule => RETURN [cell.realCellStuff.schedWatchers];
$Eval => RETURN [cell.realCellStuff.evalWatchers];
ENDCASE => RETURN [NARROW[List.Assoc[key: event, aList: cell.props]]]};
ENDCASE;
wll ← NARROW[Atom.GetProp[atom: event, prop: watchersKey]];
wl ← NARROW[List.Assoc[key: watched, aList: wll]];
END;
wl: WatcherList ← GetWatchers[];
abort: BOOLEAN ← FALSE;
abortedWatchers: WatcherList ← NIL;
WHILE wl #
NIL
DO
wl.first.Notify[
event: event,
watched: watched,
watcherData: wl.first.watcherData,
arg: arg
!
ABORTED =>
IF handleAborted
THEN {
abort ← TRUE;
abortedWatchers ← CONS[wl.first, abortedWatchers];
CONTINUE}];
wl ← wl.rest;
ENDLOOP;
IF abort THEN ERROR ABORTED;
END;
END.