WalnutWindowMenuImpl.mesa
Copyright Ó 1985, 1987, 1988, 1989, 1992 by Xerox Corporation. All rights reserved.
Willie-Sue, August 8, 1989 3:23:00 pm PDT
Jack Kent, April 7, 1987 8:17:28 am PST
Swinehart, February 26, 1991 5:01 pm PST
Doug Terry, October 2, 1992 10:28 am PDT
Willie-s, April 27, 1992 2:58 pm PDT
(Christian Jacobi, August 23, 1993 12:03 pm PDT)
Contents: Menu control for the Top level Viewer for Walnut
created March, 1985 by Willie-Sue
DIRECTORY
BasicTime USING [Now],
Buttons USING [ButtonProc, Create],
Containers USING [ChildXBound],
Convert USING [Error, IntFromRope],
FS USING [ComponentPositions, PagesForBytes, ExpandName],
Menus,
PopUpSelection USING [Request],
Process USING [DisableTimeout, Ticks, SecondsToTicks, SetTimeout],
Rope,
SendMailOps USING [CreateSendViewer],
TEditDocument USING [TEditDocumentData],
Tioga USING [Node],
TiogaButtons USING [GetState, MarkViewerNotEdited, SetState],
TiogaMenuOps USING [Store],
TiogaOps USING [SearchDir, FindText],
UserProfile USING [Boolean, Token],
ViewerBLT USING[ChangeNumberOfLines],
ViewerClasses USING [Viewer],
ViewerOps,
ViewerTools USING [GetContents, GetSelectedViewer, GetSelectionContents, SetSelection],
Wallaby USING [QueryProc],
WalnutFilter USING [MenuExtras],
WalnutNewMail USING [CheckMailBoxes],
WalnutOps USING [ActiveName, CreateMsgSet, DeletedName, DestroyMsgSet, dontCareDomainVersion, EmptyMsgSet, GetCategories, LogLength, MsgSet, MsgSetExists, MsgsInSetEnumeration, RemoveMsg, SizeOfDatabase, SizeOfMsgSet, WriteArchiveFile],
WalnutInternal USING [AddMsgSetButton, DeleteMsgSetButton, DoWaitCall, DoAppendMsg, GetButton, GetSelectedMsgSets, HowToPrint, PrepareToEditMsgSetButtons, PrintMsgCmd, PrintMsgSet, PrintMsgSetCmd, PrintMsgSetTOCCmd, PrintSelCmd, QDisplayMsg, QDisplayMsgSet, ShowMsgSetButtons, WriteMsgSets],
WalnutWindowPrivate,
WalnutViewer USING [CreateMenuEntry, ImmediateButton, buttonEntryHeight, NextRightTextViewer],
WalnutWindow USING [GetNewMail, Expunge, ReadArchiveFile, Report, ReportFormat, ReportRope, SelectMsgSetsFromMSNames];
WalnutWindowMenuImpl: CEDAR MONITOR
IMPORTS
BasicTime, Buttons, Containers, Convert, FS, Menus, PopUpSelection, Process, Rope, SendMailOps, UserProfile,
TiogaButtons, TiogaMenuOps, TiogaOps,
ViewerBLT, ViewerOps, ViewerTools, Wallaby,
WalnutFilter, WalnutNewMail, WalnutOps,
WalnutInternal,
WalnutViewer, WalnutWindow
EXPORTS WalnutInternal, WalnutWindow
SHARES ViewerClasses =
BEGIN OPEN WalnutInternal;
Walnut Viewers types and global data
ROPE: TYPE = Rope.ROPE;
Viewer: TYPE = ViewerClasses.Viewer;
buttonEntryHeight: INTEGER = WalnutViewer.buttonEntryHeight;
noMsgSetsSelected: ROPE = "No seleted MsgSet(s)";
WhatToDoToMsgSets: TYPE = {nothing, empty, destroy};
OldMailOrPrint: TYPE = {oldMail, printing};
OldMailReader: TYPE = WalnutWindowPrivate.OldMailReader;
OldMailReaderRec: TYPE = WalnutWindowPrivate.OldMailReaderRec;
PrintingOptions: TYPE = WalnutWindowPrivate.PrintingOptions;
PrintingOptionsRec: TYPE = WalnutWindowPrivate.PrintingOptionsRec;
MsgAndHandle: TYPE = WalnutWindowPrivate.MsgAndHandle;
MsgSetButton: TYPE = WalnutWindowPrivate.MsgSetButton;
WalnutHandle: TYPE = WalnutWindowPrivate.WalnutHandle;
WalnutHandleRec: PUBLIC TYPE = WalnutWindowPrivate.WalnutHandleRec;
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
ChangeMenu: PUBLIC ENTRY PROC[wH: WalnutHandle, m: Menus.Menu, isBusy: BOOL] = {
ENABLE UNWIND => NULL;
InternalChangeMenu[wH, m, isBusy]
};
InternalChangeMenu: INTERNAL PROC[wH: WalnutHandle, menu: Menus.Menu, isBusy: BOOL] = {
oldCount, newCount: Menus.MenuLine;
IF wH.walnut = NIL THEN RETURN;
oldCount ¬ Menus.GetNumberOfLines[wH.walnut.menu];
newCount ¬ Menus.GetNumberOfLines[menu];
wH.walnut.menu ¬ menu;
IF oldCount # newCount THEN ViewerBLT.ChangeNumberOfLines[wH.walnut, newCount];
ViewerOps.PaintViewer[wH.walnut, menu];
wH.walnut.newVersion ¬ isBusy;
ViewerOps.PaintViewer[wH.walnut, caption];
};
GetUserResponse: PUBLIC ENTRY PROC[wH: WalnutHandle, m: Menus.Menu ¬ NIL, tryAutoConfirm: BOOL ¬ FALSE]
RETURNS[BOOL] = {
ENABLE UNWIND => NULL;
autoConfirm: BOOL = UserProfile.Boolean["Walnut.AutoConfirmRetry", FALSE];
InternalChangeMenu[wH, IF m = NIL THEN wH.confirmMenu ELSE m, FALSE];
IF wH.walnut.iconic THEN ViewerOps.BlinkIcon[wH.walnut, 0] ELSE ViewerOps.BlinkIcon[wH.walnutTS];
IF ( NOT tryAutoConfirm ) OR ( NOT autoConfirm ) THEN
{ UNTIL wH.userHasResponded DO WAIT wH.responseSynch; ENDLOOP }
ELSE {
TRUSTED { Process.SetTimeout[@wH.responseSynch, autoTimeoutTicks] };
WAIT wH.responseSynch;
TRUSTED { Process.DisableTimeout[@wH.responseSynch] };
IF NOT wH.userHasResponded THEN {
wH.userConfirmed ¬ FALSE;
WalnutWindow.ReportFormat[wH, "\n*** Auto Retry @ %g\n", [time[BasicTime.Now[]]]];
};
};
wH.userHasResponded ¬ FALSE;
InternalChangeMenu[wH, workingMenu, FALSE];
RETURN[wH.userConfirmed];
};
autoTimeoutTicks: Process.Ticks ¬ Process.SecondsToTicks[60*10];
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
workingMenu: PUBLIC Menus.Menu ¬ Menus.CreateMenu[];
blankMenu: PUBLIC Menus.Menu ¬ Menus.CreateMenu[];
BuildWalnutMenus: PUBLIC PROC[wH: WalnutHandle] = {
OPEN Menus;
menu: Menu ¬ Menus.CreateMenu[];
menu for personal mail database
AppendMenuEntry[menu, CreateEntry["Sender", NewSenderProc, wH]];
AppendMenuEntry[menu, CreateEntry["NewMail", NewMailProc, wH]];
AppendMenuEntry[menu,
WalnutViewer.CreateMenuEntry[wH.walnutQueue, "CloseAll", CloseAllProc, wH]];
AppendMenuEntry[menu, CreateEntry["MsgSetOps", MsgSetOpsProc, wH]];
AppendMenuEntry[menu, CreateEntry["Find", FindProc, wH]];
AppendMenuEntry[menu, CreateEntry["Query", Wallaby.QueryProc, wH]];
FOR added: Menus.MenuEntry ¬ WalnutFilter.MenuExtras[$main], added.link UNTIL added = NIL DO
AppendMenuEntry[menu, CreateEntry[added.name, added.proc, wH]];
ENDLOOP;
AppendMenuEntry[menu,
CreateEntry[name: "Expunge", proc: MenuExpunge, clientData: wH, guarded: TRUE]];
wH.mailDBMenu ¬ menu;
menu ¬ Menus.CreateMenu[];
menu for read only database
AppendMenuEntry[menu, CreateEntry["Sender", NewSenderProc, wH]];
AppendMenuEntry[menu,
WalnutViewer.CreateMenuEntry[wH.walnutQueue, "CloseAll", CloseAllProc, wH]];
AppendMenuEntry[menu, CreateEntry["MsgSetOps", ROMsgSetOpsProc, wH]];
AppendMenuEntry[menu, CreateEntry["Find", FindProc, wH]];
AppendMenuEntry[menu, CreateEntry["Query", Wallaby.QueryProc, wH]];
FOR added: Menus.MenuEntry ¬ WalnutFilter.MenuExtras[$main], added.link UNTIL added = NIL DO
AppendMenuEntry[menu, CreateEntry[added.name, added.proc, wH]];
ENDLOOP;
wH.readOnlyDBMenu ¬ menu;
menu ¬ Menus.CreateMenu[];
menu for nonMail writeable database
AppendMenuEntry[menu, CreateEntry["Sender", NewSenderProc, wH]];
AppendMenuEntry[menu,
WalnutViewer.CreateMenuEntry[wH.walnutQueue, "CloseAll", CloseAllProc, wH]];
AppendMenuEntry[menu, CreateEntry["MsgSetOps", MsgSetOpsProc, wH]];
AppendMenuEntry[menu, CreateEntry["Query", Wallaby.QueryProc, wH]];
AppendMenuEntry[menu, CreateEntry["Find", FindProc, wH]];
FOR added: Menus.MenuEntry ¬ WalnutFilter.MenuExtras[$main], added.link UNTIL added = NIL DO
AppendMenuEntry[menu, CreateEntry[added.name, added.proc, wH]];
ENDLOOP;
AppendMenuEntry[menu,
CreateEntry[name: "Expunge", proc: MenuExpunge, clientData: wH, guarded: TRUE]];
wH.nonMailDBMenu ¬ menu;
menu ¬ Menus.CreateMenu[];
AppendMenuEntry[menu, CreateEntry["Sender", NewSenderProc]];
AppendMenuEntry[menu, CreateEntry["Confirm", WWConfirmProc, wH]];
AppendMenuEntry[menu, CreateEntry["Deny", WWDenyProc, wH]];
wH.confirmMenu ¬ menu;
wH.forceQuitMenu ¬ Menus.CreateMenu[];
AppendMenuEntry[wH.forceQuitMenu, CreateEntry["Quit", WWConfirmProc, wH]];
menu ¬ Menus.CreateMenu[];
AppendMenuEntry[menu, CreateEntry["Quit", WWConfirmProc, wH]];
AppendMenuEntry[menu, CreateEntry["Retry", WWDenyProc, wH]];
wH.maybeQuitMenu ¬ menu;
menu ¬ Menus.CreateMenu[];
AppendMenuEntry[menu, CreateEntry["Quit", WWDenyProc, wH]];
AppendMenuEntry[menu, CreateEntry["Scavenge", WWConfirmProc, wH]];
wH.scavMenu ¬ menu;
};
NewSenderProc: Menus.MenuProc = { [] ¬ SendMailOps.CreateSendViewer[fromExec: FALSE]};
Create a new blank form in a viewer for user to send msg with.
MsgSetOpsProc: Menus.MenuProc = {
wH: WalnutHandle = NARROW[clientData];
isEditted: BOOL = TiogaButtons.GetState[wH.msgSetsTViewer] = editing;
edRope: ROPE = IF isEditted THEN "Save msgSetButtons"
ELSE "Edit msgSetButtons";
which: INT =
PopUpSelection.Request[
header: "MessageSetOps",
choice: LIST[
"Database Info", "Size of MsgSet(s)",
"Create MsgSet", "Delete MsgSet(s)", "Make MsgSet(s) Empty", "R.O.T. MsgSet",
edRope, "Append Msg to MsgSet(s)",
"PressPrint", "Interpress2.0Print", "Interpress3.0Print", "Write MsgSet(s) To File",
"Write MsgSet TOCs To File", "Archive MsgSet(s)", "Append MsgSet(s)",
"ArchiveAndEmpty", "AppendAndEmpty", "ArchiveAndDelete", "AppendAndDelete",
"DisplayMsgFromName", "OldMailReaderOptions", "Printing Options"
] ];
SELECT which FROM
1 => DBInfoProc[wH];
2 => SizeOfMsgSetsProc[wH];
3 => CreateMsgSetButtonProc[wH];
4 => EmptyDelMsgSetsProc[wH: wH, del: TRUE];
5 => EmptyDelMsgSetsProc[wH: wH, del: FALSE];
6 => {
rootMsgSet: ROPE = ViewerTools.GetSelectionContents[];
msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH];
ChangeMenu[wH, workingMenu, TRUE];
[] ¬ DoRemoveOverThere[wH, rootMsgSet, msgSetList];
ChangeMenu[wH, wH.walnutMenu, FALSE];
};
7 => IF isEditted THEN SaveMsgSetButtonsProc[wH: wH] ELSE PrepareToEditMsgSetButtons[wH];
8 => AppendMsgProc[wH: wH];
9 => PrintMsgSetsProc[wH: wH, howToPrint: press];
10 => PrintMsgSetsProc[wH: wH, howToPrint: ip2];
11 => PrintMsgSetsProc[wH: wH, howToPrint: ip3];
12 => WriteMsgSetsProc[wH: wH, tocsOnly: FALSE];
13 => WriteMsgSetsProc[wH: wH, tocsOnly: TRUE];
14 => ArchiveOrAppend[wH: wH, append: FALSE, whatToDoToMsgSets: nothing];
15 => ArchiveOrAppend[wH: wH, append: TRUE, whatToDoToMsgSets: nothing];
16 => ArchiveOrAppend[wH: wH, append: FALSE, whatToDoToMsgSets: empty];
17 => ArchiveOrAppend[wH: wH, append: TRUE, whatToDoToMsgSets: empty];
18 => ArchiveOrAppend[wH: wH, append: FALSE, whatToDoToMsgSets: destroy];
19 => ArchiveOrAppend[wH: wH, append: TRUE, whatToDoToMsgSets: destroy];
20 => DoMsg[wH];
21 => SetupOptions[wH, oldMail];
22 => SetupOptions[wH, printing];
ENDCASE => NULL;
};
DoMsg: PROC[wH: WalnutHandle] = {
Dms: PROC = {
msg: ROPE = ViewerTools.GetSelectionContents[];
v: Viewer = QDisplayMsg[wH, msg, NIL, FALSE];
IF v = NIL THEN {
WalnutWindow.ReportFormat[wH, "Msg \"%g\" doesn't exist\n", [rope[msg]] ];
};
};
[] ¬ DoWaitCall[wH, Dms];
};
SaveMsgSetButtonsProc: PROC[wH: WalnutHandle] = {
root: Tioga.Node = NARROW[wH.msgSetsTViewer.data, TEditDocument.TEditDocumentData].text;
TiogaMenuOps.Store[wH.msgSetsTViewer, wH.localMsgSetButtonsFile];
TiogaButtons.MarkViewerNotEdited[root];
TiogaButtons.SetState[wH.msgSetsTViewer, buttoning];
IF wH.msgSetButtonsFile = NIL THEN RETURN;
[] ← FS.Copy[from: wH.localMsgSetButtonsFile, to: wH.msgSetButtonsFile]; -- to alpine
They are one and the same in PCedar! DCS, February 26, 1991 4:46:07 pm PST
};
ROMsgSetOpsProc: Menus.MenuProc = {
wH: WalnutHandle = NARROW[clientData];
which: INT =
PopUpSelection.Request[
header: "MessageSetOps",
choice: LIST["DB-Info", "SizeOf", "PressPrint",
"Interpress2.0Print", "Interpress3.0Print", "Archive", "Append",
"DisplayMsgFromName", "Printing Options"]
];
SELECT which FROM
1 => DBInfoProc[wH];
2 => SizeOfMsgSetsProc[wH];
3 => PrintMsgSetsProc[wH: wH, howToPrint: press];
4 => PrintMsgSetsProc[wH: wH, howToPrint: ip2];
5 => PrintMsgSetsProc[wH: wH, howToPrint: ip3];
6 => ArchiveOrAppend[wH: wH, append: FALSE, whatToDoToMsgSets: nothing];
7 => ArchiveOrAppend[wH: wH, append: TRUE, whatToDoToMsgSets: nothing];
8 => DoMsg[wH];
9 => SetupOptions[wH, printing];
ENDCASE => NULL;
};
MenuExpunge: Menus.MenuProc = {
wH: WalnutHandle = NARROW[clientData];
{ ENABLE UNWIND => ChangeMenu[wH, wH.walnutMenu, FALSE];
WalnutWindow.Report[wH, "You might try the DoWalnutCompact command instead (because expunge only clears the LoganBerry database instead the log)"];
ChangeMenu[wH, workingMenu, TRUE];
WalnutWindow.Expunge[wH];
};
};
NewMailProc: Menus.MenuProc = {
wH: WalnutHandle = NARROW[clientData];
IF mouseButton = blue THEN WalnutNewMail.CheckMailBoxes[wH.opsH]
ELSE WalnutWindow.GetNewMail[wH]
};
CloseAllProc: Menus.MenuProc = {
wH: WalnutHandle = NARROW[clientData];
FOR vL: LIST OF Viewer ¬ wH.msgViewerList, vL.rest UNTIL vL=NIL DO
IF ViewerOps.FetchProp[vL.first, $Frozen] = NIL THEN ViewerOps.DestroyViewer[vL.first];
vL.first ¬ NIL;
ENDLOOP;
wH.msgViewerList ¬ NIL;
FOR vL: LIST OF Viewer ¬ wH.msgSetViewerList, vL.rest UNTIL vL=NIL DO
IF NOT vL.first.destroyed THEN ViewerOps.CloseViewer[vL.first]; ENDLOOP;
and also close the wallaby viewers
FOR vL: LIST OF Viewer ¬ wH.wallabyViewerList, vL.rest UNTIL vL=NIL DO
IF NOT vL.first.destroyed THEN ViewerOps.CloseViewer[vL.first]; ENDLOOP;
IF wH.newMailRetrievalViewer # NIL THEN ViewerOps.CloseViewer[wH.newMailRetrievalViewer];
ViewerOps.CloseViewer[wH.walnut];
};
WWDenyProc: ENTRY Menus.MenuProc = {
wH: WalnutHandle = NARROW[clientData];
BEGIN ENABLE UNWIND => NULL;
wH.userConfirmed ¬ FALSE;
wH.userHasResponded ¬ TRUE;
BROADCAST wH.responseSynch;
END;
};
WWConfirmProc: ENTRY Menus.MenuProc = {
wH: WalnutHandle = NARROW[clientData];
BEGIN ENABLE UNWIND => NULL;
wH.userConfirmed ¬ TRUE;
wH.userHasResponded ¬ TRUE;
BROADCAST wH.responseSynch;
END;
};
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
"immediate" buttons that gather some parameters and then queue the real proc to call
CreateMsgSetButtonProc: PROC[wH: WalnutHandle] = {
msName: ROPE ¬ ViewerTools.GetSelectionContents[];
Cmsb: PROC = {
IF msName.Length[] = 0 THEN
{ WalnutWindow.Report[wH, "No MsgSet name specified"]; RETURN};
IF msName.Find[" "] >=0 THEN
{ WalnutWindow.Report[wH, " MsgSet names may not contain spaces"]; RETURN};
IF msName.Find["\n"] >=0 THEN
{ WalnutWindow.Report[wH, " MsgSet names may not contain CRs"]; RETURN};
IF WalnutOps.MsgSetExists[wH.opsH, msName, wH.msgSetsVersion].exists
THEN {
WalnutWindow.Report[wH, "MsgSet: ", msName, " already exists"];
[] ¬ WalnutWindow.SelectMsgSetsFromMSNames[wH, LIST[msName] ];
}
ELSE {
WalnutOps.CreateMsgSet[wH.opsH, msName, wH.msgSetsVersion];
[] ¬ AddMsgSetButton[wH, msName, TRUE];
wH.msgSetsVersion ¬ wH.msgSetsVersion + 1;
WalnutWindow.Report[wH, "\nMsgSet: ", msName, " has been created"];
};
};
[] ¬ DoWaitCall[wH, Cmsb];
};
SizeOfMsgSetsProc: PROC[wH: WalnutHandle] = {
msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH];
Sms: PROC = {
msgSet: ROPE;
IF msgSetList = NIL THEN { WalnutWindow.Report[wH, noMsgSetsSelected]; RETURN};
FOR mL: LIST OF MsgSetButton ¬ msgSetList, mL.rest UNTIL mL=NIL DO
num: INT ¬ WalnutOps.SizeOfMsgSet[wH.opsH, msgSet ¬ mL.first.msgSet.name].messages;
WalnutWindow.ReportFormat[wH, " %g msgs in MsgSet %g\n",
 [integer[num]], [rope[msgSet]] ];
ENDLOOP;
};
[] ¬ DoWaitCall[wH, Sms];
};
EmptyDelMsgSetsProc: PROC[wH: WalnutHandle, del: BOOL] = {
msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH];
Dms: PROC = {
name: ROPE;
someInDeleted: BOOL;
anyDeleted: BOOL ¬ TRUE;
whatToDo: ROPE = IF del THEN "deleted" ELSE "empty";
IF msgSetList = NIL THEN
{ WalnutWindow.Report[wH, noMsgSetsSelected, " to delete"]; RETURN};
ChangeMenu[wH, 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.DeletedName, FALSE] THEN
{ WalnutWindow.Report[wH, "Can't ", whatToDo, " the Deleted MsgSet"]; LOOP};
IF (numIn ¬ WalnutOps.SizeOfMsgSet[wH.opsH, name].messages) # 0 THEN {
WalnutWindow.ReportFormat[wH, " Confirm deletion of %g messages in MsgSet: %g\n",
[integer[numIn]], [rope[name]] ];
IF NOT GetUserResponse[wH] THEN
{ ChangeMenu[wH, wH.walnutMenu, FALSE]; RETURN }
};
IF del THEN {
DeleteMsgSetButton[wH, name];
someInDeleted ¬ WalnutOps.DestroyMsgSet[wH.opsH,
mL.first.msgSet, wH.msgSetsVersion];
}
ELSE someInDeleted ¬ WalnutOps.EmptyMsgSet[wH.opsH, mL.first.msgSet];
IF ~del AND mL.first.msViewer # NIL THEN
[] ¬ QDisplayMsgSet[wH, mL.first, mL.first.msViewer, FALSE];
anyDeleted ¬ anyDeleted OR someInDeleted;
IF ~name.Equal[WalnutOps.ActiveName, FALSE] THEN
WalnutWindow.ReportFormat[wH, "\nMsgSet: %g has been %g\n",
[rope[name]], [rope[IF del THEN "deleted" ELSE "emptied"]] ]
ELSE WalnutWindow.Report[wH, "\nMsgs have been removed from Active"];
IF del THEN wH.msgSetsVersion ¬ wH.msgSetsVersion + 1;
ENDLOOP;
IF anyDeleted THEN RedisplayDeleted[wH];
ChangeMenu[wH, wH.walnutMenu, FALSE];
};
[] ¬ DoWaitCall[wH, Dms];
};
RemoveOverThereMsgSetsProc: PROC[wH: WalnutHandle] = {
rootMsgSet: ROPE = ViewerTools.GetSelectionContents[];
msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH];
ChangeMenu[wH, workingMenu, TRUE];
[] ¬ DoRemoveOverThere[wH, rootMsgSet, msgSetList];
ChangeMenu[wH, wH.walnutMenu, FALSE];
};
DoRemoveOverThere: PUBLIC PROC[wH: WalnutHandle, rootMsgSet: ROPE, msgSetList: LIST OF MsgSetButton] = {
Rot: PROC = {
IF ~WalnutOps.MsgSetExists[wH.opsH, rootMsgSet, WalnutOps.dontCareDomainVersion].exists THEN {
WalnutWindow.ReportFormat[wH,
"MsgSet \"%g\" doesn't exist so can't do r.o.t.", [rope[rootMsgSet]] ];
RETURN;
};
IF rootMsgSet.Equal[WalnutOps.DeletedName, FALSE] THEN
{ WalnutWindow.Report[wH, "R.O.T. on Deleted is a noOp"]; RETURN };
crank out NextMsgInMsgSet until we're at end of msgset
WalnutWindow.Report[wH, "Starting R.O.T. of rootMsgSet ", rootMsgSet];
FOR msgs: LIST OF ROPE ¬ WalnutOps.MsgsInSetEnumeration[wH.opsH, rootMsgSet].mL, msgs.rest UNTIL msgs=NIL DO
thisMsg: ROPE;
catList: LIST OF ROPE ¬ WalnutOps.GetCategories[wH.opsH, thisMsg ¬ msgs.first];
for every message...get its categories
if msgSetList = nil then for every other message set that it belongs to...remove it from that message set, else remove msg from only those msgSets in msgSetList
FOR catList ¬ catList, catList.rest UNTIL catList = NIL DO
thisMsgSet: ROPE;
IF NOT Rope.Equal[thisMsgSet ¬ catList.first, rootMsgSet, FALSE] THEN {
IF msgSetList = NIL THEN
in this context, we know deleted is false...
[] ¬ WalnutOps.RemoveMsg[wH.opsH, thisMsg, [thisMsgSet], wH.msgSetsVersion]
ELSE
FOR lmsb: LIST OF MsgSetButton ¬ msgSetList, lmsb.rest UNTIL lmsb=NIL DO
IF Rope.Equal[lmsb.first.msgSet.name, thisMsgSet, FALSE] THEN
[] ¬ WalnutOps.RemoveMsg[wH.opsH, thisMsg, [lmsb.first.msgSet.name], wH.msgSetsVersion]
ENDLOOP;
};
ENDLOOP;
ENDLOOP;
ShowMsgSetButtons[wH];
update any displayed msgSets
WalnutWindow.Report[wH, " Done with R. O. T."];
};
IF rootMsgSet.Length[] = 0 THEN
{ WalnutWindow.Report[wH, "No root message set for r.o.t."]; RETURN };
[] ¬ DoWaitCall[wH, Rot];
};
AppendMsgProc: PROC[wH: WalnutHandle] = {
msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH];
curSel: ROPE = ViewerTools.GetSelectionContents[];
curV: Viewer = ViewerTools.GetSelectedViewer[];
DoAppendMsg[wH, curSel, curV, msgSetList];
};
PrintMsgSetsProc: PROC[wH: WalnutHandle, howToPrint: HowToPrint] = {
msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH];
Pms: PROC = {
IF msgSetList = NIL THEN
{ WalnutWindow.Report[wH, noMsgSetsSelected, " to print"]; RETURN };
ChangeMenu[wH, workingMenu, TRUE];
FOR mL: LIST OF MsgSetButton ¬ msgSetList, mL.rest UNTIL mL=NIL DO
IF ~PrintMsgSet[wH, mL.first.msgSet.name, howToPrint] THEN EXIT;
ENDLOOP;
ChangeMenu[wH, wH.walnutMenu, FALSE];
};
[] ¬ DoWaitCall[wH, Pms];
};
WriteMsgSetsProc: PROC[wH: WalnutHandle, tocsOnly: BOOL] = {
Pms: PROC = {
msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH];
fileName: ROPE ¬ ViewerTools.GetSelectionContents[];
fullName: ROPE;
cp: FS.ComponentPositions;
IF fileName.Length[] = 0 THEN {
WalnutWindow.Report[wH, "No fileName selected"];
RETURN
};
[fullName, cp, ] ¬ FS.ExpandName[fileName, NIL];
IF cp.ext.length = 0 THEN fullName ¬ fullName.Concat[".tioga"];
IF msgSetList = NIL THEN
{ WalnutWindow.Report[wH, noMsgSetsSelected, " to write to file"]; RETURN };
ChangeMenu[wH, workingMenu, TRUE];
WriteMsgSets[wH, msgSetList, tocsOnly, fullName];
ChangeMenu[wH, wH.walnutMenu, FALSE];
};
[] ¬ DoWaitCall[wH, Pms];
};
ArchiveOrAppend: PROC[wH: WalnutHandle, append: BOOL, whatToDoToMsgSets: WhatToDoToMsgSets ] = {
fileName: ROPE ¬ ViewerTools.GetSelectionContents[];
msgSetList: LIST OF MsgSetButton ¬ GetSelectedMsgSets[wH];
AorA: PROC = {
ENABLE UNWIND => ChangeMenu[wH, wH.walnutMenu, FALSE];
anyInDeleted: BOOL ¬ FALSE;
msList: LIST OF WalnutOps.MsgSet;
ChangeMenu[wH, workingMenu, TRUE];
FOR mL: LIST OF MsgSetButton ¬ msgSetList, mL.rest UNTIL mL=NIL DO
msList ¬ CONS[mL.first.msgSet, msList]; ENDLOOP;
IF ~DoArchive[wH, fileName, msList, append] THEN
{ ChangeMenu[wH, wH.walnutMenu, FALSE]; RETURN };
IF whatToDoToMsgSets = nothing THEN
{ ChangeMenu[wH, wH.walnutMenu, FALSE]; RETURN };
WalnutWindow.ReportRope[wH, "\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.DeletedName, FALSE] THEN {
IF whatToDoToMsgSets = destroy THEN DeleteMsgSetButton[wH, name];
WalnutWindow.ReportRope[wH, " ", name];
IF whatToDoToMsgSets = destroy THEN
someInDeleted ¬ WalnutOps.DestroyMsgSet[wH.opsH,
mL.first.msgSet, wH.msgSetsVersion ]
ELSE someInDeleted ¬ WalnutOps.EmptyMsgSet[wH.opsH, mL.first.msgSet ];
IF whatToDoToMsgSets # destroy AND mL.first.msViewer # NIL THEN
[] ¬ QDisplayMsgSet[wH, mL.first, mL.first.msViewer, FALSE];
IF whatToDoToMsgSets = destroy THEN wH.msgSetsVersion ¬ wH.msgSetsVersion + 1;
anyInDeleted ¬ anyInDeleted OR someInDeleted;
};
ENDLOOP;
WalnutWindow.ReportRope[wH, "... Done\n"];
IF anyInDeleted THEN RedisplayDeleted[wH];
ChangeMenu[wH, wH.walnutMenu, FALSE];
};
[] ¬ DoWaitCall[wH, AorA];
};
DoArchive: PUBLIC PROC[wH: WalnutHandle, fileName: ROPE, msList: LIST OF WalnutOps.MsgSet, append: BOOL]
RETURNS[ok: BOOL] = {
fullName: ROPE;
num: INT ¬ 0;
ok ¬ FALSE;
IF msList = NIL THEN
{ WalnutWindow.Report[wH, noMsgSetsSelected, " to archive"]; RETURN};
IF fileName.IsEmpty[] THEN {
IF msList.rest = NIL THEN fileName ¬ msList.first.name -- if only one message set is selected, then create a filename
ELSE {
WalnutWindow.Report[wH, "No Archive file specified for selected message sets"];
RETURN
};
};
make sure didn't specify same name as log file
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, wH.opsH.rootName, FALSE] THEN
{ WalnutWindow.Report[wH, "Can't archive on log file"]; RETURN};
IF append THEN WalnutWindow.Report[wH, "Appending msgs to the file: ", fileName];
WalnutWindow.ReportRope[wH, "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[wH.opsH, msName].messages;
WalnutWindow.ReportFormat[wH, "%g (%g messages) ", [rope[msName]], [integer[this]]];
num ¬ num + this;
ok ¬ WalnutOps.WriteArchiveFile[wH.opsH, fullName, LIST[mL.first], append];
IF ~ok THEN EXIT;
append ¬ TRUE;  -- always true after the first write
ENDLOOP;
IF ~ok THEN RETURN[FALSE];
WalnutWindow.ReportFormat[wH, "\n %g messages archived on file: %g\n", [integer[num]], [rope[fullName]] ];
RETURN[TRUE]
};
DBInfoProc: PROC[wH: WalnutHandle] = {
Dbi: PROC = {
len: INT ¬ WalnutOps.LogLength[wH.opsH];
numIn: INT ¬ WalnutOps.SizeOfMsgSet[wH.opsH, WalnutOps.DeletedName].messages;
messages, msgSets: INT;
[messages, msgSets] ¬ WalnutOps.SizeOfDatabase[wH.opsH];
WalnutWindow.ReportFormat[wH, " The log file is %g bytes (%g pages) long\n",
[integer[len]], [integer[FS.PagesForBytes[len]]] ];
WalnutWindow.ReportFormat[wH,
" There are %g deleted msgs, (%g total msgs), & %g msgSets\n",
[integer[numIn]], [integer[messages]], [integer[msgSets]] ];
};
[] ¬ DoWaitCall[wH, Dbi];
};
SetupOptions: PROC[wH: WalnutHandle, which: OldMailOrPrint] = {
Sop: PROC = {
oneHeight: INTEGER = buttonEntryHeight + 1 + 1;
move: INTEGER = (IF which = oldMail THEN 2*oneHeight ELSE oneHeight) + 1;
oldY: INTEGER = wH.walnutRulerAfter.wy + wH.walnutRulerAfter.wh;
IF which = oldMail AND wH.oldMailReader # NIL THEN RETURN;
IF which = printing AND wH.printingOptions # NIL THEN RETURN;
IF (which = oldMail AND wH.printingOptions # NIL) OR
(which = printing AND wH.oldMailReader # NIL) THEN {
WalnutWindow.Report[wH, "Can't have both OldMailReader & Printing Options"];
RETURN;
};
wH.walnut.inhibitDestroy ¬ TRUE;
move the typescript down enough space
ViewerOps.MoveViewer[wH.walnutTS, wH.walnutTS.wx, wH.walnutTS.wy+move, wH.walnutTS.ww, wH.walnutTS.wh, FALSE];
IF which = oldMail THEN {
omr: OldMailReader ¬ NEW[OldMailReaderRec];
omr.container ¬ ViewerOps.CreateViewer[
flavor: $Container,
info: [parent: wH.walnut, wy: oldY, ww: 1000, wh: move, scrollable: FALSE]];
Containers.ChildXBound[wH.walnut, omr.container];
omr.doIt ¬ Buttons.Create[
proc: OldMailReaderProc, clientData: wH, paint: FALSE,
info: [name: "DoIt", parent: omr.container, wx: 4, wy: 1, border: TRUE] ];
omr.fileLabel ¬ WalnutViewer.ImmediateButton[name: "file:", proc: FileLabelProc, data: wH, sib: omr.doIt, paint: FALSE];
omr.fileText ¬ WalnutViewer.NextRightTextViewer[omr.fileLabel, 700];
Containers.ChildXBound[omr.container, omr.fileText];
omr.close ¬ WalnutViewer.ImmediateButton[name: "Close", proc: CloseOmrProc, sib: omr.fileText, data: wH, border: TRUE, newLine: TRUE, paint: FALSE];
omr.msgSetLabel ¬ WalnutViewer.ImmediateButton[name: "msgSet:", proc: MsgSetLabelProc, data: wH, sib: omr.close, paint: FALSE];
omr.msgSetText ¬ WalnutViewer.NextRightTextViewer[omr.msgSetLabel, 700];
Containers.ChildXBound[omr.container, omr.msgSetText];
wH.oldMailReader ¬ omr;
}
ELSE {
por: PrintingOptions ¬ NEW[PrintingOptionsRec];
por.container ¬ ViewerOps.CreateViewer[
flavor: $Container,
info: [parent: wH.walnut, wy: oldY, ww: 1000, wh: move, scrollable: FALSE]];
Containers.ChildXBound[wH.walnut, por.container];
por.options ¬ Buttons.Create[
proc: PrintingOptionsProc, clientData: wH, paint: FALSE,
info: [name: "Options", parent: por.container, wx: 4, wy: 1, border: TRUE] ];
por.copiesLabel ¬ WalnutViewer.ImmediateButton[name: "copies:", proc: CopiesLabelProc, data: wH, sib: por.options, paint: FALSE];
por.copiesText ¬ WalnutViewer.NextRightTextViewer[por.copiesLabel, 50];
por.serverLabel ¬ WalnutViewer.ImmediateButton[name: "server:", proc: ServerLabelProc, data: wH, sib: por.copiesText, paint: FALSE];
por.serverText ¬ WalnutViewer.NextRightTextViewer[por.serverLabel, 500];
Containers.ChildXBound[por.container, por.serverText];
wH.printingOptions ¬ por;
};
wH.walnut.inhibitDestroy ¬ FALSE;
ViewerOps.PaintViewer[wH.walnut, client];
};
[] ¬ DoWaitCall[wH, Sop];
};
OldMailReaderProc: Buttons.ButtonProc = {
wH: WalnutHandle = NARROW[clientData];
msgSet: ROPE = ViewerTools.GetContents[wH.oldMailReader.msgSetText];
fileName: ROPE = ViewerTools.GetContents[wH.oldMailReader.fileText];
WalnutWindow.ReadArchiveFile[wH, fileName, msgSet];
};
MsgSetLabelProc: Buttons.ButtonProc = {
wH: WalnutHandle = NARROW[clientData];
ViewerTools.SetSelection[wH.oldMailReader.msgSetText, NIL];
};
FileLabelProc: Buttons.ButtonProc = {
wH: WalnutHandle = NARROW[clientData];
ViewerTools.SetSelection[wH.oldMailReader.fileText, NIL];
};
CopiesLabelProc: Buttons.ButtonProc = {
wH: WalnutHandle = NARROW[clientData];
ViewerTools.SetSelection[wH.printingOptions.copiesText, NIL];
};
ServerLabelProc: Buttons.ButtonProc = {
wH: WalnutHandle = NARROW[clientData];
ViewerTools.SetSelection[wH.printingOptions.serverText, NIL];
};
PrintingOptionsProc: Buttons.ButtonProc = {
wH: WalnutHandle = NARROW[clientData];
which, how: INT;
howToPrint: HowToPrint ¬ press;
server, numRope: ROPE;
copies: INT;
DoPrint: PROC = {
SELECT which FROM
1 => {
v: Viewer = ViewerTools.GetSelectedViewer[];
maH: MsgAndHandle = NARROW[ViewerOps.FetchProp[v, $WalnutMsgName]];
IF maH = NIL THEN {
WalnutWindow.Report[wH, "Viewer is not a Walnut Msg displayer"];
RETURN;
};
IF maH.wH # wH THEN {
WalnutWindow.Report[wH, "Msg is from a different database"];
RETURN
};
PrintMsgCmd[wH, maH.msg, server, howToPrint, copies];
};
2 =>
FOR msb: MsgSetButton ¬ wH.selectedMsgSetButtons, msb.selected UNTIL msb = NIL DO
PrintSelCmd[wH, msb.msgSet.name, server, howToPrint, copies];
ENDLOOP;
3 =>
FOR msb: MsgSetButton ¬ wH.selectedMsgSetButtons, msb.selected UNTIL msb = NIL DO
PrintMsgSetCmd[wH, msb.msgSet.name, server, howToPrint, copies];
ENDLOOP;
4 =>
FOR msb: MsgSetButton ¬ wH.selectedMsgSetButtons, msb.selected UNTIL msb = NIL DO
PrintMsgSetTOCCmd[wH, msb.msgSet.name, server, howToPrint, copies];
ENDLOOP;
5 => {
prev: PrintingOptions = wH.printingOptions;
wH.printingOptions ¬ NIL;
ViewerOps.DestroyViewer[prev.container, FALSE];
ViewerOps.MoveViewer[wH.walnutTS, wH.walnutTS.wx, wH.walnutRulerAfter.wy+wH.walnutRulerAfter.wh+1, wH.walnutTS.ww, wH.walnutTS.wh, TRUE];
};
ENDCASE;
};
which ¬ PopUpSelection.Request[
header: "WhatToPrint",
choice: LIST["Msg", "SelectedMsgInMsgSet(s)", "MsgSet(s)", "MsgSetTOC(s)", "Close"]
];
IF which = 0 THEN RETURN;
IF which # 5 THEN {
how ¬ PopUpSelection.Request[
header: "HowToPrint",
choice: LIST[ "PressPrint", "Interpress2.0Print", "Interpress3.0Print" ]
];
IF how = 0 THEN RETURN;
server ¬ ViewerTools.GetContents[wH.printingOptions.serverText];
numRope ¬ ViewerTools.GetContents[wH.printingOptions.copiesText];
IF numRope # NIL THEN
copies ¬ Convert.IntFromRope[numRope ! Convert.Error => { copies ¬ 1; CONTINUE } ]
ELSE copies ¬ 1;
howToPrint ¬ SELECT how FROM
1 => press,
2 => ip2,
3 => ip3,
ENDCASE => ip3;
};
[] ¬ DoWaitCall[wH, DoPrint];
};
CloseOmrProc: Buttons.ButtonProc = {
wH: WalnutHandle = NARROW[clientData];
prev: OldMailReader = wH.oldMailReader;
wH.oldMailReader ¬ NIL;
ViewerOps.DestroyViewer[prev.container, FALSE];
ViewerOps.MoveViewer[wH.walnutTS, wH.walnutTS.wx, wH.walnutRulerAfter.wy+wH.walnutRulerAfter.wh+1, wH.walnutTS.ww, wH.walnutTS.wh, TRUE];
};
RedisplayDeleted: PROC[wH: WalnutHandle] = {
msb: MsgSetButton ¬ GetButton[wH, WalnutOps.DeletedName];
IF msb.msViewer = NIL THEN RETURN;
[] ¬ QDisplayMsgSet[wH, msb, msb.msViewer, FALSE];
};
FindProc: Menus.MenuProc = {
wH: WalnutHandle = NARROW[clientData];
direction: TiogaOps.SearchDir =
SELECT mouseButton FROM
red => forwards,
yellow => anywhere,
blue => backwards,
ENDCASE => forwards;
IF ~TiogaOps.FindText[
viewer: wH.msgSetsTViewer,
whichDir: direction,
which: feedback,
case: ~shift]
THEN ViewerOps.BlinkIcon[wH.msgSetsTViewer];
};
* * * * * * * * * *
other menus - done only once
Menus.AppendMenuEntry[workingMenu, Menus.CreateEntry["Sender", NewSenderProc]];
* * * * * * * * * *
END.