<> <> <> <> <> <> DIRECTORY FS USING [ComponentPositions, Error, ExpandName], Rope USING [Flatten, Length, ROPE, Run, SkipTo], ViewerClasses USING [Viewer], ViewerEvents USING [EventProc, EventRegistration, ViewerEvent], UserCredentials USING [Get], UserProfile USING [GetProfileName, ProfileChanged]; ViewerEventsImpl: CEDAR PROGRAM IMPORTS FS, Rope, UserCredentials, UserProfile EXPORTS ViewerEvents = BEGIN ROPE: TYPE = Rope.ROPE; EventProcs: TYPE = LIST OF RECORD[proc: ViewerEvents.EventProc, filter: REF, before: BOOL] ; eventProcs: ARRAY ViewerEvents.ViewerEvent OF EventProcs ; RegisterEventProc: PUBLIC 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 PROC [proc: ViewerEvents.EventRegistration, event: ViewerEvents.ViewerEvent] = { prev: EventProcs _ eventProcs[event]; IF prev = NIL THEN RETURN; IF proc=prev THEN { -- its the first one on the list eventProcs[event] _ eventProcs[event].rest; RETURN }; FOR l: EventProcs _ prev.rest, l.rest UNTIL l=NIL DO IF l=proc THEN { prev.rest _ l.rest; RETURN }; prev _ l; ENDLOOP; }; ProcessEvent: PUBLIC PROC [event: ViewerEvents.ViewerEvent, viewer: ViewerClasses.Viewer, before: BOOL] RETURNS [abort: BOOL _ FALSE] = BEGIN FOR l: EventProcs _ eventProcs[event], l.rest UNTIL l=NIL DO IF l.first.before # before THEN LOOP; IF l.first.filter = NIL OR l.first.filter = viewer OR (viewer # NIL AND l.first.filter = viewer.class.flavor) THEN { abort _ l.first.proc[ viewer, event, before ! ABORTED => {abort _ TRUE; EXIT}].abort; IF abort THEN RETURN}; ENDLOOP; END; NoticeProfileChanges: ViewerEvents.EventProc = { <<[viewer: ViewerClasses.Viewer, event: ViewerEvent, before: BOOL]>> <> IF viewer # NIL THEN { fileName: ROPE _ NIL; cp: FS.ComponentPositions; SubstrEqual: PROC[s1: ROPE, pos1, len1: INT, s2: ROPE] RETURNS[BOOL] = { RETURN[len1=s2.Length AND s1.Run[pos1: pos1, s2: s2, case: FALSE]=len1] }; BaseIs: PROC[x: ROPE] RETURNS[BOOL] = { RETURN[SubstrEqual[s1: fileName, pos1: cp.base.start, len1: cp.base.length, s2: x]] }; ExtensionIs: PROC[x: ROPE] RETURNS[BOOL] = { RETURN[SubstrEqual[s1: fileName, pos1: cp.ext.start, len1: cp.ext.length, s2: x]] }; SimpleNameIs: PROC[x: ROPE] RETURNS[BOOL] = { RETURN[SubstrEqual[s1: fileName, pos1: cp.base.start, len1: (cp.ext.start+cp.ext.length)-cp.base.start, s2: x]] }; [fullFName: fileName, cp: cp] _ FS.ExpandName[viewer.file ! FS.Error => GOTO GiveUp]; IF ExtensionIs["profile"] THEN { notify: BOOL _ FALSE; profileName: ROPE _ UserProfile.GetProfileName[]; profileName _ profileName.Flatten[0, profileName.SkipTo[0, "!"]]; <> IF SimpleNameIs[profileName] THEN notify _ TRUE ELSE { <> userName: ROPE _ UserCredentials.Get[].name; userName _ userName.Flatten[0, userName.SkipTo[0, "."]]; <> IF BaseIs[userName] THEN notify _ TRUE ELSE IF profileName.Length=0 AND BaseIs["user"] THEN notify _ TRUE; }; IF notify THEN UserProfile.ProfileChanged[edit]; }; EXITS GiveUp => NULL; }; }; [] _ RegisterEventProc[NoticeProfileChanges, save, $Text, FALSE]; END.