<> <<>> <> <> 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]; <> <<================>> 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 { <> <> <<{c0: CARDINAL = Ascii.Lower[Rope.InlineFetch[s, 0]] - 0C;>> <> <> 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] = <> {RETURN [size]}; Enumerate: PUBLIC PROC[action: PROC[FONT] RETURNS[BOOL]] RETURNS[quit: BOOL] = { <> <> <> <> 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.