SchemeEdit.Mesa
Last Edited by: Spreitzer, February 23, 1984 10:42 pm
DIRECTORY Basics, IO, OrderedSymbolTableRef, Rope, SchemeRep, SchemeEditing, ViewerClasses, ViewerOps, ViewerTools, ViewRec;
SchemePictures: CEDAR PROGRAM
IMPORTS IO, OrderedSymbolTableRef, Rope, SchemeEditing, ViewerOps, ViewerTools, ViewRec
EXPORTS SchemeEditing =
BEGIN OPEN SchemeRep, SchemeEditing;
CompareNames: PUBLIC OrderedSymbolTableRef.CompareProc --PROC [r1, r2: Item] RETURNS [Comparison]-- =
BEGIN
ToRope: PROC [any: REF ANY] RETURNS [k: ROPE] =
{k ← WITH any SELECT FROM
r: ROPE => r,
ct: CellType => ct.name,
p: Port => p.name,
n: Net => n.name,
c: Component => c.name,
cp: ComponentPort => cp.port.name,
pic: PictureDef => pic.name,
c: Coord => c.name,
pt: Point => pt.name,
l: Line => l.name,
t: Text => t.name,
pi: PictureInstance => pi.name,
ENDCASE => ERROR};
k1: ROPE ← ToRope[r1];
k2: ROPE ← ToRope[r2];
RETURN [k1.Compare[k2]];
END;
CompareCoords: OrderedSymbolTableRef.CompareProc --PROC [r1, r2: Item] RETURNS [Comparison]-- =
BEGIN
k1: REALWITH r1 SELECT FROM
c: Coord => c.z,
l: LORA => NARROW[l.first, Coord].z,
r: REF REAL => r^,
ENDCASE => ERROR;
k2: REALWITH r2 SELECT FROM
c: Coord => c.z,
l: LORA => NARROW[l.first, Coord].z,
r: REF REAL => r^,
ENDCASE => ERROR;
RETURN [IF k1 < k2 THEN less ELSE IF k1 > k2 THEN greater ELSE equal];
END;
NotifyLabels: PUBLIC PROC [labels: LORA, editor: Editor] =
BEGIN
ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: CONS[$Labels, labels]];
END;
NewPicture: PUBLIC PROC [session: Session, name: ROPE] RETURNS [pic: PictureDef] =
BEGIN
pic ← NEW [PictureDefRep ← [
name: name,
coordsByValue: [
OrderedSymbolTableRef.CreateTable[CompareCoords],
OrderedSymbolTableRef.CreateTable[CompareCoords]],
coordsByName: OrderedSymbolTableRef.CreateTable[CompareNames],
points: OrderedSymbolTableRef.CreateTable[CompareNames],
objects: OrderedSymbolTableRef.CreateTable[CompareNames]
]];
session.picsTable.Insert[pic];
END;
Export: PROC [session: Session, export: BOOLEAN] =
BEGIN
editor: Editor ← session.mostRecentEditor;
session.ctlRV.DisplayMessage[ViewRec.clearMessagePlace];
IF editor.primary.point = NIL THEN {Complain[editor, "No point selected"]; RETURN};
IF NOT export THEN {
uses: LIST OF ROPE ← FindExportedPointUses[editor.primary.point];
IF uses # NIL THEN {Complain[editor, IO.PutFR["Can't unexport; it's used by %g", IO.refAny[uses]]]; RETURN};
editor.primary.point.exported ← export;
RecomputeExported[editor.primary.point.c[X]];
RecomputeExported[editor.primary.point.c[Y]]}
ELSE {
editor.primary.point.exported ← export;
editor.primary.point.c[X].exported ← TRUE;
editor.primary.point.c[Y].exported ← TRUE};
END;
RecomputeExported: PROC [c: Coord] =
{e: BOOLFALSE;
FOR l: LORA ← c.dependents, l.rest WHILE l # NIL DO
WITH l.first SELECT FROM
c2: Coord => NULL;
p: Point => IF p.exported THEN e ← TRUE;
ENDCASE => ERROR;
ENDLOOP;
c.exported ← e};
FindExportedPointUses: PROC [point: Point] RETURNS [uses: LIST OF ROPE] =
BEGIN
uses ← NIL;
FOR l: LORA ← point.pic.instances, l.rest WHILE l # NIL DO
pi: PictureInstance ← NARROW[l.first];
pip: Point ← NARROW[pi.points.Lookup[PIPointName[pi.name, point.name]]];
IF pip.dependents # NIL THEN uses ← CONS[IO.PutFR["%g.%g", IO.rope[pi.in.name], IO.rope[pi.name]], uses];
ENDLOOP;
END;
PIPointName: PUBLIC PROC [piName, pointName: ROPE] RETURNS [piPointName: ROPE] =
{piPointName ← piName.Cat[".", pointName]};
MakePoint: PUBLIC PROC [pic: PictureDef, vertex: Vertex, name: ROPENIL] RETURNS [point: Point] =
BEGIN
Try: PROC [x: Coord] RETURNS [found: BOOLEANFALSE] =
BEGIN
FOR l: LORA ← x.dependents, l.rest WHILE l # NIL DO
WITH l.first SELECT FROM
c: Coord => NULL;
p: Point => IF p.c[Y] = vertex[Y] THEN {point ← p; RETURN [TRUE]};
ENDCASE => ERROR;
ENDLOOP;
END;
atX: REF ANY ← pic.coordsByValue[X].Lookup[vertex[X]];
WITH atX SELECT FROM
c: Coord => IF Try[c] THEN RETURN;
la: LORA => FOR l: LORA ← la, l.rest WHILE l # NIL DO
IF Try[NARROW[l.first]] THEN RETURN;
ENDLOOP;
ENDCASE => ERROR;
IF name = NIL THEN name ← NewName[pic.points];
point ← NewPoint[pic, name, vertex];
END;
NewPoint: PUBLIC PROC [pic: PictureDef, name: ROPE, vertex: Vertex] RETURNS [point: Point] =
BEGIN
point ← NEW [PointRep ← [c: vertex, name: name, pic: pic, dependents: NIL]];
pic.points.Insert[point];
vertex[X].dependents ← CONS[point, vertex[X].dependents];
vertex[Y].dependents ← CONS[point, vertex[Y].dependents];
END;
nameCount: INT ← 0;
NewName: PUBLIC PROC [for: Table] RETURNS [name: ROPE] =
{found: REF ANY ← $Found;
WHILE found # NIL DO
found ← for.Lookup[name ← IO.PutFR["^%g|", IO.int[nameCount ← nameCount + 1]]];
ENDLOOP};
NewCoord: PUBLIC PROC [axis: Axis, at: REAL, pic: PictureDef, parent: REF ANYNIL, name: ROPENIL] RETURNS [new: Coord] =
BEGIN
org: REALIF parent # NIL
THEN WITH parent SELECT FROM
coord: Coord => coord.z,
pi: PictureInstance => pi.org.c[axis].z,
ENDCASE => ERROR
ELSE 0;
IF name = NIL THEN name ← NewName[pic.coordsByName];
new ← EnsureCoord[pic, name];
new^ ← [name: new.name, pic: pic, axis: axis, z: at, sz: at, dependents: NIL, parent: parent, dz: at - org];
EntableCoord[pic.coordsByValue[axis], new];
IF parent # NIL THEN WITH parent SELECT FROM
coord: Coord => coord.dependents ← CONS[new, coord.dependents];
pi: PictureInstance => pi.coords.Insert[new];
ENDCASE => ERROR;
END;
NewLine: PUBLIC PROC [pic: PictureDef, a, b: Point] RETURNS [line: Line] =
BEGIN
editor: Editor ← NARROW[pic.editor];
IF a = NIL OR b = NIL THEN RETURN [NIL];
IF a.deleted OR b.deleted THEN ERROR;
line ← NEW [LineRep ← [name: NewName[pic.objects], a: a, b: b, sa: [0, 0], sb: [0, 0]]];
pic.objects.Insert[line];
a.dependents ← CONS[line, a.dependents];
b.dependents ← CONS[line, b.dependents];
IF editor # NIL THEN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: line];
END;
DeleteLine: PUBLIC PROC [pic: PictureDef, a, b: Point, line: Line ← NIL] =
BEGIN
editor: Editor ← NARROW[pic.editor];
IF line = NIL THEN line ← FindLine[a, b];
IF line = NIL THEN RETURN;
IF editor # NIL THEN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: line];
line.a.dependents ← Filter[line.a.dependents, line];
line.b.dependents ← Filter[line.b.dependents, line];
[] ← pic.objects.Delete[line];
END;
FindLine: PUBLIC PROC [a, b: Point] RETURNS [line: Line] =
{IF a = NIL OR b = NIL THEN RETURN [NIL];
FOR l: LORA ← a.dependents, l.rest WHILE l # NIL DO
WITH l.first SELECT FROM
t: Text => NULL;
l2: Line => IF (l2.a = a AND l2.b = b) OR (l2.a = b AND l2.b = a) THEN RETURN [l2];
pi: PictureInstance => NULL;
ENDCASE => ERROR;
ENDLOOP;
line ← NIL};
NewText: PUBLIC PROC [pic: PictureDef, p: Point, rope: ROPE] =
BEGIN
editor: Editor ← NARROW[pic.editor];
text: Text;
text ← NEW [TextRep ← [name: NewName[pic.objects], org: p, sxy: [0, 0], rope: rope]];
pic.objects.Insert[text];
p.dependents ← CONS[text, p.dependents];
IF editor # NIL THEN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: text];
END;
DeleteText: PUBLIC PROC [pic: PictureDef, at: Point, text: Text ← NIL] =
BEGIN
editor: Editor ← NARROW[pic.editor];
IF text = NIL THEN text ← FindText[at];
IF text = NIL THEN RETURN;
IF editor # NIL THEN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: text];
text.org.dependents ← Filter[text.org.dependents, text];
[] ← pic.objects.Delete[text];
END;
FindText: PROC [at: Point] RETURNS [text: Text] =
{FOR l: LORA ← at.dependents, l.rest WHILE l # NIL DO
WITH l.first SELECT FROM
t: Text => IF t.org = at THEN RETURN [t];
l2: Line => NULL;
pi: PictureInstance => NULL;
ENDCASE => ERROR;
ENDLOOP;
text ← NIL};
NewInstance: PUBLIC PROC [pic: PictureDef, p: Point, className, iconName: ROPE] =
BEGIN
editor: Editor ← NARROW[pic.editor];
ct: CellType ← NARROW[editor.session.typesTable.Lookup[className]];
def: PictureDef;
IF ct = NIL THEN {Complain[editor, "No such cellType"]; RETURN};
def ← NARROW[IF ct.icons.Size[] = 1 THEN ct.icons.LookupSmallest[] ELSE ct.icons.Lookup[iconName]];
IF def = NIL THEN {Complain[editor, "No such icon"]; RETURN};
[] ← CreateInstance[in: pic, of: def, org: p];
END;
FindPI: PUBLIC PROC [at: Point] RETURNS [pi: PictureInstance] =
{FOR l: LORA ← at.dependents, l.rest WHILE l # NIL DO
WITH l.first SELECT FROM
t: Text => NULL;
l2: Line => NULL;
pi: PictureInstance => IF pi.org = at THEN RETURN [pi];
ENDCASE => ERROR;
ENDLOOP;
pi ← NIL};
DeleteInstance: PUBLIC PROC [pic: PictureDef, at: Point, pi: PictureInstance ← NIL] =
BEGIN
check, ok: BOOLEANTRUE;
Per: PROC [any: REF ANY] RETURNS [stop: BOOLEAN] =
{stop ← FALSE;
WITH any SELECT FROM
c: Coord =>
IF check THEN
{bad: BOOLEANFALSE;
FOR l: LORA ← c.dependents, l.rest WHILE l # NIL DO
WITH l.first SELECT FROM
c2: Coord => bad ← TRUE;
p: Point => bad ← bad OR (p.fromPI # pi);
ENDCASE => ERROR;
ENDLOOP;
IF bad THEN {ok ← FALSE; Complain[editor, IO.PutFR[" exported coord %g has dependents", IO.rope[c.name]]]}}
ELSE DeleteCoord[c];
p: Point =>
IF check THEN
{IF p.dependents # NIL THEN {ok ← FALSE; Complain[editor, IO.PutFR[" exported point %g has dependents", IO.rope[p.name]]]}}
ELSE DeletePoint[pic, p];
ENDCASE => ERROR};
editor: Editor ← NARROW[pic.editor];
IF pi = NIL THEN pi ← FindPI[at];
IF pi = NIL THEN RETURN;
pi.coords.EnumerateIncreasing[Per];
IF NOT ok THEN RETURN;
pi.points.EnumerateIncreasing[Per];
IF NOT ok THEN RETURN;
check ← FALSE;
IF editor # NIL THEN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: pi];
pi.points.EnumerateIncreasing[Per];
pi.coords.EnumerateIncreasing[Per];
pi.org.dependents ← Filter[pi.org.dependents, pi];
[] ← pic.objects.Delete[pi];
pi.of.instances ← Filter[pi.of.instances, pi];
END;
CreateInstance: PUBLIC PROC [in, of: PictureDef, org: Point] RETURNS [pi: PictureInstance] =
BEGIN
AddCoord: PROC [any: REF ANY] RETURNS [stop: BOOLEAN] =
BEGIN
inDef: Coord ← NARROW[any];
stop ← FALSE;
IF NOT inDef.exported THEN RETURN;
IF (inDef.exportedTo # NIL) AND (inDef.exportedTo.parent = pi) THEN RETURN;
inDef.exportedTo ← NewCoord[inDef.axis, inDef.z + pi.org.c[inDef.axis].z, in, pi];
END;
AddPoint: PROC [any: REF ANY] RETURNS [stop: BOOLEAN] =
BEGIN
inDef: Point ← NARROW[any];
inCaller: Point;
stop ← FALSE;
IF NOT inDef.exported THEN RETURN;
inCaller ← MakePoint[in, [inDef.c[X].exportedTo, inDef.c[Y].exportedTo], PIPointName[pi.name, inDef.name]];
inCaller.fromPort ← inDef.name;
inCaller.fromPI ← pi;
pi.points.Insert[inCaller];
END;
editor: Editor ← NARROW[in.editor];
pi ← EnsurePictureInstance[in, NewName[in.objects]];
pi^ ← [name: pi.name, in: in, of: of, org: org, s: [0, 0],
coords: OrderedSymbolTableRef.CreateTable[CompareNames],
points: OrderedSymbolTableRef.CreateTable[CompareNames]];
pi.of.instances ← CONS[pi, pi.of.instances];
org.dependents ← CONS[pi, org.dependents];
of.coordsByName.EnumerateIncreasing[AddCoord];
of.points.EnumerateIncreasing[AddPoint];
IF editor # NIL THEN ViewerOps.PaintViewer[viewer: editor.v, hint: client, clearClient: FALSE, whatChanged: pi];
END;
CheckInstances: PROC [pic: PictureDef] =
BEGIN
Check: PROC [any: REF ANY] RETURNS [stop: BOOL] =
{stop ← FALSE;
WITH any SELECT FROM
l: Line => NULL;
t: Text => NULL;
pi: PictureInstance => IF pi.in # pic THEN ERROR;
ENDCASE => ERROR};
pic.objects.EnumerateIncreasing[Check];
END;
Complain: PUBLIC PROC [editor: Editor, complaint: ROPE] =
{editor.session.ctlRV.DisplayMessage[complaint]};
CreateSession: PROC [name: ROPE] RETURNS [session: Session] =
BEGIN
ctl: CtlPanel ← NEW [CtlPanelRep ← [
Clear: Clear,
ReadFile: ReadFile,
WriteFile: WriteFile,
CreateCellType: CreateCellType,
CreateIcon: CreateIcon,
EditType: EditType,
Export: Export,
cellType: "foo",
icon: "bar",
name: "baz"]];
session ← NEW [SessionRep ← [
name: name,
typesMenu: ViewerTools.MakeNewTextViewer[info: [name: name.Cat[" Types"], iconic: FALSE], paint: FALSE],
ctlRV: NIL,
ctlPanel: ctl,
editors: NIL,
typesTable: OrderedSymbolTableRef.CreateTable[CompareNames],
picsTable: OrderedSymbolTableRef.CreateTable[CompareNames]]];
ViewerOps.SetOpenHeight[session.typesMenu, 100];
session.ctlRV ← ViewRec.ViewRef[
agg: ctl,
specs: ViewRec.BindAllOfATypeFromRefs[rec: ctl, handle: NEW [Session ← session]],
viewerInit: [name: name.Cat[" Ctl"], iconic: FALSE]];
END;
END.