Merge from emacs-23
[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,
5df4f04c 4;; 2005, 2006, 2007, 2008, 2009, 2010, 2011 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 48(defcustom footnote-mode-line-string " FN"
6a8b4632 49 "String to display in modes section of the mode-line."
55492d86
DL
50 :group 'footnote)
51
52(defcustom footnote-mode-hook nil
6a8b4632 53 "Hook functions run when footnote-mode is activated."
55492d86
DL
54 :type 'hook
55 :group 'footnote)
56
57(defcustom footnote-narrow-to-footnotes-when-editing nil
6a8b4632 58 "If non-nil, narrow to footnote text body while editing a footnote."
55492d86
DL
59 :type 'boolean
60 :group 'footnote)
61
62(defcustom footnote-prompt-before-deletion t
6a8b4632 63 "If non-nil, prompt before deleting a footnote.
55492d86
DL
64There is currently no way to undo deletions."
65 :type 'boolean
66 :group 'footnote)
67
68(defcustom footnote-spaced-footnotes t
6a8b4632
MR
69 "If non-nil, insert an empty line between footnotes.
70Customizing this variable has no effect on buffers already
71displaying footnotes."
55492d86
DL
72 :type 'boolean
73 :group 'footnote)
74
6a8b4632
MR
75(defcustom footnote-use-message-mode t ; Nowhere used.
76 "If non-nil, assume Footnoting will be done in `message-mode'."
55492d86
DL
77 :type 'boolean
78 :group 'footnote)
79
80(defcustom footnote-body-tag-spacing 2
6a8b4632
MR
81 "Number of spaces separating a footnote body tag and its text.
82Customizing this variable has no effect on buffers already
83displaying footnotes."
55492d86
DL
84 :type 'integer
85 :group 'footnote)
86
734db384
SM
87(defcustom footnote-prefix [(control ?c) ?!]
88 "Prefix key to use for Footnote command in Footnote minor mode.
89The value of this variable is checked as part of loading Footnote mode.
90After that, changing the prefix key requires manipulating keymaps."
91 ;; FIXME: the type should be a key-sequence, but it seems Custom
92 ;; doesn't support that yet.
93 ;; :type 'string
94 )
55492d86
DL
95
96;;; Interface variables that probably shouldn't be changed
97
c4dc7971 98(defcustom footnote-section-tag "Footnotes: "
6a8b4632
MR
99 "Tag inserted at beginning of footnote section.
100If you set this to the empty string, no tag is inserted and the
101value of `footnote-section-tag-regexp' is ignored. Customizing
102this variable has no effect on buffers already displaying
103footnotes."
c4dc7971
RS
104 :type 'string
105 :group 'footnote)
55492d86 106
5404d9b0 107(defcustom footnote-section-tag-regexp "Footnotes\\(\\[.\\]\\)?: "
6a8b4632
MR
108 "Regexp which indicates the start of a footnote section.
109This variable is disregarded when `footnote-section-tag' is the
110empty string. Customizing this variable has no effect on buffers
111already displaying footnotes."
5404d9b0
DL
112 :type 'regexp
113 :group 'footnote)
55492d86
DL
114
115;; The following three should be consumed by footnote styles.
5404d9b0 116(defcustom footnote-start-tag "["
6a8b4632
MR
117 "String used to denote start of numbered footnote.
118Should not be set to the empty string. Customizing this variable
119has no effect on buffers already displaying footnotes."
5404d9b0
DL
120 :type 'string
121 :group 'footnote)
55492d86 122
5404d9b0 123(defcustom footnote-end-tag "]"
6a8b4632
MR
124 "String used to denote end of numbered footnote.
125Should not be set to the empty string. Customizing this variable
126has no effect on buffers already displaying footnotes."
5404d9b0
DL
127 :type 'string
128 :group 'footnote)
55492d86
DL
129
130(defvar footnote-signature-separator (if (boundp 'message-signature-separator)
131 message-signature-separator
132 "^-- $")
133 "*String used to recognize .signatures.")
134
135;;; Private variables
136
137(defvar footnote-style-number nil
138 "Footnote style represented as an index into footnote-style-alist.")
139(make-variable-buffer-local 'footnote-style-number)
140
141(defvar footnote-text-marker-alist nil
142 "List of markers pointing to text of footnotes in message buffer.")
143(make-variable-buffer-local 'footnote-text-marker-alist)
144
145(defvar footnote-pointer-marker-alist nil
146 "List of markers pointing to footnote pointers in message buffer.")
147(make-variable-buffer-local 'footnote-pointer-marker-alist)
148
149(defvar footnote-mouse-highlight 'highlight
150 "Text property name to enable mouse over highlight.")
151
55492d86
DL
152;;; Default styles
153;;; NUMERIC
62b1cb94 154(defconst footnote-numeric-regexp "[0-9]+"
55492d86
DL
155 "Regexp for digits.")
156
157(defun Footnote-numeric (n)
158 "Numeric footnote style.
159Use Arabic numerals for footnoting."
160 (int-to-string n))
161
162;;; ENGLISH UPPER
163(defconst footnote-english-upper "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
164 "Upper case English alphabet.")
165
62b1cb94 166(defconst footnote-english-upper-regexp "[A-Z]+"
55492d86
DL
167 "Regexp for upper case English alphabet.")
168
169(defun Footnote-english-upper (n)
170 "Upper case English footnoting.
171Wrapping around the alphabet implies successive repetitions of letters."
172 (let* ((ltr (mod (1- n) (length footnote-english-upper)))
173 (rep (/ (1- n) (length footnote-english-upper)))
174 (chr (char-to-string (aref footnote-english-upper ltr)))
175 rc)
176 (while (>= rep 0)
177 (setq rc (concat rc chr))
178 (setq rep (1- rep)))
179 rc))
a1506d29 180
55492d86
DL
181;;; ENGLISH LOWER
182(defconst footnote-english-lower "abcdefghijklmnopqrstuvwxyz"
183 "Lower case English alphabet.")
184
62b1cb94 185(defconst footnote-english-lower-regexp "[a-z]+"
55492d86
DL
186 "Regexp of lower case English alphabet.")
187
188(defun Footnote-english-lower (n)
189 "Lower case English footnoting.
190Wrapping around the alphabet implies successive repetitions of letters."
191 (let* ((ltr (mod (1- n) (length footnote-english-lower)))
192 (rep (/ (1- n) (length footnote-english-lower)))
193 (chr (char-to-string (aref footnote-english-lower ltr)))
194 rc)
195 (while (>= rep 0)
196 (setq rc (concat rc chr))
197 (setq rep (1- rep)))
198 rc))
199
200;;; ROMAN LOWER
201(defconst footnote-roman-lower-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
62b1cb94 206(defconst footnote-roman-lower-regexp "[ivxlcdm]+"
55492d86
DL
207 "Regexp of roman numerals.")
208
209(defun Footnote-roman-lower (n)
210 "Generic Roman number footnoting."
211 (Footnote-roman-common n footnote-roman-lower-list))
212
213;;; ROMAN UPPER
214(defconst footnote-roman-upper-list
215 '((1 . "I") (5 . "V") (10 . "X")
216 (50 . "L") (100 . "C") (500 . "D") (1000 . "M"))
217 "List of roman numerals with their values.")
218
62b1cb94 219(defconst footnote-roman-upper-regexp "[IVXLCDM]+"
55492d86
DL
220 "Regexp of roman numerals. Not complete")
221
222(defun Footnote-roman-upper (n)
223 "Generic Roman number footnoting."
224 (Footnote-roman-common n footnote-roman-upper-list))
225
226(defun Footnote-roman-common (n footnote-roman-list)
227 "Lower case Roman footnoting."
228 (let* ((our-list footnote-roman-list)
229 (rom-lngth (length our-list))
230 (rom-high 0)
231 (rom-low 0)
232 (rom-div -1)
233 (count-high 0)
234 (count-low 0))
235 ;; find surrounding numbers
236 (while (and (<= count-high (1- rom-lngth))
237 (>= n (car (nth count-high our-list))))
238 ;; (message "Checking %d" (car (nth count-high our-list)))
239 (setq count-high (1+ count-high)))
240 (setq rom-high count-high)
241 (setq rom-low (1- count-high))
242 ;; find the appropriate divisor (if it exists)
243 (while (and (= rom-div -1)
244 (< count-low rom-high))
245 (when (or (> n (- (car (nth rom-high our-list))
246 (/ (car (nth count-low our-list))
247 2)))
248 (= n (- (car (nth rom-high our-list))
249 (car (nth count-low our-list)))))
250 (setq rom-div count-low))
251 ;; (message "Checking %d and %d in div loop" rom-high count-low)
252 (setq count-low (1+ count-low)))
253 ;;(message "We now have high: %d, low: %d, div: %d, n: %d"
254 ;; rom-high rom-low (if rom-div rom-div -1) n)
255 (let ((rom-low-pair (nth rom-low our-list))
256 (rom-high-pair (nth rom-high our-list))
257 (rom-div-pair (if (not (= rom-div -1)) (nth rom-div our-list) nil)))
258 ;; (message "pairs are: rom-low: %S, rom-high: %S, rom-div: %S"
259 ;; rom-low-pair rom-high-pair rom-div-pair)
260 (cond
261 ((< n 0) (error "Footnote-roman-common called with n < 0"))
262 ((= n 0) "")
263 ((= n (car rom-low-pair)) (cdr rom-low-pair))
264 ((= n (car rom-high-pair)) (cdr rom-high-pair))
265 ((= (car rom-low-pair) (car rom-high-pair))
266 (concat (cdr rom-low-pair)
267 (Footnote-roman-common
268 (- n (car rom-low-pair))
269 footnote-roman-list)))
270 ((>= rom-div 0) (concat (cdr rom-div-pair) (cdr rom-high-pair)
271 (Footnote-roman-common
272 (- n (- (car rom-high-pair)
273 (car rom-div-pair)))
274 footnote-roman-list)))
275 (t (concat (cdr rom-low-pair)
276 (Footnote-roman-common
277 (- n (car rom-low-pair))
278 footnote-roman-list)))))))
279
5404d9b0
DL
280;; Latin-1
281
dedecfd6
MR
282