ListHyphenationImpl.mesa
Copyright Ó 1986 by Xerox Corporation. All rights reserved.
Michael Plass, May 9, 1986 12:07:36 pm PDT
Registers a hyphenation routine with Tioga that looks for an explicit list of hyphenations on the node properties.
To use:
1. Run this program.
2. Add a node property with the key "HyphenationList" and the value consisting of a list of hyphenations ("-" between syllables, " " between words). This property applies to the node and everything under it.
3. Place the style rule
(List) hyphenation
so that it will be effective on the desired node. (Use a Postfix property, for example).
4. A hyphenation point may also be marked by using the discretionary hyphen character (357|043); this is used in the word "demonstrate" below, and overrides the rule in the list.
I won't vouch for the accuracy of the hyphenations in this example.
Example:
<<NodeLevel: 3, Comment: TRUE, CharProps: ..., Postfix: (List) hyphenation 1.7 in lineLength, HyphenationList: app-lic-a-bil-ity Ex-empl-ary de-mon-strate mat-er-ial hyph-en-ation tech-niques text-u-al ses-qui-ped-el-i-an >>
Exemplary textual material to dem#onstrate the applicability of hyphenation techniques to sesquipedelian words.
DIRECTORY NodeProps, NodePropsExtras, RefText, Rope, RopeReader, SymTab, TEditFormatExtras, TextNode, TextEdit;
~
BEGIN
ROPE: TYPE ~ Rope.ROPE;
HyphenationPositions:
TYPE ~ TEditFormatExtras.HyphenationPositions;
ListHyphenation:
PROC [node: TextNode.Ref, start, len:
INT, hyphData:
REF]
RETURNS [HyphenationPositions] ~ {
h: HyphenationPositions ← ALL[0];
j: NAT ← 0;
scratch: REF TEXT ~ RefText.ObtainScratch[512];
FOR i:
NAT
IN [0..
NAT[
MIN[len, scratch.maxLength]])
DO
set: [0..256); char: CHAR;
[charSet: set, char: char] ← TextEdit.Fetch[node, start+i];
scratch[i] ← char; scratch.length ← i+1;
IF set = 357B
AND char=43C
THEN {
discretionary hyphen
IF j < TEditFormatExtras.maxHyph THEN {h[j] ← i+1; j ← j+1};
};
ENDLOOP;
IF j = 0
THEN {
FOR p: TextNode.Ref ← node, TextNode.Parent[p]
UNTIL p =
NIL
DO
dict: SymTab.Ref ← NIL;
prop: REF ~ NodeProps.GetProp[p, $HyphenationList];
v: REF ← NIL;
WITH prop
SELECT
FROM
s: SymTab.Ref => dict ← s;
r: ROPE => NodeProps.PutProp[p, $HyphenationList, (dict ← Internalize[r])];
ENDCASE => NULL;
IF dict #
NIL
THEN {
v ← SymTab.FetchText[dict, scratch].val;
WITH v
SELECT
FROM
vh: REF HyphenationPositions => {h ← vh^; EXIT};
ENDCASE => NULL;
};
ENDLOOP;
};
RefText.ReleaseScratch[scratch];
RETURN [h]
};
Internalize:
PROC [rope:
ROPE]
RETURNS [SymTab.Ref] ~ {
scratch: REF TEXT ~ RefText.ObtainScratch[512];
symTab: SymTab.Ref ← SymTab.Create[101, FALSE];
ropeReader: RopeReader.Ref ~ RopeReader.GetRopeReader[];
c: CHAR;
RopeReader.SetPosition[ropeReader, rope];
RopeReader.SetCharForEndOfRope[ropeReader, 0C];
c ← RopeReader.Get[ropeReader];
WHILE c IN (0C..' ] DO c ← RopeReader.Get[ropeReader] ENDLOOP;
UNTIL c = 0C
DO
h: HyphenationPositions ← ALL[0];
j: NAT ← 0;
i: NAT ← 0;
WHILE c > '
DO
IF c = '-
THEN {IF j < TEditFormatExtras.maxHyph THEN {h[j] ← i; j ← j+1}}
ELSE {IF i < scratch.maxLength THEN {scratch[i] ← c; scratch.length ← i ← i + 1}};
c ← RopeReader.Get[ropeReader];
ENDLOOP;
IF j > 0
THEN {
key: ROPE ~ Rope.FromRefText[scratch];
val: REF ~ NEW[HyphenationPositions ← h];
[] ← SymTab.Insert[symTab, key, val];
};
WHILE c IN (0C..' ] DO c ← RopeReader.Get[ropeReader] ENDLOOP;
ENDLOOP;
RopeReader.FreeRopeReader[ropeReader];
RefText.ReleaseScratch[scratch];
IF SymTab.GetSize[symTab] = 0 THEN symTab ← NIL;
RETURN [symTab];
};
Externalize:
PROC [symTab: SymTab.Ref]
RETURNS [
ROPE] ~ {
rope: ROPE ← NIL;
buf: REF TEXT ← RefText.ObtainScratch[512];
Put:
PROC [r:
ROPE, start, end:
NAT] ~ {
IF end < start THEN RETURN;
IF end-start+buf.length > buf.maxLength
THEN {
rope ← rope.Concat[Rope.FromRefText[buf]];
buf.length ← 0;
};
[] ← Rope.AppendChars[buf, r, start, end-start];
};
ForEachPair:
PROC [key:
ROPE, val:
REF]
RETURNS [quit:
BOOL ← FALSE] ~ {
WITH val
SELECT
FROM
v:
REF HyphenationPositions => {
h: HyphenationPositions ~ v^;
from: NAT ← 0;
FOR j:
NAT
IN [0..TEditFormatExtras.maxHyph)
DO
IF h[j] = 0 THEN EXIT;
Put[key, from, h[j]];
Put["-", 0, 1];
from ← h[j];
ENDLOOP;
Put[key, from, Rope.Size[key]];
Put[" ", 0, 1];
};
ENDCASE => NULL;
};
[] ← SymTab.Pairs[symTab, ForEachPair];
rope ← rope.Concat[Rope.FromRefText[buf]];
RefText.ReleaseScratch[buf];
RETURN [rope];
};
ReadSpecs: NodeProps.ReadSpecsProc ~ { value ← Internalize[specs] };
WriteSpecs: NodeProps.WriteSpecsProc ~ {
WITH value
SELECT
FROM
symTab: SymTab.Ref => specs ← Externalize[symTab];
ENDCASE => specs ← NIL;
};
NodeProps.Register[$HyphenationList, ReadSpecs, WriteSpecs, NIL];
NodePropsExtras.DeclarePropertyAttribute[$HyphenationList, $Visible];
[] ← TEditFormatExtras.RegisterHyphenation[$List, ListHyphenation, NIL];
Note: This is a temporary hack until a real hyphenation routine for English is provided. It is here because (English) hyphenation is used in Cedar.style.
[] ← TEditFormatExtras.RegisterHyphenation[$English, ListHyphenation, NIL];