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: BOOLFALSE];
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 [BOOLFALSE] = {
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: BOOLFALSE] =
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.ROPENIL] =
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 [BOOLFALSE] =
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 [BOOLFALSE] =
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: BOOLTRUE] =
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 [BOOLTRUE] = {
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.