<> <> <> <> 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: design, interestClip: CDBasics.universe, 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[$ResetScaleTop, design, dontQueue, comm]; 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.