<> <> <> <> <> <> <> <> <> <> <> DIRECTORY Commander, IO, Menus, PeanutProfile, PeanutRetrieve, PeanutSendMail, PeanutWindow, PFS, PFSNames, PriorityQueue, Rope, Tioga, TiogaFileOps, TiogaIO, TiogaOps, TiogaOpsDefs, UserProfile, ViewerClasses, ViewerOps, ViewerTools, XNSCredentials; PeanutTopImpl: CEDAR MONITOR IMPORTS Commander, IO, PeanutProfile, PeanutRetrieve, PeanutSendMail, PeanutWindow, PFS, PFSNames, PriorityQueue, TiogaIO, Rope, TiogaFileOps, TiogaOps, UserProfile, ViewerOps, ViewerTools, XNSCredentials EXPORTS TiogaFileOps -- for opaque type = BEGIN Node: TYPE = REF NodeBody; NodeBody: PUBLIC TYPE = Tioga.NodeRep; Viewer: TYPE = ViewerClasses.Viewer; ROPE: TYPE = Rope.ROPE; mailFiles: LIST OF ROPE; -- short names of mail files, e.g. "Active" (not "Active.mail") NewMessage: Menus.ClickProc = { PeanutSendMail.NewMsgForm[]; }; AnswerMessage: Menus.ClickProc = { transport: ATOM ¬ NARROW[clientData]; PeanutSendMail.AnswerMsg[includeOriginal: shift, transport: transport] }; ForwardMessage: Menus.ClickProc = { PeanutSendMail.ForwardMsg[]; }; SendMessage: Menus.ClickProc = { transport: ATOM ¬ NARROW[clientData]; PeanutSendMail.SendMsg[transport: transport] }; GetMail: Menus.ClickProc = { PeanutRetrieve.GetNewMsgs[]; }; AbortSend: Menus.ClickProc = { PeanutSendMail.AbortSend[]; }; SaveAll: Menus.ClickProc = { PeanutWindow.SaveAllMailFiles[mailFiles, mouseButton = $blue]; }; NewMailFile: Menus.ClickProc ~ { name: ROPE ~ ViewerTools.GetSelectionContents[]; fileName: ROPE ~ Rope.Cat[PeanutProfile.workingDirectory, name, ".mail"]; IF name = NIL THEN PeanutWindow.OutputRope["\nPlease select a name for the new mail file."] ELSE IF PFS.FileLookup[PFS.PathFromRope[fileName], NIL] # NIL THEN PeanutWindow.OutputRope["\nThat mail file already exists."] ELSE { root: Node ~ TiogaIO.FromRope[Rope.Concat[name, ".mail"]]; TiogaFileOps.SetStyle[root, "Mail"]; TiogaOps.PutProp[root, $NewlineDelimiter, "\r"]; [] ¬ TiogaIO.ToFile[PFS.PathFromRope[fileName], root ! PFS.Error => { PeanutWindow.OutputRope[Rope.Concat["\nUnexpected PFS.Error: ", error.explanation]]; GO TO Return; }]; PeanutWindow.AddButton[name: name, proc: MailFileButton, data: name, redisplay: TRUE]; mailFiles ¬ CONS[name, mailFiles]; }; EXITS Return => RETURN; }; MailFileButton: Menus.ClickProc = { name: ROPE = NARROW[clientData]; SELECT mouseButton FROM red => PeanutWindow.CopyMessages[to: name, delete: FALSE]; yellow => ViewerOps.OpenIcon[PeanutWindow.GetMailViewer[name]]; blue => PeanutWindow.CopyMessages[to: name, delete: TRUE]; ENDCASE; }; EnumerateMailFileNames: PROC[action: PROC[ROPE]] = { pattern: PFS.PATH ¬ PFS.PathFromRope[Rope.Concat[PeanutProfile.workingDirectory, "*.mail!H"]]; MailFileProc: PFS.NameProc --[name: PATH] RETURNS[continue: BOOL]-- = { base: ROPE ¬ PFSNames.ComponentRope[PFSNames.ShortName[name]]; IF base # NIL THEN action[ base.Substr[0, base.FindBackward["."]] ]; RETURN[continue: TRUE]; }; PFS.EnumerateForNames[pattern: pattern, proc: MailFileProc ! PFS.Error => { PeanutWindow.OutputRope[IO.PutFR["PFS.Error for %g : %g\n", [rope[PeanutProfile.workingDirectory]], [rope[error.explanation]] ]]; CONTINUE} ]; }; MailFileListSortPred: PriorityQueue.SortPred ~ { s1: ROPE ~ NARROW[x]; s2: ROPE ~ NARROW[y]; RETURN[Rope.Compare[s1: s1, s2: s2, case: FALSE]=greater]; -- the last shall be first ... }; GetMailFileList: PROC RETURNS [result: LIST OF ROPE ¬ NIL] = { pq: PriorityQueue.Ref ~ PriorityQueue.Create[MailFileListSortPred]; AddNameToList: PROC [name: ROPE] = { PriorityQueue.Insert[pq, name] }; EnumerateMailFileNames[AddNameToList]; UNTIL PriorityQueue.Empty[pq] DO name: ROPE ~ NARROW[PriorityQueue.Remove[pq]]; result ¬ CONS[name, result]; ENDLOOP; }; <> herald: ROPE ~ "Peanut for PCedar\n"; <> NewProfile: UserProfile.ProfileChangedProc ~ { Awake[] }; asleep: BOOL ¬ FALSE; Sleep: ENTRY PROC = { ENABLE UNWIND => NULL; w: ViewerClasses.Viewer ¬ PeanutWindow.peanutParent; PeanutRetrieve.CloseConnection[]; IF w = NIL OR w.destroyed OR asleep THEN RETURN; PeanutWindow.Destroy[]; asleep ¬ TRUE; }; Awake: ENTRY PROC = { ENABLE UNWIND => NULL; IF NOT asleep THEN RETURN; StartPeanut[]; asleep ¬ FALSE; }; StartPeanut: INTERNAL 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; }; PeanutWindow.Destroy[]; PeanutRetrieve.NewUser[NIL]; IF PeanutWindow.Create[Quit, Save] THEN { -- created a new one mailFiles ¬ GetMailFileList[]; AddMailFileButtons[]; PeanutWindow.OutputRope[herald]; 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"]; }; }; Quit: PROC ~ {PeanutRetrieve.CloseConnection[]}; Save: PROC ~ {PeanutWindow.SaveAllMailFiles[mailFiles, FALSE]}; PeanutCommand: ENTRY Commander.CommandProc = { ENABLE UNWIND => NULL; IF XNSCredentials.GetIdentity[] = NIL THEN { -- User hasn't logged in to XNS yet cmd.out.PutRope["Please enter your XNS credentials:\n"]; UNTIL XNSCredentials.DoLogin[cmd] DO ENDLOOP; }; StartPeanut[]; }; DoInit: PROC = { <> <> < 1 ) };>> PeanutWindow.AddCommand[name: "GetMail", proc: GetMail]; PeanutWindow.AddCommand[name: "NewMessage", proc: NewMessage]; PeanutWindow.AddCommand[name: "SaveAll", proc: SaveAll]; PeanutWindow.AddCommand[name: "NewMailFile", proc: NewMailFile]; <> <> <> <> PeanutWindow.AddCommand[name: "Answer", proc: AnswerMessage, data: $xns, lineNum: 1]; PeanutWindow.AddCommand[name: "Forward", proc: ForwardMessage, lineNum: 1]; <> <> <> <> PeanutWindow.AddCommand[name: "SendMessage", proc: SendMessage, data: $xns, lineNum: 1]; PeanutWindow.AddCommand[name: "AbortSend", proc: AbortSend, lineNum: 1]; <> UserProfile.CallWhenProfileChanges[NewProfile]; Commander.Register[key: "Peanut", proc: PeanutCommand, doc: "For retrieving and sending mail"]; }; DoInit[]; END.