DIRECTORY Tioga, TiogaPrivate; EditNotifyImpl: CEDAR MONITOR LOCKS data USING data: EditNotifyData EXPORTS TiogaPrivate = BEGIN OPEN Tioga, TiogaPrivate; EditNotifyData: TYPE ~ REF EditNotifyDataRep; EditNotifyDataRep: PUBLIC TYPE ~ MONITORED RECORD [ beforeProcs: NotifyArray, afterProcs: NotifyArray, unlocked: CONDITION, lockCount: INTEGER _ 0 ]; NotifyList: TYPE = REF NotifyListBody; NotifyListBody: TYPE = RECORD [ next: NotifyList, action: EditNotifyProc, changeSet: ChangeSet ]; NotifyArray: TYPE = ARRAY Priority OF NotifyList; Lock: ENTRY PROC [data: EditNotifyData] = { data.lockCount _ data.lockCount+1; }; Unlock: ENTRY PROC [data: EditNotifyData] = { data.lockCount _ data.lockCount-1; IF data.lockCount <= 0 THEN { data.lockCount _ 0; BROADCAST data.unlocked }; }; InternalRemove: PROC [data: EditNotifyData, proc: EditNotifyProc, time: When] = { FOR p: Priority IN Priority DO prev: NotifyList _ NIL; list: NotifyList _ IF time=before THEN data.beforeProcs[p] ELSE data.afterProcs[p]; IF list=NIL THEN LOOP; UNTIL list=NIL DO IF list.action = proc THEN EXIT; prev _ list; list _ list.next; REPEAT FINISHED => LOOP; -- proc not found on this list ENDLOOP; IF prev#NIL THEN prev.next _ list.next ELSE IF time=before THEN data.beforeProcs[p] _ list.next ELSE data.afterProcs[p] _ list.next; ENDLOOP; }; EntryAdd: ENTRY PROC [data: EditNotifyData, proc: EditNotifyProc, time: When, priority: Priority, changeSet: ChangeSet] = { ENABLE UNWIND => NULL; WHILE data.lockCount > 0 DO WAIT data.unlocked; ENDLOOP; InternalRemove[data, proc, time]; IF time=before THEN data.beforeProcs[priority] _ NEW[NotifyListBody _ [data.beforeProcs[priority], proc, changeSet]] ELSE data.afterProcs[priority] _ NEW[NotifyListBody _ [data.afterProcs[priority], proc, changeSet]]; }; EntryRemove: ENTRY PROC [data: EditNotifyData, proc: EditNotifyProc, time: When] = { ENABLE UNWIND => NULL; WHILE data.lockCount > 0 DO WAIT data.unlocked; ENDLOOP; InternalRemove[data, proc, time]; }; AddEditNotifyProc: PUBLIC PROC [world: World, proc: EditNotifyProc, time: When _ after, priority: Priority _ normal, changeSet: ChangeSet _ defaultChangeSet] ~ { data: EditNotifyData ~ world.editNotify; EntryAdd[data, proc, time, priority, changeSet]; }; RemoveEditNotifyProc: PUBLIC PROC [world: World, proc: EditNotifyProc, time: When _ after] ~ { data: EditNotifyData ~ world.editNotify; EntryRemove[data, proc, time]; }; GetList: PROC [data: EditNotifyData, p: Priority, time: When] RETURNS [NotifyList] = { RETURN [IF time=before THEN data.beforeProcs[p] ELSE data.afterProcs[p]] }; EditNotify: PUBLIC PROC [world: World, change: REF READONLY Change, time: When] = { data: EditNotifyData ~ IF world=NIL THEN NIL ELSE world.editNotify; IF data#NIL AND change#NIL THEN { ENABLE UNWIND => Unlock[data]; kind: ChangeType ~ change.kind; Lock[data]; FOR p: Priority IN Priority DO FOR lst: NotifyList _ GetList[data, p, time], lst.next UNTIL lst=NIL DO IF lst.changeSet[kind] THEN lst.action[change]; ENDLOOP; ENDLOOP; Unlock[data]; }; }; CreateEvent: PUBLIC PROC RETURNS [Event] = { RETURN [NEW[EventBody _ [subevents: NIL]]]; }; NoteEvent: PUBLIC PROC [world: World, undoProc: UndoProc, undoRef: REF Change] = { event: Event ~ IF world=NIL THEN NIL ELSE world.currentEvent; IF event = NIL THEN RETURN; event.subevents _ NEW[SubEventBody _ [next: event.subevents, undoProc: undoProc, undoRef: undoRef]]; }; UndoEvent: PUBLIC PROC [world: World, undoEvent: Event] = { sub: SubEvent; IF undoEvent=NIL THEN RETURN; sub _ undoEvent.subevents; undoEvent.subevents _ NIL; UNTIL sub=NIL DO sub.undoProc[world, sub.undoRef]; sub _ sub.next; ENDLOOP; }; ResetEvent: PUBLIC PROC [event: Event] = { IF event # NIL THEN event.subevents _ NIL; }; EmptyEvent: PUBLIC PROC [event: Event] RETURNS [BOOL] = { RETURN [event=NIL OR event.subevents=NIL]; }; END. าEditNotifyImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. written by Bill Paxton, March 1981 last edit by Bill Paxton, October 18, 1982 10:42 am Michael Plass, March 29, 1985 2:31:39 pm PST Doug Wyatt, September 23, 1986 5:51:39 pm PDT EditNotify remove proc from list of notification procedures call notification procedures UndoEvent calls undoProc[undoRef] for each subevent in reverse order that subevents originally happened สท˜codešœ™Kšœ ฯmœ7™BKšœ"™"Kšœ4™4K™,K™-—K˜šฯk ˜ Kšœ˜Kšœ ˜ —K˜Kš ัblnœžœžœžœžœ˜CKšžœ ˜Kšœžœžœ˜!head™ Kšœžœžœ˜-š œžœžœž œžœ˜3K˜K˜Kšœ ž œ˜Kšœ žœ˜K˜—K˜Kšœ žœžœ˜&šœžœžœ˜K˜K˜K˜K˜—Kšœ žœžœ žœ ˜1K˜šฯnœžœžœ˜+Kšœ"˜"Kšœ˜K˜—š œžœžœ˜-Kšœ"˜"Kšžœžœž œ˜LKšœ˜K˜—š œžœ=˜Qšžœ žœ ž˜Kšœžœ˜šœžœ žœ˜:Kšžœ˜—Kšžœžœžœžœ˜šžœžœž˜Kšžœžœžœ˜ K˜Kšžœžœžœฯc˜7Kšžœ˜—Kšžœžœžœ˜&Kšžœžœ žœ ˜8Kšžœ ˜$Kšžœ˜—šœ˜K˜——š œžœžœg˜{Kšžœžœžœ˜Kšžœžœžœžœ˜8K˜!šžœ ž˜˜Kšžœ@˜C——šžœ˜ Kšžœ@˜C—šœ˜K˜——š  œžœžœ=˜TKšœ0™0Kšžœžœžœ˜Kšžœžœžœžœ˜8K˜!K˜K˜—š œžœžœ„˜ขKšœ(˜(K˜0K˜K˜—š œžœžœ=˜^Kšœ(˜(Kšœ˜K˜K˜—š œžœ1žœ˜VKšžœžœ žœžœ˜HKšœ˜K˜—š   œžœžœžœžœ˜SKšœ™Kš œžœžœžœžœžœ˜Cš žœžœžœžœžœ˜!Kšžœžœ˜K˜K˜ šžœ žœ ž˜šžœ4žœžœž˜GKšžœžœ˜/Kšžœ˜—Kšžœ˜—Kšœ ˜ K˜—Kšœ˜K˜——™ š  œžœžœžœ ˜,Kšžœžœžœ˜+Kšœ˜—K˜š  œžœžœ-žœ ˜RKš œžœžœžœžœžœ˜=Kšžœ žœžœžœ˜šœžœ˜$K˜?—˜K˜——š  œžœžœ%˜;Kšœ*™*Kšœ3™3K˜Kšžœ žœžœžœ˜Kšœ1žœ˜5Kšžœžœžœ3žœ˜KKšœ˜K˜—š  œžœžœ˜*Kšžœ žœžœžœ˜*Kšœ˜—K˜š   œžœžœžœžœ˜9Kšžœžœžœžœ˜*Kšœ˜K˜——K˜Kšžœ˜—…—‹