XCFontsImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
Michael Plass, June 27, 1986 11:43:35 am PDT
Rick Beach, February 27, 1986 9:02:55 am PST
Doug Wyatt, June 6, 1986 2:12:57 pm PDT
DIRECTORY
Imager USING [Box, Context, Error, MaskBox],
ImagerBox USING [BoxFromExtents, ExtentsFromBox],
ImagerFont USING [CorrectionType, Extents, nullXChar, VEC, XChar],
ImagerFontFilter USING [CharacterCodeMap, CharRangeMap, FontMap, OutputMap],
ImagerTypeface USING [Find, GenericCreator, GenericCreatorRep, RegisterGenericCreator, Typeface, TypefaceClass, TypefaceClassRep, TypefaceRep],
Rope USING [Concat, Equal, Index, Match, ROPE, Substr, Translate];
XCFontsImpl: CEDAR PROGRAM
IMPORTS Imager, ImagerTypeface, Rope, ImagerBox
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
VEC: TYPE ~ ImagerFont.VEC;
XChar: TYPE ~ ImagerFont.XChar;
nullXChar: XChar ~ ImagerFont.nullXChar;
Extents: TYPE ~ ImagerFont.Extents;
Typeface: TYPE ~ ImagerTypeface.Typeface;
GenericCreator: TYPE ~ ImagerTypeface.GenericCreator;
GenericCreatorRep: TYPE ~ ImagerTypeface.GenericCreatorRep;
CharacterCodeMap: TYPE ~ ImagerFontFilter.CharacterCodeMap;
XCGenericCreator: PROC [self: GenericCreator, name: ROPE] RETURNS [typeface: Typeface ← NIL] ~ {
IF Rope.Match["xerox/xc0-0-0/*", name, FALSE]
OR Rope.Match["xerox/xc1-1-1/*", name, FALSE]
OR Rope.Match["xerox/xc1-2-2/*", name, FALSE]
OR Rope.Match["xerox/xc82-0-0/*", name, FALSE] -- obsolete font reference
THEN {
tname: ROPE ~ Rope.Translate[name]; -- in case name is really a REF TEXT!
rest: ROPE ~ Rope.Substr[tname, 1+Rope.Index[tname, 1+Rope.Index[tname, 0, "/"], "/"]];
xc1Name: ROPE ~ Rope.Concat["xerox/xc1-1-1/", rest];
boundOutputMap: BoundOutputMap ~ FindMapping[xc1Name];
IF boundOutputMap # NIL THEN {
typeface ← NEW[ImagerTypeface.TypefaceRep ← [
class: charMapClass,
data: boundOutputMap,
name: tname
]];
};
};
};
charMapClass: ImagerTypeface.TypefaceClass ~ NEW[ImagerTypeface.TypefaceClassRep ← [
type: $CharMapper,
Contains: CharMapperContains,
NextChar: CharMapperNextChar,
Width: CharMapperWidth,
Amplified: CharMapperAmplified,
Correction: CharMapperCorrection,
BoundingBox: CharMapperBoundingBox,
FontBoundingBox: CharMapperFontBoundingBox,
Ligature: CharMapperLigature,
Kern: CharMapperKern,
NextKern: CharMapperNextKern,
Mask: CharMapperMask
]];
CharMapperContains: PROC [self: Typeface, char: XChar] RETURNS [BOOL] ~ {
boundMap: BoundOutputMap ~ NARROW[self.data];
x: TChar ~ MapChar[boundMap, char];
RETURN [x.t # NIL]
};
CharMapperNextChar: PROC [self: Typeface, char: XChar] RETURNS [next: XChar] ~ {
ch: WORDLOOPHOLE[char, WORD]+1;
UNTIL self.class.Contains[self, LOOPHOLE[ch]] OR ch = WORD.LAST DO ch ← ch + 1 ENDLOOP;
next ← LOOPHOLE[ch];
};
CharMapperWidth: PROC [self: Typeface, char: XChar] RETURNS [VEC] ~ {
boundMap: BoundOutputMap ~ NARROW[self.data];
x: TChar ~ MapChar[boundMap, char];
IF x.t = NIL THEN RETURN [[0.5, 0]];
RETURN [x.t.class.Width[x.t, x.char]];
};
CharMapperAmplified: PROC [self: Typeface, char: XChar] RETURNS [BOOL] ~ {
boundMap: BoundOutputMap ~ NARROW[self.data];
x: TChar ~ MapChar[boundMap, char];
IF x.t = NIL THEN RETURN [FALSE];
RETURN [x.t.class.Amplified[x.t, x.char]];
};
CharMapperCorrection: PROC [self: Typeface, char: XChar] RETURNS [ImagerFont.CorrectionType] ~ {
boundMap: BoundOutputMap ~ NARROW[self.data];
x: TChar ~ MapChar[boundMap, char];
IF x.t = NIL THEN RETURN [none];
RETURN [x.t.class.Correction[x.t, x.char]];
};
defaultExtents: Extents ~ [leftExtent: -0.1, rightExtent: 0.4, descent: 0, ascent: 0.7];
CharMapperBoundingBox: PROC [self: Typeface, char: XChar] RETURNS [Extents] ~ {
boundMap: BoundOutputMap ~ NARROW[self.data];
x: TChar ~ MapChar[boundMap, char];
IF x.t = NIL THEN RETURN [defaultExtents];
RETURN [x.t.class.BoundingBox[x.t, x.char]];
};
CharMapperFontBoundingBox: PROC [self: Typeface] RETURNS [Extents] ~ {
boundMap: BoundOutputMap ~ NARROW[self.data];
box: Imager.Box ← [999999, 999999, -999999, -999999];
BoundPoint: PROC [x, y: REAL] ~ INLINE {
IF x < box.xmin THEN box.xmin ← x;
IF x > box.xmax THEN box.xmax ← x;
IF y < box.ymin THEN box.ymin ← y;
IF y > box.ymax THEN box.ymax ← y;
};
FOR b: BoundOutputMap ← boundMap, b.rest UNTIL b = NIL DO
e: Extents ← b.first.newTypeface.class.FontBoundingBox[b.first.newTypeface];
bb: Imager.Box ← ImagerBox.BoxFromExtents[e];
BoundPoint[bb.xmin, bb.ymin];
BoundPoint[bb.xmax, bb.ymax];
ENDLOOP;
IF box.xmin > box.xmax THEN RETURN [[0,0,0,0]];
RETURN [ImagerBox.ExtentsFromBox[box]]
};
CharMapperLigature: PROC [self: Typeface, char, successor: XChar] RETURNS [XChar] ~ {
RETURN [nullXChar]
};
CharMapperNextLigature: PROC [self: Typeface, char, successor: XChar] RETURNS [XChar] ~ {
RETURN [nullXChar]
};
CharMapperKern: PROC [self: Typeface, char, successor: XChar] RETURNS [VEC] ~ {
RETURN [[0, 0]]
};
CharMapperNextKern: PROC [self: Typeface, char, successor: XChar] RETURNS [XChar] ~ {
RETURN [nullXChar]
};
CharMapperMask: PROC [self: Typeface, char: XChar, context: Imager.Context] ~ {
boundMap: BoundOutputMap ~ NARROW[self.data];
x: TChar ~ MapChar[boundMap, char];
IF x.t = NIL THEN Imager.MaskBox[context, ImagerBox.BoxFromExtents[defaultExtents]]
ELSE x.t.class.Mask[x.t, x.char, context];
};
BoundOutputMap: TYPE ~ LIST OF BoundOutputMapEntry;
BoundOutputMapEntry: TYPE ~ RECORD [
newTypeface: Typeface, charMap: CharacterCodeMap
];
FindMapping: PROC [name: ROPE] RETURNS [BoundOutputMap] ~ {
head, tail: BoundOutputMap ← NIL;
outputMap: ImagerFontFilter.OutputMap ← NIL;
warn: BOOLFALSE;
FOR p: ImagerFontFilter.FontMap ← xc1ToPressMap, p.rest UNTIL p=NIL DO
IF Rope.Equal[name, p.first.inputName, FALSE] THEN {
outputMap ← p.first.output;
warn ← p.first.warn;
EXIT;
};
ENDLOOP;
IF outputMap # NIL THEN {
FOR o: ImagerFontFilter.OutputMap ← outputMap, o.rest UNTIL o=NIL DO
newTypeface: Typeface ← NIL;
newTypeface ← ImagerTypeface.Find[o.first.newName ! Imager.Error => CONTINUE];
IF newTypeface # NIL THEN {
prev: BoundOutputMap ~ tail;
tail ← CONS[[newTypeface: newTypeface, charMap: o.first.charMap], NIL];
IF prev=NIL THEN head ← tail ELSE prev.rest ← tail;
};
ENDLOOP;
};
RETURN[head];
};
TChar: TYPE ~ RECORD [t: Typeface, char: XChar];
MapChar: PROC [boundMap: BoundOutputMap, char: XChar] RETURNS [TChar] ~ {
charCode: WORDLOOPHOLE[char];
FOR b: BoundOutputMap ← boundMap, b.rest UNTIL b = NIL DO
FOR c: CharacterCodeMap ← b.first.charMap, c.rest UNTIL c = NIL DO
IF charCode IN [c.first.bc..c.first.ec] THEN {
result: TChar ← [t: b.first.newTypeface, char: LOOPHOLE[c.first.newbc+(charCode-c.first.bc)]];
IF result.t.class.Contains[result.t, result.char] THEN RETURN[result] ELSE EXIT;
};
ENDLOOP;
ENDLOOP;
RETURN [[NIL, [0, 0]]];
};
nMaps: NAT ~ 3;
MapIndex: TYPE ~ [0..nMaps);
MapArray: TYPE ~ ARRAY MapIndex OF CharacterCodeMap;
BYTE: TYPE ~ [0..377B];
MakeMaps: PROC RETURNS [MapArray] ~ {
head: MapArray ← ALL[NIL];
tail: MapArray ← ALL[NIL];
Add: PROC [m: MapIndex, ch: BYTE, set: BYTE, bc: BYTE, ec: BYTE ← 0] ~ {
range: ImagerFontFilter.CharRangeMap ~ [
bc: set*400B+bc, ec: set*400B+MAX[bc, ec], newbc: ch];
new: CharacterCodeMap ~ CONS[range, NIL];
IF tail[m]=NIL THEN head[m] ← new ELSE tail[m].rest ← new;
tail[m] ← new;
};
Add[0, 040B, 000B, 040B]; -- space
Add[0, 041B, 000B, 041B]; -- exclamation point
Add[1, 047B, 000B, 042B]; -- neutral (vertical) double quote
Add[0, 043B, 000B, 043B]; -- number sign
Add[1, 051B, 000B, 044B]; -- general (international) currency symbol
Add[0, 045B, 000B, 045B]; -- percent sign
Add[0, 046B, 000B, 046B]; -- ampersand
Add[1, 046B, 000B, 047B]; -- apostrophe
Add[0, 050B, 000B, 050B]; -- opening parenthesis
Add[0, 051B, 000B, 051B]; -- closing parenthesis
Add[0, 052B, 000B, 052B]; -- asterisk
Add[0, 053B, 000B, 053B]; -- plus sign
Add[0, 054B, 000B, 054B]; -- comma
Add[0, 235B, 000B, 055B]; -- minus sign
Add[0, 056B, 000B, 056B]; -- period = full stop
Add[0, 057B, 000B, 057B]; -- slant = solidus = virgule = slash
Add[0, 060B, 000B, 060B, 071B]; -- digits 0 to 9
Add[0, 072B, 000B, 072B]; -- colon
Add[0, 073B, 000B, 073B]; -- semicolon
Add[0, 074B, 000B, 074B]; -- less than
Add[0, 075B, 000B, 075B]; -- equals
Add[0, 076B, 000B, 076B]; -- greater than
Add[0, 077B, 000B, 077B]; -- question mark
Add[0, 100B, 000B, 100B]; -- commercial at sign
Add[0, 101B, 000B, 101B, 132B]; -- uppercase Latin (Roman) letters A to Z
Add[0, 133B, 000B, 133B]; -- opening bracket
Add[0, 134B, 000B, 134B]; -- reverse slant = backslash = reverse solidus = reverse virgule
Add[0, 135B, 000B, 135B]; -- closing bracket
Add[0, 254B, 000B, 136B]; -- circumflex accent (spacing)
Add[0, 277B, 000B, 137B]; -- low bar (spacing)
Add[0, 252B, 000B, 140B]; -- grave accent (spacing)
Add[0, 141B, 000B, 141B, 172B]; -- lowercase Latin (Roman) letters a to z
Add[0, 173B, 000B, 173B]; -- opening brace
Add[0, 174B, 000B, 174B]; -- vertical bar
Add[0, 175B, 000B, 175B]; -- closing brace
Add[0, 255B, 000B, 176B]; -- tilde (spacing)
Add[0, 275B, 000B, 241B]; -- inverted exclamation point (Spanish)
Add[0, 260B, 000B, 242B]; -- cent sign
Add[0, 261B, 000B, 243B]; -- Pound-Sterling sign
Add[0, 044B, 000B, 244B]; -- dollar sign
Add[1, 247B, 000B, 245B]; -- Yen sign (Japanese)
Add[0, 266B, 000B, 247B]; -- section sign
Add[0, 140B, 000B, 251B]; -- left single quote = single quote open
Add[0, 264B, 000B, 252B]; -- left double quote
Add[0, 335B, 000B, 253B]; -- left double guillemet (European)
Add[0, 137B, 000B, 254B]; -- west arrow
Add[0, 136B, 000B, 255B]; -- north arrow
Add[1, 057B, 000B, 256B]; -- east arrow
Add[1, 056B, 000B, 257B]; -- south arrow
Add[0, 300B, 000B, 260B]; -- degree sign
Add[0, 274B, 000B, 261B]; -- plus/minus sign
Add[2, 362B, 000B, 262B]; -- superscript 2
Add[2, 363B, 000B, 263B]; -- superscript 3
Add[0, 372B, 000B, 264B]; -- multiply sign
Add[?, ???B, 000B, 265B]; -- micro sign
Add[0, 272B, 000B, 266B]; -- paragraph sign = pilcrow
Add[0, 375B, 000B, 267B]; -- centered dot
Add[0, 273B, 000B, 270B]; -- divide sign
Add[0, 047B, 000B, 271B]; -- right single quote = single quote closed
Add[0, 042B, 000B, 272B]; -- right double quote
Add[0, 336B, 000B, 273B]; -- right double guillemet (European)
Add[0, 342B, 000B, 274B]; -- fraction, 1/4
Add[0, 344B, 000B, 275B]; -- fraction, 1/2
Add[0, 346B, 000B, 276B]; -- fraction, 3/4
Add[0, 276B, 000B, 277B]; -- inverted question mark (Spanish)
Add[0, 252B, 000B, 301B]; -- grave accent
Add[0, 253B, 000B, 302B]; -- acute accent = phonetic stress mark
Add[0, 254B, 000B, 303B]; -- circumflex accent = hat
Add[0, 255B, 000B, 304B]; -- tilde accent
Add[0, 257B, 000B, 305B]; -- macron accent = long vowel mark
Add[0, 256B, 000B, 306B]; -- breve accent
Add[0, 351B, 000B, 307B]; -- over-dot accent
Add[0, 250B, 000B, 310B]; -- diaeresis accent = umlaut
Add[0, 251B, 000B, 312B]; -- over-ring accent
Add[0, 210B, 000B, 313B]; -- cedilla undermark
Add[?, ???B, 000B, 314B]; -- underline (non-spacing undermark)
Add[0, 352B, 000B, 315B]; -- double acute accent
Add[0, 213B, 000B, 316B]; -- Ogonek undermark = Polish hook
Add[0, 350B, 000B, 317B]; -- Hachek accent = caron
Add[?, ???B, 000B, 320B]; -- horizontal bar
Add[2, 361B, 000B, 321B]; -- superscript 1
Add[1, 147B, 000B, 322B]; -- registered sign
Add[1, 146B, 000B, 323B]; -- copyright sign
Add[1, 241B, 000B, 324B]; -- trademark sign (TM)
Add[2, 200B, 000B, 325B]; -- music note
Add[0, 341B, 000B, 334B]; -- fraction, 1/8
Add[0, 343B, 000B, 335B]; -- fraction, 3/8
Add[0, 345B, 000B, 336B]; -- fraction, 5/8
Add[0, 347B, 000B, 337B]; -- fraction, 7/8
Add[?, ???B, 000B, 340B]; -- ohm sign
Add[0, 206B, 000B, 341B]; -- uppercase AE digraph
Add[2, 104B, 000B, 342B]; -- uppercase D with stroke (Croatian)
Add[?, ???B, 000B, 343B]; -- feminine Spanish ordinal indicator
Add[2, 110B, 000B, 344B]; -- uppercase H with stroke (Maltese)
Add[0, 227B, 000B, 346B]; -- uppercase IJ digraph (Dutch)
Add[2, 112B, 000B, 347B]; -- uppercase L with middle dot (Catalan)
Add[2, 114B, 000B, 350B]; -- uppercase L with stroke (Polish)
Add[0, 205B, 000B, 351B]; -- uppercase O with slash (Norwegian, Danish)
Add[0, 207B, 000B, 352B]; -- uppercase OE digraph
Add[?, ???B, 000B, 353B]; -- masculine Spanish ordinal indicator
Add[2, 120B, 000B, 354B]; -- uppercase Thorn (Icelandic)
Add[2, 124B, 000B, 355B]; -- uppercase T with stroke (Lapp)
Add[2, 116B, 000B, 356B]; -- uppercase Eng (Lapp)
Add[1, 130B, 000B, 357B]; -- lowercase n with apostrophe (South African)
Add[2, 153B, 000B, 360B]; -- lowercase k (Greenlandic)
Add[0, 246B, 000B, 361B]; -- lowercase ae digraph
Add[2, 144B, 000B, 362B]; -- lowercase d with stroke (Croatian)
Add[2, 145B, 000B, 363B]; -- lowercase Eth (Icelandic)
Add[2, 150B, 000B, 364B]; -- lowercase h with stroke (Maltese)
Add[0, 376B, 000B, 365B]; -- lowercase dotless i (Turkish)
Add[0, 226B, 000B, 366B]; -- lowercase ij digraph (Dutch)
Add[2, 152B, 000B, 367B]; -- lowercase l with middle dot (Catalan)
Add[2, 154B, 000B, 370B]; -- lowercase l with stroke (Polish)
Add[0, 245B, 000B, 371B]; -- lowercase o with slash (Norwegian, Danish)
Add[0, 247B, 000B, 372B]; -- lowercase oe digraph
Add[0, 225B, 000B, 373B]; -- double s = ess-zed = sharp s (German)
Add[2, 160B, 000B, 374B]; -- lowercase Thorn (Icelandic)
Add[2, 164B, 000B, 375B]; -- lowercase t with stroke (Lapp)
Add[2, 156B, 000B, 376B]; -- lowercase Eng (Lapp)
Add[0, 211B, 041B, 042B]; -- Japanese comma = Chinese comma (???)
Add[0, 212B, 041B, 043B]; -- Japanese period = Chinese period (???)
Add[0, 055B, 041B, 076B]; -- hyphen
Add[1, 110B, 041B, 102B]; -- parallel sign, type 1 = double vertical bar
Add[1, 162B, 041B, 142B]; -- does not equal
Add[1, 100B, 041B, 145B]; -- less than or equal to
Add[1, 101B, 041B, 146B]; -- greater than or equal to
Add[1, 161B, 041B, 147B]; -- infinity
Add[1, 156B, 041B, 150B]; -- therefore
Add[1, 126B, 041B, 154B]; -- minutes sign = feet sign = prime sign = phonetic stress sign
Add[1, 127B, 041B, 155B]; -- seconds sign = double prime = inches sign
Add[0, 265B, 041B, 172B]; -- black star
Add[1, 120B, 042B, 042B]; -- ballot box = wave operator = white square
Add[0, 236B, 356B, 056B]; -- decimal point (???)
Add[0, 174B, 356B, 174B]; -- absolute value = such that, type 2
Add[0, 176B, 356B, 176B]; -- similar to = equivalent to
Add[0, 040B, 357B, 041B]; -- non-breaking space
Add[0, 055B, 357B, 042B]; -- non-breaking hyphen
Add[0, 055B, 357B, 043B]; -- discretionary hyphen
Add[0, 233B, 357B, 044B]; -- en dash (??? approximate with figure dash)
Add[0, 234B, 357B, 045B]; -- em dash
Add[0, 233B, 357B, 046B]; -- figure dash
Add[1, 046B, 357B, 047B]; -- neutral single quote
Add[0, 374B, 357B, 050B]; -- lowered left double quote (European usage)
Add[0, 264B, 357B, 051B]; -- German right double quote
Add[0, 333B, 357B, 052B]; -- single guillemet left quote
Add[0, 334B, 357B, 053B]; -- single guillemet right quote
Add[0, 230B, 357B, 054B]; -- en quad
Add[0, 231B, 357B, 055B]; -- em quad
Add[0, 232B, 357B, 056B]; -- figure space = numeric space
Add[0, 237B, 357B, 057B]; -- thin space = 5-em space
Add[0, 270B, 357B, 060B]; -- dagger
Add[0, 271B, 357B, 061B]; -- double dagger
Add[1, 062B, 357B, 062B]; -- bra
Add[1, 063B, 357B, 063B]; -- ket
Add[1, 066B, 357B, 066B]; -- left perpendicular
Add[1, 067B, 357B, 067B]; -- right perpendicular
Add[1, 070B, 357B, 070B]; -- left 2 perpendicular
Add[1, 071B, 357B, 071B]; -- right 2 perpendicular
Add[2, 173B, 357B, 072B]; -- left white lenticular bracket (Chinese)
Add[2, 175B, 357B, 073B]; -- right white lenticular bracket (Chinese)
Add[1, 074B, 357B, 074B]; -- northwest arrow
Add[1, 076B, 357B, 075B]; -- southeast arrow
Add[1, 077B, 357B, 076B]; -- northeast arrow
Add[1, 075B, 357B, 077B]; -- southwest arrow
Add[1, 060B, 357B, 100B]; -- care of
Add[0, 373B, 357B, 101B]; -- per thousand = per mil
Add[1, 102B, 357B, 102B]; -- much less than
Add[1, 103B, 357B, 103B]; -- much greater than
Add[1, 104B, 357B, 104B]; -- not less than
Add[1, 105B, 357B, 105B]; -- not greater than
Add[1, 106B, 357B, 106B]; -- divides
Add[1, 107B, 357B, 107B]; -- does not divide
Add[2, 057B, 357B, 110B]; -- double slash = parallel sign, type 2
Add[1, 111B, 357B, 111B]; -- not parallel
Add[1, 112B, 357B, 112B]; -- is a member of
Add[1, 113B, 357B, 113B]; -- is not a member of
Add[1, 132B, 357B, 114B]; -- such that, type 1 = contains as a member
Add[1, 115B, 357B, 115B]; -- double back arrow = is implied by
Add[1, 116B, 357B, 116B]; -- double double arrow = iff
Add[1, 117B, 357B, 117B]; -- double right arrow = implies
Add[1, 136B, 357B, 120B]; -- reversible reaction, type 2
Add[1, 134B, 357B, 121B]; -- reversible reaction, type 1 = electric current
Add[1, 114B, 357B, 122B]; -- double arrow
Add[1, 135B, 357B, 123B]; -- curly arrow
Add[1, 222B, 357B, 124B]; -- contains, type 1
Add[1, 223B, 357B, 125B]; -- contained in, type 1
Add[1, 224B, 357B, 126B]; -- intersection
Add[1, 225B, 357B, 127B]; -- union = sum or union of all classes (math logic) or sets (algebra)
Add[1, 272B, 357B, 130B]; -- contains or equals
Add[1, 273B, 357B, 131B]; -- contained in or equals
Add[1, 274B, 357B, 132B]; -- properly includes in set = contains, type 2
Add[1, 275B, 357B, 133B]; -- proper inclusion in set = contained in, type 2
Add[1, 312B, 357B, 134B]; -- neither contains nor is equal to = does not contain as a subset
Add[1, 313B, 357B, 135B]; -- neither contained in nor is equal to
Add[1, 314B, 357B, 136B]; -- does not contain = does not properly include in set
Add[1, 315B, 357B, 137B]; -- is not contained in = non-proper inclusion in set
Add[1, 121B, 357B, 140B]; -- checked ballot box
Add[1, 133B, 357B, 141B]; -- null set
Add[1, 142B, 357B, 142B]; -- abstract + = Earth = sign of composition
Add[1, 143B, 357B, 143B]; -- abstract -
Add[1, 144B, 357B, 144B]; -- abstract X
Add[1, 145B, 357B, 145B]; -- abstract /
Add[0, 267B, 357B, 146B]; -- centered bullet
Add[1, 151B, 357B, 147B]; -- centered ring
Add[1, 262B, 357B, 150B]; -- Planck's constant
Add[1, 220B, 357B, 151B]; -- liter
Add[1, 160B, 357B, 152B]; -- not
Add[1, 061B, 357B, 153B]; -- broken vertical bar
Add[1, 154B, 357B, 154B]; -- angle
Add[1, 155B, 357B, 155B]; -- spherical angle
Add[2, 072B, 357B, 156B]; -- identifier
Add[1, 157B, 357B, 157B]; -- because
Add[1, 264B, 357B, 160B]; -- perpendicular
Add[1, 265B, 357B, 161B]; -- is proportional to
Add[1, 163B, 357B, 162B]; -- identically equal = equivalent
Add[1, 164B, 357B, 163B]; -- equal by definition
Add[1, 165B, 357B, 164B]; -- questioned equality
Add[1, 166B, 357B, 165B]; -- integral
Add[1, 167B, 357B, 166B]; -- contour integral
Add[1, 170B, 357B, 167B]; -- asymptotically equal to = approximately equal, type 1
Add[2, 270B, 357B, 170B]; -- isomorphic = congruent
Add[1, 171B, 357B, 171B]; -- asymptotic to = approximately equal, type 2
Add[1, 041B, 357B, 172B]; -- summation
Add[1, 042B, 357B, 173B]; -- product
Add[1, 174B, 357B, 174B]; -- radical = root
Add[1, 175B, 357B, 175B]; -- minus or plus
Add[1, 246B, 357B, 241B]; -- Cruzeiro (Brazilian)
Add[0, 263B, 357B, 242B]; -- Florin = Guilder (Dutch)
Add[0, 262B, 357B, 243B]; -- Francs
Add[1, 245B, 357B, 244B]; -- Pesetas (Spanish)
Add[2, 240B, 357B, 245B]; -- European currency symbol
Add[2, 044B, 357B, 246B]; -- Milreis = Escudo (Portugese)
Add[1, 050B, 357B, 247B]; -- generic infinity sign
Add[1, 266B, 357B, 250B]; -- number
Add[?, ???B, 357B, 251B]; -- take
Add[1, 242B, 357B, 252B]; -- TEL (telephone)
Add[?, ???B, 357B, 253B]; -- Yogh (Old English) = dram = IPA "zh" sound
Add[1, 267B, 357B, 254B]; -- complex number
Add[1, 270B, 357B, 255B]; -- natural number
Add[1, 271B, 357B, 256B]; -- real number = reluctance
Add[2, 132B, 357B, 257B]; -- integer
Add[1, 052B, 357B, 260B]; -- left ceiling
Add[1, 053B, 357B, 261B]; -- right ceiling
Add[1, 072B, 357B, 262B]; -- left floor
Add[1, 073B, 357B, 263B]; -- right floor
Add[1, 152B, 357B, 264B]; -- there exists
Add[1, 153B, 357B, 265B]; -- for all
Add[1, 172B, 357B, 266B]; -- and
Add[1, 173B, 357B, 267B]; -- or
Add[1, 137B, 357B, 270B]; -- QED
Add[1, 260B, 357B, 271B]; -- nabla = del = differential operator
Add[1, 261B, 357B, 272B]; -- partial derivative
Add[2, 133B, 357B, 273B]; -- OCR hook
Add[2, 134B, 357B, 274B]; -- OCR fork
Add[2, 135B, 357B, 275B]; -- OCR chair
Add[2, 101B, 357B, 276B]; -- alternating current
Add[?, ???B, 357B, 277B]; -- double low bar
Add[2, 266B, 357B, 300B]; -- arc
Add[1, 300B, 357B, 301B, 312B]; -- fixed-pitch Roman numerals I to X
Add[?, ???B, 357B, 313B]; -- spades
Add[?, ???B, 357B, 314B]; -- hearts
Add[?, ???B, 357B, 315B]; -- diamonds
Add[?, ???B, 357B, 316B]; -- clubs
Add[?, ???B, 357B, 317B]; -- check mark = yes
Add[?, ???B, 357B, 320B]; -- X mark = no
Add[1, 320B, 357B, 321B, 332B]; -- circled numbers 1 to 10
Add[2, 137B, 357B, 333B]; -- circled east arrow
Add[2, 136B, 357B, 334B]; -- circled east-then-south arrow
Add[2, 140B, 357B, 335B]; -- circled south-then-west arrow
Add[2, 100B, 357B, 336B]; -- peace symbol
Add[?, ???B, 357B, 337B]; -- smile face
Add[?, ???B, 357B, 340B]; -- skull & crossbones
Add[?, ???B, 357B, 341B]; -- thick vertical line
Add[?, ???B, 357B, 342B]; -- thick horizontal line
Add[?, ???B, 357B, 343B]; -- thick intersecting lines
Add[?, ???B, 357B, 344B]; -- thin vertical line
Add[?, ???B, 357B, 345B]; -- thin horizontal line
Add[?, ???B, 357B, 346B]; -- thin intersecting lines
Add[?, ???B, 357B, 347B]; -- sun = abstract multiplication
Add[?, ???B, 357B, 350B]; -- first quarter moon
Add[?, ???B, 357B, 351B]; -- third quarter moon
Add[?, ???B, 357B, 352B]; -- Mercury
Add[?, ???B, 357B, 353B]; -- Jupiter
Add[?, ???B, 357B, 354B]; -- Saturn
Add[?, ???B, 357B, 355B]; -- Uranus
Add[?, ???B, 357B, 356B]; -- Neptune
Add[?, ???B, 357B, 357B]; -- Pluto
Add[?, ???B, 357B, 360B]; -- Aquarius
Add[?, ???B, 357B, 361B]; -- Pisces
Add[?, ???B, 357B, 362B]; -- Aries
Add[?, ???B, 357B, 363B]; -- Taurus
Add[?, ???B, 357B, 364B]; -- Gemini
Add[?, ???B, 357B, 365B]; -- Cancer
Add[?, ???B, 357B, 366B]; -- Leo
Add[?, ???B, 357B, 367B]; -- Virgo
Add[?, ???B, 357B, 370B]; -- Libra
Add[?, ???B, 357B, 371B]; -- Scorpius = minim
Add[?, ???B, 357B, 372B]; -- Sagittarius
Add[?, ???B, 357B, 373B]; -- Capricorn
Add[?, ???B, 357B, 374B]; -- telephone symbol
Add[1, 054B, 357B, 375B]; -- fraction, 1/3
Add[1, 055B, 357B, 376B]; -- fraction, 2/3
Add[0, 220B, 360B, 041B, 045B]; -- ff, ffi, ffl, fi, fl ligatures
Add[0, 200B, 361B, 047B]; -- uppercase A diaeresis
Add[0, 202B, 361B, 050B]; -- uppercase A over-ring
Add[0, 204B, 361B, 055B]; -- uppercase C cedilla
Add[0, 201B, 361B, 124B]; -- uppercase O diaeresis
Add[0, 203B, 361B, 145B]; -- uppercase U diaeresis
Add[0, 240B, 361B, 247B]; -- lowercase a diaeresis
Add[0, 242B, 361B, 250B]; -- lowercase a over-ring
Add[0, 244B, 361B, 255B]; -- lowercase c cedilla
Add[0, 241B, 361B, 324B]; -- lowercase o diaeresis
Add[0, 243B, 361B, 345B]; -- lowercase u diaeresis
RETURN[head];
};
MakeCharSetMap: PROC [set: BYTE] RETURNS [CharacterCodeMap] ~ {
RETURN[LIST[
[bc: set*400B+040B, ec: set*400B+176B, newbc: 040B],
[bc: set*400B+241B, ec: set*400B+376B, newbc: 241B]
]];
};
MakeGachaMap: PROC RETURNS [CharacterCodeMap] ~ {
head, tail: CharacterCodeMap ← NIL;
Add: PROC [ch: BYTE, set: BYTE, bc: BYTE, ec: BYTE ← 0] ~ {
range: ImagerFontFilter.CharRangeMap ~ [
bc: set*400B+bc, ec: set*400B+MAX[bc, ec], newbc: ch];
new: CharacterCodeMap ~ CONS[range, NIL];
IF tail=NIL THEN head ← new ELSE tail.rest ← new;
tail ← new;
};
Add[040B, 000B, 040B, 043B]; -- space to number sign
Add[045B, 000B, 045B, 135B]; -- percent sign to closing bracket
Add[030B, 000B, 137B]; -- low bar (spacing)
Add[141B, 000B, 141B, 176B]; -- lowercase a to tilde
Add[044B, 000B, 244B]; -- dollar sign
Add[047B, 000B, 251B]; -- left single quote = single quote open
Add[042B, 000B, 252B]; -- left double quote
Add[137B, 000B, 254B]; -- west arrow
Add[136B, 000B, 255B]; -- north arrow
Add[047B, 000B, 271B]; -- right single quote = single quote closed
Add[042B, 000B, 272B]; -- right double quote
Add[055B, 041B, 076B]; -- hyphen
Add[174B, 356B, 174B]; -- absolute value = such that, type 2
Add[176B, 356B, 176B]; -- similar to = equivalent to
Add[040B, 357B, 041B]; -- non-breaking space
Add[055B, 357B, 042B]; -- non-breaking hyphen
Add[055B, 357B, 043B]; -- discretionary hyphen
Add[055B, 357B, 044B]; -- en dash (???)
Add[055B, 357B, 046B]; -- figure dash
Add[047B, 357B, 047B]; -- neutral single quote
Add[040B, 357B, 054B]; -- en quad (???)
Add[040B, 357B, 056B]; -- figure space = numeric space
RETURN[head];
};
maps: MapArray ← MakeMaps[];
mapGacha: CharacterCodeMap ← MakeGachaMap[];
map000: CharacterCodeMap ← MakeCharSetMap[000B];
map000WithoutSpace: CharacterCodeMap ← LIST[ -- omit 040
[bc: 000B*400B+041B, ec: 000B*400B+176B, newbc: 041B],
[bc: 000B*400B+241B, ec: 000B*400B+376B, newbc: 241B],
];
map041: CharacterCodeMap ← MakeCharSetMap[041B];
map042: CharacterCodeMap ← MakeCharSetMap[042B];
map046: CharacterCodeMap ← MakeCharSetMap[046B];
map047: CharacterCodeMap ← MakeCharSetMap[047B];
map356: CharacterCodeMap ← MakeCharSetMap[356B];
map357: CharacterCodeMap ← LIST[ -- omit 041, 054-057, 246
[bc: 357B*400B+042B, ec: 357B*400B+053B, newbc: 042B],
[bc: 357B*400B+060B, ec: 357B*400B+176B, newbc: 060B],
[bc: 357B*400B+241B, ec: 357B*400B+245B, newbc: 241B],
[bc: 357B*400B+247B, ec: 357B*400B+376B, newbc: 247B],
];
map360: CharacterCodeMap ← MakeCharSetMap[360B];
map361: CharacterCodeMap ← MakeCharSetMap[361B];
xc1ToPressMap: ImagerFontFilter.FontMap ← MakeXC1ToPressMap[];
MakeXC1ToPressMap: PROC RETURNS [ImagerFontFilter.FontMap] ~ {
head, tail: ImagerFontFilter.FontMap ← NIL;
Enter: PROC [inputName: ROPE, output: ImagerFontFilter.OutputMap, warn: BOOLFALSE] ~ {
prev: ImagerFontFilter.FontMap ~ tail;
tail ← CONS[[inputName: inputName, output: output, warn: warn], NIL];
IF prev=NIL THEN head ← tail ELSE prev.rest ← tail;
};
Enter[inputName: "Xerox/XC1-1-1/Classic", output: LIST[
[newName: "Xerox/Pressfonts/Classic-mrrc0", charMap: map000],
[newName: "Xerox/Pressfonts/Classic-mrrc41", charMap: map041],
[newName: "Xerox/Pressfonts/Classic-mrrc42", charMap: map042],
[newName: "Xerox/Pressfonts/Classic-mrrc46", charMap: map046],
[newName: "Xerox/Pressfonts/Classic-mrrc47", charMap: map047],
[newName: "Xerox/Pressfonts/Classic-mrrc356", charMap: map356],
[newName: "Xerox/Pressfonts/Classic-mrrc357", charMap: map357],
[newName: "Xerox/Pressfonts/Classic-mrrc360", charMap: map360],
[newName: "Xerox/Pressfonts/Classic-mrrc361", charMap: map361],
[newName: "Xerox/Pressfonts/Classic-mrr", charMap: maps[0]],
[newName: "Xerox/Pressfonts/ClassicPiOne-mrr", charMap: maps[1]]
]];
Enter[inputName: "Xerox/XC1-1-1/Classic-italic", output: LIST[
[newName: "Xerox/Pressfonts/Classic-mirc0", charMap: map000WithoutSpace],
[newName: "Xerox/Pressfonts/Classic-mirc41", charMap: map041],
[newName: "Xerox/Pressfonts/Classic-mirc46", charMap: map046],
[newName: "Xerox/Pressfonts/Classic-mirc356", charMap: map356],
[newName: "Xerox/Pressfonts/Classic-mirc357", charMap: map357],
[newName: "Xerox/Pressfonts/Classic-mirc360", charMap: map360],
[newName: "Xerox/Pressfonts/Classic-mirc361", charMap: map361],
[newName: "Xerox/Pressfonts/Classic-mir", charMap: maps[0]],
[newName: "Xerox/Pressfonts/ClassicPiOne-mir", charMap: maps[1]]
]];
Enter[inputName: "Xerox/XC1-1-1/Classic-bold", output: LIST[
[newName: "Xerox/Pressfonts/Classic-brrc0", charMap: map000WithoutSpace],
[newName: "Xerox/Pressfonts/Classic-brrc41", charMap: map041],
[newName: "Xerox/Pressfonts/Classic-brrc42", charMap: map042],
[newName: "Xerox/Pressfonts/Classic-brrc46", charMap: map046],
[newName: "Xerox/Pressfonts/Classic-brrc47", charMap: map047],
[newName: "Xerox/Pressfonts/Classic-brrc356", charMap: map356],
[newName: "Xerox/Pressfonts/Classic-brrc357", charMap: map357],
[newName: "Xerox/Pressfonts/Classic-brrc360", charMap: map360],
[newName: "Xerox/Pressfonts/Classic-brrc361", charMap: map361],
[newName: "Xerox/Pressfonts/Classic-brr", charMap: maps[0]],
[newName: "Xerox/Pressfonts/ClassicPiOne-brr", charMap: maps[1]]
]];
Enter[inputName: "Xerox/XC1-1-1/Modern", output: LIST[
[newName: "Xerox/Pressfonts/Modern-mrrc0", charMap: map000],
[newName: "Xerox/Pressfonts/Modern-mrrc41", charMap: map041],
[newName: "Xerox/Pressfonts/Modern-mrrc42", charMap: map042],
[newName: "Xerox/Pressfonts/Modern-mrrc356", charMap: map356],
[newName: "Xerox/Pressfonts/Modern-mrrc357", charMap: map357],
[newName: "Xerox/Pressfonts/Modern-mrrc360", charMap: map360],
[newName: "Xerox/Pressfonts/Modern-mrrc361", charMap: map361],
[newName: "Xerox/Pressfonts/Modern-mrr", charMap: maps[0]],
[newName: "Xerox/Pressfonts/ModernPiOne-mrr", charMap: maps[1]]
]];
Enter[inputName: "Xerox/XC1-1-1/Modern-italic", output: LIST[
[newName: "Xerox/Pressfonts/Modern-mirc0", charMap: map000],
[newName: "Xerox/Pressfonts/Modern-mirc41", charMap: map041],
[newName: "Xerox/Pressfonts/Modern-mirc356", charMap: map356],
[newName: "Xerox/Pressfonts/Modern-mirc357", charMap: map357],
[newName: "Xerox/Pressfonts/Modern-mirc360", charMap: map360],
[newName: "Xerox/Pressfonts/Modern-mirc361", charMap: map361],
[newName: "Xerox/Pressfonts/Modern-mir", charMap: maps[0]],
[newName: "Xerox/Pressfonts/ModernPiOne-mir", charMap: maps[1]]
]];
Enter[inputName: "Xerox/XC1-1-1/Modern-bold", output: LIST[
[newName: "Xerox/Pressfonts/Modern-brrc0", charMap: map000],
[newName: "Xerox/Pressfonts/Modern-brrc41", charMap: map041],
[newName: "Xerox/Pressfonts/Modern-brrc356", charMap: map356],
[newName: "Xerox/Pressfonts/Modern-brrc357", charMap: map357],
[newName: "Xerox/Pressfonts/Modern-brrc360", charMap: map360],
[newName: "Xerox/Pressfonts/Modern-brrc361", charMap: map361],
[newName: "Xerox/Pressfonts/Modern-brr", charMap: maps[0]],
[newName: "Xerox/Pressfonts/ModernPiOne-brr", charMap: maps[1]]
]];
Enter[inputName: "Xerox/XC1-1-1/Modern-bold-italic", output: LIST[
[newName: "Xerox/Pressfonts/Modern-birc0", charMap: map000],
[newName: "Xerox/Pressfonts/Modern-birc41", charMap: map041],
[newName: "Xerox/Pressfonts/Modern-birc356", charMap: map356],
[newName: "Xerox/Pressfonts/Modern-birc357", charMap: map357],
[newName: "Xerox/Pressfonts/Modern-birc360", charMap: map360],
[newName: "Xerox/Pressfonts/Modern-birc361", charMap: map361],
[newName: "Xerox/Pressfonts/Modern-bir", charMap: maps[0]],
[newName: "Xerox/Pressfonts/ModernPiOne-bir", charMap: maps[1]]
]];
Enter[inputName: "Xerox/XC1-1-1/Gacha", warn: TRUE, output: LIST[
[newName: "Xerox/Pressfonts/Gacha-mrrc0", charMap: map000],
[newName: "Xerox/Pressfonts/Gacha-mrrc41", charMap: map041],
[newName: "Xerox/Pressfonts/Gacha-mrrc356", charMap: map356],
[newName: "Xerox/Pressfonts/Gacha-mrrc357", charMap: map357],
[newName: "Xerox/Pressfonts/Gacha-mrr", charMap: mapGacha]
]];
Enter[inputName: "Xerox/XC1-1-1/Terminal", warn: TRUE, output: LIST[
[newName: "Xerox/Pressfonts/Gacha-mrr", charMap: mapGacha]
]];
Enter[inputName: "Xerox/XC1-1-1/Terminal-italic", warn: TRUE, output: LIST[
[newName: "Xerox/Pressfonts/Gacha-mir", charMap: mapGacha]
]];
Enter[inputName: "Xerox/XC1-1-1/Terminal-bold", warn: TRUE, output: LIST[
[newName: "Xerox/Pressfonts/Gacha-brr", charMap: mapGacha]
]];
Enter[inputName: "Xerox/XC1-1-1/Terminal-bold-italic", warn: TRUE, output: LIST[
[newName: "Xerox/Pressfonts/Gacha-bir", charMap: mapGacha]
]];
Enter[inputName: "Xerox/XC1-1-1/Titan-Printwheel", warn: TRUE, output: LIST[
[newName: "Xerox/Pressfonts/Gacha-mrr", charMap: mapGacha]
]];
Enter[inputName: "Xerox/XC1-1-1/Titan-Printwheel-italic", warn: TRUE, output: LIST[
[newName: "Xerox/Pressfonts/Gacha-mir", charMap: mapGacha]
]];
Enter[inputName: "Xerox/XC1-1-1/Titan-Printwheel-bold", warn: TRUE, output: LIST[
[newName: "Xerox/Pressfonts/Gacha-brr", charMap: mapGacha]
]];
Enter[inputName: "Xerox/XC1-1-1/Titan-Printwheel-bold-italic", warn: TRUE, output: LIST[
[newName: "Xerox/Pressfonts/Gacha-bir", charMap: mapGacha]
]];
Enter[inputName: "Xerox/XC1-1-1/Trojan-Printwheel", warn: TRUE, output: LIST[
[newName: "Xerox/Pressfonts/XeroxBook-mrr", charMap: mapGacha]
]];
Enter[inputName: "Xerox/XC1-1-1/LetterGothic-Printwheel", warn: TRUE, output: LIST[
[newName: "Xerox/Pressfonts/Gacha-mrr", charMap: mapGacha]
]];
Enter[inputName: "Xerox/XC1-1-1/Logotypes-Xerox", output: LIST[
[newName: "Xerox/Pressfonts/Logo-mrr", charMap: mapGacha]
]];
Enter[inputName: "Xerox/XC1-1-1/Logotypes-Xerox-bold", warn: TRUE, output: LIST[
[newName: "Xerox/Pressfonts/Logo-mrr", charMap: mapGacha]
]];
RETURN[head];
};
ImagerTypeface.RegisterGenericCreator[NEW[GenericCreatorRep ← [data: NIL, proc: XCGenericCreator, priority: -1]]];
END.
mathMap: CharacterCodeMap ← LIST [
C1['ý, 357B, 173B],
C1['ý, 0B, 0B],
C1['ý, 0B, 0B],
C1['ý, 0, 243B],
C1['ý, 357B, 165B],
C1['ý, 357B, 166B],
C1['ý, 0B, 0B],
C1['ý, 357B, 172B],
C1['ý, 357B, 157B],
C1['#, 0B, 0B],
C1['°, 0, 260B],
C1[', 41B, 147B],
C1[', 0B, 0B],
C1['÷, 0, 270B],
C1['', 357B, 266B],
C1['P, 357B, 163B],
C1['`, 41B, 154B],
C1[', 357B, 174B],
C1[', 0, 307B],
C1['±, 0, 261B],
C1[' , 357B, 114B],
C1[', 357B, 175B],
C1['+, 41B, 150B],
C1['˜, 357B, 145B],
C1['Ë, 41B, 163B],
C1['¡, 42B, 042B],
C1[', 42B, 044B],
C1['., 41B, 077B],
C1[', 357B, 142B],
C1[', 357B, 143B],
C1[', 357B, 144B],
C1[' , 357B, 154B],
C1['Æ, 41B, 172B],
C1['", 0B, 0B],
C1['§, 0B, 247B],
C1['d, 41B, 145B],
C1['`, 41B, 142B],
C1['e, 41B, 146B],
C1['¿, 0B, 277B],
C1[', 357B, 100B],
C1[', 357B, 265B],
C1[', 357B, 112B],
C1['ï, 357B, 254B],
C1[', 357B, 271B],
C1[', 357B, 264B],
C1['!, 357B, 061B],
C1[', 357B, 133B],
C1['î, 357B, 135B],
C1[', 357B, 131B],
C1['ƒ, 357B, 132B],
C1[', 357B, 136B],
C1[', 357B, 130B],
C1['[, 0B, 0B],
C1[' , 357B, 133B],
C1[', 357B, 141B],
C1['Ü, 357B, 162B],
C1['Ä, 357B, 121B],
C1['], 357B, 256B],
C1['H, 357B, 171B],
C1['¥, 357B, 160B],
C1['*, 357B, 127B],
C1['(, 357B, 0],
C1['{, 357B, 162B],
C1[' , 0B, 264B],
C1['´, 360B, 272B],
C1['õ, 357B, 270B],
C1['z, 0B, 0B],
C1['ý, 0B, 0B],
C1['{, 0B, 0B],
C1['Ë, 0B, 257B],
C1['b, 0B, 256B],
C1['ý, 0B, 0B],
C1['è, 357B, 247B],
C1[', 357B, 123B],
C1['©, 0B, 323B],
C1[', 357B, 272B],
C1['C, 357B, 167B],
C1['é, 357B, 122B],
C1['Ò, 357B, 117B],
C1[', 357B, 150B],
C1[', 357B, 260B],
C1['Ë, 357B, 261B],
C1['Ð, 357B, 262B],
C1[', 357B, 263B],
C1['%, 41B, 102B],
C1['¬, 357B, 152B],
C1[', 357B, 147B],
C1['¢, 357B, 66B],
C1['«, 357B, 070B],
C1['®, 0B, 322B],
C1['g, 357B, 076B],
C1['f, 357B, 074B],
C1[', 357B, 077B],
C1['h, 357B, 075B],
C1['¡, 357B, 102B],
C1['¢, 357B, 103B],
C1['), 357B, 126B],
C1['£, 357B, 067B],
C1['¼, 0B, 274B],
C1['ý, 0B, 275B],
C1['¾, 0B, 276B],
C1['ý, 357B, 120B]
];
CharMapFromStream: PROC [stream: IO.STREAM] RETURNS [CharacterCodeMap] ~ {
state: {null, bc, dash, ec, colon, set, bar, code, comment, error} ← null;
errors: INT ← 0;
bc, ec: WORD;
set, code: [0..256);
head, tail: CharacterCodeMap ← NIL;
done: BOOLFALSE;
UNTIL done DO
char: CHAR ← '\n;
char ← IO.GetChar[stream ! IO.EndOfStream => { done ← TRUE; CONTINUE }];
SELECT state FROM
null => SELECT char FROM
<= '\040 => NULL;
IN['0..'7] => { bc ← (char-'0); state ← bc };
ENDCASE => state ← error;
bc => SELECT char FROM
IN['0..'7] => { bc ← bc*8+(char-'0) };
'- => { state ← dash };
': => { ec ← bc; state ← colon };
ENDCASE => state ← error;
dash => SELECT char FROM
<= '\040 => NULL;
IN['0..'7] => { ec ← (char-'0); state ← ec };
ENDCASE => state ← error;
ec => SELECT char FROM
IN['0..'7] => { ec ← ec*8+(char-'0) };
': => { state ← colon };
ENDCASE => state ← error;
colon => SELECT char FROM
<= '\040 => NULL;
IN['0..'7] => { set ← (char-'0); state ← set };
ENDCASE => state ← error;
set => SELECT char FROM
IN['0..'7] => { set ← set*8+(char-'0) };
'| => { state ← bar };
ENDCASE => state ← error;
bar => SELECT char FROM
<= '\040 => NULL;
IN['0..'7] => { code ← (char-'0); state ← code };
ENDCASE => state ← error;
code => SELECT char FROM
IN['0..'7] => { code ← code*8+(char-'0) };
ENDCASE => {
prev: CharacterCodeMap ~ tail;
tail ← LIST[[bc: bc, ec: ec, newbc: XC[set, code]]];
IF prev=NIL THEN head ← tail ELSE prev.rest ← tail;
state ← comment;
};
comment => NULL;
ENDCASE;
IF state=error THEN { errors ← errors+1; state ← comment };
IF char='\n THEN state ← null;
ENDLOOP;
RETURN[head];
};