<> <> <> <> <> <> <<>> DIRECTORY Process USING [Detach], Rope USING [Concat, Equal, ROPE], TEditDocumentsCache USING [Update], TEditDocumentPrivate USING [], TEditInput USING [FreeTree], TEditProfile USING [unsavedDocumentCacheSize], TextNode USING [Ref]; TEditDocumentsCacheImpl: CEDAR MONITOR IMPORTS Process, Rope, TEditDocumentsCache, TEditInput, TEditProfile EXPORTS TEditDocumentsCache, TEditDocumentPrivate = BEGIN ROPE: TYPE ~ Rope.ROPE; list: LIST OF UnsavedDocumentInfo; UnsavedDocumentInfo: TYPE = REF UnsavedDocumentInfoRec; UnsavedDocumentInfoRec: TYPE = RECORD [fileName: ROPE, root: TextNode.Ref]; GetList: PUBLIC ENTRY PROC RETURNS [rope: ROPE] = { FOR l: LIST OF UnsavedDocumentInfo _ list, l.rest UNTIL l=NIL DO rope _ Rope.Concat[rope, Rope.Concat["\n", l.first.fileName]]; ENDLOOP; }; RecordUnsavedDocument: PUBLIC ENTRY PROC [fileName: ROPE, root: TextNode.Ref] = { ENABLE UNWIND => NULL; Size: PROC RETURNS [size: INTEGER] = { size _ 0; IF list=NIL THEN RETURN; FOR l: LIST OF UnsavedDocumentInfo _ list, l.rest UNTIL l=NIL DO size _ size+1; ENDLOOP; }; info: UnsavedDocumentInfo; oldRoot: TextNode.Ref; IF (oldRoot _ SearchList[fileName]) # NIL THEN -- discard previous entry, if any TEditInput.FreeTree[oldRoot]; info _ NEW[UnsavedDocumentInfoRec _ [fileName, root]]; list _ CONS[info, list]; WHILE Size[] > MAX[TEditProfile.unsavedDocumentCacheSize, 0] DO DiscardOldest[]; ENDLOOP; TRUSTED { Process.Detach[FORK TEditDocumentsCache.Update[]] }; }; FindUnsavedDocument: PUBLIC ENTRY PROC [fileName: ROPE] RETURNS [root: TextNode.Ref] = { ENABLE UNWIND => NULL; IF (root _ SearchList[fileName]) # NIL THEN TRUSTED {Process.Detach[FORK TEditDocumentsCache.Update[]] } }; DiscardOldest: PROC = { IF list=NIL THEN RETURN; FOR l: LIST OF UnsavedDocumentInfo _ list, l.rest DO IF l.rest # NIL THEN LOOP; -- spin until get to the oldest entry TEditInput.FreeTree[SearchList[l.first.fileName]]; RETURN; ENDLOOP; }; SearchList: PROC [fileName: ROPE] RETURNS [root: TextNode.Ref] = { -- if find, then remove prev: LIST OF UnsavedDocumentInfo; IF list=NIL THEN RETURN [NIL]; IF Rope.Equal[list.first.fileName, fileName, FALSE] THEN { root _ list.first.root; list _ list.rest; RETURN; }; prev _ list; FOR l: LIST OF UnsavedDocumentInfo _ list.rest, l.rest UNTIL l=NIL DO IF Rope.Equal[l.first.fileName, fileName, FALSE] THEN { root _ l.first.root; prev.rest _ l.rest; RETURN; }; prev _ l; ENDLOOP; RETURN [NIL]; }; END.