FontRegistryImpl.mesa
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.