<> <> <> <> <> <> <> <<>> DIRECTORY Buttons, ConvertUnsafe USING [ToRope], Directory USING [Error, Lookup], File USING [Capability, read, Unknown], MessageWindow USING [Append, Blink, Clear, Confirm], Rope, --using lots TemporaryBooting, --using lots UserProfile USING [Line], UserTerminal USING [BlinkDisplay], VBootOps USING [], ViewerClasses USING [Viewer], ViewerOps USING [EnumerateViewers, EnumProc], ViewerTools USING [GetSelectionContents], Volume; --using lots VBoot: CEDAR MONITOR IMPORTS Buttons, ConvertUnsafe, Directory, File, MessageWindow, Rope, TemporaryBooting, UserProfile, UserTerminal, ViewerOps, ViewerTools, Volume EXPORTS VBootOps SHARES File = BEGIN OPEN Rope; MyData: TYPE = REF MyDataRep; MyDataRep: TYPE = RECORD [name: ROPE, volID: Volume.ID, file: BOOL _ FALSE]; nullSwitches: SwitchesArray _ ALL[FALSE]; Switches: TYPE = REF SwitchesArray; SwitchesArray: TYPE = PACKED ARRAY [0..36) OF BOOL _ ALL[FALSE]; <> <> <> GetSwitches: PROC [name: ROPE] RETURNS [Switches] = { sw: ROPE _ UserProfile.Line[name.Concat["Switches"]]; switches: Switches _ NEW[SwitchesArray _ nullSwitches]; SetSwitches[sw, switches]; RETURN [switches]; }; <> SetSwitches: PROC [sw: ROPE, switches: Switches] = { FOR i: INT IN [0..sw.Length[]) DO c: CHAR _ sw.Fetch[i]; si: CARDINAL _ 0; SELECT c FROM IN['0..'9] => switches^[c-'0] _ TRUE; IN['A..'Z] => switches^[10+(c-'A)] _ TRUE; IN['a..'z] => switches^[10+(c-'a)] _ TRUE; ENDCASE; ENDLOOP; }; BootProc: Buttons.ButtonProc = TRUSTED { viewer: ViewerClasses.Viewer ~ NARROW[parent]; data: MyData _ NARROW[clientData]; IF SomethingWorthSaving[] THEN RETURN; Buttons.SetDisplayStyle[viewer, $BlackOnGrey]; IF data.file THEN BootFromFile[data] ELSE IF data.volID = Volume.nullID THEN TemporaryBooting.BootButton[LOOPHOLE[GetSwitches[data.name]^]] ELSE TemporaryBooting.BootFromVolume[data.volID, LOOPHOLE[GetSwitches[data.name]^]]; Buttons.SetDisplayStyle[viewer, $BlackOnWhite]; }; BasicCedarDorado: Buttons.ButtonProc = { viewer: ViewerClasses.Viewer ~ NARROW[parent]; IF SomethingWorthSaving[] THEN RETURN; Buttons.SetDisplayStyle[viewer, $BlackOnGrey]; BootFromFileName["BasicCedarDorado"]; Buttons.SetDisplayStyle[viewer, $BlackOnWhite]; }; SomethingWorthSaving: PROC RETURNS[BOOLEAN] = BEGIN dirty: BOOLEAN _ FALSE; CheckDirty: ViewerOps.EnumProc = {dirty _ v.newVersion OR v.newFile OR dirty}; ViewerOps.EnumerateViewers[CheckDirty]; IF dirty THEN { MessageWindow.Blink[]; IF ~MessageWindow.Confirm["Confirm discard of edits . . . "] THEN { MessageWindow.Append["boot aborted."]; RETURN[TRUE]}}; RETURN[FALSE]; END; BootFromFile: PROC [data: MyData] = BEGIN BootFromFileName[ViewerTools.GetSelectionContents[]]; END; BootFromFileName: PUBLIC PROC [file: ROPE] = TRUSTED BEGIN ENABLE BEGIN TemporaryBooting.InvalidParameters => {MessageWindow.Append["Not a boot file: ", TRUE]; GOTO putName}; File.Unknown => {MessageWindow.Append["File unknown: ", TRUE]; GOTO putName}; Directory.Error => {MessageWindow.Append["Directory search failed: ", TRUE]; GOTO putName}; END; cap: File.Capability; sw: ROPE; switches: VBoot.Switches; i: INT; IF Rope.Length[file]=0 THEN {UserTerminal.BlinkDisplay[]; RETURN}; IF (i _ Rope.Find[file, "/"]) # -1 THEN {sw _ Rope.Substr[base: file, start: i + 1]; file _ Rope.Substr[base: file, len: i]}; IF ~Rope.Equal[Rope.Substr[file, Rope.Length[file]-5,5],".boot",FALSE] THEN file _ Rope.Cat[file, ".boot"]; cap _ [Directory.Lookup[LOOPHOLE[Rope.Flatten[file]]].fID, File.read]; TemporaryBooting.MakeBootable[cap, 1]; <> <> switches _ GetSwitches["File"]; SetSwitches[sw, switches]; TemporaryBooting.BootFromFile[cap, 1, LOOPHOLE[switches^]]; EXITS putName => MessageWindow.Append[file]; END; buttonsCreated: BOOL _ FALSE; BootButtonsProc: ENTRY Buttons.ButtonProc = BEGIN IF ~ buttonsCreated THEN BEGIN viewer: ViewerClasses.Viewer ~ NARROW[parent]; MakeBootButtons[]; buttonsCreated _ TRUE; END; END; MakeBootButtons: PROC = { name: ROPE; volID: Volume.ID _ Volume.nullID; types: Volume.TypeSet _ ALL[TRUE]; data: MyData ; MessageWindow.Clear[]; -- so can put up buttons faster data _ NEW[MyDataRep _ [name: "Alto", volID: volID]]; [] _ Buttons.Create[info: [name: "Alto"], proc: BootProc, clientData: data, guarded: TRUE]; data _ NEW[MyDataRep _ [name: "File", volID: volID, file: TRUE]]; [] _ Buttons.Create[info: [name: "File"], proc: BootProc, clientData: data, guarded: TRUE, fork: TRUE]; data _ NEW[MyDataRep _ [name: "Basic", volID: volID, file: TRUE]]; [] _ Buttons.Create[info: [name: "Basic"], proc: BasicCedarDorado, clientData: data, guarded: TRUE, fork: TRUE]; DO volName: STRING _ [Volume.maxNameLength]; volID _ Volume.GetNext[volID, types]; IF volID = Volume.nullID THEN EXIT; TRUSTED {Volume.GetLabelString[volID, volName]}; TRUSTED {name _ ConvertUnsafe.ToRope[volName]}; data _ NEW[MyDataRep _ [name: name, volID: volID, file: FALSE]]; [] _ Buttons.Create[info: [name: name], proc: BootProc, clientData: data, guarded: TRUE]; ENDLOOP; }; [] _ Buttons.Create[info: [name: "Boot"], proc: BootButtonsProc]; END. <>