<> <> <> <> <> <> DIRECTORY Ascii USING [BS, ControlA, ControlQ, ControlW, ControlX, CR, DEL, SP], BasicTime USING [GMT, nullGMT], DFOperations USING [BringOver, ChoiceInteraction, ChoiceResponse, Choices, DFInfoInteraction, FileInteraction, InfoInteraction, InteractionProc, YesNoInteraction, YesNoResponse], DFUtilities USING [DateToRope], FS USING [Close, GetInfo, GetName, Error, Open, OpenFile], IO USING [GetChar, EraseChar, PutChar, PutF, PutF1, PutRope, STREAM], List USING [PutAssoc], PrinterDefaultRemoteNames USING [Get], ProcessProps USING [PushPropList], Rope USING [Cat, Concat, Equal, Fetch, FromChar, Length, ROPE, Substr], SimpleTerminal USING [InputTimeout, TurnOff, TurnOn]; FontInstallerImpl: CEDAR PROGRAM IMPORTS DFOperations, DFUtilities, FS, IO, List, PrinterDefaultRemoteNames, ProcessProps, Rope, SimpleTerminal = BEGIN ROPE: TYPE = Rope.ROPE; in, out: IO.STREAM _ NIL; <> <<>> GetChoice: PROC [c: REF DFOperations.ChoiceInteraction] RETURNS [choice: NAT] = { DO default: ROPE = c.choices[choice _ c.default]; ans: ROPE _ NIL; firstChar: BOOL _ TRUE; FlushVisible: PROC = { r: ROPE = IF firstChar THEN default ELSE ans; FOR i: INT DECREASING IN [0..r.Length[]) DO out.EraseChar[r.Fetch[i]]; ENDLOOP; ans _ NIL; choice _ c.default; firstChar _ FALSE; }; THROUGH [0..2*depth) DO out.PutChar[Ascii.SP]; ENDLOOP; out.PutRope[c.message]; out.PutChar[Ascii.SP]; out.PutRope[default]; DO oldAns: ROPE = ans; char: CHAR _ Ascii.CR; char _ in.GetChar[ ! SimpleTerminal.InputTimeout => {char _ Ascii.CR; CONTINUE}]; SELECT char FROM Ascii.DEL => {out.PutRope[" XXX\N"]; GO TO startOver}; Ascii.CR => IF ans.Length[] = 0 THEN GO TO done; Ascii.BS, Ascii.ControlA => IF firstChar THEN FlushVisible[] ELSE IF ans.Length[] > 0 THEN { out.EraseChar[ans.Fetch[ans.Length[]-1]]; ans _ ans.Substr[len: ans.Length[]-1]; }; Ascii.ControlQ, Ascii.ControlW, Ascii.ControlX => FlushVisible[]; '? => { out.PutRope[" XXX\NChoices are: "]; FOR i: NAT IN [0..c.choices.length) DO IF i ~= 0 THEN out.PutRope[", "]; out.PutRope[c.choices[i]]; ENDLOOP; out.PutChar[Ascii.CR]; IF c.explanations ~= NIL THEN FOR i: NAT IN [0..c.explanations.length) DO IF c.explanations[i] ~= NIL THEN { out.PutRope[c.explanations[i]]; out.PutChar[Ascii.CR]; }; ENDLOOP; GO TO startOver }; ENDCASE => { state: {notFound, found, ambiguous} _ notFound; IF firstChar THEN FlushVisible[]; ans _ ans.Concat[Rope.FromChar[char]]; FOR i: NAT IN [0..c.choices.length) DO IF ans.Equal[s2: c.choices[i].Substr[len: ans.Length[]], case: FALSE] THEN { IF ans.Length[] = c.choices[i].Length[] THEN {choice _ i; state _ found; EXIT}; SELECT state FROM notFound => {choice _ i; state _ found}; found => state _ ambiguous; ENDCASE; }; ENDLOOP; SELECT state FROM notFound => { ans _ oldAns; }; found => { out.PutRope[c.choices[choice].Substr[start: oldAns.Length[]]]; GO TO done }; ambiguous => out.PutChar[c.choices[choice].Fetch[oldAns.Length[]]]; ENDCASE; }; REPEAT startOver => NULL; ENDLOOP; REPEAT done => NULL; ENDLOOP; out.PutChar[Ascii.CR]; }; Confirm: PROC [message: ROPE, default: BOOL _ TRUE] RETURNS [BOOL] = { c: REF DFOperations.ChoiceInteraction = NEW[DFOperations.ChoiceInteraction _ [ message: message, choices: yesNo, explanations: NIL, default: default.ORD ]]; OpenTerminal[]; RETURN[VAL[GetChoice[c]]] }; autoConfirm: BOOL _ TRUE; depth: INT _ -1; Interact: DFOperations.InteractionProc = { OpenTerminal[]; WITH interaction SELECT FROM info: REF DFOperations.InfoInteraction => { prompt: BOOL _ TRUE; THROUGH [0..2*depth) DO out.PutChar[Ascii.SP]; ENDLOOP; SELECT info.class FROM info => prompt _ FALSE; warning => out.PutRope["Warning: "]; error => out.PutRope["Error: "]; abort => NULL; ENDCASE; out.PutRope[info.message]; out.PutChar[Ascii.CR]; IF prompt THEN { IF Confirm["Shall I continue anyway?"] THEN RETURN; out.PutRope["Giving up..."]; Die[]; }; }; info: REF DFOperations.DFInfoInteraction => { SELECT info.action FROM start => { depth _ depth.SUCC; THROUGH [0..2*depth) DO out.PutChar[Ascii.SP]; ENDLOOP; out.PutRope["BringOver of "]; out.PutRope[info.dfFile]; }; end => { THROUGH [0..2*depth) DO out.PutChar[Ascii.SP]; ENDLOOP; out.PutRope["End BringOver of "]; out.PutRope[info.dfFile]; depth _ depth.PRED; }; abort => { out.PutRope["BringOver of "]; out.PutRope[info.dfFile]; out.PutRope[" aborted"]; depth _ -1; }; ENDCASE; IF info.message ~= NIL THEN IO.PutF1[out, " (%g)", [rope[info.message]]]; out.PutChar[Ascii.CR]; }; c: REF DFOperations.ChoiceInteraction => IF c.blunder OR ~autoConfirm THEN RETURN[response: NEW[DFOperations.ChoiceResponse _ [GetChoice[c]]]]; yn: REF DFOperations.YesNoInteraction => IF yn.blunder OR ~autoConfirm THEN { c: REF DFOperations.ChoiceInteraction = NEW[DFOperations.ChoiceInteraction _ [ message: yn.message, choices: ynqa, explanations: NIL, default: IF yn.default THEN YNQA.yes.ORD ELSE YNQA.no.ORD ]]; choice: YNQA = VAL[GetChoice[c]]; SELECT choice FROM $yes => RETURN[response: NEW[DFOperations.YesNoResponse _ [TRUE]]]; $no => RETURN[response: NEW[DFOperations.YesNoResponse _ [FALSE]]]; $quit => { abort _ TRUE; abortMessageForLog _ "(requested by user)"; }; $all => { autoConfirm _ TRUE; RETURN[response: NEW[DFOperations.YesNoResponse _ [TRUE]]] }; ENDCASE; }; file: REF DFOperations.FileInteraction => IF autoConfirm THEN { THROUGH [0..2*depth) DO out.PutChar[Ascii.SP]; ENDLOOP; IO.PutF[out, "%g %g %g {%g}%g\N", [rope[file.localFile]], [rope[SELECT file.action FROM $fetch => "<--", $store => "-->", $check => "<-->", ENDCASE => NIL]], [rope[file.remoteFile]], [rope[DFUtilities.DateToRope[[$explicit, file.date]]]], [rope[ SELECT file.dateFormat FROM $greaterThan => " > ", $notEqual => " ~= ", ENDCASE => NIL]] ]; }; ENDCASE; }; Rubout: ERROR = CODE; FileDesc: TYPE = RECORD [name: ROPE _ NIL, date: BasicTime.GMT _ BasicTime.nullGMT]; DFList: TYPE = REF DFListObject; DFListObject: TYPE = RECORD [head: LIST OF FileDesc _ NIL, tail: LIST OF FileDesc _ NIL]; profileDFList: DFList = NEW[DFListObject _ []]; newProfileDFList: DFList = NEW[DFListObject _ []]; TryForFonts: PROC = { GetFonts: PROC [name: ROPE, wDir: ROPE] ~ { dfFile: ROPE ~ Rope.Cat[PrinterDefaultRemoteNames.Get[].currentFont, "Printer", name, ".df"]; innerGetFonts: PROC = { IF TryFile[dfFile, NIL].desc.date # BasicTime.nullGMT THEN [] _ DFOperations.BringOver[dfFile: dfFile, interact: Interact, action: fetch]; }; ProcessProps.PushPropList[List.PutAssoc[$WorkingDirectory, wDir, NIL], innerGetFonts]; }; GetFonts["PressFonts", "///Fonts/Xerox/PressFonts"]; GetFonts["XC1-2-2-Fonts", "///Fonts/Xerox/XC1-2-2"]; }; <> OpenInfo: PROC [name: ROPE, wDir: ROPE _ NIL] RETURNS [fullFName: ROPE, attachedTo: ROPE, created: BasicTime.GMT] = { <> 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[]; out.PutChar[Ascii.CR]; }; CloseTerminal: PROC = { IF in = NIL THEN RETURN; SimpleTerminal.TurnOff[]; in _ out _ NIL; }; TryFile: PROC [shortName, prefix: ROPE _ NIL] RETURNS [desc: FileDesc _ [], attachedTo: ROPE _ NIL] = { [fullFName: desc.name, attachedTo: attachedTo, created: desc.date] _ OpenInfo[name: shortName, wDir: prefix ! FS.Error => CONTINUE]; }; Die: PROC = {DO ENDLOOP}; <<>> <
> <<>> working: BOOL _ FALSE; YNQA: TYPE = {yes, no, quit, all}; ynqa: REF DFOperations.Choices = NEW[DFOperations.Choices[YNQA.LAST.ORD.SUCC - YNQA.FIRST.ORD]]; yesNo: REF DFOperations.Choices = NEW[DFOperations.Choices[BOOL.LAST.ORD.SUCC - BOOL.FIRST.ORD]]; yesNo[BOOL.TRUE.ORD] _ "Yes"; yesNo[BOOL.FALSE.ORD] _ "No"; ynqa[YNQA.yes.ORD] _ "Yes"; ynqa[YNQA.no.ORD] _ "No"; ynqa[YNQA.quit.ORD] _ "Quit"; ynqa[YNQA.all.ORD] _ "All"; TryForFonts[]; END.