CDPushByNameCommands.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
by: Ch. Jacobi, February 16, 1985 6:55:29 pm PST
Last Edited by: Ch. Jacobi, February 18, 1985 10:39:34 am PST
DIRECTORY
TerminalIO,
CD,
CDDirectory,
CDCells,
CDSimpleOps,
CDSequencer,
CDOps,
CDCommandOps,
CDBasics,
CDMenus USING [CreateEntry],
CDMarks,
Rope;
CDPushByNameCommands: CEDAR PROGRAM
IMPORTS TerminalIO, CD, CDCells, CDSimpleOps, CDDirectory, CDMarks, CDMenus, CDSequencer, CDOps, CDCommandOps =
BEGIN
foundAndStop: SIGNAL = CODE;
--the global variables mare monitored using CDCommandOps.CallWithResource;
--these variables are global so they can b used by MyDrawChild
stopFlag: REF BOOLEAN = NEW[BOOLEAN];
iDidIt: BOOL;
mark: CDMarks.MarkRange;
cell: CD.ObPtr;
drawStack: CD.ApplicationList;
MyDrawChild: CD.DrawProc =
--PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: REF CD.DrawInformation]
BEGIN
IF aptr.ob=cell THEN {
drawStack ← CONS[aptr, drawStack];
iDidIt ← TRUE;
SIGNAL foundAndStop
};
WITH aptr.ob.specificRef SELECT FROM
cp: CD.CellPtr => {
IF aptr.ob.marked#mark THEN {
aptr.ob.marked ← mark;
drawStack ← CONS[aptr, drawStack];
aptr.ob.p.drawMe[aptr: aptr, pos: aptr.location, orient: aptr.orientation, pr: pr];
drawStack ← drawStack.rest;
};
};
ENDCASE => NULL;
END;
ProtectedPushNamedCellComm: PROCEDURE [comm: CDSequencer.Command] =
BEGIN
pushStack: CD.ApplicationList ← NIL; --will be draw stack in reversed order
name: Rope.ROPE;
design: CD.Design ← comm.design;
myDrawRef: CD.DrawRef;
localMark: CDMarks.MarkRange;
--get name, find if cell really exists
drawStack ← NIL;
iDidIt ← FALSE;
name ← TerminalIO.RequestRope["cell name >"];
cell ← CDDirectory.Fetch[design, name].object;
IF cell=NIL THEN {
TerminalIO.WriteRope["design, does not have this cell\n"];
RETURN
};
IF ~ISTYPE[cell.specificRef, CD.CellPtr] THEN {
TerminalIO.WriteRope["object is not a cell\n"];
RETURN
};
--if we are already pushed in, it would not harm the program,
--but it is checked because it would confuse the designer
FOR pl: LIST OF CD.PushRec ← design.actual, pl.rest WHILE pl#NIL DO
IF pl.first.mightReplace#NIL AND pl.first.mightReplace.ob=cell THEN {
TerminalIO.WriteRope["design is already pushed in\n"];
RETURN
}
ENDLOOP;
--check if a path to the cell exists, and build the path
localMark ← CDMarks.GetNewMark[design ! CDMarks.PreviousMarkWasNotReleased => GOTO markError];
mark ← localMark;
myDrawRef ← CD.CreateDrawRef[design];
myDrawRef.interestClip ← CDBasics.universe;
myDrawRef.drawChild ← MyDrawChild;
--draw only from pushed in cell point in hierarchy
design.actual.first.dummyCell.ob.p.drawMe[aptr: design.actual.first.dummyCell, pos: [0, 0], orient: CD.original, pr: myDrawRef ! foundAndStop => CONTINUE];
CDMarks.ReleaseMark[design, localMark];
IF ~iDidIt THEN {
TerminalIO.WriteRope["sorry, cell not foundAndStop in accessible position\n"];
RETURN
};
--there is a path
--make pushStack in push order; (reverse order as drawStack)
WHILE drawStack#NIL DO
pushStack ← CONS[drawStack.first, pushStack];
drawStack ← drawStack.rest
ENDLOOP;
--do the pushes
WHILE pushStack#NIL DO
--select exclusively the application we want to push in
--pushing in makes a copy of the application list! check for the right object
CDSimpleOps.DeselectAll[design];
FOR al: CD.ApplicationList ← CDOps.AppList[design], al.rest WHILE al#NIL DO
IF al.first.ob=pushStack.first.ob THEN {
al.first.selected ← TRUE;
EXIT
};
REPEAT FINISHED => {
TerminalIO.WriteRope["finding cell failed\n"];
RETURN
}
ENDLOOP;
IF ~CDCells.PushInCellSelected[design] THEN {
TerminalIO.WriteRope["push failed\n"];
RETURN
};
pushStack ← pushStack.rest
ENDLOOP;
--we are successully pushed in
--position the viewer
CDSequencer.ExecuteCommand[comm, design, $ResetScaleTop, dontQueue];
TerminalIO.WriteRope["done\n"];
--help the garbage collector
myDrawRef ← NIL;
pushStack ← drawStack ← NIL;
EXITS
markError => {
TerminalIO.WriteRope["**inconsistent use of mark\n"];
}
END;
PushNamedCellComm: PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["Push into cell by name\n"];
[] ← CDCommandOps.CallWithResource[ProtectedPushNamedCellComm, comm, $myDrawRef, stopFlag];
END;
CDMenus.CreateEntry[menu: $CellMenu, entry: "push named", key: $PushNamedCell];
CDSequencer.ImplementCommand[$PushNamedCell, PushNamedCellComm,, doQueue];
END.