ViewerEventsImpl.mesa;
McGregor on August 2, 1982 11:44 am
Maxwell, January 11, 1983 12:27 pm
Russ Atkinson, September 30, 1983 12:16 pm
Doug Wyatt, December 14, 1983 3:11 pm
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: REFNIL, before: BOOLTRUE]
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: BOOLFALSE] = 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]
RETURNS[abort: BOOLFALSE]
IF viewer # NIL THEN {
fileName: ROPENIL;
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: BOOLFALSE;
profileName: ROPE ← UserProfile.GetProfileName[];
profileName ← profileName.Flatten[0, profileName.SkipTo[0, "!"]];
remove the version info (if any), so profile name has the form "xxx.profile"
IF SimpleNameIs[profileName] THEN notify ← TRUE
ELSE {
changed file is NOT the current profile, but it MAY be the right profile to use next
userName: ROPE ← UserCredentials.Get[].name;
userName ← userName.Flatten[0, userName.SkipTo[0, "."]];
remove the registry information
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.