-- Push/Pop procedure module of silicon (pretty picture) program
-- last modified by McCreight, March 23, 1983 12:03 PM
DIRECTORY
ChipOrient,
ChipUserInt,
InlineDefs,
ppCache,
ppdddefs,
ppddefs,
ppdefs,
StringDefs;
pppush: PROGRAM
IMPORTS ChipOrient, ChipUserInt, InlineDefs, ppCache,
ppdddefs, ppdefs, ppddefs, StringDefs
EXPORTS ppdddefs =
BEGIN
OPEN StringDefs, ppdefs, ppdddefs, ppddefs;
pushName: PUBLIC cmdProc =
BEGIN OPEN ChipUserInt;
s: STRING = RequestString["Type name of cell to push into"
! Punt => GOTO ForgetIt];
c: cListPtr = FindNamedCell[s];
IF c.ob # NIL THEN {pushCell[LOOPHOLE[c.ob], NIL]};
FreeString[s];
EXITS
ForgetIt => NULL;
END;
pushSel: PUBLIC cmdProc =
BEGIN
FOR lp: listPtr ← masterList, lp.nxt WHILE lp # NIL DO
IF lp.selected AND lp.ob.otyp = cell THEN
BEGIN
pushCell[LOOPHOLE[lp↑.ob], lp];
RETURN;
END;
ENDLOOP;
END;
pushPnt: PUBLIC cmdProc =
BEGIN
FOR lp: listPtr ← masterList, lp.nxt WHILE lp # NIL DO
IF lp.ob.otyp = cell AND lp.ob.p.inMe[lp.ob, xx - lp.lx, yy - lp.ly, lp.idx] THEN
BEGIN
lp.selected ← FALSE;
pushCell[LOOPHOLE[lp↑.ob], lp];
RETURN;
END;
ENDLOOP;
END;
doPop: PUBLIC cmdProc =
BEGIN OPEN ChipUserInt;
reply: STRING ← NIL;
IF cellStack = NIL THEN RETURN;
IF NOT anyChanges THEN GOTO FlushChanges;
reply ← RequestString[
s1: "F to flush the changes you just made",
s2: "R to replace old definition",
s3: "N to create new cell (F/R/N):",
breakChars: "FRN", appendBreakChar: TRUE
! Punt => CONTINUE];
WHILE reply#NIL DO
IF reply.length = 1 THEN
BEGIN
c: CHARACTER = reply[0];
FreeString[reply];
reply ← NIL;
SELECT c FROM
'F => GOTO FlushChanges;
'R =>
BEGIN
changee: cellPtr = cellStack.dest;
popCell[changee];
IF BBoxHasChanged[changee] THEN
AdjustCallersBBoxes[changee];
dChange ← TRUE;
RETURN;
END;
'N =>
BEGIN
cpp: cListPtr;
changee: cellPtr;
oldSize: Point;
newBox: Rect;
cellName: STRING ← RequestString[
s1: "Type Name of NEW Cell",
s2: (IF cellStack.instance = NIL THEN "<CR> to Retry"
ELSE "<CR> for No Name")
! Punt => GOTO RetryPop];
IF cellStack.instance = NIL AND cellName.length = 0 THEN
{FreeString[cellName]; GOTO RetryPop};
IF cellName.length>0 AND (cpp←FindNamedCell[cellName])#NIL THEN
BEGIN
FreeString[cellName];
cellName ← NIL;
IF NOT HeSaysYes["A cell already exists by that name.",
"Want to redefine it?" ! Punt => GOTO RetryPop] THEN GOTO RetryPop;
WITH dob: cpp.ob SELECT FROM
cell => changee ← @dob;
ENDCASE => ERROR;
END
ELSE
BEGIN -- brand new cell
changee ← makeCell[sx: cellStack.origSize.x, sy: cellStack.origSize.y,
cnt: 0, ptr: NIL];
IF cellName.length > 0 THEN
BEGIN
cp: cListPtr ← alocCList[];
cp.nxt ← cellList;
cp.ob ← changee.p.anotherme[changee];
cp.ob.returnable ← FALSE;
cp.name ← cellName;
cellList ← cp;
END
ELSE FreeString[cellName];
END;
popCell[changee];
oldSize ← [x: changee.size[0], y: changee.size[1]];
IF (newBox ← AdjustBBox[changee]) #
[x1: 0, y1: 0, x2: oldSize.x, y2: oldSize.y] THEN
RepositionCalls[ob: changee, oldSize: oldSize, newBox: newBox];
Explain["Now select items that should be replaced by",
"the edited cell"];
FOR lp: listPtr ← masterList, lp.nxt WHILE lp # NIL DO
IF lp.selected THEN
BEGIN
anyChanges ← TRUE;
oldSize ← [x: lp.ob.size[0], y: lp.ob.size[1]];
lp.ob.p.release[lp.ob];
lp.ob ← changee.p.anotherme[changee];
[[x: lp.lx, y: lp.ly]] ←
RepositionCall[[x: lp.lx, y: lp.ly], lp.idx, oldSize, newBox];
END;
ENDLOOP;
AdjustCallersBBoxes[changee];
dChange ← TRUE;
RETURN;
END;
ENDCASE => NULL;
EXITS
RetryPop => NULL;
END;
IF reply#NIL THEN {FreeString[reply]; reply ← NIL};
reply ← RequestString[
s1: "Try it again: F to flush the changes you just made",
s2: "R to replace old definition",
s3: "N to create new cell (F/R/N):",
breakChars: "FRN", appendBreakChar: TRUE
! Punt => CONTINUE];
ENDLOOP;
EXITS
FlushChanges =>
BEGIN
[] ← popCell[];
dChange ← TRUE;
END;
END;
FindNamedCell: PUBLIC PROC [s: STRING]
RETURNS [cp: cListPtr] =
BEGIN
cp ← NIL;
IF s#NIL AND s.length>0 THEN
FOR cp ← cellList, cp.nxt WHILE cp#NIL DO
IF EquivalentString[s,cp.name] THEN RETURN;
ENDLOOP;
END;
pushCell: PROC [cell: cellPtr, li: listPtr] =
BEGIN OPEN ChipOrient;
cellPos: Point = (IF li = NIL THEN [0, 0] ELSE [x: li.lx, y: li.ly]);
cellSize: Point = [x: cell.size[0], y: cell.size[1]];
cellOrient: orientationIndex = (IF li = NIL THEN 0 ELSE li.idx);
bbox: Rect = [x1: cellPos.x, y1: cellPos.y,
x2: cellPos.x+Size[cellSize, cellOrient].x, y2: cellPos.y+Size[cellSize, cellOrient].y];
x, y: INTEGER;
csp: cellSEPtr;
[, x, y] ← deScaledCursor[colWidth/2, colHeight/2];
csp ← GetSpace[SIZE[cellSE]];
csp↑ ← [lp: masterList, instance: li, dest: cell, origSize: cellSize, origBB: bbox,
changes: anyChanges, nxt: cellStack,
unDel: unDelPnt, udg: unDelGrpCnt, udi: unDelItemCnt
];
cellStack ← csp;
masterList ← NIL;
FOR lp: listPtr ← cell.ptr, lp.nxt WHILE lp # NIL DO
size: Point = Size[size: [x: lp.ob.size[0], y: lp.ob.size[1]], orient: lp.idx];
rect: Rect = MapRect[
itemInCell: [x1: lp.lx, y1: lp.ly, x2: lp.lx+size.x, y2: lp.ly+size.y],
cellSize: cellSize,
cellInstOrient: cellOrient,
cellInstPos: cellPos
];
np: listPtr = makeList[lp.ob.p.anotherme[lp.ob], rect.x1, rect.y1, 0, 0];
np.idx ← ComposeOrient[cellOrientInWorld: cellOrient, itemOrientInCell: lp.idx];
np.ridx ← InlineDefs.BITXOR[np.idx, 1];
np.selected ← FALSE;
copyProps[np, lp];
masterList ← insertList[masterList, np];
ENDLOOP;
pushLevel ← pushLevel + 1;
anyChanges ← FALSE;
unDelPnt ← NIL;
unDelGrpCnt ← unDelItemCnt ← 0;
reCount[];
setCellNameDisplay[];
dChange ← TRUE;
END;
popCell: PROC [cell: cellPtr ← NIL] =
BEGIN OPEN ChipOrient;
c: cellSEPtr ← cellStack;
IF cell # NIL THEN
BEGIN -- Produces an un-normalized cell with [x1, y1] # [0, 0] and
-- cell.size incorrect as well. This will be fixed up by our caller.
origPos: Point = (IF c.instance = NIL THEN [0, 0]
ELSE [x: c.instance.lx, y: c.instance.ly]);
cellOrient: orientationIndex = (IF c.instance = NIL THEN 0
ELSE c.instance.idx);
ppCache.FlushObjectCache[cell];
flushDel[cell.ptr];
cell.ptr ← NIL;
FOR lp: listPtr ← masterList, masterList WHILE lp # NIL DO
instSize: Point = Size[size: [x: lp.ob.size[0], y: lp.ob.size[1]], orient: lp.idx];
cellRect: Rect = DeMapRect[
itemInWorld: [x1: lp.lx, y1: lp.ly, x2: lp.lx+instSize.x, y2: lp.ly+instSize.y],
cellSize: c.origSize,
cellInstOrient: cellOrient,
cellInstPos: origPos
];
[x1: lp.lx, y1: lp.ly] ← cellRect;
lp.idx ← DecomposeOrient[cellOrientInWorld: cellOrient, itemOrientInWorld: lp.idx];
lp.ridx ← InlineDefs.BITXOR[lp.idx, 1];
masterList ← lp.nxt;
cell.ptr ← insertList[cell.ptr, lp];
ENDLOOP;
sinceIOchanges ← TRUE;
END; -- of non-NIL cell
cellStack ← cellStack.nxt;
anyChanges ← c.changes;
flushDel[unDelPnt];
unDelPnt ← c.unDel;
unDelGrpCnt ← c.udg;
unDelItemCnt ← c.udi;
flushDel[masterList];
masterList ← c.lp;
FreeSpace[c];
setCellNameDisplay[];
pushLevel ← IF cellStack = NIL THEN 0 ELSE pushLevel - 1;
reCount[];
END;
setCellNameDisplay: PROC =
BEGIN
IF cellStack = NIL THEN insideCell ← "-top level-"
ELSE
BEGIN
FOR cp: cListPtr ← cellList, cp.nxt WHILE cp # NIL DO
IF cp.ob = cellStack.dest THEN {insideCell ← cp.name; RETURN};
ENDLOOP;
insideCell ← "-no name-";
END;
END;
AdjustBBox: PROC [ob: obPtr] RETURNS [newBox: Rect] =
BEGIN
WITH cob: ob SELECT FROM
cell =>
BEGIN
[mix: newBox.x1, miy: newBox.y1, max: newBox.x2,may: newBox.y2] ←
minmax[cob.ptr];
IF Point[x: newBox.x1, y: newBox.y1] # [0,0] THEN
FOR lp: listPtr ← cob.ptr, lp.nxt WHILE lp # NIL DO
lp.lx ← lp.lx - newBox.x1;
lp.ly ← lp.ly - newBox.y1;
ENDLOOP;
cob.size[0] ← cob.size[2] ← newBox.x2-newBox.x1;
cob.size[1] ← newBox.y2-newBox.y1;
END;
ENDCASE => newBox ← [x1: 0, y1: 0, x2: ob.size[0], y2: ob.size[1]];
END;
RepositionCalls: PROC [ob: obPtr, oldSize: Point, newBox: Rect] =
BEGIN
FOR lp: listPtr ← GetSuperPointer[], lp.super WHILE lp # NIL DO
IF lp.ob = ob THEN
[[x: lp.lx, y: lp.ly]] ← RepositionCall[[x: lp.lx, y: lp.ly], lp.idx, oldSize, newBox];
ENDLOOP;
END;
BBoxHasChanged: PUBLIC PROC [ob: obPtr] RETURNS [BOOLEAN] =
BEGIN
oldSize: Point = [x: ob.size[0], y: ob.size[1]];
oldBox: Rect = [x1: 0, y1: 0, x2: oldSize.x, y2: oldSize.y];
newBox: Rect = AdjustBBox[ob];
IF newBox = oldBox THEN RETURN[FALSE];
RepositionCalls[ob, oldSize, newBox];
RETURN[TRUE];
END;
RepositionCall: PROC [oldP: Point, idx: orientationIndex, oldSize: Point, newBox: Rect]
RETURNS [newP: Point] =
BEGIN
w: Rect = ChipOrient.MapRect[itemInCell: newBox,
cellSize: oldSize,
cellInstOrient: idx,
cellInstPos: oldP];
newP ← [x: w.x1, y: w.y1];
IF newP#oldP THEN anyChanges ← TRUE;
END;
cellShift: PUBLIC PROC [lp: listPtr, ix, iy, ax, ay: locNum] =
BEGIN
SELECT InlineDefs.BITAND[13, lp.idx] FROM
4 => BEGIN iy ← ix; ix ← ay; END;
8 => BEGIN iy ← ay; ix ← ax; END;
12 => BEGIN ix ← iy; iy ← ax; END;
1 => BEGIN ix ← ax; END;
5 => BEGIN ay ← iy; iy ← ix; ix ← ay; END;
9 => BEGIN iy ← ay; END;
13 => BEGIN ix ← ay; iy ← ax; END;
ENDCASE;
lp.lx ← lp.lx + ix;
lp.ly ← lp.ly + iy;
END;
AdjustCallersBBoxes: PUBLIC PROC [ob: obPtr] =
BEGIN
FOR scob: cellPtr ← GetCellSuper[], scob.super WHILE scob#NIL DO
FOR lp: listPtr ← scob.ptr, lp.nxt WHILE lp#NIL DO
IF lp.ob=ob THEN
BEGIN
IF BBoxHasChanged[scob] THEN
BEGIN
ppCache.FlushObjectCache[scob];
AdjustCallersBBoxes[scob];
END;
EXIT;
END;
ENDLOOP;
ENDLOOP;
END;
END.