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. τFontInstallerImpl.mesa Copyright c 1984, 1985 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 Doug Wyatt, May 23, 1985 5:01:01 pm PDT Tim Diebert: July 8, 1986 1:48:57 pm PDT User interaction stuff Miscellaneous 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 respobsibility of the caller. Main body Κ χ˜codešœ™Kšœ Οmœ7™BK™(K™3K™'K™(—K˜šΟk ˜ Kš œžœžœ)žœžœžœ˜FKšœ žœžœ ˜Kšœ žœ‘˜³Kšœ žœ˜Kšžœžœ2˜:Kšžœžœ5žœ˜EKšœžœ ˜Kšœžœ˜&Kšœ žœ˜"Kšœžœ/žœ ˜GKšœžœ!˜5K˜—šΠblœžœž˜ KšžœžœžœE˜nKšœž˜K˜Kšžœžœžœ˜K˜Kšœ žœžœžœ˜—K˜Kšœ™™š Οn œžœžœ!žœ žœ˜Qšž˜Kšœ žœ!˜.Kšœžœžœ˜Kšœ žœžœ˜š  œžœ˜Kš œžœžœ žœ žœ˜-š žœžœž œžœž˜+Kšœ˜Kšžœ˜—Kšœžœ˜ Kšœ˜Kšœ žœ˜K˜—Kšžœžœžœžœ˜7Kšœ*žœ˜.Kšœ˜šž˜Kšœžœ˜Kšœžœ žœ˜KšœBžœžœ˜Qšžœž˜Kšœžœžœžœ ˜6Kš œžœžœžœžœžœ˜0šœžœ˜Kšžœ žœ˜ šž˜šžœžœ˜Kšœ)˜)Kšœ&˜&K˜———KšœA˜Ašœ˜Kšœ#˜#šžœžœžœž˜&Kšžœžœ˜!Kšœ˜Kšžœ˜—Kšœžœ˜šžœžœž˜šžœžœžœž˜+šžœžœžœ˜"Kšœ˜Kšœžœ˜K˜—Kšžœ˜——Kšžœžœ ˜K˜—šžœ˜ Kšœ/˜/Kšžœ žœ˜!Kšœ&˜&šžœžœžœž˜&šžœ=žœžœ˜LKšžœ&žœžœ˜Ošžœž˜Kšœ(˜(Kšœ˜Kšžœ˜—K˜—Kšžœ˜—šžœž˜šœ ˜ Kšœ ˜ Kšœ˜—šœ ˜ Kšœ>˜>Kšžœžœ˜ Kšœ˜—KšœC˜CKšžœ˜—K˜——šž˜Kšœ žœ˜—Kšžœ˜—šž˜Kšœžœ˜ —Kšžœ˜—Kšœžœ˜K˜—K˜š œžœ žœ žœžœžœžœ˜Fšœžœ"žœ#˜NKšœ˜Kšœ˜Kšœžœ˜Kšœž˜K˜—K˜Kšžœžœ˜K˜—K˜Kšœ žœžœ˜K˜Kšœžœ˜K˜šœ+˜+K˜šžœ žœž˜šœžœ"˜+Kšœžœžœ˜Kšžœžœžœžœ˜7šžœ ž˜Kšœžœ˜Kšœ$˜$Kšœ ˜ Kšœ žœ˜Kšžœ˜—Kšœ˜Kšœžœ˜šžœžœ˜Kšžœ%žœžœ˜3K˜K˜K˜—K˜—šœžœ$˜-šžœ ž˜šœ ˜ Kšœžœ˜Kšžœžœžœžœ˜7K˜K˜K˜—šœ˜Kšžœžœžœžœ˜7K˜!K˜Kšœžœ˜K˜—šœ ˜ K˜K˜K˜Kšœ ˜ Kšœ˜—Kšžœ˜—Kšžœžœžœžœ+˜IKšœžœ˜K˜—šœžœ"˜(šžœ žœž˜!Kšžœ žœ0˜D——šœžœ!˜(šžœ žœžœ˜$šœžœ"žœ#˜NKšœ˜Kšœ˜Kšœžœ˜Kšœ žœ žœžœžœžœžœž˜9K˜—Kšœžœžœ˜!šžœž˜Kšœžœ žœžœ˜CKšœžœ žœžœ˜C˜ Kšœžœ˜ K˜+K˜—šœ ˜ Kšœžœ˜Kšžœ žœžœ˜:Kšœ˜—Kšžœ˜—K˜——šœžœ ˜)šžœ žœ˜Kšžœžœžœžœ˜7šžœ˜!Kšœ˜šœžœ ž˜Kšœ4žœžœ˜E—Kšœ˜Kšœ7˜7šœ˜šžœž˜Kšœ˜Kšœ˜Kšžœžœ˜——Kšœ˜—K˜——Kšžœ˜—K˜—K˜Kšœžœžœ˜K˜K˜Kš œ žœžœžœžœžœ˜TKšœžœžœ˜ Kšœžœžœžœžœ žœžœžœ žœ˜YKšœžœ˜/Kšœžœ˜2K˜š  œžœ˜š œžœžœžœ˜+KšœžœQ˜]šœžœ˜šžœžœ ž˜:KšœO˜O—K˜—KšœAžœ˜VK˜—Kšœ4˜4Kšœ4˜4K˜K˜—K˜—K™ ˜K˜š œžœžœžœžœžœ žœžœžœ˜uKšœžœgžœ+™³Kšœžœ žœ˜4˜Kšžœžœžœ ˜ Kšœžœ˜+Kšœ žœ˜#Kšžœ ˜Kšœ˜—K˜—K˜š  œžœ˜Kšžœžœžœžœ˜K˜$Kšœžœ˜K˜K˜—š  œžœ˜Kšžœžœžœžœ˜K˜Kšœ žœ˜K˜K˜—š œžœžœžœžœ#žœžœ˜gšœD˜DKšœ)žœ žœ˜?—K˜—K˜Kš œžœžœžœ˜—K™Kšœ ™ ˜K™šœ žœžœ˜K˜——˜Kšžœžœ˜"Kšœžœžœžœžœžœžœžœžœžœ˜`Kšœžœžœžœžœžœžœžœžœžœ˜aK˜Kšœžœžœžœ ˜Kšœžœžœžœ ˜Kšœžœžœ ˜Kšœžœžœ ˜Kšœžœžœ ˜Kšœžœžœ ˜K˜K˜K˜Kšžœ˜K˜—J˜—…—P,;