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; 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; 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; 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]]}; }; 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] = { }; 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] = { }; 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] }; 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]; }; 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.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. @ 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 Walnut Viewers types and global data * * * * * * * * * * Commander.CommandProc's - only Expunge & Shutdown Wait this is real clunky right here - don't know what else to do * * * * * * * * * * exported to WalnutWindow - these all wait for completion 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; IF wH.opsH # NIL THEN RETURN[wH.opsH.segmentID.segment] * * * * * * * * * * * * local procedures * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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]; }; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * wH.localMsgSetButtonsFile _ IO.PutFR["//%g.msgSetButtonsFile", [rope[wA.baseRootName]] ]; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * สา•NewlineDelimiter –(cedarcode) style™codešฯn™Kšœ ฯeœ7™BK™)K™&K™$—K˜šฯk ˜ Kšœ Ÿœ˜Kšœ Ÿœ!˜0Kšœ Ÿœ˜"K˜ Kšœ Ÿœ˜'KšŸœŸœ8˜@KšœŸœ˜*KšŸœ˜Kšœ Ÿœ ˜K˜KšŸœŸœ˜"KšœŸœ ˜K˜KšœŸœ ˜Kšœ Ÿœ<˜MKšœ Ÿœ ˜KšœŸœ$˜1Kšœ Ÿœ˜#KšœŸœ˜%Kšœ Ÿœ3˜EK˜ K˜Kšœ Ÿœ*˜;K˜Kšœ Ÿœ ˜Kšœ Ÿœ˜œK˜Kšœ Ÿœ<˜NK˜KšœŸœฯ˜ใKšœŸœ˜-KšœŸœL˜eKšœ Ÿœ-˜?šœŸœ˜K˜——šœŸœŸ˜'šŸ˜KšŸœŸœ˜K˜#K˜-KšŸœ˜K˜Kšœ%˜%Kšœ-˜-Kšœ*˜*—KšŸœ5˜KšœŸœ!˜=K˜KšœŸœŸœŸœ˜$K˜KšœŸœŸœŸœ˜ KšœŸœŸœŸœ˜&Kšœ ŸœŸ œ˜K˜KšœŸœŸœŸœ˜)KšœŸœŸœŸœ˜'KšœŸœŸœŸœ˜&K˜KšœŸœŸœ˜'K˜Kš œŸœŸœŸœŸœ ˜CKš œ ŸœŸœŸœŸœ˜$—K˜šœJ™JK˜š œ˜&K˜K˜KšœŸœŸœ˜K˜K˜K˜'šœŸœ˜šœH˜HKšœ$˜$—KšœŸœ˜ KšŸœ ˜K˜šŸœŸœŸœ˜KšœŸœŸœ˜Kš Ÿœ ŸœŸœŸœฯc˜2KšœHŸœ#˜mK˜2K˜šŸœŸœŸœ%Ÿ˜EK˜P—K˜KšŸœ˜K˜—KšŸœ Ÿœ˜K˜—KšŸœŸœŸœŸœ˜KšŸœŸœŸœ ˜:K˜—K˜šœ˜)Kšœ˜K˜K˜KšŸœŸœ˜0Kšœ˜—K˜šœ˜+Kšœ˜Kšœ"˜"Kš ŸœŸœŸœŸœŸœŸœ.˜^˜K˜šŸœŸœ3Ÿœ˜?K˜(K™;Kšœ Ÿœ˜AK˜—KšŸœŸœŸœŸœ˜KKšŸœŸœŸœ.˜Gšœ ˜ K˜`—KšŸœ˜—Kšœ˜—K˜šœ˜,Kšœ&˜&Kš ŸœŸœŸœ ŸœŸœŸœ˜+KšŸœŸœ˜KšœŸœ˜KšœŸœ ˜-K˜'KšŸœŸœŸœ ŸœŸœŸœŸœ˜1K˜KšœŸœ˜Kšœ˜—K˜šœŸ œ˜*šœŸœ˜ KšŸœŸœ$Ÿœ˜:KšœŸœŸœ˜Kšœ ŸœŸœ˜KšœŸœ˜ Kšœ Ÿœ˜Kšœ]˜]š ŸœŸœŸœ ŸœŸ œ˜1šœŸœ˜Kšœ@˜@—šŸœŸ˜ K˜KKšŸœ/˜3—šŸœ˜K˜——šŸœŸ˜ K˜]—šŸœ Ÿœ˜KšœŸœ ˜(KšœbŸœ˜|K˜ZK˜KšŸœ˜"—Kšœ˜Kš Ÿœ'Ÿœ ŸœŸœŸœ˜MKšœŸœ˜%K˜—K˜K˜—K˜š œŸœŸœ ŸœŸœŸœ˜TKšœŸœ ˜-KšŸœŸœŸœŸœ˜!K˜Kšœ˜KšŸœ$˜*K˜—K˜K˜šœŸœŸœŸœŸœŸœŸœ˜]šœŸœ˜ KšœŸœŸœ˜!š ŸœŸœŸœŸœŸœŸœŸ˜KšœŸœ˜KšœŸœ˜Kšœ Ÿœ˜KšœŸœ$˜8KšœŸœ˜$KšœŸœ˜K˜šŸœŸœŸœ˜K˜%šŸœŸœŸ˜šŸœŸœ˜šŸœŸ˜KšœŸœ˜KšœŸœ˜Kšœ Ÿœ˜%KšŸœ˜—K˜%K˜—K˜KšŸœ˜——K˜šŸœŸœ˜K˜EKšŸœŸœ Ÿœ'˜LK˜KšœŸœ˜K˜šŸœ˜šŸœŸ˜K˜KšŸœ Ÿœ-˜B—K˜AK˜——K˜KšœŸœŸœ˜0KšŸœŸœ+˜DK˜BK˜XK˜—K˜š œŸœ"Ÿœ˜JšœŸœŸœ˜Kšœ-˜-šŸœ˜Kšœ1ŸœŸœŸœ˜C—K˜'K˜—šŸœ!Ÿœ˜)Kšœ˜K˜—Kšœ˜—K˜KšœŸœ9˜KKšœ Ÿœ'˜7K˜š œŸœ˜$šœŸœ Ÿœ˜KšŸœŸœ$Ÿœ˜:šŸœ Ÿœ˜Kšœ Ÿœ˜Kšœ˜Kšœ[˜[K˜ K˜*šŸœ'Ÿœ Ÿœ˜@KšœŸœŸœ˜ —KšœD˜DKšœŸœ˜%K˜—šŸœ˜Kšœ-˜-šŸœ˜Kš œŸœ ŸœŸœŸœ˜:—K˜'K˜—K˜—K˜5KšŸœŸœŸœ˜*šŸœ!Ÿœ˜)Kšœ˜K˜—K˜——K˜KšœO™O˜šœŸœŸœ˜CK˜ Kšœ Ÿœ˜Kšœ ŸœŸœ˜Kšœ Ÿœ˜K˜%Kšœ Ÿœ˜šœŸœŸœŸœ˜TšŸœŸœŸ˜KšœŸœŸœ˜(KšœŸœŸœ˜'KšœŸœŸœ˜*KšŸœŸœ˜K˜——K˜KšŸœ ŸœŸœŸœ˜šŸœŸœŸ˜K˜8KšœŸœ(˜CKšŸœ&˜-—K˜K˜.KšœEŸœ˜LK˜TK˜%K˜˜#K˜šœŸœ˜4Kšœ Ÿœ˜,KšœU˜UKšœŸœ˜——K˜šœŸœŸœŸ˜NK˜K˜—K˜(K˜ZK˜K˜RK˜˜#KšœX˜X—K˜7K˜K˜Dšœ ˜ K˜—K˜*˜K˜R—Kšœ˜——K˜šœO™OK˜šœ˜$K˜š ŸœŸœŸœ+ŸœŸœŸ˜MKšŸœŸœŸœ˜;KšŸœ˜—KšŸœŸœŸœŸœŸœŸœŸœ˜:KšœŸœ˜Kšœ:˜:KšŸœŸœ˜ Kšœ˜—K˜šœŸœ"Ÿœ$Ÿœ™gšœŸœ™ KšœŸœ™ Kšœ ŸœEŸœ™[Kšœ™K™Kšœ™K™*KšœJ™JKšŸœ#ŸœŸœŸœ™7KšœK™KKšœ™Kšœ™—Kšœ™Kšœ™—K˜šœŸœŸœ˜2Kšœ$˜$Kšœ˜Kšœ˜KšŸœŸœ˜-K˜K˜—K˜š œŸœŸœ%ŸœŸœ˜ešœŸœ˜ KšŸœŸœ$Ÿœ˜:Kšœ Ÿœ˜KšœŸœ˜K˜*KšœŸœ˜&KšœŸœ$Ÿœ˜:˜šŸœŸœŸœ"˜BšŸœŸœŸœŸœ*˜@KšŸœ ˜———šŸ˜KšœŸœ˜KšœŸœ1˜;KšœŸœ˜1KšŸœŸœ+˜DKšŸœ˜—K˜šŸœ ŸœŸ˜KšœBŸœ˜K—K˜šœD˜DK˜—KšœŸœ˜"K˜>šŸœŸ˜Kšœ@˜@KšœI˜Išœ#˜#Kšœ5˜5Kšœ&˜&—KšŸœ˜—Kšœ ˜3Kšœ* #˜MKšŸœŸœ0˜DKšœŸœ˜%Kšœ˜—K˜K˜——K˜KšœO™O™KšœŸœ˜K˜šœŸœŸœŸœ˜IKšŸœŸœŸœ˜KšœŸœ˜K˜2K˜šŸœŸœŸ˜2šŸœ˜KšœŸœ/˜GKšœŸœ+˜AK˜$K˜——Kšœ+Ÿœ ˜SK˜Kšœ˜Kšœ˜KšŸœŸœ˜5K˜PKšœŸœ;™YKšœŸœ:˜XK˜K˜—š œŸœŸœ˜/KšŸœŸœŸœ˜š ŸœŸœŸœ+ŸœŸœŸ˜MšŸœŸœ˜Kšœ.˜.KšŸœ˜K˜—KšŸœ˜—KšœŸœ ˜CKšœ.˜.K˜—K˜—šœO™OK˜š œŸœ˜KšœŸœ˜(K˜KšœŸœ%˜>KšœŸœ%˜@KšœŸœ%˜?Kšœ2Ÿœ Ÿœ ˜MK˜%K˜PK˜NK˜LK˜KK˜OK˜˜4K˜(—K˜K˜MK˜šœ˜KšœQ˜Q—K˜K˜ —K˜KšŸœ˜K˜K˜—…—J<gN