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, July 1, 1985 11:43:41 am PDT
DIRECTORY
TerminalIO,
CD,
CDDirectory,
CDCells,
CDSequencer,
CDOps,
CDCommandOps,
CDBasics,
CDMenus USING [CreateEntry],
CDMarks,
Rope;
CDPushByNameCommands: CEDAR PROGRAM
IMPORTS TerminalIO, CD, CDCells, 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;
gMark: CDMarks.MarkRange;
cell: CD.Object;
drawStack: CD.InstanceList;
MyDrawChild: CD.DrawProc =
--PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: REF CD.DrawInformation]
BEGIN
IF inst.ob=cell THEN {
drawStack ← CONS[inst, drawStack];
iDidIt ← TRUE;
SIGNAL foundAndStop
};
WITH inst.ob.specificRef SELECT FROM
cp: CD.CellPtr => {
IF inst.ob.marked#gMark THEN {
inst.ob.marked ← gMark;
drawStack ← CONS[inst, drawStack];
inst.ob.class.drawMe[inst: inst, pos: inst.location, orient: inst.orientation, pr: pr];
drawStack ← drawStack.rest;
};
};
ENDCASE => NULL;
END;
ProtectedPushNamedCellComm: PROCEDURE [comm: CDSequencer.Command] =
BEGIN
pushStack: CD.InstanceList ← NIL; --will be draw stack in reversed order
name: Rope.ROPE;
design: CD.Design ← comm.design;
myDrawRef: CD.DrawRef;
DoWithMark: PROC [mark: CDMarks.MarkRange] =
BEGIN
gMark ← mark;
--draw only from pushed in cell point in hierarchy
design.actual.first.dummyCell.ob.class.drawMe[inst: design.actual.first.dummyCell, pos: [0, 0], orient: CD.original, pr: myDrawRef ! foundAndStop => CONTINUE];
END;
--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
myDrawRef ← CD.CreateDrawRef[design];
myDrawRef.interestClip ← CDBasics.universe;
myDrawRef.drawChild ← MyDrawChild;
CDMarks.DoWithMark[comm.design, DoWithMark ! CDMarks.MarkOccupied => GOTO markError];
IF ~iDidIt THEN {
TerminalIO.WriteRope["sorry, cell not found 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
inst: CD.Instance ← 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.WriteRope["finding cell failed\n"];
RETURN
}
ENDLOOP;
IF ~CDCells.PushInCellInstance[design, inst] 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.