CDCellsImpl.mesa (part of ChipNDale)
Copyright © 1983, 1985 by Xerox Corporation. All rights reserved.
by Christian Jacobi, June 24, 1983 5:00 pm
last edited Christian Jacobi, September 5, 1985 8:54:23 am PDT
DIRECTORY
CedarProcess,
CD,
CDInstances,
CDCallSpecific,
CDCells,
CDDirectory,
CDMenus,
CDEvents,
CDBasics,
CDInterestRects,
CDIO,
CDMarks,
CDOps,
CDOrient,
CDProperties,
CDRects,
CDVPrivate,
Process USING [Yield],
Rope,
TokenIO,
TerminalIO;
CDCellsImpl:
CEDAR
PROGRAM
IMPORTS CedarProcess, CD, CDInstances, CDCallSpecific, CDIO, CDDirectory, CDEvents, CDBasics, CDMarks, CDMenus, CDOps, CDOrient, CDProperties, CDRects, Process, Rope, TokenIO, TerminalIO, CDInterestRects
EXPORTS CDCells
SHARES CDDirectory =
BEGIN
-- -- -- -- -- -- -- -- -- -- -- --
pForCells: REF CD.ObjectClass = CD.RegisterObjectClass[$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] =
--old stuff for io format version 4
BEGIN
x1: INT = TokenIO.ReadInt[];
y1: INT = TokenIO.ReadInt[];
x2: INT = TokenIO.ReadInt[];
y2: INT = TokenIO.ReadInt[];
val ← NEW[CD.Rect ← [x1, y1, x2, y2]]
END;
InterestRectCells:
PROC [ob:
CD.Object]
RETURNS [
CD.Rect] =
BEGIN
RETURN [NARROW[ob.specificRef, CD.CellPtr].ir]
END;
OriginForCells:
PROC [ob:
CD.Object]
RETURNS [
CD.Position] =
BEGIN
RETURN [NARROW[ob.specificRef, CD.CellPtr].origin]
END;
OldInsideRect:
PROC [ob:
CD.Object]
RETURNS [
CD.Rect] =
BEGIN
RETURN [NARROW[ob.specificRef, CD.CellPtr].dIr]
END;
OldSetInterest:
PROC [ob:
CD.Object, r:
CD.Rect] =
BEGIN
cptr: CD.CellPtr = NARROW[ob.specificRef];
cptr.ir ← r;
cptr.useDIr ← FALSE;
END;
SetInsideRect:
PROC [ob:
CD.Object, r:
CD.Rectsics.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.Object, r: Rope.
ROPE] =
BEGIN
cptr: CD.CellPtr = NARROW[me.specificRef];
cptr.name ← r
END;
Name:
PROC [me:
CD.Object]
RETURNS [Rope.
ROPE] =
BEGIN
cptr: CD.CellPtr = NARROW[me.specificRef];
RETURN [cptr.name]
END;
EnumerateChildObjects:
PROC [me:
CD.Object, p: CDDirectory.EnumerateObjectsProc, x:
REF] =
BEGIN
cptr: CD.CellPtr = NARROW[me.specificRef];
FOR w:
CD.InstanceList ← cptr.contents, w.rest
WHILE w#
NIL
DO
p[w.first.ob, x]
ENDLOOP
END;
Another:
PROC [me:
CD.Object, from, to:
CD.Design]
RETURNS [
CD.Object] =
BEGIN
oldCp: CD.CellPtr = NARROW[me.specificRef];
newOb: CD.Object = CreateEmptyCell[];
newCp: CD.CellPtr = NARROW[newOb.specificRef];
newOb.size ← me.size;
newCp^ ← oldCp^;
newCp.contents ← CDInstances.CopyList[oldCp.contents];
newOb.properties ← CDProperties.CopyProps[newOb.properties];
IF to#NIL THEN [] ← CDDirectory.Include[to, newOb];
RETURN [newOb]
END;
DrawMeForCells:
PROC [inst:
CD.Instance, pos:
CD.Position, orient:
CD.Orientation,
pr: CD.DrawRef] =
BEGIN
cptr: CD.CellPtr = NARROW[inst.ob.specificRef];
r: CD.Rect;
FOR w:
CD.InstanceList ← 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: inst.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;
Process.Yield[];
END;
QuickDrawMeForCells:
PROC [inst:
CD.Instance, pos:
CD.Position, orient:
CD.Orientation,
pr: CD.DrawRef] =
BEGIN
cptr: CD.CellPtr = NARROW[inst.ob.specificRef];
r: REAL;
IF (r ← pr.scaleHint*inst.ob.size.y)<cptr.simplifyOn
AND pr.scaleHint>0
THEN {
pr.drawOutLine[CDOrient.RectAt[pos, inst.ob.size, orient], pr];
IF r>9 THEN pr.drawComment[CDOrient.RectAt[pos, inst.ob.size, orient], cptr.name, pr];
}
ELSE {
r: CD.Rect;
FOR w:
CD.InstanceList ← 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: inst.ob.size,
cellInstOrient: orient,
cellInstPos: pos];
IF CDBasics.Intersect[r, pr.interestClip]
THEN {
IF pr.stopFlag^ THEN EXIT;
w.first.ob.class.quickDrawMe[
w.first,
CDBasics.BaseOfRect[r],
CDOrient.ComposeOrient[w.first.orientation, orient],
pr];
}
ENDLOOP;
IF pr.b1
THEN {
WITH pr.devicePrivate
SELECT
FROM
me: CDVPrivate.MyGraphicRef => {
IF me.slowDown
THEN {
CedarProcess.SetPriority[CedarProcess.Priority[background]];
me.slowDown ← FALSE;
};
IF me.hurryUp
THEN {
--this will be executed only after the other slowed down ...
CedarProcess.SetPriority[CedarProcess.Priority[normal]];
me.hurryUp ← FALSE;
};
me.check ← FALSE;
};
ENDCASE => NULL;
pr.b1 ← FALSE;
};
Process.Yield[];
}
END;
DrawCellSelection:
PROC [inst:
CD.Instance, pos:
CD.Position, orient:
CD.Orientation,
pr: CD.DrawRef] =
BEGIN
IF (pr.scaleHint*inst.ob.size.y)<
NARROW[inst.ob.specificRef,
CD.CellPtr].simplifyOn
AND pr.scaleHint>0 THEN pr.drawRect[CDOrient.RectAt[pos, inst.ob.size, orient], CD.highLightShade, pr]
ELSE {
pr.drawOutLine[
CDOrient.MapRect[
itemInCell: CD.InterestRect[inst.ob],
cellSize: inst.ob.size,
cellInstOrient: orient,
cellInstPos: pos
],
pr
]
}
END;
RemoveSelectedFromWorld:
PROC [design:
CD.Design]
RETURNS [
CD.InstanceList] =
-- removes the selected instances from design and returns them
BEGIN
remove, keep: CD.InstanceList ← NIL;
[others: keep, selected: remove] ← CDInstances.SplitSelected[CDOps.InstList[design]];
CDOps.SetInstList[design, keep];
RETURN [remove]
END;
CreateEmptyCell:
PUBLIC
PROC []
RETURNS [
CD.Object] =
-- does not includes the cell into any design or celldirectory
-- does not name the cell
BEGIN
ob: CD.Object = NEW[CD.ObjectRep];
cp: CD.CellPtr = NEW[CD.CellRep];
ob.class ← pForCells;
ob.size ← [0, 0];
ob.specificRef ← cp;
cp.simplifyOn ← 50;
RETURN [ob]
END;
CreateCellObject:
PROC [use:
CD.InstanceList, orient:
CD.OrientationOrient.original]
RETURNS [
CD.Object] =
-- not yet included in design
BEGIN
ob: CD.Object = CreateEmptyCell[];
cp: CD.CellPtr = NARROW[ob.specificRef];
gOutR: CD.Rect = CDInstances.BoundingRectO[use]; -- coordsys of use, non oriented
ob.size ← CDOrient.OrientedSize[CDBasics.SizeOfRect[gOutR], orient];
cp.contents ← CDInstances.DeComposedCopy[use, CDBasics.BaseOfRect[gOutR], ob.size, orient];
cp.ir ← cp.dIr ← CDInstances.BoundingRectI[cp.contents];
RETURN [ob]
END;
IncludeAndNameCell:
PROC [design:
CD.Design, cp:
CD.Object, 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.Object←NIL] =
-- if name is NIL: interactive read for name
-- cell is included in directory
BEGIN
sel: CD.InstanceList = RemoveSelectedFromWorld[design];
inst: CD.Instance = NEW[CD.InstanceRep];
b: CD.Rect = CDInstances.BoundingRectO[sel];
cptr: CD.CellPtr;
inst.ob ← cellOb ← CreateCellObject[use: sel];
cptr ← NARROW[cellOb.specificRef];
cptr.name ← name;
inst.location ← CDBasics.BaseOfRect[b];
inst.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 {
--undo the command
CDOps.IncludeInstanceList[design, sel, FALSE];
RETURN [done: FALSE, cellOb: NIL]
};
}
ELSE [] ← CDDirectory.Include[design, cellOb];
CDOps.IncludeInstance[design, inst, TRUE]; -- redraw removes seletion
RETURN [done: TRUE, cellOb: cellOb]
END;
IsCellInstance:
PROC [inst:
CD.Instance]
RETURNS [yes:
BOOL ←
FALSE] =
--verbose if inst is not a cell
BEGIN
IF inst=NIL THEN TerminalIO.WriteRope[" no object\n"]
ELSE IF inst.ob=NIL OR inst.ob.specificRef=NIL THEN TerminalIO.WriteRope[" bad object\n"]
ELSE
IF NOT
ISTYPE[inst.ob.specificRef,
CD.CellPtr]
THEN
TerminalIO.WriteRope[Rope.Cat[" object is not cell but ", CDOps.Info[inst.ob], "\n"]]
ELSE yes ← TRUE
END;
CheckRecursionForPush:
PROC [design:
CD.Design, ob:
CD.Object]
RETURNS [yes:
BOOL ←
FALSE] =
--Returns "pushing into ob would cause recursion"
BEGIN
FOR l:
LIST
OF
CD.PushRec ← design.actual, l.rest
WHILE l#
NIL
DO
IF l.first.mightReplace#NIL AND l.first.mightReplace.ob=ob THEN RETURN [yes ← TRUE]
ENDLOOP;
END;
PushInCellInstance:
PUBLIC PROC [design:
CD.Design, inst:
CD.Instance]
RETURNS [done:
BOOL ←
FALSE] =
BEGIN
IF IsCellInstance[inst]
THEN {
cptr: CD.CellPtr = NARROW[inst.ob.specificRef];
dummy: CD.Object = CreateEmptyCell[];
newCptr: CD.CellPtr = NARROW[dummy.specificRef];
dummyCellAp: CD.Instance;
dummy.size ← CDBasics.highposition;
IF CheckRecursionForPush[design, inst.ob]
THEN {
TerminalIO.WriteRope[Rope.Cat[" recursive push into ", CDOps.Info[inst.ob], " not possible\n"]];
RETURN [done ← FALSE];
};
newCptr^ ← cptr^; --copies interest rect ....
newCptr.contents ← CDInstances.ComposedCopy[
il: newCptr.contents,
cellPos: inst.location,
cellSize: inst.ob.size,
cellOrient: inst.orientation
];
dummyCellAp ←
NEW[
CD.InstanceRep←[
ob: dummy,
selected: TRUE,
properties: CDProperties.CopyProps[inst.properties]
]];
dummy.properties ← CDProperties.CopyProps[inst.ob.properties];
CDOps.RemoveInstance[design, inst];
design^.actual ←
CONS[
CD.PushRec[dummyCell: dummyCellAp, specific: newCptr, mightReplace: inst],
design^.actual
];
[] ← CDEvents.ProcessEvent[pushEvent, design];
RETURN [done ← 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:
BOOLLSE] =
BEGIN
currentRect, pushedRect: CD.Rect; --cd coords
currentInst, pushedInst: CD.Instance;
currentCellOb, pushedCellOb: CD.Object;
currentCellPtr, pushedCellPtr: CD.CellPtr;
recursive: BOOL ← FALSE;
CheckRecursionForPop:
PROC [mark: CDMarks.MarkRange] =
BEGIN
CDMarks.MarkUnMarkedInclusiveChildren[design, currentCellOb, mark];
recursive ← (pushedInst.ob.marked=mark);
END;
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.IncludeInstance[design, pushedInst, FALSE];
END;
DoReplace:
PROC [] =
BEGIN
needsRep: BOOL ← FALSE;
[] ← CDEvents.ProcessEvent[beforeReplace, design, pushedInst.ob];
TerminalIO.WriteRope["replace\n"];
--HACK for CDDirectory XXX
CDProperties.PutPropOnObject[onto: currentCellOb, prop: $Owner, val: design];
design^.actual ← design^.actual.rest;
design^.actual.first.indirectlyChanged ← TRUE;
--pushedInst.ob.properties ← currentCellOb.properties; is a second copy anyway
needsRep ← pushedRect#currentRect OR pushedCellPtr.ir#currentCellPtr.ir OR currentCellPtr.dIr#pushedCellPtr.dIr OR pushedCellPtr.useDIr#currentCellPtr.useDIr;
pushedCellPtr.contents ← currentCellPtr.contents;
pushedCellPtr.useDIr ← currentCellPtr.useDIr;
pushedCellPtr.ir ← currentCellPtr.ir;
IF needsRep
THEN {
oldSize: CD.Position ← pushedInst.ob.size;
newFakeOrigin: CD.Position; --absolute coordinates
newInOldCoordinates: CD.Position; --coordinates of old cell
pushedInst.ob.size ←
CDOrient.OrientedSize[CDBasics.SizeOfRect[currentRect], pushedInst.orientation];
newFakeOrigin ← CDOrient.MapPoint[
pointInCell: [0, 0],
cellSize: pushedInst.ob.size,
cellInstOrient: pushedInst.orientation,
cellInstPos: currentInst.location
].pointInWorld;
newInOldCoordinates ← CDOrient.DeMapPoint[
pointInWorld: newFakeOrigin,
cellSize: oldSize,
cellInstOrient: pushedInst.orientation,
cellInstPos: pushedInst.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: pushedInst.ob,
oldSize: oldSize,
baseOff: newInOldCoordinates
];
};
pushedInst.location ← currentInst.location;
CDOps.IncludeInstance[design, pushedInst, FALSE];
[] ← CDEvents.ProcessEvent[afterReplace, design, pushedInst.ob];
END;
DoNewCell:
PROC [interactive:
BOOL←
FALSE] =
BEGIN
TerminalIO.WriteRope["new cell\n"];
currentInst.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 ~currentCellPtr.useDIr
THEN {
gIntRect:
CD.Rect = CDOrient.MapRect[
itemInCell: currentCellPtr.ir,
cellSize: pushedInst.ob.size,
cellInstOrient: pushedInst.orientation,
cellInstPos: pushedInst.location
];
currentCellPtr.ir ← CDOrient.DeMapRect[
itemInWorld: gIntRect,
cellSize: currentInst.ob.size,
cellInstOrient: currentInst.orientation,
cellInstPos: currentInst.location
];
};
CDOps.IncludeInstance[design, currentInst, FALSE];
CDDirectory.PropagateChange[currentInst.ob, design];
END;
menu: REF ← fullPopMenu;
IF design^.actual.rest=
NIL
THEN {
TerminalIO.WriteRope["not in cell\n"];
RETURN [FALSE]
};
pushedInst ← design^.actual.first.mightReplace;
pushedCellOb ← pushedInst.ob;
pushedCellPtr ← NARROW[pushedCellOb.specificRef];
pushedRect ← CDOrient.RectAt[pushedInst.location, pushedCellOb.size, pushedInst.orientation];
TerminalIO.WriteRope[Rope.Cat["Pop from cell ", pushedCellPtr.name, "\n"]];
CDInstances.DeSelectList[CDOps.InstList[design]];
currentRect ← CDInstances.BoundingRectO[CDOps.InstList[design]]; -- design coordinates
currentCellOb ← CreateCellObject[CDOps.InstList[design], pushedInst.orientation];
currentCellPtr ←
NARROW[currentCellOb.specificRef];
old currentCellPtr.useDIr ← pushedCellPtr.useDIr;
currentCellPtr.useDIr ← design^.actual.first.specific.useDIr;
currentCellPtr.ir ← IF currentCellPtr.useDIr THEN design^.actual.first.specific.dIr ELSE design^.actual.first.specific.ir;
currentInst ←
NEW[
CD.InstanceRep ← [
ob: currentCellOb,
location: CDBasics.BaseOfRect[currentRect],
orientation: pushedInst.orientation,
selected: TRUE,
properties: CDProperties.CopyProps[pushedInst.properties]
]];
currentCellOb.properties ← CDProperties.CopyProps[pushedInst.ob.properties];
BEGIN -- allows local declarations
interestRect: CD.Rect;
useInnerrect: BOOL;
[interestRect, useInnerrect] ← CDInterestRects.GetInterestRect[pushedInst.ob];
IF ~useInnerrect THEN {
gIntRect: CD.Rect = CDOrient.MapRect[
itemInCell: interestRect,
cellSize: pushedInst.ob.size,
cellInstOrient: pushedInst.orientation,
cellInstPos: pushedInst.location
];
interestRect ← CDOrient.DeMapRect[
itemInWorld: gIntRect,
cellSize: currentInst.ob.size,
cellInstOrient: currentInst.orientation,
cellInstPos: currentInst.location
];
CDInterestRects.SetInterestRect[currentCellOb, interestRect]
};
END;
IF m=flush
OR (m=interactive
AND ~design^.actual.first.changed)
THEN {
DoFlush[];
RETURN [TRUE]
};
IF CDBasics.NonEmpty[currentRect]
THEN {
IF m=newcell
THEN {
DoNewCell[interactive: FALSE];
RETURN [TRUE]
};
CDMarks.DoWithMark[design, CheckRecursionForPop];
IF recursive
THEN {
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];
END;
-- -- -- -- -- -- -- -- -- -- -- --
Expand: CDCallSpecific.CallProc =
BEGIN
cptr: CD.CellPtr = NARROW[inst.ob.specificRef];
removeMe ← TRUE;
repaintMe ← TRUE;
include ← CDInstances.ComposedCopy[cptr.contents, inst.location, inst.ob.size, inst.orientation];
repaintInclude ← TRUE;
END;
-- -- -- -- -- -- -- -- -- -- -- --
ComputeBounds:
PROC [ob:
CD.Object]
RETURNS [
CD.Rect] =
--returns bounds in coordinate system of ob itself
BEGIN
WITH ob.specificRef
SELECT
FROM
cptr: CD.CellPtr => RETURN [CDInstances.BoundingRectO[cptr.contents]];
ENDCASE => ERROR;
END;
ComputeBoundsI:
PROC [ob:
CD.Object] =
BEGIN
WITH ob.specificRef
SELECT
FROM
cptr: CD.CellPtr => cptr.dIr ← CDInstances.BoundingRectI[cptr.contents];
ENDCASE => ERROR;
END;
-- -- -- -- -- -- -- -- -- -- -- --
ReadCell:
CD.InternalReadProc
--PROC [] RETURNS [Object]-- =
BEGIN
ob: CD.Object = 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.ReadInstanceList[];
specific.dIr ← CDInstances.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 =
-- PROC [event: REF, design: CD.Design, x: REF]
BEGIN
lastOutputDesign ← design
END;
WriteCell:
CD.InternalWriteProc
-- PROC [me: Object] -- =
BEGIN
HandleEmptyCells:
PROC [me:
CD.Object]
RETURNS [shouldReturn:
BOOL←
FALSE] =
--most empty cells are bugs;
--however, the pushed in cells might be empty legally
BEGIN
design: CD.Design ← lastOutputDesign;
IF design#
NIL
THEN {
FOR l:
LIST
OF
CD.PushRec ← design.actual, l.rest
WHILE l#
NIL
DO
--pushed in cells might be empty legally
IF l.first.dummyCell#NIL AND l.first.dummyCell.ob=me THEN RETURN;
ENDLOOP;
--all other cells should not be empty
TerminalIO.WriteRope[Rope.Cat["** cell ", specific.name, " was empty\n"]];
CDIO.WriteInstanceList[
LIST[
CDInstances.NewInstance[
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.WriteInstanceList[specific.contents];
END;
Describe:
PROC[me:
CD.Object]
RETURNS [Rope.
ROPE] =
BEGIN
specific: CD.CellPtr = NARROW[me.specificRef];
RETURN [Rope.Concat["cell ", specific.name]]
END;
ReplaceDirectChildForCells: CDDirectory.ReplaceDChildsProc =
-- PROC[me: CD.Object, design: CD.Design, replace: LIST OF REF ReplaceRec] --
BEGIN
specific: CD.CellPtr = NARROW[me.specificRef];
needReposition: BOOL = ReplaceDirectChildForDummyCells[me, replace];
newIr: CD.Rect = CDInstances.BoundingRectI[NARROW[me.specificRef, CD.CellPtr].contents];
IF needReposition
OR specific.dIr#newIr
THEN {
changed ← RepositionCell[me, design];
}
END;
ReplaceDirectChildForDummyCells:
PUBLIC
PROC [cellOb:
CD.Object, replace: CDDirectory.ReplaceList]
RETURNS [needReposition:
BOOL] =
BEGIN
PointRect:
PROC [class:
CD.Position]
RETURNS [
CD.Rect] =
INLINE {
RETURN [[x1: class.x, y1: class.y, x2: class.x, y2: class.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.InstanceList ← 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.Position = CDOrient.MapPoint[
pointInCell: rep.off,
cellSize: rep.oldSize,
cellInstOrient: appList.first.orientation,
cellInstPos: appList.first.location
];
fakePos:
CD.Position = 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;
IsDummyCell:
PROC [cellOb:
CD.Object, design:
CD.Design]
RETURNS [isDummy:
BOOL←
FALSE] =
INLINE BEGIN
IF design#
NIL
THEN {
FOR list:
LIST
OF
CD.PushRec ← design.actual, list.rest
WHILE list#
NIL
DO
IF list.first.dummyCell.ob=cellOb THEN RETURN [isDummy←TRUE]
ENDLOOP;
};
END;
RepositionCell:
PUBLIC
PROC [cellOb:
CD.Object, design:
CD.Design]
RETURNS [didReposition:
BOOLEAN] =
BEGIN
IF IsDummyCell[cellOb, design] THEN RETURN [didReposition←FALSE]
ELSE {
cp: CD.CellPtr = NARROW[cellOb.specificRef];
oldSize: CD.Position ← cellOb.size;
oldR: CD.Rect ← CDBasics.RectAt[[0,0], oldSize];
oldDIr: CD.Rect ← cp.dIr;
newR: CD.Rect = ComputeBounds[cellOb];
newSize: CD.Position ← CDBasics.SizeOfRect[newR];
newBase: CD.Position = CDBasics.BaseOfRect[newR];
newDIr: CD.Rect ← CDInstances.BoundingRectI[cp.contents];
didReposition ← oldR#newR OR oldSize#newSize OR (cp.useDIr AND oldDIr#newDIr);
IF didReposition
THEN {
IF cp.contents=
NIL
THEN {
--actually this is an error; but it could be produced by some silly client program,
--so we do not abort
TerminalIO.WriteRope[Rope.Cat["** tried to reposition an empty cell ",
CDOps.Info[cellOb], "\n"]];
RETURN
};
IF newBase#[0, 0]
THEN {
CDInstances.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.Object, r:
CD.Rect ← [0, 0, -1, -1]] =
--defaulting r means to use a reasonable default for the interest rect
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.