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