<> <> <> DIRECTORY CD, CDApplications, CDBasics, CDRects, CDSequencer, CDCallSpecific, CDOps, CDOrient, CDProperties, TerminalIO; CDSplitWireCommands: CEDAR PROGRAM IMPORTS CDApplications, CDBasics, CDOps, CDOrient, CDProperties, CDSequencer, TerminalIO, CDRects = BEGIN SplitApplication: PROC [design: CD.Design, aPtr: CD.ApplicationPtr, from, to: CD.DesignPosition] = BEGIN cutPos, oldRectPos, oldSize: CD.DesignPosition; oldRect: CD.DesignRect; -- the bounding box L1, L2, W1, W2: CD.DesignNumber; wireLeft, wireRight: CD.ObPtr; vertical, intersect: BOOL; NearlyRoundToLambda: PROC[x: CD.DesignNumber] RETURNS[r: CD.DesignNumber] = BEGIN r _ (x/CD.lambda)*CD.lambda; IF x=0 THEN r _ CD.lambda; END; FindCut: PROC[from, to: CD.DesignPosition, oldRect: CD.DesignRect, vertical: BOOL] RETURNS[cutPos: CD.DesignPosition, intersect: BOOL _ TRUE] = BEGIN <> inter, ctr: CD.DesignPosition; -- the intersection of the two lines, if any, and the center of the wire dx, dy: CD.DesignNumber; cursorBox: CD.DesignRect; cursorBox _ CDBasics.ToRect[from, to]; dx _ to.x-from.x; dy _ to.y-from.y; ctr _ CDBasics.Center[oldRect]; <<>> <> IF vertical AND (dx=0) OR (NOT vertical) AND (dy=0) THEN RETURN[[0,0], FALSE]; <> inter _ IF vertical THEN [ctr.x, from.y+(dy*(ctr.x-from.x)/dx)] ELSE [dx*(ctr.y-from.y)/dy+from.x, ctr.y]; <> IF NOT (CDBasics.InsidePos[inter, cursorBox] AND CDBasics.InsidePos[inter, oldRect]) THEN RETURN[[0,0], FALSE]; cutPos _ IF vertical THEN [oldRect.x1, NearlyRoundToLambda[inter.y]] ELSE [NearlyRoundToLambda[inter.x], oldRect.y1]; END; oldRect _ CDApplications.ARectI[aPtr]; oldRectPos _ CDBasics.BaseOfRect[oldRect]; oldSize _ CDBasics.SizeOfRect[oldRect]; vertical _ oldSize.y > oldSize.x; [cutPos, intersect] _ FindCut[from, to, oldRect, vertical]; IF NOT intersect THEN RETURN; IF vertical THEN { L1 _ cutPos.y - oldRect.y1; L2 _ oldSize.y - L1; W1 _ W2 _ oldSize.x; } ELSE { L1 _ L2 _ oldSize.y; W1 _ cutPos.x - oldRect.x1; W2 _ oldSize.x - W1; }; wireLeft _ CDRects.CreateRect[CDOrient.OrientedSize[[W1, L1], aPtr.orientation], aPtr.ob.level]; wireRight _ CDRects.CreateRect[CDOrient.OrientedSize[[W2, L2], aPtr.orientation], aPtr.ob.level]; CDOps.IncludeApplication[design, CDApplications.NewApplicationI[wireLeft, oldRectPos, aPtr.orientation, TRUE, CDProperties.CopyProps[aPtr.properties]], FALSE]; CDOps.IncludeApplication[design, CDApplications.NewApplicationI[wireRight, cutPos, aPtr.orientation, TRUE, CDProperties.CopyProps[aPtr.properties]], FALSE]; CDOps.RemoveApplication[design, aPtr]; END; DoAllSplits: PROC [design: CD.Design, from, to: CD.DesignPosition, pointed: BOOL_FALSE] = BEGIN <> <> FOR list: CD.ApplicationList _ CDOps.AppList[design], list.rest WHILE list#NIL DO IF list.first.selected AND list.first.ob.p.wireTyped THEN SplitApplication[design, list.first, from, to]; ENDLOOP; END; SplitWireCommandS: PROC [comm: CDSequencer.Command] = BEGIN TerminalIO.WriteRope["Split selected\n"]; DoAllSplits[design: comm.design, from: comm.sPos, to: comm.pos, pointed: FALSE] END; CDSequencer.ImplementCommand[$SplitWireS, SplitWireCommandS]; END.