FontInstallerImpl.mesa
Copyright Ó 1984, 1985, 1986, 1987 by Xerox Corporation. All rights reserved.
Willie-Sue, July 30, 1984 3:56:10 pm PDT
Russ Atkinson (RRA) August 20, 1985 11:30:21 am PDT
Tim Diebert: March 12, 1987 2:50:30 pm PST
Doug Wyatt, January 26, 1987 2:28:19 pm PST
DIRECTORY
BasicTime USING [GMT, nullGMT],
DFOperations USING [BringOver],
FS USING [Close, GetInfo, GetName, Error, Open, OpenFile, StreamOpen],
FSExtras USING [DoInWDir, GetWDir],
IO USING [BreakProc, Close, EndOfStream, Error, GetLineRope, GetTokenRope, PutF, RIS, STREAM, Value],
PrinterNames USING [Get],
Rope USING [Concat, Equal, ROPE, Translate, TranslatorType],
SimpleTerminal USING [SetInputTimeout, TurnOff, TurnOn],
SystemNames USING [LocalDir];
FontInstallerImpl: CEDAR PROGRAM
IMPORTS DFOperations, FS, FSExtras, IO, PrinterNames, Rope, SimpleTerminal, SystemNames
= BEGIN
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
in, out: STREAMNIL;
User interaction stuff
PrintF: PROC [format: ROPE, v1, v2, v3, v4: IO.Value ← [null[]]] ~ {
ENABLE IO.Error => IF ec=StreamClosed AND stream=out THEN CONTINUE;
IO.PutF[out, format, v1, v2, v3, v4];
};
FileDesc: TYPE = RECORD [name: ROPENIL, date: BasicTime.GMT ← BasicTime.nullGMT];
haveFonts: BOOLFALSE;
fonts: FileDesc ← [];
fontsDir: ROPE ~ SystemNames.LocalDir["Fonts"]; -- e.g., "[]<>7.0>Fonts>"
FindBasicFonts: PROC = {
Upon return, if 'haveFonts' is TRUE, the contents of 'fonts' are unpredictable. If 'haveFonts' is FALSE, however, 'fonts' describes an extant file to which ParseBasicFonts is to be applied.
name: ROPE = "BasicPrinter.fonts";
desc: FileDesc ← TryFile[name, topPath].desc;
SELECT TRUE FROM
desc.date ~= BasicTime.nullGMT => NULL;
ENDCASE => {PrintF["The fonts can't be found. I give up.\N"]; Die[]; };
fonts ← desc;
};
InstallBasicFonts: PROC [name: ROPE] = {
FontAction: TYPE ~ PROC [prefix: ROPE, dfFile: ROPE];
ParseBasicFonts: PROC [stream: STREAM, action: FontAction] ~ {
DO
lineRope: ROPE ~ IO.GetLineRope[stream ! IO.EndOfStream => EXIT];
line: STREAM ~ IO.RIS[lineRope];
break: IO.BreakProc ~ { RETURN[SELECT char FROM
<=' => sepr, '← => break, ENDCASE => other] };
prefix: ROPE ~ line.GetTokenRope[break ! IO.EndOfStream => LOOP --empty--].token;
arrow: ROPE ~ line.GetTokenRope[break ! IO.EndOfStream => EXIT].token;
dfFile: ROPE ~ line.GetTokenRope[break ! IO.EndOfStream => EXIT].token;
IF Rope.Equal[arrow, "←"] THEN action[prefix, dfFile];
ENDLOOP;
};
GetFonts: FontAction ~ {
ToBrackets: Rope.TranslatorType ~ {
SELECT old FROM '/ => RETURN['>]; ENDCASE => RETURN[old];
};
wDir: ROPE ~ fontsDir.Concat[Rope.Translate[base: prefix, translator: ToBrackets]];
IF TryFile[dfFile, NIL].desc.date # BasicTime.nullGMT THEN {
[] ← DFOperations.BringOver[dfFile: dfFile, action: [fetch: TRUE], workingDir: wDir]
};
};
stream: STREAM ~ FS.StreamOpen[name];
ParseBasicFonts[stream, GetFonts];
IO.Close[stream];
};
Miscellaneous
topPath: ROPENIL; -- "[Fonts]<CedarPS>Top>"
InitUserAndPaths: PROC = {
topPath ← PrinterNames.Get[].currentFont;
};
OpenInfo: PROC [name: ROPE, wDir: ROPENIL] RETURNS [fullFName: ROPE, attachedTo: ROPE, created: BasicTime.GMT] = {
This procedure is similar to FS.FileInfo, except that it also makes certain that the file is on the local disk. Any errors raised by FS.Open are the responsibility of the caller.
file: FS.OpenFile ← FS.Open[name: name, wDir: wDir];
{
ENABLE UNWIND => FS.Close[file];
[fullFName, attachedTo] ← FS.GetName[file];
created ← FS.GetInfo[file].created;
FS.Close[file];
};
};
OpenTerminal: PROC = {
IF in # NIL THEN RETURN;
[in, out] ← SimpleTerminal.TurnOn[];
PrintF["\N"];
};
CloseTerminal: PROC = {
IF in = NIL THEN RETURN;
SimpleTerminal.TurnOff[];
in ← out ← NIL;
};
TryFile: PROC [shortName, prefix: ROPENIL] RETURNS [desc: FileDesc ← [], attachedTo: ROPENIL] = {
[fullFName: desc.name, attachedTo: attachedTo, created: desc.date] ←
OpenInfo[name: shortName, wDir: prefix ! FS.Error => CONTINUE];
};
Die: PROC = {DO ENDLOOP};
Main body
working: BOOLFALSE;
installDir: ROPE ~ FSExtras.GetWDir[];
DoRealWork: PROC [] = {
DoRealWorkInner: PROC ~ {
haveFonts ← FALSE;
InitUserAndPaths[];
FindBasicFonts[];
The profile may have changed. Even if it hasn't, we notify.
InstallBasicFonts[fonts.name];
SimpleTerminal.SetInputTimeout[0];
CloseTerminal[];
};
IF NOT working THEN {
working ← TRUE;
FSExtras.DoInWDir[installDir, DoRealWorkInner];
working ← FALSE;
};
};
DoRealWork[ !FS.Error => {OpenTerminal[];
PrintF["\NFatal FS Error: %g\N", [rope[error.explanation]]]; Die[]}];
END.