<> <> <> <> DIRECTORY Atom, Ascii, FileIO, IO, RefText, Rope, UFFileManager, UFFontDirReader, UserTerminal; UFFontDirReaderImpl: CEDAR PROGRAM IMPORTS Atom, FileIO, IO, RefText, Rope, UFFileManager, UserTerminal EXPORTS UFFontDirReader = BEGIN OPEN UFFontDirReader; EnumerateFontDirectory: PUBLIC PROCEDURE [fontDirectoryName: ROPE, examine: ExamineProc, result: ResultProc] = { stream: IO.STREAM _ FileIO.Open[fontDirectoryName]; inputBuffer: REF TEXT _ RefText.ObtainScratch[128]; fontName: REF TEXT _ RefText.ObtainScratch[64]; codeScheme: REF TEXT _ RefText.ObtainScratch[64]; metricsName: REF TEXT _ RefText.ObtainScratch[64]; graphicsName: REF TEXT _ RefText.ObtainScratch[64]; 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 _ FileIO.Open["UnifiedFonts.errorLog", append]; stream.PutF["%g Error at position %g in file %g", IO.time[], IO.int[locationOfBufferStart+tokenStart], IO.rope[fontDirectoryName]]; stream.Close; TRUSTED {UserTerminal.BlinkDisplay[]}; }; GetToken: PROC = { <> c: CHAR; tokenStart _ tokenStart+tokenLength; tokenLength _ 0; WHILE tokenStart> scratchText: REF TEXT _ RefText.ObtainScratch[64]; Save[scratchText]; scratchText[0] _ Rope.Upper[scratchText[0]]; FOR i: NAT IN [1..scratchText.length) DO scratchText[i] _ Rope.Lower[scratchText[i]]; ENDLOOP; atom _ Atom.MakeAtom[Rope.FromRefText[scratchText]]; RefText.ReleaseScratch[scratchText]; }; 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_1}; IF tokenLength=0 THEN Error[]; real _ num/denom; }; Save: PROC [r: REF TEXT] = { r.length _ 0; RefText.Append[to: r, from: inputBuffer, start: tokenStart, len: tokenLength]; }; 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[]; Save[fontName]; GetToken[]}; Match["CODESCHEME:"] => {GetToken[]; Save[codeScheme]; GetToken[]}; Match["METRICS:"] => {GetToken[]; metricsType _ SELECT TRUE FROM Match["TFM"] => $Tfm, Match["STRIKE"] => $Strike, ENDCASE => AtomFromToken[]; GetToken[]; Save[metricsName]; GetToken[]; }; Match["GRAPHICS:"] => {GetToken[]; graphicsType _ SELECT TRUE FROM Match["PRESS"] => $Press, Match["STRIKE"] => $Strike, Match["SD"] => $Sd, ENDCASE => AtomFromToken[]; GetToken[]; 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[inputBuffer]; RefText.ReleaseScratch[fontName]; RefText.ReleaseScratch[codeScheme]; RefText.ReleaseScratch[metricsName]; RefText.ReleaseScratch[graphicsName]; stream.Close[]; }; END.