PWPinsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reversed.
Created by Bertrand Serlet, June, 1985 10:07:28 am PDT
Bertrand Serlet, December 18, 1986 5:38:14 pm PST
Curry, January 28, 1986 1:42:02 pm PST
DIRECTORY
CD, CDBasics, CDCells, CDDirectory, CDInstances, CDProperties, CDSymbolicObjects,
Convert, PWPins, Rope;
PWPinsImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCells, CDDirectory, CDInstances, CDProperties, CDSymbolicObjects, Convert, Rope
EXPORTS PWPins
SHARES CDCells, CDSymbolicObjects =
BEGIN
OPEN PWPins;
EnumerationProc: TYPE = PROC [ob: CD.Object, transf: CD.Transformation, properties: CD.PropList ← NIL, eachPin: InstanceEnumerator, stopEnumerateDeepPins: BOOL, filter: FilterProc] RETURNS [quit: BOOLFALSE];
FilterProc: TYPE = PROC [subRect: CD.Rect] RETURNS [isSubInteresting: BOOLTRUE];
GetSide: PUBLIC PROC [ob: CD.Object, pin: CD.Instance] RETURNS [side: Side] = {
LargerSide: PROC [hSide, vSide: Side] RETURNS [side: Side] = {
delta: INT ← pinRect.x2-pinRect.x1- (pinRect.y2-pinRect.y1);
side ← IF delta=0 THEN ERROR ELSE IF delta>0 THEN hSide ELSE vSide;
};
rect: CD.Rect ← CD.InterestRect[ob]; -- the border
pinRect: CD.Rect ← CDSymbolicObjects.Denotes[pin]; -- bbox of the pin (CDInstances.InstRectO)
side ← SELECT TRUE FROM
pinRect.x1 = pinRect.x2 AND pinRect.y1 = pinRect.y2 => none,
pinRect.x1 = pinRect.x2 AND pinRect.y1 = pinRect.y2 => SELECT pinRect.x1 FROM
rect.x1 => left,
rect.y1 => bottom,
rect.x2 => right,
rect.y2 => top,
ENDCASE => none,
pinRect.x1 = pinRect.x2 => SELECT pinRect.x1 FROM
rect.x1 => left,
rect.x2 => right,
ENDCASE => none,
pinRect.y1 = pinRect.y2 => SELECT pinRect.y1 FROM
rect.y1 => bottom,
rect.y2 => top,
ENDCASE => none,
rect.y1 = pinRect.y1 AND rect.y2 = pinRect.y2 => ERROR, -- pin on 2 opposite sides
rect.x1 = pinRect.x1 AND rect.x2 = pinRect.x2 => ERROR, -- pin on 2 opposite sides
rect.y2 = pinRect.y2 AND rect.x1 = pinRect.x1 => LargerSide[top, left],
rect.y2 = pinRect.y2 AND rect.x2 = pinRect.x2 => LargerSide[top, right],
rect.y1 = pinRect.y1 AND rect.x1 = pinRect.x1 => LargerSide[bottom, left],
rect.y1 = pinRect.y1 AND rect.x2 = pinRect.x2 => LargerSide[bottom, right],
rect.y2 = pinRect.y2 => top,
rect.y1 = pinRect.y1 => bottom,
rect.x1 = pinRect.x1 => left,
rect.x2 = pinRect.x2 => right,
ENDCASE    => none;
};
Because we must finally get instances, this one has in its parameters all necessary information for reconstructing the application.
EnumerateDeepPinsInContext: PUBLIC EnumerationProc = {
value: REF;
IF ~filter[CDBasics.MapRect[itemInCell: CD.InterestRect[ob], cellInWorld: transf]]
THEN RETURN;
value ← CDProperties.GetObjectProp[ob, enumerationProcProp];
IF value#NIL THEN RETURN [NARROW [value, REF EnumerationProc]^[ob, transf, properties, eachPin, stopEnumerateDeepPins, filter]];
value ← CDProperties.GetProp[ob.class, enumerationProcProp];
IF value#NIL THEN RETURN [NARROW [value, REF EnumerationProc]^[ob, transf, properties, eachPin, stopEnumerateDeepPins, filter]];
ob ← CDDirectory.Expand[ob, NIL, NIL].new;
quit ← ob#NIL AND EnumerateDeepPinsInContext[ob, transf, NIL, eachPin, stopEnumerateDeepPins, filter];
};
PinEnumerateDeepPinsInContext: EnumerationProc = {
quit ← eachPin[NEW [CD.InstanceRep ← [ob: ob, trans: transf, properties: CDProperties.DCopyProps[properties]]]];
};
CellEnumerateDeepPinsInContext: EnumerationProc = {
cellPtr: CD.CellSpecific ← NARROW [ob.specific];
InstEnumerate: CDCells.InstEnumerator = {
IF ~stopEnumerateDeepPins OR CDProperties.GetInstanceProp[inst, $StopEnumerateDeepPins]=NIL THEN
quit ← EnumerateDeepPinsInContext[
inst.ob,
CDBasics.ComposeTransform[inst.trans, transf],
inst.properties,
eachPin, stopEnumerateDeepPins, filter];
};
quit ← CDCells.EnumerateInstances[ob, InstEnumerate];
};
EnumerateDeepPins: PUBLIC PROC [ob: CD.Object, eachPin: InstanceEnumerator, stopEnumerateDeepPins: BOOLTRUE] RETURNS [quit: BOOL] = {
DefaultFilter: FilterProc = {};
quit ← EnumerateDeepPinsInContext[ob: ob, transf: [], eachPin: eachPin, stopEnumerateDeepPins: stopEnumerateDeepPins, filter: DefaultFilter];
};
EnumerateEdgePins: PUBLIC PROC [ob: CD.Object, eachPin: InstanceEnumerator, stopEnumerateDeepPins: BOOLTRUE] RETURNS [quit: BOOL] = {
iRectShrank: CD.Rect ← CDBasics.Extend[CD.InterestRect[ob], -1];
EdgeFilter: FilterProc = {isSubInteresting ← ~CDBasics.Inside[subRect, iRectShrank]};
EachPinFilter: InstanceEnumerator -- [inst: CD.Instance] RETURNS [quit: BOOL ← FALSE] -- = {
IF GetSide[ob, inst]#none THEN quit ← eachPin[inst];
};
quit ← EnumerateDeepPinsInContext[ob: ob, transf: [], eachPin: EachPinFilter, stopEnumerateDeepPins: stopEnumerateDeepPins, filter: EdgeFilter];
};
ChangePins: PUBLIC PROC [ob: CD.Object, changePinProc: ChangePinProc ← DefaultChangePinProc, stopEnumerateDeepPins: BOOLTRUE] RETURNS [cell: CD.Object] =
BEGIN
cellPtr: CD.CellSpecific;
KeepPinOnEdge: InstanceEnumerator -- [inst: CD.Instance] RETURNS [quit: BOOL ← FALSE] -- = {
newInst: CD.Instance ← changePinProc[inst];
IF newInst#NIL THEN cellPtr.contents ← CONS [newInst, cellPtr.contents];
};
inst: CD.Instance ← NEW [CD.InstanceRep ← [ob: ob]];
IF stopEnumerateDeepPins THEN CDProperties.PutInstanceProp[inst, $StopEnumerateDeepPins, $StopEnumerateDeepPins];
cell ← CDCells.CreateEmptyCell[]; cellPtr ← NARROW [cell.specific];
[] ← EnumerateEdgePins[ob, KeepPinOnEdge];
cellPtr.contents ← CONS[inst, cellPtr.contents];
CDCells.SetInterestRect[NIL, cell, CD.InterestRect[ob], dontNotify];
END;
DefaultChangePinProc: PUBLIC ChangePinProc = {newPin ← oldPin};
RenamePins: PUBLIC PROC [ob: CD.Object, renameProc: RenameProc ← DefaultRenameProc, stopEnumerateDeepPins: BOOLTRUE] RETURNS [cell: CD.Object] = {
ChangePin: ChangePinProc = {
newRope: ROPE ← renameProc[CDSymbolicObjects.GetName[oldPin]];
IF Rope.IsEmpty[newRope] THEN RETURN;
newPin ← CDInstances.Copy[oldPin];
CDSymbolicObjects.SetName[newPin, newRope];
};
cell ← ChangePins[ob, ChangePin, stopEnumerateDeepPins];
};
DefaultRenameProc: PUBLIC RenameProc = {newRope ← oldRope};
Useful in many RenameProcs for indexing names. e.g. Index["foo", 4]="foo[4]"
Index: PUBLIC PROC [rope: ROPE, index: INT] RETURNS [indexedRope: ROPE] = {
indexedRope ← Rope.Cat[rope, "[", Convert.RopeFromInt[index], "]"];
};
KeepAll: PUBLIC SelectNamesProc = {keepIt ← TRUE};
Position: PROC [inst: CD.Instance, newObj, template: CD.Object, side: Side, orientation: CD.Orientation] RETURNS [position: CD.Position] = {
position ← CDBasics.SubPoints[
CDBasics.BaseOfRect[
CDBasics.MapRect[CD.InterestRect[inst.ob], inst.trans]],
CDBasics.BaseOfRect[CD.InterestRect[template]]];
SELECT side FROM
top, bottom => position.y ← 0;
left, right => position.x ← 0;
ENDCASE => ERROR;
position ← CDBasics.SubPoints[position, CDBasics.BaseOfRect[CDBasics.MapRect[CD.InterestRect[newObj], [[0, 0], orientation]]]];
};
TransferCell: PUBLIC PROC [template: CD.Object, objSide: Side, width: INT, objProc: ForEachPinProc, selectNameProc: SelectNamesProc ← KeepAll] RETURNS [cell: CD.Object] = {
instances: CD.InstanceList ← NIL;
KeepPinOnEdge: PWPins.InstanceEnumerator = {
newObj: CD.Object;
side: Side ← GetSide[template, inst].side;
IF side=objSide AND selectNameProc[CDSymbolicObjects.GetName[inst]] THEN {
orient: CD.Orientation ← SELECT objSide FROM
bottom => rotate270, right => original, top => rotate90, left => rotate180,
ENDCASE => ERROR;
newObj ← objProc[inst]; IF newObj=NIL THEN RETURN;
instances ← CONS [CDInstances.NewInst[ob: newObj, trans: [Position[inst, newObj, template, objSide, orient], orient]], instances];
};
};
iRect: CD.Rect = CD.InterestRect[template];
-- Start with an empty cell of appropriate interestRect (origin in 0,0)
IF objSide=none THEN ERROR;
[] ← EnumerateEdgePins[template, KeepPinOnEdge];
cell ← CDCells.CreateCell[il: instances, ir: SELECT objSide FROM
top, bottom => [0, 0, iRect.x2-iRect.x1, width],
left, right => [0, 0, width, iRect.y2-iRect.y1],
ENDCASE => ERROR];
};
enumerationProcProp: PUBLIC ATOM ← $EnumerationProcPWPins;
[] ← CDProperties.RegisterProperty[enumerationProcProp, $PWPins];
CDProperties.InstallProcs[enumerationProcProp, [makeCopy: CDProperties.CopyVal]];
[] ← CDProperties.RegisterProperty[$StopEnumerateDeepPins, $PWPins];
CDProperties.InstallProcs[$StopEnumerateDeepPins, [makeCopy: CDProperties.CopyVal]];
CDProperties.PutProp[CDSymbolicObjects.pinClass, enumerationProcProp, NEW [EnumerationProc ← PinEnumerateDeepPinsInContext]];
CDProperties.PutProp[CDSymbolicObjects.segmentClass, enumerationProcProp, NEW [EnumerationProc ← PinEnumerateDeepPinsInContext]];
CDProperties.PutProp[CDSymbolicObjects.markClass, enumerationProcProp, NEW [EnumerationProc ← PinEnumerateDeepPinsInContext]];
CDProperties.PutProp[CDCells.pCellClass, enumerationProcProp, NEW [EnumerationProc ← CellEnumerateDeepPinsInContext]];
END.