<> <> <> <> DIRECTORY BasicTime, CD, CDBasics, CDInstances, CDLayers, CDOps, CDRects, CDSequencer, CDValue, IO, PopUpSelection, Rope, TerminalIO; CDBasicCommands: CEDAR PROGRAM IMPORTS BasicTime, CDInstances, CDLayers, CDOps, CDSequencer, CDValue, PopUpSelection, TerminalIO, CDRects, CDBasics = BEGIN <<-- common xxxxxxxxxxxxxxxxxxxxxx>> <<>> DescribeInst: PROC [inst: CD.Instance, design: CD.Design_NIL] RETURNS [r: Rope.ROPE] = { r _ CDOps.InstRope[inst, design]; <> <> <<};>> }; <<>> <<-- selections xxxxxxxxxxxxxxxxxxxxxx>> MatchLayer: PROC [template, found: CD.Layer] RETURNS [BOOL] = INLINE { IF template#CD.undefLayer THEN IF CDLayers.AbstractToPaint[template]#CDLayers.AbstractToPaint[found] THEN RETURN [FALSE]; RETURN [TRUE] }; RectDist: PROC [pos: CD.Position, r: CD.Rect] RETURNS [CD.Number] = { <<--Distance between a point and a rectangle>> RETURN [MAX[ (IF pos.xr.x2 THEN (pos.x-r.x2) ELSE 0), (IF pos.yr.y2 THEN (pos.y-r.y2) ELSE 0) ]] }; ComputeBB: PROC [list: CD.InstanceList, selectedOnly: BOOL_FALSE] RETURNS [bound: CD.Rect_CDBasics.empty, cnt: INT_0] = { FOR l: LIST OF CD.Instance _ list, l.rest WHILE l#NIL DO IF selectedOnly AND NOT l.first.selected THEN LOOP; cnt _ cnt+1; bound _ CDBasics.Surround[bound, CDInstances.InstRectO[l.first]] ENDLOOP; }; <<--Crazy heuristics to determine which kind of selection is wanted >> <<--these variables are used by PROC ReUseSameSelection only>> lastPos: CD.Position; lastKey: REF _ NIL; lastTime: BasicTime.GMT _ BasicTime.earliestGMT; ReUseSameSelection: PROC [comm: CDSequencer.Command] RETURNS [yes: BOOL] = { lambda: CD.Number = comm.design.technology.lambda; ReallyClose: PROC [p1, p2: CD.Position] RETURNS [BOOL] = INLINE { RETURN [ABS[p1.x-p2.x]<=lambda AND ABS[p1.y-p2.y]<=lambda] }; now: BasicTime.GMT _ BasicTime.Now[]; yes _ ReallyClose[lastPos, comm.pos] AND lastKey=comm.key AND BasicTime.Period[lastTime, now]<=2; lastPos _ comm.pos; lastKey _ comm.key; lastTime _ now; }; Select: PROC [design: CD.Design, pos: CD.Position] = { <<--Select an instance at position pos>> sel: CD.Instance _ NIL; <<--check whether a different instances should be selected>> FOR w: CD.InstanceList _ CDOps.InstList[design], w.rest WHILE w#NIL DO IF ~w.first.selected THEN { IF CDInstances.PointToI[pos, w.first] THEN {sel _ w.first; EXIT} }; ENDLOOP; IF sel#NIL THEN { <<--a new instance will be selected>> sel.selected _ TRUE; <<--reorder list, future selection will selects next lower instance>> CDOps.ReOrderInstance[design, sel]; CDOps.RedrawInstance[design, sel]; TerminalIO.PutRope[DescribeInst[sel, design]]; } ELSE { <<--no new instance found; can we select an already selected one?>> FOR w: CD.InstanceList _ CDOps.InstList[design], w.rest WHILE w#NIL DO IF w.first.selected THEN { IF CDInstances.PointToI[pos, w.first] THEN { TerminalIO.PutRopes[DescribeInst[w.first, design], " again"]; RETURN } }; ENDLOOP; TerminalIO.PutRope[" no pointed object"]; } }; DeSelect: PROC [design: CD.Design, pos: CD.Position] = { <<--Deselect an instance at position pos>> inst: CD.Instance _ CDInstances.InstanceAt[CDOps.InstList[design], pos, TRUE]; IF inst#NIL THEN { inst.selected _ FALSE; CDOps.RedrawInstance[design, inst]; <<--reorder list, future selection will find next instance>> CDOps.ReOrderInstance[design, inst]; }; TerminalIO.PutRope[DescribeInst[inst, design]]; }; AreaSelect: PROC [design: CD.Design, area: CD.Rect, includePartial: BOOL_FALSE] = { FOR w: CD.InstanceList _ CDOps.InstList[design], w.rest WHILE w#NIL DO IF ~w.first.selected THEN { IF CDBasics.Intersect[area, CDInstances.InstRectI[w.first]] THEN IF includePartial OR CDBasics.Inside[CDInstances.InstRectI[w.first], area] THEN { w.first.selected _ TRUE; CDOps.RedrawInstance[design, w.first, FALSE]; }; }; ENDLOOP; }; AreaDeSelect: PROC [design: CD.Design, area: CD.Rect, includePartial: BOOL_FALSE] = { FOR w: CD.InstanceList _ CDOps.InstList[design], w.rest WHILE w#NIL DO IF w.first.selected THEN { IF CDBasics.Intersect[area, CDInstances.InstRectI[w.first]] THEN IF includePartial OR CDBasics.Inside[CDInstances.InstRectI[w.first], area] THEN { w.first.selected _ FALSE; CDOps.RedrawInstance[design, w.first]; }; }; ENDLOOP; }; SelectExclusiveComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["select pointed "]; CDOps.DeselectAll[comm.design, FALSE]; Select[comm.design, comm.pos]; TerminalIO.PutRope["\n"]; }; ReSelectExclusive: PROC [design: CD.Design, pos: CD.Position, verbose: BOOL_TRUE, layer: CD.Layer_CD.undefLayer] RETURNS [done: BOOL_TRUE] = { Deselect: PROC [i: CD.Instance] = INLINE { IF i.selected THEN { i.selected _ FALSE; CDOps.RedrawInstance[design, i] } }; DeselectList: PROC [list: CD.InstanceList] = { FOR w: CD.InstanceList _ list, w.rest WHILE w#NIL DO Deselect[w.first] ENDLOOP }; ValidForSelection: PROC [inst: CD.Instance] RETURNS [BOOL] = INLINE { RETURN [ CDInstances.PointToI[pos, inst] AND MatchLayer[layer, inst.ob.layer] ]; }; inst: CD.Instance _ NIL; --any instance where pos points to FOR w: CD.InstanceList _ CDOps.InstList[design], w.rest WHILE w#NIL DO IF ValidForSelection[w.first] THEN { <<--hit>> IF w.first.selected THEN { DeselectList[w.rest]; CDOps.ReOrderInstance[design, w.first]; IF verbose THEN TerminalIO.PutRope[DescribeInst[w.first, design]]; RETURN } ELSE IF inst=NIL THEN inst _ w.first } ELSE Deselect[w.first] ENDLOOP; <<--if a selected inst is pointed we already did return>> IF inst#NIL THEN { inst.selected _ TRUE; CDOps.ReOrderInstance[design, inst]; CDOps.RedrawInstance[design, inst, FALSE]; IF verbose THEN TerminalIO.PutRope[DescribeInst[inst, design]] } ELSE { done _ FALSE; IF verbose THEN TerminalIO.PutRope[" (no object)"]; } }; CloseReSelectExclusive: PROC [design: CD.Design, pos: CD.Position, verbose: BOOL_TRUE, dist: CD.Number_100, layer: CD.Layer_CD.undefLayer] = { IF ~ReSelectExclusive[design, pos, verbose, layer] THEN { inst: CD.Instance _ NIL; FOR w: CD.InstanceList _ CDOps.InstList[design], w.rest WHILE w#NIL DO d: CD.Number = RectDist[pos, CDInstances.InstRectI[w.first]]; IF d> <<--(but dont select an other instance if the pointed one is already the right one)>> TerminalIO.PutRope["select "]; [] _ ReSelectExclusive[comm.design, comm.pos]; TerminalIO.PutRope["\n"]; }; ReSelectExclusiveWithLayerComm: PROC [comm: CDSequencer.Command] = { <<--select pointed instance of right layer exclusive>> layer: CD.Layer _ CDLayers.AbstractToPaint[CDLayers.PlaceholderToAbstract[comm.design, CDLayers.CurrentLayer[comm.design]]]; TerminalIO.PutF["select with layer %g ", [rope[CDOps.LayerRope[layer]]]]; [] _ ReSelectExclusive[comm.design, comm.pos, TRUE, layer]; TerminalIO.PutRope["\n"]; }; CloseReSelectComm: PROC [comm: CDSequencer.Command] = { <<--select pointed instance exclusive;>> <<--(but dont select an other instance if the pointed one is already the right one)>> <<--if there is none, select closest>> <<--cycle through if exactly sme position>> TerminalIO.PutRope["select "]; IF ReUseSameSelection[comm] THEN CDOps.DeselectAll[comm.design, FALSE]; [] _ CloseReSelectExclusive[comm.design, comm.pos, TRUE, 50]; TerminalIO.PutRope["\n"]; }; MultiOnlySelectComm: PROC [comm: CDSequencer.Command] = { ReallyClose: PROC [p1, p2: CD.Position] RETURNS [BOOL] = INLINE { RETURN [ABS[p1.x-p2.x]<=lambda OR ABS[p1.y-p2.y]<=lambda] }; lambda: CD.Number = comm.design.technology.lambda; IF ReallyClose[comm.pos, comm.sPos] THEN CloseReSelectComm[comm] ELSE AreaOnlySelectComm[comm]; }; DoubleAddSelectComm: PROC [comm: CDSequencer.Command] = { IF ReUseSameSelection[comm] THEN { TerminalIO.PutRope["change selection "]; [] _ DeSelectLast[comm.design, comm.pos, TRUE]; } ELSE TerminalIO.PutRope["add selection "]; Select[comm.design, comm.pos]; TerminalIO.PutRope["\n"]; }; DeselectPointedComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["remove selection "]; DeSelect[comm.design, comm.pos]; TerminalIO.PutRope["\n"]; }; DeSelectLast: PROC [design: CD.Design, pos: CD.Position, usePos: BOOL_TRUE] RETURNS [done: BOOL_FALSE] = { sel: CD.Instance _ NIL; FOR w: CD.InstanceList _ CDOps.InstList[design], w.rest WHILE w#NIL DO IF w.first.selected THEN { IF ~usePos OR CDInstances.PointToI[pos, w.first] THEN sel _ w.first; }; ENDLOOP; IF sel#NIL THEN { sel.selected _ FALSE; done _ TRUE; CDOps.RedrawInstance[design, sel] } }; DeselectLastSelectedComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["remove selection "]; [] _ DeSelectLast[comm.design, comm.pos, TRUE]; TerminalIO.PutRope["\n"]; }; AddSelectionComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["add selection "]; Select[comm.design, comm.pos]; TerminalIO.PutRope["\n"]; }; DeselectAllComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["de-select all\n"]; CDOps.DeselectAll[comm.design, FALSE] }; SelectAllComm: PROC [comm: CDSequencer.Command] = { cnt: INT _ 0; TerminalIO.PutRope["select all: "]; CDOps.DeselectAll[comm.design, TRUE]; FOR w: CD.InstanceList _ CDOps.InstList[comm.design], w.rest WHILE w#NIL DO cnt _ cnt+1; ENDLOOP; TerminalIO.PutF1["%g selected objects\n", [integer[cnt]]]; }; AreaAddSelectComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["inclusive select area\n"]; AreaSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]] }; MultiAddSelectComm: PROC [comm: CDSequencer.Command] = { <<--Auto select area or pointed or changed>> NotRect: PROC [p1, p2: CD.Position] RETURNS [BOOL] = INLINE { RETURN [ABS[p1.x-p2.x]<=lambda OR ABS[p1.y-p2.y]<=lambda] }; lambda: CD.Number = comm.design.technology.lambda; IF NotRect[comm.pos, comm.sPos] THEN DoubleAddSelectComm[comm] ELSE { TerminalIO.PutRope["select inclusive area\n"]; AreaSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]] } }; AreaAddSelectTouchingComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["select inclusive touching\n"]; AreaSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos], TRUE] }; AreaOnlySelectComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["select area\n"]; CDOps.DeselectAll[comm.design, FALSE]; AreaSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]] }; ADeSelectComm: PROC [comm: CDSequencer.Command] = { <<--Auto deselect area or pointed>> TerminalIO.PutRope["de-select "]; IF comm.pos=comm.sPos THEN DeSelect[comm.design, comm.pos] ELSE AreaDeSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]]; TerminalIO.PutRope["\n"]; }; AreaDeSelectComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["de-select area\n"]; AreaDeSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]] }; AreaDeSelectTouchingComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["de-select touching\n"]; AreaDeSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos], TRUE] }; <<-- xx delete, abort xxxxxxxxxxxxxxxxxxxxxx>> <<>> DeleteSelected: PROC [design: CD.Design] = { toDelete, newContents: CD.InstanceList; count: INT _ 0; [selected: toDelete, others: newContents] _ CDInstances.SplitSelected[CDOps.InstList[design]]; CDOps.SetInstList[design, newContents]; CDOps.Remember[design, toDelete]; FOR w: CD.InstanceList _ toDelete, w.rest WHILE w#NIL DO count _ count+1; CDOps.RedrawInstance[design, w.first, TRUE]; ENDLOOP; IF count#1 THEN TerminalIO.PutF1["%g objects", [integer[count]]] ELSE TerminalIO.PutRope[DescribeInst[toDelete.first, design]] }; DeleteSelectedComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["delete selected "]; DeleteSelected[comm.design]; TerminalIO.PutRope["\n"]; }; UndeleteComm: PROC [comm: CDSequencer.Command] = { il: CD.InstanceList _ CDOps.GetRemembered[comm.design]; TerminalIO.PutRope["un-delete\n"]; CDOps.IncludeInstanceList[comm.design, il]; }; AbortComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["try to abort current command\n"]; CDSequencer.AbortDesignsCommand[comm.design] }; <<-- xx wires xxxxxxxxxxxxxxxxxxxxxx>> AddARect: PROC [design: CD.Design, r: CD.Rect, l: CD.Layer] = { IF ~CDBasics.NonEmpty[r] THEN TerminalIO.PutRope["empty rect not included\n"] ELSE { orient: CD.Orientation _ original; sz: CD.Position _ CDBasics.SizeOfRect[r]; IF sz.y> <<--temporary wires in the rubber banding part>> start: CD.Position _ comm.sPos; stop: CD.Position _ comm.pos; wireWidth: CD.Number _ comm.n; IF wireWidth=0 THEN {AddRectComm[comm]; RETURN}; TerminalIO.PutRope["draw wire\n"]; IF --firstHorizontal-- comm.b THEN { IF stop.x<=start.x AND stop.x>=start.x-wireWidth AND (stop.ystart.y+wireWidth) THEN { --crazy vertical wire IF ABS[start.y-stop.y]> IF stop.y>=start.y AND stop.y<=start.y+wireWidth THEN { --horizontal wire stop.y _ start.y+wireWidth; AddARect[comm.design, CDBasics.ToRect[start, stop], comm.l] } ELSE { --L shaped (firsthorizontal) IF start.x<=stop.x THEN {stop.x _ stop.x+wireWidth} ELSE {t: CD.Number=stop.x; stop.x _ start.x; start.x _ t}; stop.y _ start.y+wireWidth; AddARect[comm.design, CDBasics.ToRect[start, stop], comm.l]; IF firstOnly THEN RETURN; start.x _ comm.pos.x; stop.y _ comm.pos.y; stop.x _ start.x+wireWidth; AddARect[comm.design, CDBasics.ToRect[start, stop], comm.l]; } } ELSE { -- NOT firstHorizontalVC -- IF stop.y<=start.y AND stop.y>=start.y-wireWidth AND (stop.xstart.x+wireWidth) THEN { --crazy horizontal wire IF ABS[stop.x-start.x]> IF stop.x>=start.x AND stop.x<=start.x+wireWidth THEN { --vertical wire stop.x _ start.x+wireWidth; AddARect[comm.design, CDBasics.ToRect[start, stop], comm.l] } ELSE { --L shaped (firstVertical) IF start.y<=stop.y THEN {stop.y _ stop.y+wireWidth} ELSE {t: CD.Number = stop.y; stop.y _ start.y; start.y _ t}; stop.x _ start.x+wireWidth; AddARect[comm.design, CDBasics.ToRect[start, stop], comm.l]; IF firstOnly THEN RETURN; start.y _ comm.pos.y; stop.y _ start.y+wireWidth; stop.x _ comm.pos.x; AddARect[comm.design, CDBasics.ToRect[start, stop], comm.l]; } } }; AddRectComm: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["draw rect\n"]; AddARect[comm.design, CDBasics.ToRect[comm.sPos, comm.pos], comm.l]; }; AddWireComm: PROC [comm: CDSequencer.Command] = { <<--uses pos, sPos, n (for width), b (for firstHorizontal), l (for layer)>> InternalAddWire[comm: comm, firstOnly: FALSE] }; ContinueWireComm: PROC [comm: CDSequencer.Command] = { InternalAddWire[comm: comm, firstOnly: TRUE] }; <<-- moves and copies xxxxxxxxxxxxxxxxxxxxxx>> RedrawMoved: PROC [design: CD.Design, r: CD.Rect, offset: CD.Position] = { moved: CD.Rect _ CDBasics.MoveRect[r, offset]; IF CDBasics.Intersect[r, moved] THEN CDOps.Redraw[design, CDBasics.Surround[r, moved], TRUE] ELSE { CDOps.Redraw[design, r]; CDOps.Redraw[design, moved]; -- use eraseFirst because also used by copy } }; OrientSelected: PROC [design: CD.Design, transform: CD.Orientation, base: CD.Rect_[0,0,-1,-1]] = { <<--Orientates the selection such that:>> <<--takes the base rectangle, transforms orientation and translates the transformed rectangle >> <<--to fit its lower left point [after transformation] to be at the same point as the lower left >> <<--point of the base rectangle before the transformation. >> <<--If base is empty, use bbox of selection. >> ib, is, orientOff: CD.Position; r, oldbb: CD.Rect; oldPseudoCellT, newPseudoCellT: CD.Transformation; sel: CD.InstanceList = CDInstances.OnlySelected[CDOps.InstList[design]]; IF sel=NIL THEN RETURN; oldbb _ CDInstances.BoundingRectO[sel]; IF ~CDBasics.NonEmpty[base] THEN base _ CDInstances.BoundingRectI[sel]; ib _ CDBasics.BaseOfRect[base]; is _ CDBasics.SizeOfRect[base]; oldPseudoCellT _ [ib, original]; r _ CDBasics.MapRect[CDBasics.RectAt[[0,0], is], [[0,0], transform]]; orientOff _ CDBasics.BaseOfRect[r]; newPseudoCellT _ [CDBasics.SubPoints[ib, orientOff], transform]; FOR w: CD.InstanceList _ sel, w.rest WHILE w#NIL DO pseudoCellRel: CD.Transformation _ CDBasics.DecomposeTransform[w.first.trans, oldPseudoCellT]; w.first.trans _ CDBasics.ComposeTransform[pseudoCellRel, newPseudoCellT] ENDLOOP; CDOps.Redraw[design, oldbb]; CDOps.Redraw[design, CDBasics.MapRect[CDBasics.DeMapRect[oldbb, oldPseudoCellT], newPseudoCellT]] }; MoveSelected: PROC [design: CD.Design, offset: CD.Position] = { sel: CD.InstanceList = CDInstances.OnlySelected[CDOps.InstList[design]]; bounding: CD.Rect _ CDBasics.empty; FOR w: CD.InstanceList _ sel, w.rest WHILE w#NIL DO inst: CD.Instance _ w.first; bounding _ CDBasics.Surround[bounding, CDInstances.InstRectO[inst]]; inst.trans.off _ CDBasics.AddPoints[inst.trans.off, offset]; ENDLOOP; RedrawMoved[design, bounding, offset] }; CopySelected: PUBLIC PROC [design: CD.Design, offset: CD.Position] = { new: CD.InstanceList_NIL; sel: CD.InstanceList = CDInstances.OnlySelected[CDOps.InstList[design]]; bounding: CD.Rect _ CDInstances.BoundingRectO[sel]; FOR w: CD.InstanceList _ sel, w.rest WHILE w#NIL DO inst: CD.Instance _ CDInstances.Copy[w.first]; inst.trans.off _ CDBasics.AddPoints[inst.trans.off, offset]; inst.selected _ TRUE; new _ CONS[inst, new]; w.first.selected _ FALSE; ENDLOOP; CDOps.IncludeInstanceList[design, new, FALSE]; RedrawMoved[design, bounding, offset]; }; TransformS: PROC [comm: CDSequencer.Command] = { n: CARDINAL; TerminalIO.PutRope["transform: "]; n _ PopUpSelection.Request[ header: "transform", choice: LIST["mirror x", "mirror y", "rot 90", "rot 180", "rot 270"]]; SELECT n FROM 1 => {TerminalIO.PutRope["mirror x\n"]; OrientSelected[comm.design, mirrorX]}; 2 => {TerminalIO.PutRope["mirror y\n"]; OrientSelected[comm.design, rotate180]; OrientSelected[comm.design, mirrorX]}; 3 => {TerminalIO.PutRope["rot 90\n"]; OrientSelected[comm.design, rotate90]}; 4 => {TerminalIO.PutRope["rot 180\n"]; OrientSelected[comm.design, rotate180]}; 5 => {TerminalIO.PutRope["rot 270\n"]; OrientSelected[comm.design, rotate270]}; ENDCASE => TerminalIO.PutRope["Skipped\n"]; }; RotS: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["rotate counterclockwise\n"]; OrientSelected[comm.design, rotate90] }; MirrorS: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["mirror on x axis\n"]; OrientSelected[comm.design, mirrorX] }; MirrorYS: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["mirror on y axis\n"]; OrientSelected[comm.design, CD.mirrorY]; }; SimpleMoveSCommand: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["move (no stretch)\n"]; MoveSelected[design: comm.design, offset: CD.Position[comm.pos.x-comm.sPos.x, comm.pos.y-comm.sPos.y]] }; CopySCommand: PROC [comm: CDSequencer.Command] = { IF comm.pos.x#comm.sPos.x OR comm.pos.y#comm.sPos.y THEN { IF comm.data#NIL AND comm.data#comm.design AND ISTYPE[comm.data, CD.Design] THEN { <<--we dont want to import fancy imports; copy is logically deeper in hierachy>> p: CDSequencer.CommandProc _ CDSequencer.FetchCommand[$UnqueuedCopyInterDesign].proc; IF p=NIL THEN TerminalIO.PutRope["failed, command issued in other design\n"] ELSE CDSequencer.ExecuteProc[p, comm.design, dontQueue, comm]; RETURN }; TerminalIO.PutRope["copy\n"]; CopySelected[comm.design, CD.Position[comm.pos.x-comm.sPos.x, comm.pos.y-comm.sPos.y]] } ELSE TerminalIO.PutRope["no copy in place\n"]; }; StepSize: PROC [comm: CDSequencer.Command] RETURNS [n: CD.Number] = { design: CD.Design _ comm.design; n _ CDValue.FetchInt[boundTo: design, key: $CDxStepValue, propagation: design]; IF n<=0 THEN { n _ CDOps.GetGrid[design, comm]; IF n<=0 THEN n _ design.technology.lambda } }; LambdaUpS: PROC [comm: CDSequencer.Command] = { <<--TerminalIO.PutRope["step move up\n"];>> MoveSelected[comm.design, [0, StepSize[comm]]] }; LambdaDownS: PROC [comm: CDSequencer.Command] = { <<--TerminalIO.PutRope["step move down\n"];>> MoveSelected[comm.design, [0, -StepSize[comm]]] }; LambdaLeftS: PROC [comm: CDSequencer.Command] = { <<--TerminalIO.PutRope["step move left\n"];>> MoveSelected[comm.design, [-StepSize[comm], 0]] }; LambdaRightS: PROC [comm: CDSequencer.Command] = { <<--TerminalIO.PutRope["step move right\n"];>> MoveSelected[comm.design, [StepSize[comm], 0]] }; RenameDesign: PROC [comm: CDSequencer.Command] = { name: Rope.ROPE; done: BOOL; TerminalIO.PutRopes["rename design ", comm.design.name, "\n"]; name _ TerminalIO.RequestRope["enter name: "]; done _ CDOps.RenameDesign[comm.design, name]; IF done THEN TerminalIO.PutRope["done\n"] ELSE TerminalIO.PutRope["not done\n"]; }; CDValue.StoreInt[boundTo: NIL, key: $CDxStepValue, value: 0]; CDSequencer.ImplementCommand[$DrawRect, AddRectComm]; CDSequencer.ImplementCommand[$DrawWire, AddWireComm]; CDSequencer.ImplementCommand[$ContinueWire, ContinueWireComm]; CDSequencer.ImplementCommand[$DeleteS, DeleteSelectedComm]; CDSequencer.ImplementCommand[$Undel, UndeleteComm]; CDSequencer.ImplementCommand[$AbortCommand, AbortComm,, dontQueue]; CDSequencer.ImplementCommand[$OnlySelectP, SelectExclusiveComm,, doQueue]; CDSequencer.ImplementCommand[$ReSelectOnlyP, ReSelectExclusiveComm,, doQueue]; CDSequencer.ImplementCommand[$ReSelectOnlyWithLayerP, ReSelectExclusiveWithLayerComm,, doQueue]; CDSequencer.ImplementCommand[$CloseReSelectOnlyP, CloseReSelectComm,, doQueue]; CDSequencer.ImplementCommand[$AddSelectP, AddSelectionComm,, doQueue]; CDSequencer.ImplementCommand[$DeSelectLP, DeselectLastSelectedComm,, doQueue]; CDSequencer.ImplementCommand[$DeSelectFP, DeselectPointedComm,, doQueue]; CDSequencer.ImplementCommand[$DeSelectS, DeselectAllComm,, doQueue]; CDSequencer.ImplementCommand[$SelectAll, SelectAllComm,, doQueue]; CDSequencer.ImplementCommand[$AreaOnlySelect, AreaOnlySelectComm,, doQueue]; CDSequencer.ImplementCommand[$MultiOnlySelect, MultiOnlySelectComm,, doQueue]; CDSequencer.ImplementCommand[$AreaAddSelect, AreaAddSelectComm,, doQueue]; CDSequencer.ImplementCommand[$AreaAddSelectTouching, AreaAddSelectTouchingComm,, doQueue]; CDSequencer.ImplementCommand[$MultiAddSelect, MultiAddSelectComm,, doQueue]; CDSequencer.ImplementCommand[$DoubleAddSelect, DoubleAddSelectComm,, doQueue]; CDSequencer.ImplementCommand[$AreaDeSelect, AreaDeSelectComm,, doQueue]; CDSequencer.ImplementCommand[$AreaDeSelectTouching, AreaDeSelectTouchingComm,, doQueue]; CDSequencer.ImplementCommand[$ADeSelect, ADeSelectComm,, doQueue]; CDSequencer.ImplementCommand[$MoveS, SimpleMoveSCommand]; CDSequencer.ImplementCommand[$CopyS, CopySCommand]; CDSequencer.ImplementCommand[$LambdaUpS, LambdaUpS]; CDSequencer.ImplementCommand[$LambdaDownS, LambdaDownS]; CDSequencer.ImplementCommand[$LambdaLeftS, LambdaLeftS]; CDSequencer.ImplementCommand[$LambdaRightS, LambdaRightS]; CDSequencer.ImplementCommand[$RotS, RotS]; CDSequencer.ImplementCommand[$MirrorYS, MirrorYS]; CDSequencer.ImplementCommand[$MirrorS, MirrorS]; CDSequencer.ImplementCommand[$TransformS, TransformS]; CDSequencer.ImplementCommand[$RenameDesign, RenameDesign]; END.