(rfc822-addresses): Prevent rfc822-bad-address from raising a
[bpt/emacs.git] / lisp / mail / footnote.el
CommitLineData
e8af40ee 1;;; footnote.el --- footnote support for message mode -*- coding: iso-latin-1;-*-
55492d86 2
f2e3589a 3;; Copyright (C) 1997, 2000, 2001, 2002, 2003, 2004,
2f043267 4;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
55492d86
DL
5
6;; Author: Steven L Baur <steve@xemacs.org>
7;; Keywords: mail, news
8;; Version: 0.19
9
409f8a3f 10;; This file is part of GNU Emacs.
55492d86 11
b1fc2b50
GM
12;; GNU Emacs is free software: you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
55492d86 16
b1fc2b50
GM
17;; GNU Emacs 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
20;; GNU General Public License for more details.
55492d86
DL
21
22;; You should have received a copy of the GNU General Public License
b1fc2b50 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
55492d86 24
55492d86
DL
25;;; Commentary:
26
27;; This file provides footnote[1] support for message-mode in emacsen.
28;; footnote-mode is implemented as a minor mode.
29
30;; [1] Footnotes look something like this. Along with some decorative
31;; stuff.
32
33;; TODO:
34;; Reasonable Undo support.
35;; more language styles.
36
55492d86
DL
37;;; Code:
38
409f8a3f
DL
39(eval-when-compile
40 (require 'cl)
41 (defvar filladapt-token-table))
42
55492d86
DL
43(defgroup footnote nil
44 "Support for footnotes in mail and news messages."
5404d9b0 45 :version "21.1"
55492d86
DL
46 :group 'message)
47
55492d86
DL
48(defcustom footnote-mode-line-string " FN"
49 "*String to display in modes section of the mode-line."
50 :group 'footnote)
51
52(defcustom footnote-mode-hook nil
53 "*Hook functions run when footnote-mode is activated."
54 :type 'hook
55 :group 'footnote)
56
57(defcustom footnote-narrow-to-footnotes-when-editing nil
58 "*If set, narrow to footnote text body while editing a footnote."
59 :type 'boolean
60 :group 'footnote)
61
62(defcustom footnote-prompt-before-deletion t
63 "*If set, prompt before deleting a footnote.
64There is currently no way to undo deletions."
65 :type 'boolean
66 :group 'footnote)
67
68(defcustom footnote-spaced-footnotes t
69 "If set true it will put a blank line between each footnote.
70If nil, no blank line will be inserted."
71 :type 'boolean
72 :group 'footnote)
73
55492d86
DL
74(defcustom footnote-use-message-mode t
75 "*If non-nil assume Footnoting will be done in message-mode."
76 :type 'boolean
77 :group 'footnote)
78
79(defcustom footnote-body-tag-spacing 2
80 "*Number of blanks separating a footnote body tag and its text."
81 :type 'integer
82 :group 'footnote)
83
55492d86
DL
84(defvar footnote-prefix [(control ?c) ?!]
85 "*When not using message mode, the prefix to bind in `mode-specific-map'")
86
87;;; Interface variables that probably shouldn't be changed
88
c4dc7971
RS
89(defcustom footnote-section-tag "Footnotes: "
90 "*Tag inserted at beginning of footnote section."
bf247b6e 91 :version "22.1"
c4dc7971
RS
92 :type 'string
93 :group 'footnote)
55492d86 94
5404d9b0
DL
95(defcustom footnote-section-tag-regexp "Footnotes\\(\\[.\\]\\)?: "
96 "*Regexp which indicates the start of a footnote section.
97See also `footnote-section-tag'."
98 :type 'regexp
99 :group 'footnote)
55492d86
DL
100
101;; The following three should be consumed by footnote styles.
5404d9b0
DL
102(defcustom footnote-start-tag "["
103 "*String used to denote start of numbered footnote."
104 :type 'string
105 :group 'footnote)
55492d86 106
5404d9b0
DL
107(defcustom footnote-end-tag "]"
108 "*String used to denote end of numbered footnote."
109 :type 'string
110 :group 'footnote)
55492d86
DL
111
112(defvar footnote-signature-separator (if (boundp 'message-signature-separator)
113 message-signature-separator
114 "^-- $")
115 "*String used to recognize .signatures.")
116
117;;; Private variables
118
119(defvar footnote-style-number nil
120 "Footnote style represented as an index into footnote-style-alist.")
121(make-variable-buffer-local 'footnote-style-number)
122
123(defvar footnote-text-marker-alist nil
124 "List of markers pointing to text of footnotes in message buffer.")
125(make-variable-buffer-local 'footnote-text-marker-alist)
126
127(defvar footnote-pointer-marker-alist nil
128 "List of markers pointing to footnote pointers in message buffer.")
129(make-variable-buffer-local 'footnote-pointer-marker-alist)
130
131(defvar footnote-mouse-highlight 'highlight
132 "Text property name to enable mouse over highlight.")
133
134(defvar footnote-mode nil
135 "Variable indicating whether footnote minor mode is active.")
136(make-variable-buffer-local 'footnote-mode)
137
138;;; Default styles
139;;; NUMERIC
62b1cb94 140(defconst footnote-numeric-regexp "[0-9]+"
55492d86
DL
141 "Regexp for digits.")
142
143(defun Footnote-numeric (n)
144 "Numeric footnote style.
145Use Arabic numerals for footnoting."
146 (int-to-string n))
147
148;;; ENGLISH UPPER
149(defconst footnote-english-upper "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
150 "Upper case English alphabet.")
151
62b1cb94 152(defconst footnote-english-upper-regexp "[A-Z]+"
55492d86
DL
153 "Regexp for upper case English alphabet.")
154
155(defun Footnote-english-upper (n)
156 "Upper case English footnoting.
157Wrapping around the alphabet implies successive repetitions of letters."
158 (let* ((ltr (mod (1- n) (length footnote-english-upper)))
159 (rep (/ (1- n) (length footnote-english-upper)))
160 (chr (char-to-string (aref footnote-english-upper ltr)))
161 rc)
162 (while (>= rep 0)
163 (setq rc (concat rc chr))
164 (setq rep (1- rep)))
165 rc))
a1506d29 166
55492d86
DL
167;;; ENGLISH LOWER
168(defconst footnote-english-lower "abcdefghijklmnopqrstuvwxyz"
169 "Lower case English alphabet.")
170
62b1cb94 171(defconst footnote-english-lower-regexp "[a-z]+"
55492d86
DL
172 "Regexp of lower case English alphabet.")
173
174(defun Footnote-english-lower (n)
175 "Lower case English footnoting.
176Wrapping around the alphabet implies successive repetitions of letters."
177 (let* ((ltr (mod (1- n) (length footnote-english-lower)))
178 (rep (/ (1- n) (length footnote-english-lower)))
179 (chr (char-to-string (aref footnote-english-lower ltr)))
180 rc)
181 (while (>= rep 0)
182 (setq rc (concat rc chr))
183 (setq rep (1- rep)))
184 rc))
185
186;;; ROMAN LOWER
187(defconst footnote-roman-lower-list
188 '((1 . "i") (5 . "v") (10 . "x")
189 (50 . "l") (100 . "c") (500 . "d") (1000 . "m"))
190 "List of roman numerals with their values.")
191
62b1cb94 192(defconst footnote-roman-lower-regexp "[ivxlcdm]+"
55492d86
DL
193 "Regexp of roman numerals.")
194
195(defun Footnote-roman-lower (n)
196 "Generic Roman number footnoting."
197 (Footnote-roman-common n footnote-roman-lower-list))
198
199;;; ROMAN UPPER
200(defconst footnote-roman-upper-list
201 '((1 . "I") (5 . "V") (10 . "X")
202 (50 . "L") (100 . "C") (500 . "D") (1000 . "M"))
203 "List of roman numerals with their values.")
204
62b1cb94 205(defconst footnote-roman-upper-regexp "[IVXLCDM]+"
55492d86
DL
206 "Regexp of roman numerals. Not complete")
207
208(defun Footnote-roman-upper (n)
209 "Generic Roman number footnoting."
210 (Footnote-roman-common n footnote-roman-upper-list))
211
212(defun Footnote-roman-common (n footnote-roman-list)
213 "Lower case Roman footnoting."
214 (let* ((our-list footnote-roman-list)
215 (rom-lngth (length our-list))
216 (rom-high 0)
217 (rom-low 0)
218 (rom-div -1)
219 (count-high 0)
220 (count-low 0))
221 ;; find surrounding numbers
222 (while (and (<= count-high (1- rom-lngth))
223 (>= n (car (nth count-high our-list))))
224 ;; (message "Checking %d" (car (nth count-high our-list)))
225 (setq count-high (1+ count-high)))
226 (setq rom-high count-high)
227 (setq rom-low (1- count-high))
228 ;; find the appropriate divisor (if it exists)
229 (while (and (= rom-div -1)
230 (< count-low rom-high))
231 (when (or (> n (- (car (nth rom-high our-list))
232 (/ (car (nth count-low our-list))
233 2)))
234 (= n (- (car (nth rom-high our-list))
235 (car (nth count-low our-list)))))
236 (setq rom-div count-low))
237 ;; (message "Checking %d and %d in div loop" rom-high count-low)
238 (setq count-low (1+ count-low)))
239 ;;(message "We now have high: %d, low: %d, div: %d, n: %d"
240 ;; rom-high rom-low (if rom-div rom-div -1) n)
241 (let ((rom-low-pair (nth rom-low our-list))
242 (rom-high-pair (nth rom-high our-list))
243 (rom-div-pair (if (not (= rom-div -1)) (nth rom-div our-list) nil)))
244 ;; (message "pairs are: rom-low: %S, rom-high: %S, rom-div: %S"
245 ;; rom-low-pair rom-high-pair rom-div-pair)
246 (cond
247 ((< n 0) (error "Footnote-roman-common called with n < 0"))
248 ((= n 0) "")
249 ((= n (car rom-low-pair)) (cdr rom-low-pair))
250 ((= n (car rom-high-pair)) (cdr rom-high-pair))
251 ((= (car rom-low-pair) (car rom-high-pair))
252 (concat (cdr rom-low-pair)
253 (Footnote-roman-common
254 (- n (car rom-low-pair))
255 footnote-roman-list)))
256 ((>= rom-div 0) (concat (cdr rom-div-pair) (cdr rom-high-pair)
257 (Footnote-roman-common
258 (- n (- (car rom-high-pair)
259 (car rom-div-pair)))
260 footnote-roman-list)))
261 (t (concat (cdr rom-low-pair)
262 (Footnote-roman-common
263 (- n (car rom-low-pair))
264 footnote-roman-list)))))))
265
5404d9b0
DL
266;; Latin-1
267
dedecfd6
MR
268