Syntax10.Scn.FntBalloonElemsAlloc_Syntax10.Scn.Fnt~1Syntax10i.Scn.FntG^ gM3"MailboxMenu" MailboxMenu = "^MailBox.Menu.Text"; The menu displayed for mailboxes. "MailMenu" MailMenu = "^MailSend.Menu.Text"; The menu displayed new messages. "SigMenu" SigMenu = "^Edit.Menu.Text"; The menu displayed in the signature editing viewer. "MR" Symbolic constant for right mouse button "MM" Symbolic constant for middle mouse button "ML" Symbolic constant for left mouse button "BackgCol" Background color for mail viewers. This value can be changed. "colUnread" Color for unread messages. This value can be changed. "colRead" Color for read messages. This value can be changed. "colDeleted" Color for deleted messages. This value can be changed. "Scheme" Scheme* = POINTER TO SchemeDesc; SchemeDesc* = RECORD (Web.LoaderDesc) END ; Used to install the 'mailto:' protocol. "SchemeDesc" SchemeDesc* = RECORD (Web.LoaderDesc) END ; Used to install the 'mailto:' protocol. "MailboxFrame" MailboxFrame = POINTER TO MailboxFrameDesc; MailboxFrameDesc = RECORD (TextFrames.FrameDesc) box: PostOffice.Mailbox END; A MailboxFrame is handled by Handle and contains a mailbox. A MailboxFrame has the following properties: * allows drag & drop of messages between viewers. (MM, move mouse) * allows pop up of messages (MM+MR) * allows deleting of messages (MR+ML) * allows undeleting of messages (MR+MM) * selection are always enlarged to whole lines * handles PostOffice.NotifyMsgs by adapting the mails colors. A MailboxFrame can be considered a view of the mailbox it contains. "MailboxFrameDesc" MailboxFrameDesc = RECORD (TextFrames.FrameDesc) box: PostOffice.Mailbox END; A MailboxFrame is handled by Handle and contains a mailbox. A MailboxFrame has the following properties: * allows drag & drop of messages between viewers. (MM, move mouse) * allows pop up of messages (MM+MR) * allows deleting of messages (MR+ML) * allows undeleting of messages (MR+MM) * selection are always enlarged to whole lines * handles PostOffice.NotifyMsgs by adapting the mails colors. A MailboxFrame can be considered a view of the mailbox it contains. "NormalFont" Standard font to display mailboxes. Can be changed in procedure Init. "SubjectFont" Font to display subjects in mailboxes. Can be changed in procedure Init. "Task" The task which handles polling. "TaskStarted" True, iff polling is currently turned on. "user" Current POP user name. "pwd" Current POP password. Warning! This password is held plain in memory and can be accessed by System.State Mail ~ "signatureText" Filename of signature file. "mBox" Default mailbox name. "copyMarker" Marker used when copying mails by drag & drop mechanism "moveMarker" Marker used when moving mails by drag & drop mechanism "moveIcon" Icon used when moving mails by drag & drop mechansim "copyIcon" Icon used when copying mails by drag & drop mechanism "pollerAction" Indicates what the poller should do. pollerAction = check ... only check for new Mail pollerAction = copy ... get mails from server leaving them on server pollerAction = move ... get mails from server removing them from server This variable is defined by the PollerAction key in Mail.Profile. "UnmarkMenu" PROCEDURE UnmarkMenu (V: Viewers.Viewer); Unmarks the viewer V by removing the exclamation mark (dirty flag) from the menu, if such a character exists at the end of the menu. "Read" PROCEDURE Read (prompt: ARRAY OF CHAR; VAR passwd: ARRAY OF CHAR; hide: BOOLEAN); Writes prompt to Oberon.Log and blocks the system to wait for direct keyboard input. A string must be entered, terminated by . This string is returned in passwd. If hide is true, then the typed characters are not displayed, but hidden as asterisk characters. "MarkWebLink" PROCEDURE MarkWebLink (t: Texts.Text); Finds all occurences of "http://" in t and inserts Web LinkElems around such URLs. "ShowText" PROCEDURE ShowText (mail: PostOffice.Mail; T: Texts.Text); ShowText displays mail with Text T in a viewer it opens. It decodes MIME messages if neccessary and inserts web links if desired (cf. entry 'MakeWebLinks' in Mail.Profile). "GetPasswd" PROCEDURE GetPasswd; Prompts the user for a password, which is stored in pwd. "GetMenuFrame" PROCEDURE GetMenuFrame (VAR f: MailboxFrame); Gets the MailboxFrame from which the last command was issued. Returns NIL (in f) if last command has not been issued from a MailboxFrame's menu. "GetFocusFrame" PROCEDURE GetFocusFrame (VAR f: MailboxFrame); Gets the Mailbox frame which currently has the focus. Returns NIL (in f) if currently focused frame is not a mailbox frame. "SetWriterColor" PROCEDURE SetWriterColor (VAR w: Texts.Writer; mail: PostOffice.Mail); Sets the color of w according to the status of mail. Cf. colRead, colUnread and colDeleted. "ChangeMailColor" PROCEDURE ChangeMailColor (f: MailboxFrame; mail: PostOffice.Mail); Changes the color of the line in f which displays mail according to the status of mail. "WriteBox" PROCEDURE WriteBox (VAR box: PostOffice.Mailbox; VAR t: Texts.Text); WriteBox writes all mails of box to t, using a PostOffice.Reader and a Texts.Writer. "Open" Syntax: Mail.Open [mailboxname] Opens the mailbox with the given name. If no mailbox name is given the standard mailbox is opened. "Move" Syntax: Can only be called from a menu in a MailboxFrame. Moves selected message to focus viewer. "Copy" Syntax: Can only be called from a menu in a MailboxFrame. Copies selected message to focus viewer. "CheckNew" Syntax: Mail.CheckNew Checks if new mail is on the POP server and prints out a message. Tries to download new messages from POP server. If no password has been supplied so far, the user is prompted for a password. "FetchNew" Syntax: Mail.FetchNew Tries to download new messages from POP server. If no password has been supplied so far, the user is prompted for a password. pollerAction specifies if messages are copied or moved from the server. "Show" Syntax: Can only be called from a menu in a MailboxFrame Shows the selected message. "Delete" Syntax: Can only be called from a menu in a MailboxFrame Deletes the selected message. "Undelete" Syntax: Can only be called from a menu in a MailboxFrame Undeletes the selected message. "MarkRead" Syntax: Can only be called from a menu in a MailboxFrame Marks the selected message as read. "Store" Syntax: Can only be called from a menu in a MailboxFrame Stores the mailbox. "SortBySubject" Syntax: Can only be called from a menu in a MailboxFrame Sorts the mailbox ascendingly with respect to the mails' subject. "SortBySender" Syntax: Can only be called from a menu in a MailboxFrame Sorts the mailbox ascendingly with respect to the mails' sender. "SortBySize" Syntax: Can only be called from a menu in a MailboxFrame Sorts the mailbox ascendingly with respect to the mails' size. "GetRecipient" PROCEDURE GetRecipient (t: Texts.Text; VAR pos: LONGINT; VAR str: String); Reads one recipient (mail address) from t at pos and yields the result in str. "GetRecipientList" PROCEDURE GetRecipientList (t: Texts.Text; pattern: ARRAY OF CHAR; VAR list: PostOffice.StringList); Reads the list of recipients called 'pattern' (e.g.: To, cc) from t and yields the result in list. "ParseRecipients" PROCEDURE ParseRecipients* (t: Texts.Text; VAR to, cc, bcc: PostOffice.StringList); Gets the three recipient lists to, cc and bcc from t. "ParseAttachments" PROCEDURE ParseAttachments* (t: Texts.Text; VAR att: PostOffice.StringList; VAR ok: BOOLEAN); Gets the list of attachments from t. ok is true, iff all file names in att are names of existing files. "SendDone" PROCEDURE SendDone (sucess: BOOLEAN; msg: ARRAY OF CHAR; V: Viewers.Viewer; backup: Texts.Buffer); Gives out msg. If success = false restores V with backup. "Send" Syntax: Can only be called from menu. Sends the newly created mail. "OpenSendNew" PROCEDURE OpenSendNew* (rcpts, cc, bcc, subject, attachments: ARRAY OF CHAR); Opens a viewer containing an empty bodied mail with recipients, subject and attachments as given in rcpts, cc, bcc, subject, attachments. "SendNew" Syntax: Mail.SendNew [to [subject [cc [bcc [attachments]]]]] Suply all parameters as Strings; Example: Mail.SendNew "me@mydomain.com" "Just a test" "" "" "Welcome.Text" "OpenReplyFwd" PROCEDURE OpenReplyFwd (oldTxt: Texts.Text; to, subject: ARRAY OF CHAR; x, y: INTEGER); Opens a viewer at x, y containing oldTxt and a header for sending the text to recipients 'to' and with subject 'subject'. "Quote" PROCEDURE Quote (t: Texts.Text); Puts quotation marks (">") before each line of text in t. "GetOldMail" PROCEDURE GetOldMail (VAR t: Texts.Text; VAR mail: PostOffice.Mail; VAR x, y: INTEGER); Gets the mail and message text from the Viewer the command was launched in. Also returns the position (x,y) of the viewer to allow creation of a new Viewer at the same position. "Reply" Syntax: Can only be called from menu Opens a new viewer for sending a reply message to a certain mail. "Forward" Syntax: Can only be called from menu Opens a new viewer for forwarding a mail. "GetMsgNr" PROCEDURE GetMsgNr (t: Texts.Text; pos: LONGINT): INTEGER; Returns the integer value at pos in t or -1 if there is no integer value at pos in t. "NextLine" PROCEDURE NextLine (t: Texts.Text; pos: LONGINT): LONGINT; Returns the position of the next line from pos in t. "ThisFrame" PROCEDURE ThisFrame (x, y: INTEGER): TextFrames.Frame; Returns the text frame at position x, y or NIL if there is no text frame at position x, y. "InvertRect" PROCEDURE InvertRect (f: TextFrames.Frame; x, y, w, h: INTEGER); Inverts the given rectangle (x, y, w, h) in f. "TrackMM" PROCEDURE TrackMM (F: MailboxFrame); Handles middle mouse button clicks. If MM is clicked without moving the mouse, the message clicked on is displayed. If MM is clicked and a message dragged to another MailboxFrame the message will be moved to the mailbox of that frame. If MM is clicked and a message dragged to another MailboxFrame and an interclick of the right mouse button occurs, the message will be copied to the mailbox of that frame. If MM is clicked and MR is interclicked without moving the mouse, the message is popped up, if it is small enough to easily fit in one screen. ML+MM+MR cancels all actions. "TrackMR" PROCEDURE TrackMR (F: MailboxFrame); Handles right mouse button clicks. MR causes one complete line (message) to be selected. If the mouse button is held down and the mouse moved around more lines (messages) will be added to the selection. If ML is interclicked the selected messages will be marked for deletion. If MR is interclicked the selected messages will be unmarked from deletion. "Handle" PROCEDURE Handle* (f: Display.Frame; VAR msg: Display.FrameMsg); Handles MailboxFrames by calling TrackMM and TrackMR as well as adjusting mail colours on PostOffice.NotifyMsgs. "PollNewMail" PROCEDURE PollNewMail; Tries to fetch new mail, prompting for a password if needed. "Poller" PROCEDURE Poller (cmd: ARRAY OF CHAR); If cmd = "on" the poller will be turned on. If cmd = "off" the poller will be turned off. Else the state of the poller is displayed. "Terminate" PROCEDURE Terminate; Removes the polling task when unloading the module (to avoid dangling procedure pointers) "PollerOn" Syntax: Mail.PollerOn Turns on the poller. "PollerOff" Syntax: Mail.PollerOff "SetUser" Syntax: Mail.SetUser username Gets username and prompts for password. "CreateSign" Syntax: Mail.CreateSign Opens signature file, using the menu defined in SigMenu. "ImportMailbox" Syntax: Mail.ImportMailbox filename boxname Imports the plain ASCII file 'filename' which must contain mails to the mailbox 'boxname'. Both names must be supplied. "DrawCopy" Used for copyMarker "DrawMove" Used for moveMarker "Init" Initializes Mail. Sets Fonts, installs termination handler for polling task, Installs 'mailto:' protocol for web browser, checks Mail.Profile and sets up icons for drag & drop. Sets up action for poller. "FetchDone" FetchDone is called when the PostOffice background POP task has finished popping mails from the POP Server. It displays a message telling the user how many messages have been fetched. "FetchDoneSilent" FetchDone silent does the same as FetchDone but does not display any message if no message has been fetched. It used by the Poller. "GetPwd" Gets the password from encrypted form "SetPwd" Sets the password. "CreateBoxNames" Enters all .mbx - Files into the list of known Mailbox - Files. "Search" Syntax: Mail.Search pattern Searches one (if called from menu with pattern marked) or all (if called from commandline) mailboxes for the given pattern. Matching mails are copied into the mailbox 'Search'. "SearchText" PROCEDURE SearchText (t: Texts.Text; pattern: ARRAY OF CHAR): BOOLEAN; Searches t for pattern returning TRUE, iff pattern occurs at least one time in t. "receiver" receiver*: PostOffice.Receiver; You can install additional e-mail Filters by assigning Receiver procedures to this variable. "sender" sender*: PostOffice.Sender; You can install a procedure to be executed for each outgoing mail here. InfoElemsAllocUSyntax10.Scn.FntStampElemsAlloc4 Jun 99"Title": Mail "Author": MH 27.4.1994 / 1.7.94, CS 1.9.96, RLI Feb.-Oct 98 "Abstract": Front end of mail application "Keywords": mail e-mail "Version": 1.0 "From": 1994 "Until":  "Changes": Virtually nothing survived from the first version of Mail. Almost completely rewritten by RLI. 3 Dec 98 RLI multiple copy / move implemented 3 Dec 09 RLI Oberon.CopyMsg handled by MailboxFrame and MailFrame "Hints": Edit.Open MailTool.Text Syntax10i.Scn.FntbpVersionElemsAllocBeg#Syntax10.Scn.FntLinuxAndWindows Macintosh MacintoshLinuxAndWindows$Syntax10i.Scn.FntWindows and LinuxMacintosh  pVersionElemsAllocEnd8FoldElemsNewSyntax10.Scn.Fnt  Syntax10i.Scn.Fnt    MailboxMenu = "^MailBox.Menu.Text"; MailMenu = "^MailSend.Menu.Text"; SigMenu = "^Edit.Menu.Text"; MR = 0; MM = 1; ML = 2; BackgCol = 0; CR = 0DX; NL = 0DX; Tab = 09X; maxBoxes = 30; PopupTime = 5; (* --- poller actions *) check = 0; move = 1; copy = 2; (* --- mailbox colors *) colUnread = 1; (* Red *) colRead = 15; (* Black *) colDeleted = 3; (* Blue *) 88mSyntax10.Scn.FntSyntax10b.Scn.Fnt  String = PostOffice.String; Scheme* = POINTER TO SchemeDesc; SchemeDesc* = RECORD (Web.LoaderDesc) END ; MailboxFrame = POINTER TO MailboxFrameDesc; MailboxFrameDesc = RECORD (TextFrames.FrameDesc) box: PostOffice.Mailbox END; MailFrame = POINTER TO MailFrameDesc; MailFrameDesc = RECORD (TextFrames.FrameDesc) box: PostOffice.Mailbox; mail: PostOffice.Mail END; MovePopup = POINTER TO MovePopupDesc; MovePopupDesc = RECORD (PopupElems.ElemDesc) box: PostOffice.Mailbox; msgNr: INTEGER END; 8h8Syntax10.Scn.FntQSyntax10b.Scn.Fnt xSyntax10i.Scn.Fnt  NormalFont, SubjectFont: Fonts.Font; Task: Oberon.Task; TaskStarted: BOOLEAN; user: ARRAY 32 OF CHAR; passwd: ARRAY 32 OF INTEGER; signatureText, mBox: ARRAY 256 OF CHAR; copyMarker, moveMarker: Oberon.Marker; moveIcon, copyIcon: Display.Pattern; pollerAction: INTEGER; boxName: ARRAY maxBoxes OF String; nrBoxNames: INTEGER; receiver*: PostOffice.Receiver; sender*: PostOffice.Sender; SuperHandle: Display.Handler; gList: PostOffice.StringList; gListCur: INTEGER; desc: BOOLEAN; (* Sort descendingly *) 82}8#Syntax10.Scn.Fntaa BEGIN IF In.Next() = In.name THEN In.Name(str) ELSE In.String(str) END END InNameString; 8+8#Syntax10.Scn.Fnt VAR R: Texts.Reader; T: Texts.Text; ch: CHAR; BEGIN T := V.dsc(TextFrames.Frame).text; Texts.OpenReader(R, T, T.len - 1); Texts.Read(R, ch); IF ch = "!" THEN Texts.Delete(T, T.len - 1, T.len) END END UnmarkMenu; 8S 8CSyntax10.Scn.FntSyntax10i.Scn.FntPb (* Prompts for the user to enter a password. If hide characters are invisible *) VAR i: INTEGER; ch: CHAR; w: Texts.Writer; BEGIN Texts.OpenWriter(w); Texts.WriteString(w, prompt); Texts.Append(Oberon.Log, w.buf); i := 0; Input.Read(ch); WHILE (ch # 0DX) & (i < LEN(passwd)) DO IF ch = 7FX THEN IF (i > 0) THEN DEC(i); Texts.Delete(Oberon.Log, Oberon.Log.len - 1, Oberon.Log.len) END ELSE IF ~hide THEN Texts.Write(w, ch); Texts.Append(Oberon.Log, w.buf); passwd[i] := ch; INC(i) ELSE Texts.WriteString(w, "*"); Texts.Append(Oberon.Log, w.buf); passwd[i] := ch; INC(i) END END; Input.Read(ch) END; passwd[i] := 0X; Texts.WriteLn(w) END Read; 8 Syntax10b.Scn.Fnt08#Syntax10.Scn.Fnt++ VAR newF: MailFrame; BEGIN WITH f: MailFrame DO WITH msg: Oberon.CopyMsg DO NEW(newF); msg.F := newF; TextFrames.Handle(f, msg); msg.F(MailFrame).box := f.box; msg.F(MailFrame).mail := f.mail ELSE SuperHandle(f, msg) END ELSE SuperHandle(f, msg) END END HandleMailFrame; 8d38#Syntax10.Scn.Fnt VAR F: MailFrame; BEGIN NEW(F); F.mail := mail; F.box := box; TextFrames.Open(F, T, 0); F.col := BackgCol; F.handle := HandleMailFrame; RETURN F END NewMailFrame; 8P8#Syntax10.Scn.Fnt VAR r: Texts.Reader; j: INTEGER; ch: CHAR; BEGIN Texts.OpenReader(r, t, beg); Texts.Read(r, ch); j := 0; WHILE beg < end DO isUrl[j] := ch; INC(beg); INC(j); Texts.Read(r, ch) END; isUrl[j] := 0X END GetUrl; 8:8#Syntax10.Scn.Fnt VAR e: WebElems.LinkElem; isUrl: ARRAY 256 OF CHAR; w: Texts.Writer; BEGIN Texts.OpenWriter(w); GetUrl(beg, end, t, isUrl); e := WebElems.NewLink(WebElems.LeftSide, TRUE); NEW(e.url, Strings.Length(isUrl) + 1); COPY (isUrl, e.url^); Texts.WriteElem(w, e); Texts.Insert(t, beg, w.buf); e := WebElems.NewLink(WebElems.RightSide, TRUE); Texts.WriteElem(w, e); Texts.Insert(t, end + 1, w.buf); Texts.ChangeLooks(t, beg, end + 1, {1}, NIL, WebElems.linkCol, 0) END LinkToMail; 8( 8Syntax10.Scn.FntFL8FoldElemsNew#Syntax10.Scn.FntTexts.OpenReader(r, t, end - 2); Texts.Read(r, ch); WHILE ch = "." DO DEC(end); Texts.OpenReader(r, t, end - 2); Texts.Read(r, ch) END; 8 VAR beg, end: LONGINT; r: Texts.Reader; ch: CHAR; BEGIN beg := 0; beg := PostOffice.SearchPatt2(t, "http://", beg); WHILE beg # - 1 DO Texts.OpenReader(r, t, beg); Texts.Read(r, ch); WHILE ~r.eot & (ch # " ") & (ch # '"') & (ch # 0DX) & (ch # ")") & (ch # "(") DO Texts.Read(r, ch) END; end := Texts.Pos(r); Cut trailing dots LinkToMail(beg - 7, end - 1, t); Texts.OpenReader(r, t, end); beg := PostOffice.SearchPatt2(t, "http://", end) END END MarkWebLink; 8'8#Syntax10.Scn.Fnt VAR e: FoldElems.Elem; BEGIN NEW(e); e.mode := FoldElems.colLeft; e.W := FoldElems.elemW; e.H := FoldElems.elemH; e.handle := FoldElems.FoldHandler; e.visible := TRUE; NEW(e.hidden); Texts.OpenBuf(e.hidden); Texts.Copy(w.buf, e.hidden); Texts.OpenBuf(w.buf); Texts.WriteElem(w, e); Texts.WriteString(w, "header"); NEW(e); e.mode := FoldElems.colRight; e.W := FoldElems.elemW; e.H := FoldElems.elemH; e.handle := FoldElems.FoldHandler; e.visible := TRUE; Texts.WriteElem(w, e) END Fold; 8UX8Syntax10.Scn.Fnt8FoldElemsNew#Syntax10.Scn.Fnt<<Texts.OpenWriter(w); Texts.Save(T, 0, mail.bodyOff, w.buf);  8a8#Syntax10.Scn.Fnt}}IF ~PostOffice.GetAsBuffer("MIMEDelimiter", w.buf) THEN Out.String("MIME: Error. No entry MIMEDelimiter in Profile") END;  8O%8#Syntax10.Scn.FntIF ~PostOffice.Get('HeaderLength', headerL) THEN headerL := 'NONE' END; IF headerL # 'NONE' THEN IF headerL = 'FOLDED' THEN Fold(w) END; Texts.Insert(T, 0, w.buf) END; 8 8#Syntax10.Scn.FntIF ~PostOffice.Get ('HeaderLength', headerL) THEN headerL := 'NONE' END; IF headerL = 'NONE' THEN Texts.Delete(T, 0, mail.bodyOff) END; IF headerL = 'FOLDED' THEN Texts.Delete(T, 0, mail.bodyOff); Fold(w); Texts.WriteLn(w); Texts.Insert(T, 0, w.buf) END; 88#Syntax10.Scn.Fnt88Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y); F := NewMailFrame(box, mail, T); COPY(mail.subject^, subj); IF Files.Old("Mail.Menu.Text") = NIL THEN M := TextFrames.NewMenu(subj, MailMenu) ELSE M := TextFrames.NewMenu(subj, "^Mail.Menu.Text") END; V := MenuViewers.New(M, F, TextFrames.menuH, x, y);  8# VAR V: MenuViewers.Viewer; M: TextFrames.Frame; F: MailFrame; x, y: INTEGER; w: Texts.Writer; headerL, webLinks: ARRAY 32 OF CHAR; res: INTEGER; str: String; subj: ARRAY 64 OF CHAR; e: FoldElems.Elem; BEGIN Save header Add delimiter IF MIME.IsMime(mail) THEN MIME.Decode(mail, T, res); IF res = MIME.notExact THEN Out.String("Mail: Warning! Unknown MIME - subtype '"); str := MIME.GetCompleteContentType(mail.header); Out.String(str^); Out.String("'$") ELSIF res = MIME.unknownContent THEN Out.String("Mail: Error! Unknown MIME - type.$") END; Restore header, if neccessary ELSE Cut header, if neccessary END; IF ~PostOffice.Get('MakeWebLinks', webLinks) THEN webLinks := 'YES' END; IF webLinks = 'YES' THEN MarkWebLink(T) END; Open viewer END ShowText; 8 YQ+J8#Syntax10.Scn.Fnt VAR ch: CHAR; i: INTEGER; BEGIN i := 0; REPEAT ch := CHR(255 - passwd[i]); str[i] := ch; INC(i) UNTIL ch = 0X; str[i] := ch END GetPwd; 8,<8#Syntax10.Scn.Fnt VAR i: INTEGER; BEGIN i := 0; REPEAT passwd[i] := SHORT(255 - ORD(str[i])); INC(i) UNTIL str[i] = 0X; passwd[i] := SHORT(255 - ORD(str[i])) END SetPwd; 88#Syntax10.Scn.FntLL VAR str, pwd, polstr: ARRAY 64 OF CHAR; BEGIN GetPwd(pwd); IF pwd = "" THEN str := "Enter password for "; Strings.Append(user, str); Strings.Append(": ", str); Read(str, pwd, TRUE); Out.Ln; SetPwd(pwd); IF PostOffice.Get('Poller' , polstr) THEN IF polstr = "ON" THEN Poller("on") END END END END GetPasswd; 8/8#Syntax10.Scn.Fnt BEGIN IF Oberon.Par.vwr.dsc = Oberon.Par.frame THEN IF (Oberon.Par.vwr IS MenuViewers.Viewer) & (Oberon.Par.vwr.dsc.next IS MailboxFrame) THEN f := Oberon.Par.vwr.dsc.next(MailboxFrame) ELSE f := NIL END END END GetMenuFrame; 808#Syntax10.Scn.Fnt BEGIN IF (Oberon.FocusViewer IS MenuViewers.Viewer) & (Oberon.FocusViewer.dsc.next IS MailboxFrame) THEN f := Oberon.FocusViewer.dsc.next(MailboxFrame) ELSE f := NIL END END GetFocusFrame; 8H8#Syntax10.Scn.Fnt BEGIN IF (PostOffice.statDeleted IN mail.status) THEN Texts.SetColor(w, colDeleted) ELSIF (PostOffice.statRead IN mail.status) THEN Texts.SetColor(w, colRead) ELSE Texts.SetColor(w, colUnread) END END SetWriterColor; 8E8XSyntax10.Scn.FntYSyntax10i.Scn.Fnt 68FoldElemsNew#Syntax10.Scn.FntTexts.OpenReader(r, f.text, Texts.Pos(s)); Texts.Read(r, ch); WHILE ~r.eot & (ch # CR) DO Texts.Read(r, ch) END; Texts.OpenScanner(s, f.text, Texts.Pos(r)); '8ND VAR r: Texts.Reader; s: Texts.Scanner; ch: CHAR; col: SHORTINT; start: LONGINT; BEGIN (* --- Find beginning of line *) Texts.OpenScanner(s, f.text, 0); Texts.OpenReader(r, f.text, 0); REPEAT Texts.Scan(s) UNTIL (s.class = Texts.Int) OR s.eot; ASSERT(s.class = Texts.Int); WHILE (s.i # mail.key) DO Find start of next line and set s to it Texts.Scan(s); ASSERT(s.class = Texts.Int) END; start := Texts.Pos(r); (* --- Find end of line *) Texts.Read(r, ch); WHILE ~r.eot & (ch # CR) DO Texts.Read(r, ch) END; IF PostOffice.statDeleted IN mail.status THEN col := colDeleted ELSIF PostOffice.statRead IN mail.status THEN col := colRead ELSE col := colUnread END; Texts.ChangeLooks(f.text, start, Texts.Pos(r), {1}, NIL, col, 0) END ChangeMailColor; 8F8Syntax10.Scn.Fnt_8FoldElemsNew#Syntax10.Scn.Fnt++PostOffice.OpenReader(box, R); PostOffice.Read(R); WHILE ~R.eof DO SetWriterColor(W, R.mail); Texts.WriteInt(W, R.mail.key, 0); Texts.Write(W, Tab); IF (R.mail.sender = NIL) OR (R.mail.sender^ = "") THEN Texts.WriteString(W, "unknown") ELSE Texts.WriteString(W, R.mail.sender^) END; Texts.Write(W, Tab); Texts.SetFont(W, SubjectFont); Texts.WriteString(W, R.mail.subject^); Texts.SetFont(W, NormalFont); Texts.Write(W, Tab); Texts.WriteInt(W, R.mail.size, 0); Texts.WriteLn(W); PostOffice.Read(R) END; Texts.Append(t, W.buf); 8 VAR R: PostOffice.Reader; W: Texts.Writer; BEGIN IF t = NIL THEN t := TextFrames.Text("") ELSE Texts.Delete(t, 0, t.len) END; Texts.OpenWriter(W); IF ~PostOffice.GetAsBuffer('MailboxParc', W.buf) THEN Out.String("Mail: Warning! No Mailbox parc defined in Mail.Profile$") ELSE Texts.Append(t, W.buf); Texts.Delete(t, t.len - 1, t.len) END; Write mails of box to t END WriteBox; 8 8Syntax10.Scn.Fnt8FoldElemsNew#Syntax10.Scn.Fnt..IF boxname = "" THEN COPY(mBox, boxname) END; 8uy VAR V: MenuViewers.Viewer; M: TextFrames.Frame; x, y: INTEGER; boxname: ARRAY 256 OF CHAR; t: Texts.Text; F: MailboxFrame; box: PostOffice.Mailbox; i: INTEGER; BEGIN In.Open; InNameString(boxname); IF ~ In.Done THEN boxname := "" END; Mailboxname given? IF Strings.Pos(".mbx", boxname, 0) # - 1 THEN boxname[Strings.Pos(".mbx", boxname, 0)] := 0X END; i := 0; WHILE (i < nrBoxNames) & (boxName[i]^ # boxname) DO INC(i) END; IF (i = nrBoxNames) THEN NEW(boxName[nrBoxNames], Strings.Length(boxname) + 1); COPY(boxname, boxName[nrBoxNames]^); INC(nrBoxNames) END; PostOffice.GetBox(boxname, box); WriteBox(box, t); Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y); NEW(F); F.box := box; TextFrames.Open(F, t, 0); F.handle := Handle; F.col := BackgCol; M := TextFrames.NewMenu(box.name, MailboxMenu); V := MenuViewers.New(M, F, TextFrames.menuH, x, y) END Open; 8 Kx8QSyntax10.Scn.FntSyntax10b.Scn.Fnta)8 VAR curLine: INTEGER; src, dst: MailboxFrame; S: Texts.Scanner; BEGIN GetMenuFrame(src); IF src = NIL THEN Out.String("Mail: Move must be called from menu$"); RETURN END; GetFocusFrame(dst); IF dst = NIL THEN Out.String("Mail: Place caret in target mailbox$"); RETURN END; IF src.hasSel THEN Texts.OpenScanner(S, src.text, src.selbeg.pos); Texts.Scan(S); WHILE (Texts.Pos(S) < src.selend.pos) & (S.class = Texts.Int) DO src.box.Move(dst.box, SHORT(S.i)); curLine := S.line; WHILE ~S.eot & (curLine = S.line) DO Texts.Scan(S) END END END END Move; 8 Lx8QSyntax10.Scn.FntSyntax10b.Scn.Fnta)8 VAR curLine: INTEGER; src, dst: MailboxFrame; S: Texts.Scanner; BEGIN GetMenuFrame(src); IF src = NIL THEN Out.String("Mail: Copy must be called from menu$"); RETURN END; GetFocusFrame(dst); IF dst = NIL THEN Out.String("Mail: Place caret in target mailbox$"); RETURN END; IF src.hasSel THEN Texts.OpenScanner(S, src.text, src.selbeg.pos); Texts.Scan(S); WHILE (Texts.Pos(S) < src.selend.pos) & (S.class = Texts.Int) DO src.box.Copy(dst.box, SHORT(S.i)); curLine := S.line; WHILE ~S.eot & (curLine = S.line) DO Texts.Scan(S) END END END END Copy; 8  )W8#Syntax10.Scn.Fnt VAR box: PostOffice.Mailbox; msg: PostOffice.NotifyMsg; BEGIN PostOffice.GetBox(mBox, box); box.AppendMail(mail, t) END DefaultIn; 8H8#Syntax10.Scn.Fnt BEGIN IF ok THEN IF nrMsg = 0 THEN Out.String("Mail: No mails for "); Out.String(user) ELSE Out.F("Mail: # mail(s) found for ", nrMsg); Out.String(user) END ELSE Out.String("Mail: Error! "); Out.String(msg) END; Out.Ln END FetchDone; 8N8#Syntax10.Scn.Fnt BEGIN IF ok THEN IF nrMsg # 0 THEN Out.F("Mail: # mail(s) found for ", nrMsg); Out.String(user); Out.Ln END ELSE Out.String("Mail: Error! "); Out.String(msg); Out.Ln END END FetchDoneSilent; 8  84Syntax10.Scn.Fnt=,8FoldElemsNewCSyntax10.Scn.FntSyntax10b.Scn.FntIF PostOffice.popConnOpen THEN Out.String("Mail: Cannot check for new mail. $ A connection to the pop server already exists.$"); RETURN END; 8 VAR box: PostOffice.Mailbox; pwd: ARRAY 32 OF CHAR; BEGIN Check POP state GetPasswd; PostOffice.GetBox(mBox, box); GetPwd(pwd); PostOffice.FetchNew(user, pwd, receiver, pollerAction = move, FetchDone) END FetchNew; 8  84Syntax10.Scn.FntE,8FoldElemsNewCSyntax10.Scn.FntSyntax10b.Scn.FntIF PostOffice.popConnOpen THEN Out.String("Mail: Cannot check for new mail. $ A connection to the pop server already exists.$"); RETURN END; 8o VAR nofmsgs: LONGINT; done: BOOLEAN; pwd: ARRAY 32 OF CHAR; BEGIN Check POP state GetPasswd; GetPwd(pwd); PostOffice.CheckNew(user, pwd, nofmsgs, done); IF done THEN IF nofmsgs = 0 THEN Out.String("Mail: No mail for "); Out.String(user) ELSE Out.String("Mail: "); Out.Int(nofmsgs, 0); Out.String(" mail(s) found for "); Out.String(user) END; Out.Ln ELSE Out.String("Mail: Could not connect to POP server.$") END END CheckNew; 8 ;8CSyntax10.Scn.FntSyntax10b.Scn.Fnt) VAR S: Texts.Scanner; T: Texts.Text; F: MailboxFrame; mail: PostOffice.Mail; BEGIN GetMenuFrame(F); IF F = NIL THEN Out.String("Mail: Mail.Show must be called from menu$"); RETURN END; IF F.hasSel THEN Texts.OpenScanner(S, F.text, F.selbeg.pos); Texts.Scan(S); IF S.class = Texts.Int THEN T := TextFrames.Text(""); F.box.GetText(SHORT(S.i), T); F.box.GetMailByNr(SHORT(S.i), mail); ShowText(F.box, mail, T); F.box.MarkRead(SHORT(S.i)) END END END Show; 8 %8CSyntax10.Scn.FntSyntax10b.Scn.Fnt4 VAR S: Texts.Scanner; F: MailboxFrame; curLine: INTEGER; BEGIN GetMenuFrame(F); IF F = NIL THEN Out.String("Mail: Mail.Delete must be called from menu$"); RETURN END; IF F.hasSel THEN Texts.OpenScanner(S, F.text, F.selbeg.pos); Texts.Scan(S); F.box.Delete(SHORT(S.i)); WHILE (Texts.Pos(S) < F.selend.pos) & (S.class = Texts.Int) DO F.box.Delete(SHORT(S.i)); curLine := S.line; WHILE ~S.eot & (curLine = S.line) DO Texts.Scan(S) END END END END Delete; 8  '8CSyntax10.Scn.FntSyntax10b.Scn.Fnt: VAR S: Texts.Scanner; F: MailboxFrame; curLine: INTEGER; BEGIN GetMenuFrame(F); IF F = NIL THEN Out.String("Mail: Mail.Undelete must be called from menu$"); RETURN END; IF F.hasSel THEN Texts.OpenScanner(S, F.text, F.selbeg.pos); Texts.Scan(S); F.box.Undelete(SHORT(S.i)); WHILE (Texts.Pos(S) < F.selend.pos) & (S.class = Texts.Int) DO F.box.Undelete(SHORT(S.i)); curLine := S.line; WHILE ~S.eot & (curLine = S.line) DO Texts.Scan(S) END END END END Undelete; 8  )8CSyntax10.Scn.FntSyntax10b.Scn.Fnt: VAR S: Texts.Scanner; F: MailboxFrame; curLine: INTEGER; BEGIN GetMenuFrame(F); IF F = NIL THEN Out.String("Mail: Mail.MarkAsRead must be called from menu$"); RETURN END; IF F.hasSel THEN Texts.OpenScanner(S, F.text, F.selbeg.pos); Texts.Scan(S); F.box.Undelete(SHORT(S.i)); WHILE (Texts.Pos(S) < F.selend.pos) & (S.class = Texts.Int) DO F.box.MarkRead(SHORT(S.i)); curLine := S.line; WHILE ~S.eot & (curLine = S.line) DO Texts.Scan(S) END END END END MarkRead; 8 $8CSyntax10.Scn.FntySyntax10b.Scn.Fnt VAR F: MailboxFrame; BEGIN GetMenuFrame(F); IF F = NIL THEN Out.String("Mail: Mail.Store must be called from menu$"); RETURN END; F.box.Store; Out.String("Mail: "); Out.String(F.box.name); Out.String(" stored$"); UnmarkMenu(Oberon.Par.vwr) END Store; 8 8#Syntax10.Scn.Fnt** BEGIN desc := FALSE END SortAscending; 8 8#Syntax10.Scn.Fnt** BEGIN desc := TRUE END SortDescending; 8E8#Syntax10.Scn.Fnt BEGIN IF mail1.subject^ > mail2.subject^ THEN RETURN PostOffice.greater ELSIF mail1.subject^ = mail2.subject^ THEN RETURN PostOffice.equal ELSE RETURN PostOffice.less END END CompareSubject; 8 ,8CSyntax10.Scn.FntSyntax10b.Scn.Fnt; VAR F: MailboxFrame; BEGIN GetMenuFrame(F); IF F = NIL THEN Out.String("Mail: Mail.SortBySubject must be called from menu$"); RETURN END; F.box.Sort(CompareSubject, desc) END SortBySubject; 8D8#Syntax10.Scn.Fnt BEGIN IF mail1.sender^ > mail2.sender^ THEN RETURN PostOffice.greater ELSIF mail1.sender^ = mail2.sender^ THEN RETURN PostOffice.equal ELSE RETURN PostOffice.less END END CompareSender; 8 +8CSyntax10.Scn.FntSyntax10b.Scn.Fnt9 VAR F: MailboxFrame; BEGIN GetMenuFrame(F); IF F = NIL THEN Out.String("Mail: Mail.SortBySender must be called from menu$"); RETURN END; F.box.Sort(CompareSender, desc) END SortBySender; 8B-8#Syntax10.Scn.Fnt BEGIN IF mail1.size > mail2.size THEN RETURN PostOffice.greater ELSIF mail1.size = mail2.size THEN RETURN PostOffice.equal ELSE RETURN PostOffice.less END END CompareSize; 8  )8CSyntax10.Scn.Fnt~Syntax10b.Scn.Fnt5 VAR F: MailboxFrame; BEGIN GetMenuFrame(F); IF F = NIL THEN Out.String("Mail: Mail.SortBySize must be called from menu$"); RETURN END; F.box.Sort(CompareSize, desc) END SortBySize; 8:8PSyntax10.Scn.FntH8FoldElemsNew#Syntax10.Scn.Fntidx := 0; WHILE (date[idx] < "0") OR (date[idx] > "9") DO INC(idx) END; x := 0; WHILE (date[idx] >= "0") & (date[idx] <= "9") DO day[x] := date[idx]; INC(x); INC(idx) END; IF x < 2 THEN Strings.Insert("0", 0, day) END; day[x] := 0X; INC(idx); 88#Syntax10.Scn.Fnt++Strings.Extract(date^, idx, 3, month); INC(idx, 4); IF month = "Jan" THEN month := "01" ELSIF month = "Feb" THEN month := "02" ELSIF month = "Mar" THEN month := "03" ELSIF month = "Apr" THEN month := "04" ELSIF month = "May" THEN month := "05" ELSIF month = "Jun" THEN month := "06" ELSIF month = "Jul" THEN month := "07" ELSIF month = "Aug" THEN month := "08" ELSIF month = "Sep" THEN month := "09" ELSIF month = "Oct" THEN month := "10" ELSIF month = "Nov" THEN month := "11" ELSIF month = "Dec" THEN month := "12" ELSE month := "01" END;  8'8#Syntax10.Scn.Fntx := 0; WHILE (date[idx] >= "0") & (date[idx] <= "9") DO year[x] := date[idx]; INC(x); INC(idx) END; year[x] := 0X; INC(idx); IF x < 4 THEN Strings.Insert("19", 0, year) END;  88#Syntax10.Scn.Fnt33Strings.Extract(date^, idx, 8, time); INC(idx, 9); 8f8#Syntax10.Scn.FntxxNEW(str, 20); COPY(year, str^); Strings.Append(month, str^); Strings.Append(day, str^); Strings.Append(time, str^); ,8 VAR day, month, year, time: ARRAY 32 OF CHAR; idx, x: INTEGER; BEGIN Get day Get month Get year  Get time Concatenate everything (year month day time) END GetDateString; 8B8CSyntax10.Scn.Fnt;Syntax10i.Scn.Fnt VAR date1, date2: PostOffice.Header; datStr1, datStr2, cmp1, cmp2: String; BEGIN date1 := mail1.header.GetHeaderField("DATE"); IF date1 # NIL THEN datStr1 := date1.body ELSE datStr1 := NIL END; date2 := mail2.header.GetHeaderField("DATE"); IF date2 # NIL THEN datStr2 := date2.body ELSE datStr2 := NIL END; (* NIL checks *) IF datStr1 = NIL THEN IF datStr2 = NIL THEN RETURN PostOffice.equal ELSE RETURN PostOffice.less END ELSIF datStr2 = NIL THEN RETURN PostOffice.greater END; GetDateString(datStr1, cmp1); GetDateString(datStr2, cmp2); IF cmp1^ > cmp2^ THEN RETURN PostOffice.greater ELSIF cmp1^ = cmp2^ THEN RETURN PostOffice.equal ELSE RETURN PostOffice.less END END CompareDate; 8  )8CSyntax10.Scn.Fnt~Syntax10b.Scn.Fnt5 VAR F: MailboxFrame; BEGIN GetMenuFrame(F); IF F = NIL THEN Out.String("Mail: Mail.SortByDate must be called from menu$"); RETURN END; F.box.Sort(CompareDate, desc) END SortByDate; 8D8#Syntax10.Scn.Fnt VAR st1, st2: INTEGER; BEGIN st1 := 0; st2 := 0; IF PostOffice.statDeleted IN mail1.status THEN INC(st1, 2) END; IF PostOffice.statRead IN mail1.status THEN INC(st1) END; IF PostOffice.statDeleted IN mail2.status THEN INC(st2, 2) END; IF PostOffice.statRead IN mail2.status THEN INC(st2) END; IF st1 < st2 THEN RETURN PostOffice.less ELSIF st1 = st2 THEN RETURN PostOffice.equal ELSE RETURN PostOffice.greater END END CompareStatus; 8 +8CSyntax10.Scn.Fnt~Syntax10b.Scn.Fnt9 VAR F: MailboxFrame; BEGIN GetMenuFrame(F); IF F = NIL THEN Out.String("Mail: Mail.SortByDate must be called from menu$"); RETURN END; F.box.Sort(CompareStatus, desc) END SortByStatus; 8JL]8bSyntax10.Scn.FntH08FoldElemsNew#Syntax10.Scn.Fnt PROCEDURE IsWhiteSpace (ch: CHAR): BOOLEAN; BEGIN RETURN (ch = " ") OR (ch = ",") OR (ch = "<") OR (ch = ">") OR (ch = ";") OR (ch = CR) OR (ch = CHR(9)) END IsWhiteSpace; 8I8#Syntax10.Scn.Fnt VAR s: Texts.Scanner; BEGIN Texts.OpenScanner(s, t, pos); Texts.Scan(s); IF s.class = Texts.String THEN NEW(str, Strings.Length(s.s) + 1); COPY(s.s, str^); pos := Texts.Pos(s) END; END GetString; 8Syntax10b.Scn.FntB VAR buffer: ARRAY 512 OF CHAR; r: Texts.Reader; ch: CHAR; i: INTEGER;  PROCEDURE GetString (t: Texts.Text; VAR pos: LONGINT; VAR str: String);  BEGIN str := NIL; GetString(t, pos, str); IF str # NIL THEN RETURN END; i := 0; str := NIL; Texts.OpenReader(r, t, pos); Texts.Read(r, ch); WHILE IsWhiteSpace(ch) DO IF (ch = CR) THEN RETURN END; Texts.Read(r, ch) END; WHILE ~IsWhiteSpace(ch) DO buffer[i] := ch; INC(i); Texts.Read(r, ch) END; buffer[i] := 0X; pos := Texts.Pos(r); NEW(str, Strings.Length(buffer) + 1); COPY(buffer, str^) END GetRecipient; 8f88#Syntax10.Scn.Fnt VAR pos: LONGINT; buffer: PostOffice.StringList; i, j: INTEGER; str: String; BEGIN NEW(buffer, 256); pos := PostOffice.SearchPatt2(t, pattern, 0); IF pos # - 1 THEN i := 0; GetRecipient(t, pos, str); WHILE str # NIL DO buffer[i] := str; INC(i); DEC(pos); GetRecipient(t, pos, str) END; IF i > 0 THEN NEW(list, i); FOR j := 0 TO i - 1 DO list[j] := buffer[j] END END END END GetRecipientList; 8*8#Syntax10.Scn.Fnt@@ BEGIN gList[gListCur] := a.email; INC(gListCur) END Collect; 8?V8#Syntax10.Scn.Fnt VAR a: AddrBook.Address; i, j: LONGINT; g: AddrBook.Group; newList: PostOffice.StringList; BEGIN IF list = NIL THEN RETURN END; IF AddrBook.nrEntries = 0 THEN AddrBook.Load END; i := 0; WHILE i < LEN(list^) DO AddrBook.SearchByName(list[i]^, a); IF a # NIL THEN NEW(list[i], Strings.Length(a.email^) + 1); COPY(a.email^, list[i]^) ELSE AddrBook.SearchGroupByName(list[i]^, g); IF g # NIL THEN NEW(gList, g.nrMembers); gListCur := 0; AddrBook.EnumerateAdrGroup(g, AddrBook.CompRealAndNick, Collect); NEW(newList, LEN(list^) + g.nrMembers - 1); FOR j := 0 TO i - 1 DO newList[j] := list[j] END; FOR j := i TO i + g.nrMembers - 1 DO newList[j] := gList[j - i] END; FOR j := i + g.nrMembers TO LEN(newList^) - 1 DO newList[j] := list[1 + j - g.nrMembers] END; list := newList END; INC(i) END END END LookupNicknames; 8 :8#Syntax10.Scn.Fnt BEGIN GetRecipientList(t, "To:", to); LookupNicknames(to); GetRecipientList(t, "cc:", cc); LookupNicknames(cc); GetRecipientList(t, "bcc:", bcc); LookupNicknames(bcc) END ParseRecipients; 8 C8Syntax10.Scn.FntE8FoldElemsNew#Syntax10.Scn.FntLL VAR f: Files.File; BEGIN f := Files.Old(fn); RETURN f # NIL END Exists; 8MSyntax10b.Scn.Fntf VAR x: LONGINT; PROCEDURE Exists (VAR fn: ARRAY OF CHAR): BOOLEAN;  BEGIN GetRecipientList(t, "Attach.:", att); ok := TRUE; IF att = NIL THEN RETURN END; FOR x := 0 TO LEN(att^) - 1 DO IF ~Exists(att[x]^) THEN Out.String("Mail: Cannot attach "); Out.String(att[x]^); Out.String(": no such file$"); ok := FALSE END END END ParseAttachments; 8dM8#Syntax10.Scn.Fnt VAR x, y: INTEGER; M: Viewers.ViewerMsg; t: Texts.Text; BEGIN Out.String(msg); Out.Ln; IF ~sucess THEN IF (V # NIL) THEN Oberon.AllocateUserViewer (Oberon.Mouse.X, x, y); t := V.dsc.next(TextFrames.Frame).text; IF backup # NIL THEN Texts.Delete(t, 0, t.len); Texts.Append(t, backup) END; Viewers.Open(V, x, y); M.id := Viewers.restore; V.handle(V, M) END END END SendDone; 8 %8#Syntax10.Scn.Fnt VAR backup: Texts.Buffer; to, cc, bcc, att: PostOffice.StringList; ok: BOOLEAN; BEGIN NEW(backup); Texts.OpenBuf(backup); Texts.Save(T, 0, T.len, backup); ParseRecipients(T, to, cc, bcc); ParseAttachments(T, att, ok); IF ok & (to # NIL) THEN Out.String("Mail: Sending mail ...$"); MIME.Encode(T, att); PostOffice.SendInBackground(T, to, cc, bcc, SendDone, V, backup) ELSE SendDone(FALSE, "Mail: Cannot send this mail", V, backup) END END DoSend; 8 8#Syntax10.Scn.FntTT VAR T: Texts.Text; cur: PostOffice.Sender; V: Viewers.Viewer; to, cc, bcc, att: PostOffice.StringList; ok: BOOLEAN; BEGIN T := NIL; V := Oberon.Par.vwr; IF (V # NIL ) & (V IS MenuViewers.Viewer) & (V.dsc.next IS TextFrames.Frame) THEN T := V.dsc.next(TextFrames.Frame).text END; ParseRecipients(T, to, cc, bcc); ParseAttachments(T, att, ok); IF ok & (to # NIL) THEN Viewers.Close(V); cur := sender; WHILE cur # NIL DO cur.do(V, T); cur := cur.next END ELSE IF to = NIL THEN Out.String("Mail: Cannot send mail to noone. Specify recipient(s).$") END END END Send; 8  8#Syntax10.Scn.Fnt11 BEGIN MIME.ascii := TRUE; Send END SendAscii; 8  88#Syntax10.Scn.FntJJ VAR T, text: Texts.Text; buf: Texts.Buffer; V: MenuViewers.Viewer; F, M: TextFrames.Frame; x, y: INTEGER; BEGIN T := TextFrames.Text(""); PostOffice.MakeMailText(T, rcpts, cc, bcc, subject, attachments); Oberon.AllocateUserViewer (Oberon.Mouse.X, x, y); F := TextFrames.NewText(T, 0); M := TextFrames.NewMenu ("Message", MailMenu); V := MenuViewers.New (M, F, TextFrames.menuH, x, y); NEW(text); text.notify := TextFrames.NotifyDisplay; Texts.Open(text, signatureText); NEW(buf); Texts.OpenBuf(buf); Texts.Save(text, 0, text.len, buf); Texts.Append(T, buf) END OpenSendNew; 8  @8#Syntax10.Scn.Fnt VAR subject, rcpts, cc, bcc, attachments: ARRAY 255 OF CHAR; BEGIN In.Open; In.String(rcpts); IF ~In.Done THEN rcpts := "" END; In.String(subject); IF ~In.Done THEN subject := "" END; In.String(cc); IF ~In.Done THEN cc := "" END; In.String(bcc); IF ~In.Done THEN bcc := "" END; In.String(attachments); IF ~In.Done THEN attachments := "" END; OpenSendNew(rcpts, cc, bcc, subject, attachments) END SendNew; 8Y8#Syntax10.Scn.Fnt## VAR T, text: Texts.Text; F, M: TextFrames.Frame; V: Viewers.Viewer; buf: Texts.Buffer; BEGIN T := TextFrames.Text(""); PostOffice.MakeMailText(T, to, "", "", subject, ""); F := TextFrames.NewText(T, 0); M := TextFrames.NewMenu ("Message", MailMenu); NEW(text); text.notify := TextFrames.NotifyDisplay; Texts.Open(text, signatureText); NEW(buf); Texts.OpenBuf(buf); Texts.Save(oldTxt, 0, oldTxt.len, buf); Texts.Save(text, 0, text.len, buf); Texts.Append(T, buf); V := MenuViewers.New (M, F, TextFrames.menuH, x, y) END OpenReplyFwd; 8"N8#Syntax10.Scn.Fnt VAR r: Texts.Reader; w: Texts.Writer; ch: CHAR; BEGIN Texts.OpenReader(r, t, 0); Texts.OpenWriter(w); Texts.Write(w, ">"); Texts.Insert(t, 0, w.buf); Texts.Read(r, ch); WHILE ~r.eot DO IF ch = NL THEN Texts.Write(w, ">"); Texts.Insert(t, Texts.Pos(r), w.buf); Texts.OpenReader(r, t, Texts.Pos(r)) END; Texts.Read(r, ch) END; Texts.WriteLn(w); Texts.Append(t, w.buf) END Quote; 8Y8CSyntax10.Scn.FntwSyntax10b.Scn.FntD VAR V: Viewers.Viewer; box: PostOffice.Mailbox; BEGIN V := NIL; IF Oberon.Par.vwr.dsc = Oberon.Par.frame THEN V := Oberon.Par.vwr ELSE V := Oberon.MarkedViewer() END; IF (V # NIL) & (V IS MenuViewers.Viewer) & (V.dsc.next IS MailFrame) THEN mail := V.dsc.next(MailFrame).mail; box := V.dsc.next(MailFrame).box; t := V.dsc.next(TextFrames.Frame).text ELSE RETURN END; Viewers.Close(V); x := V.X; y := V.Y + V.H END GetOldMail; 8 8#Syntax10.Scn.Fnt== VAR src: Texts.Text; oldMail: PostOffice.Mail; subject: String; x, y: INTEGER; BEGIN GetOldMail(src, oldMail, x, y); NEW(subject, Strings.Length(oldMail.subject^) + 5); COPY("Re: ", subject^); Strings.Append(oldMail.subject^, subject^); Quote(src); OpenReplyFwd(src, oldMail.reply^, subject^, x, y) END Reply; 8  h8#Syntax10.Scn.Fntvv VAR src: Texts.Text; oldMail: PostOffice.Mail; to, subject: String; x, y: INTEGER; len: LONGINT; cc: PostOffice.Header; BEGIN GetOldMail(src, oldMail, x, y); NEW(subject, Strings.Length(oldMail.subject^) + 5); COPY("Re: ", subject^); Strings.Append(oldMail.subject^, subject^); Quote(src); len := Strings.Length(oldMail.reply^) + 1; cc := oldMail.header.GetHeaderField("CC"); IF cc # NIL THEN len := len + Strings.Length(cc.body^) + 2 END; NEW(to, len); COPY(oldMail.reply^, to^); IF cc # NIL THEN Strings.Append(" ", to^); Strings.Append(cc.body^, to^) END; OpenReplyFwd(src, to^, subject^, x, y) END ReplyAll; 8  8#Syntax10.Scn.Fnt44 VAR src: Texts.Text; oldMail: PostOffice.Mail; subject: String; x, y: INTEGER; BEGIN GetOldMail(src, oldMail, x, y); NEW(subject, Strings.Length(oldMail.subject^) + 6); COPY("Fwd: ", subject^); Strings.Append(oldMail.subject^, subject^); Quote(src); OpenReplyFwd(src, "", subject^, x, y) END Forward; 8H%8Syntax10.Scn.FntSyntax10i.Scn.Fnt %=EWD@ExEf CONST bufSize = 31744; (*2**15 - 1024*) VAR m: INTEGER; r: Texts.Reader; n, pos: LONGINT; i, j, i0: INTEGER; ch, patj: CHAR; tab: ARRAY 265 OF SHORTINT; text: ARRAY bufSize OF CHAR; BEGIN m := Strings.Length(pattern); (*----- open file *) pos := 0; (*----- initialize tab *) FOR i := 0 TO 255 DO tab[i] := SHORT(m) END; FOR i := 0 TO m - 2 DO tab[ORD(pattern[i])] := SHORT(m - i - 1) END; patj := pattern[m - 1]; LOOP (*----- read text[0..n-1] *) n := t.len - pos; IF n > bufSize THEN n := bufSize END; IF n < m THEN EXIT END; Texts.OpenReader(r, t, pos); i := 0; WHILE i < n DO Texts.Read(r, text[i]); INC(i) END; (*----- search pat in text[0..n-1] *) i := m - 1; j := i; WHILE i < n DO ch := text[i]; (* IF d.noCase & ("a" <= ch) & (ch <= "z") THEN ch := CAP(ch) END; *) IF ch = patj THEN i0 := i; REPEAT DEC(i); DEC(j); ch := text[i] (* IF d.noCase & ("a" <= ch) & (ch <= "z") THEN ch := CAP(ch) END *) UNTIL (j < 0) OR (ch # pattern[j]); IF j < 0 THEN (*------ found: print result *) WHILE (i >= 0) & (text[i] # CR) & (text[i] >= 09X) DO DEC(i) END; INC(i); RETURN TRUE ELSE ch := text[i]; (* IF d.noCase & ("a" <= ch) & (ch <= "z") THEN ch := CAP(ch) END; *) i := i + tab[ORD(ch)] END; IF i <= i0 THEN i := i0 + 1 END; j := m - 1 ELSE ch := text[i]; (* IF d.noCase & ("a" <= ch) & (ch <= "z") THEN ch := CAP(ch) END; *) i := i + tab[ORD(ch)] END END; pos := pos + i - m + 1 END; RETURN FALSE END SearchText; 8 8/Syntax10.Scn.Fnt18FoldElemsNew#Syntax10.Scn.FntPostOffice.GetBox("Search", dBox); PostOffice.OpenReader(dBox, r); PostOffice.Read(r); WHILE ~r.eof DO dBox.Delete(r.mail.key); PostOffice.Read(r) END; dBox.Store; 8# VAR pattern: ARRAY 256 OF CHAR; F: MailboxFrame; sBox, dBox: PostOffice.Mailbox; r: PostOffice.Reader; t: Texts.Text; x, y: INTEGER; M: TextFrames.Frame; V: Viewers.Viewer; all: BOOLEAN; boxIdx: INTEGER; BEGIN IF nrBoxNames = 0 THEN RETURN END; boxIdx := 0; make empty search result box t := TextFrames.Text(""); GetMenuFrame(F); IF F = NIL THEN all := TRUE ELSE sBox := F.box END; In.Open; InNameString(pattern); ASSERT(In.Done); REPEAT IF all THEN PostOffice.GetBox(boxName[boxIdx]^, sBox) END; PostOffice.OpenReader(sBox, r); PostOffice.Read(r); WHILE ~r.eof DO sBox.GetText(r.mail.key, t); IF SearchText(t, pattern) THEN sBox.Copy(dBox, r.mail.key) END; PostOffice.Read(r) END; INC(boxIdx); ; UNTIL ~all OR (boxIdx >= nrBoxNames); WriteBox(dBox, t); Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y); NEW(F); F.box := dBox; TextFrames.Open(F, t, 0); F.handle := Handle; F.col := BackgCol; M := TextFrames.NewMenu(dBox.name, MailboxMenu); V := MenuViewers.New(M, F, TextFrames.menuH, x, y) END Search; 8H<;8#Syntax10.Scn.Fnt VAR s: Texts.Scanner; BEGIN Texts.OpenScanner(s, t, pos); Texts.Scan(s); IF s.class = Texts.Int THEN RETURN SHORT(s.i) ELSE RETURN - 1 END END GetMsgNr; 8<+8#Syntax10.Scn.Fnt VAR r: Texts.Reader; ch: CHAR; BEGIN Texts.OpenReader(r, t, pos); Texts.Read(r, ch); WHILE ~r.eot & (ch # NL) DO Texts.Read(r, ch) END; RETURN Texts.Pos(r) END NextLine; 898#Syntax10.Scn.Fnt00 VAR v: Viewers.Viewer; f: Display.Frame; BEGIN v := Viewers.This(x, y); f := v.dsc; WHILE (f # NIL) & ((x < f.X) OR (x > f.X + f.W) OR (y < f.Y) OR (y > f.Y + f.H)) DO f := f.next END; IF (f # NIL) & (f IS TextFrames.Frame) THEN RETURN f(TextFrames.Frame) ELSE RETURN NIL END END ThisFrame; 8B8CSyntax10.Scn.FntSyntax10i.Scn.Fnt* (*clips to right and bottom frame margin*) BEGIN IF x + w > f.X + f.W - f.right THEN w := f.X + f.W - f.right - x END; IF y >= f.Y + f.bot THEN Display.ReplConst(Display.white, x, y, w, h, Display.invert) END END InvertRect; 8As8#Syntax10.Scn.Fntkk VAR s: Texts.Scanner; dest: PostOffice.Mailbox; BEGIN WITH E: MovePopup DO WITH msg: PopupElems.ExecMsg DO Texts.OpenScanner(s, E.menu, msg.pos); Texts.Scan(s); ASSERT(s.class = Texts.Name); PostOffice.GetBox(s.s, dest); E.box.Move(dest, E.msgNr) ELSE PopupElems.Handle(E, msg) END ELSE PopupElems.Handle(E, msg) END END MoverHandler; 898#Syntax10.Scn.Fnt VAR msg: TextFrames.TrackMsg; e: MovePopup; w: Texts.Writer; i: INTEGER; BEGIN NEW(e); e.box := F.box; e.msgNr := msgNr; e.handle := MoverHandler; e.def := 0; Texts.OpenWriter(w); FOR i := 0 TO nrBoxNames - 1 DO Texts.WriteString(w, boxName[i]^); Texts.WriteLn(w) END; e.menu := TextFrames.Text(""); Texts.Append(e.menu, w.buf); msg.frame := F; msg.fnt := Fonts.Default; Input.Mouse(msg.keys, msg.X0, msg.Y0); Input.Mouse(msg.keys, msg.X, msg.Y); PopupElems.Handle(e, msg) END PopupMover; 8A8#Syntax10.Scn.Fnt VAR r: Texts.Reader; ch: CHAR; BEGIN DEC(pos); ch := 0X; WHILE (pos > 0) & (ch # NL) DO Texts.OpenReader(r, t, pos); Texts.Read(r, ch); DEC(pos) END; IF pos > 0 THEN INC(pos) END; INC(pos); RETURN pos END FindLineStart; 8@)8#Syntax10.Scn.Fnt VAR r: Texts.Reader; ch: CHAR; BEGIN Texts.OpenReader(r, t, pos); Texts.Read(r, ch); WHILE ~r.eot & (ch # NL) DO Texts.Read(r, ch) END; RETURN Texts.Pos(r) END FindLineEnd; 8(f8Syntax10.Scn.Fnt8FoldElemsNew#Syntax10.Scn.Fnt'' VAR v: Viewers.Viewer; f: TextFrames.Frame; loc, loc2: TextFrames.Location; okeys: SET; s: Texts.Scanner; i: INTEGER; BEGIN v := Viewers.This(x, y); IF (v # NIL) & (v.dsc # NIL) & (v.dsc.next IS TextFrames.Frame) THEN f := v.dsc.next(TextFrames.Frame); TextFrames.LocateWord(f, x, y, loc); Texts.OpenScanner(s, f.text, loc.pos); Texts.Scan(s); IF s.class IN {Texts.Name, Texts.String} THEN i := 0; IF Strings.Pos(".mbx", s.s, 0) # - 1 THEN s.s[Strings.Pos(".mbx", s.s, 0)] := 0X END; WHILE (i < maxBoxes) & (boxName[i] # NIL) & (boxName[i]^ # s.s) DO INC(i) END; IF (i < maxBoxes) & (boxName[i] # NIL) THEN COPY(s.s, fileName) ELSE fileName := "" END END; IF fileName # "" THEN InvertRect(f, loc.x, loc.y, loc.dx, 2); okeys := keys; REPEAT Input.Mouse(keys, x, y); TextFrames.LocateWord(f, x, y, loc2); Oberon.DrawCursor(Oberon.Mouse, marker, x, y) UNTIL (loc.x # loc2.x) OR (loc.y # loc2.y) OR (keys # okeys); InvertRect(f, loc.x, loc.y, loc.dx, 2) END END END HighlightBox; 8i CONST moved = 1000; VAR keys, keysum: SET; msgNr, x, y, x0, y0: INTEGER; T: Texts.Text; loc: TextFrames.Location; start, end: LONGINT; marker: Oberon.Marker; N: Oberon.ControlMsg; f2: TextFrames.Frame; fDest: MailboxFrame; fileName: ARRAY 512 OF CHAR; dBox: PostOffice.Mailbox; w: Texts.Writer; mail: PostOffice.Mail; startMM: LONGINT; PROCEDURE HighlightBox (VAR x, y: INTEGER; VAR keys: SET);  BEGIN Texts.OpenWriter(w); fileName := ""; Input.Mouse(keys, x, y); x0 := x; y0 := y; keysum := keys; startMM := 0; TextFrames.LocateLine(F, y, loc); end := TextFrames.Pos(F, F.X + F.W - 2, loc.y); end := FindLineEnd(F.text, end); start := loc.org; start := FindLineStart(F.text, start); TextFrames.SetSelection(F, start, end); msgNr := GetMsgNr(F.text, start); marker := Oberon.Arrow; T := TextFrames.Text(""); WHILE keys # {} DO Input.Mouse(keys, x, y); keysum := keysum + keys; IF (msgNr # - 1) & ((ABS(x - x0) > 10) OR (ABS(y - y0) > 10)) THEN x0 := moved; IF keysum = {MM, MR} THEN marker := copyMarker ELSE marker := moveMarker END; HighlightBox(x, y, keys) END; IF (x0 # moved) & (keys = {MM, MR}) THEN F.box.GetText(msgNr, T); F.box.GetMailByNr(msgNr, mail); Texts.Delete(T, 0, mail.bodyOff); IF T.len > 2500 THEN Texts.Delete(T, 0, T.len); Texts.WriteString(w, "Mail too long for popup display. Use MM to open viewer"); Texts.WriteLn(w); Texts.Append(T, w.buf) END; BalloonElems.Popup(T, 0, T.len, keys); keys := {} END; IF (x0 # moved) & (keys = {MM}) THEN IF startMM = 0 THEN startMM := Input.Time() ELSE IF (Input.Time() - startMM) * 10 DIV Input.TimeUnit > PopupTime THEN PopupMover(F, msgNr); keys := {}; keysum := {} END END ELSE startMM := 0 END; Oberon.DrawCursor(Oberon.Mouse, marker, x, y) END; Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, x, y); IF ((keysum = {MM}) & (x0 # moved)) THEN IF msgNr # - 1 THEN T := TextFrames.Text(""); F.box.GetText(msgNr, T); F.box.GetMailByNr(msgNr, mail); ShowText(F.box, mail, T); F.box.MarkRead(msgNr) END ELSIF (keysum # {ML, MM, MR}) & (msgNr # - 1) THEN dBox := NIL; f2 := ThisFrame(x, y); IF (f2 # NIL) & (f2 # F) & (f2 IS MailboxFrame) THEN fDest := f2(MailboxFrame); dBox := fDest.box ELSIF fileName # "" THEN PostOffice.GetBox(fileName, dBox) END; IF dBox # NIL THEN IF keysum = {MM, MR} THEN F.box.Copy(dBox, msgNr) ELSE F.box.Move(dBox, msgNr) END END END; N.id := Oberon.neutralize; F.handle(F, N) END TrackMM; 8&n8#Syntax10.Scn.Fntpp VAR keys, keysum: SET; msgNr, x, y: INTEGER; loc, loc2: TextFrames.Location; pos, end: LONGINT; BEGIN Input.Mouse(keys, x, y); keysum := keys; TextFrames.LocateLine(F, y, loc); end := TextFrames.Pos(F, F.X + F.W - 2, loc.y); TextFrames.SetSelection(F, loc.org, end); WHILE keys # {} DO Input.Mouse(keys, x, y); keysum := keysum + keys; TextFrames.LocateLine(F, y, loc2); end := TextFrames.Pos(F, F.X + F.W - 2, loc2.y); TextFrames.SetSelection(F, loc.org, end); Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, x, y) END; IF GetMsgNr(F.text, loc.org) # - 1 THEN pos := loc.org; msgNr := GetMsgNr(F.text, pos); WHILE (pos <= loc2.org) & (msgNr # - 1) DO IF keysum = {MR, ML} THEN F.box.Delete(msgNr) ELSIF keysum = {MR, MM} THEN F.box.Undelete(msgNr) END; pos := NextLine(F.text, pos); msgNr := GetMsgNr(F.text, pos) END END END TrackMR; 8 08CSyntax10.Scn.FntSyntax10i.Scn.Fnt VAR newF: MailboxFrame; BEGIN WITH msg: Oberon.InputMsg DO WITH f: MailboxFrame DO IF (msg.id = Oberon.track) & (msg.keys = {MM}) & (msg.X >= f.X + f.left) THEN TrackMM(f) ELSIF (msg.id = Oberon.track) & (msg.keys = {MR}) THEN IF msg.X < f.X + f.barW THEN (* scrollbar *) TextFrames.Handle(f, msg) ELSE TrackMR(f) END ELSE TextFrames.Handle(f, msg) END ELSE Out.String("Error: Mail.Handle called for non-Mailbox-Frame$"); TextFrames.Handle(f, msg) END | msg: PostOffice.NotifyMsg DO WITH f: MailboxFrame DO IF msg.box.name = f.box.name THEN IF (msg.op = PostOffice.stat) OR (msg.op = PostOffice.delete) OR (msg.op = PostOffice.undelete) THEN ChangeMailColor(f, msg.mail) ELSE WriteBox(f.box, f.text) END END END | msg: Oberon.CopyMsg DO WITH f: MailboxFrame DO NEW(newF); msg.F := newF; TextFrames.Handle(f, msg); msg.F(MailboxFrame).box := f.box END ELSE TextFrames.Handle(f, msg) END END Handle; 8J;8#Syntax10.Scn.Fnt VAR beg: INTEGER; BEGIN x := 0; beg := 0; WHILE (s[beg] # 0X) & ((s[beg] < "0") OR ("9" < s[beg])) DO INC(beg) END; WHILE ("0" <= s[beg]) & (s[beg] <= "9") DO x := 10 * x + (ORD(s[beg]) - ORD("0")); INC(beg) END END StrToInt; 88Syntax10.Scn.Fntg8FoldElemsNewCSyntax10.Scn.Fnt!Syntax10b.Scn.Fnt.IF PostOffice.popConnOpen THEN RETURN END; 8e VAR nofmsgs, pt: LONGINT; done: BOOLEAN; box: PostOffice.Mailbox; pwd, buf: ARRAY 32 OF CHAR; BEGIN Check POP state GetPasswd; PostOffice.GetBox(mBox, box); GetPwd(pwd); IF pollerAction = check THEN PostOffice.CheckNew(user, pwd, nofmsgs, done); IF done THEN IF nofmsgs > 0 THEN Out.String("Mail: You have new mail"); Out.Ln END END ELSE PostOffice.FetchNew(user, pwd, receiver, pollerAction = move, FetchDoneSilent) END; IF ~PostOffice.Get('PollerIntervall', buf) THEN pt := 600 ELSE StrToInt(buf, pt) END; Oberon.CurTask.time := Input.Time() + pt * Input.TimeUnit END PollNewMail; 8(8#Syntax10.Scn.Fnt BEGIN IF cmd = "on" THEN IF ~TaskStarted THEN Oberon.Install(Task); TaskStarted := TRUE; Out.String("Mail: Poller started") ELSE Out.String("Mail: Poller is already on") END ELSIF cmd = "off" THEN IF TaskStarted THEN Oberon.Remove(Task); TaskStarted := FALSE; Out.String("Mail: Poller stopped") ELSE Out.String("Mail: Poller is already off") END ELSE IF TaskStarted THEN Out.String("Mail: Poller is on") ELSE Out.String("Mail: Poller is off") END END; Out.Ln END Poller; 88#Syntax10.Scn.FntYY BEGIN IF TaskStarted THEN Oberon.Remove(Task); TaskStarted := FALSE END END Terminate; 8  8#Syntax10.Scn.Fnt## BEGIN Poller("on") END PollerOn; 8  8#Syntax10.Scn.Fnt%% BEGIN Poller("off") END PollerOff; 8  8#Syntax10.Scn.Fnt VAR str: ARRAY 65 OF CHAR; pwd: ARRAY 32 OF CHAR; BEGIN In.Open; InNameString(user); str := "Enter password for "; Strings.Append(user, str); Strings.Append(": ", str); Read(str, pwd, TRUE); Out.Ln; SetPwd(pwd); Out.String('Mail: New User set!'); Out.Ln END SetUser; 8A  8#Syntax10.Scn.FntNN VAR T: Texts.Text; V: MenuViewers.Viewer; F, M: TextFrames.Frame; x, y: INTEGER; BEGIN T := TextFrames.Text (signatureText); Oberon.AllocateUserViewer (Oberon.Mouse.X, x, y); F := TextFrames.NewText(T, 0); M := TextFrames.NewMenu ("Signature.Text", SigMenu); V := MenuViewers.New (M, F, TextFrames.menuH, x, y) END CreateSign; 8> K8#Syntax10.Scn.Fnt VAR filename, boxname: ARRAY 512 OF CHAR; done: BOOLEAN; BEGIN In.Open; InNameString(filename); InNameString(boxname); ASSERT(In.Done); PostOffice.ImportMailbox(filename, boxname, done); IF done THEN Out.String("Mail: Successfully imported mailbox "); Out.String(filename); Out.Ln ELSE Out.String("Mail: Error. Could not import mailbox "); Out.String(filename); Out.Ln END END ImportMailbox; 8GJ8#Syntax10.Scn.Fnt<< BEGIN OpenSendNew(act.url.path, "", "", "", "") END Open; 8D&8#Syntax10.Scn.FntYY BEGIN Display.CopyPattern(Display.white, copyIcon, x, y, Display.invert) END DrawCopy; 8&8#Syntax10.Scn.FntYY BEGIN Display.CopyPattern(Display.white, moveIcon, x, y, Display.invert) END DrawMove; 8n8#Syntax10.Scn.Fnt BEGIN cont := TRUE; IF ~isDir THEN IF Strings.Match(name, "*.mbx") THEN name[Strings.Pos(".mbx", name, 0)] := 0X; NEW(boxName[nrBoxNames], Strings.Length(name) + 1); COPY(name, boxName[nrBoxNames]^); INC(nrBoxNames) END END END CreateBoxNames; 88#Syntax10.Scn.Fnt VAR b: Texts.Buffer; t: Texts.Text; s: Texts.Scanner; buf: ARRAY 32 OF CHAR; BEGIN t := TextFrames.Text(""); NEW(b); Texts.OpenBuf(b); receiver := DefaultIn; IF PostOffice.Get('Send', buf) THEN Strings.Cap(buf) ELSE Out.String("Mail: No send time specified. Defaulting to immediate$"); buf := "IMMEDIATE" END; IF buf = "DELAYED" THEN sender := NIL ELSE NEW(sender); sender.do := DoSend; sender.next := NIL END; IF PostOffice.GetAsBuffer('AddOn', b) THEN Texts.Append(t, b); Texts.OpenScanner(s, t, 0); Texts.Scan(s); WHILE ~s.eot & (s.class = Texts.Name) DO IF Modules.ThisMod(s.s) = NIL THEN Out.String("Mail: Could not load add-on module "); Out.String(s.s); Out.Ln END; Texts.Scan(s) END END END InstallAddOns; 88!Op#Syntax10.Scn.FntLinuxAndWindows MacintoshMacintoshLinuxAndWindows#Syntax10.Scn.Fnt&&Kernel.InstallTermHandler(Terminate); Macintosh p"x8#Syntax10.Scn.Fnt77line[1] := {}; line[2] := {1..8}; line[3] := {1, 8}; line[4] := {1, 8}; line[5] := {1, 8}; line[6] := {1, 8}; line[7] := {1, 8}; line[8] := {1, 8}; line[9] := {1, 5..8}; line[10] := {1, 5, 7}; line[11] := {1, 5, 6}; line[12] := {1..5}; line[13] := {}; moveIcon := Display.NewPattern(line, 15, 13);  88#Syntax10.Scn.FntIIline[1] := {}; line[2] := {1..8}; line[3] := {1, 4, 8}; line[4] := {1, 4, 8}; line[5] := {1, 2..6, 8}; line[6] := {1, 4, 8}; line[7] := {1, 4, 8}; line[8] := {1, 8}; line[9] := {1, 5..8}; line[10] := {1, 5, 7}; line[11] := {1, 5, 6}; line[12] := {1..5}; line[13] := {}; copyIcon := Display.NewPattern(line, 15, 13);  88v8#Syntax10.Scn.Fnthh HandlerElems.SetHandler("Mail.HandleMailFrame", HandleMailFrame, SuperHandle); Init; Base64.Install; 8qMODULE Mail;   (* Macintosh *) IMPORT AddrBook, Directories, Kernel, Files, Display, FoldElems, HandlerElems, Input, Oberon, Viewers, MenuViewers, Modules, PopupElems, Texts, Fonts, TextFrames, In, PostOffice, Strings, Web, WebElems, Out, BalloonElems, MIME, Base64; CONST  TYPE  VAR  (* --- auxiliary ---*) PROCEDURE InNameString (VAR str: ARRAY OF CHAR);  PROCEDURE UnmarkMenu (V: Viewers.Viewer);  PROCEDURE Read (prompt: ARRAY OF CHAR; VAR passwd: ARRAY OF CHAR; hide: BOOLEAN);  PROCEDURE HandleMailFrame* (f: Display.Frame; VAR msg: Display.FrameMsg);  PROCEDURE NewMailFrame (box: PostOffice.Mailbox; mail: PostOffice.Mail; T: Texts.Text): MailFrame;  PROCEDURE GetUrl (beg, end: LONGINT; t: Texts.Text; VAR isUrl: ARRAY OF CHAR);  PROCEDURE LinkToMail (beg, end: LONGINT; t: Texts.Text);  PROCEDURE MarkWebLink (t: Texts.Text);  PROCEDURE Fold (VAR w: Texts.Writer);  PROCEDURE ShowText (box: PostOffice.Mailbox; mail: PostOffice.Mail; T: Texts.Text);  PROCEDURE ^Handle* (f: Display.Frame; VAR msg: Display.FrameMsg); PROCEDURE ^Poller (cmd: ARRAY OF CHAR); (* -------------------------------------------------------------------------- *) PROCEDURE GetPwd (VAR str: ARRAY OF CHAR);  PROCEDURE SetPwd (VAR str: ARRAY OF CHAR);  PROCEDURE GetPasswd;  PROCEDURE GetMenuFrame (VAR f: MailboxFrame);  PROCEDURE GetFocusFrame (VAR f: MailboxFrame);  PROCEDURE SetWriterColor (VAR w: Texts.Writer; mail: PostOffice.Mail);  PROCEDURE ChangeMailColor (f: MailboxFrame; mail: PostOffice.Mail);  PROCEDURE WriteBox (VAR box: PostOffice.Mailbox; VAR t: Texts.Text);  PROCEDURE Open*; (** Mail.Open **) PROCEDURE Move*; (** Mail.Move, called from menu, moves selected message to focus viewer **)  PROCEDURE Copy*; (** Mail.Copy, called from menu, copies selected message to focus viewer **)  PROCEDURE DefaultIn* (mail: PostOffice.Mail; t: Texts.Text);  PROCEDURE FetchDone (ok: BOOLEAN; msg: ARRAY OF CHAR; nrMsg: LONGINT);  PROCEDURE FetchDoneSilent (ok: BOOLEAN; msg: ARRAY OF CHAR; nrMsg: LONGINT);  PROCEDURE FetchNew*; (** Mail.FetchNew **)  PROCEDURE CheckNew*; (** Mail.CheckNew **)  PROCEDURE Show*; (** Mail.Show, called from menu, shows selected message **)  PROCEDURE Delete*; (** Mail.Delete, called from menu **) PROCEDURE Undelete*; (** Mail.Undelete, called from menu **) PROCEDURE MarkRead*; (** Mail.MarkAsRead, called from menu **) PROCEDURE Store*; (** Mail.Store, called from menu **)  PROCEDURE SortAscending*;  PROCEDURE SortDescending*;  PROCEDURE CompareSubject (mail1, mail2: PostOffice.Mail): SHORTINT;  PROCEDURE SortBySubject*; (** Mail.SortBySubject, called from menu **) PROCEDURE CompareSender (mail1, mail2: PostOffice.Mail): SHORTINT;  PROCEDURE SortBySender*; (** Mail.SortBySender, called from menu **) PROCEDURE CompareSize (mail1, mail2: PostOffice.Mail): SHORTINT;  PROCEDURE SortBySize*; (** Mail.SortBySize, called from menu **) PROCEDURE GetDateString (date: String; VAR str: String);  PROCEDURE CompareDate (mail1, mail2: PostOffice.Mail): SHORTINT;  PROCEDURE SortByDate*; (** Mail.SortByDate, called from menu **)  PROCEDURE CompareStatus (mail1, mail2: PostOffice.Mail): SHORTINT;  PROCEDURE SortByStatus*; (** Mail.SortByStatus, called from menu **) (* ----------------------------- Mail Methods ------------------------- *) PROCEDURE GetRecipient (t: Texts.Text; VAR pos: LONGINT; VAR str: String);  PROCEDURE GetRecipientList (t: Texts.Text; pattern: ARRAY OF CHAR; VAR list: PostOffice.StringList);  PROCEDURE Collect (a: AddrBook.Address);  PROCEDURE LookupNicknames (VAR list: PostOffice.StringList);  PROCEDURE ParseRecipients* (t: Texts.Text; VAR to, cc, bcc: PostOffice.StringList);  PROCEDURE ParseAttachments* (t: Texts.Text; VAR att: PostOffice.StringList; VAR ok: BOOLEAN);  PROCEDURE SendDone (sucess: BOOLEAN; msg: ARRAY OF CHAR; V: Viewers.Viewer; backup: Texts.Buffer);  PROCEDURE DoSend* (V: Viewers.Viewer; T: Texts.Text);  PROCEDURE Send*;  PROCEDURE SendAscii*;  PROCEDURE OpenSendNew* (rcpts, cc, bcc, subject, attachments: ARRAY OF CHAR);  PROCEDURE SendNew*;  PROCEDURE OpenReplyFwd (oldTxt: Texts.Text; to, subject: ARRAY OF CHAR; x, y: INTEGER);  PROCEDURE Quote (t: Texts.Text);  PROCEDURE GetOldMail (VAR t: Texts.Text; VAR mail: PostOffice.Mail; VAR x, y: INTEGER);  PROCEDURE Reply*;  PROCEDURE ReplyAll*;  PROCEDURE Forward*;  PROCEDURE SearchText (t: Texts.Text; pattern: ARRAY OF CHAR): BOOLEAN;  PROCEDURE Search*;  (* ---------------------- Mailbox frame handler --------------------- *) PROCEDURE GetMsgNr (t: Texts.Text; pos: LONGINT): INTEGER;  PROCEDURE NextLine (t: Texts.Text; pos: LONGINT): LONGINT;  PROCEDURE ThisFrame (x, y: INTEGER): TextFrames.Frame;  PROCEDURE InvertRect (f: TextFrames.Frame; x, y, w, h: INTEGER);  PROCEDURE MoverHandler (E: Texts.Elem; VAR msg: Texts.ElemMsg);  PROCEDURE PopupMover (F: MailboxFrame; msgNr: INTEGER);  PROCEDURE FindLineStart (t: Texts.Text; pos: LONGINT): LONGINT;  PROCEDURE FindLineEnd (t: Texts.Text; pos: LONGINT): LONGINT;  PROCEDURE TrackMM (F: MailboxFrame);  PROCEDURE TrackMR (F: MailboxFrame);  PROCEDURE Handle* (f: Display.Frame; VAR msg: Display.FrameMsg);  (* ------------------------ Post Office Poller ----------------------- *) PROCEDURE StrToInt (VAR s: ARRAY OF CHAR; VAR x: LONGINT);  PROCEDURE PollNewMail;  PROCEDURE Poller (cmd: ARRAY OF CHAR);  PROCEDURE Terminate;  PROCEDURE PollerOn*;  PROCEDURE PollerOff*;  PROCEDURE SetUser*;  (* ------------------------ Signature ----------------------- *) PROCEDURE CreateSign*;  (* ------------------------ Import ----------------------- *) PROCEDURE ImportMailbox*;  (* ------------------------ WEB registration ----------------------- *) PROCEDURE (s: Scheme) Open* (act: Web.UrlStack; txt: Web.Text; elem: Texts.Elem; useCache: BOOLEAN);  (* ------------------------ Initialization --------------------- *) PROCEDURE DrawCopy (x, y: INTEGER);  PROCEDURE DrawMove (x, y: INTEGER);  PROCEDURE CreateBoxNames (d: Directories.Directory; name: ARRAY OF CHAR; isDir: BOOLEAN; VAR cont: BOOLEAN);  PROCEDURE InstallAddOns;  PROCEDURE Init;  VAR s: Scheme; action, sortOrder: ARRAY 64 OF CHAR; line: ARRAY 14 OF SET; d: Directories.Directory; pos: INTEGER; BEGIN NormalFont := Fonts.Default; SubjectFont := Fonts.This("Syntax10i.Scn.Fnt"); NEW(Task); Task.safe := FALSE; Task.handle := PollNewMail; Task.time := Input.Time();  TaskStarted := FALSE; user := ""; SetPwd(user); NEW(s); s.scheme := "mailto"; Web.InstallLoader(s); IF ~PostOffice.Get ('inBox', mBox) THEN Out.String('Mail: inBox - Entry not existent in Profile'); Out.Ln END; IF ~PostOffice.Get ('Signature', signatureText) THEN Out.String('Mail: Signature Text - Entry not existent in Profile !'); Out.Ln END; IF ~PostOffice.Get('POPUser', user) THEN Out.String("Mail: No default pop - user in Profile$"); Out.Ln; user := "nouser" END; IF ~PostOffice.Get('PollerAction', action) THEN Out.String("Mail: No action for poller specified. Defaulting to check"); pollerAction := check ELSE Strings.Cap(action); IF action = "MOVE" THEN pollerAction := move ELSIF action = "COPY" THEN pollerAction := copy ELSIF action = "CHECK" THEN pollerAction := check ELSE Out.String("Mail: No valid action for poller specified. Defaulting to check."); pollerAction := check END END; IF ~PostOffice.Get('SortOrder', sortOrder) THEN Out.String("Mail: No sort order specified. Defaulting to ascending"); desc := FALSE; ELSE Strings.Cap(sortOrder); desc := sortOrder = "DESC" END; (* Init icons for drag and drop *) copyMarker.Draw := DrawCopy; copyMarker.Fade := DrawCopy; moveMarker.Draw := DrawMove; moveMarker.Fade := DrawMove; move icon copy icon nrBoxNames := 0; d := Directories.This(PostOffice.mDir); Directories.Enumerate(d, CreateBoxNames); InstallAddOns; END Init;  BEGIN END Mail.Open