DIRECTORY CD, CDInstances, CDCells, CDCellsBackdoor, CDDirectory, CDBasics, CDBasicsInline, CDIO, CDLayers, CDOps, CDProperties, CDRects, Process USING [Yield, Detach], Properties, Real, RefTab, Rope, TerminalIO, TokenIO; CDCellsImpl: CEDAR MONITOR IMPORTS CD, CDCells, CDInstances, CDIO, CDDirectory, CDBasics, CDBasicsInline, CDLayers, CDOps, CDProperties, CDRects, Process, Properties, Real, RefTab, TerminalIO, TokenIO EXPORTS CDCells, CDCellsBackdoor SHARES CD, CDRects, CDDirectory = BEGIN cellClass: PUBLIC CD.ObjectClass = CD.RegisterObjectClass[$Cell, [ drawMe: DrawMeForCells, quickDrawMe: QuickDrawMeForCells, showMeSelected: DrawCellSelection, internalRead: ReadCell, internalWrite: WriteCell, interestRect: InterestRectCells, showsErrors: TRUE, description: "cell" ]]; pCellClass: PUBLIC CD.ObjectClass = cellClass; Init: PROC [] = { dp: REF CDDirectory.DirectoryProcs = CDDirectory.InstallDirectoryProcs[cellClass, [ enumerateChildObjects: EnumerateChildObjects, another: Another, replaceDirectChilds: ReplaceDirectChildForCell ]]; [] _ CDProperties.RegisterProperty[$InsideRect]; CDProperties.InstallProcs[prop: $InsideRect, procs: CDProperties.PropertyProcsRec[ makeCopy: CDProperties.DontCopy, internalWrite: NIL, internalRead: InternalReadProperty, exclusive: TRUE ] ]; }; IsDummyCell: PUBLIC PROC [cell: CD.Object] RETURNS [BOOL_FALSE] = { WITH cell.specific SELECT FROM cp: CD.CellSpecific => RETURN [cp.dummyCell]; ENDCASE => NULL; }; InternalReadProperty: PROC [h: TokenIO.Handle, prop: ATOM] RETURNS [val: REF] = { val _ NEW[CD.Rect _ CDIO.ReadRect[h]] }; InterestRectCells: PROC [ob: CD.Object] RETURNS [CD.Rect] = { RETURN [NARROW[ob.specific, CD.CellSpecific].ir] }; EnumerateChildObjects: PROC [me: CD.Object, proc: CDDirectory.EachObjectProc, data: REF] RETURNS [quit: BOOL_FALSE] = { cp: CD.CellSpecific _ NARROW[me.specific]; FOR list: CD.InstanceList _ cp.contents, list.rest WHILE list#NIL AND ~quit DO IF proc[list.first.ob, data] THEN RETURN [quit_TRUE] ENDLOOP; IF cp.sequence#NIL THEN FOR n: NAT IN [0..cp.sequence.length) DO IF proc[cp.sequence[n].ob, data] THEN RETURN [quit_TRUE] ENDLOOP; }; Another: PROC [me: CD.Object, fromOrNil: CD.Design_NIL, into: CD.Design_NIL, friendly: BOOL_FALSE] RETURNS [new: CD.Object_CreateEmptyCell[], childAccessible: BOOL_FALSE] = { oldCp: CD.CellSpecific _ NARROW[me.specific]; newCp: CD.CellSpecific _ NARROW[new.specific]; new.bbox _ me.bbox; newCp^ _ oldCp^; newCp.dummyCell _ FALSE; [newCp.contents, newCp.sequence] _ CopyInsts[oldCp.contents, oldCp.sequence]; CDProperties.AppendProps[winner: new.properties, looser: me.properties, putOnto: new]; IF into#NIL THEN { CDDirectory.SetOwner[into, new]; IF fromOrNil=into THEN childAccessible _ TRUE; }; }; CopyInsts: PUBLIC PROC [list: CD.InstanceList, seq: CD.InstanceSequence, inPlace: BOOL_FALSE] RETURNS [lCopy: CD.InstanceList_NIL, sCopy: CD.InstanceSequence] = { maxSSize: NAT = 10000; i: CD.Instance; from, to: INT _ 0; oldSLeng: INT _ IF seq=NIL THEN 0 ELSE MIN[seq.length, seq.size]; newSLeng: INT _ MIN[maxSSize, CDInstances.Length[list]+oldSLeng]; sCopy _ NEW[CD.InstanceSequenceRep[newSLeng]]; DO IF from DrawMeForCells[pr, ob1, trans, NIL]; ENDCASE => NULL; }; DrawMeForCells: CD.DrawProc = { cp: CD.CellSpecific _ NARROW[ob.specific, CD.CellSpecific]; mapClip: CD.Rect _ CDBasics.DeMapRect[pr.interestClip, trans].itemInCell; --clipping boundary in cell coordinates IF pr.borders AND cp.drawBorder THEN pr.drawOutLine[pr, CDBasicsInline.MapRect[CD.InterestRect[ob], trans], CD.outlineLayer]; FOR w: CD.InstanceList _ cp.contents, w.rest WHILE w#NIL DO IF CDBasicsInline.IntersectRI[mapClip, w.first] THEN { IF pr.stopFlag^ THEN RETURN; pr.drawChild[pr, w.first.ob, CDBasics.ComposeTransform[w.first.trans, trans], w.first.properties]; } ENDLOOP; IF cp.sequence#NIL THEN FOR n: NAT IN [0..cp.sequence.length) DO IF CDBasicsInline.IntersectRI[mapClip, cp.sequence[n]] THEN { IF pr.stopFlag^ THEN RETURN; pr.drawChild[pr, cp.sequence[n].ob, CDBasicsInline.ComposeTransform[cp.sequence[n].trans, trans], cp.sequence[n].properties]; } ENDLOOP; IF pr.showErrors AND ob.showErrors THEN ShowErrors[pr, ob, trans]; Yield[]; }; n: INTEGER _ 8; Yield: PROC [] = INLINE { IF (n_n-1)<0 THEN {n_5; Process.Yield[]} }; QuickDrawMeForCells: CD.DrawProc = { cp: CD.CellSpecific = NARROW[ob.specific]; IF pr.scaleHint0 THEN { pr.drawOutLine[pr, CDBasics.MapRect[cp.ir, trans], CD.outlineLayer]; IF pr.scaleHint*(ob.bbox.y2-ob.bbox.y1)>9 THEN { name: Rope.ROPE ~ CDDirectory.Name[ob, pr.design]; IF name#NIL THEN pr.drawComment[pr, CDBasics.MapRect[cp.ir, trans], name]; } } ELSE { mapClip: CD.Rect _ CDBasicsInline.DeMapRect[pr.interestClip, trans]; --clipping boundary in cell coordinates IF pr.borders AND cp.drawBorder THEN pr.drawOutLine[pr, CDBasicsInline.MapRect[cp.ir, trans], CD.outlineLayer]; FOR w: CD.InstanceList _ cp.contents, w.rest WHILE w#NIL DO IF CDBasicsInline.IntersectRI[mapClip, w.first] THEN { IF pr.stopFlag^ THEN RETURN; w.first.ob.class.quickDrawMe[pr, w.first.ob, CDBasics.ComposeTransform[w.first.trans, trans], w.first.properties]; } ENDLOOP; IF cp.sequence#NIL THEN FOR n: NAT IN [0..cp.sequence.length) DO IF CDBasicsInline.IntersectRI[mapClip, cp.sequence[n]] THEN { IF pr.stopFlag^ THEN RETURN; IF cp.sequence[n].ob.class=CDRects.bareRectClass THEN pr.drawRect[pr: pr, r: CDBasicsInline.MapRect[cp.sequence[n].ob.bbox, CDBasicsInline.ComposeTransform[cp.sequence[n].trans, trans]], l: cp.sequence[n].ob.layer] ELSE cp.sequence[n].ob.class.quickDrawMe[pr, cp.sequence[n].ob, CDBasicsInline.ComposeTransform[cp.sequence[n].trans, trans], cp.sequence[n].properties]; } ENDLOOP; Yield[]; IF pr.showErrors AND ob.showErrors THEN ShowErrors[pr, ob, trans]; IF pr.checkPriority THEN pr.priorityChecker[pr]; } }; DrawCellSelection: CD.DrawProc = { cp: CD.CellSpecific ~ NARROW[ob.specific]; IF pr.scaleHint0 THEN pr.drawRect[pr, CDBasicsInline.MapRect[cp.ir, trans], CD.shadeLayer] ELSE pr.drawOutLine[pr, CDBasicsInline.MapRect[cp.ir, trans], CD.selectionLayer] }; CreateEmptyCell: PUBLIC PROC [] RETURNS [ob: CD.Object] = { ob _ NEW[CD.ObjectRep_[ class: cellClass, bbox: [0, 0, 1, 1], specific: NEW[CD.CellRep_[simplifyOn: -1]] ]]; }; CreateCell: PUBLIC PROC [il: CD.InstanceList_NIL, sq: CD.InstanceSequence_NIL, ir: CD.Rect_[0,0,-1,-1]] RETURNS [CD.Object] = { ob: CD.Object = CreateEmptyCell[]; cp: CD.CellSpecific = NARROW[ob.specific]; cp.contents _ il; cp.sequence _ sq; SetInterestRect[NIL, ob, ir, dontResize]; [] _ ResizeCell[NIL, ob]; SetSimplificationTreshhold[ob, -1]; RETURN [ob] }; CreateCellXTransformed: PUBLIC PROC [il: CD.InstanceList_NIL, sq: CD.InstanceSequence_NIL, ir: CD.Rect_[0,0,-1,-1], cTrans: CD.Transformation_[]] RETURNS [ob: CD.Object] = { [il, sq] _ CopyInsts[il, sq, FALSE]; FOR l: CD.InstanceList _ il, l.rest WHILE l#NIL DO l.first.trans _ CDBasics.DecomposeTransform[l.first.trans, cTrans]; ENDLOOP; IF sq#NIL THEN FOR n: NAT IN [0..sq.length) DO sq[n].trans _ CDBasics.DecomposeTransform[sq[n].trans, cTrans]; ENDLOOP; RETURN [ CreateCell[il, sq, CDBasics.DeMapRect[ir, cTrans]]]; }; ReadCell: CD.InternalReadProc = { i: INT; ob: CD.Object = CreateEmptyCell[]; specific: CD.CellSpecific = NARROW[ob.specific]; IF h.oldVersion AND CDIO.VersionKey[h]<=15 THEN { ReadCell23[ob, h]; RETURN [ob] }; specific.ir _ CDIO.ReadRect[h]; specific.simplifyOn _ TokenIO.ReadInt[h]; i _ TokenIO.ReadInt[h]; specific.specifiedIr _ (i MOD 2)#0; specific.drawBorder _ (i/2)#0; [specific.sequence, specific.contents] _ ReadInstances[h]; IF h.oldVersion AND CDIO.VersionKey[h]<17 THEN OldResize24Cell[ob] ELSE [] _ ResizeCell[NIL, ob]; IF ob.bbox.y2>ob.bbox.y1 THEN specific.simplifyOn _ specific.simplifyOn/(ob.bbox.y2-ob.bbox.y1); CDDirectory.SetOwner[CDIO.DesignInReadOperation[h], ob]; RETURN [ob]; }; ReadInstances: PUBLIC PROC [h: TokenIO.Handle] RETURNS [seq: CD.InstanceSequence, list: CD.InstanceList_NIL] = { maxSSize: NAT = 10000; num: INT = TokenIO.ReadInt[h]; newSLeng: INT _ MIN[maxSSize, num]; natNewSLeng: NAT _ newSLeng; seq _ NEW[CD.InstanceSequenceRep[natNewSLeng]]; FOR n: NAT IN [0..natNewSLeng) DO seq[n] _ CDIO.ReadInstance[h]; ENDLOOP; seq.length _ natNewSLeng; THROUGH [natNewSLeng..num) DO list _ CONS[CDIO.ReadInstance[h], list]; ENDLOOP; }; CountInstances: PUBLIC PROC [cell: CD.Object] RETURNS [n: INT_0] = { specific: CD.CellSpecific = NARROW[cell.specific]; n _ CDInstances.Length[specific.contents]; IF specific.sequence#NIL THEN n _ n+specific.sequence.length }; WriteCell: CD.InternalWriteProc = { specific: CD.CellSpecific = NARROW[ob.specific]; sLeng: NAT _ IF specific.sequence=NIL THEN 0 ELSE specific.sequence.length; i: INT _ IF specific.drawBorder THEN 2 ELSE 0; IF specific.specifiedIr THEN i _ i+1; CDIO.WriteRect[h, specific.ir]; TokenIO.WriteInt[h, Real.Round[ MAX[MIN[specific.simplifyOn, 500.0], 0.0] * MAX[MIN[(ob.bbox.y2-ob.bbox.y1), 100000], 0] ]]; TokenIO.WriteInt[h, i]; TokenIO.WriteInt[h, CountInstances[ob]]; FOR l: CD.InstanceList _ specific.contents, l.rest WHILE l#NIL DO CDIO.WriteInstance[h, l.first]; ENDLOOP; IF specific.sequence#NIL THEN FOR n: NAT IN [0..specific.sequence.length) DO CDIO.WriteInstance[h, specific.sequence[n]]; ENDLOOP; }; ReplaceDirectChildForCell: PUBLIC PROC [me: CD.Object, design: CD.Design, replace: CDDirectory.ReplaceList] RETURNS [changed: BOOL_FALSE] = { cp: CD.CellSpecific = NARROW[me.specific]; IF me.immutable THEN ERROR; FOR replaceList: CDDirectory.ReplaceList _ replace, replaceList.rest WHILE replaceList#NIL DO rep: REF CDDirectory.ReplaceRec = replaceList.first; PerInst: PROC [i: CD.Instance] = --INLINE-- { IF i.ob=rep.old THEN { changed _ TRUE; IF rep.trans#[] THEN i.trans _ CDBasics.ComposeTransform[itemInCell: rep.trans, cellInWorld: i.trans].itemInWorld; i.ob _ rep.new }; }; IF rep.old=me THEN LOOP; FOR l: CD.InstanceList _ cp.contents, l.rest WHILE l#NIL DO PerInst[l.first] ENDLOOP; IF cp.sequence#NIL THEN FOR n: NAT IN [0..cp.sequence.length) DO PerInst[cp.sequence[n]] ENDLOOP; ENDLOOP; IF changed AND ~cp.dummyCell THEN [] _ ResizeCell[design, me]; }; Bounds: PUBLIC PROC [list: CD.InstanceList_NIL, seq: CD.InstanceSequence_NIL, doIr: BOOL_TRUE, doBb: BOOL_TRUE] RETURNS [ir, bbox: CD.Rect _ CDBasics.empty] = { FOR l: LIST OF CD.Instance _ list, l.rest WHILE l#NIL DO IF doBb THEN bbox _ CDBasics.Surround[bbox, CDInstances.InstRectO[l.first]]; IF doIr AND ~CDLayers.SuppressIR[l.first.ob.layer] THEN ir _ CDBasics.Surround[ir, CDInstances.InstRectI[l.first]]; ENDLOOP; IF seq#NIL THEN FOR n: NAT IN [0..seq.length) DO IF doBb THEN bbox _ CDBasics.Surround[bbox, CDInstances.InstRectO[seq[n]]]; IF doIr AND ~CDLayers.SuppressIR[seq[n].ob.layer] THEN ir _ CDBasics.Surround[ir, CDInstances.InstRectI[seq[n]]]; ENDLOOP; }; EnumerateInstances: PUBLIC PROC [cell: CD.Object, proc: CDCells.InstEnumerator] RETURNS [quit: BOOL] = { cp: CD.CellSpecific _ NARROW[cell.specific]; quit _ EnumInsts[cp.contents, cp.sequence, proc]; }; EnumInsts: PUBLIC PROC [list: CD.InstanceList, seq: CD.InstanceSequence, proc: CDCells.InstEnumerator] RETURNS [quit: BOOL_FALSE] = { FOR l: LIST OF CD.Instance _ list, l.rest WHILE l#NIL DO IF quit THEN RETURN; quit _ proc[l.first] ENDLOOP; IF seq#NIL THEN FOR n: NAT IN [0..seq.length) DO IF quit THEN RETURN; quit _ proc[seq[n]] ENDLOOP; }; OldResize24Cell: PROC [cell: CD.Object] = { OldIBounds: PROC [list: CD.InstanceList_NIL, seq: CD.InstanceSequence_NIL] RETURNS [ir: CD.Rect _ CDBasics.empty] = { FOR l: LIST OF CD.Instance _ list, l.rest WHILE l#NIL DO ir _ CDBasics.Surround[ir, CDInstances.InstRectI[l.first]]; ENDLOOP; IF seq#NIL THEN FOR n: NAT IN [0..seq.length) DO ir _ CDBasics.Surround[ir, CDInstances.InstRectI[seq[n]]]; ENDLOOP; }; cp: CD.CellSpecific = NARROW[cell.specific]; IF ~cp.dummyCell THEN { oldBb: CD.Rect _ cell.bbox; oldIr: CD.Rect _ cp.ir; bb, ir, oir: CD.Rect; [ir, bb] _ Bounds[cp.contents, cp.sequence, ~cp.specifiedIr, TRUE]; IF cp.specifiedIr THEN ir _ cp.ir ELSE { oir _ OldIBounds[cp.contents, cp.sequence]; IF ir#oir THEN {cp.specifiedIr_TRUE; ir_oir}; }; bb _ CDBasics.Surround[bb, ir]; IF ~CDBasics.NonEmpty[bb] THEN ir _ bb _ [0, 0, 1, 1]; IF ~CDBasics.NonEmpty[ir] THEN ir _ bb; cp.ir _ ir; cell.bbox _ bb; IF cp.simplifyOn<0 THEN SetSimplificationTreshhold[cell, -1]; } }; ResizeCell: PUBLIC PROC [design: CD.Design, cell: CD.Object] RETURNS [didResize: BOOL] = { max: CD.Number = 536870910; -- LAST[CD.Number]/4-1 cp: CD.CellSpecific = NARROW[cell.specific]; IF cp.dummyCell THEN RETURN [didResize_FALSE] ELSE { oldBb: CD.Rect _ cell.bbox; oldIr: CD.Rect _ cp.ir; bb, ir: CD.Rect; [ir, bb] _ Bounds[cp.contents, cp.sequence, ~cp.specifiedIr, TRUE]; IF cp.specifiedIr THEN ir _ cp.ir; bb _ CDBasics.Surround[bb, ir]; IF ~CDBasics.NonEmpty[bb] THEN ir _ bb _ [0, 0, 1, 1]; IF ~CDBasics.NonEmpty[ir] THEN ir _ bb; IF didResize _ (ir#oldIr OR bb#oldBb) THEN { cp.ir _ ir; cell.bbox _ bb; CDDirectory.PropagateResize[design, cell] }; IF bb.x1<=-max OR bb.x2>=max OR bb.y1<=-max OR bb.y2>=max THEN TerminalIO.PutRopes["**WARNING: cell ", CD.Describe[cell, NIL, design], " too large, it might generate arithmetic overflow\n"]; IF cp.simplifyOn<0 THEN SetSimplificationTreshhold[cell, -1]; } }; IsPushedIn: PUBLIC PROC [design: CD.Design] RETURNS [yes: BOOL] = { RETURN [ design^.actual.rest#NIL ] }; IsEmpty: PUBLIC PROC [cell: CD.Object] RETURNS [BOOL_FALSE] = { cp: CD.CellSpecific _ NARROW[cell.specific]; IF cp.contents=NIL THEN RETURN [ cp.sequence=NIL OR cp.sequence.length=0 ] }; PushedCellName: PUBLIC PROC [design: CD.Design] RETURNS [Rope.ROPE] = { RETURN [SELECT TRUE FROM design=NIL => "no design", design.actual.rest=NIL => "top level", ENDCASE => design.actual.first.desc ] }; SetInterestRect: PUBLIC PROC [design: CD.Design, cell: CD.Object, r: CD.Rect _ [0, 0, -1, -1], mode: CDCells.IncludeMode] = { cp: CD.CellSpecific _ NARROW[cell.specific]; old: CD.Rect _ cp.ir; cp.specifiedIr _ CDBasics.NonEmpty[r]; IF ~cp.specifiedIr THEN { r _ Bounds[cp.contents, cp.sequence, TRUE, FALSE].ir; IF CDBasics.NonEmpty[r] THEN r _ cell.bbox; }; cp.ir _ r; SELECT mode FROM doit, dontNotify => [] _ ResizeCell[design, cell]; ENDCASE => NULL; IF mode=doit THEN CDDirectory.PropagateChange[cell, design]; }; SetBorderMode: PUBLIC PROC [cell: CD.Object, draw: BOOL] = { WITH cell.specific SELECT FROM cp: CD.CellSpecific => cp.drawBorder _ draw ENDCASE => NULL; }; SetSimplificationTreshhold: PUBLIC PROC [cell: CD.Object, val: REAL, inPixels: BOOL_TRUE] = { WITH cell.specific SELECT FROM cp: CD.CellSpecific => cp.simplifyOn _ IF val<0 THEN 100.0/MAX[(cell.bbox.y2-cell.bbox.y1)+(cell.bbox.x2-cell.bbox.x1), 2] ELSE IF inPixels THEN val/MAX[(cell.bbox.y2-cell.bbox.y1), 1] ELSE val; ENDCASE => NULL; }; ToSequenceMode: PUBLIC PROC [cell: CD.Object] = { IF CDCells.IsCell[cell] AND ~IsDummyCell[cell] THEN { cp: CD.CellSpecific _ NARROW[cell.specific]; [cp.contents, cp.sequence] _ CopyInsts[cp.contents, cp.sequence, TRUE] } }; -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- IncludeInstance: PUBLIC PROC [design: CD.Design _ NIL, cell: CD.Object _ NIL, inst: CD.Instance, mode: CDCells.IncludeMode] RETURNS [resize: BOOL] = { cp: CD.CellSpecific; IF inst=NIL OR inst.ob=NIL THEN ERROR CD.Error[calling, "Include NIL inst"]; IF cell#NIL THEN cp _ NARROW[cell.specific] ELSE IF design#NIL THEN cp _ design^.actual.first.specific ELSE ERROR; IF cell=NIL THEN cp.contents _ CONS[inst, cp.contents] --does not yet change insideRect !! ELSE { IF cell.immutable THEN ERROR; cp.contents _ CONS[inst, cp.contents]; --does not yet change insideRect !! resize _ ~CDBasics.Inside[CDInstances.InstRectO[inst], cell.bbox]; IF ~resize AND ~cp.specifiedIr THEN resize _ ~CDBasics.Inside[CDInstances.InstRectI[inst], cp.ir]; IF resize THEN SELECT mode FROM doit, dontNotify => [] _ ResizeCell[design, cell]; ENDCASE => NULL; IF mode=doit THEN CDDirectory.PropagateChange[cell, design]; }; IF design#NIL AND mode=doit THEN { IF cp.dummyCell THEN CDOps.RedrawInstance[design, inst, FALSE] ELSE CDOps.Redraw[design] }; }; IncludeOb: PUBLIC PROC [design: CD.Design, cell: CD.Object, ob: CD.Object, trans: CD.Transformation, mode: CDCells.IncludeMode] RETURNS [newInst: CD.Instance_NIL, resize: BOOL_FALSE] = { newInst _ NEW[CD.InstanceRep _ [ob: ob, trans: trans]]; resize _ IncludeInstance[design, cell, newInst, mode]; }; RemoveN: ENTRY PROC [seq: CD.InstanceSequence, n: INT] = { ENABLE UNWIND => NULL; IF seq#NIL THEN { leng: NAT _ seq.length; IF leng>seq.size THEN { leng _ seq.length _ seq.size; TRUSTED {Process.Detach[FORK TerminalIO.PutRope["**unconsistant instance sequence found/n"]]}; }; IF n>=leng OR leng=0 THEN RETURN; seq[n] _ seq[leng-1]; seq.length _ leng-1; seq[leng-1] _ NIL; } }; RemoveInstance: PUBLIC PROC [design: CD.Design _ NIL, cell: CD.Object, inst: CD.Instance, mode: CDCells.IncludeMode] RETURNS [resize: BOOL] = { cp: CD.CellSpecific; done: BOOL _ FALSE; IF cell=NIL THEN { IF design=NIL THEN ERROR CD.Error[calling, "Remove from NIL cell"]; cp _ design^.actual.first.specific; } ELSE { IF cell.immutable THEN ERROR; cp _ NARROW[cell.specific]; }; IF cp.contents#NIL THEN { IF cp.contents.first=inst THEN {cp.contents _ cp.contents.rest; done _ TRUE} ELSE FOR list: CD.InstanceList _ cp.contents, list.rest WHILE list.rest#NIL DO IF list.rest.first=inst THEN {list.rest _ list.rest.rest; done _ TRUE; EXIT} ENDLOOP; }; IF ~done AND cp.sequence#NIL THEN FOR n: NAT IN [0..cp.sequence.length) DO IF cp.sequence[n]=inst THEN { RemoveN[cp.sequence, n]; done _ TRUE; EXIT } ENDLOOP; IF cell#NIL THEN { oldr: CD.Rect _ CDBasics.Surround[cell.bbox, cp.ir]; r: CD.Rect = CDInstances.InstRectO[inst]; resize _ r.x1<=oldr.x1 OR r.y1<=oldr.y1 OR r.x2>=oldr.x2 OR r.y2>=oldr.y2; IF ~resize AND ~cp.specifiedIr THEN { r: CD.Rect = CDInstances.InstRectI[inst]; resize _ r.x1<=cp.ir.x1 OR r.y1<=cp.ir.y1 OR r.x2>=cp.ir.x2 OR r.y2>=cp.ir.y2; }; IF resize THEN SELECT mode FROM doit, dontNotify => [] _ ResizeCell[design, cell]; ENDCASE => NULL; IF mode=doit THEN CDDirectory.PropagateChange[cell, design]; }; IF design#NIL AND mode=doit THEN { IF cp.dummyCell THEN CDOps.RedrawInstance[design, inst] ELSE CDOps.Redraw[design] }; }; Get23Table: PROC [h: TokenIO.Handle] RETURNS [RefTab.Ref_NIL] = { rt: RefTab.Ref; WITH Properties.GetProp[h.properties^, $convert23] SELECT FROM tab: RefTab.Ref => rt _ tab; ENDCASE => { rt _ RefTab.Create[201]; h.properties^ _ Properties.PutProp[h.properties^, $convert23, rt] }; RETURN [rt]; }; ReadCell23: PROC [ob: CD.Object, h: TokenIO.Handle] = { i: INT; origin: CD.Position; oldBbox: CD.Rect; bb1: CD.Rect; specific: CD.CellSpecific = NARROW[ob.specific]; size: CD.Position _ CDIO.ReadPos[h]; IF CDIO.VersionKey[h]>=8 THEN { --not that old specific.simplifyOn _ TokenIO.ReadInt[h]; i _ TokenIO.ReadInt[h]; specific.specifiedIr _ (i MOD 2)#0; specific.drawBorder _ (i/2)#0; IF specific.specifiedIr THEN specific.ir _ CDIO.ReadRect[h]; origin _ CDIO.ReadPos[h]; } ELSE { -- very old versions IF CDIO.VersionKey[h]<1 THEN { [--name--] _ TokenIO.ReadRope[h]; } ELSE { specific.simplifyOn _ TokenIO.ReadInt[h]; }; }; [specific.sequence, specific.contents] _ ReadInstances[h]; oldBbox _ CDBasics.RectAt[[0, 0], size]; bb1 _ BoundsSL23[specific.sequence, specific.contents, h]; IF bb1#oldBbox THEN { TerminalIO.PutRope["conversion problem; check design carefully\n"]; }; [] _ ResizeCell[NIL, ob]; IF oldBbox#ob.bbox THEN PutBox23[ob, h, oldBbox]; IF ob.bbox.y2>ob.bbox.y1 THEN specific.simplifyOn _ specific.simplifyOn/(ob.bbox.y2-ob.bbox.y1); }; PutBox23: PROC [ob: CD.Object, h: TokenIO.Handle, bbox: CD.Rect] = { tab: RefTab.Ref _ Get23Table[h]; [] _ RefTab.Insert[tab, ob, NEW[CD.Rect_bbox]] }; BBox23: PROC [ob: CD.Object, h: TokenIO.Handle] RETURNS [bbox: CD.Rect] = { bbox_ob.bbox; IF ob.class.composed THEN WITH RefTab.Fetch[Get23Table[h], ob].val SELECT FROM rr: REF CD.Rect => RETURN [rr^] ENDCASE => NULL; }; InstRectOBound23: PROC [inst: CD.Instance, h: TokenIO.Handle] RETURNS [CD.Rect] = { RETURN [CDBasics.MapRect[BBox23[inst.ob, h], inst.trans]] }; BoundsSL23: PROC [seq: CD.InstanceSequence_NIL, list: CD.InstanceList_NIL, h: TokenIO.Handle] RETURNS [bbox: CD.Rect_CDBasics.empty] = { Proc: CDCells.InstEnumerator = { bbox _ CDBasics.Surround[bbox, InstRectOBound23[inst, h]]; }; [] _ EnumInsts[list, seq, Proc]; }; Init[]; END. ¸CDCellsImpl.mesa (part of ChipNDale) Copyright c 1983, 1987 by Xerox Corporation. All rights reserved. Created by Christian Jacobi, June 24, 1983 5:00 pm Last Edited by: Christian Jacobi, October 16, 1987 11:57:49 am PDT --old stuff for io format version 4 --makes a copy of the list and the sequence, but tries to make the sequence as long as possible --inPlace TRUE: just re-use old Instances; FALSE: copy the Instances --draw border --draw inside --we do want to yield, but not too often --draw border --draw inside --speed up rects... RETURN [ CreateCell[CDInstances.DeComposedList[il, cTrans], CDBasics.DeMapRect[ir, cTrans]] ] [il, sq] _ CopyInsts[il, sq, FALSE, CDBasics.InverseTransform[cTrans]]; --be conservative; make sure no nil instances are introduced by bad client concurrency --xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --old file format versions --it doesn't work with properties, they aren't yet initialized Ê ˜codešœ&™&Kšœ Ïmœ7™BKšœ3™3K™BK˜—šÏk ˜ Kšžœ˜K˜ K˜K˜K˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœžœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜—K˜šÏn œžœžœ˜Kšžœžœžœ‡˜­Kšžœ˜ Kšžœžœ˜"—Kšž˜K˜šœ ž œžœ˜BKšœ˜Kšœ!˜!Kšœ"˜"Kšœ˜Kšœ˜Kšœ ˜ Kšœ žœ˜K˜Kšœ˜—Kšœ žœžœ˜.K˜šŸœžœ˜šœžœL˜SKšœ-˜-Kšœ˜Kšœ.˜.Kšœ˜—Kšœ0˜0šœ-˜-šœ%˜%Kšœ!˜!Kšœžœ˜Kšœ#˜#Kšœ ž˜Kšœ˜—Kšœ˜—Kšœ˜—K˜šŸ œžœžœžœ žœžœžœ˜Cšžœžœž˜Kšœžœžœ˜-Kšžœžœ˜—K˜K˜—š Ÿœžœžœžœžœ˜QKšœ#™#Kšœžœžœžœ ˜%Kšœ˜—K˜š Ÿœžœžœ žœžœ ˜=Kšžœžœžœ˜0Kšœ˜K˜—šŸœžœžœ1žœžœžœžœ˜wKšœžœžœ˜*š žœžœ'žœžœžœž˜NKšžœžœžœžœ˜4Kšžœ˜—šžœ žœžœ˜šžœžœžœžœ˜)Kšžœžœžœžœ˜9Kšžœ˜——Kšœ˜—K˜šŸœžœžœžœžœžœžœ žœžœžœžœ,žœžœ˜®Kšœžœžœ˜-Kšœžœžœ˜.Kšœ˜Kšœ˜Kšœžœ˜KšœM˜MKšœV˜Všžœžœžœ˜Kšœ ˜ Kšžœžœžœ˜.K˜—Kšœ˜—K˜šŸ œž œžœžœžœžœžœ žœžœ žœ˜¢KšÏc_™_Kš D™DKšœ žœ ˜Kšœžœ ˜Kšœ žœ˜Kš œ žœžœžœžœžœžœ˜AKšœ žœžœ.˜AKšœžœžœ ˜.šž˜Kšžœžœ˜4Kšžœžœžœžœ$˜9Kšžœžœ˜ š žœžœžœžœžœ˜Kšžœ žœ˜)Kšžœ žœ˜.Kš žœžœ žœ žœ žœ˜2Kšžœ žœ ˜K˜—Kšžœ˜—Kšœ˜K˜—K˜š Ÿ œžœžœžœžœ˜Nšžœ6žœž˜EKšœžœ*žœ˜6Kšžœž˜—Kšœ˜—K˜šŸœ˜Kšœžœžœ˜;Kšœ žœ? '˜qK™ šžœ žœ žœ˜%Kšœ*žœ,˜X—K™ š žœžœ$žœžœž˜;šžœ.žœ˜6Kšžœžœžœ˜Kšœb˜bK˜—Kšžœ˜—šžœ žœž˜šžœžœžœž˜(šžœ5žœ˜=Kšžœžœžœ˜Kšœ}˜}K˜—Kšžœ˜——Kšžœžœžœ˜BKšœ˜Kšœ˜—J˜Jšœžœ˜šŸœžœžœ˜J™(Jšžœ žœ˜(J˜—K˜šŸœ˜$Kšœžœžœ˜*šžœžœžœ˜9Kšœ3žœ˜Dšžœ(žœ˜1Kšœ žœ#˜2Kšžœžœžœ:˜JK˜—K˜—šžœ˜Kšœ žœ: '˜lK™ šžœ žœ žœ˜%KšœJ˜J—K™ š žœžœ$žœžœž˜;šžœ.žœ˜6Kšžœžœžœ˜Kšœr˜rK˜—Kšžœ˜—šžœ žœž˜šžœžœžœž˜(šžœ5žœ˜=K™Kšžœžœžœ˜šžœ/žœ˜6šœ˜Kšœp˜pKšœ˜——šžœ˜Kšœ”˜”—K˜—Kšžœ˜——Kšœ˜Kšžœžœžœ˜BKšžœžœ˜0Kšœ˜—Kšœ˜—K˜šŸœ˜"Kšœžœ˜*šžœžœžœ˜6Kšœ6žœ ˜D—šžœ˜Kšœ8žœ˜K—Kšœ˜—K˜š Ÿœžœžœžœžœ ˜;šœžœžœ ˜Kšœ˜Kšœ˜Kšœ žœžœ˜*Kšœ˜—Kšœ˜—K˜šŸ œžœžœžœžœžœžœžœžœžœ ˜Kšœžœ˜"Kšœžœžœ˜*Kšœ˜Kšœ˜Kšœžœ˜)Kšœžœ˜Kšœ#˜#Kšžœ˜ Kšœ˜—K˜šŸœžœžœžœžœžœžœžœžœžœžœ ˜­KšžœW™]Kšœžœ%™GKšœžœ˜$š žœžœžœžœž˜2KšœC˜CKšžœ˜—šžœžœž˜šžœžœžœž˜Kšœ?˜?Kšžœ˜——Kšžœ7˜=K˜—K˜šÐbnœžœ˜!Kšœžœ˜Kšœžœ˜"Kšœ žœžœ˜0šžœžœžœžœ˜1Kšœžœ˜K˜—Kšœžœ˜ Kšœ)˜)Kšœ˜Kšœžœ˜#Kšœžœ˜Kšœ:˜:šžœžœžœ˜*Kšžœ˜Kšžœžœ˜—šžœžœ˜KšœB˜B—Kšœžœ˜8Kšžœ˜ K˜K˜—š Ÿ œžœžœžœ"žœžœ˜pKšœ žœ ˜Kšœžœ˜Kšœ žœžœžœ ˜@Kšœžœžœ#˜/šžœžœžœž˜!Kšœ žœ˜Kšžœ˜—Kšœ˜šžœž˜Kšœžœžœ˜(Kšžœ˜—Kšœ˜—K˜š Ÿœž œžœ žœžœ˜DKšœ žœžœ˜2Kšœ*˜*Kšžœžœžœ˜Kšœ˜K˜—šŸœž œžœžœžœžœžœžœžœžœžœ žœ˜ š žœžœžœžœžœžœž˜8Kšžœžœ@˜Lšžœžœ(žœ˜8Kšœ;˜;—Kšžœ˜—šžœžœž˜šžœžœžœž˜ Kšžœžœ?˜Kšžœžœ'žœ˜7Kšœ:˜:—Kšžœ˜——K˜—K˜š Ÿœžœžœžœ'žœžœ˜hKšœžœžœ˜,Kšœ1˜1Kšœ˜—K˜šŸ œž œžœžœ1žœžœžœ˜…š žœžœžœžœžœžœž˜8Kšžœžœžœ˜Kšœ˜Kšžœ˜—šžœžœž˜šžœžœžœž˜ Kšžœžœžœ˜Kšœ˜Kšžœ˜——K˜—K˜šŸœžœžœ ˜+šŸ œžœžœžœžœžœžœžœ˜uš žœžœžœžœžœžœž˜8Kšœ;˜;Kšžœ˜—šžœžœž˜šžœžœžœž˜ Kšœ:˜:Kšžœ˜——K˜—Kšœžœžœ˜,šžœžœ˜Kšœžœžœ˜3Kšœ žœ˜Kšœ,žœžœ˜CKšžœžœ ˜!šžœ˜Jšœ+˜+Jšžœžœžœ ˜-J˜—Kšœ˜Kšžœžœ˜6Kšžœžœž˜'Kšœ˜Kšžœžœ&˜=K˜—Kšœ˜—K˜šŸ œžœžœ žœžœ žœ žœ˜ZKšœžœ ˜2Kšœžœžœ˜,Kšžœžœžœ žœ˜-šžœ˜Kšœžœžœ˜3Kšœžœ˜Kšœ=žœ˜CKšžœžœ ˜"Kšœ˜Kšžœžœ˜6Kšžœžœž˜'šžœžœ žœ˜,Kšœ˜Kšœ)˜)Kšœ˜—š žœ žœ žœ žœ ž˜>Kšœ(žœžœB˜—Kšžœžœ&˜=K˜—Kšœ˜—K˜š Ÿ œž œ žœ žœžœ˜CKšžœžœ˜"Kšœ˜K™—šŸœžœžœžœ žœžœžœ˜?Kšœžœžœ˜,šžœ žœž˜Kšžœžœžœ˜2—K˜K˜—š Ÿœžœžœ žœ žœžœ˜Gšžœžœžœž˜Kšœžœ˜Kšœžœ˜&Kšžœ˜$Kšœ˜—Kšœ˜—K˜š Ÿœžœžœ žœžœ žœ6˜}Kšœžœžœ˜,Kšœ˜Kšœ&˜&šžœžœ˜Kšœ%žœžœ˜5Kšžœžœ˜+K˜—Kšœ ˜ šžœž˜Kšœ2˜2Kšžœžœ˜—Kšžœ žœ+˜Kšžœ˜ —Kšžœžœ˜—Kšœ˜—K˜šŸœžœžœžœ ˜1šžœžœžœ˜5Jšœžœžœ˜,JšœAžœ˜FJ˜—J˜—K˜K˜0K˜šŸœžœžœ žœ žœžœ žœžœ&žœ žœ˜–Kšœžœ˜Kšžœžœžœ žœžœžœžœ$˜LKšžœžœžœžœ˜+Kšžœžœžœžœ#˜:Kšžœžœ˜ Kš žœžœžœžœ #˜Zšžœ˜Kšžœžœžœ˜Kšœžœ #˜JKšœB˜Bšžœ žœžœ˜%Kšœ>˜>—šžœžœ˜šžœž˜Kšœ2˜2Kšžœžœ˜——Kšžœ žœ+˜Kšœ˜šžœ˜ Kšœ˜KšœA˜AK˜——Kšžœ˜ K˜—K˜š¡ œžœžœ˜7Kš ™Kšœžœ žœ*˜™>šžœ%žœž˜4Kšœžœžœ žœ˜Kšžœžœ˜——Kšœ˜K˜—š Ÿœžœžœžœžœ ˜SKšžœ3˜9Kšœ˜K˜—šŸ œžœžœžœžœžœžœžœ˜ˆšŸœ˜ Kšœ:˜:K˜—Kšœ ˜ K˜—K˜K˜Kšžœ˜K˜—…—Q¦r~