EnumerateFontDirectory:
PUBLIC
PROCEDURE [fontDirectoryName:
ROPE, examine: ExamineProc, result: ResultProc] = {
stream: IO.STREAM ← FS.StreamOpen[fontDirectoryName];
inputBufferScratch: REF TEXT = RefText.ObtainScratch[128];
fontNameScratch: REF TEXT = RefText.ObtainScratch[64];
codeSchemeScratch: REF TEXT = RefText.ObtainScratch[64];
metricsNameScratch: REF TEXT = RefText.ObtainScratch[64];
graphicsNameScratch: REF TEXT = RefText.ObtainScratch[64];
inputBuffer: REF TEXT ← inputBufferScratch;
fontName: REF TEXT ← fontNameScratch;
codeScheme: REF TEXT ← codeSchemeScratch;
metricsName: REF TEXT ← metricsNameScratch;
graphicsName: REF TEXT ← graphicsNameScratch;
deviceType: DeviceType ← $Ideal;
metricsType: ATOM ← $Nil;
graphicsType: ATOM ← $Nil;
rotation: REAL ← 0;
size, plusSize, minusSize: REAL ← 0;
cp: NAT ← 0;
locationOfBufferStart: INT ← 0;
tokenStart, tokenLength: NAT ← 0;
Error:
PROC = {
stream: IO.STREAM ← FS.StreamOpen["UnifiedFonts.errorLog", $append];
stream.PutF["%g Error at position %g in file %g", IO.time[], IO.int[locationOfBufferStart+tokenStart], IO.rope[fontDirectoryName]];
stream.Close;
Terminal.Current[].BlinkBWDisplay;
};
GetToken:
PROC = {
Gets the next token into inputBuffer[tokenStart] .. inputBuffer[tokenLength-1]
c: CHAR;
tokenStart ← tokenStart+tokenLength;
tokenLength ← 0;
WHILE tokenStart<inputBuffer.length
AND ((c ← inputBuffer[tokenStart]) = Ascii.
SP
OR c = Ascii.
TAB
OR c = Ascii.
CR
OR c = Ascii.
LF
OR c = ',
OR c = ';)
DO
tokenStart ← tokenStart + 1;
IF tokenStart = inputBuffer.length THEN RefillBuffer[];
ENDLOOP;
WHILE tokenStart+tokenLength<inputBuffer.length
AND
NOT ((c ← inputBuffer[tokenStart+tokenLength]) = Ascii.
SP
OR c = Ascii.
TAB
OR c = Ascii.
CR
OR c = Ascii.
LF
OR c = ',
OR c = ';)
DO
tokenLength ← tokenLength + 1;
IF tokenStart + tokenLength = inputBuffer.length THEN RefillBuffer[];
ENDLOOP;
};
RefillBuffer:
PROC = {
FOR i:
NAT
IN [0..tokenLength)
DO
inputBuffer[i] ← inputBuffer[i+tokenStart];
ENDLOOP;
inputBuffer.length ← tokenLength;
locationOfBufferStart ← locationOfBufferStart+tokenStart;
tokenStart ← 0;
[] ← stream.GetBlock[block: inputBuffer, startIndex: tokenLength, count: inputBuffer.maxLength-tokenLength];
};
Match:
PROC [key:
REF
READONLY
TEXT]
RETURNS [equal:
BOOLEAN] = {
i: NAT ← tokenStart;
IF key.length # tokenLength THEN RETURN [FALSE];
FOR j:
NAT
IN [0..key.length)
DO
IF key[j]#inputBuffer[i] THEN RETURN [FALSE];
i←i+1;
ENDLOOP;
RETURN [TRUE]
};
GetDimn:
PROC []
RETURNS [dimn:
REAL] = {
dimn ← TokenAsReal[];
GetToken[];
SELECT
TRUE
FROM
Match["mm"] => {GetToken[]; dimn ← dimn*72/25.4};
Match["cm"] => {GetToken[]; dimn ← dimn*72/2.54};
Match["in"] => {GetToken[]; dimn ← dimn*72};
Match["bp"] => {GetToken[]};
Match["pt"] => {GetToken[]; dimn ← dimn*72/72.27};
ENDCASE => NULL;
};
TokenAsReal:
PROC []
RETURNS [real:
REAL] = {
c: CHAR ← ' ;
i: NAT ← tokenStart;
num: REAL ← 0;
denom: REAL ← 1;
WHILE i < inputBuffer.length
AND (c ← inputBuffer[i])
IN ['0..'9]
DO
num ← 10.0*num + (c-'0);
i ← i+1;
ENDLOOP;
IF c='.
THEN {i ← i+1; c ← ' ;
WHILE i < inputBuffer.length
AND (c ← inputBuffer[i])
IN ['0..'9]
DO
num ← 10.0*num + (c-'0);
denom ← 10.0*denom;
i ← i+1;
ENDLOOP;
}
ELSE
IF c='/
THEN {i ← i+1; denom ← 0;
WHILE i < inputBuffer.length
AND (c ← inputBuffer[i])
IN ['0..'9]
DO
denom ← 10.0*denom + (c-'0);
i ← i+1;
ENDLOOP;
};
tokenLength ← i-tokenStart;
IF denom=0.0 THEN {Error[]; denom𡤁};
IF tokenLength=0 THEN Error[];
real ← num/denom;
};
Save:
PROC[r:
REF
TEXT]
RETURNS[
REF
TEXT] = {
r.length ← 0;
RETURN[RefText.Append[to: r, from: inputBuffer, start: tokenStart, len: tokenLength]];
};
AtomFromToken:
PROC
RETURNS [atom:
ATOM] = {
Not called often; makes an atom with first char upper case, rest lower case.
scratch: REF TEXT = RefText.ObtainScratch[64];
text: REF TEXT ← Save[scratch];
text[0] ← Ascii.Upper[text[0]];
FOR i:
NAT
IN [1..text.length)
DO
text[i] ← Ascii.Lower[text[i]];
ENDLOOP;
atom ← Atom.MakeAtom[Rope.FromRefText[text]];
RefText.ReleaseScratch[scratch];
};
RefillBuffer[];
GetToken[];
WHILE tokenLength>0
DO
SELECT TRUE FROM
Match["DEVICE:"] => {GetToken[];
SELECT TRUE FROM
Match["Ideal"] => deviceType ← $Ideal;
Match["Spruce"] => deviceType ← $Spruce;
Match["Press"] => deviceType ← $Press;
Match["Ideal"] => deviceType ← $Screen;
ENDCASE => deviceType ← AtomFromToken[];
GetToken[]
};
Match["SIZE:"] => {GetToken[];
IF Match["ANY"] THEN {GetToken[]; size ← minusSize ← 0; plusSize ← 1000000.0}
ELSE {
size ← plusSize ← minusSize ← GetDimn[];
DO
SELECT
TRUE
FROM
Match["+"] => {GetToken[]; plusSize ← size + GetDimn[]};
Match["-"] => {GetToken[]; minusSize ← size - GetDimn[]};
Match["+-"] => {r: REAL; GetToken[]; r ← GetDimn[]; plusSize ← size + r; minusSize ← size - r};
ENDCASE => EXIT;
ENDLOOP;
};
};
Match["ROTATION:"] => {GetToken[];
IF Match["ANY"] THEN rotation ← -360.0 ELSE rotation ← TokenAsReal[];
GetToken[]
};
Match["FONTNAME:"] => {GetToken[]; fontName ← Save[fontName]; GetToken[]};
Match["CODESCHEME:"] => {GetToken[]; codeScheme ← Save[codeScheme]; GetToken[]};
Match["METRICS:"] => {GetToken[];
metricsType ←
SELECT TRUE FROM
Match["TFM"] => $Tfm,
Match["STRIKE"] => $Strike,
ENDCASE => AtomFromToken[];
GetToken[]; metricsName ← Save[metricsName]; GetToken[];
};
Match["GRAPHICS:"] => {GetToken[];
graphicsType ←
SELECT TRUE FROM
Match["PRESS"] => $Press,
Match["STRIKE"] => $Strike,
Match["SD"] => $Sd,
ENDCASE => AtomFromToken[];
GetToken[]; graphicsName ← Save[graphicsName]; GetToken[];
};
Match["DEFINEFONT"] => {
GetToken[];
IF examine[
candidateFontName: fontName,
candidateSize: size,
candidateMaxSize: plusSize,
candidateMinSize: minusSize,
candidateRotation: rotation,
candidateDeviceType: deviceType
]
THEN {
quit:
BOOLEAN ← result[
candidateFontName: fontName,
candidateSize: size,
candidateMaxSize: plusSize,
candidateMinSize: minusSize,
candidateRotation: rotation,
candidateDeviceType: deviceType,
metricsType: metricsType,
codeScheme: UFFileManager.KeyOfRefText[codeScheme],
metricsName: UFFileManager.KeyOfRefText[metricsName],
graphicsType: graphicsType,
graphicsName: UFFileManager.KeyOfRefText[graphicsName]
];
IF quit THEN EXIT;
};
};
ENDCASE => {Error[]; EXIT};
ENDLOOP;
RefText.ReleaseScratch[inputBufferScratch];
RefText.ReleaseScratch[fontNameScratch];
RefText.ReleaseScratch[codeSchemeScratch];
RefText.ReleaseScratch[metricsNameScratch];
RefText.ReleaseScratch[graphicsNameScratch];
stream.Close[];
};