SpinifexInvertImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Written by: Mark Shand, August 9, 1984 8:38:33 pm PDT
Last Edited by: Shand, August 24, 1984 0:44:28 am PDT
Last Edited by: Beretta, October 30, 1984 9:53:54 am PST
DIRECTORY
CD USING [ApplicationPtr, ObPtr, DrawProc, DrawRectProc, Design, DrawRef, NewNullDeviceDrawRef, original],
RefTab USING [Create, Insert, Fetch, Ref],
SpinifexCellPredicates USING [IsLogicalCell, CellPredicateProc],
SpinifexInvert
;
SpinifexInvertImpl: CEDAR PROGRAM
IMPORTS CD, RefTab, SpinifexCellPredicates
EXPORTS SpinifexInvert
~ BEGIN
Inversion: TYPE ~ SpinifexInvert.Inversion;
Invert: PUBLIC PROCEDURE [design: CD.Design, appls: LIST OF CD.ApplicationPtr, ClientData: SpinifexInvert.ClientDataProc ← NIL, IsCell: SpinifexCellPredicates.CellPredicateProc ← SpinifexCellPredicates.IsLogicalCell] RETURNS [leaves: LIST OF REF Inversion] ~ {
dr: CD.DrawRef ~ CD.NewNullDeviceDrawRef[design];
leafList: LIST OF REF Inversion ~ CONS[NIL, NIL];
lilith: REF Inversion ~ NEW[Inversion ← [childCount~ 0, parents~ NIL, cell~ NIL, data~ NIL]];
idRef: REF InvData ~ NEW[InvData ← [listTail~ leafList, parent~ lilith, design~ design, parentData~ NIL, ClientData~ ClientData, IsCell~ IsCell, CellTab~ RefTab.Create[997]]];
dr.drawChild ← InvCell;
dr.drawRect ← dr.saveRect ← Oops;
dr.devicePrivate ← idRef;
FOR al: LIST OF CD.ApplicationPtr ← appls, al.rest WHILE al # NIL DO
InvCell[al.first, [0,0], CD.original, dr];
ENDLOOP;
leaves ← NIL;
FOR invList: LIST OF REF Inversion ← leafList.rest, invList.rest WHILE invList # NIL DO
IF invList.first.childCount = 0 THEN {
leaves ← CONS[ invList.first, leaves]
}
ENDLOOP;
IF leaves = NIL THEN ERROR;
};
Oops: CD.DrawRectProc ~ { ERROR };
InvData: TYPE ~ RECORD [
listTail: LIST OF REF Inversion,
parent: REF Inversion,
design: CD.Design,
parentData: REF ANY,
ClientData: SpinifexInvert.ClientDataProc,
IsCell: SpinifexCellPredicates.CellPredicateProc,
CellTab: RefTab.Ref
];
InvCell: CD.DrawProc -- [aptr: ApplicationPtr, pos: DesignPosition, orient: Orientation, pr: REF DrawInformation] -- ~ {
data: REF InvData ~ NARROW[pr.devicePrivate];
Test if aptr.ob is a hierarchy inducing object in the terms of the requested inversion.
IF ~data.IsCell[aptr.ob] THEN {
IF aptr.ob.p.inDirectory THEN
aptr.ob.p.drawMe[ aptr, pos, orient, pr]
}
ELSE {
aptr.ob is a hierarchy node.
thisCell: REF Inversion;
tc: REF ANY;
Has aptr.ob been seen before?
WITH tc ← data.CellTab.Fetch[aptr.ob].val SELECT FROM
this: REF Inversion => thisCell ← this;
ENDCASE => IF tc # NIL THEN ERROR
ELSE {
This is the first appearence of aptr.ob.
thisCellParent: REF Inversion~ data.parent;
thisCell ← NEW[Inversion ← [childCount~ 0, parents~ NIL, cell~ aptr.ob, data~ IF data.ClientData = NIL THEN NIL ELSE data.ClientData[data.design, aptr, pos, orient, thisCellParent] ]];
Setup and save enclosing cell.
data.parent ← thisCell;
aptr.ob.p.drawMe[ aptr, [0,0], CD.original, pr];
data.parent ← thisCellParent;
IF ~data.CellTab.Insert[aptr.ob, thisCell] THEN ERROR;
data.listTail.rest ← CONS[thisCell, NIL];
data.listTail ← data.listTail.rest;
};
Add data.parent to thisCell's parents list if it is not already present.
IF data.parent # NIL THEN {
IF thisCell.parents = NIL THEN {
thisCell.parents ← CONS[data.parent, NIL];
data.parent.childCount ← data.parent.childCount.SUCC
}
ELSE {
FOR p: LIST OF REF Inversion ← thisCell.parents, p.rest DO
IF p.first = data.parent THEN EXIT;
IF p.rest = NIL THEN {
p.rest ← CONS[data.parent, NIL];
data.parent.childCount ← data.parent.childCount.SUCC;
EXIT
}
ENDLOOP;
}
}
}
};
END.