]> code.delx.au - gnu-emacs/blobdiff - lisp/org/org-footnote.el
Update copyright year to 2016
[gnu-emacs] / lisp / org / org-footnote.el
index 18f1bb76ff0d7b574cf16d53b075001641af551d..a25afee97f1edcc183450436fbf1230c7360b5da 100644 (file)
@@ -1,11 +1,10 @@
 ;;; org-footnote.el --- Footnote support in Org and elsewhere
 ;;
-;; Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2016 Free Software Foundation, Inc.
 ;;
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 7.4
 ;;
 ;; This file is part of GNU Emacs.
 ;;
 (require 'org-macs)
 (require 'org-compat)
 
-(declare-function org-in-commented-line "org" ())
-(declare-function org-in-regexp "org" (re &optional nlines visually))
-(declare-function org-mark-ring-push "org" (&optional pos buffer))
-(declare-function outline-next-heading "outline")
-(declare-function org-trim "org" (s))
-(declare-function org-show-context "org" (&optional key))
+(declare-function message-point-in-header-p "message" ())
+(declare-function org-back-over-empty-lines "org" ())
 (declare-function org-back-to-heading "org" (&optional invisible-ok))
+(declare-function org-combine-plists "org" (&rest plists))
 (declare-function org-end-of-subtree "org"  (&optional invisible-ok to-heading))
+(declare-function org-fill-paragraph "org" (&optional justify))
+(declare-function org-icompleting-read "org" (&rest args))
+(declare-function org-id-uuid "org-id" ())
+(declare-function org-in-block-p "org" (names))
+(declare-function org-in-commented-line "org" ())
+(declare-function org-in-indented-comment-line "org" ())
+(declare-function org-in-regexp "org" (re &optional nlines visually))
 (declare-function org-in-verbatim-emphasis "org" ())
+(declare-function org-inside-LaTeX-fragment-p "org" ())
 (declare-function org-inside-latex-macro-p "org" ())
-(defvar org-odd-levels-only) ;; defined in org.el
-(defvar message-signature-separator) ;; defined in message.el
+(declare-function org-mark-ring-push "org" (&optional pos buffer))
+(declare-function org-show-context "org" (&optional key))
+(declare-function org-trim "org" (s))
+(declare-function org-skip-whitespace "org" ())
+(declare-function outline-next-heading "outline")
+(declare-function org-skip-whitespace "org" ())
+
+(defvar org-outline-regexp-bol)                ; defined in org.el
+(defvar org-odd-levels-only)           ; defined in org.el
+(defvar org-bracket-link-regexp)       ; defined in org.el
+(defvar message-cite-prefix-regexp)    ; defined in message.el
+(defvar message-signature-separator)   ; defined in message.el
 
 (defconst org-footnote-re
-  (concat "[^][\n]"   ; to make sure it is not at the beginning of a line
-         "\\["
-         "\\(?:"
-         "\\([0-9]+\\)"
-         "\\|"
-         (org-re "\\(fn:\\([-_[:word:]]+?\\)?\\)\\(?::\\([^\]]*?\\)\\)?")
-         "\\)"
-         "\\]")
+  ;; Only [1]-like footnotes are closed in this regexp, as footnotes
+  ;; from other types might contain square brackets (i.e. links) in
+  ;; their definition.
+  ;;
+  ;; `org-re' is used for regexp compatibility with XEmacs.
+  (concat "\\[\\(?:"
+         ;; Match inline footnotes.
+         (org-re "fn:\\([-_[:word:]]+\\)?:\\|")
+         ;; Match other footnotes.
+         "\\(?:\\([0-9]+\\)\\]\\)\\|"
+         (org-re "\\(fn:[-_[:word:]]+\\)")
+         "\\)")
   "Regular expression for matching footnotes.")
 
 (defconst org-footnote-definition-re
-  (org-re "^\\(\\[\\([0-9]+\\|fn:[-_[:word:]]+\\)\\]\\)")
+  (org-re "^\\[\\([0-9]+\\|fn:[-_[:word:]]+\\)\\]")
   "Regular expression matching the definition of a footnote.")
 
+(defconst org-footnote-forbidden-blocks
+  '("ascii" "beamer" "comment" "example" "html" "latex" "odt" "src")
+  "Names of blocks where footnotes are not allowed.")
+
 (defgroup org-footnote nil
   "Footnotes in Org-mode."
   :tag "Org Footnote"
   :group 'org)
 
 (defcustom org-footnote-section "Footnotes"
-  "Outline heading containing footnote definitions before export.
-This can be nil, to place footnotes locally at the end of the current
-outline node.  If can also be the name of a special outline heading
-under which footnotes should be put.
+  "Outline heading containing footnote definitions.
+
+This can be nil, to place footnotes locally at the end of the
+current outline node.  If can also be the name of a special
+outline heading under which footnotes should be put.
+
 This variable defines the place where Org puts the definition
-automatically, i.e. when creating the footnote, and when sorting the notes.
-However, by hand you may place definitions *anywhere*.
-If this is a string, during export, all subtrees starting with this
-heading will be removed after extracting footnote definitions."
+automatically, i.e. when creating the footnote, and when sorting
+the notes.  However, by hand you may place definitions
+*anywhere*.
+
+If this is a string, during export, all subtrees starting with
+this heading will be ignored."
   :group 'org-footnote
   :type '(choice
          (string :tag "Collect footnotes under heading")
@@ -88,13 +114,17 @@ heading will be removed after extracting footnote definitions."
 
 (defcustom org-footnote-tag-for-non-org-mode-files "Footnotes:"
   "Tag marking the beginning of footnote section.
-The Org-mode footnote engine can be used in arbitrary text files as well
-as in Org-mode.  Outside Org-mode, new footnotes are always placed at
+The Org footnote engine can be used in arbitrary text files as well
+as in Org-mode.  Outside Org mode, new footnotes are always placed at
 the end of the file.  When you normalize the notes, any line containing
 only this tag will be removed, a new one will be inserted at the end
-of the file, followed by the collected and normalized footnotes."
+of the file, followed by the collected and normalized footnotes.
+
+If you don't want any tag in such buffers, set this variable to nil."
   :group 'org-footnote
-  :type 'string)
+  :type '(choice
+         (string :tag "Collect footnotes under tag")
+         (const :tag "Don't use a tag" nil)))
 
 (defcustom org-footnote-define-inline nil
   "Non-nil means define footnotes inline, at reference location.
@@ -108,17 +138,19 @@ will be used to define the footnote at the reference position."
   "Non-nil means define automatically new labels for footnotes.
 Possible values are:
 
-nil        prompt the user for each label
-t          create unique labels of the form [fn:1], [fn:2], ...
-confirm    like t, but let the user edit the created value.  In particular,
-           the label can be removed from the minibuffer, to create
+nil        Prompt the user for each label.
+t          Create unique labels of the form [fn:1], [fn:2], etc.
+confirm    Like t, but let the user edit the created value.
+           The label can be removed from the minibuffer to create
            an anonymous footnote.
-plain      Automatically create plain number labels like [1]"
+random    Automatically generate a unique, random label.
+plain      Automatically create plain number labels like [1]."
   :group 'org-footnote
   :type '(choice
          (const :tag "Prompt for label" nil)
          (const :tag "Create automatic [fn:N]" t)
          (const :tag "Offer automatic [fn:N] for editing" confirm)
+         (const :tag "Create a random label" random)
          (const :tag "Create automatic [N]" plain)))
 
 (defcustom org-footnote-auto-adjust nil
@@ -134,6 +166,7 @@ The main values of this variable can be set with in-buffer options:
 #+STARTUP: nofnadjust"
   :group 'org-footnote
   :type '(choice
+         (const :tag "No adjustment" nil)
          (const :tag "Renumber" renumber)
          (const :tag "Sort" sort)
          (const :tag "Renumber and Sort" t)))
@@ -146,96 +179,256 @@ extracted will be filled again."
   :group 'org-footnote
   :type 'boolean)
 
+(defun org-footnote-in-valid-context-p ()
+  "Is point in a context where footnotes are allowed?"
+  (save-match-data
+    (not (or (org-in-commented-line)
+            (org-in-indented-comment-line)
+            (org-inside-LaTeX-fragment-p)
+            ;; Avoid literal example.
+            (org-in-verbatim-emphasis)
+            (save-excursion
+              (beginning-of-line)
+              (looking-at "[ \t]*:[ \t]+"))
+            ;; Avoid cited text and headers in message-mode.
+            (and (derived-mode-p 'message-mode)
+                 (or (save-excursion
+                       (beginning-of-line)
+                       (looking-at message-cite-prefix-regexp))
+                     (message-point-in-header-p)))
+            ;; Avoid forbidden blocks.
+            (org-in-block-p org-footnote-forbidden-blocks)))))
+
 (defun org-footnote-at-reference-p ()
   "Is the cursor at a footnote reference?
-If yes, return the beginning position, the label, and the definition, if local."
-  (when (org-in-regexp org-footnote-re 15)
-    (list (match-beginning 0)
-         (or (match-string 1)
-             (if (equal (match-string 2) "fn:") nil (match-string 2)))
-         (match-string 4))))
+
+If so, return a list containing its label, beginning and ending
+positions, and the definition, when inlined."
+  (when (and (org-footnote-in-valid-context-p)
+            (or (looking-at org-footnote-re)
+                (org-in-regexp org-footnote-re)
+                (save-excursion (re-search-backward org-footnote-re nil t)))
+            (/= (match-beginning 0) (point-at-bol)))
+    (let* ((beg (match-beginning 0))
+          (label (or (org-match-string-no-properties 2)
+                     (org-match-string-no-properties 3)
+                     ;; Anonymous footnotes don't have labels
+                     (and (match-string 1)
+                          (concat "fn:" (org-match-string-no-properties 1)))))
+          ;; Inline footnotes don't end at (match-end 0) as
+          ;; `org-footnote-re' stops just after the second colon.
+          ;; Find the real ending with `scan-sexps', so Org doesn't
+          ;; get fooled by unrelated closing square brackets.
+          (end (ignore-errors (scan-sexps beg 1))))
+      ;; Point is really at a reference if it's located before true
+      ;; ending of the footnote.
+      (when (and end (< (point) end)
+                ;; Verify match isn't a part of a link.
+                (not (save-excursion
+                       (goto-char beg)
+                       (let ((linkp
+                              (save-match-data
+                                (org-in-regexp org-bracket-link-regexp))))
+                         (and linkp (< (point) (cdr linkp))))))
+                ;; Verify point doesn't belong to a LaTeX macro.
+                (not (org-inside-latex-macro-p)))
+       (list label beg end
+             ;; Definition: ensure this is an inline footnote first.
+             (and (or (not label) (match-string 1))
+                  (org-trim (buffer-substring-no-properties
+                             (match-end 0) (1- end)))))))))
 
 (defun org-footnote-at-definition-p ()
-  "Is the cursor at a footnote definition.
-This matches only pure definitions like [1] or [fn:name] at the beginning
-of a line.  It does not a references like [fn:name:definition], where the
-footnote text is included and defined locally.
-The return value will be nil if not at a footnote definition, and a list
-with start and label of the footnote if there is a definition at point."
+  "Is point within a footnote definition?
+
+This matches only pure definitions like [1] or [fn:name] at the
+beginning of a line.  It does not match references like
+[fn:name:definition], where the footnote text is included and
+defined locally.
+
+The return value will be nil if not at a footnote definition, and
+a list with label, start, end and definition of the footnote
+otherwise."
+  (when (save-excursion (beginning-of-line) (org-footnote-in-valid-context-p))
+    (save-excursion
+      (end-of-line)
+      ;; Footnotes definitions are separated by new headlines, another
+      ;; footnote definition or 2 blank lines.
+      (let ((lim (save-excursion
+                  (re-search-backward
+                   (concat org-outline-regexp-bol
+                           "\\|^\\([ \t]*\n\\)\\{2,\\}") nil t))))
+       (when (re-search-backward org-footnote-definition-re lim t)
+         (let ((label (org-match-string-no-properties 1))
+               (beg (match-beginning 0))
+               (beg-def (match-end 0))
+               ;; In message-mode, do not search after signature.
+               (end (let ((bound (and (derived-mode-p 'message-mode)
+                                      (save-excursion
+                                        (goto-char (point-max))
+                                        (re-search-backward
+                                         message-signature-separator nil t)))))
+                      (if (progn
+                            (end-of-line)
+                            (re-search-forward
+                             (concat org-outline-regexp-bol "\\|"
+                                     org-footnote-definition-re "\\|"
+                                     "^\\([ \t]*\n\\)\\{2,\\}") bound 'move))
+                          (match-beginning 0)
+                        (point)))))
+           (list label beg end
+                 (org-trim (buffer-substring-no-properties beg-def end)))))))))
+
+(defun org-footnote-get-next-reference (&optional label backward limit)
+  "Return complete reference of the next footnote.
+
+If LABEL is provided, get the next reference of that footnote.  If
+BACKWARD is non-nil, find previous reference instead.  LIMIT is
+the buffer position bounding the search.
+
+Return value is a list like those provided by `org-footnote-at-reference-p'.
+If no footnote is found, return nil."
   (save-excursion
-    (end-of-line 1)
-    (let ((lim (save-excursion (re-search-backward "^\\*+ \\|^[ \t]*$" nil t))))
-      (when (re-search-backward org-footnote-definition-re lim t)
-       (list (match-beginning 0) (match-string 2))))))
+    (let* ((label-fmt (if label (format "\\[%s[]:]" label) org-footnote-re)))
+      (catch 'exit
+       (while t
+         (unless (funcall (if backward #'re-search-backward #'re-search-forward)
+                          label-fmt limit t)
+           (throw 'exit nil))
+         (unless backward (backward-char))
+         (let ((ref (org-footnote-at-reference-p)))
+           (when ref (throw 'exit ref))))))))
+
+(defun org-footnote-next-reference-or-definition (limit)
+  "Move point to next footnote reference or definition.
+
+LIMIT is the buffer position bounding the search.
+
+Return value is a list like those provided by
+`org-footnote-at-reference-p' or `org-footnote-at-definition-p'.
+If no footnote is found, return nil."
+  (let* (ref (origin (point)))
+    (catch 'exit
+      (while t
+       (unless (re-search-forward org-footnote-re limit t)
+         (goto-char origin)
+         (throw 'exit nil))
+       ;; Beware: with [1]-like footnotes point will be just after
+       ;; the closing square bracket.
+       (backward-char)
+       (cond
+        ((setq ref (org-footnote-at-reference-p))
+         (throw 'exit ref))
+        ;; Definition: also grab the last square bracket, only
+        ;; matched in `org-footnote-re' for [1]-like footnotes.
+        ((save-match-data (org-footnote-at-definition-p))
+         (let ((end (match-end 0)))
+           (throw 'exit
+                  (list nil (match-beginning 0)
+                        (if (eq (char-before end) 93) end (1+ end)))))))))))
+
+(defun org-footnote-get-definition (label)
+  "Return label, boundaries and definition of the footnote LABEL."
+  (let* ((label (regexp-quote (org-footnote-normalize-label label)))
+        (re (format "^\\[%s\\]\\|.\\[%s:" label label))
+        pos)
+    (save-excursion
+      (save-restriction
+       (when (or (re-search-forward re nil t)
+                 (and (goto-char (point-min))
+                      (re-search-forward re nil t))
+                 (and (progn (widen) t)
+                      (goto-char (point-min))
+                      (re-search-forward re nil t)))
+         (let ((refp (org-footnote-at-reference-p)))
+           (cond
+            ((and (nth 3 refp) refp))
+            ((org-footnote-at-definition-p)))))))))
 
 (defun org-footnote-goto-definition (label)
-  "Find the definition of the footnote with label LABEL."
+  "Move point to the definition of the footnote LABEL.
+Return a non-nil value when a definition has been found."
   (interactive "sLabel: ")
   (org-mark-ring-push)
-  (setq label (org-footnote-normalize-label label))
-  (let ((re (format "^\\[%s\\]\\|.\\[%s:" label label))
-       pos)
-    (save-excursion
-      (setq pos (or (re-search-forward re nil t)
-                   (and (goto-char (point-min))
-                        (re-search-forward re nil t))
-                   (and (progn (widen) t)
-                        (goto-char (point-min))
-                        (re-search-forward re nil t)))))
-    (if (not pos)
+  (let ((def (org-footnote-get-definition label)))
+    (if (not def)
        (error "Cannot find definition of footnote %s" label)
-      (goto-char pos)
+      (goto-char (nth 1 def))
+      (looking-at (format "\\[%s\\]\\|\\[%s:" label label))
+      (goto-char (match-end 0))
       (org-show-context 'link-search)
-      (message "Edit definition and go back with `C-c &' or, if unique, with `C-c C-c'."))))
+      (when (derived-mode-p 'org-mode)
+       (message "Edit definition and go back with `C-c &' or, if unique, with `C-c C-c'."))
+      t)))
 
 (defun org-footnote-goto-previous-reference (label)
   "Find the first closest (to point) reference of footnote with label LABEL."
   (interactive "sLabel: ")
   (org-mark-ring-push)
-  (setq label (org-footnote-normalize-label label))
-  (let ((re (format ".\\[%s[]:]" label))
-       (p0 (point)) pos)
+  (let* ((label (org-footnote-normalize-label label)) ref)
     (save-excursion
-      (setq pos (or (re-search-backward re nil t)
-                   (and (goto-char (point-max))
-                        (re-search-backward re nil t))
-                   (and (progn (widen) t)
-                        (goto-char p0)
-                        (re-search-backward re nil t))
-                   (and (goto-char (point-max))
-                        (re-search-forward re nil t)))))
-    (if pos
-       (progn
-         (goto-char (match-end 0))
-         (org-show-context 'link-search))
-      (error "Cannot find reference of footnote %s" label))))
+      (setq ref (or (org-footnote-get-next-reference label t)
+                   (org-footnote-get-next-reference label)
+                   (save-restriction
+                     (widen)
+                     (or
+                      (org-footnote-get-next-reference label t)
+                      (org-footnote-get-next-reference label))))))
+    (if (not ref)
+       (error "Cannot find reference of footnote %s" label)
+      (goto-char (nth 1 ref))
+      (org-show-context 'link-search))))
 
 (defun org-footnote-normalize-label (label)
-  (if (numberp label) (setq label (number-to-string label)))
-  (if (not (string-match "^[0-9]+$\\|^$\\|^fn:" label))
-      (setq label (concat "fn:" label)))
-  label)
-
-(defun org-footnote-all-labels ()
-  "Return list with all defined foot labels used in the buffer."
-  (let (rtn l)
+  "Return LABEL as an appropriate string."
+  (cond
+   ((numberp label) (number-to-string label))
+   ((equal "" label) nil)
+   ((not (string-match "^[0-9]+$\\|^fn:" label))
+    (concat "fn:" label))
+   (t label)))
+
+(defun org-footnote-all-labels (&optional with-defs)
+  "Return list with all defined foot labels used in the buffer.
+
+If WITH-DEFS is non-nil, also associate the definition to each
+label.  The function will then return an alist whose key is label
+and value definition."
+  (let* (rtn
+        (push-to-rtn
+         (function
+          ;; Depending on WITH-DEFS, store label or (label . def) of
+          ;; footnote reference/definition given as argument in RTN.
+          (lambda (el)
+            (let ((lbl (car el)))
+              (push (if with-defs (cons lbl (nth 3 el)) lbl) rtn))))))
     (save-excursion
       (save-restriction
        (widen)
+       ;; Find all labels found in definitions.
        (goto-char (point-min))
-       (while (re-search-forward org-footnote-definition-re nil t)
-         (setq l (org-match-string-no-properties 2))
-         (and l (add-to-list 'rtn l)))
+       (let (def)
+         (while (re-search-forward org-footnote-definition-re nil t)
+           (when (setq def (org-footnote-at-definition-p))
+             (funcall push-to-rtn def))))
+       ;; Find all labels found in references.
        (goto-char (point-min))
-       (while (re-search-forward org-footnote-re nil t)
-         (setq l (or (org-match-string-no-properties 1)
-                     (org-match-string-no-properties 2)))
-         (and l (not (equal l "fn:")) (add-to-list 'rtn l)))))
+       (let (ref)
+         (while (setq ref (org-footnote-get-next-reference))
+           (goto-char (nth 2 ref))
+           (and (car ref)              ; ignore anonymous footnotes
+                (not (funcall (if with-defs #'assoc #'member) (car ref) rtn))
+                (funcall push-to-rtn ref))))))
     rtn))
 
 (defun org-footnote-unique-label (&optional current)
   "Return a new unique footnote label.
-The returns the firsts fn:N labels that is currently not used."
+
+The function returns the first \"fn:N\" or \"N\" label that is
+currently not used.
+
+Optional argument CURRENT is the list of labels active in the
+buffer."
   (unless current (setq current (org-footnote-all-labels)))
   (let ((fmt (if (eq org-footnote-auto-label 'plain) "%d" "fn:%d"))
        (cnt 1))
@@ -243,32 +436,37 @@ The returns the firsts fn:N labels that is currently not used."
       (incf cnt))
     (format fmt cnt)))
 
-(defvar org-footnote-label-history nil
-  "History of footnote labels entered in current buffer.")
-(make-variable-buffer-local 'org-footnote-label-history)
-
 (defun org-footnote-new ()
   "Insert a new footnote.
 This command prompts for a label.  If this is a label referencing an
 existing label, only insert the label.  If the footnote label is empty
 or new, let the user edit the definition of the footnote."
   (interactive)
-  (let* ((labels (org-footnote-all-labels))
-        (propose (org-footnote-unique-label labels))
+  (unless (org-footnote-in-valid-context-p)
+    (error "Cannot insert a footnote here"))
+  (let* ((lbls (and (not (equal org-footnote-auto-label 'random))
+                   (org-footnote-all-labels)))
+        (propose (and (not (equal org-footnote-auto-label 'random))
+                      (org-footnote-unique-label lbls)))
         (label
-         (if (member org-footnote-auto-label '(t plain))
-             propose
-           (completing-read
-            "Label (leave empty for anonymous): "
-            (mapcar 'list labels) nil nil
-            (if (eq org-footnote-auto-label 'confirm) propose nil)
-            'org-footnote-label-history))))
-    (setq label (org-footnote-normalize-label label))
+         (org-footnote-normalize-label
+          (cond
+           ((member org-footnote-auto-label '(t plain))
+            propose)
+           ((equal org-footnote-auto-label 'random)
+            (require 'org-id)
+            (substring (org-id-uuid) 0 8))
+           (t
+            (org-icompleting-read
+             "Label (leave empty for anonymous): "
+             (mapcar 'list lbls) nil nil
+             (if (eq org-footnote-auto-label 'confirm) propose nil)))))))
     (cond
-     ((equal label "")
+     ((bolp) (error "Cannot create a footnote reference at left margin"))
+     ((not label)
       (insert "[fn:: ]")
       (backward-char 1))
-     ((member label labels)
+     ((member label lbls)
       (insert "[" label "]")
       (message "New reference to existing note"))
      (org-footnote-define-inline
@@ -280,50 +478,94 @@ or new, let the user edit the definition of the footnote."
       (org-footnote-create-definition label)
       (org-footnote-auto-adjust-maybe)))))
 
+(defvar org-blank-before-new-entry) ; silence byte-compiler
 (defun org-footnote-create-definition (label)
   "Start the definition of a footnote with label LABEL."
   (interactive "sLabel: ")
-  (setq label (org-footnote-normalize-label label))
-  (let (re)
+  (let ((label (org-footnote-normalize-label label))
+       electric-indent-mode) ;; Prevent wrong indentation
     (cond
-     ((org-mode-p)
-      (if (not org-footnote-section)
-         ;; No section, put footnote into the current outline node
-         nil
-       ;; Try to find or make the special node
-       (setq re (concat "^\\*+[ \t]+" org-footnote-section "[ \t]*$"))
-       (unless (or (re-search-forward re nil t)
-                   (and (progn (widen) t)
-                        (re-search-forward re nil t)))
-         (goto-char (point-max))
-         (insert "\n\n* " org-footnote-section "\n")))
-      ;; Now go to the end of this entry and insert there.
+     ;; In an Org file.
+     ((derived-mode-p 'org-mode)
+      ;; If `org-footnote-section' is defined, find it, or create it
+      ;; at the end of the buffer.
+      (when org-footnote-section
+       (goto-char (point-min))
+       (let ((re (concat "^\\*+[ \t]+" org-footnote-section "[ \t]*$")))
+         (unless (or (re-search-forward re nil t)
+                     (and (progn (widen) t)
+                          (re-search-forward re nil t)))
+           (goto-char (point-max))
+           (skip-chars-backward " \t\r\n")
+           (unless (bolp) (newline))
+           ;; Insert new section.  Separate it from the previous one
+           ;; with a blank line, unless `org-blank-before-new-entry'
+           ;; explicitly says no.
+           (when (and (cdr (assq 'heading org-blank-before-new-entry))
+                      (zerop (save-excursion (org-back-over-empty-lines))))
+             (insert "\n"))
+           (insert "* " org-footnote-section "\n"))))
+      ;; Move to the end of this entry (which may be
+      ;; `org-footnote-section' or the current one).
       (org-footnote-goto-local-insertion-point)
       (org-show-context 'link-search))
      (t
-      (setq re (concat "^" org-footnote-tag-for-non-org-mode-files "[ \t]*$"))
-      (unless (re-search-forward re nil t)
-       (let ((max (if (and (derived-mode-p 'message-mode)
-                           (re-search-forward message-signature-separator nil t))
-                      (progn (beginning-of-line) (point))
-                    (goto-char (point-max)))))
+      ;; In a non-Org file.  Search for footnote tag, or create it if
+      ;; specified (at the end of buffer, or before signature if in
+      ;; Message mode).  Set point after any definition already there.
+      (let ((tag (and org-footnote-tag-for-non-org-mode-files
+                     (concat "^" (regexp-quote
+                                  org-footnote-tag-for-non-org-mode-files)
+                             "[ \t]*$")))
+           (max (if (and (derived-mode-p 'message-mode)
+                         (goto-char (point-max))
+                         (re-search-backward
+                          message-signature-separator nil t))
+                    (progn
+                      ;; Ensure one blank line separates last
+                      ;; footnote from signature.
+                      (beginning-of-line)
+                      (open-line 2)
+                      (point-marker))
+                  (point-max-marker))))
+       (set-marker-insertion-type max t)
+       (goto-char max)
+       ;; Check if the footnote tag is defined but missing.  In this
+       ;; case, insert it, before any footnote or one blank line
+       ;; after any previous text.
+       (when (and tag (not (re-search-backward tag nil t)))
          (skip-chars-backward " \t\r\n")
-         (delete-region (point) max)
-         (insert "\n\n")
-         (insert org-footnote-tag-for-non-org-mode-files "\n")))))
-    ;; Skip existing footnotes
-    (while (re-search-forward "^[[:space:]]*\\[[^]]+\\] " nil t)
-      (forward-line))
+         (while (re-search-backward org-footnote-definition-re nil t))
+         (unless (bolp) (newline 2))
+         (insert org-footnote-tag-for-non-org-mode-files "\n\n"))
+       ;; Remove superfluous white space and clear marker.
+       (goto-char max)
+       (skip-chars-backward " \t\r\n")
+       (delete-region (point) max)
+       (unless (bolp) (newline))
+       (set-marker max nil))))
+    ;; Insert footnote label.
+    (when (zerop (org-back-over-empty-lines)) (newline))
     (insert "[" label "] \n")
-    (goto-char (1- (point)))
-    (message "Edit definition and go back with `C-c &' or, if unique, with `C-c C-c'.")))
+    (backward-char)
+    ;; Only notify user about next possible action when in an Org
+    ;; buffer, as the bindings may have different meanings otherwise.
+    (when (derived-mode-p 'org-mode)
+      (message
+       "Edit definition and go back with `C-c &' or, if unique, with `C-c C-c'."))))
 
 ;;;###autoload
 (defun org-footnote-action (&optional special)
   "Do the right thing for footnotes.
-When at a footnote reference, jump to the definition.  When at a definition,
-jump to the references.  When neither at definition or reference,
-create a new footnote, interactively.
+
+When at a footnote reference, jump to the definition.
+
+When at a definition, jump to the references if they exist, offer
+to create them otherwise.
+
+When neither at definition or reference, create a new footnote,
+interactively.
+
 With prefix arg SPECIAL, offer additional commands in a menu."
   (interactive "P")
   (let (tmp c)
@@ -332,175 +574,199 @@ With prefix arg SPECIAL, offer additional commands in a menu."
       (message "Footnotes: [s]ort  |  [r]enumber fn:N  |  [S]=r+s |->[n]umeric  |  [d]elete")
       (setq c (read-char-exclusive))
       (cond
-       ((equal c ?s)
-       (org-footnote-normalize 'sort))
-       ((equal c ?r)
-       (org-footnote-renumber-fn:N))
-       ((equal c ?S)
+       ((eq c ?s) (org-footnote-normalize 'sort))
+       ((eq c ?r) (org-footnote-renumber-fn:N))
+       ((eq c ?S)
        (org-footnote-renumber-fn:N)
        (org-footnote-normalize 'sort))
-       ((equal c ?n)
-       (org-footnote-normalize))
-       ((equal c ?d)
-       (org-footnote-delete))
+       ((eq c ?n) (org-footnote-normalize))
+       ((eq c ?d) (org-footnote-delete))
        (t (error "No such footnote command %c" c))))
      ((setq tmp (org-footnote-at-reference-p))
-      (if (nth 1 tmp)
-         (org-footnote-goto-definition (nth 1 tmp))
-       (goto-char (match-beginning 4))))
+      (cond
+       ;; Anonymous footnote: move point at the beginning of its
+       ;; definition.
+       ((not (car tmp))
+       (goto-char (nth 1 tmp))
+       (forward-char 5))
+       ;; A definition exists: move to it.
+       ((ignore-errors (org-footnote-goto-definition (car tmp))))
+       ;; No definition exists: offer to create it.
+       ((yes-or-no-p (format "No definition for %s.  Create one? " (car tmp)))
+       (org-footnote-create-definition (car tmp)))))
      ((setq tmp (org-footnote-at-definition-p))
-      (org-footnote-goto-previous-reference (nth 1 tmp)))
+      (org-footnote-goto-previous-reference (car tmp)))
      (t (org-footnote-new)))))
 
 ;;;###autoload
-(defun org-footnote-normalize (&optional sort-only for-preprocessor)
+(defun org-footnote-normalize (&optional sort-only)
   "Collect the footnotes in various formats and normalize them.
+
 This finds the different sorts of footnotes allowed in Org, and
-normalizes them to the usual [N] format that is understood by the
-Org-mode exporters.
+normalizes them to the usual [N] format.
+
 When SORT-ONLY is set, only sort the footnote definitions into the
 referenced sequence."
   ;; This is based on Paul's function, but rewritten.
+  ;;
+  ;; Re-create `org-with-limited-levels', but not limited to Org
+  ;; buffers.
   (let* ((limit-level
          (and (boundp 'org-inlinetask-min-level)
               org-inlinetask-min-level
               (1- org-inlinetask-min-level)))
         (nstars (and limit-level
-                     (if org-odd-levels-only
-                         (and limit-level (1- (* limit-level 2)))
+                     (if org-odd-levels-only (1- (* limit-level 2))
                        limit-level)))
-        (outline-regexp
+        (org-outline-regexp
          (concat "\\*" (if nstars (format "\\{1,%d\\} " nstars) "+ ")))
         (count 0)
-        ref def idef ref-table beg beg1 marker a before ins-point)
-     (save-excursion
-      ;; Now find footnote references, and extract the definitions
-      (goto-char (point-min))
-      (while (re-search-forward org-footnote-re nil t)
-       (unless (or (org-in-commented-line) (org-in-verbatim-emphasis)
-                   (org-inside-latex-macro-p))
-         (org-if-unprotected
-          (setq def (match-string 4)
-                idef def
-                ref (or (match-string 1) (match-string 2))
-                before (char-to-string (char-after (match-beginning 0))))
-          (if (equal ref "fn:") (setq ref nil))
-          (if (and ref (setq a (assoc ref ref-table)))
-              (progn
-                (setq marker (nth 1 a))
-                (unless (nth 2 a) (setf (caddr a) def)))
-            (setq marker (number-to-string (incf count))))
-          (save-match-data
-            (if def
-                (setq def (org-trim def))
-              (save-excursion
-                (goto-char (point-min))
-                (if (not (re-search-forward (concat "^\\[" (regexp-quote ref)
-                                                    "\\]") nil t))
-                    (setq def nil)
-                  (setq beg (match-beginning 0))
-                  (setq beg1 (match-end 0))
-                  (re-search-forward
-                   (org-re "^[ \t]*$\\|^\\*+ \\|^\\[\\([0-9]+\\|fn:[-_[:word:]]+\\)\\]")
-                   nil 'move)
-                  (setq def (buffer-substring beg1 (or (match-beginning 0)
-                                                       (point-max))))
-                  (goto-char beg)
-                  (skip-chars-backward " \t\n\t")
-                  (delete-region (1+ (point)) (match-beginning 0))))))
-          (unless sort-only
-            (replace-match (concat before "[" marker "]") t t)
-            (and idef
-                 org-footnote-fill-after-inline-note-extraction
-                 (fill-paragraph)))
-          (if (not a) (push (list ref marker def (if idef t nil))
-                            ref-table)))))
-
-      ;; First find and remove the footnote section
+        ins-point ref ref-table)
+    (save-excursion
+      ;; 1. Find every footnote reference, extract the definition, and
+      ;;    collect that data in REF-TABLE.  If SORT-ONLY is nil, also
+      ;;    normalize references.
       (goto-char (point-min))
+      (while (setq ref (org-footnote-get-next-reference))
+       (let* ((lbl (car ref))
+              (pos (nth 1 ref))
+              ;; When footnote isn't anonymous, check if it's label
+              ;; (REF) is already stored in REF-TABLE.  In that case,
+              ;; extract number used to identify it (MARKER).  If
+              ;; footnote is unknown, increment the global counter
+              ;; (COUNT) to create an unused identifier.
+              (a (and lbl (assoc lbl ref-table)))
+              (marker (or (nth 1 a) (incf count)))
+              ;; Is the reference inline or pointing to an inline
+              ;; footnote?
+              (inlinep (or (stringp (nth 3 ref)) (nth 3 a))))
+         ;; Replace footnote reference with [MARKER].  Maybe fill
+         ;; paragraph once done.  If SORT-ONLY is non-nil, only move
+         ;; to the end of reference found to avoid matching it twice.
+         (if sort-only (goto-char (nth 2 ref))
+           (delete-region (nth 1 ref) (nth 2 ref))
+           (goto-char (nth 1 ref))
+           (insert (format "[%d]" marker))
+           (and inlinep
+                org-footnote-fill-after-inline-note-extraction
+                (org-fill-paragraph)))
+         ;; Add label (REF), identifier (MARKER), definition (DEF)
+         ;; type (INLINEP) and position (POS) to REF-TABLE if data
+         ;; was unknown.
+         (unless a
+           (let ((def (or (nth 3 ref)  ; Inline definition.
+                          (nth 3 (org-footnote-get-definition lbl)))))
+             (push (list lbl marker def
+                         ;; Reference beginning position is a marker
+                         ;; to preserve it during further buffer
+                         ;; modifications.
+                         inlinep (copy-marker pos)) ref-table)))))
+      ;; 2. Find and remove the footnote section, if any.  Also
+      ;;    determine where footnotes shall be inserted (INS-POINT).
       (cond
-       ((org-mode-p)
-       (if (and org-footnote-section
-                (re-search-forward
-                 (concat "^\\*[ \t]+" (regexp-quote org-footnote-section)
-                         "[ \t]*$")
-                 nil t))
-           (if (or for-preprocessor (not org-footnote-section))
-               (replace-match "")
-             (org-back-to-heading t)
-             (forward-line 1)
-             (setq ins-point (point))
-             (delete-region (point) (org-end-of-subtree t)))
-         (goto-char (point-max))
-         (unless for-preprocessor
-           (when org-footnote-section
-             (or (bolp) (insert "\n"))
-             (insert "* " org-footnote-section "\n")
-             (setq ins-point (point))))))
-       (t
+       ((and org-footnote-section (derived-mode-p 'org-mode))
+       (goto-char (point-min))
        (if (re-search-forward
-            (concat "^"
-                    (regexp-quote org-footnote-tag-for-non-org-mode-files)
-                    "[ \t]*$")
-            nil t)
-           (replace-match ""))
+            (concat "^\\*[ \t]+" (regexp-quote org-footnote-section)
+                    "[ \t]*$") nil t)
+           (delete-region (match-beginning 0) (org-end-of-subtree t t)))
+       ;; A new footnote section is inserted by default at the end of
+       ;; the buffer.
        (goto-char (point-max))
-       (skip-chars-backward " \t\n\r")
-       (delete-region (point) (point-max))
-       (insert "\n\n" org-footnote-tag-for-non-org-mode-files "\n")
-       (setq ins-point (point))))
-
-      ;; Insert the footnotes again
-      (goto-char (or ins-point (point-max)))
-      (setq ref-table (reverse ref-table))
-      (when sort-only
-       ;; remove anonymous and inline footnotes from the list
-       (setq ref-table
-             (delq nil (mapcar
-                        (lambda (x) (and (car x)
-                                         (not (equal (car x) "fn:"))
-                                         (not (nth 3 x))
-                                         x))
-                        ref-table))))
-      ;; Make sure each footnote has a description, or an error message.
+       (skip-chars-backward " \r\t\n")
+       (forward-line)
+       (unless (bolp) (newline)))
+       ;; No footnote section set: Footnotes will be added at the end
+       ;; of the section containing their first reference.
+       ((derived-mode-p 'org-mode))
+       (t
+       ;; Remove any left-over tag in the buffer, if one is set up.
+       (when org-footnote-tag-for-non-org-mode-files
+         (let ((tag (concat "^" (regexp-quote
+                                 org-footnote-tag-for-non-org-mode-files)
+                            "[ \t]*$")))
+           (goto-char (point-min))
+           (while (re-search-forward tag nil t)
+             (replace-match "")
+             (delete-region (point) (progn (forward-line) (point))))))
+       ;; In Message mode, ensure footnotes are inserted before the
+       ;; signature.
+       (if (and (derived-mode-p 'message-mode)
+                (goto-char (point-max))
+                (re-search-backward message-signature-separator nil t))
+           (beginning-of-line)
+         (goto-char (point-max)))))
+      (setq ins-point (point-marker))
+      ;; 3. Clean-up REF-TABLE.
       (setq ref-table
-           (mapcar
-            (lambda (x)
-              (if (not (nth 2 x))
-                  (setcar (cddr x)
-                          (format "FOOTNOTE DEFINITION NOT FOUND: %s" (car x)))
-                (setcar (cddr x) (org-trim (nth 2 x))))
-              x)
-            ref-table))
-
-      (if (or (not (org-mode-p))     ; not an Org file
-             org-footnote-section   ; we do not use a footnote section
-             (not sort-only)        ; this is normalization
-             for-preprocessor)       ; the is the preprocessor
-         ;; Insert the footnotes together in one place
-         (progn
-           (setq def
-                 (mapconcat
+           (delq nil
+                 (mapcar
                   (lambda (x)
-                    (format "[%s] %s" (nth (if sort-only 0 1) x)
-                            (org-trim (nth 2 x))))
-                  ref-table "\n\n"))
-           (if ref-table (insert "\n" def "\n\n")))
-       ;; Insert each footnote near the first reference
-       ;; Happens only in Org files with no special footnote section,
-       ;; and only when doing sorting
-       (mapc 'org-insert-footnote-reference-near-definition
-             ref-table)))))
-
-(defun org-insert-footnote-reference-near-definition (entry)
-  "Find first reference of footnote ENTRY and insert the definition there.
-ENTRY is (fn-label num-mark definition)."
-  (when (car entry)
-    (goto-char (point-min))
-    (when (re-search-forward (format ".\\[%s[]:]" (regexp-quote (car entry)))
-                            nil t)
-      (org-footnote-goto-local-insertion-point)
-      (insert (format "\n\n[%s] %s" (car entry) (nth 2 entry))))))
+                    (cond
+                     ;; When only sorting, ignore inline footnotes.
+                     ;; Also clear position marker.
+                     ((and sort-only (nth 3 x))
+                      (set-marker (nth 4 x) nil) nil)
+                     ;; No definition available: provide one.
+                     ((not (nth 2 x))
+                      (append
+                       (list (car x) (nth 1 x)
+                             (format "DEFINITION NOT FOUND: %s" (car x)))
+                       (nthcdr 3 x)))
+                     (t x)))
+                  ref-table)))
+      (setq ref-table (nreverse ref-table))
+      ;; 4. Remove left-over definitions in the buffer.
+      (mapc (lambda (x)
+             (unless (nth 3 x) (org-footnote-delete-definitions (car x))))
+           ref-table)
+      ;; 5. Insert the footnotes again in the buffer, at the
+      ;;    appropriate spot.
+      (goto-char ins-point)
+      (cond
+       ;; No footnote: exit.
+       ((not ref-table))
+       ;; Cases when footnotes should be inserted in one place.
+       ((or (not (derived-mode-p 'org-mode)) org-footnote-section)
+       ;; Insert again the section title, if any.  Ensure that title,
+       ;; or the subsequent footnotes, will be separated by a blank
+       ;; lines from the rest of the document.  In an Org buffer,
+       ;; separate section with a blank line, unless explicitly
+       ;; stated in `org-blank-before-new-entry'.
+       (if (not (derived-mode-p 'org-mode))
+           (progn (skip-chars-backward " \t\n\r")
+                  (delete-region (point) ins-point)
+                  (unless (bolp) (newline))
+                  (when org-footnote-tag-for-non-org-mode-files
+                    (insert "\n" org-footnote-tag-for-non-org-mode-files "\n")))
+         (when (and (cdr (assq 'heading org-blank-before-new-entry))
+                    (zerop (save-excursion (org-back-over-empty-lines))))
+           (insert "\n"))
+         (insert "* " org-footnote-section "\n"))
+       (set-marker ins-point nil)
+       ;; Insert the footnotes, separated by a blank line.
+       (insert
+        (mapconcat
+         (lambda (x)
+           ;; Clean markers.
+           (set-marker (nth 4 x) nil)
+           (format "\n[%s] %s" (nth (if sort-only 0 1) x) (nth 2 x)))
+         ref-table "\n"))
+       (unless (eobp) (insert "\n\n")))
+       ;; Each footnote definition has to be inserted at the end of
+       ;; the section where its first reference belongs.
+       (t
+       (mapc
+        (lambda (x)
+          (let ((pos (nth 4 x)))
+            (goto-char pos)
+            ;; Clean marker.
+            (set-marker pos nil))
+          (org-footnote-goto-local-insertion-point)
+          (insert (format "\n[%s] %s\n"
+                          (if sort-only (car x) (nth 1 x))
+                          (nth 2 x))))
+        ref-table))))))
 
 (defun org-footnote-goto-local-insertion-point ()
   "Find insertion point for footnote, just before next outline heading."
@@ -509,44 +775,70 @@ ENTRY is (fn-label num-mark definition)."
   (beginning-of-line 0)
   (while (and (not (bobp)) (= (char-after) ?#))
     (beginning-of-line 0))
-  (if (looking-at "[ \t]*#\\+TBLFM:") (beginning-of-line 2))
+  (if (let ((case-fold-search t)) (looking-at "[ \t]*#\\+tblfm:")) (beginning-of-line 2))
   (end-of-line 1)
   (skip-chars-backward "\n\r\t ")
   (forward-line))
 
+(defun org-footnote-delete-references (label)
+  "Delete every reference to footnote LABEL.
+Return the number of footnotes removed."
+  (save-excursion
+    (goto-char (point-min))
+    (let (ref (nref 0))
+      (while (setq ref (org-footnote-get-next-reference label))
+       (goto-char (nth 1 ref))
+       (delete-region (nth 1 ref) (nth 2 ref))
+       (incf nref))
+      nref)))
+
+(defun org-footnote-delete-definitions (label)
+  "Delete every definition of the footnote LABEL.
+Return the number of footnotes removed."
+  (save-excursion
+    (goto-char (point-min))
+    (let ((def-re (concat "^\\[" (regexp-quote label) "\\]"))
+         (ndef 0))
+      (while (re-search-forward def-re nil t)
+       (let ((full-def (org-footnote-at-definition-p)))
+         (when full-def
+           ;; Remove the footnote, and all blank lines before it.
+           (goto-char (nth 1 full-def))
+           (skip-chars-backward " \r\t\n")
+           (unless (bolp) (forward-line))
+           (delete-region (point) (nth 2 full-def))
+           (incf ndef))))
+      ndef)))
+
 (defun org-footnote-delete (&optional label)
   "Delete the footnote at point.
 This will remove the definition (even multiple definitions if they exist)
-and all references of a footnote label."
+and all references of a footnote label.
+
+If LABEL is non-nil, delete that footnote instead."
   (catch 'done
-    (let (x label l beg def-re (nref 0) (ndef 0))
-      (unless label
-       (when (setq x (org-footnote-at-reference-p))
-         (setq label (nth 1 x))
-         (when (or (not label) (equal "fn:" label))
-           (delete-region (1+ (match-beginning 0)) (match-end 0))
-           (message "Anonymous footnote removed")
-           (throw 'done t)))
-       (when (and (not label) (setq x (org-footnote-at-definition-p)))
-         (setq label (nth 1 x)))
-       (unless label (error "Don't know which footnote to remove")))
-      (save-excursion
-       (save-restriction
-         (goto-char (point-min))
-         (while (re-search-forward org-footnote-re nil t)
-           (setq l (or (match-string 1) (match-string 2)))
-           (when (equal l label)
-             (delete-region (1+ (match-beginning 0)) (match-end 0))
-             (incf nref)))
-         (goto-char (point-min))
-         (setq def-re (concat "^\\[" (regexp-quote label) "\\]"))
-         (while (re-search-forward def-re nil t)
-           (setq beg (match-beginning 0))
-           (if (re-search-forward "^\\[\\|^[ \t]*$\\|^\\*+ " nil t)
-               (goto-char (match-beginning 0))
-             (goto-char (point-max)))
-           (delete-region beg (point))
-           (incf ndef))))
+    (let* ((nref 0) (ndef 0) x
+          ;; 1. Determine LABEL of footnote at point.
+          (label (cond
+                  ;; LABEL is provided as argument.
+                  (label)
+                  ;; Footnote reference at point.  If the footnote is
+                  ;; anonymous, delete it and exit instead.
+                  ((setq x (org-footnote-at-reference-p))
+                   (or (car x)
+                       (progn
+                         (delete-region (nth 1 x) (nth 2 x))
+                         (message "Anonymous footnote removed")
+                         (throw 'done t))))
+                  ;; Footnote definition at point.
+                  ((setq x (org-footnote-at-definition-p))
+                   (car x))
+                  (t (error "Don't know which footnote to remove")))))
+      ;; 2. Now that LABEL is non-nil, find every reference and every
+      ;; definition, and delete them.
+      (setq nref (org-footnote-delete-references label)
+           ndef (org-footnote-delete-definitions label))
+      ;; 3. Verify consistency of footnotes and notify user.
       (org-footnote-auto-adjust-maybe)
       (message "%d definition(s) of and %d reference(s) of footnote %s removed"
               ndef nref label))))
@@ -554,27 +846,28 @@ and all references of a footnote label."
 (defun org-footnote-renumber-fn:N ()
   "Renumber the simple footnotes like fn:17 into a sequence in the document."
   (interactive)
-  (let (map i (n 0))
-    (save-excursion
-      (save-restriction
-       (widen)
-       (goto-char (point-min))
-       (while (re-search-forward "\\[fn:\\([0-9]+\\)[]:]" nil t)
-         (setq i (string-to-number (match-string 1)))
-         (when (and (string-match "\\S-" (buffer-substring
-                                          (point-at-bol) (match-beginning 0)))
-                    (not (assq i map)))
-           (push (cons i (number-to-string (incf n))) map)))
-       (goto-char (point-min))
-       (while (re-search-forward "\\(\\[fn:\\)\\([0-9]+\\)\\([]:]\\)" nil t)
-         (replace-match (concat "\\1" (cdr (assq (string-to-number (match-string 2)) map)) "\\3")))))))
+  (let (map (n 0))
+    (org-with-wide-buffer
+     (goto-char (point-min))
+     (while (re-search-forward "\\[fn:\\([0-9]+\\)[]:]" nil t)
+       (save-excursion
+        (goto-char (match-beginning 0))
+        ;; Ensure match is a footnote reference or definition.
+        (when (save-match-data (if (bolp)
+                                   (org-footnote-at-definition-p)
+                                 (org-footnote-at-reference-p)))
+          (let ((new-val (or (cdr (assoc (match-string 1) map))
+                             (number-to-string (incf n)))))
+            (unless (assoc (match-string 1) map)
+              (push (cons (match-string 1) new-val) map))
+            (replace-match new-val nil nil nil 1))))))))
 
 (defun org-footnote-auto-adjust-maybe ()
   "Renumber and/or sort footnotes according to user settings."
   (when (memq org-footnote-auto-adjust '(t renumber))
     (org-footnote-renumber-fn:N))
   (when (memq org-footnote-auto-adjust '(t sort))
-    (let ((label (nth 1 (org-footnote-at-definition-p))))
+    (let ((label (car (org-footnote-at-definition-p))))
       (org-footnote-normalize 'sort)
       (when label
        (goto-char (point-min))
@@ -585,5 +878,8 @@ and all references of a footnote label."
 
 (provide 'org-footnote)
 
+;; Local variables:
+;; generated-autoload-file: "org-loaddefs.el"
+;; End:
 
 ;;; org-footnote.el ends here