<> <> <> <> <> DIRECTORY Booting USING [CheckpointProc, RegisterProcs, RollbackProc], Commander USING [CommandProc, Register], FS USING [ComponentPositions, EnumerateForNames, ExpandName, NameProc], Menus USING [ClickProc, MenuProc], PeanutProfile USING [activeMailFile, killViewersOnSaveAll, outgoingMailFile], PeanutRetrieve, PeanutSendMail, PeanutWindow, Process USING [Detach], Rope USING [Equal, ROPE, Substr], ViewerClasses USING [Viewer], ViewerOps; PeanutTopImpl: CEDAR PROGRAM IMPORTS Booting, Commander, FS, PeanutProfile, PeanutRetrieve, PeanutSendMail, PeanutWindow, Process, Rope, ViewerOps = BEGIN Viewer: TYPE = ViewerClasses.Viewer; ROPE: TYPE = Rope.ROPE; mailFiles: LIST OF ROPE; -- short names of mail files, e.g. "Active" (not "Active.mail") NewForm: Menus.MenuProc = { PeanutSendMail.NewMsgForm[mouseButton, shift, control] }; AnswerMessage: Menus.MenuProc = { PeanutSendMail.AnswerMsg[mouseButton, shift, control] }; ForwardMessage: Menus.MenuProc = { PeanutSendMail.ForwardMsg[mouseButton, shift, control] }; SendMessage: Menus.MenuProc = { PeanutSendMail.SendMsg[mouseButton, shift, control] }; NewMail: Menus.MenuProc = { PeanutRetrieve.GetNewMsgs[] }; Abort: Menus.MenuProc = { PeanutWindow.abortFlag _ TRUE }; SaveAll: Menus.MenuProc = { killThem: BOOL _ PeanutProfile.killViewersOnSaveAll; activeName: ROPE _ PeanutProfile.activeMailFile; outgoingName: ROPE _ PeanutProfile.outgoingMailFile; PeanutWindow.OutputRope["\nSaving all message sets:"]; FOR files: LIST OF ROPE _ mailFiles, files.rest UNTIL files=NIL DO name: ROPE = files.first; viewer: Viewer _ PeanutRetrieve.FindMailViewer[name]; IF viewer # NIL THEN { IF viewer.newVersion THEN { PeanutWindow.OutputRope["\nSaving "]; PeanutWindow.OutputRope[name]; ViewerOps.SaveViewer[viewer]; }; IF killThem THEN { IF Rope.Equal[name, activeName] OR Rope.Equal[name, outgoingName] THEN ViewerOps.CloseViewer[viewer] ELSE ViewerOps.DestroyViewer[viewer]; }; }; ENDLOOP; PeanutWindow.OutputRope["\nDone saving all message sets."]; }; MailFileButton: Menus.ClickProc = { name: ROPE = NARROW[clientData]; SELECT mouseButton FROM red => PeanutRetrieve.CopyMessages[to: name, delete: FALSE]; yellow => ViewerOps.OpenIcon[PeanutRetrieve.GetMailViewer[name]]; blue => PeanutRetrieve.CopyMessages[to: name, delete: TRUE]; ENDCASE; }; restartAfterRollback: BOOL _ FALSE; PeanutCheckpointProc: Booting.CheckpointProc = { CloseDown[]; restartAfterRollback _ TRUE }; PeanutRollbackProc: Booting.RollbackProc = { IF restartAfterRollback THEN TRUSTED {Process.Detach[FORK StartPeanut[]]}}; CloseDown: PROC = { PeanutRetrieve.CloseConnection[] }; EnumerateMailFileNames: PROC[action: PROC[ROPE]] = { MailFileProc: FS.NameProc --[fullFName: ROPE] RETURNS[continue: BOOL]-- = { name, base: ROPE; cp: FS.ComponentPositions; [fullFName: name, cp: cp] _ FS.ExpandName[fullFName]; base _ Rope.Substr[base: name, start: cp.base.start, len: cp.base.length]; action[base]; RETURN[continue: TRUE]; }; FS.EnumerateForNames[pattern: "*.mail!H", proc: MailFileProc]; }; GetMailFileList: PROC RETURNS[LIST OF ROPE] = { head, tail: LIST OF ROPE _ NIL; AddNameToList: PROC[name: ROPE] = { item: LIST OF ROPE = LIST[name]; IF head=NIL THEN head _ item ELSE tail.rest _ item; tail _ item; }; EnumerateMailFileNames[AddNameToList]; RETURN[head]; }; StartPeanut: PROC = { AddMailFileButtons: PROC = { FOR names: LIST OF ROPE _ mailFiles, names.rest UNTIL names=NIL DO name: ROPE = names.first; PeanutWindow.AddButton[name: name, proc: MailFileButton, data: name, redisplay: names.rest=NIL]; ENDLOOP; }; IF PeanutSendMail.AuthenticateUser[] THEN [] _ PeanutRetrieve.NewUser[PeanutSendMail.userRName]; IF PeanutWindow.Create[] THEN { -- created a new one mailFiles _ GetMailFileList[]; AddMailFileButtons[]; PeanutWindow.OutputRope["MIDDLE click mail file button to open the file\n"]; PeanutWindow.OutputRope["LEFT click to copy selected message(s)\n"]; PeanutWindow.OutputRope["RIGHT click to move selected message(s)\n"]; } ELSE { -- restarting, probably after Rollback; check for new Mail files MatchLists: PROC[a, b: LIST OF ROPE] RETURNS[BOOL] = { UNTIL a=NIL OR b=NIL DO IF NOT Rope.Equal[a.first, b.first] THEN RETURN[FALSE]; a _ a.rest; b _ b.rest; ENDLOOP; RETURN[a=NIL AND b=NIL]; }; oldMailFiles: LIST OF ROPE = mailFiles; mailFiles _ GetMailFileList[]; IF NOT MatchLists[oldMailFiles, mailFiles] THEN { PeanutWindow.Destroy[]; [] _ PeanutWindow.Create[]; AddMailFileButtons[]; }; }; }; PeanutCommand: Commander.CommandProc = { StartPeanut[] }; PeanutWindow.AddCommand[name: "NewMail", proc: NewMail]; PeanutWindow.AddCommand[name: "NewForm", proc: NewForm]; PeanutWindow.AddCommand[name: "Answer", proc: AnswerMessage]; PeanutWindow.AddCommand[name: "Forward", proc: ForwardMessage]; PeanutWindow.AddCommand[name: "Send", proc: SendMessage]; PeanutWindow.AddCommand[name: "Abort", proc: Abort]; PeanutWindow.AddCommand[name: "SaveAll", proc: SaveAll]; Booting.RegisterProcs[c: PeanutCheckpointProc, r: PeanutRollbackProc]; Commander.Register[key: "Peanut", proc: PeanutCommand, doc: "For retrieving and sending mail"]; END.