CDCleanUpImpl.mesa
Copyright (C) 1986 by Xerox Corporation. All rights reserved.
by Ch. Jacobi, January 29, 1986 5:31:20 pm PST
last edited Ch. Jacobi, February 20, 1986 4:03:34 pm PST
DIRECTORY
CD,
CDCells,
CDCleanUp,
CDDirectory,
CDExtras,
CDMenus,
CDOps,
CDProperties,
CDSequencer,
TerminalIO;
CDCleanUpImpl: CEDAR PROGRAM
IMPORTS CDDirectory, CDCells, CDExtras, CDMenus, CDOps, CDProperties, TerminalIO
EXPORTS CDCleanUp
SHARES CD, CDDirectory =
BEGIN
ReplaceFunnys: PUBLIC PROC [design: CD.Design, key: REFNIL] =
BEGIN
myVal: REF ~ NEW[INT];
realKey: REF ~ IF key=NIL THEN NEW[INT] ELSE key;
DirtyExpand: PROC [ob: CD.Object] = {
WHILE ob.class.internalWrite=NIL DO
--real dirty, but it never happens because internalWrite is never NIL, except...
new: CD.Object ← CDDirectory.ExpandHard[ob, NIL, NIL];
own: REF ← CDProperties.GetPropFromObject[ob, $OwnerDesign];
IF new=NIL THEN EXIT;
CDProperties.AppendProps[looser: new.properties, winner: ob.properties, putOnto: new];
ob^ ← new^; --real dirty--
CDProperties.PutPropOnObject[ob, $OwnerDesign, own];
ENDLOOP;
};
DoIt: CDDirectory.EnumerateObjectsProc = {
IF me.class.inDirectory AND CDProperties.GetPropFromObject[me, realKey]#x THEN {
CDProperties.PutProp[me, realKey, x];
DirtyExpand[me];
CDDirectory.EnumerateChildObjects[me, DoIt, x];
};
};
EachEntry: CDDirectory.EachEntryAction = {DoIt[ob, myVal]};
IF design^.actual.rest#NIL THEN CDExtras.PopToTopLevel[design];
FOR list: LIST OF CD.Instance ← CDOps.InstList[design], list.rest WHILE list#NIL DO
DoIt[list.first.ob, myVal];
ENDLOOP;
[] ← CDDirectory.Enumerate[design, EachEntry];
IF key=NIL THEN CDExtras.RemoveProperties[design, realKey];
END;
PreTag: PROC [design: CD.Design, replaceBy: REF, key: REF] =
--figures out whether objects should be replaced because they are in different designs
--such objects will be copied and put onto the replaceBy property
BEGIN
myVal: REF ~ NEW[INT];
DoIt: CDDirectory.EnumerateObjectsProc = {
IF me.class.inDirectory AND CDProperties.GetPropFromObject[me, key]#x THEN {
CDProperties.PutProp[me, key, x];
IF CDProperties.GetPropFromObject[me, $OwnerDesign]=NIL THEN {
[] ← CDDirectory.Include[design, me];
}
ELSE IF CDDirectory.Fetch[design, CDDirectory.Name[me]].object#me THEN {
new: CD.Object ← CDDirectory.Another[me, NIL, design];
IF new=NIL THEN new ← CDDirectory.ExpandHard[me, NIL, design];
CDProperties.PutProp[me, replaceBy, new];
IF new=NIL THEN TerminalIO.WriteRope["**** something is fishy\n"]
ELSE me ← new;
};
CDDirectory.EnumerateChildObjects[me, DoIt, x];
};
};
EachEntry: CDDirectory.EachEntryAction = {DoIt[ob, myVal]};
FOR list: LIST OF CD.Instance ← CDOps.InstList[design], list.rest WHILE list#NIL DO
DoIt[list.first.ob, myVal];
ENDLOOP;
[] ← CDDirectory.Enumerate[design, EachEntry];
END;
ReplaceTagged: PUBLIC PROC [design: CD.Design, replaceBy: REF, key: REFNIL] =
BEGIN
myVal: REF ~ NEW[INT];
realKey: REF ~ IF key=NIL THEN NEW[INT] ELSE key;
DoChilds: CDDirectory.EnumerateObjectsProc = {
--uses globals design and realKey
DoCell: PROC [cell: CD.Object] = {
FOR list: LIST OF CD.Instance ← NARROW[cell.specificRef, CD.CellPtr].contents, list.rest WHILE list#NIL DO
WITH CDProperties.GetPropFromObject[list.first.ob, replaceBy] SELECT FROM
ob: CD.Object => list.first.ob ← ob;
ENDCASE => NULL;
ENDLOOP;
}; --DoCell
DoHard: PROC [ob: CD.Object] = {
replaces: CDDirectory.ReplaceList ← NIL;
FindReplaces: CDDirectory.EnumerateObjectsProc = {
WITH CDProperties.GetPropFromObject[me, replaceBy] SELECT FROM
new: CD.Object => {
replaces ← CONS[NEW[CDDirectory.ReplaceRec←[old: me, oldSize: me.size, new: new, newSize: new.size, off: [0, 0]]], replaces];
};
ENDCASE => NULL;
}; --FindReplaces
--DoHard
CDDirectory.EnumerateChildObjects[ob, FindReplaces, NIL];
IF replaces#NIL THEN
[] ← CDDirectory.ObToDirectoryProcs[ob].replaceDirectChilds[ob, design, replaces]
}; --DoHard
--DoChilds
IF me.class.inDirectory AND CDProperties.GetPropFromObject[me, realKey]#x THEN {
CDProperties.PutProp[me, realKey, x];
IF CDCells.IsCell[me] THEN DoCell[me] ELSE DoHard[me];
CDDirectory.EnumerateChildObjects[me, DoChilds, x];
};
}; --DoChilds
EachEntry: CDDirectory.EachEntryAction = {
WITH CDProperties.GetPropFromObject[ob, replaceBy] SELECT FROM
new: CD.Object => {
[] ← CDDirectory.Remove[design, name, ob];
[] ← CDDirectory.Include[design, new];
ob ← new;
};
ENDCASE => NULL;
DoChilds[ob, myVal];
}; --EachEntry
--ReplaceTagged
IF design^.actual.rest#NIL THEN CDExtras.PopToTopLevel[design];
FOR list: LIST OF CD.Instance ← CDOps.InstList[design], list.rest WHILE list#NIL DO
WITH CDProperties.GetPropFromObject[list.first.ob, replaceBy] SELECT FROM
ob: CD.Object => {
list.first.ob ← ob;
DoChilds[ob, myVal];
}
ENDCASE => NULL;
ENDLOOP;
[] ← CDDirectory.Enumerate[design, EachEntry];
IF key=NIL THEN CDExtras.RemoveProperties[design, realKey];
END; --ReplaceTagged
CleanUp: PUBLIC PROC [design: CD.Design] =
BEGIN
myKey: REF ~ NEW[INT];
replaceBy: REF ~ NEW[INT];
ReplaceFunnys[design, myKey];
PreTag[design, replaceBy, myKey];
ReplaceTagged[design, replaceBy, myKey];
CDExtras.RemoveProperties[design, myKey];
CDExtras.RemoveProperties[design, replaceBy];
END;
CleanupCommand: PROC [comm: CDSequencer.Command] =
BEGIN
n: INT;
TerminalIO.WriteRope["cleanup directory\n"];
n ← comm.design.cellDirectory.size;
CleanUp[comm.design];
IF n = comm.design.cellDirectory.size THEN
TerminalIO.WriteF["design was ok; has %g entries in directory\n", [integer[n]]]
ELSE
TerminalIO.WriteF["design was not ok; previously had %g; now has %g entries in directory\n", [integer[n]], [integer[comm.design.cellDirectory.size]]];
END;
CDMenus.ImplementEntryCommand[$SpecialMenu, "check directory", CleanupCommand];
END.