-- 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 " to Retry" ELSE " 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.