DIRECTORY CD, CDApplications, CDCallSpecific, CDCells, CDDirectory, CDMenus, CDEvents, CDBasics, CDInterestRects, CDIO, CDMarks, CDOps, CDOrient, CDProperties, CDRects, Process USING [Yield], Rope, TokenIO, TerminalIO; CDCellsImpl: CEDAR PROGRAM IMPORTS CD, CDApplications, CDCallSpecific, CDIO, CDDirectory, CDEvents, CDBasics, CDMarks, CDMenus, CDOps, CDOrient, CDProperties, CDRects, Process, Rope, TokenIO, TerminalIO, CDInterestRects EXPORTS CDCells SHARES CDDirectory = BEGIN -- -- -- -- -- -- -- -- -- -- -- -- pForCells: REF CD.ObjectProcs = CD.RegisterObjectType[$Cell]; beforeReplace: CDEvents.EventRegistration = CDEvents.RegisterEventType[$BeforeCellReplacement]; afterReplace: CDEvents.EventRegistration = CDEvents.RegisterEventType[$AfterCellReplacement]; pushEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$AfterPush]; popEvent: CDEvents.EventRegistration = CDEvents.RegisterEventType[$AfterPop]; fullPopMenu: REF = CDMenus.CreateMenu["Pop from cell"]; partialPopMenu: REF = CDMenus.CreateMenu["Pop from cell"]; emptyPopMenu: REF = CDMenus.CreateMenu["Pop from cell: empty cell"]; lastOutputDesign: CD.Design _ NIL; Init: PROC [] = BEGIN dp: REF CDDirectory.DirectoryProcs = CDDirectory.InstallDirectoryProcs[pForCells]; dp.enumerateChildObjects _ EnumerateChildObjects; dp.name _ Name; dp.setName _ SetName; dp.another _ Another; dp.replaceDirectChilds _ ReplaceDirectChildForCells; pForCells.drawMe _ DrawMeForCells; pForCells.quickDrawMe _ QuickDrawMeForCells; pForCells.showMeSelected _ DrawCellSelection; pForCells.internalRead _ ReadCell; pForCells.internalWrite _ WriteCell; pForCells.describe _ Describe; pForCells.interestRect _ InterestRectCells; pForCells.oldInsideRect _ OldInsideRect; pForCells.origin _ OriginForCells; CDInterestRects.InstallOldSetInterest[pForCells, OldSetInterest]; CDCallSpecific.Register[$Expand, pForCells, Expand]; CDMenus.CreateEntry[fullPopMenu, "flush", $flush]; CDMenus.CreateEntry[partialPopMenu, "flush", $flush]; CDMenus.CreateEntry[emptyPopMenu, "flush", $flush]; CDMenus.CreateEntry[fullPopMenu, "new cell", $new]; CDMenus.CreateEntry[partialPopMenu, "new cell", $new]; CDMenus.CreateEntry[fullPopMenu, "replace", $replace]; [] _ CDProperties.RegisterProperty[$InsideRect]; CDProperties.InstallProcs[prop: $InsideRect, new: CDProperties.PropertyProcsRec[ makeCopy: CDProperties.DontCopy, internalWrite: NIL, internalRead: InternalReadProperty, exclusive: TRUE ] ]; CDEvents.RegisterEventProc[$WriteTechnologyPrivate, RememberDesignOnWriting]; END; InternalReadProperty: PROC [prop: ATOM] RETURNS [val: REF] = BEGIN x1: INT = TokenIO.ReadInt[]; y1: INT = TokenIO.ReadInt[]; x2: INT = TokenIO.ReadInt[]; y2: INT = TokenIO.ReadInt[]; val _ NEW[CD.DesignRect _ [x1, y1, x2, y2]] END; InterestRectCells: PROC [ob: CD.ObPtr] RETURNS [CD.DesignRect] = BEGIN RETURN [NARROW[ob.specificRef, CD.CellPtr].ir] END; OriginForCells: PROC [ob: CD.ObPtr] RETURNS [CD.DesignPosition] = BEGIN RETURN [NARROW[ob.specificRef, CD.CellPtr].origin] END; OldInsideRect: PROC [ob: CD.ObPtr] RETURNS [CD.DesignRect] = BEGIN RETURN [NARROW[ob.specificRef, CD.CellPtr].dIr] END; OldSetInterest: PROC [ob: CD.ObPtr, r: CD.DesignRect] = BEGIN cptr: CD.CellPtr = NARROW[ob.specificRef]; cptr.ir _ r; cptr.useDIr _ FALSE; END; SetInsideRect: PROC [ob: CD.ObPtr, r: CD.DesignRect_CDBasics.empty] = BEGIN cptr: CD.CellPtr = NARROW[ob.specificRef]; IF CDBasics.NonEmpty[r] THEN cptr.dIr _ r ELSE cptr.dIr _ CDBasics.RectAt[[0,0], ob.size] END; SetName: PROC [me: CD.ObPtr, r: Rope.ROPE] = BEGIN cptr: CD.CellPtr = NARROW[me.specificRef]; cptr.name _ r END; Name: PROC [me: CD.ObPtr] RETURNS [Rope.ROPE] = BEGIN cptr: CD.CellPtr = NARROW[me.specificRef]; RETURN [cptr.name] END; EnumerateChildObjects: PROC [me: CD.ObPtr, p: CDDirectory.EnumerateObjectsProc, x: REF] = BEGIN cptr: CD.CellPtr = NARROW[me.specificRef]; FOR w: CD.ApplicationList _ cptr.contents, w.rest WHILE w#NIL DO p[w.first.ob, x] ENDLOOP END; Another: PROC [me: CD.ObPtr, from, to: CD.Design] RETURNS [CD.ObPtr] = BEGIN oldCp: CD.CellPtr = NARROW[me.specificRef]; newOb: CD.ObPtr = CreateEmptyCell[]; newCp: CD.CellPtr = NARROW[newOb.specificRef]; newOb.size _ me.size; newCp^ _ oldCp^; newCp.contents _ CDApplications.CopyList[oldCp.contents]; newOb.properties _ CDProperties.CopyProps[newOb.properties]; [] _ CDDirectory.Include[to, newOb]; RETURN [newOb] END; DrawMeForCells: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN ENABLE UNWIND => IF pr.nesting.table[pr.nestDepth_1]=aptr THEN pr.nestDepth _ pr.nestDepth-1; cptr: CD.CellPtr = NARROW[aptr.ob.specificRef]; r: CD.DesignRect; pr.nesting.table[pr.nestDepth] _ aptr; pr.nestDepth _ pr.nestDepth+1; FOR w: CD.ApplicationList _ cptr.contents, w.rest WHILE w#NIL DO r _ CDOrient.MapRect[ itemInCell: CDOrient.RectAt[w.first.location, w.first.ob.size, w.first.orientation], cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos]; IF CDBasics.Intersect[r, pr.interestClip] THEN { IF pr.stopFlag^ THEN EXIT; pr.drawChild[ w.first, CDBasics.BaseOfRect[r], CDOrient.ComposeOrient[w.first.orientation, orient], pr]; } ENDLOOP; pr.nestDepth _ pr.nestDepth-1; Process.Yield[]; END; QuickDrawMeForCells: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN ENABLE UNWIND => IF pr.nesting.table[pr.nestDepth_1]=aptr THEN pr.nestDepth _ pr.nestDepth-1; cptr: CD.CellPtr = NARROW[aptr.ob.specificRef]; r: REAL; IF (r _ pr.scaleHint*aptr.ob.size.y)0 THEN { pr.outLineProc[CDOrient.RectAt[pos, aptr.ob.size, orient], pr]; IF r>9 THEN pr.drawComment[CDOrient.RectAt[pos, aptr.ob.size, orient], cptr.name, pr]; } ELSE { r: CD.DesignRect; pr.nesting.table[pr.nestDepth] _ aptr; pr.nestDepth _ pr.nestDepth+1; FOR w: CD.ApplicationList _ cptr.contents, w.rest WHILE w#NIL DO r _ CDOrient.MapRect[ itemInCell: CDOrient.RectAt[w.first.location, w.first.ob.size, w.first.orientation], cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos]; IF CDBasics.Intersect[r, pr.interestClip] THEN { IF pr.stopFlag^ THEN EXIT; w.first.ob.p.quickDrawMe[ w.first, CDBasics.BaseOfRect[r], CDOrient.ComposeOrient[w.first.orientation, orient], pr]; } ENDLOOP; Process.Yield[]; pr.nestDepth _ pr.nestDepth-1; } END; DrawCellSelection: PROC [aptr: CD.ApplicationPtr, pos: CD.DesignPosition, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN IF (pr.scaleHint*aptr.ob.size.y)0 THEN pr.drawRect[CDOrient.RectAt[pos, aptr.ob.size, orient], CD.highLightShade, pr] ELSE { pr.outLineProc[ CDOrient.MapRect[ itemInCell: CD.InterestRect[aptr.ob], cellSize: aptr.ob.size, cellInstOrient: orient, cellInstPos: pos ], pr ] } END; RemoveSelectedFromWorld: PROC [design: CD.Design] RETURNS [CD.ApplicationList] = BEGIN remove, keep: CD.ApplicationList _ NIL; [others: keep, selected: remove] _ CDApplications.SplitSelected[CDOps.AppList[design]]; CDOps.SetAppList[design, keep]; RETURN [remove] END; CreateEmptyCell: PUBLIC PROC [] RETURNS [CD.ObPtr] = BEGIN ob: CD.ObPtr = NEW[CD.ObjectDefinition]; cp: CD.CellPtr = NEW[CD.CellRecord]; ob.p _ pForCells; ob.size _ [0, 0]; ob.specificRef _ cp; cp.simplifyOn _ 50; RETURN [ob] END; CreateCellObject: PROC [use: CD.ApplicationList, orient: CD.Orientation_CDOrient.original] RETURNS [CD.ObPtr] = BEGIN ob: CD.ObPtr = CreateEmptyCell[]; cp: CD.CellPtr = NARROW[ob.specificRef]; gOutR: CD.DesignRect = CDApplications.BoundingRectO[use]; -- coordsys of use, non oriented ob.size _ CDOrient.OrientedSize[CDBasics.SizeOfRect[gOutR], orient]; cp.contents _ CDApplications.DeComposedCopy[use, CDBasics.BaseOfRect[gOutR], ob.size, orient]; cp.ir _ cp.dIr _ CDApplications.BoundingRectI[cp.contents]; RETURN [ob] END; IncludeAndNameCell: PROC [design: CD.Design, cp: CD.ObPtr, interactive: BOOL_TRUE, allowAbort: BOOL_FALSE] RETURNS [done: BOOL] = BEGIN name: Rope.ROPE; cptr: CD.CellPtr = NARROW[cp.specificRef]; IF ~interactive THEN { [] _ CDDirectory.Include[design, cp]; RETURN [done_TRUE]; } ELSE --interactive DO fiddle: BOOL _ FALSE; aborted: BOOL _ FALSE; name _ TerminalIO.RequestRope["enter object name: " ! TerminalIO.UserAbort => {aborted_TRUE; fiddle _ TRUE; CONTINUE} ]; IF aborted THEN { TerminalIO.WriteRope[" **name input aborted\n"]; IF allowAbort THEN RETURN [done_FALSE]; }; IF Rope.IsEmpty[name] THEN { fiddle _ TRUE; name _ "-no name"; }; IF Rope.Fetch[name, name.Length[]-1]='@ THEN { fiddle _ TRUE; name _ Rope.Substr[name, 0, name.Length[]-1]; }; IF CDDirectory.Include[design, cp, name, fiddle] THEN { TerminalIO.WriteRope[cptr.name]; TerminalIO.WriteRope[" included\n"]; RETURN [done_TRUE]; }; TerminalIO.WriteRope[name]; TerminalIO.WriteRope[" does already exist\nnot accepted, please repeat\n"]; ENDLOOP; END; CreateCellSelected: PUBLIC PROC [design: CD.Design, name: Rope.ROPE_NIL] RETURNS [done: BOOL_FALSE, cellOb: CD.ObPtr_NIL] = BEGIN sel: CD.ApplicationList = RemoveSelectedFromWorld[design]; app: CD.ApplicationPtr = NEW[CD.Application]; b: CD.DesignRect = CDApplications.BoundingRectO[sel]; cptr: CD.CellPtr; app.ob _ cellOb _ CreateCellObject[use: sel]; cptr _ NARROW[cellOb.specificRef]; cptr.name _ name; app.location _ CDBasics.BaseOfRect[b]; app.selected _ TRUE; IF NOT CDBasics.NonEmpty[b] THEN { TerminalIO.WriteRope["no empty cell\n"]; RETURN [done: FALSE, cellOb: NIL] }; IF name=NIL THEN { IF ~IncludeAndNameCell[design: design, cp: cellOb, allowAbort: TRUE, interactive: TRUE].done THEN { CDOps.IncludeApplicationList[design, sel, FALSE]; RETURN [done: FALSE, cellOb: NIL] }; } ELSE [] _ CDDirectory.Include[design, cellOb]; CDOps.IncludeApplication[design, app, TRUE]; -- redraw removes seletion RETURN [done: TRUE, cellOb: cellOb] END; IsCellAp: PROC [aptr: CD.ApplicationPtr] RETURNS [yes: BOOL _ FALSE] = BEGIN IF aptr=NIL THEN TerminalIO.WriteRope[" no object\n"] ELSE IF aptr.ob=NIL OR aptr.ob.specificRef=NIL THEN TerminalIO.WriteRope[" bad object\n"] ELSE IF NOT ISTYPE[aptr.ob.specificRef, CD.CellPtr] THEN { TerminalIO.WriteRope[" object is not cell but "]; TerminalIO.WriteRope[CDOps.Info[aptr.ob]]; TerminalIO.WriteLn[]; } ELSE yes _ TRUE END; PushInCellSelected: PUBLIC PROC [design: CD.Design] RETURNS [done: BOOL _ FALSE] = BEGIN first: CD.ApplicationPtr; multiple: BOOL; [first, multiple] _ CDOps.SelectedApplication[design]; IF multiple THEN TerminalIO.WriteRope[" multiple selected object\n"] ELSE done _ DoPushInCell[design, first]; END; DoPushInCell: PROC [design: CD.Design, originalApp: CD.ApplicationPtr] RETURNS [done: BOOL_FALSE] = BEGIN IF IsCellAp[originalApp] THEN { cptr: CD.CellPtr = NARROW[originalApp.ob.specificRef]; dummy: CD.ObPtr = CreateEmptyCell[]; newCptr: CD.CellPtr = NARROW[dummy.specificRef]; dummyCellAp: CD.ApplicationPtr; dummy.size _ CDBasics.highposition; FOR l: LIST OF CD.PushRec _ design.actual, l.rest WHILE l#NIL DO IF l.first.mightReplace#NIL AND l.first.mightReplace.ob=originalApp.ob THEN { TerminalIO.WriteRope[" push not possible; [already pushed in "]; TerminalIO.WriteRope[CDOps.Info[l.first.mightReplace.ob]]; TerminalIO.WriteRope["]\n"]; RETURN [FALSE] } ENDLOOP; newCptr^ _ cptr^; newCptr.contents _ CDApplications.ComposedCopy[ al: newCptr.contents, cellPos: originalApp.location, cellSize: originalApp.ob.size, cellOrient: originalApp.orientation ]; dummyCellAp _ NEW[CD.Application_[ ob: dummy, selected: TRUE, properties: CDProperties.CopyProps[originalApp.properties] ]]; dummy.properties _ CDProperties.CopyProps[originalApp.ob.properties]; CDOps.RemoveApplication[design, originalApp]; design^.actual _ CONS[ CD.PushRec[dummyCell: dummyCellAp, specific: newCptr, mightReplace: originalApp], design^.actual ]; [] _ CDEvents.ProcessEvent[pushEvent, design]; RETURN [TRUE]; } END; PopFromCell: PUBLIC PROC [design: CD.Design, m: CDCells.Method_interactive, name: Rope.ROPE_NIL] RETURNS [done: BOOL] = BEGIN done _ IPopFromCell[design, m, name]; IF done THEN [] _ CDEvents.ProcessEvent[popEvent, design]; END; IPopFromCell: PROC [design: CD.Design, m: CDCells.Method, name: Rope.ROPE] RETURNS [done: BOOL_FALSE] = BEGIN currentRect, pushedRect: CD.DesignRect; --cd coords currentAptr, pushedAptr: CD.ApplicationPtr; currentCellOb, pushedCellOb: CD.ObPtr; currentCellPtr, pushedCellPtr: CD.CellPtr; DoFlush: PROC [] = BEGIN b: BOOL _ design^.actual.first.indirectlyChanged; TerminalIO.WriteRope["flush\n"]; design^.actual _ design^.actual.rest; design^.actual.first.indirectlyChanged _ TRUE; IF b THEN design^.actual.first.indirectlyChanged _ TRUE; CDOps.IncludeApplication[design, pushedAptr, FALSE]; END; DoReplace: PROC [] = BEGIN [] _ CDEvents.ProcessEvent[beforeReplace, design, pushedAptr.ob]; TerminalIO.WriteRope["replace\n"]; CDProperties.PutPropOnObject[onto: currentCellOb, prop: $Owner, val: design]; design^.actual _ design^.actual.rest; design^.actual.first.indirectlyChanged _ TRUE; pushedCellPtr.contents _ currentCellPtr.contents; IF pushedRect#currentRect OR currentCellPtr.ir#pushedCellPtr.ir OR currentCellPtr.dIr#pushedCellPtr.dIr THEN { -- both in design coordinates oldSize: CD.DesignPosition _ pushedAptr.ob.size; newFakeOrigin: CD.DesignPosition; --absolute coordinates newInOldCoordinates: CD.DesignPosition; --coordinates of old cell pushedAptr.ob.size _ CDOrient.OrientedSize[CDBasics.SizeOfRect[currentRect], pushedAptr.orientation]; newFakeOrigin _ CDOrient.MapPoint[ pointInCell: [0, 0], cellSize: pushedAptr.ob.size, cellInstOrient: pushedAptr.orientation, cellInstPos: currentAptr.location ].pointInWorld; newInOldCoordinates _ CDOrient.DeMapPoint[ pointInWorld: newFakeOrigin, cellSize: oldSize, cellInstOrient: pushedAptr.orientation, cellInstPos: pushedAptr.location ].pointInCell; pushedCellPtr.origin _ CDBasics.SubPoints[pushedCellPtr.origin, newInOldCoordinates]; IF ~pushedCellPtr.useDIr THEN pushedCellPtr.ir _ CDBasics.MoveRect[pushedCellPtr.ir, CDBasics.NegOffset[newInOldCoordinates]]; CDDirectory.RepositionObject[design: design, ob: pushedAptr.ob, oldSize: oldSize, baseOff: newInOldCoordinates ]; }; pushedAptr.location _ currentAptr.location; CDOps.IncludeApplication[design, pushedAptr, FALSE]; [] _ CDEvents.ProcessEvent[afterReplace, design, pushedAptr.ob]; END; DoNewCell: PROC [interactive: BOOL_FALSE] = BEGIN TerminalIO.WriteRope["new cell\n"]; currentAptr.ob _ currentCellOb; design^.actual _ design^.actual.rest; design^.actual.first.indirectlyChanged _ TRUE; design^.actual.first.changed _ TRUE; IF ~IncludeAndNameCell[design, currentCellOb, interactive, FALSE].done THEN ERROR; IF ~pushedCellPtr.useDIr THEN { gIntRect: CD.DesignRect = CDOrient.MapRect[ itemInCell: pushedCellPtr.ir, cellSize: pushedAptr.ob.size, cellInstOrient: pushedAptr.orientation, cellInstPos: pushedAptr.location ]; currentCellPtr.ir _ CDOrient.DeMapRect[ itemInWorld: gIntRect, cellSize: currentAptr.ob.size, cellInstOrient: currentAptr.orientation, cellInstPos: currentAptr.location ]; }; CDOps.IncludeApplication[design, currentAptr, FALSE]; CDDirectory.PropagateChange[currentAptr.ob, design]; END; menu: REF _ fullPopMenu; IF design^.actual.rest=NIL THEN {TerminalIO.WriteRope["not in cell\n"]; RETURN [FALSE]}; pushedAptr _ design^.actual.first.mightReplace; pushedCellOb _ pushedAptr.ob; pushedCellPtr _ NARROW[pushedCellOb.specificRef]; pushedRect _ CDOrient.RectAt[pushedAptr.location, pushedCellOb.size, pushedAptr.orientation]; TerminalIO.WriteRope["Pop from cell "]; TerminalIO.WriteRope[pushedCellPtr.name]; TerminalIO.WriteLn[]; CDApplications.DeSelectList[CDOps.AppList[design]]; currentRect _ CDApplications.BoundingRectO[CDOps.AppList[design]]; -- design coordinates currentCellOb _ CreateCellObject[CDOps.AppList[design], pushedAptr.orientation]; currentCellPtr _ NARROW[currentCellOb.specificRef]; currentCellPtr.useDIr _ pushedCellPtr.useDIr; IF currentCellPtr.useDIr THEN currentCellPtr.ir _ currentCellPtr.dIr ELSE currentCellPtr.ir _ pushedCellPtr.ir; currentAptr _ NEW[CD.Application_[ ob: currentCellOb, location: CDBasics.BaseOfRect[currentRect], orientation: pushedAptr.orientation, selected: TRUE, properties: CDProperties.CopyProps[pushedAptr.properties] ]]; currentCellOb.properties _ CDProperties.CopyProps[pushedAptr.ob.properties]; IF m=flush OR (m=interactive AND ~design^.actual.first.changed) THEN { DoFlush[]; RETURN [TRUE] }; IF CDBasics.NonEmpty[currentRect] THEN { mark: CDMarks.MarkRange; recursive: BOOL; IF m=newcell THEN { DoNewCell[interactive: FALSE]; RETURN [TRUE] }; mark _ CDMarks.GetNewMark[design ! CDMarks.PreviousMarkWasNotReleased => GOTO requestProblem]; CDMarks.MarkUnMarkedInclusiveChildren[design, currentCellOb, mark]; recursive _ (pushedAptr.ob.marked=mark); CDMarks.ReleaseMark[design, mark ! CD.Error => { TerminalIO.WriteRope["**internal problem releasing mark; better save design and destroy the viewer(s)\n"]; CONTINUE } ]; IF recursive THEN { -- recursive TerminalIO.WriteRope[" Original cell used inside, replace not possible\n"]; IF m=replace THEN RETURN[FALSE]; menu _ partialPopMenu; } ELSE { --ok, normal case IF m=replace THEN { DoReplace[]; RETURN [TRUE] }; } } ELSE { -- empty TerminalIO.WriteRope[" create empty cell not possible\n"]; IF m#interactive THEN {DoFlush[]; RETURN [TRUE]}; menu _ emptyPopMenu; }; SELECT CDMenus.CallMenu[menu] FROM $flush => DoFlush[]; $replace => DoReplace[]; $new => DoNewCell[interactive: TRUE]; ENDCASE => { TerminalIO.WriteRope["skipped\n"]; RETURN [FALSE] }; RETURN [TRUE]; EXITS requestProblem => TerminalIO.WriteRope["**internal problem requesting mark; not done\n"]; END; Expand: CDCallSpecific.CallProc = BEGIN cptr: CD.CellPtr = NARROW[aptr.ob.specificRef]; removeMe _ TRUE; repaintMe _ TRUE; include _ CDApplications.ComposedCopy[cptr.contents, aptr.location, aptr.ob.size, aptr.orientation]; repaintInclude _ TRUE; END; ComputeBounds: PROC [ob: CD.ObPtr] RETURNS [CD.DesignRect] = BEGIN WITH ob.specificRef SELECT FROM cptr: CD.CellPtr => RETURN [CDApplications.BoundingRectO[cptr.contents]]; ENDCASE => ERROR; END; ComputeBoundsI: PROC [ob: CD.ObPtr] = BEGIN WITH ob.specificRef SELECT FROM cptr: CD.CellPtr => cptr.dIr _ CDApplications.BoundingRectI[cptr.contents]; ENDCASE => ERROR; END; -- -- -- -- -- -- -- -- -- -- -- -- ReadCell: CD.InternalReadProc --PROC [] RETURNS [ObPtr]-- = BEGIN ob: CD.ObPtr = CreateEmptyCell[]; specific: CD.CellPtr = NARROW[ob.specificRef]; ob.size.x _ TokenIO.ReadInt[]; ob.size.y _ TokenIO.ReadInt[]; IF CDIO.VersionKey[]>=8 THEN { --now specific.simplifyOn _ TokenIO.ReadInt[]; specific.useDIr _ (TokenIO.ReadInt[]=0); IF ~specific.useDIr THEN specific.ir _ ReadRect[]; specific.origin.x _ TokenIO.ReadInt[]; specific.origin.y _ TokenIO.ReadInt[]; } ELSE { -- old versions IF CDIO.VersionKey[]<1 THEN { specific.name _ TokenIO.ReadRope[]; } ELSE { specific.simplifyOn _ TokenIO.ReadInt[]; }; }; specific.contents _ CDIO.ReadApplicationList[]; specific.dIr _ CDApplications.BoundingRectI[specific.contents]; IF specific.useDIr THEN specific.ir _ specific.dIr; RETURN [ob]; END; WriteRect: PROC[r: CD.Rect] = BEGIN TokenIO.WriteInt[r.x1]; TokenIO.WriteInt[r.y1]; TokenIO.WriteInt[r.x2]; TokenIO.WriteInt[r.y2]; END; ReadRect: PROC [] RETURNS [CD.Rect] = BEGIN r: CD.Rect; r.x1 _ TokenIO.ReadInt[]; r.y1 _ TokenIO.ReadInt[]; r.x2 _ TokenIO.ReadInt[]; r.y2 _ TokenIO.ReadInt[]; RETURN [r] END; RememberDesignOnWriting: CDEvents.EventProc = BEGIN lastOutputDesign _ design END; WriteCell: CD.InternalWriteProc -- PROC [me: ObPtr] -- = BEGIN HandleEmptyCells: PROC [me: CD.ObPtr] RETURNS [shouldReturn: BOOL_FALSE] = BEGIN design: CD.Design _ lastOutputDesign; IF design#NIL THEN { FOR l: LIST OF CD.PushRec _ design.actual, l.rest WHILE l#NIL DO IF l.first.dummyCell#NIL AND l.first.dummyCell.ob=me THEN RETURN; ENDLOOP; TerminalIO.WriteRope[Rope.Cat["** cell ", specific.name, " was empty\n"]]; CDIO.WriteApplicationList[LIST[ CDApplications.NewApplicationI[ ob: CDRects.CreateRect[[CD.lambda, CD.lambda], CD.highLightError] ]]]; shouldReturn _ TRUE; } END; specific: CD.CellPtr = NARROW[me.specificRef]; TokenIO.WriteInt[me.size.x]; TokenIO.WriteInt[me.size.y]; TokenIO.WriteInt[specific.simplifyOn]; IF specific.useDIr AND specific.ir=specific.dIr THEN TokenIO.WriteInt[0] ELSE { TokenIO.WriteInt[1]; WriteRect[specific.ir]; }; TokenIO.WriteInt[specific.origin.x]; TokenIO.WriteInt[specific.origin.y]; IF specific.contents=NIL AND HandleEmptyCells[me].shouldReturn THEN RETURN; CDIO.WriteApplicationList[specific.contents]; END; Describe: PROC[me: CD.ObPtr] RETURNS [Rope.ROPE] = BEGIN specific: CD.CellPtr = NARROW[me.specificRef]; RETURN [Rope.Concat["cell ", specific.name]] END; ReplaceDirectChildForCells: CDDirectory.ReplaceDChildsProc = BEGIN specific: CD.CellPtr = NARROW[me.specificRef]; needReposition: BOOL = ReplaceDirectChildForDummyCells[me, replace]; newIr: CD.DesignRect = CDApplications.BoundingRectI[NARROW[me.specificRef, CD.CellPtr].contents]; IF needReposition OR specific.dIr#newIr THEN { changed _ RepositionCell[me, design]; } END; ReplaceDirectChildForDummyCells: PUBLIC PROC [cellOb: CD.ObPtr, replace: CDDirectory.ReplaceList] RETURNS [needReposition: BOOL] = BEGIN PointRect: PROC [p: CD.Position] RETURNS [CD.Rect] = INLINE { RETURN [[x1: p.x, y1: p.y, x2: p.x, y2: p.y]] }; cp: CD.CellPtr = NARROW[cellOb.specificRef]; needReposition _ FALSE; FOR replaceList: CDDirectory.ReplaceList _ replace, replaceList.rest WHILE replaceList#NIL DO rep: REF CDDirectory.ReplaceRec = replaceList.first; IF rep.old=cellOb THEN LOOP; FOR appList: CD.ApplicationList _ cp.contents, appList.rest WHILE appList#NIL DO IF appList.first.ob=rep.old THEN { IF rep.newSize#rep.oldSize OR rep.off#[0, 0] THEN { realPos: CD.DesignPosition = CDOrient.MapPoint[ pointInCell: rep.off, cellSize: rep.oldSize, cellInstOrient: appList.first.orientation, cellInstPos: appList.first.location ]; fakePos: CD.DesignPosition = CDOrient.MapPoint[ pointInCell: [0, 0], cellSize: rep.newSize, cellInstOrient: appList.first.orientation, cellInstPos: [0, 0] ]; appList.first.location _ CDBasics.SubPoints[realPos, fakePos]; needReposition _ TRUE; }; appList.first.ob _ rep.new }; ENDLOOP; ENDLOOP; END; RepositionCell: PUBLIC PROC [cellOb: CD.ObPtr, design: CD.Design] RETURNS [didReposition: BOOLEAN] = BEGIN cp: CD.CellPtr = NARROW[cellOb.specificRef]; oldSize: CD.DesignPosition _ cellOb.size; oldR: CD.DesignRect _ CDBasics.RectAt[[0,0], oldSize]; oldDIr: CD.DesignRect _ cp.dIr; newR: CD.DesignRect = ComputeBounds[cellOb]; newSize: CD.DesignPosition _ CDBasics.SizeOfRect[newR]; newBase: CD.DesignPosition = CDBasics.BaseOfRect[newR]; newDIr: CD.DesignRect _ CDApplications.BoundingRectI[cp.contents]; didReposition _ oldR#newR OR oldSize#newSize OR (cp.useDIr AND oldDIr#newDIr); IF didReposition THEN { IF cp.contents=NIL THEN { TerminalIO.WriteRope[Rope.Cat["** tried to reposition an empty cell ", CDOps.Info[cellOb], "\n"]]; RETURN }; IF newBase#[0, 0] THEN { CDApplications.TranslateList[cp.contents, CDBasics.NegOffset[newBase]]; newDIr _ CDBasics.MoveRect[newDIr, CDBasics.NegOffset[newBase]]; cp.origin _ CDBasics.SubPoints[cp.origin, newBase]; }; cellOb.size _ newSize; cp.dIr _ newDIr; IF cp.useDIr THEN cp.ir _ newDIr ELSE cp.ir _ CDBasics.MoveRect[cp.ir, CDBasics.NegOffset[newBase]]; CDDirectory.RepositionObject[ design: design, ob: cellOb, oldSize: oldSize, baseOff: newBase ] } END; SetInterestRect: PUBLIC PROC [cellOb: CD.ObPtr, r: CD.DesignRect _ [0, 0, -1, -1]] = BEGIN cp: CD.CellPtr = NARROW[cellOb.specificRef]; cp.useDIr _ ~CDBasics.NonEmpty[r]; IF cp.useDIr THEN cp.ir _ cp.dIr ELSE cp.ir _ r END; Init[]; END. JCDCellsImpl.mesa (part of ChipNDale) Copyright c 1983, 1985 by Xerox Corporation. All rights reserved. by Christian Jacobi, June 24, 1983 5:00 pm last edited Christian Jacobi, April 15, 1985 5:22:32 pm PST --old stuff for io format version 4 -- removes the selected applications from design and returns them -- does not includes the cell into any design or celldirectory -- does not name the cell -- not yet included in design -- if name is NIL: interactive read for name -- cell is included in directory --undo the command --verbose if aptr is not a cell --HACK for CDDirectory XXX --pushedAptr.ob.properties _ currentCellOb.properties; is a second copy anyway BEGIN -- allows local declarations interestRect: CD.DesignRect; useInnerrect: BOOL; [interestRect, useInnerrect] _ CDInterestRects.GetInterestRect[pushedAptr.ob]; IF ~useInnerrect THEN { gIntRect: CD.DesignRect = CDOrient.MapRect[ itemInCell: interestRect, cellSize: pushedAptr.ob.size, cellInstOrient: pushedAptr.orientation, cellInstPos: pushedAptr.location ]; interestRect _ CDOrient.DeMapRect[ itemInWorld: gIntRect, cellSize: currentAptr.ob.size, cellInstOrient: currentAptr.orientation, cellInstPos: currentAptr.location ]; CDInterestRects.SetInterestRect[currentCellOb, interestRect] }; END; -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --returns bounds in coordinate system of ob itself -- PROC [event: REF, design: CD.Design, x: REF] --most empty cells are bugs; --however, the pushed in cells might be empty legally --pushed in cells might be empty legally --all other cells should not be empty -- PROC[me: CD.ObPtr, design: CD.Design, replace: LIST OF REF ReplaceRec] -- --actually this is an error; but it could be produced by some silly client program, --so we do not abort --defaulting r means to use a reasonable default for the interest rect Κ$˜šœ&™&Jšœ Οmœ7™BJšœ-™-Jšœ=™=—J˜šΟk ˜ Jšžœ˜J˜J˜J˜J˜ J˜J˜ Jšœ ˜ Jšœ˜Jšœ˜J˜Jšœ˜J˜ Jšœ ˜ Jšœ˜Jšœžœ ˜Jšœ˜J˜Jšœ ˜ J˜—šΟb œžœžœ˜Jšžœžœ žœ˜ΐJšžœ˜Jšžœ˜—Jšž˜J˜JšΟn#˜#J˜Jšœ žœžœ˜=J˜˜,J˜3—˜(J˜4—J˜OJ˜MJ˜J˜Jšœ žœ'˜7Jšœžœ'˜:Jšœžœ3˜DJšœžœ žœ˜"J˜š œžœ˜Jšž˜JšœžœK˜RJšœ1˜1Jšœ˜Jšœ˜Jšœ˜Jšœ4˜4Jšœ"˜"Jšœ,˜,J˜-Jšœ"˜"Jšœ$˜$Jšœ˜Jšœ+˜+Jšœ)˜)Jšœ#˜#JšœA˜AJšœ4˜4Jšœ2˜2Jšœ5˜5Jšœ3˜3Jšœ3˜3Jšœ6˜6Jšœ6˜6Jšœ0˜0šœ-˜-šœ#˜#Jšœ!˜!Jšœžœ˜Jšœ#˜#Jšœ ž˜Jšœ˜—Jšœ˜—JšœM˜MJšžœ˜—J˜š  œžœžœžœžœ˜™>Jšœ™Jšž˜Jšœžœ žœžœ˜(Jšœžœ žœžœ ˜$J˜Jšœ˜Jšœ˜Jšœ˜Jšžœ˜ Jšžœ˜—J˜š  œžœžœžœ žœžœ ˜oJšœ™Jšž˜Jšœžœ˜!Jšœžœ žœ˜(Jšœžœ0Οc!˜ZJšœD˜DJšœ^˜^Jšœ;˜;Jšžœ˜ Jšžœ˜—J˜š œžœ žœ žœžœžœžœžœžœžœ˜Jšž˜Jšœ žœ˜Jšœžœ žœ˜*šžœžœ˜Jšœ%˜%Jšžœžœ˜J˜—šžœ’ ˜šžœ˜Jšœžœžœ˜Jšœ žœžœ˜šœ5˜5Jšœ#žœ žœžœ˜AJšœ˜—šžœ žœ˜Jšœ0˜0Jšžœ žœžœžœ˜'J˜—šžœžœ˜Jšœ žœ˜Jšœ˜Jšœ˜—šžœ&žœ˜.Jšœ žœ˜Jšœ-˜-Jšœ˜—šžœ/žœ˜8J˜!J˜$Jšžœžœ˜J˜—Jšœ˜J˜KJšžœ˜——Jšžœ˜—J˜š  œžœžœ žœžœžœ˜IJš žœžœžœ žœžœ˜2Jšœ,™,Jšœ ™ Jšž˜Jšœžœ3˜:Jšœžœžœžœ˜-Jšœžœ0˜5Jšœžœ ˜Jšœ-˜-Jšœžœ˜"J˜J˜&Jšœžœ˜šžœžœžœ˜"Jšœ)˜)Jšžœžœ žœ˜!Jšœ˜—šžœžœžœ˜šžœ=žœžœžœ˜cJšœ™Jšœ*žœ˜1Jšžœžœ žœ˜!J˜—J˜—Jšžœ*˜.Jšœ&žœ’˜GJšžœžœ˜#Jšžœ˜—J˜š  œžœžœžœžœžœ˜FJšœ™Jšž˜Jšžœžœžœ&˜6Jš žœžœ žœžœžœžœ'˜Zš žœžœžœžœ žœ˜:Jšœ1˜1Jšœ*˜*Jšœ˜J˜—Jšžœž˜Jšžœ˜J˜—š œžœžœ žœ žœžœžœ˜RJšž˜Jšœžœ˜Jšœ žœ˜Jšœ6˜6Jšžœ žœ5˜EJšžœ$˜(Jšžœ˜—J˜š  œžœ žœžœ˜GJšžœžœžœ˜Jšž˜šžœžœ˜Jšœžœ žœ˜6Jšœžœ˜$Jšœ žœ žœ˜0Jšœ žœ˜Jšœ#˜#š žœžœžœžœ!žœžœž˜@šžœžœžœ(žœ˜MJšœA˜AJšœ:˜:Jšœ˜Jšžœžœ˜Jšœ˜—Jšžœ˜—J˜˜/J˜J˜J˜J˜#J˜—šœžœžœ˜"Jšœ ˜ Jšœ žœ˜Jšœ:˜:Jšœ˜—JšœE˜EJšœ.˜.šœžœ˜JšžœP˜RJ˜J˜—J˜.Jšžœžœ˜J˜—Jšžœ˜—J˜š  œžœžœ žœ ˜-Jšœ*žœžœ˜4šžœžœ˜Jšž˜J˜%Jšžœžœ.˜:Jšžœ˜——J˜š  œžœ žœ'žœ˜Kšžœž œ˜Jšž˜Jšœžœ ’ ˜3Jšœžœ˜+Jšœžœ˜&Jšœžœ ˜*J˜š œžœ˜Jšž˜Jšœžœ*˜1J˜ J˜%Jšœ)žœ˜.Jšžœžœ*ž˜8Jšœ-žœ˜4Jšžœ˜J˜—š  œžœ˜Jšžœ˜J˜AJ˜"šœ™JšœM˜M—J˜%Jšœ)žœ˜.JšœN™NJ˜1š žœžœ$žœ&žœ’˜ŒJšœ žœ%˜0Jšœžœ’˜8Jšœžœ’˜Ašœ˜JšœP˜P—šœ"˜"Jšœ˜Jšœ˜Jšœ'˜'Jšœ!˜!Jšœ˜—šœ+˜+Jšœ˜Jšœ˜Jšœ'˜'Jšœ ˜ Jšœ˜—JšœU˜Ušžœžœ˜Jšœ`˜`—šœ-˜-Jšœ˜Jšœ˜Jšœ˜Jšœ˜—Jšœ˜—Jšœ+˜+Jšœ-žœ˜4Jšœ@˜@Jšžœ˜—J˜š  œžœžœžœ˜+Jšž˜Jšœ#˜#J˜ J˜%Jšœ)žœ˜.Jšœžœ˜$Jšžœ9žœžœžœ˜Ršžœžœ˜šœ žœ˜+Jšœ˜Jšœ˜Jšœ'˜'Jšœ ˜ J˜—šœ'˜'Jšœ˜Jšœ˜Jšœ(˜(Jšœ!˜!J˜—Jšœ˜—Jšœ.žœ˜5Jšœ4˜4Jšžœ˜—J˜Jšœžœ˜Jš žœžœžœ)žœžœ˜XJ˜/Jšœ˜Jšœžœ˜1Jšœ^˜^J˜'J˜*J˜Jšœ3˜3JšœC’˜XJšœP˜PJšœžœ˜3Jšœ-˜-Jšžœžœ'˜DJšžœ&˜*šœžœžœ˜"J˜Jšœ+˜+J˜$Jšœ žœ˜Jšœ:˜:J˜—šœL˜LJ™šžœ’™"Jšœžœ ™Jšœžœ™JšœN™Nšžœžœ™šœ žœ™+Jšœ™Jšœ™Jšœ'™'Jšœ ™ J™—šœ"™"Jšœ™Jšœ™Jšœ(™(Jšœ!™!J™—Jšœ<™˜>Jšœžœ˜J˜—Jšœ˜Jšœ˜—Jšžœ˜—Jšžœ˜—Jšžœ˜—J˜š œžœžœ žœžœ žœžœ˜dJšž˜Jšœžœ žœ˜,J˜Jšœ žœ˜)Jšœžœ.˜6Jšœžœ˜J˜Jšœžœ$˜,Jšœ žœ,˜7Jšœ žœ,˜7Jšœžœ8˜BJ˜Jšœžœžœ žœ˜Nšžœžœ˜šžœ žœžœ˜JšœT™TJšœ™šœG˜GJšœ˜—Jšž˜J˜—šžœžœ˜JšœG˜GJšœ@˜@Jšœ3˜3Jšœ˜—Jšœ˜Jšœ˜Jšžœ žœ˜!Jšžœ?˜Cšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜—Jšœ˜—Jšžœ˜—J˜š  œžœžœ žœ žœ˜TJšœF™FJšž˜Jšœžœ žœ˜,Jšœ"˜"Jšžœ žœžœ ˜/Jšžœ˜—J˜J˜Jšžœ˜J˜—…—\pή