Last edited by:
Doug Wyatt, May 21, 1984 2:47:44 pm PDT
DIRECTORY
FontRegistry USING [FONT, FontRep],
ImagerBasic USING [Transformation],
Rope USING [Equal, ROPE];
FontRegistryImpl: CEDAR MONITOR
IMPORTS Rope
EXPORTS FontRegistry
= BEGIN
ROPE: TYPE ~ Rope.ROPE;
Transformation: TYPE ~ ImagerBasic.Transformation;
FONT: TYPE ~ FontRegistry.FONT;
FontRep: TYPE ~ FontRegistry.FontRep;
NodeRep: TYPE = RECORD [key: FONT, next: Node];
Node: TYPE = REF NodeRep;
Array: TYPE = RECORD[nodes: SEQUENCE max: CARDINAL OF Node];
Global (monitored) data:
================
mod: CARDINAL ~ 17; -- should be IN[1..4095]
size: CARDINAL ← 0;
data: REF Array ← NEW[Array[mod]];
================
Hash:
PROC[name:
ROPE, m: Transformation]
RETURNS [
CARDINAL] =
TRUSTED {
size: INT ← Rope.InlineSize[s];
IF size = 0 THEN RETURN[0];
{c0: CARDINAL = Ascii.Lower[Rope.InlineFetch[s, 0]] - 0C;
c1: CARDINAL = Ascii.Lower[Rope.InlineFetch[s, size-1]] - 0C;
RETURN [(size + c0 + c1) MOD mod]};
RETURN[0];
};
TransformationEqual:
PROC[m, n: Transformation]
RETURNS[
BOOL] ~ {
RETURN[m^=n^];
};
Register:
PUBLIC
ENTRY
PROC[name:
ROPE, m: Transformation]
RETURNS[font:
FONT] ~ {
ENABLE UNWIND => NULL;
hash: CARDINAL ~ Hash[name, m];
head: Node ~ data[hash];
FOR node: Node ← head, node.next
WHILE node#
NIL
DO
font: FONT ~ node.key;
IF Rope.Equal[name, font.name, FALSE]
AND TransformationEqual[m, font.m] THEN RETURN[font];
ENDLOOP;
font ← NEW[FontRep ← [name: name, m: m]];
data[hash] ← NEW[NodeRep ← [key: font, next: head]];
size ← size + 1;
RETURN[font];
};
GetSize:
PUBLIC
ENTRY
PROC
RETURNS[
CARDINAL] =
returns number of key-value pairs in table
{RETURN [size]};
Enumerate:
PUBLIC
PROC[action:
PROC[
FONT]
RETURNS[
BOOL]]
RETURNS[quit:
BOOL] = {
enumerates fonts currently registered in unspecified order
fonts registered during enumeration may or may not be seen
applies action to each pair until action returns TRUE or no more pairs
returns TRUE if some action returns TRUE
node: Node ← NIL;
index: CARDINAL ← 0;
DO
[node, index] ← GetNext[node, index];
IF node = NIL THEN RETURN [FALSE];
IF action[node.key] THEN RETURN [TRUE];
ENDLOOP;
};
GetNext:
ENTRY
PROC[node: Node, index:
CARDINAL]
RETURNS[Node,
CARDINAL] = {
ENABLE UNWIND => NULL;
IF node #
NIL
THEN {
node ← node.next;
IF node # NIL THEN RETURN [node, index];
index ← index + 1;
}
ELSE index ← 0;
WHILE index < mod
DO
node ← data[index];
IF node = NIL THEN {index ← index + 1; LOOP};
RETURN [node, index];
ENDLOOP;
RETURN [NIL, mod];
};
END.