1 ;;; hmail.el --- Support for Hyperbole buttons embedded in e-mail messages.
3 ;; Copyright (C) 1991-1995, 2004 Free Software Foundation, Inc.
4 ;; Developed with support from Motorola Inc.
6 ;; Author: Bob Weiner, Brown U.
7 ;; Maintainer: Mats Lidell <matsl@contactor.se>
8 ;; Keywords: hypermedia, mail
10 ;; This file is part of GNU Hyperbole.
12 ;; GNU Hyperbole is free software; you can redistribute it and/or
13 ;; modify it under the terms of the GNU General Public License as
14 ;; published by the Free Software Foundation; either version 3, or (at
15 ;; your option) any later version.
17 ;; GNU Hyperbole is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ;; General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
29 ;; The 'hmail' class provides an abstract interface for connecting
30 ;; GNU Emacs-based mail readers and composers to Hyperbole. Its
31 ;; public variables together with supporting classes determine the
32 ;; mail tools that Hyperbole will support.
34 ;; The 'rmail' and 'lmail' classes provide a set of feature names
35 ;; that Hyperbole packages can call to interface to a user's selected
36 ;; mail reader. Eventually, a full abstract calling interface may be
37 ;; developed. The public features (the ones above the line of dashes)
38 ;; must be redefined for any mail reader. The private features are
39 ;; used only by a particular mail reader.
41 ;; The 'smail' class is similar; it connects a mail composer for use
51 (defvar hnews:composer 'news-reply-mode
52 "Major mode for composing USENET news to be sent with Hyperbole buttons.")
53 (defvar hnews:lister 'gnus-summary-mode
54 "Major mode for listing USENET news header summaries with Hyperbole buttons.")
55 (defvar hnews:reader 'gnus-article-mode
56 "Major mode for reading USENET news with Hyperbole buttons.")
58 (defvar hmail:init-function nil
59 "*Function (a symbol) to run to initialize Hyperbole support for a mail reader/composer.
60 Valid values are: nil, Rmail-init, Vm-init, Mh-init, or Pm-init.")
62 (defvar hmail:composer 'mail-mode
63 "Major mode for composing mail to be sent with Hyperbole buttons.")
64 (defvar hmail:lister nil
65 "Major mode for listing mail header summaries with Hyperbole buttons.")
66 (defvar hmail:modifier nil
67 "Major mode for editing received mail with Hyperbole buttons.")
68 (defvar hmail:reader nil
69 "Major mode for reading mail with Hyperbole buttons.")
76 ;;; hmail class - abstract
79 (defun hmail:hbdata-start (&optional msg-start msg-end)
80 "Returns point immediately before any Hyperbole button data in current msg.
81 Returns message end point when no button data is found.
82 Has side-effect of widening buffer.
83 Message's displayable part begins at optional MSG-START and ends at or before
86 (or msg-end (setq msg-end (point-max)))
89 (if (search-backward hmail:hbdata-sep msg-start t) (1- (point)) msg-end)))
91 (defun hmail:hbdata-to-p ()
92 "Moves point to Hyperbole but data start in an e-mail msg.
93 Returns t if button data is found."
94 (and (cond ((memq major-mode (list hmail:reader hmail:modifier))
96 ((or (hmail:lister-p) (hnews:lister-p)) t)
97 ((memq major-mode (list hmail:composer hnews:reader
101 (goto-char (point-max))
102 (if (search-backward hmail:hbdata-sep nil t)
103 (progn (forward-line 1) t)))))
105 (defun hmail:browser-p ()
106 "Returns t iff current major mode helps browse received e-mail messages."
107 (memq major-mode (list hmail:reader hmail:lister)))
109 (defun hmail:buffer (&optional buf invisible-flag)
110 "Start composing mail with the contents of optional BUF as the message body.
111 Invisible text is expanded and included in the mail only if INVISIBLE-FLAG is
112 non-nil. BUF defaults to the current buffer and may be a buffer or buffer
114 (interactive (list (current-buffer) (y-or-n-p "Include invisible text? ")))
115 (or buf (setq buf (current-buffer)))
116 (if (stringp buf) (setq buf (get-buffer buf)))
118 (hmail:region (point-min) (point-max) buf invisible-flag))
121 (defun hmail:compose (address expr &optional subject help)
122 "Compose mail with ADDRESS and evaluation of EXPR.
123 Optional SUBJECT and HELP message may also be given."
124 (interactive "sDeliver e-mail to: \nSubject: ")
125 (require 'hactypes) ;; Needed in case EXPR calls 'hact.
126 (if (or (stringp help) (stringp subject))
128 (setq subject "Be explicit here. Make a statement or ask a question."))
129 (hmail:invoke address nil subject)
131 (if (re-search-backward "^Subject: " nil t)
132 (goto-char (match-end 0)))
133 (message (if (stringp help)
135 "Replace subject, compose message, and then mail.")))
137 (defun hmail:composing-dir (key-src)
138 "If button KEY-SRC is a mail/news composure buffer, returns composure directory, else nil."
140 (and (bufferp key-src)
141 (progn (set-buffer key-src)
142 (or (eq major-mode hmail:composer)
143 (eq major-mode hnews:composer)))
146 (defun hmail:editor-p ()
147 "Returns t iff current major mode edits Hyperbole e-mail/news messages."
148 (memq major-mode (list hmail:composer hnews:composer hmail:modifier)))
150 (defun hmail:init (class-prefix func-suffix-list)
151 "Sets up CLASS-PREFIX functions with aliases for FUNC-SUFFIX-LIST.
152 'hmail:reader' should be set appropriately before this is called."
153 (if (null hmail:reader)
155 (let* ((reader-name (symbol-name hmail:reader))
156 (reader-prefix (capitalize
157 (substring reader-name
158 0 (string-match "-" reader-name))))
161 (lambda (func-suffix)
162 (setq hmail-func (hypb:replace-match-string
163 "Summ-" func-suffix "" t))
164 (fset (intern (concat class-prefix hmail-func))
165 (intern (concat reader-prefix "-" func-suffix)))))
168 (defun hmail:invoke (&optional address cc subject)
169 "Invoke user preferred mail composer selected by the variable
170 `mail-user-agent'. Optional arguments are ADDRESS, CC list and SUBJECT
172 (compose-mail address subject (if cc (list (cons "CC" cc)))))
174 (defun hmail:lister-p ()
175 "Returns t iff current major mode is a Hyperbole e-mail lister mode."
176 (eq major-mode hmail:lister))
178 (defun hnews:lister-p ()
179 "Returns t iff current major mode is a Hyperbole news summary lister mode."
180 (eq major-mode hnews:lister))
182 (defun hmail:mode-is-p ()
183 "Returns current major mode if a Hyperbole e-mail or news mode, else nil."
184 (car (memq major-mode
185 (list hmail:reader hmail:composer hmail:lister hmail:modifier
186 hnews:reader hnews:composer hnews:lister)
189 (defun hmail:msg-narrow (&optional msg-start msg-end)
190 "Narrows buffer to displayable part of current message.
191 Its displayable part begins at optional MSG-START and ends at or before
193 (if (hmail:reader-p) (rmail:msg-widen))
194 (setq msg-start (or msg-start (point-min))
195 msg-end (or msg-end (point-max)))
196 (narrow-to-region msg-start (hmail:hbdata-start msg-start msg-end)))
198 (defun hmail:reader-p ()
199 "Returns t iff current major mode shows received Hyperbole e-mail messages."
200 (memq major-mode (list hmail:reader hmail:modifier)))
202 (defun hmail:region (start end &optional buf invisible-flag)
203 "Start composing mail with region between START and END included in message.
204 Invisible text is expanded and included in the mail only if INVISIBLE-FLAG is
205 non-nil. Optional BUF contains the region and defaults to the current
206 buffer. It may be a buffer or buffer name."
207 (interactive (list (region-beginning) (region-end) (current-buffer)
208 (y-or-n-p "Include invisible text? ")))
209 (or buf (setq buf (current-buffer)))
210 (if (stringp buf) (setq buf (get-buffer buf)))
213 (setq mail-buf (current-buffer))
215 (if (search-forward mail-header-separator nil t)
216 ;; Within header, so move to body
217 (goto-char (point-max)))
219 (hypb:insert-region mail-buf start end invisible-flag))))
222 ;;; rmail class - mail reader interface - abstract
226 "Initializes Hyperbole abstract mail interface for a particular mail reader.
227 'hmail:reader' should be set appropriately before this is called."
228 (hmail:init "rmail:" '("msg-hdrs-full" "msg-narrow" "msg-num"
229 "msg-prev" "msg-next"
230 "msg-to-p" ;; 2 args: (mail-msg-id mail-file)
232 (hmail:init "lmail:" '("Summ-delete" "Summ-expunge" "Summ-goto" "Summ-to"
233 "Summ-undelete-all")))
235 (defvar rmail:msg-hdr-prefix "\\(^Date: \\|\n\nFrom [^ \n]+ \\)"
236 "String header preceding an e-mail received message-id.")
238 (defun rmail:msg-id-get ()
239 "Returns current msg id for an 'hmail:reader' buffer as a string, else nil.
240 Signals error when current mail reader is not supported."
241 (let* ((reader (symbol-name hmail:reader))
244 (or (fboundp 'rmail:msg-hdrs-full)
245 (error "(rmail:msg-id-get): Invalid mail reader: %s" reader))
249 ;; (setq toggled (rmail:msg-hdrs-full nil))
250 (goto-char (point-min))
251 (if (re-search-forward (concat rmail:msg-hdr-prefix
253 ;; Found matching msg
254 (buffer-substring (match-beginning 2) (match-end 2))))
255 ;; (rmail:msg-hdrs-full toggled)
259 ;;; Each mail reader-specific Hyperbole support module must also define
260 ;;; the following functions, commonly aliased to existing mail reader
261 ;;; functions within the "-init" function of the Hyperbole module.
262 ;;; See "hrmail.el" for examples.
264 ;;; rmail:get-new, rmail:msg-forward, rmail:summ-msg-to, rmail:summ-new
267 ;;; Private variables
270 (defvar hmail:hbdata-sep "\^Lbd"
271 "Text separating e-mail msg from any trailing Hyperbole button data.")
275 ;;; hmail.el ends here