<> <> <> <> 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.