<> <> <> <> <> <> <> <> <> DIRECTORY DB, DBNames, Nut, Rope, ViewerOps; NutImpl: CEDAR MONITOR IMPORTS DB, DBNames, Rope, ViewerOps EXPORTS Nut = BEGIN OPEN Nut, DB; <> implementations: PUBLIC ImplementationList _ NIL; ImplementationProcList: TYPE = LIST OF ImplementationProcRecord _ NIL; ImplementationProcRecord: TYPE = REF ImplementationProcRecordObject; ImplementationProcRecordObject: TYPE = RECORD[ display: NutProc, -- a nut displayer for a domain edit: NutProc, -- a nut editor for a domain query: NutProc, -- a nut queryer for a domain reset: PROC[v: Viewer] ]; -- the reset proc for a domain ImplementationList: TYPE = LIST OF ImplementationRecord _ NIL; ImplementationRecord: TYPE = REF ImplementationRecordObject; ImplementationRecordObject: TYPE = RECORD[ domain: ROPE, -- name of domain segment: DB.Segment, -- the segment of the domain procList: ImplementationProcList]; -- stack of procedures for this domain PlaceRecord: TYPE = REF PlaceRecordObject; PlaceRecordObject: TYPE = RECORD[ previous: ImplementationList, current: ImplementationList, next: ImplementationList]; NoProcRegistered: PUBLIC ERROR = CODE; <> Display: PUBLIC ENTRY PROC[eName, domain: ROPE, segment: DB.Segment, parent: Viewer_ NIL] RETURNS[v: Viewer] = BEGIN ENABLE UNWIND => NULL; implRec: ImplementationRecord = FindImpl[domain, segment]; lastSpawned: Viewer = IF parent = NIL THEN NIL ELSE GetSpawnedProperty[parent]; IF implRec = NIL THEN RETURN WITH ERROR NoProcRegistered[]; v _ implRec.procList.first.display[eName, domain, segment, lastSpawned ! ABORTED => CONTINUE]; IF v # NIL AND NOT v.destroyed THEN { [] _ SetSpawnedProperty[parent, v]; IF v.iconic THEN ViewerOps.OpenIcon[v] } END; Edit: PUBLIC ENTRY PROC[eName, domain: ROPE, segment: DB.Segment, parent: Viewer_ NIL] RETURNS[v: Viewer] = BEGIN ENABLE UNWIND => NULL; implRec: ImplementationRecord = FindImpl[domain, segment]; lastSpawned: Viewer = IF parent = NIL THEN NIL ELSE GetSpawnedProperty[parent]; IF implRec = NIL THEN RETURN WITH ERROR NoProcRegistered[]; v _ implRec.procList.first.edit[eName, domain, segment, lastSpawned ! ABORTED => CONTINUE]; IF v # NIL AND NOT v.destroyed THEN { [] _ SetSpawnedProperty[parent, v]; IF v.iconic THEN ViewerOps.OpenIcon[v] } END; Query: PUBLIC ENTRY PROC[eName, domain: ROPE, segment: DB.Segment, parent: Viewer_ NIL] RETURNS[v: Viewer] = BEGIN ENABLE UNWIND => NULL; implRec: ImplementationRecord = FindImpl[domain, segment]; lastSpawned: Viewer = IF parent = NIL THEN NIL ELSE GetSpawnedProperty[parent]; IF implRec = NIL OR implRec.procList.first.query = NIL THEN RETURN WITH ERROR NoProcRegistered[]; v _ implRec.procList.first.query[eName, domain, segment, lastSpawned ! ABORTED => CONTINUE]; IF v # NIL AND NOT v.destroyed THEN { [] _ SetSpawnedProperty[parent, v]; IF v.iconic THEN ViewerOps.OpenIcon[v] } END; Register: PUBLIC ENTRY PROC[domain: ROPE, segment: DB.Segment, display: NutProc _ NIL, edit: NutProc _ NIL, query: NutProc _ NIL, reset: PROC[v: Viewer] _ NIL] = <> <> BEGIN LoadEntry[domain, segment, display, edit, query, reset, TRUE]; END; Push: PUBLIC ENTRY PROC[ domain: ROPE, segment: DB.Segment, display: NutProc _ NIL, edit: NutProc _ NIL, query: NutProc _ NIL, reset: PROC[v: Viewer] _ NIL, register: BOOLEAN _ FALSE] = <> <> BEGIN LoadEntry[domain, segment, display, edit, query, reset, FALSE] END; SetSpawnedProperty: PUBLIC PROC [v: Viewer, new: Viewer] RETURNS [previous: Viewer] ~ { IF v = NIL OR v.destroyed THEN RETURN[NIL]; previous _ NARROW[ViewerOps.FetchProp[v, $LastSpawned]]; ViewerOps.AddProp[v, $LastSpawned, new] }; GetSpawnedProperty: PUBLIC PROC [v: Viewer] RETURNS [current: Viewer] ~ { current _ NARROW[ViewerOps.FetchProp[v, $LastSpawned]]; IF GetFrozenProperty[current] THEN RETURN[NIL] }; SetFrozenProperty: PUBLIC PROC [v: Viewer, new: BOOL] RETURNS [previous: BOOL] ~ { IF v = NIL THEN RETURN[TRUE]; -- the non-existent viewer is always frozen {refFrozen: REF BOOL = NARROW[ViewerOps.FetchProp[v, $Frozen]]; IF refFrozen = NIL THEN {previous _ FALSE; ViewerOps.AddProp[v, $Frozen, NEW[BOOL _ new]] } ELSE {previous _ refFrozen^; refFrozen^ _ new} } }; GetNutInfo: PUBLIC PROC[v: Viewer] RETURNS[segment: Segment, domain, entity: ROPE] = { filePath: Rope.ROPE = NARROW[ViewerOps.FetchProp[v, $SegmentFile]]; entity _ NARROW[ViewerOps.FetchProp[v, $EntityName]]; segment _ NARROW[ViewerOps.FetchProp[v, $Segment]]; domain _ NARROW[ViewerOps.FetchProp[v, $DomainName]]; <> IF NOT Rope.Equal[filePath, DB.GetSegmentInfo[segment].filePath] THEN RETURN[NIL, NIL, NIL] }; SetNutInfo: PUBLIC PROC[v: Viewer, segment: Segment, domain, entity: ROPE] = { ViewerOps.AddProp[v, $EntityName, entity]; ViewerOps.AddProp[v, $Segment, segment]; ViewerOps.AddProp[v, $SegmentFile, DB.GetSegmentInfo[segment].filePath]; ViewerOps.AddProp[v, $DomainName, domain] }; ChangeName: PUBLIC PROC[v: Viewer, newName: ROPE] = { ViewerOps.AddProp[v, $EntityName, newName] }; EntityNameForViewer: PUBLIC PROC [v: Viewer] RETURNS [entityName: ROPE] ~ { segment: DB.Segment; entity, domain: ROPE; [segment, domain, entity] _ GetNutInfo[v]; RETURN[DBNames.MakeName[segment, domain, entity]] }; GetFrozenProperty: PUBLIC PROC [v: Viewer] RETURNS [current: BOOL] ~ { IF v = NIL THEN RETURN[TRUE]; -- the non-existent viewer is always frozen { refFrozen: REF BOOL = NARROW[ViewerOps.FetchProp[v, $Frozen]]; IF refFrozen = NIL THEN current _ FALSE ELSE current _ refFrozen^ } }; LoadEntry: INTERNAL PROC[ domain: ROPE, segment: DB.Segment, display: NutProc _ NIL, edit: NutProc _ NIL, query: NutProc _ NIL, reset: PROC[v: Viewer] _ NIL, register: BOOLEAN _ FALSE] = <> BEGIN implRec: ImplementationRecord_ FindImpl[domain, segment]; IF implRec = NIL THEN BEGIN implRec _ NEW[ImplementationRecordObject]; implRec.domain _ domain; implRec.segment _ segment; implRec.procList _ CONS[ NEW[ImplementationProcRecordObject], NIL]; implementations _ CONS[ implRec, implementations ]; END; IF ~register THEN implRec.procList _ CONS[ NEW[ImplementationProcRecordObject], implRec.procList ]; IF display#NIL THEN implRec.procList.first.display_ display; IF edit#NIL THEN implRec.procList.first.edit_ edit; IF query#NIL THEN implRec.procList.first.query_ query; IF reset#NIL THEN implRec.procList.first.reset_ reset; END; DeRegister: PUBLIC ENTRY PROC[domain: ROPE, segment: DB.Segment] = <> BEGIN placeRec: PlaceRecord _ FindPlace[domain, segment]; IF placeRec.previous = NIL THEN implementations_ placeRec.next ELSE placeRec.previous.rest _ placeRec.next; END; Pop: PUBLIC ENTRY PROC[domain: ROPE, segment: DB.Segment] = <> BEGIN placeRec: PlaceRecord _ FindPlace[domain, segment]; IF placeRec.current # NIL THEN BEGIN procRec: ImplementationProcRecord _ placeRec.current.first.procList.first; IF placeRec.current.first.procList.rest = NIL THEN IF placeRec.previous = NIL THEN implementations _ placeRec.next ELSE placeRec.previous.rest _ placeRec.next ELSE placeRec.current.first.procList _ placeRec.current.first.procList.rest; END; END; PushDefaults: PUBLIC ENTRY PROC[domain: ROPE, segment: DB.Segment] = <> BEGIN defaultRec: ImplementationProcRecord_ FindImpl[NIL, segment].procList.first; LoadEntry[domain, segment, defaultRec.display, defaultRec.edit, defaultRec.query, defaultRec.reset, FALSE]; END; <> FindImpl: INTERNAL PROC[d: ROPE, seg: Segment] RETURNS[ImplementationRecord] = <> BEGIN placeRec: PlaceRecord; IF (placeRec _ FindPlace[d, seg]).current = NIL THEN BEGIN implRec: ImplementationRecord; IF (placeRec _ FindPlace[d, NIL]).current = NIL THEN IF (placeRec _ FindPlace[NIL, NIL]).current = NIL THEN RETURN[NIL]; implRec _ NEW[ImplementationRecordObject]; implRec.domain _ d; implRec.segment _ seg; implRec.procList _ CONS[ NEW[ImplementationProcRecordObject], NIL]; implRec.procList.first^ _ placeRec.current.first.procList.first^; implementations _ CONS[ implRec, implementations ]; RETURN[implRec]; END; RETURN[placeRec.current.first]; END; FindPlace: INTERNAL PROC[d: ROPE, seg: Segment] RETURNS[PlaceRecord] = <> BEGIN placeRec: PlaceRecord _ NEW[PlaceRecordObject]; placeRec.current _ implementations; FOR iL: ImplementationList _ implementations, iL.rest UNTIL iL=NIL DO placeRec.previous _ placeRec.current; placeRec.current _ iL; placeRec.next _ iL.rest; IF Rope.Equal[iL.first.domain, d] AND (seg = iL.first.segment) THEN RETURN[placeRec]; ENDLOOP; placeRec.current _ NIL; RETURN[placeRec]; END; END. Change Log: Cattell on January 16, 1984 12:12 pm: passing NIL in for segment when registering means will take any segment. Butler on June 4, 1984: Users can register their own defaults. They are no longer built in. NIL in the place of the domain and/or segment will register a default for a domain and/or segment. Cattell on January 16, 1984 12:12 pm: passing NIL in for segment when registering means will take any segment. Butler on June 4, 1984: Users can register their own defaults. They are no longer built in. NIL in the place of the domain and/or segment will register a default for a domain and/or segment. Butler on June 26, 1984: Major Revision of code has been completed. Dependencies between Squirrel and Nut and whiteboards have been altered. Nut is now independent of Squirrel. The creation of all viewers is now done through NutViewer. Donahue on July 12, 1984: NutImpl is now a free standing implementation of Nut; it can be run independently of any other piece of Squirrel.