<<>> <> <> <> <> <> <> <> <<>> DIRECTORY Booting USING [RegisterProcs, RollbackProc], FS USING [Error, StreamOpen], IO USING [Close, GetChar, GetLength, PutRope, STREAM], MessageWindow USING [Append], Process USING [Detach], Rope USING [Concat, Equal, Fetch, Find, FromProc, ROPE, Size], SystemNames USING [UserName], ViewerEvents USING [EventProc, RegisterEventProc, UnRegisterEventProc]; MaintainFilesList: CEDAR MONITOR IMPORTS Booting, FS, IO, Process, Rope, MessageWindow, SystemNames, ViewerEvents = { STREAM: TYPE = IO.STREAM; ROPE: TYPE = Rope.ROPE; regProc: REF; filesList: ROPE; FileName: PROC RETURNS [name: ROPE] = { RETURN [Rope.Concat[SystemNames.UserName[], ".List"]] }; Add: ViewerEvents.EventProc = TRUSTED { Process.Detach[FORK AddToFilesList[viewer.file]] }; AddToFilesList: ENTRY PROC [name: ROPE] = { ENABLE UNWIND => NULL; fileName: ROPE ~ FileName[]; s: STREAM ¬ NIL; AlreadyThere: PROC RETURNS [BOOL] = { pos: INT ¬ 0; len: INT = Rope.Size[name]; fileLen: INT = Rope.Size[filesList]; blank: CHAR = ' ; WHILE (pos ¬ Rope.Find[filesList, name, pos, FALSE]) # -1 DO -- look for adjacent blanks IF (pos>0 AND Rope.Fetch[filesList, pos-1] # blank) OR (pos+len < fileLen AND Rope.Fetch[filesList, pos+len] # blank) THEN { pos ¬ pos+len; LOOP }; RETURN [TRUE]; ENDLOOP; RETURN [FALSE] }; IF Rope.Size[name]=0 THEN RETURN; IF Rope.Equal[name, fileName, FALSE] THEN { <> GetFilesList[]; RETURN; }; IF AlreadyThere[] THEN RETURN; MessageWindow.Append["Adding ", TRUE]; MessageWindow.Append[name]; MessageWindow.Append[" to "]; MessageWindow.Append[fileName]; filesList ¬ Rope.Concat[filesList, Rope.Concat[" ", name]]; s ¬ FS.StreamOpen[fileName, $create]; IO.PutRope[s, filesList]; IO.Close[s]; }; AfterRollback: Booting.RollbackProc = { --update cached copy-- GetFilesList[]; }; GetFilesList: PROC = { fileName: ROPE ~ FileName[]; s: IO.STREAM = FS.StreamOpen[fileName, $read ! FS.Error => GO TO Quit]; len: INT = IO.GetLength[s]; readChar: SAFE PROC RETURNS [CHAR] = { RETURN [IO.GetChar[s]] }; filesList ¬ Rope.FromProc[len, readChar]; IO.Close[s]; EXITS Quit => filesList ¬ NIL; }; UnReg: ENTRY PROC = { ENABLE UNWIND => NULL; IF regProc # NIL THEN ViewerEvents.UnRegisterEventProc[regProc, save]; regProc ¬ NIL; filesList ¬ NIL }; Reg: ENTRY PROC = { ENABLE UNWIND => NULL; IF regProc # NIL THEN ViewerEvents.UnRegisterEventProc[regProc, save]; regProc ¬ ViewerEvents.RegisterEventProc[Add, save]; GetFilesList[] }; Reg[]; Booting.RegisterProcs[r: AfterRollback]; }...