<> <> <> <> <> DIRECTORY FS USING [ComponentPositions, PagesForBytes, ExpandName], IO, Menus, PopUpSelection USING [Request], Rope, TiogaOps USING [SearchDir, FindText], UserProfile USING [Token], ViewerBLT USING[ChangeNumberOfLines], ViewerClasses USING [Viewer], ViewerOps, ViewerTools USING [GetSelectionContents], WalnutNewMail USING [CheckGrapevine], WalnutOps USING [ActiveMsgSetName, DeletedMsgSetName, MsgSet, CreateMsgSet, DestroyMsgSet, EmptyMsgSet, LogLength, MsgSetExists, SizeOfDatabase, SizeOfMsgSet, WriteArchiveFile], WalnutSendOps USING [WalnutSendProc], WalnutControlInternal USING [walnutRootFile, DoWaitCall], WalnutDisplayerInternal USING [QDisplayMsgSet], WalnutPrintOps USING [PrintMsgSet, WriteMsgSets], WalnutWindowInternal USING [MsgSetButton, msgSetsVersion, msgSetsTViewer, walnut, walnutQueue, walnutTS, AddMsgSetButton, DeleteMsgSetButton, GetButton, GetSelectedMsgSets, Report, ReportRope, RetrieveNewMail], WalnutViewer USING [CreateMenuEntry], WalnutWindow USING [EnumWalnutViewers, Expunge]; WalnutWindowMenuImpl: CEDAR MONITOR IMPORTS FS, Menus, IO, PopUpSelection, Rope, UserProfile, TiogaOps, ViewerBLT, ViewerOps, ViewerTools, WalnutNewMail, WalnutOps, WalnutControlInternal, WalnutDisplayerInternal, WalnutPrintOps, WalnutSendOps, WalnutViewer, WalnutWindow, WalnutWindowInternal EXPORTS WalnutControlInternal = BEGIN OPEN WalnutControlInternal, WalnutWindowInternal; <> ROPE: TYPE = Rope.ROPE; Viewer: TYPE = ViewerClasses.Viewer; responseSynch: CONDITION; userHasResponded, userConfirmed: BOOL_ FALSE; noMsgSetsSelected: ROPE = "No seleted MsgSet(s)"; WhatToDoToMsgSets: TYPE = {nothing, empty, destroy}; <<* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *>> <<>> ChangeMenu: PUBLIC ENTRY PROC[m: Menus.Menu, isBusy: BOOL] = { ENABLE UNWIND => NULL; InternalChangeMenu[m, isBusy] }; InternalChangeMenu: INTERNAL PROC[menu: Menus.Menu, isBusy: BOOL] = { oldCount, newCount: Menus.MenuLine; IF walnut = NIL THEN RETURN; oldCount _ Menus.GetNumberOfLines[walnut.menu]; newCount _ Menus.GetNumberOfLines[menu]; walnut.menu _ menu; IF oldCount # newCount THEN ViewerBLT.ChangeNumberOfLines[walnut, newCount]; ViewerOps.PaintViewer[walnut, menu]; walnut.newVersion _ isBusy; ViewerOps.PaintViewer[walnut, caption]; }; GetUserResponse: PUBLIC ENTRY PROC[m: Menus.Menu _ NIL] RETURNS[BOOL] = { ENABLE UNWIND => NULL; InternalChangeMenu[IF m = NIL THEN confirmMenu ELSE m, FALSE]; IF walnut.iconic THEN ViewerOps.BlinkIcon[walnut, 0] ELSE ViewerOps.BlinkIcon[walnutTS]; UNTIL userHasResponded DO WAIT responseSynch; ENDLOOP; userHasResponded _ FALSE; InternalChangeMenu[workingMenu, FALSE]; RETURN[userConfirmed]; }; <<>> <<* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *>> walnutMenu: PUBLIC Menus.Menu; workingMenu: PUBLIC Menus.Menu _ Menus.CreateMenu[]; confirmMenu: Menus.Menu _ Menus.CreateMenu[]; blankMenu: PUBLIC Menus.Menu _ Menus.CreateMenu[]; startupConfirmMenu: Menus.Menu _ Menus.CreateMenu[]; forceQuitMenu: PUBLIC Menus.Menu _ Menus.CreateMenu[]; maybeQuitMenu: PUBLIC Menus.Menu _ Menus.CreateMenu[]; scavMenu: PUBLIC Menus.Menu _ Menus.CreateMenu[]; mailDBMenu: PUBLIC Menus.Menu _ Menus.CreateMenu[]; readOnlyDBMenu: PUBLIC Menus.Menu _ Menus.CreateMenu[]; nonMailDBMenu: PUBLIC Menus.Menu _ Menus.CreateMenu[]; readOnlyMsgSetOpsList: LIST OF ROPE = LIST[ "Database Info", "Size of MsgSet(s)", "PressPrint", "InterpressPrint", "Archive", "Append" ]; BuildWalnutMenus: PUBLIC PROC = { OPEN Menus; expRope: ROPE = "Will Expunge the Walnut Mail database"; <> AppendMenuEntry[mailDBMenu, CreateEntry["Sender", NewSenderProc]]; AppendMenuEntry[mailDBMenu, CreateEntry["NewMail", NewMailProc]]; AppendMenuEntry[mailDBMenu, WalnutViewer.CreateMenuEntry[walnutQueue, "CloseAll", CloseAllProc]]; AppendMenuEntry[mailDBMenu, CreateEntry["MsgSetOps", MsgSetOpsProc]]; AppendMenuEntry[mailDBMenu, CreateEntry["Find", FindProc]]; AppendMenuEntry[mailDBMenu, CreateEntry[name: "Expunge", proc: MenuExpunge, documentation: expRope, guarded: TRUE ]]; <<>> <> AppendMenuEntry[readOnlyDBMenu, CreateEntry["Sender", NewSenderProc]]; AppendMenuEntry[readOnlyDBMenu, WalnutViewer.CreateMenuEntry[walnutQueue, "CloseAll", CloseAllProc]]; AppendMenuEntry[readOnlyDBMenu, CreateEntry["MsgSetOps", ROMsgSetOpsProc]]; AppendMenuEntry[readOnlyDBMenu, CreateEntry["Find", FindProc]]; <> AppendMenuEntry[nonMailDBMenu, CreateEntry["Sender", NewSenderProc]]; AppendMenuEntry[nonMailDBMenu, WalnutViewer.CreateMenuEntry[walnutQueue, "CloseAll", CloseAllProc]]; AppendMenuEntry[nonMailDBMenu, CreateEntry["MsgSetOps", MsgSetOpsProc]]; AppendMenuEntry[nonMailDBMenu, CreateEntry["Find", FindProc]]; AppendMenuEntry[nonMailDBMenu, CreateEntry[name: "Expunge", proc: MenuExpunge, documentation: expRope, guarded: TRUE ]]; <> AppendMenuEntry[workingMenu, CreateEntry["Sender", NewSenderProc]]; AppendMenuEntry[confirmMenu, CreateEntry["Sender", NewSenderProc]]; AppendMenuEntry[confirmMenu, CreateEntry["Confirm", WWConfirmProc]]; AppendMenuEntry[confirmMenu, CreateEntry["Deny", WWDenyProc]]; AppendMenuEntry[startupConfirmMenu, CreateEntry["Continue", WWConfirmProc]]; AppendMenuEntry[startupConfirmMenu, CreateEntry["Quit", WWDenyProc]]; AppendMenuEntry[forceQuitMenu, CreateEntry["Quit", WWConfirmProc]]; AppendMenuEntry[maybeQuitMenu, CreateEntry["Quit", WWConfirmProc]]; AppendMenuEntry[maybeQuitMenu, CreateEntry["Retry", WWDenyProc]]; AppendMenuEntry[scavMenu, CreateEntry["Quit", WWDenyProc]]; AppendMenuEntry[scavMenu, CreateEntry["Scavenge", WWConfirmProc]]; }; NewSenderProc: Menus.MenuProc = { WalnutSendOps.WalnutSendProc[fromExec: FALSE]}; <> MsgSetOpsProc: Menus.MenuProc = { which: INT = PopUpSelection.Request[ header: "MessageSetOps", choice: LIST["Database Info", "Size of MsgSet(s)", "PressPrint", "Interpress3.0Print", "Write MsgSet(s) To File", "Create MsgSet", "Delete MsgSet(s)", "Make MsgSet(s) Empty", "Archive MsgSet(s)", "Append MsgSet(s)", "ArchiveAndEmpty", "AppendAndEmpty", "ArchiveAndDelete", "AppendAndDelete" ] ]; SELECT which FROM 1 => DBInfoProc[]; 2 => SizeOfMsgSetsProc[]; 3 => PrintMsgSetsProc[usePress: TRUE]; 4 => PrintMsgSetsProc[usePress: FALSE]; 5 => WriteMsgSetsProc[]; 6 => CreateMsgSetButtonProc[]; 7 => EmptyDelMsgSetsProc[del: TRUE]; 8 => EmptyDelMsgSetsProc[del: FALSE]; 9 => ArchiveOrAppend[append: FALSE, whatToDoToMsgSets: nothing]; 10 => ArchiveOrAppend[append: TRUE, whatToDoToMsgSets: nothing]; 11 => ArchiveOrAppend[append: FALSE, whatToDoToMsgSets: empty]; 12 => ArchiveOrAppend[append: TRUE, whatToDoToMsgSets: empty]; 13 => ArchiveOrAppend[append: FALSE, whatToDoToMsgSets: destroy]; 14 => ArchiveOrAppend[append: TRUE, whatToDoToMsgSets: destroy]; ENDCASE => NULL; }; ROMsgSetOpsProc: Menus.MenuProc = { which: INT = PopUpSelection.Request[ header: "MessageSetOps", choice: LIST["DB-Info", "SizeOf", "PressPrint", "InterpressPrint", "Archive", "Append"] ]; SELECT which FROM 1 => DBInfoProc[]; 2 => SizeOfMsgSetsProc[]; 3 => PrintMsgSetsProc[usePress: TRUE]; 4 => PrintMsgSetsProc[usePress: FALSE]; 5 => ArchiveOrAppend[append: FALSE, whatToDoToMsgSets: nothing]; 6 => ArchiveOrAppend[append: TRUE, whatToDoToMsgSets: nothing]; ENDCASE => NULL; }; MenuExpunge: Menus.MenuProc = { ENABLE UNWIND => ChangeMenu[walnutMenu, FALSE]; ChangeMenu[workingMenu, TRUE]; WalnutWindow.Expunge[]; }; NewMailProc: Menus.MenuProc = { IF mouseButton = blue THEN WalnutNewMail.CheckGrapevine[] ELSE WalnutWindowInternal.RetrieveNewMail[] }; CloseAllProc: Menus.MenuProc = { msgSetList, msgList: LIST OF Viewer; mpViewer: Viewer; [msgSetList, msgList] _ WalnutWindow.EnumWalnutViewers[TRUE]; FOR vL: LIST OF Viewer _ msgList, vL.rest UNTIL vL=NIL DO IF ViewerOps.FetchProp[vL.first, $Frozen] = NIL THEN ViewerOps.DestroyViewer[vL.first]; ENDLOOP; FOR vL: LIST OF Viewer _ msgSetList, vL.rest UNTIL vL=NIL DO ViewerOps.CloseViewer[vL.first]; ENDLOOP; IF (mpViewer _ ViewerOps.FindViewer["NewMail Retrieval"]) # NIL THEN ViewerOps.CloseViewer[mpViewer]; ViewerOps.CloseViewer[walnut]; }; WWDenyProc: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; userConfirmed _ FALSE; userHasResponded _ TRUE; BROADCAST responseSynch }; WWConfirmProc: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; userConfirmed _ TRUE; userHasResponded _ TRUE; BROADCAST responseSynch }; -- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * <<"immediate" buttons that gather some parameters and then queue the real proc to call>> CreateMsgSetButtonProc: PROC = { msName: ROPE _ ViewerTools.GetSelectionContents[]; Cmsb: PROC = { IF msName.Length[] = 0 THEN { Report["No MsgSet name specified"]; RETURN}; IF msName.Find[" "] >=0 THEN { Report[" MsgSet names may not contain spaces"]; RETURN}; IF WalnutOps.MsgSetExists[msName, WalnutWindowInternal.msgSetsVersion].exists THEN Report["MsgSet: ", msName, " already exists"] ELSE { WalnutOps.CreateMsgSet[msName, WalnutWindowInternal.msgSetsVersion]; [] _ AddMsgSetButton[msName, TRUE]; WalnutWindowInternal.msgSetsVersion _ WalnutWindowInternal.msgSetsVersion + 1; }; }; [] _ DoWaitCall[Cmsb]; }; SizeOfMsgSetsProc: PROC = { Sms: PROC = { msgSetList: LIST OF MsgSetButton _ GetSelectedMsgSets[]; msgSet: ROPE; IF msgSetList = NIL THEN { Report[noMsgSetsSelected]; RETURN}; FOR mL: LIST OF MsgSetButton _ msgSetList, mL.rest UNTIL mL=NIL DO num: INT _ WalnutOps.SizeOfMsgSet[msgSet _ mL.first.msgSet.name].messages; Report[IO.PutFR[" %g msgs in MsgSet %g", IO.int[num], IO.rope[msgSet]]]; ENDLOOP; }; [] _ DoWaitCall[Sms]; }; EmptyDelMsgSetsProc: PROC[del: BOOL] = { Dms: PROC = { msgSetList: LIST OF MsgSetButton _ GetSelectedMsgSets[]; name: ROPE; someInDeleted: BOOL; anyDeleted: BOOL _ TRUE; whatToDo: ROPE = IF del THEN "deleted" ELSE "empty"; IF msgSetList = NIL THEN { Report[noMsgSetsSelected, " to delete"]; RETURN}; ChangeMenu[workingMenu, TRUE]; FOR mL: LIST OF MsgSetButton _ msgSetList, mL.rest UNTIL mL=NIL DO numIn: INT; name _ mL.first.msgSet.name; IF name.Equal[WalnutOps.DeletedMsgSetName, FALSE] THEN { Report["Can't ", whatToDo, " the Deleted MsgSet"]; LOOP}; IF del THEN IF (numIn _ WalnutOps.SizeOfMsgSet[name].messages) # 0 THEN { Report[IO.PutFR[" Confirm deletion of %g messages in MsgSet: %g", IO.int[numIn], IO.rope[name]] ]; IF ~GetUserResponse[] THEN { ChangeMenu[walnutMenu, FALSE]; RETURN } }; IF del THEN { DeleteMsgSetButton[name]; someInDeleted _ WalnutOps.DestroyMsgSet[ mL.first.msgSet, WalnutWindowInternal.msgSetsVersion]; } ELSE someInDeleted _ WalnutOps.EmptyMsgSet[mL.first.msgSet]; IF ~del AND mL.first.msViewer # NIL THEN [] _ WalnutDisplayerInternal.QDisplayMsgSet[mL.first, mL.first.msViewer, FALSE]; anyDeleted _ anyDeleted OR someInDeleted; IF ~name.Equal[WalnutOps.ActiveMsgSetName, FALSE] THEN Report[IO.PutFR["\nMsgSet: %g has been %g", IO.rope[name], IO.rope[IF del THEN "deleted" ELSE "emptied"]] ] ELSE Report["\nMsgs have been removed from Active"]; IF del THEN WalnutWindowInternal.msgSetsVersion _ WalnutWindowInternal.msgSetsVersion + 1; ENDLOOP; IF anyDeleted THEN RedisplayDeleted[]; ChangeMenu[walnutMenu, FALSE]; }; [] _ DoWaitCall[Dms]; }; PrintMsgSetsProc: PROC[usePress: BOOL] = { Pms: PROC = { msgSetList: LIST OF MsgSetButton _ GetSelectedMsgSets[]; IF msgSetList = NIL THEN { Report[noMsgSetsSelected, " to print"]; RETURN }; ChangeMenu[workingMenu, TRUE]; FOR mL: LIST OF MsgSetButton _ msgSetList, mL.rest UNTIL mL=NIL DO IF ~WalnutPrintOps.PrintMsgSet[mL.first.msgSet.name, usePress] THEN EXIT; ENDLOOP; ChangeMenu[walnutMenu, FALSE]; }; [] _ DoWaitCall[Pms]; }; WriteMsgSetsProc: PROC = { Pms: PROC = { msgSetList: LIST OF MsgSetButton _ GetSelectedMsgSets[]; fileName: ROPE _ ViewerTools.GetSelectionContents[]; fullName: ROPE; cp: FS.ComponentPositions; IF fileName.Length[] = 0 THEN { Report["No fileName selected"]; RETURN }; [fullName, cp, ] _ FS.ExpandName[fileName, NIL]; IF cp.ext.length = 0 THEN fullName _ fullName.Concat[".tioga"]; IF msgSetList = NIL THEN { Report[noMsgSetsSelected, " to write to file"]; RETURN }; ChangeMenu[workingMenu, TRUE]; WalnutPrintOps.WriteMsgSets[msgSetList, fullName]; ChangeMenu[walnutMenu, FALSE]; }; [] _ DoWaitCall[Pms]; }; ArchiveOrAppend: PROC[append: BOOL, whatToDoToMsgSets: WhatToDoToMsgSets ] = { fileName: ROPE _ ViewerTools.GetSelectionContents[]; msgSetList: LIST OF MsgSetButton _ GetSelectedMsgSets[]; AorA: PROC = { ENABLE UNWIND => ChangeMenu[walnutMenu, FALSE]; anyInDeleted: BOOL _ FALSE; msList: LIST OF WalnutOps.MsgSet; ChangeMenu[workingMenu, TRUE]; FOR mL: LIST OF MsgSetButton _ msgSetList, mL.rest UNTIL mL=NIL DO msList _ CONS[mL.first.msgSet, msList]; ENDLOOP; IF ~DoArchive[fileName, msList, append] THEN { ChangeMenu[walnutMenu, FALSE]; RETURN }; IF whatToDoToMsgSets = nothing THEN { ChangeMenu[walnutMenu, FALSE]; RETURN }; ReportRope["\t", IF whatToDoToMsgSets = destroy THEN "Deleting" ELSE "Emptying", " archived msgSet(s):"]; FOR mL: LIST OF MsgSetButton _ msgSetList, mL.rest UNTIL mL = NIL DO someInDeleted: BOOL _ FALSE; name: ROPE = mL.first.msgSet.name; IF ~name.Equal[WalnutOps.DeletedMsgSetName, FALSE] THEN { IF whatToDoToMsgSets = destroy THEN DeleteMsgSetButton[name]; ReportRope[" ", name]; IF whatToDoToMsgSets = destroy THEN someInDeleted _ WalnutOps.DestroyMsgSet[ mL.first.msgSet, WalnutWindowInternal.msgSetsVersion ] ELSE someInDeleted _ WalnutOps.EmptyMsgSet[mL.first.msgSet ]; IF whatToDoToMsgSets # destroy AND mL.first.msViewer # NIL THEN [] _ WalnutDisplayerInternal.QDisplayMsgSet[mL.first, mL.first.msViewer, FALSE]; IF whatToDoToMsgSets = destroy THEN WalnutWindowInternal.msgSetsVersion _ WalnutWindowInternal.msgSetsVersion + 1; anyInDeleted _ anyInDeleted OR someInDeleted; }; ENDLOOP; ReportRope["\n"]; IF anyInDeleted THEN RedisplayDeleted[]; ChangeMenu[walnutMenu, FALSE]; }; [] _ DoWaitCall[AorA]; }; DoArchive: PUBLIC PROC[fileName: ROPE, msList: LIST OF WalnutOps.MsgSet, append: BOOL] RETURNS[ok: BOOL] = { fullName: ROPE; num: INT _ 0; ok _ FALSE; IF fileName.Length[] = 0 THEN { Report["No Archive file specified"]; RETURN}; IF msList = NIL THEN { Report[noMsgSetsSelected, " to archive"]; RETURN}; <> BEGIN cp: FS.ComponentPositions; wDir: ROPE _ UserProfile.Token["Walnut.DefaultArchiveDir"]; [fullName, cp, ] _ FS.ExpandName[fileName, wDir]; IF cp.ext.length = 0 THEN fullName _ fullName.Concat[".ArchiveLog"]; END; IF Rope.Equal[fullName, walnutRootFile, FALSE] THEN { Report["Can't archive on log file"]; RETURN}; IF append THEN Report["Appending msgs to the file: ", fileName]; ReportRope["Archiving the MsgSet(s): "]; FOR mL: LIST OF WalnutOps.MsgSet _ msList, mL.rest UNTIL mL = NIL DO msName: ROPE = mL.first.name; this: INT _ WalnutOps.SizeOfMsgSet[msName].messages; ReportRope[msName, IO.PutFR[" (%g messages) ", IO.int[this]]]; num _ num + this; ok _ WalnutOps.WriteArchiveFile[file: fullName, msgSetList: LIST[mL.first], append: append]; IF ~ok THEN EXIT; append _ TRUE; -- always true after the first write ENDLOOP; IF ~ok THEN RETURN[FALSE]; Report[IO.PutFR["\n %g messages archived on file: %g", IO.int[num], IO.rope[fullName]]]; RETURN[TRUE] }; DBInfoProc: PROC = { len: INT _ WalnutOps.LogLength[]; numIn: INT _ WalnutOps.SizeOfMsgSet[WalnutOps.DeletedMsgSetName].messages; messages, msgSets: INT; [messages, msgSets] _ WalnutOps.SizeOfDatabase[]; Report[IO.PutFR[" The log file is %g bytes (%g pages) long", IO.int[len], IO.int[FS.PagesForBytes[len]]]]; Report[IO.PutFR[ " There are %g deleted msgs, (%g total msgs), & %g msgSets", IO.int[numIn], IO.int[messages], IO.int[msgSets] ]]; }; RedisplayDeleted: PROC = { msb: MsgSetButton _ GetButton[WalnutOps.DeletedMsgSetName]; IF msb.msViewer = NIL THEN RETURN; [] _ WalnutDisplayerInternal.QDisplayMsgSet[msb, msb.msViewer, FALSE]; }; FindProc: Menus.MenuProc = { IF ~TiogaOps.FindText[ viewer: WalnutWindowInternal.msgSetsTViewer, whichDir: GetDirection[mouseButton], which: feedback, case: ~shift] THEN ViewerOps.BlinkIcon[WalnutWindowInternal.msgSetsTViewer]; }; GetDirection: PROC[mb: Menus.MouseButton] RETURNS[sd: TiogaOps.SearchDir] = { SELECT mb FROM red => RETURN[forwards]; yellow => RETURN[anywhere]; blue => RETURN[backwards]; ENDCASE; }; <<* * * * * * * * * *>> END.