<> <> <> <> DIRECTORY BasicTime, CD, CDBasics, CDInstances, CDLayers, CDSimpleOps, CDOps, CDRects, CDSequencer, TerminalIO; CDBasicCommands: CEDAR PROGRAM IMPORTS BasicTime, CDInstances, CDLayers, CDSimpleOps, CDOps, CDSequencer, TerminalIO, CDRects, CDBasics = BEGIN AddARect: PROC [design: CD.Design, r: CD.Rect, l: CD.Layer] = { IF CDBasics.NonEmpty[r] THEN { ob: CD.Object; sz: CD.Position _ CDBasics.SizeOfRect[r]; orient: CD.Orientation _ original; IF sz.y> InternalAddWire[comm: comm, firstOnly: FALSE] }; ContinueWire: PROC [comm: CDSequencer.Command] = { InternalAddWire[comm: comm, firstOnly: TRUE] }; InternalAddWire: PROC [comm: CDSequencer.Command, firstOnly: BOOL_FALSE] = { <<--this procedure knows EXACTLY the algorithm used for showing>> <<--temporary wires in the cursor part>> start: CD.Position _ comm.sPos; stop: CD.Position _ comm.pos; wireWidth: CD.Number _ comm.n; IF wireWidth=0 THEN {AddRect[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]; } } }; DeleteSelected: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["delete selected "]; CDSimpleOps.DeleteSelected[comm.design]; TerminalIO.PutRope["\n"]; }; Undelete: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["un-delete\n"]; CDSimpleOps.Undelete[comm.design] }; AbortCommand: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["try to abort current command\n"]; CDSequencer.AbortDesignsCommand[comm.design] }; SelectExclusive: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["select pointed "]; CDSimpleOps.DeselectAll[comm.design]; CDSimpleOps.Select[comm.design, comm.pos]; TerminalIO.PutRope["\n"]; }; 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] }; 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[CDOps.InstRope[w.first]]; 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[CDOps.InstRope[inst]] } ELSE { done _ FALSE; IF verbose THEN TerminalIO.PutRope[" (no object)"]; } }; 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) ]] }; 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"]; }; <> lastPos: CD.Position; lastKey: REF _ NIL; lastTime: BasicTime.GMT _ BasicTime.earliestGMT; SameAsLast: 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; }; 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 SameAsLast[comm] THEN CDSimpleOps.DeselectAll[comm.design]; [] _ CloseReSelectExclusive[comm.design, comm.pos, TRUE, 50]; TerminalIO.PutRope["\n"]; }; MultiOnlySelectComm: PROC [comm: CDSequencer.Command] = { 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 CloseReSelectComm[comm] ELSE AreaOnlySelect[comm]; }; DoubleAddSelectComm: PROC [comm: CDSequencer.Command] = { IF SameAsLast[comm] THEN { TerminalIO.PutRope["change selection "]; [] _ DeSelectLast[comm.design, comm.pos, TRUE]; } ELSE TerminalIO.PutRope["add selection "]; CDSimpleOps.Select[comm.design, comm.pos]; TerminalIO.PutRope["\n"]; }; DeselectPointed: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["remove selection "]; CDSimpleOps.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] } }; DeselectLastSelected: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["remove selection "]; [] _ DeSelectLast[comm.design, comm.pos, TRUE]; TerminalIO.PutRope["\n"]; }; AddSelection: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["add selection "]; CDSimpleOps.Select[comm.design, comm.pos]; TerminalIO.PutRope["\n"]; }; DeselectAll: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["de-select all\n"]; CDSimpleOps.DeselectAll[comm.design] }; SelectAll: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["select all\n"]; CDSimpleOps.SelectAll[comm.design] }; AreaAddSelect: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["inclusive select area\n"]; CDSimpleOps.AreaSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]] }; MultiAddSelect: 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"]; CDSimpleOps.AreaSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]] } }; AreaAddSelectTouching: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["select inclusive touching\n"]; CDSimpleOps.AreaSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos], TRUE] }; AreaOnlySelect: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["select area\n"]; CDSimpleOps.DeselectAll[comm.design]; CDSimpleOps.AreaSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]] }; ADeSelect: PROC [comm: CDSequencer.Command] = { <<--Auto deselect area or pointed>> TerminalIO.PutRope["de-select "]; IF comm.pos=comm.sPos THEN CDSimpleOps.DeSelect[comm.design, comm.pos] ELSE CDSimpleOps.AreaDeSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]]; TerminalIO.PutRope["\n"]; }; AreaDeSelect: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["de-select area\n"]; CDSimpleOps.AreaDeSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos]] }; AreaDeSelectTouching: PROC [comm: CDSequencer.Command] = { TerminalIO.PutRope["de-select touching\n"]; CDSimpleOps.AreaDeSelect[comm.design, CDBasics.ToRect[comm.pos, comm.sPos], TRUE] }; CDSequencer.ImplementCommand[$AbortCommand, AbortCommand,, dontQueue]; CDSequencer.ImplementCommand[$DrawRect, AddRect]; CDSequencer.ImplementCommand[$DrawWire, AddWire]; CDSequencer.ImplementCommand[$ContinueWire, ContinueWire]; CDSequencer.ImplementCommand[$DeleteS, DeleteSelected]; CDSequencer.ImplementCommand[$Undel, Undelete]; CDSequencer.ImplementCommand[$OnlySelectP, SelectExclusive,, doQueue]; CDSequencer.ImplementCommand[$ReSelectOnlyP, ReSelectExclusiveComm,, doQueue]; CDSequencer.ImplementCommand[$ReSelectOnlyWithLayerP, ReSelectExclusiveWithLayerComm,, doQueue]; CDSequencer.ImplementCommand[$CloseReSelectOnlyP, CloseReSelectComm,, doQueue]; CDSequencer.ImplementCommand[$AddSelectP, AddSelection,, doQueue]; CDSequencer.ImplementCommand[$DeSelectLP, DeselectLastSelected,, doQueue]; CDSequencer.ImplementCommand[$DeSelectFP, DeselectPointed,, doQueue]; CDSequencer.ImplementCommand[$DeSelectS, DeselectAll,, doQueue]; CDSequencer.ImplementCommand[$SelectAll, SelectAll,, doQueue]; CDSequencer.ImplementCommand[$AreaOnlySelect, AreaOnlySelect,, doQueue]; CDSequencer.ImplementCommand[$MultiOnlySelect, MultiOnlySelectComm,, doQueue]; CDSequencer.ImplementCommand[$AreaAddSelect, AreaAddSelect,, doQueue]; CDSequencer.ImplementCommand[$AreaAddSelectTouching, AreaAddSelectTouching,, doQueue]; CDSequencer.ImplementCommand[$MultiAddSelect, MultiAddSelect,, doQueue]; CDSequencer.ImplementCommand[$DoubleAddSelect, DoubleAddSelectComm,, doQueue]; CDSequencer.ImplementCommand[$AreaDeSelect, AreaDeSelect,, doQueue]; CDSequencer.ImplementCommand[$AreaDeSelectTouching, AreaDeSelectTouching,, doQueue]; CDSequencer.ImplementCommand[$ADeSelect, ADeSelect,, doQueue]; END.