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