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: 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]
RETURNS[abort: BOOL ← FALSE]
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, "!"]];
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.