DIRECTORY
CD,
CDBasics,
CDCells,
CDCellsInteractions,
CDDirectory,
CDDirectoryOps,
CDDefaultProcs,
CDInstances,
CDImports,
CDOps,
CDPanel,
CDProperties,
CDSequencer,
CDTexts,
CDValue,
Convert,
IO,
PopUpSelection,
Real,
RefTab,
Rope,
RopeList,
TerminalIO,
TextFind,
UserProfile,
ViewerClasses,
ViewerOps,
ViewerTools;

CDCellCommands: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDOps, CDCells, CDCellsInteractions, CDDefaultProcs, CDDirectory, CDDirectoryOps, CDInstances, CDImports, CDPanel, CDProperties, CDSequencer, CDTexts, CDValue, Convert, IO, PopUpSelection, Real, RefTab, Rope, RopeList, TerminalIO, TextFind, UserProfile, ViewerOps, ViewerTools = 
BEGIN

interactiveKey: Rope.ROPE ~ "_ interactive";

IgnoreContext: CD.DrawContextProc = {};

Feedback: PROC [b: BOOL] = {
IF b THEN TerminalIO.PutRope["done\n"] ELSE TerminalIO.PutRope["not done\n"]  
};

GetPattern: PROC [design: CD.Design] RETURNS [pattern: Rope.ROPE] = {
pattern _ CDPanel.TakeDownText[design, $pattern];
IF Rope.IsEmpty[pattern] THEN pattern _ NIL;
};

GetObjectName: PROC [design: CD.Design, prompt: Rope.ROPE] RETURNS [name: Rope.ROPE] = {
name _ CDPanel.TakeDownText[design, $ObjectName];
IF Rope.IsEmpty[name] OR Rope.Equal[name, interactiveKey, FALSE] THEN
name _ TerminalIO.RequestRope[prompt]; 
};

DrawByNameComm: PROC [comm: CDSequencer.Command] = {
name: Rope.ROPE; ob: CD.Object; 
TerminalIO.PutRope["draw object; "];
name _ GetObjectName[comm.design, "object name>\n"];
ob _ FindObject[comm.design, name].object;
IF ob#NIL THEN {
[] _ CDOps.IncludeObjectI[comm.design, ob, comm.pos];
TerminalIO.PutRopes[name, " inserted\n"];
};
};

FindObject: PROC [design: CD.Design, name: Rope.ROPE] RETURNS [object: CD.Object_NIL] = {
address: CARD;
object _ CDDirectory.Fetch[design, name];
IF object=NIL THEN {
address _ Convert.CardFromRope[name ! Convert.Error => {address_0; CONTINUE}];
IF address#0 THEN {
object _ Find[design, IsAddress, NEW[CARD_address]].object;
IF object#NIL THEN 
TerminalIO.PutRopes["use ", CD.Describe[object, NIL, design], "; because of address\n"]
};
IF object=NIL THEN {
object _ Find[design, IsText, name].object;
IF object#NIL THEN 
TerminalIO.PutRopes["use text object ", CD.Describe[object, NIL, design], "; because of text match\n"]
};
};
IF object=NIL THEN TerminalIO.PutRopes["design does not have object ", name, "\n"];
};

RemoveObFromDirComm: PROC [comm: CDSequencer.Command] = {
name: Rope.ROPE_NIL; done: BOOL _ FALSE; ob: CD.Object;
TerminalIO.PutRope["remove object from directory; "];
name _ GetObjectName[comm.design, "object name>\n"];
ob _ CDDirectory.Fetch[comm.design, name].object;
IF ob=NIL THEN TerminalIO.PutRopes[name, " not found\n"]
ELSE {
IF TerminalIO.Confirm[Rope.Cat["remove ", name]] THEN {
CDSequencer.MarkChangedIOOnly[comm.design];
[] _ CDDirectory.Remove[comm.design, name, ob];
};
Feedback[done];
};
};

DisplayDirectoryComm: PROC [comm: CDSequencer.Command] = {

EachEntry: CDDirectory.EachEntryAction = { 
--[name: Rope.ROPE, ob: CD.Object] RETURNS [quit: BOOL] -- 
quit _ FALSE;
count _ count+1;
IF finder#NIL THEN {
IF ~TextFind.SearchRope[finder: finder, rope: name].found THEN RETURN;
};
displayed _ displayed+1;
list _ CONS[CD.Describe[ob, NIL, comm.design], list];
};

trailer, contents: Rope.ROPE _ NIL;
list: LIST OF Rope.ROPE _ NIL; count: INT _ 0; displayed: INT _ 0;
pattern: Rope.ROPE _ GetPattern[comm.design];
header: Rope.ROPE;
finder: TextFind.Finder _ NIL;
TerminalIO.PutRopes["directory\n"];
header _ Rope.Cat["directory of ", CD.DesignName[comm.design]];
IF ~Rope.IsEmpty[pattern] THEN {
header _ Rope.Cat[header, " PATTERN [", pattern, "]"];
finder _ TextFind.CreateFromRope[pattern: pattern, ignoreCase: TRUE];
};
[] _ CDDirectory.Enumerate[comm.design, EachEntry];
list _ RopeList.Sort[list, RopeList.Compare];
FOR l: LIST OF Rope.ROPE _ list, l.rest WHILE l#NIL DO
contents _ Rope.Cat[contents, "  ", l.first, "\n"];
ENDLOOP;
trailer _ IF count=displayed 
THEN IO.PutFR["%g objects\n", IO.int[count]]
ELSE IO.PutFR["%g objects listed [out of %g objects]\n", IO.int[displayed], IO.int[count]];
contents _ Rope.Cat[header, "\n", contents, trailer];
IF displayed>9 THEN {
TerminalIO.PutRopes["extra viewer opened\n", "   ", trailer];
ViewerOps.OpenIcon[ViewerTools.MakeNewTextViewer[info: [name: header, data: contents]]];
}
ELSE TerminalIO.PutRopes[contents];
};

CreateCellComm: PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["create cell  "]; 
IF ~CDCellsInteractions.CreateCellSelected[comm.design, TRUE].done THEN 
TerminalIO.PutRope[" not done\n"];
};

PushComm: PROC [comm: CDSequencer.Command] = {
inst: CD.Instance _ CDOps.TheInstance[design: comm.design, text: "push into "]; 
IF inst#NIL THEN {
TerminalIO.PutRopes[CD.Describe[inst.ob, inst.properties, comm.design], " "];
IF CDTexts.IsText[inst.ob] THEN {
p: CDSequencer.CommandProc _ CDSequencer.FetchCommand[$PushText].proc;
IF p#NIL THEN {p[comm]; RETURN};
};
IF ~CDCells.IsCell[inst.ob] THEN {
TerminalIO.PutRope[" **is not cell; object expanded**"]; 
IF ~ inst.ob.class.composed THEN CDSequencer.Quit[" not done"];
};
TerminalIO.PutRope["\n"];
Feedback[ CDCellsInteractions.PushInCellInstance[comm.design, inst, TRUE] ];
};
};

PushIntoCellSIconic: PROC [comm: CDSequencer.Command] = {
name: Rope.ROPE _ NIL;
inst: CD.Instance _ CDOps.TheInstance[design: comm.design, text: "push into representant "]; 
IF inst#NIL THEN {
TerminalIO.PutRopes[CD.Describe[inst.ob, inst.properties, comm.design], "\n"];
WITH CDProperties.GetProp[inst.ob, $IconFor] SELECT FROM
r: Rope.ROPE => name _ r;
ENDCASE => NULL;
IF name=NIL THEN 
WITH CDProperties.GetProp[inst, $IconFor] SELECT FROM
r: Rope.ROPE => name _ r;
ENDCASE => NULL;
IF Rope.IsEmpty[name] THEN {
TerminalIO.PutRope["   has no iconic property; try pushing into itself\n"];
PushComm[comm];
}
ELSE {
TerminalIO.PutRopes["   pushing into ", name, "\n"];
Feedback[ PushNamed[comm.design, name, comm] ];
};
};
};

ExpandComm: PROC [comm: CDSequencer.Command] = {
instances: CD.InstanceList _ NIL; --this will be the instances of the design
cnt: INT _ 0; 
someOb: CD.Object _ NIL; --if a single object is expanded we need it for its name

ExpandIncludeOneCell: PROC [instOfCell: CD.Instance, cell: CD.Object] = {
EachCellInst: CDCells.InstEnumerator = {
new: CD.Instance _ CDInstances.Composed[inst, instOfCell.trans];
new.selected _ TRUE;
instances _ CONS[new, instances];
};
[] _ CDCells.EnumerateInstances[cell, EachCellInst];
CDOps.RedrawInstance[comm.design, instOfCell]; --delayed!
cnt _ cnt+1;
someOb _ instOfCell.ob;
};

CantAndPutBack: PROC [inst: CD.Instance, msg: Rope.ROPE] = {
instances _ CONS[inst, instances];
inst.selected _ FALSE;
CDOps.RedrawInstance[comm.design, inst];
TerminalIO.PutF["%g %g; deselected\n",
[rope[CD.Describe[inst.ob, inst.properties, comm.design]]], [rope[msg]]
]; 
};

selected: CD.InstanceList _ NIL;
TerminalIO.PutRope["expand\n"];
[selected, instances] _ CDInstances.SplitSelected[CDOps.InstList[comm.design]];
FOR il: CD.InstanceList _ selected, il.rest WHILE il#NIL DO
IF ~il.first.ob.class.composed THEN CantAndPutBack[il.first, "atomic, can not be expanded"]
ELSE {
ob: CD.Object _ il.first.ob;
WHILE ob#NIL AND ~CDCells.IsCell[ob] DO
ob _ CDDirectory.ExpandRecursed[ob, comm.design, comm.design];
IF ob=il.first.ob THEN ob _ NIL; --to exit loop
IF ob#NIL AND CDCells.IsCell[ob] THEN {
TerminalIO.PutRopes[CD.Describe[il.first.ob, il.first.properties, comm.design], " converted to cell\n"];
[] _ CDDirectoryOps.RemoveIfUnused[comm.design, ob];
}
ENDLOOP;
IF ob#NIL  AND CDCells.IsCell[ob] THEN ExpandIncludeOneCell[il.first, ob] 
ELSE CantAndPutBack[il.first, "can not be converted to cell to expand"]
}
ENDLOOP;
IF cnt>0 THEN CDOps.SetInstList[comm.design, instances];
IF cnt=1 AND someOb#NIL 
THEN TerminalIO.PutRopes[CD.Describe[someOb, NIL, comm.design], " expanded"]
ELSE TerminalIO.PutF1["%g objects expanded\n", IO.int[cnt]];
};

PopFromCellMenu: PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["pop\n"];
IF ~CDCellsInteractions.PopFromCell[comm.design, interactive] THEN 
TerminalIO.PutRope["  not done\n"];
};

PopFromCellFlush: PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["pop and flush\n"];
IF ~CDCellsInteractions.PopFromCell[comm.design, flush] THEN 
TerminalIO.PutRope["  not done\n"];
};

PopFromCellReplace: PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["pop and replace\n"];
IF ~CDCellsInteractions.PopFromCell[comm.design, replace] THEN 
TerminalIO.PutRope["  not done\n"];
};

PopFromCellNew: PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["pop and new\n"];
IF ~CDCellsInteractions.PopFromCell[comm.design, newcell] THEN 
TerminalIO.PutRope["  not done\n"];
};

PruneDirComm: PROC [comm: CDSequencer.Command] = {
pattern: Rope.ROPE _ GetPattern[comm.design];
TerminalIO.PutRope["prune directory\n"]; 
IF ~Rope.IsEmpty[pattern] THEN TerminalIO.PutRopes["    PATTERN [", pattern, "]\n"];
CDDirectoryOps.PruneDirectory[design: comm.design, askFirst: TRUE, pattern: pattern];
};

BorderModeOnComm: PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["set cells(s) draw mode: draw with border\n"]; 
FOR l: CD.InstanceList _ CDOps.InstList[comm.design], l.rest WHILE l#NIL DO
IF l.first.selected THEN {
CDCells.SetBorderMode[l.first.ob, TRUE];
CDOps.RedrawInstance[comm.design, l.first, FALSE];
}
ENDLOOP;
};

BorderModeOffComm: PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["set cells(s) draw mode: draw without border\n"]; 
FOR l: CD.InstanceList _ CDOps.InstList[comm.design], l.rest WHILE l#NIL DO
IF l.first.selected THEN {
CDCells.SetBorderMode[l.first.ob, FALSE];
CDOps.RedrawInstance[comm.design, l.first];
}
ENDLOOP;
};

SetCellSimplificationComm: PROC [comm: CDSequencer.Command] = {
inst: CD.Instance; multiple: BOOL;
TerminalIO.PutRope["set cell simplification #\n"]; 
[inst, multiple] _ CDOps.SelectedInstance[comm.design];
IF multiple THEN TerminalIO.PutRope["   multiple selection; not done\n"] 
ELSE IF inst=NIL THEN TerminalIO.PutRope["   no selection; not done\n"] 
ELSE {
TerminalIO.PutRope[inst.ob.class.describe[inst.ob]];
IF ISTYPE[inst.ob.specific, CD.CellSpecific] THEN {
cptr: CD.CellSpecific ~ NARROW[inst.ob.specific];
h: CD.Number _ MAX[1, inst.ob.bbox.x2-inst.ob.bbox.x1];
TerminalIO.PutF["   [currently: simplification if height < %g pixels", [integer[Real.Round[cptr.simplifyOn*h]]]];
cptr.simplifyOn _ MIN[MAX[TerminalIO.RequestInt[" pixels] type > "], 0], LAST[NAT]]/h;
CDOps.RedrawInstance[comm.design, inst];
TerminalIO.PutRope["   done\n"];
}
ELSE TerminalIO.PutRope[" not a cell; not done\n"]; 
}
};

RenameObjectComm: PROC [comm: CDSequencer.Command] = {
desc: Rope.ROPE; handled: CD.Object; newName: Rope.ROPE;
inst: CD.Instance _ CDOps.TheInstance[comm.design];
IF inst#NIL THEN {
desc _ CD.Describe[inst.ob, inst.properties, comm.design];
newName _ GetObjectName[comm.design, " new name > "];
CDSequencer.MarkChangedIOOnly[comm.design];
IF Rope.IsEmpty[newName] THEN { 
handled _ CDDirectory.Remove[comm.design, CDDirectory.Name[inst.ob, comm.design], inst.ob];
IF handled#NIL THEN {
TerminalIO.PutRopes["  ", desc, " removed from directory\n"];
RETURN
}
}
ELSE { 
IF CDDirectory.Rename[comm.design, inst.ob, newName, FALSE].done THEN { 
TerminalIO.PutF["  %g renamed to %g\n", 
[rope[desc]], [rope[CDDirectory.Name[inst.ob, comm.design]]]
];
RETURN
};
};
TerminalIO.PutRope["  not done\n"]
};
};

SubstituteObjectComm: PROC [comm: CDSequencer.Command] = {
newName, oldName: Rope.ROPE; old, new: CD.Object; 
offset: CD.Position _ [0, 0];
lambda: CD.Number _ comm.design.technology.lambda;
TerminalIO.PutRope["replace object allover in design\n"];
oldName _ TerminalIO.RequestRope["  replace (name) > "];
old _ FindObject[comm.design, oldName];
IF old=NIL THEN {TerminalIO.PutRopes["  ", oldName, " not found\n"]; RETURN};
newName _ TerminalIO.RequestRope["  by (name) > "];
new _ FindObject[comm.design, newName];
IF new=NIL THEN {TerminalIO.PutRopes["  ", newName, " not found\n"]; RETURN};
IF CDImports.OccursInDrawing[x: old, in: new] THEN {
TerminalIO.PutRope["  **infinite recursion; not done\n"];
RETURN
};
TerminalIO.PutRope["  do you want to specify an offset?\n"];
SELECT PopUpSelection.Request[header: "offset", 
choice: LIST["lambda", "ints", "none"]] FROM
1 => {
offset.x _ TerminalIO.RequestInt["  x in lambda >"]*lambda;
offset.y _ TerminalIO.RequestInt["  y in lambda >"]*lambda;
};
2 => {
offset.x _ TerminalIO.RequestInt["  x in ints >"];
offset.y _ TerminalIO.RequestInt["  y in ints >"];
};
ENDCASE => offset _ [0, 0];
CDDirectory.ReplaceObject[design: comm.design, old: old, new: new, trans: [offset, original]];
IF new.class.composed AND old.class.composed THEN
SELECT PopUpSelection.Request[header: "cleanup ?", 
choice: LIST["remove replaced ob from dir", "remove replaced ob from dir and rename other", "no"]] FROM
1 => [] _ CDDirectoryOps.RemoveIfUnused[comm.design, old];
2 => [] _ CDDirectory.Rename[design: comm.design, object: new, newName: oldName, removeFirst: TRUE];
ENDCASE => NULL;
TerminalIO.PutRope["  end replace\n"];
};




ObPredicate: TYPE = PROC [step: StepRec, design: CD.Design, data: REF] RETURNS [BOOL_FALSE];

IsName: ObPredicate = {
RETURN [ Rope.Equal[CDDirectory.Name[step.ob, design], NARROW[data], FALSE] ]
};

IsOb: ObPredicate = {
RETURN [ step.ob = data] 
};

IsText: ObPredicate = {
WITH step.ob.specific SELECT FROM
t: CDTexts.TextSpecific => RETURN [ Rope.Equal[t.text, NARROW[data], TRUE] ]
ENDCASE => NULL
};

IsAddress: ObPredicate = {
RETURN [ LOOPHOLE[step.ob, CARD] = NARROW[data, REF CARD]^] 
};

HandleRec: TYPE = RECORD [
foundOb: CD.Object _ NIL,
seen: RefTab.Ref,
predicate: ObPredicate _ NIL,
predicateData: REF _ NIL,
drawStack: LIST OF StepRec _ NIL
];

found: ERROR[ob: CD.Object] = CODE; --not an error

PrunedDrawChild: CD.DrawProc = {
h: REF HandleRec _ NARROW[pr.devicePrivate];
IF ~RefTab.Insert[h.seen, ob, $x] THEN RETURN;
IF h.predicate[[ob, trans, readOnlyInstProps], pr.design, h.predicateData] THEN {
h.drawStack _ CONS[StepRec[ob, trans, readOnlyInstProps], h.drawStack];
h.foundOb _ ob;
ERROR found[ob]
};
IF ob.class.composed AND ~ob.class.xDesign THEN {
h.drawStack _ CONS[StepRec[ob, trans, readOnlyInstProps], h.drawStack];
CD.DrawOb[pr: pr, ob: ob, trans: trans, readOnlyInstProps: readOnlyInstProps]; 
h.drawStack _ h.drawStack.rest;
};
};

StepRec: TYPE = RECORD [ob: CD.Object, trans: CD.Transformation_[], readOnlyInstProps: CD.PropList_NIL];

Find: PROC [design: CD.Design, predicate: ObPredicate, predicateData: REF _ NIL, stopFlag: REF BOOL _ NIL] RETURNS [object: CD.Object_NIL, drawStack: LIST OF StepRec, pops: INT_0] = {
sf: REF BOOL _ IF stopFlag#NIL THEN stopFlag ELSE NEW[BOOL_FALSE];
h: REF HandleRec = NEW[HandleRec_[
predicate: predicate,
predicateData: predicateData,
seen: RefTab.Create[]
]];
myDrawRef: CD.DrawRef _ CD.CreateDrawRef[[
design: design,
stopFlag: sf,
drawChild: PrunedDrawChild,
drawRect: CDDefaultProcs.IgnoreRect,
drawContext: IgnoreContext,
devicePrivate: h
]];
TryFromLevel: PROC [prec: CD.PushRec] = {
FOR il: CD.InstanceList _ prec.specific.contents, il.rest WHILE il#NIL DO
IF predicate[[il.first.ob, il.first.trans, il.first.properties], design, predicateData] THEN {
object _ h.foundOb _ il.first.ob; 
h.drawStack _ LIST[[il.first.ob, il.first.trans, il.first.properties]]; 
EXIT
};
ENDLOOP;
IF h.foundOb=NIL THEN  
CD.DrawOb[myDrawRef, prec.dummyCell.ob ! found => {object_ob; CONTINUE}];
};
EachOb: CDDirectory.EachObjectProc = {
IF predicate[[me], design, predicateData] THEN {object_me; quit_TRUE}
};
FOR list: LIST OF CD.PushRec _ design.actual, list.rest WHILE list#NIL DO
TryFromLevel[list.first];
IF sf^ THEN RETURN;
IF h.foundOb#NIL THEN {
drawStack _ h.drawStack;
object _ h.foundOb;
RETURN
};
pops _ pops+1;
ENDLOOP; 
[] _ CDDirectory.EnumerateDesign[design: design, proc: EachOb, dir: TRUE, top: FALSE, recurse: TRUE, visited: h.seen];
};

ReverseStepRecList: PROC [list: LIST OF StepRec] RETURNS [rev: LIST OF StepRec_NIL] = {
UNTIL list=NIL DO
rev _ CONS[list.first, rev];
list _ list.rest;
ENDLOOP;
}; 

IsPushedIn: PROC [design: CD.Design, ob: CD.Object _ NIL, address: CARD_0] RETURNS [yes: BOOL_FALSE] = {
FOR pl: LIST OF CD.PushRec _ design.actual, pl.rest WHILE pl#NIL DO
IF pl.first.mightReplace#NIL THEN 
IF pl.first.mightReplace.ob=ob OR address=LOOPHOLE[pl.first.mightReplace.ob, CARD] THEN 
RETURN [yes_TRUE]
ENDLOOP;
};

FindFromRope: PROC [design: CD.Design, name: Rope.ROPE, placeifNotFound: BOOL_TRUE, commHint: REF_NIL, scale: BOOL _ TRUE, selection: BOOL_TRUE] RETURNS [inst: CD.Instance _ NIL] = {

Pops: PROC [design: CD.Design, pops: INT _ LAST[INT]] RETURNS [done: BOOL_TRUE] = {
IF pops>0 AND CDCells.IsPushedIn[design] THEN {
TerminalIO.PutRope["not found in accessible position\n try to pop out\n"];
WHILE CDCells.IsPushedIn[design] AND pops>0 DO
pops _ pops-1;
IF ~ CDCellsInteractions.PopFromCell[design, interactive] THEN {
TerminalIO.PutRope["failed: user did not allow pop out\n"];
RETURN [FALSE]
}
ENDLOOP;
};
};

pushStack: LIST OF StepRec _ NIL; --will be draw stack in reversed order
pops: INT; address: CARD _ 0; ob: CD.Object;
stopFlag: REF BOOL _ NEW[BOOL_FALSE];
CDSequencer.UseAbortFlag[design, stopFlag];
ob _ CDDirectory.Fetch[design, name];
IF ob=NIL THEN address _ Convert.CardFromRope[name ! Convert.Error => {address_0; CONTINUE}];
IF ob#NIL OR address#0 THEN 
IF IsPushedIn[design, ob, address] THEN {
TerminalIO.PutRopes["design is pushed into", name, "\n"]; RETURN [NIL]
};
IF ob#NIL THEN 
[drawStack: pushStack, pops: pops] _ Find[design, IsOb, ob, stopFlag]
ELSE {
IF address#0 THEN 
[object: ob, drawStack: pushStack, pops: pops] _ Find[design, IsAddress, NEW[CARD_address], stopFlag];
IF ob=NIL THEN
[object: ob, drawStack: pushStack, pops: pops] _ Find[design, IsText, name, stopFlag];
IF ob=NIL THEN
[object: ob, drawStack: pushStack, pops: pops] _ Find[design, IsName, name, stopFlag];
}; 
IF pushStack=NIL THEN {
IF stopFlag^ THEN RETURN [NIL];
IF ~placeifNotFound OR ob=NIL THEN {
TerminalIO.PutRope["failed: object not found\n"]; RETURN [NIL]
};
IF ~Pops[design, 10000] THEN RETURN [NIL];
inst _ CDOps.PlaceInst[design, ob, commHint];
TerminalIO.PutRopes["**object ", CD.Describe[ob, NIL, design], " drawn**\n"];
pushStack _ LIST[StepRec[inst.ob, inst.trans, inst.properties]]; 
pops _ 0;
};
IF ~Pops[design, pops] THEN RETURN [NIL];
pushStack _ ReverseStepRecList[pushStack];
WHILE pushStack#NIL DO
IF stopFlag^ THEN RETURN [NIL];
FOR il: CD.InstanceList _ CDOps.InstList[design], il.rest WHILE il#NIL DO
IF il.first.ob=pushStack.first.ob THEN {inst _ il.first; EXIT};
REPEAT FINISHED => {TerminalIO.PutRope["finding object failed\n"]; RETURN [NIL]}
ENDLOOP;
IF pushStack.rest#NIL THEN {
IF ~CDCellsInteractions.PushInCellInstance[design, inst] THEN {
TerminalIO.PutRope["push failed\n"]; RETURN [NIL]
};
};
pushStack _ pushStack.rest
ENDLOOP;
IF selection OR scale THEN {
CDOps.DeselectAll[design];
inst.selected _ TRUE;
CDOps.Redraw[design]; --redraw just in case scaling would fail
};
IF scale THEN 
WITH commHint SELECT FROM
comm: CDSequencer.Command => {
CDSequencer.ExecuteCommand[key: $ResetScaleSel, design: design, queue: dontQueue, comm: comm];
};
ENDCASE => NULL;
};



PushNamed: PROC [design: CD.Design, name: Rope.ROPE, commHint: REF] RETURNS [done: BOOL] = {
inst: CD.Instance _ FindFromRope[design: design, name: name, scale: TRUE, commHint: commHint];
done _ inst#NIL AND CDCellsInteractions.PushInCellInstance[design, inst];
};

PushNamedComm: PROC [comm: CDSequencer.Command] = {
name: Rope.ROPE;
TerminalIO.PutRope["push into cell by name\n"];
WITH comm.data SELECT FROM
r: Rope.ROPE => {name _ r; TerminalIO.PutRopes["push into cell", name, "\n"]};
ENDCASE => {
TerminalIO.PutRope["push into cell by name\n"]; 
name _ GetObjectName[comm.design, "  cell name >"];
TerminalIO.PutRopes["  for: ", name, "\n"]; 
};
Feedback[ PushNamed[comm.design, name, comm] ];
};

AccessNamedComm: PROC [comm: CDSequencer.Command] = {
inst: CD.Instance; name: Rope.ROPE;
TerminalIO.PutRope["access named object\n"]; 
WITH comm.data SELECT FROM
r: Rope.ROPE => {name _ r; TerminalIO.PutRopes["access", name, "\n"]};
ENDCASE => {
TerminalIO.PutRope["access by name\n"]; 
name _ GetObjectName[comm.design, "  cell name >"];
TerminalIO.PutRopes["  for: ", name, "\n"]; 
};
inst _ FindFromRope[design: comm.design, name: name, scale: TRUE, commHint: comm];
Feedback[ inst#NIL ];
};


TransformToCellComm: PROC [comm: CDSequencer.Command] = {
n: INT _ 0;
selection: CD.InstanceList _ CDInstances.OnlySelected[CDOps.InstList[comm.design]];
TerminalIO.PutRope["transform to cell\n"];
FOR l: CD.InstanceList _ selection, l.rest WHILE l#NIL DO
IF l.first.selected AND l.first.ob.class.composed AND ~CDCells.IsCell[l.first.ob] THEN {
cob: CD.Object _ CDDirectory.ExpandRecursed[l.first.ob, comm.design, comm.design];
IF cob#NIL AND cob#l.first.ob THEN {l.first.ob _ cob; n _ n+1}
};
ENDLOOP;
TerminalIO.PutF1["%g objects transformed to cells\n", [integer[n]]];
};

CleanupComm: PROC [comm: CDSequencer.Command] = {
n: INT;
TerminalIO.PutRope["cleanup directory\n"];
n _ CDDirectory.DirSize[comm.design];
CDDirectoryOps.CleanUp[comm.design, NIL];
IF n = CDDirectory.DirSize[comm.design] THEN 
TerminalIO.PutF["design was ok; has %g entries in directory\n", [integer[n]]]
ELSE
TerminalIO.PutF["design was not ok; previously had %g; now has %g entries in directory\n", 
[integer[n]], 
[integer[CDDirectory.DirSize[comm.design]]]
];
};

DefaultIRComm: PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["default the interest rect\n"];
IF comm.design.actual.rest=NIL THEN TerminalIO.PutRope["  not pushed in; not done\n"]
ELSE {
oldWir: CD.Rect _ comm.design^.actual.first.specific.ir;
newWir: CD.Rect _ CDInstances.BoundingRectI[CDOps.InstList[comm.design]];
comm.design.actual.first.specific.ir _ newWir;
comm.design.actual.first.specific.specifiedIr _ FALSE;
CDOps.Redraw[comm.design, CDBasics.Surround[oldWir, newWir]];
};
};

SetIRComm: PROC [comm: CDSequencer.Command] = {
TerminalIO.PutRope["set the interest rect\n"];
IF comm.design.actual.rest=NIL THEN TerminalIO.PutRope["  not pushed in; not done\n"]
ELSE {
mightReplace: CD.Instance _ comm.design^.actual.first.mightReplace;
oldWir: CD.Rect = comm.design^.actual.first.specific.ir;
newWir: CD.Rect = CDBasics.ToRect[comm.pos, comm.sPos]; -- new interest rect 
comm.design.actual.first.specific.ir _ newWir;
comm.design.actual.first.specific.specifiedIr _ TRUE;
CDOps.Redraw[comm.design, CDBasics.Surround[oldWir, newWir]];
};
};


CDSequencer.ImplementCommand[$PopMenu, PopFromCellMenu,, doQueue];
CDSequencer.ImplementCommand[$PopNew, PopFromCellNew,, doQueue];
CDSequencer.ImplementCommand[$PopFlush, PopFromCellFlush,, doQueue];
CDSequencer.ImplementCommand[$PopReplace, PopFromCellReplace,, doQueue];
CDSequencer.ImplementCommand[$PushS, PushComm,, doQueue];
CDSequencer.ImplementCommand[$PushSIconic, PushIntoCellSIconic,, doQueue];
CDSequencer.ImplementCommand[$ExpandS, ExpandComm];
CDSequencer.ImplementCommand[$CreateCellSAndName, CreateCellComm];
CDSequencer.ImplementCommand[$DisplayCellNames, DisplayDirectoryComm,, doQueue];
CDSequencer.ImplementCommand[$DrawCell, DrawByNameComm];
CDSequencer.ImplementCommand[$RemoveCell, RemoveObFromDirComm,, doQueue];
CDSequencer.ImplementCommand[$DeleteUnUsedObjects, PruneDirComm,, doQueue];
CDSequencer.ImplementCommand[$CellSimplification, SetCellSimplificationComm,, doQueue];
CDSequencer.ImplementCommand[$RenameS, RenameObjectComm,, doQueue];
CDSequencer.ImplementCommand[$Replace, SubstituteObjectComm];
CDSequencer.ImplementCommand[$DrawWithoutBorder, BorderModeOffComm];
CDSequencer.ImplementCommand[$DrawWithBorder, BorderModeOnComm];
CDSequencer.ImplementCommand[$PushNamed, PushNamedComm,, doQueue];
CDSequencer.ImplementCommand[$AccessNamed, AccessNamedComm,, doQueue];
CDSequencer.ImplementCommand[$TransformToCellS, TransformToCellComm];
CDSequencer.ImplementCommand[$CheckDir, CleanupComm,, doQueue];
CDSequencer.ImplementCommand[$DefaultIR, DefaultIRComm];
CDSequencer.ImplementCommand[$SetIR, SetIRComm];

CDValue.RegisterKey[$ObjectName, NIL, $chj];
CDValue.Store[NIL, $ObjectName, interactiveKey];
IF UserProfile.Boolean["ChipNDale.ObjectPrefix", FALSE] THEN {
CDPanel.Text[text: [cdValueKey: $ObjectName], button: [text: "object name:"]];
CDPanel.Line[];
};
END. 


������CDCellCommands.mesa   (part of ChipNDale)
Copyright c 1983, 1986, 1987 by Xerox Corporation.  All rights reserved.
Created by Christian Jacobi,  July 11, 1983 3:42 pm
Last Edited by: Christian Jacobi, June 5, 1987 6:51:15 pm PDT
--either find object or makes a message
--replace the instance by an instance of the expanded cell 
--and include the instance into "instances" 
--***find or push named ***
--check if it exists in an easy accessible position on this level
--now try down the recursion
--now use directory
--comm is used to find a viewer used for scale changes...
--	[using the viewer command enables its undo on the scale change]
--Feedback on TerminalIO at least on failure
--pushing-in made a copy of the instance list! check for the right object

ÊT��˜�codešœ)™)Kšœ
Ïmœ=™HKšœ3™3K™=K˜�—šÏk	˜	Kšžœ˜Kšœ	˜	K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ
˜
K˜Kšœ˜Kšœ
˜
Kšœ˜K˜K˜Kšœ˜Kšœ˜K˜K˜Kšœ˜Kšœ˜K˜	K˜Kšœ	˜	Kšœ˜Kšœ˜Kšœ
˜
Kšœ˜—K˜�šÏnœžœž˜Kšžœžœ³žœl˜­—Kšž˜K˜�Kšœžœ˜,K˜�KšŸ
œžœ˜'K˜�šŸœžœžœ˜Kšžœžœžœ#˜NKšœ˜—K˜�š
Ÿ
œžœ
žœ	žœžœ˜EKšœ1˜1Kšžœžœžœ˜,K˜—K˜�šŸ
œžœ
žœžœžœ
žœ˜XKšœ1˜1šžœžœ"žœž˜EKšœ'˜'—K˜—K˜�šŸœžœ ˜4Kšœžœžœ	˜ Kšœ$˜$Kšœ4˜4Kšœ*˜*šžœžœžœ˜Kšœ5˜5Kšœ)˜)Kšœ˜—Kšœ˜K˜�—šŸ
œžœ
žœžœžœ
žœžœ˜YKšÏc'™'Kšœ	žœ˜Kšœ)˜)šžœžœžœ˜KšœCžœ˜Nšžœžœ˜Kšœ!žœžœ˜;šžœžœžœ˜Kšœžœžœ$˜W—K˜—šžœžœžœ˜Kšœ+˜+šžœžœžœ˜Kšœ(žœžœ'˜f—K˜—K˜—KšžœžœžœA˜SK˜K˜�—šŸœžœ ˜9Kšœžœžœžœžœžœ˜7Kšœ5˜5Kšœ4˜4Kšœ1˜1Kšžœžœžœ*˜8šžœ˜šžœ/žœ˜7Kšœ+˜+Kšœ/˜/Kšœ˜—Kšœ˜Kšœ˜—Kšœ˜—K˜�šŸœžœ ˜:K˜�šÏb	œ"˜+Kš :œ˜;Kšœžœ˜
Kšœ˜šžœžœžœ˜Kšžœ8žœžœ˜FK˜—Kšœ˜Kšœžœžœžœ˜5Kšœ˜K˜�—Kšœž
œ˜#Kš
œžœžœžœžœ	žœžœ˜BKšœžœ˜-Kšœ
ž˜Kšœžœ˜Kšœ#˜#Kšœ#žœ˜?šžœžœ˜ Kšœ6˜6Kšœ?žœ˜EKšœ˜—Kšœ3˜3Kšœ-˜-š
žœžœžœžœžœžœž˜6Kšœ3˜3Kšžœ˜—šœ
žœ˜Kšžœžœžœ˜,Kšžœžœ2žœžœ
˜[—Kšœ5˜5šžœ
žœ˜Kšœ=˜=KšœX˜XK˜—Kšžœ˜#Kšœ˜K˜�—šŸœžœ ˜4Kšœ%˜%šžœ6žœžœ˜HKšœ"˜"—Kšœ˜K˜�—šŸœžœ ˜.KšœžœH˜Pšžœžœžœ˜Kšœžœ7˜Mšžœžœ˜!KšœF˜FKšžœžœžœžœ˜ K˜—šžœžœ˜"Kšœ9˜9Kšžœžœ˜?Kšœ˜—Kšœ˜KšœDžœ˜LKšœ˜—Kšœ˜K˜�—šŸœžœ ˜9Kšœžœžœ˜KšœžœU˜]šžœžœžœ˜KšœN˜Nšžœ)žœž˜8Kšœžœ
˜Kšžœžœ˜—šžœžœžœ˜šžœ&žœž˜5Kšœžœ
˜Kšžœžœ˜——šžœžœ˜KšœK˜KKšœ˜K˜—šžœ˜Kšœ4˜4Kšœ/˜/K˜—K˜—Kšœ˜K˜�—šŸ
œžœ ˜0Kšœžœžœ *˜LKšœžœ˜Kšœžœ
žœ 8˜QK˜�šŸœžœžœžœ˜IKšœ;™;Kšœ,™,šŸœ˜(Kšœžœ9˜@Kšœžœ˜Kšœžœ˜!K˜—Kšœ4˜4Kšœ/ 
˜9Kšœ˜Kšœ˜Kšœ˜—K˜�šŸœžœžœžœ˜<Kšœžœ˜"Kšœžœ˜Kšœ(˜(šœ&˜&KšœG˜GKšœ˜—Kšœ˜—K˜�Kšœ
žœžœ˜ Kšœ˜KšœO˜Oš	žœžœ"žœžœž˜;Kšžœžœ8˜[šžœ˜Kšœžœ˜šžœžœžœž˜'Kšœ>˜>Kšžœžœžœ ˜/šžœžœžœžœ˜'KšœžœR˜hKšœ4˜4K˜—Kšžœ˜—Kšžœžœžœžœ$˜JKšžœC˜GK˜—Kšžœ˜—Kšžœžœ+˜8šžœžœžœ˜KšžœH˜LKšžœ+žœ˜<—Kšœ˜K˜�—šŸœžœ ˜5Kšœ˜šžœ<žœ˜CKšœ#˜#—Kšœ˜K˜�—šŸœžœ ˜6Kšœ&˜&šžœ6žœ˜=Kšœ#˜#—Kšœ˜K˜�—šŸœžœ ˜8Kšœ(˜(šžœ8žœ˜?Kšœ#˜#—Kšœ˜K˜�—šŸœžœ ˜4Kšœ$˜$šžœ8žœ˜?Kšœ#˜#—Kšœ˜K˜�—šŸœžœ ˜2Kšœžœ˜-Kšœ)˜)Jšžœžœ6˜TKšœ=žœ˜UKšœ˜K˜�—šŸœžœ ˜6KšœB˜Bš	žœžœ4žœžœž˜Kšžœžœ˜Kšœ"žœ˜(Kšœ+žœ˜2K˜—Kšžœ˜—Kšœ˜K˜�—šŸœžœ ˜7KšœE˜Eš	žœžœ4žœžœž˜Kšžœžœ˜Kšœ"žœ˜)Kšœ+˜+K˜—Kšžœ˜—Kšœ˜K˜�—šŸœžœ ˜?Kšœžœžœ˜"Kšœ3˜3Kšœ7˜7Kšžœ
žœ9˜IKšžœžœžœžœ3˜Hšžœ˜Kšœ4˜4šžœžœžœžœ˜3Kšœžœžœ˜1Kšœžœ
žœ%˜7Kšœq˜qKš	œžœžœ0žœžœ˜VKšœ(˜(Kšœ ˜ K˜—Kšžœ0˜4Kšœ˜—Kšœ˜K˜�—šŸœžœ ˜6Kšœžœžœžœ˜8Kšœžœ+˜3šžœžœžœ˜Kšœžœ1˜:Kšœ5˜5Kšœ+˜+šžœžœ˜ Kšœ[˜[šžœ	žœžœ˜Kšœ=˜=Kšž˜K˜—K˜—šžœ˜šžœ3žœžœ˜Hšœ(˜(Kšœ<˜<Kšœ˜—Kšž˜K˜—Kšœ˜—Kšœ"˜"K˜—Kšœ˜—K˜�šŸœžœ ˜:Kšœžœžœ	˜2Kšœžœ˜Kšœ2˜2Kšœ9˜9Kšœ8˜8Kšœ'˜'Kšžœžœžœ6žœ˜MKšœ3˜3Kšœ'˜'Kšžœžœžœ6žœ˜Mšžœ,žœ˜4Kšœ9˜9Kšž˜K˜—Kšœ<˜<šžœ*˜0Kšœžœž˜,šœ˜Jšœ;˜;Kšœ;˜;Kšœ˜—šœ˜Jšœ2˜2Kšœ2˜2Jšœ˜—Kšžœ˜—Kšœ^˜^šžœžœž˜1šžœ-˜3KšœžœWž˜gKšœ:˜:Kšœ^žœ˜dKšžœžœ˜——Kšœ&˜&Kšœ˜—K˜�K˜�K˜�Kšœ™K˜�Kšœ
žœžœžœžœžœžœžœ˜\K˜�šŸœ˜Kšžœ1žœžœ˜MK˜—K˜�šŸœ˜Kšžœ˜K˜—K˜�šŸœ˜šžœžœž˜!Kšœžœžœžœ˜LKšžœž˜—K˜—K˜�šŸ	œ˜Kšžœžœ
žœžœžœžœ˜<K˜—K˜�šœžœžœ˜Kšœ	žœ
žœ˜Kšœ˜Kšœžœ˜Kšœžœžœ˜Kšœžœžœž˜ K˜—K˜�Kšœžœžœžœ ˜2K˜�šÐbnœžœ
˜ Kšœžœ
žœ˜,Kšžœ žœžœ˜.šžœIžœ˜QKšœžœ5˜GKšœ˜Kšžœ
˜K˜—šžœžœžœ˜1Kšœžœ5˜GKšžœM˜OKšœ˜K˜—Kšœ˜—K˜�Kš
œ	žœžœžœžœ'žœ
žœ˜hK˜�šŸœžœ
žœ0žœžœžœžœžœžœ
žœžœ
žœžœžœ˜·Kšœžœžœžœ
žœžœ
žœžœžœžœ˜Bšœžœ
žœ˜"Kšœ˜Kšœ˜Kšœ˜K˜—šœžœžœ˜*Kšœ˜Kšœ
˜
Kšœ˜Kšœ$˜$Kšœ˜Kšœ˜Kšœ˜—š¢œžœžœ
˜)Kš A™Aš	žœžœ0žœžœž˜IšžœVžœ˜^Kšœ"˜"Kšœžœ6˜HKšž˜Kšœ˜—Kšžœ˜—Kš ™šžœžœžœ˜Kšžœ<žœ˜I—K˜—šŸœ ˜&Kšžœ(žœžœ˜EK˜—š
žœžœžœžœ$žœžœž˜IKšœ˜Kšžœžœžœ˜šžœžœžœ˜Kšœ˜Kšœ˜Kšž˜Kšœ˜—Kšœ˜Kšžœ˜	—K™KšœDžœžœžœ˜vK˜—K˜�šŸœžœžœžœ
žœžœžœ	žœ˜Wšžœžœž˜Kšœžœ˜K˜Kšžœ˜—Kšœ˜—K˜�šŸ
œžœ
žœ
žœ
žœžœžœžœžœ˜hš
žœžœžœžœ"žœžœž˜Cšžœžœžœ˜"š
žœžœ	žœžœžœ˜XKšžœžœ˜——Kšžœ˜—K˜—K˜�šŸœžœ
žœžœžœžœžœžœ	žœžœ
žœžœžœžœžœ˜¶Kš 9™9Kš B™BKš ,™,K˜�šŸœžœ
žœžœžœžœžœžœžœ˜Sšžœžœžœ˜/KšœJ˜Jšžœžœž˜.Kšœ˜šžœ8žœ˜@Kšœ;˜;Kšžœžœ˜K˜—Kšžœ˜—K˜—Jšœ˜K˜�—Kšœžœžœžœ &˜HKšœžœžœ
žœ˜,Kšœ
žœžœžœžœžœ˜%Kšœ+˜+Kšœ%˜%KšžœžœžœDžœ˜]šžœžœžœžœ˜šžœ!žœ˜)Kšœ:žœžœ˜FK˜——šžœžœžœ˜KšœE˜E—šžœ˜šžœžœ˜KšœIžœžœ˜f—šžœžœž˜KšœV˜V—šžœžœž˜KšœV˜V—K˜—šžœžœžœ˜Kšžœžœžœžœ˜šžœžœžœžœ˜$Kšœ2žœžœ˜>Kšœ˜—Kšžœžœžœžœ˜*Kšœ-˜-Kšœ!žœžœ˜MKšœžœ1˜AKšœ	˜	K˜—Kšžœžœžœžœ˜)Kšœ*˜*šžœžœž˜š CÐbc™IKšžœžœžœžœ˜š	žœžœ0žœžœž˜IKšžœ žœžœ˜?Kšžœžœ4žœžœ˜PKšžœ˜——šžœžœžœ˜šžœ7žœ˜?Kšœ%žœžœ˜1K˜—K˜—Kšœ˜Kšžœ˜—šžœžœžœ˜Kšœ˜Kšœžœ˜Kšœ (˜>K˜—šžœžœ˜šžœ
žœž˜šœ˜Kšœ^˜^K˜—Kšžœžœ˜——Kšœ˜—K˜�K˜�J˜�šŸ	œžœ
žœžœžœžœžœ˜\Kšœžœ<žœ˜^Kšœžœžœ6˜IK˜—K˜�šŸ
œžœ ˜3Kšœžœ˜Kšœ/˜/šžœžœž˜KšœžœB˜Nšžœ˜Kšœ0˜0Kšœ3˜3Kšœ,˜,K˜——Kšœ/˜/Kšœ˜K˜�—šŸœžœ ˜5Kšœžœžœ˜#Kšœ-˜-šžœžœž˜Kšœžœ:˜Fšžœ˜Kšœ(˜(Kšœ3˜3Kšœ,˜,K˜——Kšœ<žœ˜RKšœžœ˜Kšœ˜K˜�—K™�K˜�šŸœžœ ˜9Kšœžœ˜KšœžœF˜SKšœ*˜*š	žœžœ"žœžœž˜9šžœžœžœžœ˜XKšœžœK˜RKšžœžœžœžœ˜>Kšœ˜—Kšžœ˜—KšœD˜DKšœ˜K˜�—š¢œžœ ˜1Kšœžœ˜Kšœ*˜*Kšœ%˜%Kšœ$žœ˜)šžœ&žœ˜-KšœM˜M—šž˜Kšœ™˜™—Kšœ˜—K˜�šŸ
œžœ ˜3K˜2Kšžœžœžœ2˜Ušžœ˜Kšœžœ.˜8Kšœžœ?˜IKšœ.˜.Kšœ0žœ˜6Kšœ=˜=K˜—Kšœ˜—K˜�šŸ	œžœ ˜/K˜.Kšžœžœžœ2˜Ušžœ˜KšœC˜CKšœžœ.˜8Kšœžœ- ˜MKšœ.˜.Kšœ0žœ˜5Kšœ=˜=K˜—Kšœ˜—K˜�K˜�KšœB˜BKšœ@˜@KšœD˜DKšœH˜HKšœ9˜9KšœJ˜JKšœ3˜3KšœB˜BKšœP˜PKšœ8˜8KšœI˜IKšœK˜KKšœW˜WKšœC˜CKšœ=˜=KšœD˜DKšœ@˜@KšœB˜BKšœF˜FKšœE˜EKšœ?˜?Kšœ8˜8Kšœ0˜0K˜�Kšœ!žœ˜,Kšœžœ˜0šžœ/žœžœ˜>KšœN˜NK˜K˜—Kšžœ˜K˜�K˜�—�…—����^¬��}���