DIRECTORY Menus USING [ChangeNumberOfLines], Process USING [Detach], Rope USING [Concat, Equal, Map, ROPE, Size], TEditDocumentsCache USING [], TEditDocumentPrivate USING [], TEditInput USING [FreeTree], TEditProfile USING [showUnsavedDocumentsList, unsavedDocumentCacheSize], TextNode USING [Ref], TiogaAccess USING [Create, Looks, Put, Writer, WriteViewer], ViewerClasses USING [Viewer], ViewerOps USING [CreateViewer, DestroyViewer, EstablishViewerPosition, PaintViewer]; TEditDocumentsCacheImpl: CEDAR MONITOR IMPORTS Menus, Process, Rope, TEditInput, TEditProfile, TiogaAccess, ViewerOps EXPORTS TEditDocumentsCache, TEditDocumentPrivate = BEGIN ROPE: TYPE ~ Rope.ROPE; UnsavedDocumentInfo: TYPE = REF UnsavedDocumentInfoRec; UnsavedDocumentInfoRec: TYPE = RECORD [fileName: ROPE, root: TextNode.Ref]; list: LIST OF UnsavedDocumentInfo; viewer: ViewerClasses.Viewer; GetList: PUBLIC ENTRY PROC RETURNS [ROPE] = { RETURN [GetListInternal[]] }; GetListInternal: INTERNAL 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 Update[]] }; }; FindUnsavedDocument: PUBLIC ENTRY PROC [fileName: ROPE] RETURNS [root: TextNode.Ref] = { ENABLE UNWIND => NULL; IF (root _ SearchList[fileName]) # NIL THEN TRUSTED {Process.Detach[FORK 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]; }; Update: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; rope: ROPE _ GetListInternal[]; -- this is monitored, so get consistent list viewerName: ROPE = "Unsaved Documents List"; ViewerOk: PROC RETURNS [BOOL] = { RETURN [viewer # NIL AND NOT viewer.destroyed AND viewer.file=NIL AND Rope.Equal[viewer.name, viewerName]] }; writer: TiogaAccess.Writer ~ TiogaAccess.Create[]; looks: TiogaAccess.Looks _ ALL[FALSE]; format: ATOM _ NIL; comment: BOOL _ FALSE; deltaLevel: INT _ 1; Put: PROC [rope: ROPE] ~ { action: PROC [c: CHAR] RETURNS [quit: BOOL _ FALSE] ~ { TiogaAccess.Put[writer, [ charSet: 0, char: c, looks: looks, format: format, comment: comment, endOfNode: (c = '\n), deltaLevel: deltaLevel, propList: NIL ]]; }; [] _ Rope.Map[base: rope, action: action]; }; IF NOT TEditProfile.showUnsavedDocumentsList THEN RETURN; IF Rope.Size[rope] = 0 THEN { IF ViewerOk[] THEN ViewerOps.DestroyViewer[viewer]; RETURN }; IF NOT ViewerOk[] THEN { viewer _ ViewerOps.CreateViewer[flavor: $Text, info: [name: viewerName, iconic: TRUE], paint: FALSE]; viewer.class.set[self: viewer, data: NIL, op: $ReadOnly]; Menus.ChangeNumberOfLines[viewer.menu, 0]; -- don't let user mess with it ViewerOps.EstablishViewerPosition[viewer, viewer.wx, viewer.wy, viewer.ww, viewer.wh]; ViewerOps.PaintViewer[viewer, all] }; format _ $note; Put["The following files were edited but not saved. They may still be restored with edits intact simply by loading them. If you really want to get rid of the edits, load the file and hit Reset.\n"]; format _ $lead; deltaLevel _ 0; Put[rope]; Put["\n"]; TiogaAccess.WriteViewer[writer, viewer]; viewer.newVersion _ TRUE; -- set edited bit ViewerOps.PaintViewer[viewer, caption] }; -- repaint the caption END. PTEditDocumentsCacheImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Edited by Paxton on October 20, 1982 8:39 am Last Edited by: Maxwell, January 6, 1983 11:10 am Last Edited by: Plass, April 10, 1985 10:17:55 am PST Michael Plass, October 19, 1987 10:37:13 am PDT Doug Wyatt, March 3, 1985 3:21:28 pm PST ΚΉ˜šœ™Icodešœ Οmœ1™Jšžœ˜—J˜J˜—š  œžœžœžœ žœ˜QJšžœžœžœ˜š œžœžœžœ˜&J˜ Jšžœžœžœžœ˜š žœžœžœ$žœžœž˜@J˜Jšžœ˜—J˜—J˜J˜šžœ$žœžœΟc!˜PJ˜—Jšœžœ,˜6Jšœžœ ˜šžœ žœ+ž˜?Jšœ˜Jšžœ˜—Jšžœžœ ˜*J˜J˜—š  œžœžœžœ žœžœ˜XJšžœžœžœ˜Jš žœ!žœžœžœžœ ˜TJ˜J˜—š  œžœ˜Jšžœžœžœžœ˜šžœžœžœ$ž˜4Jš žœ žœžœžœ‘%˜@J˜2Jšžœ˜Jšžœ˜—J˜J˜—š   œžœ žœžœ‘˜ZJšœžœžœ˜"Jš žœžœžœžœžœ˜šžœ+žœžœ˜:J˜J˜Jšžœ˜J˜—J˜ š žœžœžœ)žœžœž˜Ešžœ(žœžœ˜7J˜J˜Jšžœ˜J˜—J˜ Jšžœ˜—Jšžœžœ˜ J˜—J˜š œžœžœžœ˜Kšžœžœžœ˜Kšœžœ‘,˜LKšœ žœ˜,š œžœžœžœ˜!š žœ žœžœžœžœ žœž˜EK˜%—K˜—Kšœ2˜2Kšœžœžœ˜&Kšœžœžœ˜Kšœ žœžœ˜Kšœ žœ˜š œžœžœ˜š œžœžœžœžœžœ˜7šœ˜Jšœ ˜ Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ž˜ Jšœ˜—Jšœ˜—J•StartOfExpansionT[base: ROPE, start: INT _ 0, len: INT _ 2147483647, action: Rope.ActionType]šœ*˜*Jšœ˜—Kšžœžœ'žœžœ˜9šžœžœ˜Kšžœ žœ!˜3Kšžœ˜K˜—šžœžœ žœ˜˜GKšœžœ žœ˜—Kšœ%žœ˜9Kšœ+‘˜IK˜VK˜#K˜—K˜KšœΘ˜ΘK˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ(˜(Kšœžœ‘˜+K˜'Kšœ‘˜K˜—Jšžœ˜—J˜—…—v