<> <> <> <> DIRECTORY FS USING [ComponentPositions, Error, ExpandName], Rope USING [ROPE, Run, SkipTo], ViewerClasses USING [Viewer], ViewerEvents USING [EventProc, EventRegistration, ViewerEvent], ViewerPrivate USING [Severity], UserProfile USING [Boolean, GetProfileName, ProfileChanged]; ViewerEventsImpl: CEDAR MONITOR IMPORTS FS, Rope, UserProfile EXPORTS ViewerEvents, ViewerPrivate = BEGIN ROPE: TYPE = Rope.ROPE; EventProcs: TYPE = LIST OF RECORD[proc: ViewerEvents.EventProc, filter: REF, before: BOOL]; ArrayEventProcs: TYPE = ARRAY ViewerEvents.ViewerEvent OF EventProcs; eventProcs: REF ArrayEventProcs _ NEW[ArrayEventProcs _ ALL[NIL]]; <> Error: PUBLIC SIGNAL [severity: ViewerPrivate.Severity _ fatal, msg: Rope.ROPE _ NIL] = CODE; UserErrorQuery: PUBLIC ENTRY PROC RETURNS [continue: BOOL _ FALSE] = TRUSTED { <> ENABLE UNWIND => NULL; IF UserProfile.Boolean["Viewers.WorldSwapDebug", FALSE] THEN RETURN [FALSE]; }; <> RegisterEventProc: PUBLIC ENTRY PROC [proc: ViewerEvents.EventProc, event: ViewerEvents.ViewerEvent, filter: REF _ NIL, before: BOOL _ TRUE] RETURNS [ViewerEvents.EventRegistration] = { <> RETURN [eventProcs[event] _ CONS[[proc, filter, before], eventProcs[event]]]; }; UnRegisterEventProc: PUBLIC ENTRY PROC [proc: ViewerEvents.EventRegistration, event: ViewerEvents.ViewerEvent] = { <> newHead: EventProcs _ NIL; newTail: EventProcs _ NIL; FOR each: EventProcs _ eventProcs[event], each.rest WHILE each # NIL DO IF proc # each THEN { new: EventProcs _ LIST[each.first]; IF newTail # NIL THEN newTail.rest _ new ELSE newHead _ new; newTail _ new; }; ENDLOOP; eventProcs[event] _ newHead; }; GetHead: ENTRY PROC [event: ViewerEvents.ViewerEvent] RETURNS [EventProcs] = { <> RETURN [eventProcs[event]]; }; ProcessEvent: PUBLIC PROC [event: ViewerEvents.ViewerEvent, viewer: ViewerClasses.Viewer, before: BOOL] RETURNS [abort: BOOL _ FALSE] = { <> FOR l: EventProcs _ GetHead[event], l.rest UNTIL l=NIL DO IF l.first.before = before THEN { filter: REF _ l.first.filter; IF filter = NIL OR filter = viewer OR (viewer # NIL AND filter = viewer.class.flavor) THEN { proc: ViewerEvents.EventProc _ l.first.proc; IF proc # NIL THEN abort _ proc[viewer, event, before ! ABORTED => {abort _ TRUE; EXIT}].abort; IF abort THEN RETURN; }; }; ENDLOOP; }; <> NoticeProfileChanges: ViewerEvents.EventProc = { <<[viewer: ViewerClasses.Viewer, event: ViewerEvent, before: BOOL] RETURNS[abort: BOOL _ FALSE]>> IF viewer # NIL THEN { ENABLE FS.Error => GOTO GiveUp; name1: ROPE _ FS.ExpandName[viewer.file].fullFName; bang1: INT _ Rope.SkipTo[name1, 0, "!"]; name2: ROPE _ FS.ExpandName[UserProfile.GetProfileName[]].fullFName; bang2: INT _ Rope.SkipTo[name2, 0, "!"]; IF bang1 # 0 AND bang1 = bang2 AND Rope.Run[name1, 0, name2, 0, FALSE] = bang1 THEN <> UserProfile.ProfileChanged[edit]; EXITS GiveUp => NULL; }; }; [] _ RegisterEventProc[NoticeProfileChanges, save, $Text, FALSE]; END.