<> <> <<>> <> <<>> DIRECTORY Booting USING [CallBootingProcs], Buttons USING [ButtonProc, Create], Commander USING [CommandProc, Register], CommandTool USING [ParseToList], DeviceCleanup USING[Perform], IO USING [PutF], MessageWindow USING [Append, Blink-- , Confirm--], PrincOpsUtils USING[DisableInterrupts], ProcessorFace USING[PowerOff], Rope USING[Concat, Equal, ROPE], ViewerOps USING[ChangeColumn, EnumProc, EnumerateViewers]; PowerOff: CEDAR PROGRAM IMPORTS Booting, Buttons, Commander, CommandTool, DeviceCleanup, IO, MessageWindow, PrincOpsUtils, ProcessorFace, Rope, ViewerOps ~ BEGIN PowerOffButton: Buttons.ButtonProc ~ TRUSTED BEGIN DoPowerOff[FALSE, TRUE]; END; DoPowerOff: PROC [force: BOOL, confirm: BOOL] = TRUSTED BEGIN rejection: Rope.ROPE _ NIL; I: INT _ 0 ; IF ~force AND SomethingWorthSaving[confirm] THEN RETURN; rejection _ Booting.CallBootingProcs[]; IF ~force AND rejection # NIL THEN { MessageWindow.Blink[]; MessageWindow.Append[message: Rope.Concat["Power off rejected due to", rejection], clearFirst: TRUE]; }; PrincOpsUtils.DisableInterrupts[]; -- make it hold still first DeviceCleanup.Perform[turnOff]; ProcessorFace.PowerOff[]; DO I _ I + 1; ENDLOOP; END; SomethingWorthSaving: PROC [confirm: BOOL] RETURNS [BOOL] = { dirty: BOOL _ FALSE; CheckDirty: ViewerOps.EnumProc = { IF v.newVersion OR v.newFile THEN dirty _ TRUE ELSE RETURN; IF v.offDeskTop THEN ViewerOps.ChangeColumn[v, left]; }; ViewerOps.EnumerateViewers[CheckDirty]; IF dirty AND confirm THEN { MessageWindow.Blink[]; MessageWindow.Append[message: "Dirty viewer => no power off", clearFirst: TRUE]; <> <> <> <<}>> << ELSE RETURN[FALSE];>> }; RETURN[dirty] }; PowerOffCmdProc: Commander.CommandProc = { skip: BOOL _ FALSE; force: BOOL _ FALSE; cmdLine: LIST OF Rope.ROPE; cmdLine _ CommandTool.ParseToList[cmd].list; IF cmdLine # NIL THEN { IF Rope.Equal[cmdLine.first, "-f", FALSE] AND cmdLine.rest = NIL THEN force _ TRUE ELSE { IO.PutF[cmd.err, "Usage: PowerOff [-f]\n"]; skip _ TRUE; }; }; IF ~skip THEN DoPowerOff[force, FALSE]; result _ $Failure; msg _ "PowerOff not done because there are unsaved viewers."; }; [] _ Buttons.Create[info: [name: "PowerOff"], proc: PowerOffButton, guarded: TRUE]; Commander.Register[key: "PowerOff", proc: PowerOffCmdProc, doc: "Perform a somewhat orderly system shutdown, and power the machine off. The command will fail if there are any unsaved viewers. The f switch can be used to override."]; END. <> <> <<>> <<>>