WalnutWindowCommandsImpl.mesa
Copyright Ó 1988, 1992 by Xerox Corporation. All rights reserved.
Willie-Sue, August 8, 1989 4:19:16 pm PDT
Doug Terry, July 21, 1992 11:27 am PDT
Willie-s, April 27, 1992 8:01 pm PDT
DIRECTORY
BasicTime USING [Now],
Commander USING [CommandProc, Handle, Register],
CommanderOps USING [NextArgument],
Containers,
FileNames USING [ConvertToSlashFormat],
FS USING [ComponentPositions, Error, ExpandName, PagesForBytes],
Icons USING [IconFlavor, NewIconFromFile],
IO,
MailBasics USING [RNameList],
Menus,
PFS USING [GetWDir, RopeFromPath],
Process USING [Detach],
Rope,
Rules USING [Create],
SendMailOps USING [userRNameList, ChangeUserRNameList, IsThisTheCurrentUser],
SystemNames USING [UserName],
TBQueue USING [Queue, Create, QueueClientAction],
UserProfile USING [Boolean, Token],
ViewerClasses USING [Column, Viewer],
ViewerEvents USING [EventProc, EventRegistration, RegisterEventProc],
ViewerOps,
ViewerSpecs USING[openLeftWidth, openTopY, openRightWidth],
WalnutDefs USING [Error],
WalnutOps USING [LogLength, MsgSet, dontCareMsgSetVersion, CopyToExpungeLog, CreateWalnutOpsHandle, ExpungeMsgs, ReadArchiveFile, Shutdown, ValidOpsHandle],
WalnutViewer USING [FirstLabel, tiogaButtonHeight, MakeRuler, MakeTypescript],
WalnutInternal USING [blankMenu, BuildWalnutMenus, ChangeMenu, CreateMsgMenu, CreateMsgSetMenus, DestroyAllMsgSetButtons, DisableNewMail, displayMsgSetInIcon, DoArchive, DoWaitCall, DoStartupCall, FlushWQueue, GetButton, HowToPrint, OpenTS, QDisplayMsgSet, QuitWalnut, RestartWalnut, ShowMsgSetButtons, TakeDownWalnutViewers, WalnutNotifier, workingMenu],
WalnutRegistryPrivate USING [NotifyForEvent],
WalnutWindowPrivate USING [MsgSetButton, WalnutHandle, WalnutHandleRec, WalnutIcons, WalnutIconsRec],
WalnutWindow USING [GetNewMail, OutCome, Report, ReportFormat],
WalnutWindowSidedoor USING [];
WalnutWindowCommandsImpl: CEDAR MONITOR
IMPORTS
FS, PFS,
BasicTime, Commander, CommanderOps,
Containers, FileNames, Icons, Rules, TBQueue,
IO, Process, Rope, SendMailOps,
SystemNames, UserProfile,
ViewerEvents, ViewerOps, ViewerSpecs,
WalnutDefs, WalnutOps, WalnutRegistryPrivate,
WalnutInternal, WalnutViewer, WalnutWindow
EXPORTS WalnutInternal, WalnutWindow, WalnutWindowSidedoor =
BEGIN OPEN WalnutInternal;
Walnut Viewers types and global data
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Viewer: TYPE = ViewerClasses.Viewer;
tiogaButtonHeight: INTEGER = WalnutViewer.tiogaButtonHeight;
MsgSetButton: TYPE = WalnutWindowPrivate.MsgSetButton;
WalnutHandle: TYPE = WalnutWindowPrivate.WalnutHandle;
WalnutHandleRec: PUBLIC TYPE = WalnutWindowPrivate.WalnutHandleRec;
HowToPrint: TYPE = WalnutInternal.HowToPrint;
InitialNotifyLabel: PUBLIC ROPE ¬
" ";
walnutVersion: ROPE = "Walnut 7.1";
msgSetIcon: PUBLIC Icons.IconFlavor ¬ tool;
msgIcon: PUBLIC Icons.IconFlavor ¬ tool;
labelledWalnutIcons: PUBLIC WalnutWindowPrivate.WalnutIcons;
unLabelledWalnutIcons: PUBLIC WalnutWindowPrivate.WalnutIcons;
alternateWalnutIcons: PUBLIC WalnutWindowPrivate.WalnutIcons;
iconFilePathName: PUBLIC ROPE ¬ NIL;
previousUser: PUBLIC ROPE ¬ NIL;
gettingOrganized: PUBLIC BOOL ¬ FALSE;
readyToGo: PUBLIC CONDITION;
initialActiveIconic: PUBLIC BOOL ¬ FALSE;
initialActiveRight: PUBLIC BOOL ¬ TRUE;
initialActiveOpen: PUBLIC BOOL ¬ TRUE;
walnutHandleList: LIST OF WalnutHandle;
invocationDirectory: PUBLIC ROPE ¬ PFS.RopeFromPath[PFS.GetWDir[]];
searchRules: PUBLIC LIST OF REF ANY;
* * * * * * * * * * Commander.CommandProc's - only Expunge & Shutdown Wait
BuildWalnut: Commander.CommandProc = {
wA: WalnutArgs;
wH: WalnutHandle;
ok: BOOL ¬ TRUE;
wA ¬ ParseCmdLine[cmd];
wH ¬ GetHandleForRootFile[wA.rootName];
{ ENABLE WalnutDefs.Error => {
cmd.out.PutF["*****WalnutDefs.Error [code: $%g, explanation: \"%g\"]\n",
[atom[code]], [rope[explanation]] ];
ok ¬ FALSE;
GOTO gotError;
};
IF wH # NIL THEN {
needNewOpsHandle: BOOL ¬ FALSE;
IF wH.walnut # NIL THEN RETURN; -- already running
needNewOpsHandle ¬ ( wH.userAskedForReadOnly # wA.userAskedForReadOnly) OR
( wH.dontDoMail # wA.dontDoMail );
wH.userAskedForReadOnly ¬ wA.userAskedForReadOnly;
wH.dontDoMail ¬ wA.dontDoMail;
IF needNewOpsHandle OR ( NOT WalnutOps.ValidOpsHandle[wH.opsH] ) THEN
wH.opsH ¬ WalnutOps.CreateWalnutOpsHandle[wA.rootName, wH.userAskedForReadOnly];
}
ELSE wH ¬ CreateNewHandle[wA];
EXITS gotError => NULL;
};
IF NOT ok THEN RETURN;
TRUSTED { Process.Detach[FORK DoStartup[wH, FALSE, wA]] };
};
WalnutScavenge: Commander.CommandProc = {
wA: WalnutArgs;
wA ¬ ParseCmdLine[cmd];
TRUSTED { Process.Detach[FORK DoScavenge[wA]] };
};
WalnutMasquerade: Commander.CommandProc = {
wA: WalnutArgs;
oldUserList: MailBasics.RNameList;
BEGIN ENABLE UNWIND =>
IF oldUserList # NIL THEN SendMailOps.ChangeUserRNameList[oldUserList];
wA ¬ ParseCmdLine[cmd];
IF NOT SendMailOps.IsThisTheCurrentUser[wA.rootUserName] THEN {
oldUserList ¬ SendMailOps.userRNameList;
this is real clunky right here - don't know what else to do
SendMailOps.ChangeUserRNameList[LIST[ [$gv, wA.rootUserName] ] ];
};
IF wA.masContinue THEN [] ¬ StartUp[wA.rootName, TRUE] ELSE DoScavenge[wA];
IF oldUserList # NIL THEN SendMailOps.ChangeUserRNameList[oldUserList];
cmd.out.PutF[
" Finished scavenging %g (done by %g)\n",
[rope[wA.rootName]], [rope[oldUserList.first.name]] ];
END;
};
WalnutNewMailProc: Commander.CommandProc = {
wH: WalnutHandle = GetHandleForMail[];
IF wH = NIL OR wH.walnut = NIL THEN RETURN;
TRUSTED { Process.Detach[FORK WalnutWindow.GetNewMail[wH]]};
};
* * * * * * * * * * exported to WalnutWindow - these all wait for completion
StartUp: PUBLIC PROC[rootFile: ROPE, dontDoMail: BOOL ¬ FALSE]
RETURNS[wH: WalnutHandle] = {
wA: WalnutArgs = ParseCmdLine[NIL, rootFile];
wH ¬ GetHandleForRootFile[wA.rootName];
IF wH # NIL AND wH.walnut # NIL THEN RETURN[NIL];
wH ¬ CreateNewHandle[wA];
DoStartup[wH, FALSE, wA]
};
Expunge: PUBLIC PROC[wH: WalnutHandle] = {
Ep: PROC = {
ENABLE UNWIND => { ChangeMenu[wH, wH.walnutMenu, FALSE] };
ok: BOOL ¬ TRUE;
didCopy: BOOL ¬ FALSE;
exp: ROPE;
Quitting[wH, TRUE];
WalnutWindow.ReportFormat[wH, "\n****** Starting expunge at %g\n", [time[BasicTime.Now[]]] ];
BEGIN ENABLE ABORTED => { ok ¬ FALSE; CONTINUE };
bytesInDestroyedMsgs: INT =
WalnutOps.ExpungeMsgs[wH.opsH, WalnutOps.dontCareMsgSetVersion];
IF bytesInDestroyedMsgs = 0 THEN
WalnutWindow.Report[wH, "No messages were expunged - log rewrite not done"]
ELSE didCopy ¬ WalnutOps.CopyToExpungeLog[wH.opsH];
END;
IF ~ok THEN
WalnutWindow.Report[wH,
"\n***** Expunge failed or aborted; some changes have been aborted"];
IF didCopy THEN {
len: INT = WalnutOps.LogLength[wH.opsH];
WalnutWindow.ReportFormat[wH, "Log length is now %g bytes (%g pages)\n",
[integer[len]], [integer[FS.PagesForBytes[len]]] ];
WalnutWindow.ReportFormat[wH, "***** Expunge complete at %g\n",
[time[BasicTime.Now[]]] ];
}
ELSE WalnutWindow.Report[wH, exp];
WalnutOps.Shutdown[wH.opsH];
IF ~RestartWalnut[wH: wH, scavengeFirst: FALSE, firstTime: TRUE] THEN RETURN;
ChangeMenu[wH, wH.walnutMenu, FALSE];
};
[] ¬ DoWaitCall[wH, Ep];
};
Scavenge: PUBLIC PROC[rootFile: ROPE, dontDoMail: BOOL] RETURNS[wH: WalnutHandle]= {
wA: WalnutArgs ¬ ParseCmdLine[NIL, rootFile];
IF wA.rootName = NIL THEN RETURN;
wA.dontDoMail ¬ dontDoMail;
DoScavenge[wA];
RETURN[GetHandleForRootFile[wA.rootName]];
};
WriteArchiveFile: PUBLIC PROC[wH: WalnutHandle, fileName: ROPE, msgSetList: LIST OF ROPE] = {
Waf: PROC = {
msList: LIST OF WalnutOps.MsgSet;
FOR mL: LIST OF ROPE ¬ msgSetList, mL.rest UNTIL mL = NIL DO
msList ¬ CONS[ [mL.first, WalnutOps.dontCareMsgSetVersion], msList];
ENDLOOP;
[] ¬ DoArchive[wH: wH, fileName: fileName, msList: msList, append: FALSE] };
[] ¬ DoWaitCall[wH, Waf];
};
GetHandleList: PUBLIC ENTRY PROC RETURNS[LIST OF WalnutHandle] = {
ENABLE UNWIND => NULL;
RETURN[walnutHandleList]
};
GetHandleForRootFile: PUBLIC ENTRY PROC[rootFile: ROPE] RETURNS[wH: WalnutHandle] = {
ENABLE UNWIND => NULL;
fullName: ROPE ¬ FS.ExpandName[rootFile].fullFName;
FOR whL: LIST OF WalnutHandle ¬ walnutHandleList, whL.rest UNTIL whL = NIL DO
IF fullName.Equal[whL.first.opsH.rootName, FALSE] THEN RETURN[whL.first];
ENDLOOP;
};
GetHandleForSegment: PUBLIC ENTRY PROC[segment: ATOM] RETURNS[wH: WalnutHandle] = {
ENABLE UNWIND => NULL;
FOR whL: LIST OF WalnutHandle ← walnutHandleList, whL.rest UNTIL whL = NIL DO
IF whL.first.opsH.segmentID.segment = segment THEN RETURN[whL.first];
ENDLOOP;
};
GetHandleForMail: PUBLIC ENTRY PROC RETURNS[wH: WalnutHandle] = {
ENABLE UNWIND => NULL;
FOR whL: LIST OF WalnutHandle ¬ walnutHandleList, whL.rest UNTIL whL = NIL DO
IF whL.first.personalMailDB THEN RETURN[whL.first];
ENDLOOP
};
GetRootFileForHandle: PUBLIC PROC[wH: WalnutHandle] RETURNS[rootFile: ROPE] =
{ IF wH.opsH # NIL THEN RETURN[wH.opsH.rootName] };
GetSegmentForHandle: PUBLIC PROC[wH: WalnutHandle] RETURNS[segment: ATOM] = {
IF wH.opsH # NIL THEN RETURN[wH.opsH.segmentID.segment]
};
GetHandleForViewer: PUBLIC ENTRY PROC[v: ViewerClasses.Viewer]
RETURNS[wH: WalnutHandle] = {
ENABLE UNWIND => NULL;
CheckList: PROC[vL: LIST OF Viewer] RETURNS[found: BOOL ¬ FALSE] = {
FOR xL: LIST OF Viewer ¬ vL, xL.rest UNTIL xL = NIL DO
IF xL.first = thisV THEN RETURN[TRUE];
ENDLOOP;
};
thisV: Viewer ¬ v;
UNTIL thisV.parent = NIL DO thisV ¬ thisV.parent; ENDLOOP; -- top
FOR whL: LIST OF WalnutHandle ¬ walnutHandleList, whL.rest UNTIL whL = NIL DO
IF whL.first.walnut = thisV THEN RETURN[whL.first];
IF CheckList[whL.first.msgSetViewerList] THEN RETURN[whL.first];
IF CheckList[whL.first.msgViewerList] THEN RETURN[whL.first];
IF CheckList[whL.first.wallabyViewerList] THEN RETURN[whL.first];
ENDLOOP;
RETURN[NIL];
};
IsHandleActive: PUBLIC ENTRY PROC[wH: WalnutHandle]
RETURNS[yes: BOOL] = { RETURN[wH.walnut # NIL] };
* * * * * * * * * * * * local procedures
WalnutArgs: TYPE = REF WalnutArgsRec;
WalnutArgsRec: TYPE = RECORD[
dirName, rootName, captionName, rootUserName, baseRootName: ROPE,
dontDoMail, userAskedForReadOnly, masContinue: BOOL ¬ FALSE,
dontUseNumber: BOOL ¬ FALSE
];
ParseCmdLine: PROC[cmd: Commander.Handle, nameArg: ROPE ¬ NIL]
RETURNS[wA: WalnutArgs] = {
cp: FS.ComponentPositions;
arg, rName: ROPE;
defaultPattern: ROPE = "[Luther.alpine]<%g>Walnut.Root";
user: ROPE ¬ SystemNames.UserName[];
wA ¬ NEW[WalnutArgsRec];
IF cmd # NIL THEN {
arg ¬ CommanderOps.NextArgument[cmd];
IF arg # NIL THEN
IF arg.Fetch[0] = '- THEN {
SELECT arg.Fetch[1] FROM
'c => wA.masContinue ¬ TRUE;
'n => wA.dontDoMail ¬ TRUE;
'r => wA.userAskedForReadOnly ¬ TRUE;
ENDCASE;
arg ¬ CommanderOps.NextArgument[cmd];
};
}
ELSE arg ¬ nameArg;
wA.dirName ¬ arg;
IF wA.dirName.Length = 0 THEN {
rName ¬ UserProfile.Token[key: "Walnut.WalnutRootFile", default: ""];
IF rName.Length[] = 0 THEN rName ¬ IO.PutFR1[defaultPattern, [rope[user]] ];
wA.captionName ¬ walnutVersion;
wA.dontUseNumber ¬ TRUE;
}
ELSE {
SELECT wA.dirName.Fetch[0] FROM
'[, '/ => rName ¬ wA.dirName;
ENDCASE => rName ¬ IO.PutFR1[defaultPattern, [rope[wA.dirName]] ];
wA.captionName ¬ Rope.Cat[walnutVersion, " {", wA.dirName, "}"];
};
[wA.rootName, cp, ] ¬ FS.ExpandName[rName, NIL];
IF cp.ext.length = 0 THEN wA.rootName ¬ wA.rootName.Concat[".Root"];
wA.rootUserName ¬ wA.rootName.Substr[cp.dir.start, cp.dir.length];
wA.baseRootName ¬ FileNames.ConvertToSlashFormat[wA.rootName.Substr[0, cp.ext.start-1]];
};
DoStartup: PROC[wH: WalnutHandle, scavengeFirst: BOOL, wA: WalnutArgs] = {
Su: PROC[BOOL] = {
BuildWalnutControlWindow[wH, wA.captionName];
IF ~RestartWalnut[
wH: wH, scavengeFirst: scavengeFirst, firstTime: TRUE] THEN RETURN;
WalnutWindow.Report[wH, "\n ...Ready"];
};
IF DoStartupCall[wH, Su] # flushed THEN {
AddGoodHandle[wH];
};
};
startScavMsg: ROPE = "\n ***** Starting scavenge @ %g, using rootFile %g ";
endScavMsg: ROPE = "\n ***** Scavenge finished @ %g\n";
DoScavenge: PROC[wA: WalnutArgs] = {
Sp: PROC[isRunning: BOOL] = {
ENABLE UNWIND => { ChangeMenu[wH, wH.walnutMenu, FALSE] };
IF isRunning THEN {
Quitting[wH, TRUE];
WalnutOps.Shutdown[wH.opsH];
WalnutWindow.ReportFormat[wH, startScavMsg, [time[BasicTime.Now[]]], [rope[wA.rootName]] ];
wH.walnut.name ¬ wA.captionName;
ViewerOps.PaintViewer[wH.walnut, caption];
IF ~RestartWalnut[wH: wH, scavengeFirst: TRUE, firstTime: FALSE]
THEN RETURN;
WalnutWindow.ReportFormat[wH, endScavMsg, [time[BasicTime.Now[]]] ];
ChangeMenu[wH, wH.walnutMenu, FALSE];
}
ELSE {
BuildWalnutControlWindow[wH, wA.captionName];
IF ~RestartWalnut[
wH: wH, scavengeFirst: TRUE, firstTime: TRUE] THEN RETURN;
WalnutWindow.Report[wH, "\n ...Ready"];
};
};
wH: WalnutHandle ¬ GetHandleForRootFile[wA.rootName];
IF wH = NIL THEN wH ¬ CreateNewHandle[wA];
IF DoStartupCall[wH, Sp] # flushed THEN {
AddGoodHandle[wH];
};
};
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
BuildWalnutControlWindow: PROC[wH: WalnutHandle, caption: ROPE] = {
bt: Viewer;
walnutWidth: INTEGER;
transOK: BOOL ¬ TRUE;
guarded: BOOL;
column: ViewerClasses.Column ¬ right;
columnRope: ROPE;
WhichCol: PROC[rp: ROPE, df: ViewerClasses.Column] RETURNS[ViewerClasses.Column] = {
SELECT TRUE FROM
rp.Equal["left", FALSE] => RETURN[left];
rp.Equal["color", FALSE] => RETURN[df];
rp.Equal["right", FALSE] => RETURN[right];
ENDCASE => RETURN[df];
};
IF wH.walnut # NIL THEN RETURN;
SELECT TRUE FROM
displayMsgSetInIcon => wH.iconSet ¬ labelledWalnutIcons;
( wH.identifierPrefix = NIL) => wH.iconSet ¬ unLabelledWalnutIcons;
ENDCASE => wH.iconSet ¬ alternateWalnutIcons;
caption ¬ wH.identifierPrefix.Concat[caption];
guarded ¬ UserProfile.Boolean[key: "Walnut.GuardedDestroy", default: FALSE];
columnRope ¬ UserProfile.Token[key: "Walnut.ControlWindowColumn", default: "right"];
column ¬ WhichCol[columnRope, right];
wH.walnut ¬ ViewerOps.CreateViewer[
flavor: $Container,
info: [name: caption, iconic: FALSE, column: column,
scrollable: FALSE, label: wH.iconIdentifier,
icon: wH.iconSet[regular], openHeight: ViewerSpecs.openTopY/4, guardDestroy: guarded,
inhibitDestroy: TRUE ]];
walnutWidth ¬ IF wH.walnut.column = right THEN ViewerSpecs.openRightWidth ELSE
ViewerSpecs.openLeftWidth;
ViewerOps.SetMenu[wH.walnut, blankMenu];
wH.mailNotifyLabel ¬ WalnutViewer.FirstLabel[name: InitialNotifyLabel, parent: wH.walnut];
bt ¬ wH.walnutRulerBefore ¬ WalnutViewer.MakeRuler[sib: wH.mailNotifyLabel, h: 2];
wH.walnutRulerAfter ¬ Rules.Create[
info: [parent: wH.walnut, wy: bt.wy+bt.wh+tiogaButtonHeight+1, ww: walnutWidth, wh: 2]];
Containers.ChildXBound[wH.walnut, wH.walnutRulerAfter];
wH.walnutTS ¬ WalnutViewer.MakeTypescript[sib: wH.walnutRulerAfter];
OpenTS[wH];
ViewerOps.SetMenu[wH.walnut, workingMenu];
wH.walnutEventReg ¬
ViewerEvents.RegisterEventProc[proc: QuitProc, event: destroy, filter: wH.walnut];
};
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
QuitProc: ViewerEvents.EventProc = {
wH: WalnutHandle;
FOR whL: LIST OF WalnutHandle ¬ walnutHandleList, whL.rest UNTIL whL = NIL DO
IF whL.first.walnut = viewer THEN { wH ¬ whL.first; EXIT };
ENDLOOP;
IF wH = NIL OR wH.walnutEventReg = NIL THEN RETURN[FALSE];
wH.mustQuitMsg ¬ NIL;
TBQueue.QueueClientAction[wH.walnutQueue, QuitWalnut, wH];
RETURN[TRUE];
};
ChangeDatabase: PROC[wH: WalnutHandle, scavengeFirst: BOOL, rootName, captionName, iconLabel: ROPE] = {
Cdb: PROC = {
wH.walnut.inhibitDestroy ← TRUE;
Quitting[wH, IO.PutFR["\nClosing database for %g", [rope[walnutHandle.rootName]] ], TRUE ];
WalnutOps.Shutdown[wH.opsH];
wH.walnut.name ← captionName;
ViewerOps.PaintViewer[wH.walnut, caption];
wH.opsH ← WalnutOps.CreateWalnutHandle[rootName, wH.userAskedForReadOnly];
IF ~RestartWalnut[wH, scavengeFirst, TRUE] THEN RETURN;
WalnutWindow.Report[wH, "\nDatabase is now defined by ", wH.opsH.rootName];
wH.walnut.label ← iconLabel;
};
[] ← DoWaitCall[wH, Cdb];
};
Quitting: PROC[wH: WalnutHandle, isBusy: BOOL] = {
ChangeMenu[wH, workingMenu, isBusy];
TakeDownWalnutViewers[wH];
DestroyAllMsgSetButtons[wH];
IF wH.personalMailDB THEN DisableNewMail[wH];
FlushWQueue[wH];
};
ReadArchiveFile: PUBLIC PROC[wH: WalnutHandle, fileName, msgSet: ROPE, useCategoriesInFile: BOOL] = {
Erm: PROC = {
ENABLE UNWIND => { ChangeMenu[wH, wH.walnutMenu, FALSE] };
fullName: ROPE;
numNew: INT ¬ 0;
msb: MsgSetButton ¬ GetButton[wH, msgSet];
startVersion: INT ¬ wH.msgSetsVersion;
activeIsOpen: BOOL ¬ wH.activeMsgSetButton.msViewer # NIL;
thisMS: WalnutOps.MsgSet ¬
IF useCategoriesInFile THEN [NIL, WalnutOps.dontCareMsgSetVersion]
ELSE IF msb = NIL THEN [msgSet, WalnutOps.dontCareMsgSetVersion]
ELSE msb.msgSet;
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 fullName = NIL THEN
{ WalnutWindow.Report[wH, "No input file specified so quitting"]; RETURN };
WalnutWindow.Report[wH, "Reading messages from ", fullName, "... "];
ChangeMenu[wH, workingMenu, TRUE];
numNew ¬ WalnutOps.ReadArchiveFile[wH.opsH, fullName, thisMS];
SELECT numNew FROM
< 0 => WalnutWindow.Report[wH, "\nProblems reading ", fullName];
0 => WalnutWindow.Report[wH, "\nNo messages in ", fullName, " were new"];
>0 => WalnutWindow.ReportFormat[wH,
"\n%g new messages from %g were added to database\n",
[integer[numNew]], [rope[fullName]] ];
ENDCASE;
ShowMsgSetButtons[wH];  -- in case anything changed
ViewerOps.PaintViewer[wH.walnut, client]; -- msgSet buttons don't get painted
IF activeIsOpen THEN [] ¬ QDisplayMsgSet[wH, wH.activeMsgSetButton];
ChangeMenu[wH, wH.walnutMenu, FALSE];
};
[] ¬ DoWaitCall[wH, Erm];
};
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
nextIdentifier: CARD16 ¬ 1;
CreateNewHandle: ENTRY PROC[wA: WalnutArgs] RETURNS[wH: WalnutHandle] = {
ENABLE UNWIND => NULL;
wH ¬ NEW[WalnutHandleRec];
wH.userAskedForReadOnly ¬ wA.userAskedForReadOnly;
wH.dontDoMail ¬ wA.dontDoMail;
IF wA.dontUseNumber THEN wH.identifierPrefix ¬ NIL
ELSE {
wH.identifierPrefix ¬ IO.PutFR1["(#%g) ", [cardinal[nextIdentifier]] ];
wH.iconIdentifier ¬ IO.PutFR1["%g", [cardinal[nextIdentifier]] ];
nextIdentifier ¬ nextIdentifier + 1;
};
wH.walnutQueue ¬ TBQueue.Create[pushModel: FALSE]; -- queue for menu/button pushes
BuildWalnutMenus[wH];
CreateMsgMenu[wH];
CreateMsgSetMenus[wH];
TRUSTED { Process.Detach[FORK WalnutNotifier[wH] ] };
wH.opsH ¬ WalnutOps.CreateWalnutOpsHandle[wA.rootName, wH.userAskedForReadOnly];
wH.localMsgSetButtonsFile ← IO.PutFR["//%g.msgSetButtonsFile", [rope[wA.baseRootName]] ];
wH.localMsgSetButtonsFile ¬ IO.PutFR1["%g.msgSetButtonsFile", [rope[wA.baseRootName]] ];
};
AddGoodHandle: ENTRY PROC[wH: WalnutHandle] = {
ENABLE UNWIND => NULL;
FOR whL: LIST OF WalnutHandle ¬ walnutHandleList, whL.rest UNTIL whL = NIL DO
IF whL.first = wH THEN {
WalnutRegistryPrivate.NotifyForEvent[started];
RETURN;
};
ENDLOOP;
walnutHandleList ¬ CONS[wH, walnutHandleList];  -- not found so add
WalnutRegistryPrivate.NotifyForEvent[started];
};
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
InitIcons: PROC = {
iconFilePathName: ROPE = "Walnut.icons";
one: Icons.IconFlavor;
labelledWalnutIcons ¬ NEW[WalnutWindowPrivate.WalnutIconsRec];
unLabelledWalnutIcons ¬ NEW[WalnutWindowPrivate.WalnutIconsRec];
alternateWalnutIcons ¬ NEW[WalnutWindowPrivate.WalnutIconsRec];
one ¬ Icons.NewIconFromFile[iconFilePathName, 0 ! FS.Error => GOTO notFound];
unLabelledWalnutIcons[regular] ¬ one;
unLabelledWalnutIcons[haveNewMail] ¬ Icons.NewIconFromFile[iconFilePathName, 5];
unLabelledWalnutIcons[expunging] ¬ Icons.NewIconFromFile[iconFilePathName, 3];
unLabelledWalnutIcons[broken] ¬ Icons.NewIconFromFile[iconFilePathName, 14];
labelledWalnutIcons[regular] ¬ Icons.NewIconFromFile[iconFilePathName, 11];
labelledWalnutIcons[haveNewMail] ¬ Icons.NewIconFromFile[iconFilePathName, 12];
labelledWalnutIcons[broken] ¬ unLabelledWalnutIcons[broken];
alternateWalnutIcons[regular] ¬ Icons.NewIconFromFile[iconFilePathName, 15];
alternateWalnutIcons[haveNewMail] ¬ Icons.NewIconFromFile[iconFilePathName, 16];
alternateWalnutIcons[expunging] ¬ Icons.NewIconFromFile[iconFilePathName, 17];
alternateWalnutIcons[broken] ¬ Icons.NewIconFromFile[iconFilePathName, 18];
msgSetIcon¬ Icons.NewIconFromFile[iconFilePathName, 1];
msgIcon¬ Icons.NewIconFromFile[iconFilePathName, 2];
EXITS
notFound => NULL;
};
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Commander.Register["Walnut", BuildWalnut, "For retrieving and sending mail"];
Commander.Register["WallTapestry", BuildWalnut, "Aka Walnut"];
Commander.Register["WalnutScavenge", WalnutScavenge,
"Rebuilds Mail database from log file"];
Commander.Register["WalnutNewMail", WalnutNewMailProc, "Retrieves new mail"];
Commander.Register[
"WalnutMasquerade", WalnutMasquerade, "Scavenge someone else's walnut database"];
InitIcons[];
END.