PWPinsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reversed.
Created by Bertrand Serlet, June 4, 1985 11:27:01 am PDT
Last Edited by: Serlet, July 6, 1985 12:32:54 pm PDT
Last Edited by: Monier, June 6, 1985 0:05:34 am PDT
DIRECTORY
CD, CDBasics, CDCells, CDDirectory, CDImports, CDOrient, CDPinObjects, CDProperties,
Convert, PWPins, Rope;
PWPinsImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCells, CDDirectory, CDImports, CDOrient, CDPinObjects, CDProperties, Convert, Rope
EXPORTS PWPins =
BEGIN
OPEN PWPins;
GetSide: PUBLIC PROC [ob: CD.ObPtr, pin: CD.ApplicationPtr] RETURNS [isOnBorder: BOOL, side: Side] = {
LargerSide: PROC [hSide, vSide: Side] RETURNS [side: Side] = {
side ← IF pinRect.x2-pinRect.x1>pinRect.y2-pinRect.y1 THEN hSide ELSE vSide;
};
rect: CD.Rect ← CD.InterestRect[ob]; -- the border
pinRect: CD.Rect ← CDOrient.RectAt[pin.location, pin.ob.size, pin.orientation]; -- bbox of the pin
isOnBorder ← TRUE;
SELECT TRUE FROM
rect.y2 = pinRect.y2 AND rect.x1 = pinRect.x1 => side ← LargerSide[top, left];
rect.y2 = pinRect.y2 AND rect.x2 = pinRect.x2 => side ← LargerSide[top, right];
rect.y1 = pinRect.y1 AND rect.x1 = pinRect.x1 => side ← LargerSide[bottom, left];
rect.y1 = pinRect.y1 AND rect.x2 = pinRect.x2 => side ← LargerSide[bottom, right];
rect.y2 = pinRect.y2 => side ← top;
rect.y1 = pinRect.y1 => side ← bottom;
rect.x1 = pinRect.x1 => side ← left;
rect.x2 = pinRect.x2 => side ← right;
ENDCASE    => isOnBorder ← FALSE;
};
FilterProc: TYPE = PROC [subRect: CD.Rect] RETURNS [isSubInteresting: BOOLTRUE];
DefaultFilter: FilterProc = {};
Because we must finally get applications, this one has in its parameters all necessary information for reconstructing the application.
EnumerateDeepPinsInContext: PRIVATE PROC [ob: CD.ObPtr, location: CD.Position ← [0, 0], orientation: CD.Orientation ← 0, properties: CD.Properties ← NIL, eachPin: AppEnumerator, stopEnumerateDeepPins: BOOL, filter: FilterProc] RETURNS [quit: BOOLFALSE] = {
IF ~filter[CDOrient.MapRect[
itemInCell: CD.InterestRect[ob],
cellSize: ob.size,
cellInstOrient: orientation,
cellInstPos: location]] THEN RETURN;
SELECT TRUE FROM
CDPinObjects.IsPinOb[ob] => {
quit ← eachPin[NEW[CD.Application ← [ob: ob, location: location, orientation: orientation, properties: CDProperties.CopyProps[properties]]]];
};
CDCells.IsCell[ob]   => {
cellPtr: CD.CellPtr ← NARROW[ob.specificRef];
FOR list: CD.ApplicationList ← cellPtr.contents, list.rest WHILE (list#NIL AND ~quit) DO
IF ~stopEnumerateDeepPins OR CDProperties.GetPropFromApplication[list.first, $StopEnumerateDeepPins]=NIL THEN
quit ← EnumerateDeepPinsInContext[
list.first.ob,
CDBasics.BaseOfRect[
CDOrient.MapRect[
itemInCell:
CDOrient.RectAt[list.first.location, list.first.ob.size, list.first.orientation],
cellSize: ob.size,
cellInstOrient: orientation,
cellInstPos: location]],
CDOrient.ComposeOrient[list.first.orientation, orientation],
list.first.properties,
eachPin, stopEnumerateDeepPins, filter];
IF quit THEN EXIT;
ENDLOOP;
};
CDImports.IsImport[ob]  => {
HACKK until imports handle pins reasonably
ip: CDImports.ReferencePtr ← NARROW[ob.specificRef];
IF ip.boundApp=NIL THEN RETURN;
quit ← EnumerateDeepPinsInContext[ip.boundApp.ob, location, orientation, NIL, eachPin, stopEnumerateDeepPins, filter];
};
ENDCASE      => {
newOb: CD.ObPtr ← CDDirectory.Expand[ob, NIL, NIL];
quit ← newOb#NIL AND EnumerateDeepPinsInContext[newOb, location, orientation, NIL, eachPin, stopEnumerateDeepPins, filter];
};
};
EnumerateDeepPins: PUBLIC PROC [ob: CD.ObPtr, eachPin: AppEnumerator, stopEnumerateDeepPins: BOOLTRUE] RETURNS [quit: BOOL] = {
quit ← EnumerateDeepPinsInContext[ob: ob, eachPin: eachPin, stopEnumerateDeepPins: stopEnumerateDeepPins, filter: DefaultFilter];
};
EnumerateEdgePins: PUBLIC PROC [ob: CD.ObPtr, eachPin: AppEnumerator, stopEnumerateDeepPins: BOOLTRUE] RETURNS [quit: BOOL] = {
iRectShrank: CD.Rect ← CDBasics.Extend[CD.InterestRect[ob], -1];
EdgeFilter: FilterProc = {isSubInteresting ← ~CDBasics.Inside[subRect, iRectShrank]};
EachPinFilter: AppEnumerator -- [app: CD.ApplicationPtr] RETURNS [quit: BOOL ← FALSE] -- = {
IF GetSide[ob, app].isOnBorder THEN quit ← eachPin[app];
};
quit ← EnumerateDeepPinsInContext[ob: ob, eachPin: EachPinFilter, stopEnumerateDeepPins: stopEnumerateDeepPins, filter: EdgeFilter];
};
RenamePins: PUBLIC PROC [design: CD.Design, ob: CD.ObPtr, renameProc: RenameProc ← DefaultRenameProc, stopEnumerateDeepPins: BOOLTRUE] RETURNS [cell: CD.ObPtr] =
BEGIN
cellPtr: CD.CellPtr;
KeepPinOnEdge: AppEnumerator -- [app: CD.ApplicationPtr] RETURNS [quit: BOOL ← FALSE] -- = {
newApp: CD.ApplicationPtr;
newRope: ROPE ← renameProc[CDPinObjects.GetName[app]];
IF Rope.IsEmpty[newRope] THEN RETURN;
newApp ← NEW[CD.Application ← [
ob: CDPinObjects.CreatePinOb[app.ob.size],
location: app.location, orientation: app.orientation,
properties: CDProperties.CopyProps[app.properties]]];
CDPinObjects.SetName[newApp, newRope];
cellPtr.contents ← CONS[newApp, cellPtr.contents];
};
app: CD.ApplicationPtr ← NEW[CD.Application ← [ob: ob]];
IF stopEnumerateDeepPins THEN CDProperties.PutPropOnApplication[app, $StopEnumerateDeepPins, $StopEnumerateDeepPins];
cell ← CDCells.CreateEmptyCell[]; cellPtr ← NARROW[cell.specificRef];
[] ← EnumerateEdgePins[ob, KeepPinOnEdge];
cellPtr.contents ← CONS[app, cellPtr.contents];
CDCells.SetInterestRect[cell, CD.InterestRect[ob]];
[] ← CDCells.RepositionCell[cell, NIL];
[] ← CDDirectory.Include[design, cell, "RenamedPins"];
END;
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], "]"];
};
[] ← CDProperties.RegisterProperty[$StopEnumerateDeepPins, $CDPinExtras];
CDProperties.FetchProcs[$StopEnumerateDeepPins].makeCopy ← CDProperties.CopyVal;
END.