CDPropertiesImpl.mesa a ChipNDale module
Copyright © 1983, 1985 by Xerox Corporation. All rights reserved.
by Ch. Jacobi, September 27, 1983 2:06 pm
last edited Christian Jacobi, April 11, 1985 3:17:45 pm PST
DIRECTORY
CDProperties,
CD,
CDPrivate,
Atom,
RefTab,
Rope,
TokenIO,
ViewerTools USING [TiogaContents, TiogaContentsRec];
CDPropertiesImpl:
CEDAR
MONITOR
IMPORTS CD, CDPrivate, CDProperties, Atom, RefTab, TokenIO
EXPORTS CDProperties =
BEGIN
Properties: TYPE = CD.Properties;
PropertyProcs: TYPE = CDProperties.PropertyProcs;
PropertyProcsRec: TYPE = CDProperties.PropertyProcsRec;
atomTab: RefTab.Ref = RefTab.Create[]; -- contains atoms [maybe in future ref's] where properties hang
--Registration
propertyNameTab: RefTab.Ref = RefTab.Create[]; -- key: propertynames; value: PropertyProcs
registrationTab: RefTab.Ref = RefTab.Create[]; -- contains registrationKeys
RegisterProperty:
PUBLIC
ENTRY PROC [prop:
REF, registrationKey:
REF←
NIL]
RETURNS [first:
BOOLEAN←TRUE] =
--registers "prop" in a table; any program which wants to use an ATOM
--as a "prop" gets to know if it is already in use.
BEGIN
val: RefTab.Val;
found: BOOL;
[found, val] ← RefTab.Fetch[x: registrationTab, key: prop]; -- returns a registration key
IF found
THEN {
IF registrationKey#NIL AND registrationKey=val THEN RETURN [FALSE];
RETURN WITH ERROR CD.Error[doubleRegistration]
}
ELSE {
pp: PropertyProcs ← NEW[PropertyProcsRec];
[] ← RefTab.Insert[propertyNameTab, prop, pp]; -- procs
[] ← RefTab.Insert[registrationTab, prop, registrationKey]; -- registration
};
END;
--Usage
HasNoCDProperties: ERROR = CODE;
PutProp:
PUBLIC
PROC [onto:
REF, prop:
REF, val:
REF] =
--a NIL val removes the property
BEGIN
WITH onto
SELECT
FROM
a: CD.ApplicationPtr => PutPropOnApplication[a, prop, val];
o:
CD.ObPtr =>
IF o.p.inDirectory THEN PutPropOnObject[o, prop, val]
ELSE ERROR HasNoCDProperties;
d: CD.Design => PutPropOnDesign[d, prop, val];
t: CD.Technology => PutPropOnTechnology[t, prop, val];
--l: CD.LayerRef => PutPropOnLayerRef[l, prop, val];
at: ATOM => PutPropOnAtom[at, prop, val];
ENDCASE => ERROR HasNoCDProperties
END;
GetProp:
PUBLIC
PROC [from:
REF, prop:
REF]
RETURNS [
REF] =
--NIL if prop is not found
BEGIN
RETURN [
WITH from
SELECT
FROM
a: CD.ApplicationPtr => CDProperties.GetPropFromList[a.properties, prop],
o: CD.ObPtr => CDProperties.GetPropFromList[o.properties, prop],
d: CD.Design => CDProperties.GetPropFromList[d.properties, prop],
t: CD.Technology => CDProperties.GetPropFromList[t.properties, prop],
--l: CD.LayerRef => CDProperties.GetPropFromList[l.properties, prop],
at: ATOM => GetPropFromAtom[at, prop],
ENDCASE => ERROR HasNoCDProperties]
END;
--speed ups
PutPropOnObject:
PUBLIC
ENTRY
PROC [onto:
CD.ObPtr, prop:
REF, val:
REF] =
--a NIL val removes the property
BEGIN
ENABLE UNWIND => NULL;
IF val#NIL THEN onto.properties ← Atom.PutPropOnList[onto.properties, prop, val]
ELSE onto.properties ← Atom.RemPropFromList[onto.properties, prop]
END;
PutPropOnApplication:
PUBLIC
ENTRY
PROC[onto:
CD.ApplicationPtr, prop:
REF, val:
REF] =
--a NIL val removes the property
BEGIN
ENABLE UNWIND => NULL;
IF val#NIL THEN onto.properties ← Atom.PutPropOnList[onto.properties, prop, val]
ELSE onto.properties ← Atom.RemPropFromList[onto.properties, prop]
END;
PutPropOnDesign:
PUBLIC
ENTRY
PROC [onto:
CD.Design, prop:
REF, val:
REF] =
--a NIL val removes the property
BEGIN
ENABLE UNWIND => NULL;
IF val#NIL THEN onto.properties ← Atom.PutPropOnList[onto.properties, prop, val]
ELSE onto.properties ← Atom.RemPropFromList[onto.properties, prop]
END;
PutPropOnTechnology:
PUBLIC
ENTRY
PROC[onto:
CD.Technology, prop:
REF, val:
REF] =
--a NIL val removes the property
BEGIN
ENABLE UNWIND => NULL;
IF val#NIL THEN onto.properties ← Atom.PutPropOnList[onto.properties, prop, val]
ELSE onto.properties ← Atom.RemPropFromList[onto.properties, prop]
END;
PutPropOnAtom:
PUBLIC
PROC[onto:
ATOM, prop:
REF, val:
REF] =
--a NIL val removes the property
{PutPropOnRef[onto: onto, prop: prop, val: val]};
PutPropOnLayer:
PUBLIC
ENTRY
PROC[onto:
CD.Layer, prop:
REF, val:
REF] =
--a NIL val removes the property
BEGIN
ENABLE UNWIND => NULL;
CDPrivate.layers[onto].properties ←
IF val#NIL THEN Atom.PutPropOnList[CDPrivate.layers[onto].properties, prop, val]
ELSE Atom.RemPropFromList[CDPrivate.layers[onto].properties, prop];
END;
PutPropOnRef:
ENTRY
PROC[onto:
REF, prop:
REF, val:
REF] =
--a NIL val removes the property
--here onto MUST NOT be a Chipndale ref pointing to a record with properties,
--since then the properties must be used, not the hash table
BEGIN
x: REF;
found: BOOL;
pp: REF CD.Properties;
[found, x] ← RefTab.Fetch[x: atomTab, key: onto];
IF found THEN pp ← NARROW[x, REF CD.Properties]
ELSE {
IF prop=NIL THEN RETURN;
pp ← NEW[CD.Properties←NIL];
[] ← RefTab.Store[x: atomTab, key: onto, val: pp];
};
IF prop#NIL THEN pp^ ← Atom.PutPropOnList[propList: pp^, prop: prop, val: val]
ELSE {
pp^ ← Atom.RemPropFromList[propList: pp^, prop: prop];
IF pp^=NIL THEN [] ← RefTab.Delete[x: atomTab, key: onto]
}
END;
GetPropFromRef:
ENTRY PROC [from:
REF, prop:
REF]
RETURNS [
REF] =
--NIL if prop is not found
--here from MUST NOT be a Chipndale ref pointing to a record with properties,
--since then the properties must be used, not the hash table
INLINE BEGIN
x: REF;
found: BOOL;
pp: REF CD.Properties;
[found, x] ← RefTab.Fetch[x: atomTab, key: from];
IF NOT found THEN RETURN[NIL];
pp ← NARROW[x, REF CD.Properties];
RETURN[Atom.GetPropFromList[propList: pp^, prop: prop]]
END;
GetPropFromObject:
PUBLIC
PROC [from:
CD.ObPtr, prop:
REF]
RETURNS [
REF] =
--NIL if prop is not found
BEGIN
ENABLE UNWIND => NULL;
RETURN[CDProperties.GetPropFromList[from.properties, prop]]
END;
GetPropFromApplication:
PUBLIC
PROC [from:
CD.ApplicationPtr, prop:
REF]
RETURNS [
REF] =
--NIL if prop is not found
BEGIN
ENABLE UNWIND => NULL;
RETURN[CDProperties.GetPropFromList[from.properties, prop]]
END;
GetPropFromDesign:
PUBLIC
PROC [from:
CD.Design, prop:
REF]
RETURNS [
REF] =
--NIL if prop is not found
BEGIN
ENABLE UNWIND => NULL;
RETURN[CDProperties.GetPropFromList[from.properties, prop]]
END;
GetPropFromTechnology:
PUBLIC
PROC [from:
CD.Technology, prop:
REF]
RETURNS [
REF] =
--NIL if prop is not found
BEGIN
ENABLE UNWIND => NULL;
RETURN[CDProperties.GetPropFromList[from.properties, prop]]
END;
GetPropFromLayer:
PUBLIC
PROC [from:
CD.Layer, prop:
REF]
RETURNS [
REF] =
--NIL if prop is not found
BEGIN
ENABLE UNWIND => NULL;
RETURN[CDProperties.GetPropFromList[CDPrivate.layers[from].properties, prop]]
END;
GetPropFromAtom:
PUBLIC
PROC [from:
ATOM, prop:
REF]
RETURNS [
REF] =
--NIL if prop is not found
{RETURN[GetPropFromRef[from: from, prop: prop]]};
--property procedures
InstallProcs:
PUBLIC
ENTRY
PROC [prop:
REF, new: PropertyProcsRec] =
--prop must be registered and yours
--overwrites values for which new has non NIL entries
BEGIN
p: PropertyProcs ← FetchProcs[prop];
IF p#
NIL
THEN {
IF new.exclusive THEN p.exclusive←TRUE;
IF new.makeCopy#NIL THEN p.makeCopy ← new.makeCopy;
IF new.internalWrite#NIL THEN p.internalWrite ← new.internalWrite;
IF new.internalRead#NIL THEN p.internalRead ← new.internalRead;
FOR l: Properties ← new.properties, l.rest
WHILE l#
NIL
DO
p.properties ←
(IF l.first.val#
NIL
THEN Atom.PutPropOnList[p.properties, l.first.key, l.first.val]
ELSE Atom.RemPropFromList[p.properties, l.first.key]);
ENDLOOP;
}
END;
FetchProcs:
PUBLIC
PROC [prop:
REF]
RETURNS [PropertyProcs] =
--never copy PropertyProcs^; it can be extended by future calls of InstallProcs
BEGIN
x: REF;
found: BOOL;
[found: found, val: x] ← RefTab.Fetch[propertyNameTab, prop];
IF found THEN RETURN [NARROW[x, PropertyProcs]] ELSE RETURN [NIL]
END;
CopyVal:
PUBLIC
PROC [prop:
REF, val:
REF]
RETURNS [valCopy:
REF] =
{valCopy ← val};
DontCopy:
PUBLIC
PROC [prop:
REF, val:
REF]
RETURNS [nil:
REF] =
{nil ← NIL};
CopyProps:
PUBLIC
PROC [propList: Properties]
RETURNS [copy: Properties←
NIL] =
BEGIN
FOR l: Properties ← propList, l.rest
WHILE l#
NIL
DO
copy ← CopyItem[copy, l.first]
ENDLOOP;
END;
CopyItem:
PROC[list: CDProperties.Properties, item: Atom.DottedPair]
RETURNS [newList: CDProperties.Properties] =
BEGIN
p: CDProperties.PropertyProcs = FetchProcs[item.key];
IF p#
NIL
AND p.makeCopy#
NIL
THEN {
newVal: REF = p.makeCopy[prop: item.key, val: item.val];
IF newVal=NIL THEN newList ← list
ELSE
newList ← Atom.PutPropOnList[
propList: list,
prop: item.key,
val: newVal
];
}
ELSE
IF
ISTYPE[item.key,
ATOM]
AND item.val#
NIL
THEN
WITH item.val
SELECT
FROM
r: Rope.
ROPE => {
newList ← Atom.PutPropOnList[
propList: list,
prop: item.key,
val: r
];
};
at:
ATOM => {
newList ← Atom.PutPropOnList[
propList: list,
prop: item.key,
val: at
];
};
pl:
CD.Properties => {
newList ← Atom.PutPropOnList[
propList: list,
prop: item.key,
val: CopyProps[pl]
];
};
ri:
REF
INT => {
newList ← Atom.PutPropOnList[
propList: list,
prop: item.key,
val: NEW[INT←ri^]
];
};
ENDCASE => newList ← list
ELSE newList ← list;
END;
AppendProps:
PUBLIC
PROC [winner, looser: CDProperties.Properties]
RETURNS [copy: CDProperties.Properties] =
BEGIN
copy ← CopyProps[looser];
FOR l: Properties ← winner, l.rest
WHILE l#
NIL
DO
copy ← CopyItem[copy, l.first]
ENDLOOP;
END;
RopePWrite:
PUBLIC PROC [prop:
REF, val:
REF] =
BEGIN
WITH val
SELECT
FROM
r: Rope.ROPE => TokenIO.WriteRope[r];
at: ATOM => TokenIO.WriteRope[Atom.GetPName[at]];
ENDCASE => TokenIO.WriteRope["bad property value"];
END;
AtomPWrite:
PUBLIC PROC [prop:
REF, val:
REF] =
BEGIN
WITH val
SELECT
FROM
at: ATOM => TokenIO.WriteAtom[at];
r: Rope.ROPE => TokenIO.WriteAtom[Atom.MakeAtom[r]];
ENDCASE => TokenIO.WriteAtom[$Bad];
END;
IntPWrite:
PUBLIC
PROC [prop:
REF, val:
REF] =
BEGIN
WITH val
SELECT
FROM
ri: REF INT => TokenIO.WriteInt[ri^];
rc: REF CARDINAL => TokenIO.WriteInt[rc^];
rn: REF NAT => TokenIO.WriteInt[rn^];
ENDCASE => TokenIO.WriteInt[0];
END;
SomePWrite:
PUBLIC
PROC [prop:
REF, val:
REF] =
BEGIN
WITH val
SELECT
FROM
at: ATOM => TokenIO.WriteAtom[at];
r: Rope.ROPE => TokenIO.WriteRope[r];
ri: REF INT => TokenIO.WriteInt[ri^];
rc: REF CARDINAL => TokenIO.WriteInt[rc^];
rn: REF NAT => TokenIO.WriteInt[rn^];
ENDCASE => TokenIO.WriteAtom[$Unknown];
END;
RopePRead:
PUBLIC PROC [prop:
ATOM]
RETURNS [val:
REF] =
BEGIN
val ← TokenIO.ReadRope[]
END;
AtomPRead:
PUBLIC PROC [prop:
ATOM]
RETURNS [val:
REF] =
BEGIN
val ← TokenIO.ReadAtom[]
END;
IntPRead:
PUBLIC
PROC [prop:
ATOM]
RETURNS [val:
REF] =
BEGIN
val ← NEW[INT←TokenIO.ReadInt[]]
END;
SomePRead:
PUBLIC
PROC [prop:
ATOM]
RETURNS [val:
REF] =
BEGIN
t: TokenIO.Token ← TokenIO.ReadToken[];
SELECT t.kind
FROM
atom, int, rope => val ← t.ref;
ENDCASE => val ← $Error;
END;
--------------------------
--now some special properties
TiogaPCopy:
PROC [prop:
REF, val:
REF]
RETURNS [copy:
REF] =
BEGIN
contents: Rope.ROPE ← NIL;
formatting: Rope.ROPE ← NIL;
WITH val
SELECT
FROM
t: ViewerTools.TiogaContents => {
contents ← t.contents;
formatting ← t.formatting};
r: Rope.ROPE => contents ← r;
ENDCASE => contents ← "$Error";
copy ← NEW[ViewerTools.TiogaContentsRec←[contents: contents, formatting: formatting]]
END;
TiogaPWrite:
PROC [prop:
REF, val:
REF] =
BEGIN
contents: Rope.ROPE ← NIL;
formatting: Rope.ROPE ← NIL;
WITH val
SELECT
FROM
t: ViewerTools.TiogaContents => {
contents ← t.contents;
formatting ← t.formatting};
r: Rope.ROPE => contents ← r;
ENDCASE => NULL;
TokenIO.WriteRope[contents];
TokenIO.WriteRope[formatting];
END;
TiogaPRead:
PROC [prop:
ATOM]
RETURNS [val:
REF] =
BEGIN
contents: Rope.ROPE ← TokenIO.ReadRope[];
formatting: Rope.ROPE ← TokenIO.ReadRope[];
val ← NEW[ViewerTools.TiogaContentsRec←[contents: contents, formatting: formatting]]
END;
[] ← CDProperties.RegisterProperty[$SignalName];
[] ← CDProperties.RegisterProperty[$InstanceName];
[] ← CDProperties.RegisterProperty[$Tioga];
CDProperties.InstallProcs[prop: $SignalName, new:
CDProperties.PropertyProcsRec[
makeCopy: CDProperties.CopyVal,
internalWrite: CDProperties.RopePWrite,
internalRead: CDProperties.RopePRead
]];
CDProperties.InstallProcs[prop: $InstanceName, new:
CDProperties.PropertyProcsRec[
makeCopy: CDProperties.CopyVal,
internalWrite: CDProperties.RopePWrite,
internalRead: CDProperties.RopePRead
]];
CDProperties.InstallProcs[prop: $Tioga, new:
CDProperties.PropertyProcsRec[
makeCopy: TiogaPCopy,
internalWrite: TiogaPWrite,
internalRead: TiogaPRead
]];
END.