-- Push/Pop procedure module of silicon (pretty picture) program -- last modified by McCreight, December 20, 1982 3:19 PM DIRECTORY ChipOrient, ChipUserInt, InlineDefs, StringDefs, ppdddefs, ppddefs, ppdefs; pppush: PROGRAM IMPORTS ChipOrient, ChipUserInt, InlineDefs, 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; IF li # NIL THEN BEGIN IF li.ob # cell THEN ERROR; li.ob ← NIL; -- detach to avoid display during edit END; [, x, y] ← deScaledCursor[colWidth/2, colHeight/2]; csp ← GetSpace[SIZE[cellSE]]; csp↑ ← [lp: masterList, instance: li, dest: cell, origSize: cellSize, origBB: bbox, cCenter: [x, y], cScale: cScale, 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; np.gotText ← lp.gotText; 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 c.instance # NIL THEN c.instance.ob ← c.dest; -- hook it back up 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); 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; FOR cs: cellSEPtr ← cellStack.nxt, cs.nxt WHILE cs#NIL DO IF NOT cs.changes THEN FOR lp: listPtr ← cs.lp, lp.nxt WHILE lp#NIL DO IF cell = lp.ob THEN {cs.changes ← TRUE; EXIT}; ENDLOOP; ENDLOOP; 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]; RETURN[[x: w.x1, y: w.y1]]; 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 AdjustCallersBBoxes[scob]; EXIT; END; ENDLOOP; ENDLOOP; END; END.