CDPCommands.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
by Ch. Jacobi, November 20, 1985 7:59:40 pm PST
Last Edited by: Jacobi, November 26, 1985 11:07:31 am PST
DIRECTORY
Ascii,
Atom,
CD,
CDBasics,
CDCells,
CDCommandOps,
CDErrors,
CDExtras,
CDInstances,
CDMenus,
CDProperties,
CDSequencer,
CDSymbolicObjects,
CDTexts,
CDOps,
IO,
Rope,
TerminalIO;
CDPCommands:
CEDAR
PROGRAM
IMPORTS Ascii, Atom, CDBasics, CDCells, CDCommandOps, CDErrors, CDExtras, CDInstances, CDMenus, CDProperties, CDSequencer, CDSymbolicObjects, CDTexts, CDOps, IO, Rope, TerminalIO =
BEGIN
PropertyRec: TYPE = RECORD [key: ATOM←NIL, value: REF←NIL, onOb: BOOL←FALSE];
PutPropFromPropertyRec:
PROC [inst:
CD.Instance, prop: PropertyRec] =
BEGIN
IF prop.onOb
THEN {
IF inst.ob.class.inDirectory
THEN
CDProperties.PutProp[onto: inst.ob, prop: prop.key, val: prop.value]
}
ELSE CDProperties.PutProp[onto: inst, prop: prop.key, val: prop.value]
END;
SetPropsFromTextsComm:
PROC [comm: CDSequencer.Command] =
BEGIN
n, m: INT;
TerminalIO.WriteRope["propertize all texts"];
n ← SetPropsFromTexts[comm.design];
TerminalIO.WriteRope["; now check\n"];
m ← CheckProps[comm.design, NIL];
TerminalIO.WriteF[" %g texts propertized; %g mismatch(es) found\n", IO.int[n], IO.int[m]];
END;
PutPropOnSelectedComm:
PROC [comm: CDSequencer.Command] =
BEGIN
TerminalIO.WriteRope["propertize selected\n"];
PutPropOnSelected[comm.design];
TerminalIO.WriteRope[" end\n"];
END;
CheckPropsFromTextsComm:
PROC [comm: CDSequencer.Command] =
BEGIN
n: INT;
TerminalIO.WriteRope["check properties\n"];
n ← CheckProps[comm.design, NIL];
TerminalIO.WriteF[" %g unmatched text(s) found\n", IO.int[n]];
END;
CellCheckPropsComm:
PROC [comm: CDSequencer.Command] =
BEGIN
inst: CD.Instance ← CDCommandOps.TheInstance[comm: comm, text: "check properties"];
IF inst#
NIL
THEN {
no: INT ← 0;
IF ~CDCells.IsCell[inst.ob]
THEN {
TerminalIO.WriteRope[" not done: selected object is not cell\n"];
RETURN;
};
no ← CheckProps[comm.design, inst.ob];
TerminalIO.WriteF[" %g unmatched text(s) found\n", IO.int[no]];
};
END;
SimilarRopes:
PROC [x, y:
REF]
RETURNS [
BOOL←
FALSE] = {
IF x=y THEN RETURN [TRUE];
IF
ISTYPE[x, Rope.
ROPE]
AND
ISTYPE[y, Rope.
ROPE]
THEN {
RETURN [ Rope.Equal[ NARROW[x, Rope.ROPE], NARROW[y, Rope.ROPE] ] ]
};
};
SelectFromPropertyComm:
PROC [comm: CDSequencer.Command] =
BEGIN
pRec: PropertyRec ← [$SignalName, NIL, FALSE];
inst: CD.Instance ← CDCommandOps.TheInstance[comm: comm, text: "select from property"];
IF inst#
NIL
THEN {
design: CD.Design ← comm.design;
no: INT ← 0;
IF MyKindOfText[inst.ob] THEN pRec ← TextToPropRec[inst.ob]
ELSE
IF inst.ob.class.wireTyped
OR CDSymbolicObjects.IsSymbolicOb[inst.ob]
THEN {
pRec.key ← $SignalName;
pRec.value ← CDProperties.GetProp[from: inst, prop: pRec.key];
}
ELSE {
TerminalIO.WriteRope[" not done: selected object is not text (Helvetica*I) or rectangle\n"];
RETURN;
};
IF pRec.key=
NIL
THEN {
TerminalIO.WriteRope[" not done: property key is NIL\n"];
RETURN;
};
TerminalIO.WriteF[" select using property: %g, value: %g\n", IO.atom[pRec.key], IO.rope[(IF pRec.value=NIL THEN "NIL" ELSE CDExtras.ToRope[pRec.value])]];
FOR l:
CD.InstanceList ← CDOps.InstList[design], l.rest
WHILE l#
NIL
DO
x: REF ← CDProperties.GetProp[l.first, pRec.key];
IF SimilarRopes[x, pRec.value]
THEN {
l.first.selected ← TRUE;
CDCommandOps.RedrawInstance[design, l.first, FALSE];
no ← no+1
};
ENDLOOP;
IF no>0
AND CDTexts.IsText[inst.ob]
THEN {
inst.selected ← FALSE;
CDCommandOps.RedrawInstance[design, inst];
};
TerminalIO.WriteF[" %g instance(s) selected\n", IO.int[no]];
};
END;
PropagateSignalNameComm:
PROC [comm: CDSequencer.Command] =
BEGIN
inst: CD.Instance ← CDCommandOps.TheInstance[comm: comm, text: "propagate signal name"];
IF inst#
NIL
THEN {
design: CD.Design ← comm.design;
il: CD.InstanceList ← CDOps.InstList[design];
foundL: CD.InstanceList ← LIST[inst];
no: INT ← 1;
value: REF ← CDProperties.GetProp[from: inst, prop: $SignalName];
IF value=
NIL
THEN {
TerminalIO.WriteRope[" not done: no signal name\n"];
RETURN;
};
WHILE foundL#
NIL
DO
curr: CD.Instance ← foundL.first;
currR: CD.Rect ← CDInstances.InstRectI[curr];
foundL ← foundL.rest;
FOR l:
CD.InstanceList ← il, l.rest
WHILE l#
NIL
DO
IF ~l.first.selected
AND l.first.ob.class.wireTyped
AND l.first.ob.layer=curr.ob.layer
THEN {
IF CDBasics.Intersect[currR, CDInstances.InstRectI[l.first]]
THEN {
foundL ← CONS[l.first, foundL];
l.first.selected ← TRUE;
no ← no+1;
CDProperties.PutProp[l.first, $SignalName, value];
CDCommandOps.RedrawInstance[design, l.first, FALSE];
};
}
ENDLOOP;
ENDLOOP;
TerminalIO.WriteF[" %g instance(s) selected\n", IO.int[no]];
};
END;
SetPropsFromTexts:
PROC [design:
CD.Design]
RETURNS [n:
INT𡤀] =
BEGIN
HandleOneText:
PROC [inst:
CD.Instance, design:
CD.Design]
RETURNS [someFound:
BOOL←
FALSE] =
BEGIN
IF MyKindOfText[inst.ob]
THEN {
pRec: PropertyRec ← TextToPropRec[inst.ob];
r: CD.Rect ← CDInstances.InstRectI[inst];
IF pRec.key=NIL OR ~PublicProperty[pRec.key] THEN RETURN;
FOR l:
CD.InstanceList ← CDOps.InstList[design], l.rest
WHILE l#
NIL
DO
IF ~CDTexts.IsText[l.first.ob]
AND CDBasics.Intersect[r, CDInstances.InstRectI[l.first]]
THEN {
someFound ← TRUE;
PutPropFromPropertyRec[l.first, pRec]
}
ENDLOOP;
}
END;
--SetPropsFromTexts
FOR l:
CD.InstanceList ← CDOps.InstList[design], l.rest
WHILE l#
NIL
DO
IF MyKindOfText[l.first.ob]
THEN
IF HandleOneText[l.first, design].someFound THEN n ← n+1;
ENDLOOP;
END;
TextToPropRec:
PROC [ob:
CD.Object]
RETURNS [pRec: PropertyRec ← [
NIL,
NIL,
FALSE]] =
BEGIN
RopeToPropRec:
PROC [text: Rope.
ROPE]
RETURNS [pRec: PropertyRec ← [$SignalName,
NIL,
FALSE]] =
--key nil means bad syntax
BEGIN
keyPart: Rope.ROPE;
val: Rope.ROPE;
n: INT ← Rope.SkipTo[s: text, skip: ":"];
IF n<Rope.Length[text]
THEN {
keyPart ← RemoveBlanksFromBothEnds[Rope.Substr[base: text, start: 0, len: n]];
text ← Rope.Substr[base: text, start: n+1];
IF Rope.Length[keyPart]=0 THEN pRec.key ← NIL
ELSE pRec.key ← Atom.MakeAtom[keyPart];
};
val ← RemoveBlanksFromBothEnds[text];
IF ~Rope.IsEmpty[val] THEN pRec.value ← val
END;
TextRope:
PROC [ob:
CD.Object]
RETURNS [r: Rope.
ROPE←
NIL] =
BEGIN
WITH ob.specificRef
SELECT
FROM
tp: CDTexts.TextPtr => RETURN [tp.text]
ENDCASE => NULL;
END;
--TextToPropRec
RETURN [RopeToPropRec[TextRope[ob]]]
END;
MyKindOfText:
PROC [ob:
CD.Object]
RETURNS [
BOOL←
FALSE] =
BEGIN
ThatIsMyFont:
PROC [name: Rope.
ROPE]
RETURNS [
BOOL] =
BEGIN
RETURN [
Rope.Match[object: name, pattern: "Xerox/TiogaFonts/Helvetica*", case: FALSE] AND
Ascii.Upper[Rope.Fetch[name, Rope.Length[name]-1]]='I
]
END;
--MyKindOfText
WITH ob.specificRef
SELECT
FROM
tp: CDTexts.TextPtr => RETURN [ThatIsMyFont[tp.cdFont.supposedName]]
ENDCASE => NULL;
END;
PutPropOnSelected:
PROC [design:
CD.Design] =
BEGIN
Occurs:
PROC [list:
LIST
OF PropertyRec, key:
ATOM]
RETURNS [
BOOL←
FALSE] =
BEGIN
FOR pl:
LIST
OF PropertyRec ← list, pl.rest
WHILE pl#
NIL
DO
IF pl.first.key=key THEN RETURN [TRUE]
ENDLOOP;
END;
--PutPropOnSelected
doList: LIST OF PropertyRec←NIL;
--build list of properties
FOR l:
CD.InstanceList ← CDOps.InstList[design], l.rest
WHILE l#
NIL
DO
IF l.first.selected
AND MyKindOfText[l.first.ob]
THEN {
pr: PropertyRec ← TextToPropRec[l.first.ob];
IF pr.key=
NIL
THEN {
TerminalIO.WriteRope["unknown property\n"];
[] ← CDErrors.IncludeMessage[design: design, ob: NIL, rect: CDInstances.InstRectI[l.first], message: "bad property key", owner: $PropertyChecker]
}
ELSE
IF Occurs[doList, pr.key]
THEN {
TerminalIO.WriteF[" ** property: %g, value: %g twice or contradicting! ignored\n", IO.atom[pr.key], IO.rope[(IF pr.value=NIL THEN "NIL" ELSE CDExtras.ToRope[pr.value])]]
}
ELSE {
doList ← CONS[pr, doList];
TerminalIO.WriteF[" property: %g, value: %g\n", IO.atom[pr.key], IO.rope[(IF pr.value=NIL THEN "NIL" ELSE CDExtras.ToRope[pr.value])]];
}
}
ENDLOOP;
-- put properties on instances
IF doList=NIL THEN TerminalIO.WriteRope["no text (in Helvetica*I) selected"]
ELSE {
FOR il:
CD.InstanceList ← CDOps.InstList[design], il.rest
WHILE il#
NIL
DO
IF il.first.selected
AND ~CDTexts.IsText[il.first.ob]
THEN {
FOR pl:
LIST
OF PropertyRec ← doList, pl.rest
WHILE pl#
NIL
DO
PutPropFromPropertyRec[il.first, pl.first]
ENDLOOP;
}
ENDLOOP;
}
END;
CheckProps:
PROC [design:
CD.Design, cell:
CD.Object]
RETURNS [cnt:
INT𡤀] =
BEGIN
BlownIntersection:
PROC [r1, r2:
CD.Rect, blow:
CD.Number]
RETURNS [
CD.Rect] = {
RETURN [ CDBasics.Intersection[CDBasics.Extend[r1, blow], CDBasics.Extend[r2, blow]] ];
};
CheckPropsOfOneText:
PROC [inst:
CD.Instance, design:
CD.Design, cell:
CD.Object]
RETURNS [ok:
BOOL←
TRUE] =
BEGIN
IF MyKindOfText[inst.ob]
THEN {
r: CD.Rect ← CDInstances.InstRectI[inst];
pRec: PropertyRec ← TextToPropRec[inst.ob];
cellPtr: CD.CellPtr ← IF cell=NIL THEN design.actual.first.specific ELSE NARROW[cell.specificRef];
val: REF;
IF pRec.key=NIL THEN RETURN;
FOR l:
CD.InstanceList ← cellPtr.contents, l.rest
WHILE l#
NIL
DO
IF ~CDTexts.IsText[l.first.ob]
AND CDBasics.Intersect[r, CDInstances.InstRectI[l.first]]
THEN {
IF pRec.onOb THEN val ← CDProperties.GetProp[from: l.first.ob, prop: pRec.key]
ELSE val ← CDProperties.GetProp[from: l.first, prop: pRec.key];
IF ~SimilarRopes[val, pRec.value]
THEN {
errR: CD.Rect ← BlownIntersection[r, CDInstances.InstRectI[l.first], design.technology.lambda];
[] ← CDErrors.IncludeMessage[design: design, ob: cell, rect: r, message: "property missmatch", owner: $PropertyChecker];
RETURN [ok←FALSE]
}
};
ENDLOOP;
}
END;
--CheckProps
cellPtr: CD.CellPtr ← IF cell=NIL THEN design.actual.first.specific ELSE NARROW[cell.specificRef];
CDErrors.RemoveMessages[design: design, ob: cell, owner: $PropertyChecker];
FOR l:
CD.InstanceList ← cellPtr.contents, l.rest
WHILE l#
NIL
DO
IF CDTexts.IsText[l.first.ob]
THEN
IF ~CheckPropsOfOneText[inst: l.first, design: design, cell: cell] THEN cnt ← cnt+1
ENDLOOP;
END;
PublicProperty:
PROC [key:
ATOM]
RETURNS [
BOOL←
TRUE] = {
pType: CDProperties.PropertyProcs ← CDProperties.FetchProcs[key];
RETURN [ pType=NIL OR ~pType.exclusive ];
};
RemoveTrailingBlanks:
PROC [r: Rope.
ROPE]
RETURNS [Rope.
ROPE] = {
n: INT ← Rope.Length[r];
WHILE n>0 AND Rope.Fetch[r, n-1]=' DO n ← n-1 ENDLOOP;
RETURN [Rope.Substr[base: r, start: 0, len: n]];
};
RemoveLeadingBlanks:
PROC [r: Rope.
ROPE]
RETURNS [Rope.
ROPE] = {
RETURN [Rope.Substr[base: r, start: Rope.SkipOver[s: r, skip: " "]]]
};
RemoveBlanksFromBothEnds:
PROC [r: Rope.
ROPE]
RETURNS [Rope.
ROPE] = {
RETURN [RemoveLeadingBlanks[RemoveTrailingBlanks[r]]]
};
CDSequencer.ImplementCommand[a: $AllPropertize, p: SetPropsFromTextsComm, queue: doQueue];
CDSequencer.ImplementCommand[a: $SelPropertize, p: PutPropOnSelectedComm, queue: doQueue];
CDSequencer.ImplementCommand[a: $PropSel, p: SelectFromPropertyComm, queue: doQueue];
CDSequencer.ImplementCommand[a: $PropTextCheckCell, p: CellCheckPropsComm, queue: doQueue];
CDSequencer.ImplementCommand[a: $PropTextCheck, p: CheckPropsFromTextsComm, queue: doQueue];
CDSequencer.ImplementCommand[a: $PropSig, p: PropagateSignalNameComm, queue: doQueue];
[] ← CDMenus.CreateMenu["Names & Properties", $NameMenu];
CDMenus.ImplementMenuCommand[$NameMenu, $NameMenu];
CDMenus.CreateEntry[menu: $NameMenu, entry: "properties from intersecting Texts", key: $AllPropertize];
CDMenus.CreateEntry[menu: $NameMenu, entry: "propertize selected from Text(s)", key: $SelPropertize];
CDMenus.CreateEntry[menu: $NameMenu, entry: "select all having property (Text)", key: $PropSel];
CDMenus.CreateEntry[menu: $NameMenu, entry: "check properties (top level)", key: $PropTextCheck];
CDMenus.CreateEntry[menu: $NameMenu, entry: "check properties (selected CELL)", key: $PropTextCheckCell];
CDMenus.CreateEntry[menu: $NameMenu, entry: "propagate SignalName of selected", key: $PropSig];
CDMenus.CreateEntry[menu: $NameMenu, entry: "other entries", key: $NameMenu2];
END.