emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/lisp/textmodes/bibtex.el [lexbind]


From: Miles Bader
Subject: [Emacs-diffs] Changes to emacs/lisp/textmodes/bibtex.el [lexbind]
Date: Wed, 15 Sep 2004 20:33:09 -0400

Index: emacs/lisp/textmodes/bibtex.el
diff -c emacs/lisp/textmodes/bibtex.el:1.69.2.6 
emacs/lisp/textmodes/bibtex.el:1.69.2.7
*** emacs/lisp/textmodes/bibtex.el:1.69.2.6     Tue Jul  6 09:39:54 2004
--- emacs/lisp/textmodes/bibtex.el      Thu Sep 16 00:14:56 2004
***************
*** 1,6 ****
  ;;; bibtex.el --- BibTeX mode for GNU Emacs
  
! ;; Copyright (C) 1992,94,95,96,97,98,1999,2003,2004
  ;;           Free Software Foundation, Inc.
  
  ;; Author: Stefan Schoef <address@hidden>
--- 1,6 ----
  ;;; bibtex.el --- BibTeX mode for GNU Emacs
  
! ;; Copyright (C) 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2004
  ;;           Free Software Foundation, Inc.
  
  ;; Author: Stefan Schoef <address@hidden>
***************
*** 61,73 ****
    :type 'hook)
  
  (defcustom bibtex-field-delimiters 'braces
!   "*Type of field delimiters. Allowed values are `braces' or `double-quotes'."
    :group 'bibtex
    :type '(choice (const braces)
                   (const double-quotes)))
  
  (defcustom bibtex-entry-delimiters 'braces
!   "*Type of entry delimiters. Allowed values are `braces' or `parentheses'."
    :group 'bibtex
    :type '(choice (const braces)
                   (const parentheses)))
--- 61,73 ----
    :type 'hook)
  
  (defcustom bibtex-field-delimiters 'braces
!   "*Type of field delimiters.  Allowed values are `braces' or 
`double-quotes'."
    :group 'bibtex
    :type '(choice (const braces)
                   (const double-quotes)))
  
  (defcustom bibtex-entry-delimiters 'braces
!   "*Type of entry delimiters.  Allowed values are `braces' or `parentheses'."
    :group 'bibtex
    :type '(choice (const braces)
                   (const parentheses)))
***************
*** 154,163 ****
  Allowed non-nil values are:
  plain        All entries are sorted alphabetically.
  crossref     All entries are sorted alphabetically unless an entry has a
!              crossref field. These crossrefed entries are placed in
               alphabetical order immediately preceding the main entry.
  entry-class  The entries are divided into classes according to their
!              entry name, see `bibtex-sort-entry-class'. Within each class
               the entries are sorted alphabetically.
  See also `bibtex-sort-ignore-string-entries'."
    :group 'bibtex
--- 154,163 ----
  Allowed non-nil values are:
  plain        All entries are sorted alphabetically.
  crossref     All entries are sorted alphabetically unless an entry has a
!              crossref field.  These crossrefed entries are placed in
               alphabetical order immediately preceding the main entry.
  entry-class  The entries are divided into classes according to their
!              entry name, see `bibtex-sort-entry-class'.  Within each class
               the entries are sorted alphabetically.
  See also `bibtex-sort-ignore-string-entries'."
    :group 'bibtex
***************
*** 172,179 ****
      ("Book" "Proceedings"))
    "*List of classes of BibTeX entry names, used for sorting entries.
  If value of `bibtex-maintain-sorted-entries' is `entry-class'
! entries are ordered according to the classes they belong to. Each
! class contains a list of entry names. An entry `catch-all' applies
  to all entries not explicitely mentioned.")
  
  (defcustom bibtex-sort-ignore-string-entries t
--- 172,179 ----
      ("Book" "Proceedings"))
    "*List of classes of BibTeX entry names, used for sorting entries.
  If value of `bibtex-maintain-sorted-entries' is `entry-class'
! entries are ordered according to the classes they belong to.  Each
! class contains a list of entry names.  An entry `catch-all' applies
  to all entries not explicitely mentioned.")
  
  (defcustom bibtex-sort-ignore-string-entries t
***************
*** 640,646 ****
  
  (defcustom bibtex-autokey-titleword-ignore
    '("A" "An" "On" "The" "Eine?" "Der" "Die" "Das"
!     "[^A-Z].*" ".*[^a-zA-Z0-9].*")
    "*Determines words from the title that are not to be used in the key.
  Each item of the list is a regexp.  If a word of the title matchs a
  regexp from that list, it is not included in the title part of the key.
--- 640,646 ----
  
  (defcustom bibtex-autokey-titleword-ignore
    '("A" "An" "On" "The" "Eine?" "Der" "Die" "Das"
!     "[^A-Z].*" ".*[^A-Z0-9].*")
    "*Determines words from the title that are not to be used in the key.
  Each item of the list is a regexp.  If a word of the title matchs a
  regexp from that list, it is not included in the title part of the key.
***************
*** 762,772 ****
    "Automatically fill fields if possible for those BibTeX entry types."
    :type '(repeat string))
  
! (defcustom bibtex-complete-key-cleanup nil
!   "*Function called by `bibtex-complete' after insertion of a key fragment."
!   :group 'bibtex-autokey
!   :type '(choice (const :tag "None" nil)
!                  (function :tag "Cleanup function")))
  
  ;; bibtex-font-lock-keywords is a user option as well, but since the
  ;; patterns used to define this variable are defined in a later
--- 762,808 ----
    "Automatically fill fields if possible for those BibTeX entry types."
    :type '(repeat string))
  
! (defcustom bibtex-generate-url-list
!   '((("url" . ".*:.*"))
!     ;; Example of a complex setup.
!     (("journal" . "\\<\\(PR[ABCDEL]?\\|RMP\\)\\>")
!      "http://publish.aps.org/abstract/";
!      ("journal" ".*" downcase)
!      "/v"
!      ("volume" ".*" 0)
!      "/p"
!      ("pages" "\\`\\([0-9]+\\)" 1)))
!   "List of schemes for generating the URL of a BibTeX entry.
! These schemes are used by `bibtex-url'.
! 
! Each scheme is of the form ((FIELD . REGEXP) STEP...).
! 
! FIELD is a field name as returned by `bibtex-parse-entry'.
! REGEXP is matched against the text of FIELD.  If the match succeed, then
! this scheme will be used.  If no STEPS are specified the matched text is used
! as the URL, otherwise the URL is built by concatenating the STEPS.
! 
! A STEP can be a string or a list (FIELD REGEXP REPLACE) in which case
! the text of FIELD is matched against REGEXP, and is replaced with REPLACE.
! REPLACE can be a string, or a number (which selects the corresponding 
submatch)
! or a function called with the field's text as argument and with the
! `match-data' properly set.
! 
! Case is always ignored.  Always remove the field delimiters."
!   :group 'bibtex
!   :type '(repeat
!           (list :tag "Scheme"
!                 (cons :tag "Matcher" :extra-offset 4
!                       (string :tag "BibTeX field")
!                     (regexp :tag "Regexp"))
!                 (repeat :tag "Steps to generate URL" :inline t
!                         (choice
!                          (string :tag "Literal text")
!                          (list (string :tag "BibTeX field")
!                              (regexp :tag "Regexp")
!                                (choice (string :tag "Replacement")
!                                      (integer :tag "Sub-match")
!                                      (function :tag "Filter"))))))))
  
  ;; bibtex-font-lock-keywords is a user option as well, but since the
  ;; patterns used to define this variable are defined in a later
***************
*** 801,806 ****
--- 837,843 ----
      (define-key km "\C-c}" 'bibtex-remove-delimiters)
      (define-key km "\C-c\C-c" 'bibtex-clean-entry)
      (define-key km "\C-c\C-q" 'bibtex-fill-entry)
+     (define-key km "\C-c\C-s" 'bibtex-find-entry)
      (define-key km "\C-c?" 'bibtex-print-help-message)
      (define-key km "\C-c\C-p" 'bibtex-pop-previous)
      (define-key km "\C-c\C-n" 'bibtex-pop-next)
***************
*** 821,826 ****
--- 858,864 ----
      (define-key km "\C-c\C-b" 'bibtex-entry)
      (define-key km "\C-c\C-rn" 'bibtex-narrow-to-entry)
      (define-key km "\C-c\C-rw" 'widen)
+     (define-key km "\C-c\C-l" 'bibtex-url)
      (define-key km "\C-c\C-o" 'bibtex-remove-OPT-or-ALT)
      (define-key km "\C-c\C-e\C-i" 'bibtex-InProceedings)
      (define-key km "\C-c\C-ei" 'bibtex-InCollection)
***************
*** 854,874 ****
      ("Moving in BibTeX Buffer"
       ["Find Entry" bibtex-find-entry t]
       ["Find Crossref Entry" bibtex-find-crossref t])
-     ("Operating on Current Entry"
-      ["Fill Entry" bibtex-fill-entry t]
-      ["Clean Entry" bibtex-clean-entry t]
       "--"
-      ["Kill Entry" bibtex-kill-entry t]
-      ["Copy Entry to Kill Ring" bibtex-copy-entry-as-kill t]
-      ["Paste Most Recently Killed Entry" bibtex-yank t]
-      ["Paste Previously Killed Entry" bibtex-yank-pop t]
-      "--"
-      ["Ispell Entry" bibtex-ispell-entry t]
-      ["Ispell Entry Abstract" bibtex-ispell-abstract t]
-      ["Narrow to Entry" bibtex-narrow-to-entry t]
-      "--"
-      ["View Cite Locations (RefTeX)" reftex-view-crossref-from-bibtex
-       (fboundp 'reftex-view-crossref-from-bibtex)])
      ("Operating on Current Field"
       ["Fill Field" fill-paragraph t]
       ["Remove Delimiters" bibtex-remove-delimiters t]
--- 892,898 ----
***************
*** 888,899 ****
       ["String or Key Complete" bibtex-complete t]
       "--"
       ["Help about Current Field" bibtex-print-help-message t])
      ("Operating on Buffer or Region"
       ["Validate Entries" bibtex-validate t]
       ["Sort Entries" bibtex-sort-buffer t]
       ["Reformat Entries" bibtex-reformat t]
!      ["Count Entries" bibtex-count-entries t])
!     ("Miscellaneous"
       ["Convert Alien Buffer" bibtex-convert-alien t])))
  
  (easy-menu-define
--- 912,939 ----
       ["String or Key Complete" bibtex-complete t]
       "--"
       ["Help about Current Field" bibtex-print-help-message t])
+     ("Operating on Current Entry"
+      ["Fill Entry" bibtex-fill-entry t]
+      ["Clean Entry" bibtex-clean-entry t]
+      ["Update Entry" bibtex-entry-update t]
+      "--"
+      ["Kill Entry" bibtex-kill-entry t]
+      ["Copy Entry to Kill Ring" bibtex-copy-entry-as-kill t]
+      ["Paste Most Recently Killed Entry" bibtex-yank t]
+      ["Paste Previously Killed Entry" bibtex-yank-pop t]
+      "--"
+      ["Ispell Entry" bibtex-ispell-entry t]
+      ["Ispell Entry Abstract" bibtex-ispell-abstract t]
+      ["Narrow to Entry" bibtex-narrow-to-entry t]
+      "--"
+      ["View Cite Locations (RefTeX)" reftex-view-crossref-from-bibtex
+       (fboundp 'reftex-view-crossref-from-bibtex)])
      ("Operating on Buffer or Region"
       ["Validate Entries" bibtex-validate t]
       ["Sort Entries" bibtex-sort-buffer t]
       ["Reformat Entries" bibtex-reformat t]
!      ["Count Entries" bibtex-count-entries t]
!      "--"
       ["Convert Alien Buffer" bibtex-convert-alien t])))
  
  (easy-menu-define
***************
*** 915,920 ****
--- 955,967 ----
          ["String" bibtex-String t]
          ["Preamble" bibtex-Preamble t]))
  
+ (defvar bibtex-url-map
+   (let ((km (make-sparse-keymap)))
+     (define-key km [(mouse-2)] 'bibtex-url)
+     km)
+   "Local keymap for clickable URLs.")
+ (fset 'bibtex-url-map bibtex-url-map)
+     
  
  ;; Internal Variables
  
***************
*** 954,961 ****
  (make-variable-buffer-local 'bibtex-reference-keys)
  
  (defvar bibtex-buffer-last-parsed-tick nil
!   "Last value returned by `buffer-modified-tick' when buffer
! was parsed for keys the last time.")
  
  (defvar bibtex-parse-idle-timer nil
    "Stores if timer is already installed.")
--- 1001,1007 ----
  (make-variable-buffer-local 'bibtex-reference-keys)
  
  (defvar bibtex-buffer-last-parsed-tick nil
!   "Value of `buffer-modified-tick' last time buffer was parsed for keys.")
  
  (defvar bibtex-parse-idle-timer nil
    "Stores if timer is already installed.")
***************
*** 1040,1080 ****
  (defconst bibtex-empty-field-re "\"\"\\|{}"
    "Regexp matching an empty field.")
  
- (defconst bibtex-quoted-string-re
-   (concat "\""
-           "\\("
-           "[^\"\\]"          ; anything but quote or backslash
-           "\\|"
-           "\\("
-           "\\\\\\(.\\|\n\\)" ; any backslash quoted character
-           "\\)"
-           "\\)*"
-           "\"")
-   "Regexp matching a field string enclosed by quotes.")
- 
  (defconst bibtex-font-lock-syntactic-keywords
    `((,(concat "^[ \t]*\\(" (substring bibtex-comment-start 0 1) "\\)"
                (substring bibtex-comment-start 1) "\\>")
       1 '(11))))
  
  (defvar bibtex-font-lock-keywords
!   (list
!    ;; entry type and reference key
!    (list bibtex-entry-maybe-empty-head
!          (list bibtex-type-in-head 'font-lock-function-name-face)
!          (list bibtex-key-in-head 'font-lock-constant-face nil t))
!    ;; optional field names (treated as comments)
!    (list
!     (concat "^[ \t]*\\(OPT" bibtex-field-name "\\)[ \t]*=")
!     1 'font-lock-comment-face)
!    ;; field names
!    (list (concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=")
!          1 'font-lock-variable-name-face))
    "*Default expressions to highlight in BibTeX mode.")
  
  (defvar bibtex-field-name-for-parsing nil
!   "Temporary variable storing the name string to be parsed by the callback
! function `bibtex-parse-field-name'.")
  
  (defvar bibtex-sort-entry-class-alist
    (let ((i -1) alist)
--- 1086,1120 ----
  (defconst bibtex-empty-field-re "\"\"\\|{}"
    "Regexp matching an empty field.")
  
  (defconst bibtex-font-lock-syntactic-keywords
    `((,(concat "^[ \t]*\\(" (substring bibtex-comment-start 0 1) "\\)"
                (substring bibtex-comment-start 1) "\\>")
       1 '(11))))
  
  (defvar bibtex-font-lock-keywords
!   ;; entry type and reference key
!   `((,bibtex-entry-maybe-empty-head
!      (,bibtex-type-in-head font-lock-function-name-face)
!      (,bibtex-key-in-head font-lock-constant-face nil t))
!     ;; optional field names (treated as comments)
!     (,(concat "^[ \t]*\\(OPT" bibtex-field-name "\\)[ \t]*=")
!      1 font-lock-comment-face)
!     ;; field names
!     (,(concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=")
!      1 font-lock-variable-name-face)
!     ;; url
!     (bibtex-font-lock-url 0 '(face nil mouse-face highlight
!                                    keymap bibtex-url-map)))
    "*Default expressions to highlight in BibTeX mode.")
  
+ (defvar bibtex-font-lock-url-regexp
+   (concat "\\<" (regexp-opt (mapcar 'caar bibtex-generate-url-list) t)
+           "\\>[ \t]*=[ \t]*")
+   "Regexp for `bibtex-font-lock-url'.")
+ 
  (defvar bibtex-field-name-for-parsing nil
!   "Regexp of field name to be parsed by function `bibtex-parse-field-name'.
! Passed by dynamic scoping.")
  
  (defvar bibtex-sort-entry-class-alist
    (let ((i -1) alist)
***************
*** 1083,1123 ****
        (dolist (entry class)
          ;; all entry names should be downcase (for ease of comparison)
          (push (cons (if (stringp entry) (downcase entry) entry) i) alist))))
!   "Alist for the classes of the entry types if the value of
! `bibtex-maintain-sorted-entries' is `entry-class'.")
  
  
  ;; Special support taking care of variants
  (defvar zmacs-regions)
! (if (boundp 'mark-active)
!     (defun bibtex-mark-active ()
        ;; In Emacs mark-active indicates if mark is active.
!       mark-active)
!   (defun bibtex-mark-active ()
      ;; In XEmacs (mark) returns nil when not active.
!     (if zmacs-regions (mark) (mark t))))
  
! (if (fboundp 'run-with-idle-timer)
!     ;; timer.el is distributed with Emacs
!     (fset 'bibtex-run-with-idle-timer 'run-with-idle-timer)
!   ;; timer.el is not distributed with XEmacs
!   ;; Notice that this does not (yet) pass the arguments, but they
!   ;; are not used (yet) in bibtex.el. Fix if needed.
!   (defun bibtex-run-with-idle-timer (secs repeat function &rest args)
!     (start-itimer "bibtex" function secs (if repeat secs nil) t)))
  
  
  ;; Support for hideshow minor mode
  (defun bibtex-hs-forward-sexp (arg)
!   "Replacement for `forward-sexp' to be used by `hs-minor-mode'."
!   (if (< arg 0)
!       (backward-sexp 1)
!     (if (looking-at "@\\S(*\\s(")
!         (progn
!           (goto-char (match-end 0))
!           (forward-char -1)
!           (forward-sexp 1))
!       (forward-sexp 1))))
  
  (add-to-list
   'hs-special-modes-alist
--- 1123,1160 ----
        (dolist (entry class)
          ;; all entry names should be downcase (for ease of comparison)
          (push (cons (if (stringp entry) (downcase entry) entry) i) alist))))
!   "Alist mapping entry types to their sorting index.
! Auto-generated from `bibtex-sort-entry-class'.
! Used when `bibtex-maintain-sorted-entries' is `entry-class'.")
  
  
  ;; Special support taking care of variants
  (defvar zmacs-regions)
! (defalias 'bibtex-mark-active
!   (if (boundp 'mark-active)
        ;; In Emacs mark-active indicates if mark is active.
!       (lambda () mark-active)
      ;; In XEmacs (mark) returns nil when not active.
!     (lambda () (if zmacs-regions (mark) (mark t)))))
  
! (defalias 'bibtex-run-with-idle-timer
!   (if (fboundp 'run-with-idle-timer)
!       ;; timer.el is distributed with Emacs
!       'run-with-idle-timer
!     ;; timer.el is not distributed with XEmacs
!     ;; Notice that this does not (yet) pass the arguments, but they
!     ;; are not used (yet) in bibtex.el. Fix if needed.
!     (lambda (secs repeat function &rest args)
!       (start-itimer "bibtex" function secs (if repeat secs nil) t))))
  
  
  ;; Support for hideshow minor mode
  (defun bibtex-hs-forward-sexp (arg)
!   "Replacement for `forward-sexp' to be used by `hs-minor-mode'.
! ARG is ignored."
!   (if (looking-at "@\\S(*\\s(")
!     (goto-char (1- (match-end 0))))
!   (forward-sexp 1))
  
  (add-to-list
   'hs-special-modes-alist
***************
*** 1144,1150 ****
    "Parse the field name stored in `bibtex-field-name-for-parsing'.
  If the field name is found, return a triple consisting of the position of the
  very first character of the match, the actual starting position of the name
! part and end position of the match. Move point to end of field name.
  If `bibtex-autoadd-commas' is non-nil add missing comma at end of preceeding
  BibTeX field as necessary."
    (cond ((looking-at ",[ \t\n]*")
--- 1181,1187 ----
    "Parse the field name stored in `bibtex-field-name-for-parsing'.
  If the field name is found, return a triple consisting of the position of the
  very first character of the match, the actual starting position of the name
! part and end position of the match.  Move point to end of field name.
  If `bibtex-autoadd-commas' is non-nil add missing comma at end of preceeding
  BibTeX field as necessary."
    (cond ((looking-at ",[ \t\n]*")
***************
*** 1206,1212 ****
  The text part is either a string, or an empty string, or a constant followed
  by one or more <# (string|constant)> pairs.  If a syntactically correct text
  is found, a pair containing the start and end position of the text is
! returned, nil otherwise. Move point to end of field text."
    (let ((starting-point (point))
          end-point failure boundaries)
      (while (not (or end-point failure))
--- 1243,1249 ----
  The text part is either a string, or an empty string, or a constant followed
  by one or more <# (string|constant)> pairs.  If a syntactically correct text
  is found, a pair containing the start and end position of the text is
! returned, nil otherwise.  Move point to end of field text."
    (let ((starting-point (point))
          end-point failure boundaries)
      (while (not (or end-point failure))
***************
*** 1215,1223 ****
              ((setq boundaries (bibtex-parse-field-string))
               (goto-char (cdr boundaries)))
              ((setq failure t)))
!       (if (not (looking-at "[ \t\n]*#[ \t\n]*"))
!           (setq end-point (point))
!         (goto-char (match-end 0))))
      (if (and (not failure)
               end-point)
          (cons starting-point end-point))))
--- 1252,1260 ----
              ((setq boundaries (bibtex-parse-field-string))
               (goto-char (cdr boundaries)))
              ((setq failure t)))
!       (if (looking-at "[ \t\n]*#[ \t\n]*")
!           (goto-char (match-end 0))
!         (setq end-point (point))))
      (if (and (not failure)
               end-point)
          (cons starting-point end-point))))
***************
*** 1234,1241 ****
    "Search forward to find a field of name NAME.
  If a syntactically correct field is found, a pair containing the boundaries of
  the name and text parts of the field is returned.  The search is limited by
! optional arg BOUND. If BOUND is t the search is limited by the end of the 
current
! entry. Do not move point."
    (save-match-data
      (save-excursion
        (unless (integer-or-marker-p bound)
--- 1271,1278 ----
    "Search forward to find a field of name NAME.
  If a syntactically correct field is found, a pair containing the boundaries of
  the name and text parts of the field is returned.  The search is limited by
! optional arg BOUND.  If BOUND is t the search is limited by the end of the
! current entry.  Do not move point."
    (save-match-data
      (save-excursion
        (unless (integer-or-marker-p bound)
***************
*** 1261,1268 ****
    "Search backward to find a field of name NAME.
  If a syntactically correct field is found, a pair containing the boundaries of
  the name and text parts of the field is returned.  The search is limited by
! optional arg BOUND. If BOUND is t the search is limited by the beginning of 
the
! current entry. Do not move point."
    (save-match-data
      (save-excursion
        (unless (integer-or-marker-p bound)
--- 1298,1305 ----
    "Search backward to find a field of name NAME.
  If a syntactically correct field is found, a pair containing the boundaries of
  the name and text parts of the field is returned.  The search is limited by
! optional arg BOUND.  If BOUND is t the search is limited by the beginning of 
the
! current entry.  Do not move point."
    (save-match-data
      (save-excursion
        (unless (integer-or-marker-p bound)
***************
*** 1294,1303 ****
  (defsubst bibtex-end-of-text-in-field (bounds)
    (cddr bounds))
  
! (defun bibtex-name-in-field (bounds)
!   "Get content of name in BibTeX field defined via BOUNDS."
!   (buffer-substring-no-properties (nth 1 (car bounds))
!                                   (nth 2 (car bounds))))
  
  (defun bibtex-text-in-field-bounds (bounds &optional remove-delim)
    "Get content of text in BibTeX field defined via BOUNDS.
--- 1331,1345 ----
  (defsubst bibtex-end-of-text-in-field (bounds)
    (cddr bounds))
  
! (defun bibtex-name-in-field (bounds &optional remove-opt-alt)
!   "Get content of name in BibTeX field defined via BOUNDS.
! If optional arg REMOVE-OPT-ALT is non-nil remove \"OPT\" and \"ALT\"."
!   (let ((name (buffer-substring-no-properties (nth 1 (car bounds))
!                                               (nth 2 (car bounds)))))
!     (if (and remove-opt-alt
!              (string-match "\\`\\(OPT\\|ALT\\)" name))
!         (substring name 3)
!       name)))
  
  (defun bibtex-text-in-field-bounds (bounds &optional remove-delim)
    "Get content of text in BibTeX field defined via BOUNDS.
***************
*** 1311,1317 ****
        content)))
  
  (defun bibtex-text-in-field (field &optional follow-crossref)
!   "Get content of field FIELD of current BibTeX entry. Return nil if not 
found.
  If optional arg FOLLOW-CROSSREF is non-nil, follow crossref."
    (save-excursion
      (save-restriction
--- 1353,1359 ----
        content)))
  
  (defun bibtex-text-in-field (field &optional follow-crossref)
!   "Get content of field FIELD of current BibTeX entry.  Return nil if not 
found.
  If optional arg FOLLOW-CROSSREF is non-nil, follow crossref."
    (save-excursion
      (save-restriction
***************
*** 1351,1357 ****
    "Parse the postfix part of a BibTeX string entry, including the text.
  If the string postfix is found, return a triple consisting of the position of
  the actual starting and ending position of the text and the very last
! character of the string entry. Move point past BibTeX string entry."
    (let* ((case-fold-search t)
           (bounds (bibtex-parse-field-text)))
      (when bounds
--- 1393,1399 ----
    "Parse the postfix part of a BibTeX string entry, including the text.
  If the string postfix is found, return a triple consisting of the position of
  the actual starting and ending position of the text and the very last
! character of the string entry.  Move point past BibTeX string entry."
    (let* ((case-fold-search t)
           (bounds (bibtex-parse-field-text)))
      (when bounds
***************
*** 1373,1379 ****
  (defun bibtex-search-forward-string ()
    "Search forward to find a BibTeX string entry.
  If a syntactically correct entry is found, a pair containing the boundaries of
! the reference key and text parts of the string is returned. Do not move 
point."
    (save-excursion
      (save-match-data
        (let ((case-fold-search t)
--- 1415,1421 ----
  (defun bibtex-search-forward-string ()
    "Search forward to find a BibTeX string entry.
  If a syntactically correct entry is found, a pair containing the boundaries of
! the reference key and text parts of the string is returned.  Do not move 
point."
    (save-excursion
      (save-match-data
        (let ((case-fold-search t)
***************
*** 1389,1395 ****
  (defun bibtex-search-backward-string ()
    "Search backward to find a BibTeX string entry.
  If a syntactically correct entry is found, a pair containing the boundaries of
! the reference key and text parts of the field is returned. Do not move point."
    (save-excursion
      (save-match-data
        (let ((case-fold-search t)
--- 1431,1437 ----
  (defun bibtex-search-backward-string ()
    "Search backward to find a BibTeX string entry.
  If a syntactically correct entry is found, a pair containing the boundaries of
! the reference key and text parts of the field is returned.  Do not move 
point."
    (save-excursion
      (save-match-data
        (let ((case-fold-search t)
***************
*** 1430,1436 ****
                                    (match-end bibtex-type-in-head)))
  
  (defun bibtex-key-in-head (&optional empty)
!   "Extract BibTeX key in head. Return optional arg EMPTY if key is empty."
    (if (match-beginning bibtex-key-in-head)
        (buffer-substring-no-properties (match-beginning bibtex-key-in-head)
                                        (match-end bibtex-key-in-head))
--- 1472,1478 ----
                                    (match-end bibtex-type-in-head)))
  
  (defun bibtex-key-in-head (&optional empty)
!   "Extract BibTeX key in head.  Return optional arg EMPTY if key is empty."
    (if (match-beginning bibtex-key-in-head)
        (buffer-substring-no-properties (match-beginning bibtex-key-in-head)
                                        (match-end bibtex-key-in-head))
***************
*** 1438,1443 ****
--- 1480,1489 ----
  
  ;; Helper Functions
  
+ (defsubst bibtex-string= (str1 str2)
+   "Return t if STR1 and STR2 are equal, ignoring case."
+   (eq t (compare-strings str1 0 nil str2 0 nil t)))
+ 
  (defun bibtex-delete-whitespace ()
    "Delete all whitespace starting at point."
    (if (looking-at "[ \t\n]+")
***************
*** 1448,1469 ****
    (+ (count-lines 1 (point))
       (if (equal (current-column) 0) 1 0)))
  
- (defun bibtex-member-of-regexp (string list)
-   "Return non-nil if STRING is exactly matched by an element of LIST.
- The value is actually the tail of LIST whose car matches STRING."
-   (let (case-fold-search)
-     (while (and list
-                 (not (string-match (concat "\\`\\(?:" (car list) "\\)\\'") 
string)))
-       (setq list (cdr list)))
-     list))
- 
  (defun bibtex-skip-to-valid-entry (&optional backward)
!   "Unless at beginning of a valid BibTeX entry, move point to beginning of the
! next valid one. With optional argument BACKWARD non-nil, move backward to
! beginning of previous valid one. A valid entry is a syntactical correct one
  with type contained in `bibtex-entry-field-alist' or, if
  `bibtex-sort-ignore-string-entries' is nil, a syntactical correct string
! entry. Return buffer position of beginning and ending of entry if a valid
  entry is found, nil otherwise."
    (interactive "P")
    (let ((case-fold-search t)
--- 1494,1507 ----
    (+ (count-lines 1 (point))
       (if (equal (current-column) 0) 1 0)))
  
  (defun bibtex-skip-to-valid-entry (&optional backward)
!   "Move point to beginning of the next valid BibTeX entry.
! Do not move if we are already at beginning of a valid BibTeX entry.
! With optional argument BACKWARD non-nil, move backward to
! beginning of previous valid one.  A valid entry is a syntactical correct one
  with type contained in `bibtex-entry-field-alist' or, if
  `bibtex-sort-ignore-string-entries' is nil, a syntactical correct string
! entry.  Return buffer position of beginning and ending of entry if a valid
  entry is found, nil otherwise."
    (interactive "P")
    (let ((case-fold-search t)
***************
*** 1488,1496 ****
  
  (defun bibtex-map-entries (fun)
    "Call FUN for each BibTeX entry starting with the current.
! Do this to the end of the file. FUN is called with three arguments, the key of
  the entry and the buffer positions (marker) of beginning and end of entry.
! Point is inside the entry. If `bibtex-sort-ignore-string-entries' is non-nil,
  FUN will not be called for @String entries."
    (let ((case-fold-search t))
      (bibtex-beginning-of-entry)
--- 1526,1534 ----
  
  (defun bibtex-map-entries (fun)
    "Call FUN for each BibTeX entry starting with the current.
! Do this to the end of the file.  FUN is called with three arguments, the key 
of
  the entry and the buffer positions (marker) of beginning and end of entry.
! Point is inside the entry.  If `bibtex-sort-ignore-string-entries' is non-nil,
  FUN will not be called for @String entries."
    (let ((case-fold-search t))
      (bibtex-beginning-of-entry)
***************
*** 1501,1507 ****
              (end (copy-marker (save-excursion (bibtex-end-of-entry)))))
          (save-excursion
            (if (or (and (not bibtex-sort-ignore-string-entries)
!                        (string-equal "string" (downcase entry-type)))
                    (assoc-string entry-type bibtex-entry-field-alist t))
                (funcall fun key beg end)))
          (goto-char end)))))
--- 1539,1545 ----
              (end (copy-marker (save-excursion (bibtex-end-of-entry)))))
          (save-excursion
            (if (or (and (not bibtex-sort-ignore-string-entries)
!                        (bibtex-string= entry-type "string"))
                    (assoc-string entry-type bibtex-entry-field-alist t))
                (funcall fun key beg end)))
          (goto-char end)))))
***************
*** 1556,1563 ****
  
  (defun bibtex-search-entry (empty-head &optional bound noerror backward)
    "Search for a BibTeX entry (maybe without reference key if EMPTY-HEAD is t).
! BOUND and NOERROR are exactly as in `re-search-forward'. If BACKWARD
! is non-nil, search is done in reverse direction. Point is moved past the
  closing delimiter (at the beginning of entry if BACKWARD is non-nil).
  Return a cons pair with buffer positions of beginning and end of entry.
  After call to this function MATCH-BEGINNING and MATCH-END functions
--- 1594,1601 ----
  
  (defun bibtex-search-entry (empty-head &optional bound noerror backward)
    "Search for a BibTeX entry (maybe without reference key if EMPTY-HEAD is t).
! BOUND and NOERROR are exactly as in `re-search-forward'.  If BACKWARD
! is non-nil, search is done in reverse direction.  Point is moved past the
  closing delimiter (at the beginning of entry if BACKWARD is non-nil).
  Return a cons pair with buffer positions of beginning and end of entry.
  After call to this function MATCH-BEGINNING and MATCH-END functions
***************
*** 1575,1581 ****
            (if found
                (progn (goto-char (match-beginning 0))
                       found)
!             (cond ((equal noerror nil)
                     ;; yell
                     (error "Backward search of BibTeX entry failed"))
                    ((equal noerror t)
--- 1613,1619 ----
            (if found
                (progn (goto-char (match-beginning 0))
                       found)
!             (cond ((not noerror)
                     ;; yell
                     (error "Backward search of BibTeX entry failed"))
                    ((equal noerror t)
***************
*** 1660,1666 ****
      (skip-chars-forward " \t\n")))
  
  (defun bibtex-beginning-of-first-entry ()
!   "Go to the beginning of the first BibTeX entry in buffer. Return point."
    (goto-char (point-min))
    (if (re-search-forward "^[ \t]*@" nil 'move)
        (beginning-of-line))
--- 1698,1704 ----
      (skip-chars-forward " \t\n")))
  
  (defun bibtex-beginning-of-first-entry ()
!   "Go to the beginning of the first BibTeX entry in buffer.  Return point."
    (goto-char (point-min))
    (if (re-search-forward "^[ \t]*@" nil 'move)
        (beginning-of-line))
***************
*** 1684,1693 ****
        (forward-char -1)))
  
  (defun bibtex-enclosing-field (&optional noerr)
!   "Search for BibTeX field enclosing point. Point moves to end of field.
! Use `match-beginning' and `match-end' to parse the field. If NOERR is non-nil,
! no error is signalled. In this case, bounds are returned on success,
! nil otherwise."
    (let ((bounds (bibtex-search-backward-field bibtex-field-name t)))
      (if (and bounds
               (<= (bibtex-start-of-field bounds) (point))
--- 1722,1731 ----
        (forward-char -1)))
  
  (defun bibtex-enclosing-field (&optional noerr)
!   "Search for BibTeX field enclosing point.
! Use `match-beginning' and `match-end' to parse the field.  If NOERR is 
non-nil,
! no error is signalled.  In this case, bounds are returned on success,
! nil otherwise.  Does not move point."
    (let ((bounds (bibtex-search-backward-field bibtex-field-name t)))
      (if (and bounds
               (<= (bibtex-start-of-field bounds) (point))
***************
*** 1697,1703 ****
          (error "Can't find enclosing BibTeX field")))))
  
  (defun bibtex-enclosing-entry-maybe-empty-head ()
!   "Search for BibTeX entry enclosing point. Move point to end of entry.
  Beginning (but not end) of entry is given by (`match-beginning' 0)."
    (let ((case-fold-search t)
          (old-point (point)))
--- 1735,1741 ----
          (error "Can't find enclosing BibTeX field")))))
  
  (defun bibtex-enclosing-entry-maybe-empty-head ()
!   "Search for BibTeX entry enclosing point.  Move point to end of entry.
  Beginning (but not end) of entry is given by (`match-beginning' 0)."
    (let ((case-fold-search t)
          (old-point (point)))
***************
*** 1732,1739 ****
          (message "Mark set")
          (bibtex-make-field (list (elt current 1) nil (elt current 2)) t))
         ((equal bibtex-last-kill-command 'entry)
!         (if (not (eobp))
!             (bibtex-beginning-of-entry))
          (set-mark (point))
          (message "Mark set")
          (insert (elt current 1)))
--- 1770,1776 ----
          (message "Mark set")
          (bibtex-make-field (list (elt current 1) nil (elt current 2)) t))
         ((equal bibtex-last-kill-command 'entry)
!         (unless (eobp) (bibtex-beginning-of-entry))
          (set-mark (point))
          (message "Mark set")
          (insert (elt current 1)))
***************
*** 1741,1755 ****
          (error "Unknown tag field: %s.  Please submit a bug report"
                 bibtex-last-kill-command))))))
  
- (defun bibtex-assoc-regexp (regexp alist)
-   "Return non-nil if REGEXP matches the car of an element of ALIST.
- The value is actually the element of ALIST matched by REGEXP.
- Case is ignored if `case-fold-search' is non-nil in the current buffer."
-   (while (and alist
-               (not (string-match regexp (caar alist))))
-     (setq alist (cdr alist)))
-   (car alist))
- 
  (defun bibtex-format-entry ()
    "Helper function for `bibtex-clean-entry'.
  Formats current entry according to variable `bibtex-entry-format'."
--- 1778,1783 ----
***************
*** 1764,1770 ****
                                    unify-case inherit-booktitle)
                        bibtex-entry-format))
              crossref-key bounds alternatives-there non-empty-alternative
!             entry-list req-field-list field-done field-list)
  
          ;; identify entry type
          (goto-char (point-min))
--- 1792,1798 ----
                                    unify-case inherit-booktitle)
                        bibtex-entry-format))
              crossref-key bounds alternatives-there non-empty-alternative
!             entry-list req-field-list field-list)
  
          ;; identify entry type
          (goto-char (point-min))
***************
*** 1792,1800 ****
          ;; one alternative is non-empty
          (goto-char (point-min))
          (let* ((fields-alist (bibtex-parse-entry))
!                (case-fold-search t)
!                (field (bibtex-assoc-regexp "\\`\\(OPT\\)?crossref\\'"
!                                            fields-alist)))
            (setq crossref-key (and field
                                    (not (string-match bibtex-empty-field-re
                                                       (cdr field)))
--- 1820,1826 ----
          ;; one alternative is non-empty
          (goto-char (point-min))
          (let* ((fields-alist (bibtex-parse-entry))
!                (field (assoc-string "crossref" fields-alist t)))
            (setq crossref-key (and field
                                    (not (string-match bibtex-empty-field-re
                                                       (cdr field)))
***************
*** 1806,1814 ****
            (dolist (rfield req-field-list)
              (when (nth 3 rfield) ; we should have an alternative
                (setq alternatives-there t
!                     field (bibtex-assoc-regexp
!                            (concat "\\`\\(ALT\\)?" (car rfield) "\\'")
!                            fields-alist))
                (if (and field
                         (not (string-match bibtex-empty-field-re
                                            (cdr field))))
--- 1832,1838 ----
            (dolist (rfield req-field-list)
              (when (nth 3 rfield) ; we should have an alternative
                (setq alternatives-there t
!                     field (assoc-string (car rfield) fields-alist t))
                (if (and field
                         (not (string-match bibtex-empty-field-re
                                            (cdr field))))
***************
*** 1887,1893 ****
  
                ;; update page dashes
                (if (and (memq 'page-dashes format)
!                        (string-match "\\`\\(OPT\\)?pages\\'" field-name)
                         (progn (goto-char beg-text)
                                (looking-at
                                 "\\([\"{][0-9]+\\)[ \t\n]*--?[ 
\t\n]*\\([0-9]+[\"}]\\)")))
--- 1911,1917 ----
  
                ;; update page dashes
                (if (and (memq 'page-dashes format)
!                        (bibtex-string= field-name "pages")
                         (progn (goto-char beg-text)
                                (looking-at
                                 "\\([\"{][0-9]+\\)[ \t\n]*--?[ 
\t\n]*\\([0-9]+[\"}]\\)")))
***************
*** 1896,1902 ****
                ;; use book title of crossref'd entry
                (if (and (memq 'inherit-booktitle format)
                         empty-field
!                        (equal (downcase field-name) "booktitle")
                         crossref-key)
                    (let ((title (save-restriction
                                   (widen)
--- 1920,1926 ----
                ;; use book title of crossref'd entry
                (if (and (memq 'inherit-booktitle format)
                         empty-field
!                        (bibtex-string= field-name "booktitle")
                         crossref-key)
                    (let ((title (save-restriction
                                   (widen)
***************
*** 1909,1915 ****
  
              ;; Use booktitle to set a missing title.
              (if (and empty-field
!                      (equal (downcase field-name) "title"))
                  (let ((booktitle (bibtex-text-in-field "booktitle")))
                    (when booktitle
                      (setq empty-field nil)
--- 1933,1939 ----
  
              ;; Use booktitle to set a missing title.
              (if (and empty-field
!                      (bibtex-string= field-name "title"))
                  (let ((booktitle (bibtex-text-in-field "booktitle")))
                    (when booktitle
                      (setq empty-field nil)
***************
*** 1990,1997 ****
  (defun bibtex-autokey-abbrev (string len)
    "Return an abbreviation of STRING with at least LEN characters.
  If LEN is positive the abbreviation is terminated only after a consonant
! or at the word end. If LEN is negative the abbreviation is strictly
! enforced using abs (LEN) characters. If LEN is not a number, STRING
  is returned unchanged."
    (cond ((or (not (numberp len))
               (<= (length string) (abs len)))
--- 2014,2021 ----
  (defun bibtex-autokey-abbrev (string len)
    "Return an abbreviation of STRING with at least LEN characters.
  If LEN is positive the abbreviation is terminated only after a consonant
! or at the word end.  If LEN is negative the abbreviation is strictly
! enforced using abs (LEN) characters.  If LEN is not a number, STRING
  is returned unchanged."
    (cond ((or (not (numberp len))
               (<= (length string) (abs len)))
***************
*** 2007,2015 ****
                 string)))))
  
  (defun bibtex-autokey-get-field (field &optional change-list)
!   "Get content of BibTeX field FIELD. Return empty string if not found.
  Optional arg CHANGE-LIST is a list of substitution patterns that is
! applied to the content of FIELD. It is an alist with pairs
  \(OLD-REGEXP . NEW-STRING\)."
    (let ((content (bibtex-text-in-field field bibtex-autokey-use-crossref))
          case-fold-search)
--- 2031,2039 ----
                 string)))))
  
  (defun bibtex-autokey-get-field (field &optional change-list)
!   "Get content of BibTeX field FIELD.  Return empty string if not found.
  Optional arg CHANGE-LIST is a list of substitution patterns that is
! applied to the content of FIELD.  It is an alist with pairs
  \(OLD-REGEXP . NEW-STRING\)."
    (let ((content (bibtex-text-in-field field bibtex-autokey-use-crossref))
          case-fold-search)
***************
*** 2023,2037 ****
    "Get contents of the name field of the current entry.
  Do some modifications based on `bibtex-autokey-name-change-strings'
  and return results as a list."
!   (let ((case-fold-search t))
!     (mapcar 'bibtex-autokey-demangle-name
!             (split-string (bibtex-autokey-get-field
!                            "author\\|editor"
!                            bibtex-autokey-name-change-strings)
!                           "[ \t\n]+and[ \t\n]+"))))
  
  (defun bibtex-autokey-demangle-name (fullname)
!   "Get the last part from a well-formed name and perform abbreviations."
    (let* (case-fold-search
           (name (cond ((string-match "\\([A-Z][^, ]*\\)[^,]*," fullname)
                        ;; Name is of the form "von Last, First" or
--- 2047,2062 ----
    "Get contents of the name field of the current entry.
  Do some modifications based on `bibtex-autokey-name-change-strings'
  and return results as a list."
!   (let ((case-fold-search t)
!         (names (bibtex-autokey-get-field "author\\|editor"
!                                          bibtex-autokey-name-change-strings)))
!     ;; Some entries do not have a name field.
!     (unless (string= "" names)
!       (mapcar 'bibtex-autokey-demangle-name
!               (split-string names "[ \t\n]+and[ \t\n]+")))))
  
  (defun bibtex-autokey-demangle-name (fullname)
!   "Get the last part from a well-formed FULLNAME and perform abbreviations."
    (let* (case-fold-search
           (name (cond ((string-match "\\([A-Z][^, ]*\\)[^,]*," fullname)
                        ;; Name is of the form "von Last, First" or
***************
*** 2059,2076 ****
  
  (defun bibtex-autokey-get-title ()
    "Get title field contents up to a terminator."
!   (let ((titlestring
           (bibtex-autokey-get-field "title"
                                     bibtex-autokey-titleword-change-strings)))
      ;; ignore everything past a terminator
!     (let ((case-fold-search t))
!       (dolist (terminator bibtex-autokey-title-terminators)
!         (if (string-match terminator titlestring)
!             (setq titlestring (substring titlestring 0 (match-beginning 
0))))))
      ;; gather words from titlestring into a list. Ignore
      ;; specific words and use only a specific amount of words.
      (let ((counter 0)
!           case-fold-search titlewords titlewords-extra titleword end-match)
        (while (and (or (not (numberp bibtex-autokey-titlewords))
                        (< counter (+ bibtex-autokey-titlewords
                                      bibtex-autokey-titlewords-stretch)))
--- 2084,2101 ----
  
  (defun bibtex-autokey-get-title ()
    "Get title field contents up to a terminator."
!   (let ((case-fold-search t)
!         (titlestring
           (bibtex-autokey-get-field "title"
                                     bibtex-autokey-titleword-change-strings)))
      ;; ignore everything past a terminator
!     (dolist (terminator bibtex-autokey-title-terminators)
!       (if (string-match terminator titlestring)
!           (setq titlestring (substring titlestring 0 (match-beginning 0)))))
      ;; gather words from titlestring into a list. Ignore
      ;; specific words and use only a specific amount of words.
      (let ((counter 0)
!           titlewords titlewords-extra titleword end-match)
        (while (and (or (not (numberp bibtex-autokey-titlewords))
                        (< counter (+ bibtex-autokey-titlewords
                                      bibtex-autokey-titlewords-stretch)))
***************
*** 2078,2085 ****
          (setq end-match (match-end 0)
                titleword (substring titlestring
                                     (match-beginning 0) end-match))
!         (unless (bibtex-member-of-regexp titleword
!                                          bibtex-autokey-titleword-ignore)
            (setq titleword
                  (funcall bibtex-autokey-titleword-case-convert titleword))
            (if (or (not (numberp bibtex-autokey-titlewords))
--- 2103,2114 ----
          (setq end-match (match-end 0)
                titleword (substring titlestring
                                     (match-beginning 0) end-match))
!         (unless (let ((lst bibtex-autokey-titleword-ignore))
!                   (while (and lst
!                               (not (string-match (concat "\\`\\(?:" (car lst)
!                                                          "\\)\\'") 
titleword)))
!                     (setq lst (cdr lst)))
!                   lst)
            (setq titleword
                  (funcall bibtex-autokey-titleword-case-convert titleword))
            (if (or (not (numberp bibtex-autokey-titlewords))
***************
*** 2097,2103 ****
    "Do some abbreviations on TITLEWORD.
  The rules are defined in `bibtex-autokey-titleword-abbrevs'
  and `bibtex-autokey-titleword-length'."
!   (let ((case-folde-search t)
          (alist bibtex-autokey-titleword-abbrevs))
      (while (and alist
                  (not (string-match (concat "\\`\\(?:" (caar alist) "\\)\\'")
--- 2126,2132 ----
    "Do some abbreviations on TITLEWORD.
  The rules are defined in `bibtex-autokey-titleword-abbrevs'
  and `bibtex-autokey-titleword-length'."
!   (let ((case-fold-search t)
          (alist bibtex-autokey-titleword-abbrevs))
      (while (and alist
                  (not (string-match (concat "\\`\\(?:" (caar alist) "\\)\\'")
***************
*** 2119,2125 ****
      `bibtex-autokey-name-change-strings' to the corresponding new
      one (see documentation of this variable for further detail).
   4. For every of at least first `bibtex-autokey-names' names in
!     the name field, determine the last name. If there are maximal
      `bibtex-autokey-names' + `bibtex-autokey-names-stretch'
      names, all names are used.
   5. From every last name, take at least `bibtex-autokey-name-length'
--- 2148,2154 ----
      `bibtex-autokey-name-change-strings' to the corresponding new
      one (see documentation of this variable for further detail).
   4. For every of at least first `bibtex-autokey-names' names in
!     the name field, determine the last name.  If there are maximal
      `bibtex-autokey-names' + `bibtex-autokey-names-stretch'
      names, all names are used.
   5. From every last name, take at least `bibtex-autokey-name-length'
***************
*** 2128,2139 ****
      `bibtex-autokey-name-case-convert'.
   7. Build the name part of the key by concatenating all
      abbreviated last names with the string
!     `bibtex-autokey-name-separator' between any two. If there are
      more names than are used in the name part, prepend the string
      contained in `bibtex-autokey-additional-names'.
   8. Build the year part of the key by truncating the contents of
      the year field to the rightmost `bibtex-autokey-year-length'
!     digits (useful values are 2 and 4). If the year field (or any
      other field required to generate the key) is absent, but the entry
      has a valid crossref field and the variable
      `bibtex-autokey-use-crossref' is non-nil, use the field of the
--- 2157,2168 ----
      `bibtex-autokey-name-case-convert'.
   7. Build the name part of the key by concatenating all
      abbreviated last names with the string
!     `bibtex-autokey-name-separator' between any two.  If there are
      more names than are used in the name part, prepend the string
      contained in `bibtex-autokey-additional-names'.
   8. Build the year part of the key by truncating the contents of
      the year field to the rightmost `bibtex-autokey-year-length'
!     digits (useful values are 2 and 4).  If the year field (or any
      other field required to generate the key) is absent, but the entry
      has a valid crossref field and the variable
      `bibtex-autokey-use-crossref' is non-nil, use the field of the
***************
*** 2149,2155 ****
      appear in `bibtex-autokey-titleword-ignore'.
      Build the title part of the key by using at least the first
      `bibtex-autokey-titlewords' words from this
!     abbreviated title. If the abbreviated title ends after
      maximal `bibtex-autokey-titlewords' +
      `bibtex-autokey-titlewords-stretch' words, all
      words from the abbreviated title are used.
--- 2178,2184 ----
      appear in `bibtex-autokey-titleword-ignore'.
      Build the title part of the key by using at least the first
      `bibtex-autokey-titlewords' words from this
!     abbreviated title.  If the abbreviated title ends after
      maximal `bibtex-autokey-titlewords' +
      `bibtex-autokey-titlewords-stretch' words, all
      words from the abbreviated title are used.
***************
*** 2170,2182 ****
      and the title part with `bibtex-autokey-name-year-separator'
      between the name part and the year part if both are non-empty
      and `bibtex-autokey-year-title-separator' between the year
!     part and the title part if both are non-empty. If the year
      part is empty, but not the other two parts,
      `bibtex-autokey-year-title-separator' is used as well.
  16. If the value of `bibtex-autokey-before-presentation-function'
!     is non-nil, it must be a function taking one argument. This
      function is then called with the generated key as the
!     argument. The return value of this function (a string) is
      used as the key.
  17. If the value of `bibtex-autokey-edit-before-use' is non-nil,
      the key is then presented in the minibuffer to the user,
--- 2199,2211 ----
      and the title part with `bibtex-autokey-name-year-separator'
      between the name part and the year part if both are non-empty
      and `bibtex-autokey-year-title-separator' between the year
!     part and the title part if both are non-empty.  If the year
      part is empty, but not the other two parts,
      `bibtex-autokey-year-title-separator' is used as well.
  16. If the value of `bibtex-autokey-before-presentation-function'
!     is non-nil, it must be a function taking one argument.  This
      function is then called with the generated key as the
!     argument.  The return value of this function (a string) is
      used as the key.
  17. If the value of `bibtex-autokey-edit-before-use' is non-nil,
      the key is then presented in the minibuffer to the user,
***************
*** 2230,2238 ****
  The buffer might possibly be restricted.
  Find both entry keys and crossref entries.
  If ADD is non-nil add the new keys to `bibtex-reference-keys' instead of
! simply resetting it. If ADD is an alist of keys, also add ADD to
! `bibtex-reference-keys'. If ABORTABLE is non-nil abort on user
! input. If VERBOSE is non-nil gives messages about progress.
  Return alist of keys if parsing was completed, `aborted' otherwise."
    (let ((reference-keys (if (and add
                                   (listp bibtex-reference-keys))
--- 2259,2267 ----
  The buffer might possibly be restricted.
  Find both entry keys and crossref entries.
  If ADD is non-nil add the new keys to `bibtex-reference-keys' instead of
! simply resetting it.  If ADD is an alist of keys, also add ADD to
! `bibtex-reference-keys'.  If ABORTABLE is non-nil abort on user
! input.  If VERBOSE is non-nil gives messages about progress.
  Return alist of keys if parsing was completed, `aborted' otherwise."
    (let ((reference-keys (if (and add
                                   (listp bibtex-reference-keys))
***************
*** 2296,2303 ****
    "Set `bibtex-strings' to the string definitions in the whole buffer.
  The buffer might possibly be restricted.
  If ADD is non-nil add the new strings to `bibtex-strings' instead of
! simply resetting it. If ADD is an alist of strings, also add ADD to
! `bibtex-strings'. If ABORTABLE is non-nil abort on user input.
  Return alist of strings if parsing was completed, `aborted' otherwise."
    (save-excursion
      (save-match-data
--- 2325,2332 ----
    "Set `bibtex-strings' to the string definitions in the whole buffer.
  The buffer might possibly be restricted.
  If ADD is non-nil add the new strings to `bibtex-strings' instead of
! simply resetting it.  If ADD is an alist of strings, also add ADD to
! `bibtex-strings'.  If ABORTABLE is non-nil abort on user input.
  Return alist of strings if parsing was completed, `aborted' otherwise."
    (save-excursion
      (save-match-data
***************
*** 2308,2314 ****
              bounds key)
          (if (listp add)
              (dolist (string add)
!               (unless (assoc (car string) strings)
                  (push string strings))))
          (catch 'userkey
            (while (setq bounds (bibtex-search-forward-string))
--- 2337,2343 ----
              bounds key)
          (if (listp add)
              (dolist (string add)
!               (unless (assoc-string (car string) strings t)
                  (push string strings))))
          (catch 'userkey
            (while (setq bounds (bibtex-search-forward-string))
***************
*** 2317,2325 ****
                  ;; user has aborted by typing a key --> return `aborted'
                  (throw 'userkey 'aborted))
              (setq key (bibtex-reference-key-in-string bounds))
!             (if (not (assoc key strings))
!                 (push (cons key (bibtex-text-in-string bounds t))
!                       strings))
              (goto-char (bibtex-end-of-text-in-string bounds)))
            ;; successful operation --> return `bibtex-strings'
            (setq bibtex-strings strings))))))
--- 2346,2354 ----
                  ;; user has aborted by typing a key --> return `aborted'
                  (throw 'userkey 'aborted))
              (setq key (bibtex-reference-key-in-string bounds))
!             (unless (assoc-string key strings t)
!               (push (cons key (bibtex-text-in-string bounds t))
!                     strings))
              (goto-char (bibtex-end-of-text-in-string bounds)))
            ;; successful operation --> return `bibtex-strings'
            (setq bibtex-strings strings))))))
***************
*** 2357,2363 ****
        (append bibtex-predefined-strings (nreverse compl)))))
  
  (defun bibtex-parse-buffers-stealthily ()
!   "Called by `bibtex-run-with-idle-timer'. Whenever emacs has been idle
  for `bibtex-parse-keys-timeout' seconds, all BibTeX buffers (starting
  with the current) are parsed."
    (save-excursion
--- 2386,2393 ----
        (append bibtex-predefined-strings (nreverse compl)))))
  
  (defun bibtex-parse-buffers-stealthily ()
!   "Parse buffer in the background during idle time.
! Called by `bibtex-run-with-idle-timer'.  Whenever Emacs has been idle
  for `bibtex-parse-keys-timeout' seconds, all BibTeX buffers (starting
  with the current) are parsed."
    (save-excursion
***************
*** 2381,2389 ****
          (setq buffers (cdr buffers))))))
  
  (defun bibtex-complete-internal (completions)
!   "Complete word fragment before point to longest prefix of one
! string defined in list COMPLETIONS.  If point is not after the part
! of a word, all strings are listed. Return completion."
    (let* ((case-fold-search t)
           (beg (save-excursion
                  (re-search-backward "[ \t{\"]")
--- 2411,2419 ----
          (setq buffers (cdr buffers))))))
  
  (defun bibtex-complete-internal (completions)
!   "Complete word fragment before point to longest prefix of COMPLETIONS.
! COMPLETIONS should be a list of strings.  If point is not after the part
! of a word, all strings are listed.  Return completion."
    (let* ((case-fold-search t)
           (beg (save-excursion
                  (re-search-backward "[ \t{\"]")
***************
*** 2409,2419 ****
             ;; return value is handled by choose-completion-string-functions
             nil))))
  
! (defun bibtex-complete-string-cleanup (str)
    "Cleanup after inserting string STR.
! Remove enclosing field delimiters for string STR. Display message with
! expansion of STR."
!   (let ((pair (assoc str bibtex-strings)))
      (when pair
        (if (cdr pair)
            (message "Abbreviation for `%s'" (cdr pair)))
--- 2439,2450 ----
             ;; return value is handled by choose-completion-string-functions
             nil))))
  
! (defun bibtex-complete-string-cleanup (str strings-alist)
    "Cleanup after inserting string STR.
! Remove enclosing field delimiters for string STR.  Display message with
! expansion of STR using expansion list STRINGS-ALIST."
!   (let ((pair (if (stringp str)
!                   (assoc-string str strings-alist t))))
      (when pair
        (if (cdr pair)
            (message "Abbreviation for `%s'" (cdr pair)))
***************
*** 2427,2432 ****
--- 2458,2495 ----
                              (bibtex-end-of-text-in-field bounds)))
                  (bibtex-remove-delimiters))))))))
  
+ (defun bibtex-complete-key-cleanup (key)
+   "Display message on entry KEY after completion of a crossref key."
+   (save-excursion
+     ;; Don't do anything if we completed the key of an entry.
+     (let ((pnt (bibtex-beginning-of-entry)))
+       (if (and (stringp key)
+                (bibtex-find-entry key)
+                (/= pnt (point)))
+           (let* ((bibtex-autokey-name-case-convert 'identity)
+                  (bibtex-autokey-name-length 'infty)
+                  (nl (bibtex-autokey-get-names))
+                  (name (concat (nth 0 nl) (if (nth 1 nl) " etal")))
+                  (year (bibtex-autokey-get-field "year"))
+                  (bibtex-autokey-titlewords 5)
+                  (bibtex-autokey-titlewords-stretch 2)
+                  (bibtex-autokey-titleword-case-convert 'identity)
+                  (bibtex-autokey-titleword-length 5)
+                  (title (mapconcat 'identity
+                                    (bibtex-autokey-get-title) " "))
+                  (journal (bibtex-autokey-get-field
+                            "journal" bibtex-autokey-transcriptions))
+                  (volume (bibtex-autokey-get-field "volume"))
+                  (pages (bibtex-autokey-get-field "pages" '(("-.*\\'" . 
"")))))
+             (message "Ref:%s"
+                      (mapconcat (lambda (arg)
+                                   (if (not (string= "" (cdr arg)))
+                                       (concat (car arg) (cdr arg))))
+                                 `((" " . ,name) (" " . ,year)
+                                   (": " . ,title) (", " . ,journal)
+                                   (" " . ,volume) (":" . ,pages))
+                                 "")))))))
+ 
  (defun bibtex-choose-completion-string (choice buffer mini-p base-size)
    ;; Code borrowed from choose-completion-string:
    ;; We must duplicate the code from choose-completion-string
***************
*** 2450,2456 ****
      (set-window-point window (point))))
  
  (defun bibtex-pop (arg direction)
!   "Generic function used by `bibtex-pop-previous' and `bibtex-pop-next'."
    (let (bibtex-help-message)
      (bibtex-find-text nil))
    (save-excursion
--- 2513,2520 ----
      (set-window-point window (point))))
  
  (defun bibtex-pop (arg direction)
!   "Fill current field from the ARG'th same field's text in DIRECTION.
! Generic function used by `bibtex-pop-previous' and `bibtex-pop-next'."
    (let (bibtex-help-message)
      (bibtex-find-text nil))
    (save-excursion
***************
*** 2460,2476 ****
             (bounds (bibtex-enclosing-field))
             (start-old-text (bibtex-start-of-text-in-field bounds))
             (stop-old-text (bibtex-end-of-text-in-field bounds))
!            (start-name (bibtex-start-of-name-in-field bounds))
!            (stop-name (bibtex-end-of-name-in-field bounds))
!            ;; construct regexp for field with same name as this one,
!            ;; ignoring possible OPT's or ALT's
!            (field-name (progn
!                          (goto-char start-name)
!                          (buffer-substring-no-properties
!                           (if (looking-at "\\(OPT\\)\\|\\(ALT\\)")
!                               (match-end 0)
!                             (point))
!                           stop-name))))
        ;; if executed several times in a row, start each search where
        ;; the last one was finished
        (unless (eq last-command 'bibtex-pop)
--- 2524,2530 ----
             (bounds (bibtex-enclosing-field))
             (start-old-text (bibtex-start-of-text-in-field bounds))
             (stop-old-text (bibtex-end-of-text-in-field bounds))
!            (field-name (bibtex-name-in-field bounds t)))
        ;; if executed several times in a row, start each search where
        ;; the last one was finished
        (unless (eq last-command 'bibtex-pop)
***************
*** 2523,2537 ****
  General information on working with BibTeX mode:
  
  You should use commands such as \\[bibtex-Book] to get a template for a
! specific entry. You should then fill in all desired fields using
! \\[bibtex-next-field] to jump from field to field. After having filled
  in all desired fields in the entry, you should clean the new entry
  with the command \\[bibtex-clean-entry].
  
  Some features of BibTeX mode are available only by setting the variable
! `bibtex-maintain-sorted-entries' to non-nil. However, then BibTeX mode will
  work only with buffers containing valid (syntactical correct) entries
! and with entries being sorted. This is usually the case, if you have
  created a buffer completely with BibTeX mode and finished every new
  entry with \\[bibtex-clean-entry].
  
--- 2577,2591 ----
  General information on working with BibTeX mode:
  
  You should use commands such as \\[bibtex-Book] to get a template for a
! specific entry.  You should then fill in all desired fields using
! \\[bibtex-next-field] to jump from field to field.  After having filled
  in all desired fields in the entry, you should clean the new entry
  with the command \\[bibtex-clean-entry].
  
  Some features of BibTeX mode are available only by setting the variable
! `bibtex-maintain-sorted-entries' to non-nil.  However, then BibTeX mode will
  work only with buffers containing valid (syntactical correct) entries
! and with entries being sorted.  This is usually the case, if you have
  created a buffer completely with BibTeX mode and finished every new
  entry with \\[bibtex-clean-entry].
  
***************
*** 2639,2647 ****
                  )
           nil
           (font-lock-syntactic-keywords . bibtex-font-lock-syntactic-keywords)
         (font-lock-mark-block-function
          . (lambda ()
!          (set-mark (bibtex-end-of-entry))
              (bibtex-beginning-of-entry)))))
    (setq imenu-generic-expression
          (list (list nil bibtex-entry-head bibtex-key-in-head)))
--- 2693,2702 ----
                  )
           nil
           (font-lock-syntactic-keywords . bibtex-font-lock-syntactic-keywords)
+          (font-lock-extra-managed-props . (mouse-face keymap))
         (font-lock-mark-block-function
          . (lambda ()
!               (set-mark (bibtex-end-of-entry))
              (bibtex-beginning-of-entry)))))
    (setq imenu-generic-expression
          (list (list nil bibtex-entry-head bibtex-key-in-head)))
***************
*** 2681,2687 ****
      (cons required optional)))
  
  (defun bibtex-entry (entry-type)
!   "Insert a new BibTeX entry.
  After insertion it calls the functions in `bibtex-add-entry-hook'."
    (interactive (let* ((completion-ignore-case t)
                        (e-t (completing-read
--- 2736,2742 ----
      (cons required optional)))
  
  (defun bibtex-entry (entry-type)
!   "Insert a new BibTeX entry of type ENTRY-TYPE.
  After insertion it calls the functions in `bibtex-add-entry-hook'."
    (interactive (let* ((completion-ignore-case t)
                        (e-t (completing-read
***************
*** 2698,2705 ****
      (insert "@" entry-type (bibtex-entry-left-delimiter))
      (if key (insert key))
      (save-excursion
!       (mapcar 'bibtex-make-field (car field-list))
!       (mapcar 'bibtex-make-optional-field (cdr field-list))
        (if bibtex-comma-after-last-field
            (insert ","))
        (insert "\n")
--- 2753,2760 ----
      (insert "@" entry-type (bibtex-entry-left-delimiter))
      (if key (insert key))
      (save-excursion
!       (mapc 'bibtex-make-field (car field-list))
!       (mapc 'bibtex-make-optional-field (cdr field-list))
        (if bibtex-comma-after-last-field
            (insert ","))
        (insert "\n")
***************
*** 2722,2750 ****
      (let* ((fields-alist (bibtex-parse-entry))
             (field-list (bibtex-field-list
                          (substring (cdr (assoc "=type=" fields-alist))
!                                    1))) ; don't want @
!            (case-fold-search t))
        (dolist (field (car field-list))
!         (unless (bibtex-assoc-regexp (concat "\\`\\(ALT\\)?" (car field) 
"\\'")
!                                      fields-alist)
            (bibtex-make-field field)))
        (dolist (field (cdr field-list))
!         (unless (bibtex-assoc-regexp (concat "\\`\\(OPT\\)?" (car field) 
"\\'")
!                                      fields-alist)
            (bibtex-make-optional-field field))))))
  
  (defun bibtex-parse-entry ()
    "Parse entry at point, return an alist.
  The alist elements have the form (FIELD . TEXT), where FIELD can also be
! the special strings \"=type=\" and \"=key=\". For the FIELD \"=key=\"
! TEXT may be nil. Move point to the end of the last field."
    (let (alist bounds)
      (when (looking-at bibtex-entry-maybe-empty-head)
        (push (cons "=type=" (match-string bibtex-type-in-head)) alist)
        (push (cons "=key=" (match-string bibtex-key-in-head)) alist)
        (goto-char (match-end 0))
        (while (setq bounds (bibtex-parse-field bibtex-field-name))
!       (push (cons (bibtex-name-in-field bounds)
                    (bibtex-text-in-field-bounds bounds))
              alist)
        (goto-char (bibtex-end-of-field bounds))))
--- 2777,2803 ----
      (let* ((fields-alist (bibtex-parse-entry))
             (field-list (bibtex-field-list
                          (substring (cdr (assoc "=type=" fields-alist))
!                                    1)))) ; don't want @
        (dolist (field (car field-list))
!         (unless (assoc-string (car field) fields-alist t)
            (bibtex-make-field field)))
        (dolist (field (cdr field-list))
!         (unless (assoc-string (car field) fields-alist t)
            (bibtex-make-optional-field field))))))
  
  (defun bibtex-parse-entry ()
    "Parse entry at point, return an alist.
  The alist elements have the form (FIELD . TEXT), where FIELD can also be
! the special strings \"=type=\" and \"=key=\".  For the FIELD \"=key=\"
! TEXT may be nil.  Remove \"OPT\" and \"ALT\" from FIELD.
! Move point to the end of the last field."
    (let (alist bounds)
      (when (looking-at bibtex-entry-maybe-empty-head)
        (push (cons "=type=" (match-string bibtex-type-in-head)) alist)
        (push (cons "=key=" (match-string bibtex-key-in-head)) alist)
        (goto-char (match-end 0))
        (while (setq bounds (bibtex-parse-field bibtex-field-name))
!       (push (cons (bibtex-name-in-field bounds t)
                    (bibtex-text-in-field-bounds bounds))
              alist)
        (goto-char (bibtex-end-of-field bounds))))
***************
*** 2770,2776 ****
        (bibtex-beginning-of-entry)
        (when (and
               (looking-at bibtex-entry-head)
!              (equal type (match-string bibtex-type-in-head))
               ;; In case we found ourselves :-(
               (not (equal key (setq tmp (match-string bibtex-key-in-head)))))
          (setq other-key tmp)
--- 2823,2829 ----
        (bibtex-beginning-of-entry)
        (when (and
               (looking-at bibtex-entry-head)
!              (bibtex-string= type (match-string bibtex-type-in-head))
               ;; In case we found ourselves :-(
               (not (equal key (setq tmp (match-string bibtex-key-in-head)))))
          (setq other-key tmp)
***************
*** 2780,2786 ****
        (bibtex-skip-to-valid-entry)
        (when (and
               (looking-at bibtex-entry-head)
!              (equal type (match-string bibtex-type-in-head))
               ;; In case we found ourselves :-(
               (not (equal key (setq tmp (match-string bibtex-key-in-head))))
               (or (not other-key)
--- 2833,2839 ----
        (bibtex-skip-to-valid-entry)
        (when (and
               (looking-at bibtex-entry-head)
!              (bibtex-string= type (match-string bibtex-type-in-head))
               ;; In case we found ourselves :-(
               (not (equal key (setq tmp (match-string bibtex-key-in-head))))
               (or (not other-key)
***************
*** 2794,2804 ****
        (setq other (save-excursion (goto-char other) (bibtex-parse-entry)))
        (setq key-end (point))      ;In case parse-entry changed the buffer.
        (while (setq bounds (bibtex-parse-field bibtex-field-name))
!         (goto-char (bibtex-start-of-name-in-field bounds))
!         (let* ((name (buffer-substring
!                       (if (looking-at "ALT\\|OPT") (match-end 0) (point))
!                       (bibtex-end-of-name-in-field bounds)))
!                (text (assoc-string name other t)))
            (goto-char (bibtex-start-of-text-in-field bounds))
            (if (not (and (looking-at bibtex-empty-field-re) text))
                (goto-char (bibtex-end-of-field bounds))
--- 2847,2854 ----
        (setq other (save-excursion (goto-char other) (bibtex-parse-entry)))
        (setq key-end (point))      ;In case parse-entry changed the buffer.
        (while (setq bounds (bibtex-parse-field bibtex-field-name))
!         (let ((text (assoc-string (bibtex-name-in-field bounds t)
!                                     other t)))
            (goto-char (bibtex-start-of-text-in-field bounds))
            (if (not (and (looking-at bibtex-empty-field-re) text))
                (goto-char (bibtex-end-of-field bounds))
***************
*** 2821,2833 ****
    (interactive)
    (save-excursion
      (let* ((case-fold-search t)
!            (bounds (bibtex-enclosing-field))
!            (mb (bibtex-start-of-name-in-field bounds))
!            (field-name (buffer-substring-no-properties
!                         (if (progn (goto-char mb)
!                                    (looking-at "OPT\\|ALT"))
!                             (match-end 0) mb)
!                         (bibtex-end-of-name-in-field bounds)))
             (field-list (bibtex-field-list (progn (re-search-backward
                                                    
bibtex-entry-maybe-empty-head nil t)
                                                   (bibtex-type-in-head))))
--- 2871,2877 ----
    (interactive)
    (save-excursion
      (let* ((case-fold-search t)
!            (field-name (bibtex-name-in-field (bibtex-enclosing-field) t))
             (field-list (bibtex-field-list (progn (re-search-backward
                                                    
bibtex-entry-maybe-empty-head nil t)
                                                   (bibtex-type-in-head))))
***************
*** 2843,2849 ****
    "Make a field named FIELD in current BibTeX entry.
  FIELD is either a string or a list of the form
  \(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in
! `bibtex-entry-field-alist'."
    (interactive
     (list (let ((completion-ignore-case t)
                 (field-list (bibtex-field-list
--- 2887,2894 ----
    "Make a field named FIELD in current BibTeX entry.
  FIELD is either a string or a list of the form
  \(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in
! `bibtex-entry-field-alist'.
! If CALLED-BY-YANK is non-nil, don't insert delimiters."
    (interactive
     (list (let ((completion-ignore-case t)
                 (field-list (bibtex-field-list
***************
*** 2868,2883 ****
        (indent-to-column (+ bibtex-entry-offset
                             (- bibtex-text-indentation 2))))
    (insert "= ")
!   (if (not bibtex-align-at-equal-sign)
!       (indent-to-column (+ bibtex-entry-offset
!                            bibtex-text-indentation)))
!   (if (not called-by-yank) (insert (bibtex-field-left-delimiter)))
    (let ((init (nth 2 field)))
      (cond ((stringp init)
             (insert init))
            ((fboundp init)
             (insert (funcall init)))))
!   (if (not called-by-yank) (insert (bibtex-field-right-delimiter)))
    (when (interactive-p)
      (forward-char -1)
      (bibtex-print-help-message)))
--- 2913,2928 ----
        (indent-to-column (+ bibtex-entry-offset
                             (- bibtex-text-indentation 2))))
    (insert "= ")
!   (unless bibtex-align-at-equal-sign
!     (indent-to-column (+ bibtex-entry-offset
!                          bibtex-text-indentation)))
!   (unless called-by-yank (insert (bibtex-field-left-delimiter)))
    (let ((init (nth 2 field)))
      (cond ((stringp init)
             (insert init))
            ((fboundp init)
             (insert (funcall init)))))
!   (unless called-by-yank (insert (bibtex-field-right-delimiter)))
    (when (interactive-p)
      (forward-char -1)
      (bibtex-print-help-message)))
***************
*** 2885,2892 ****
  (defun bibtex-beginning-of-entry ()
    "Move to beginning of BibTeX entry (beginning of line).
  If inside an entry, move to the beginning of it, otherwise move to the
! beginning of the previous entry. If point is ahead of all BibTeX entries
! move point to the beginning of buffer. Return the new location of point."
    (interactive)
    (skip-chars-forward " \t")
    (if (looking-at "@")
--- 2930,2937 ----
  (defun bibtex-beginning-of-entry ()
    "Move to beginning of BibTeX entry (beginning of line).
  If inside an entry, move to the beginning of it, otherwise move to the
! beginning of the previous entry.  If point is ahead of all BibTeX entries
! move point to the beginning of buffer.  Return the new location of point."
    (interactive)
    (skip-chars-forward " \t")
    (if (looking-at "@")
***************
*** 2897,2903 ****
  (defun bibtex-end-of-entry ()
    "Move to end of BibTeX entry (past the closing brace).
  If inside an entry, move to the end of it, otherwise move to the end
! of the previous entry. Do not move if ahead of first entry.
  Return the new location of point."
    (interactive)
    (let ((case-fold-search t)
--- 2942,2948 ----
  (defun bibtex-end-of-entry ()
    "Move to end of BibTeX entry (past the closing brace).
  If inside an entry, move to the end of it, otherwise move to the end
! of the previous entry.  Do not move if ahead of first entry.
  Return the new location of point."
    (interactive)
    (let ((case-fold-search t)
***************
*** 2997,3005 ****
                        (bibtex-end-of-entry))))
  
  (defun bibtex-entry-index ()
!   "Return the index of the BibTeX entry at point. Move point.
  The index is a list (KEY CROSSREF-KEY ENTRY-NAME) that is used for sorting
! the entries of the BibTeX buffer. Return nil if no entry found."
    (let ((case-fold-search t))
      (if (re-search-forward bibtex-entry-maybe-empty-head nil t)
          (let ((key (bibtex-key-in-head))
--- 3042,3050 ----
                        (bibtex-end-of-entry))))
  
  (defun bibtex-entry-index ()
!   "Return the index of the BibTeX entry at point.  Move point.
  The index is a list (KEY CROSSREF-KEY ENTRY-NAME) that is used for sorting
! the entries of the BibTeX buffer.  Return nil if no entry found."
    (let ((case-fold-search t))
      (if (re-search-forward bibtex-entry-maybe-empty-head nil t)
          (let ((key (bibtex-key-in-head))
***************
*** 3049,3056 ****
  (defun bibtex-sort-buffer ()
    "Sort BibTeX buffer alphabetically by key.
  The predicate for sorting is defined via `bibtex-maintain-sorted-entries'.
! If its value is nil use plain sorting. Text outside of BibTeX entries is not
! affected. If `bibtex-sort-ignore-string-entries' is non-nil, @String entries
  will be ignored."
    (interactive)
    (save-restriction
--- 3094,3101 ----
  (defun bibtex-sort-buffer ()
    "Sort BibTeX buffer alphabetically by key.
  The predicate for sorting is defined via `bibtex-maintain-sorted-entries'.
! If its value is nil use plain sorting.  Text outside of BibTeX entries is not
! affected.  If `bibtex-sort-ignore-string-entries' is non-nil, @String entries
  will be ignored."
    (interactive)
    (save-restriction
***************
*** 3084,3096 ****
          (error "This entry must not follow the crossrefed entry!"))
      (goto-char pos)))
  
! (defun bibtex-find-entry (key)
    "Move point to the beginning of BibTeX entry named KEY.
! Return position of entry if KEY is found or nil if not found."
!   (interactive (list (bibtex-read-key "Find key: ")))
    (let* (case-fold-search
           (pnt (save-excursion
!                 (goto-char (point-min))
                  (if (re-search-forward (concat "^[ \t]*\\("
                                                 bibtex-entry-type
                                                 "\\)[ \t]*[({][ \t\n]*\\("
--- 3129,3145 ----
          (error "This entry must not follow the crossrefed entry!"))
      (goto-char pos)))
  
! (defun bibtex-find-entry (key &optional start)
    "Move point to the beginning of BibTeX entry named KEY.
! Return position of entry if KEY is found or nil if not found.
! Optional arg START is buffer position where the search starts.
! If it is nil, start search at beginning of buffer.
! With prefix arg, the value of START is position of point."
!   (interactive (list (bibtex-read-key "Find key: ")
!                      (if current-prefix-arg (point))))
    (let* (case-fold-search
           (pnt (save-excursion
!                 (goto-char (or start (point-min)))
                  (if (re-search-forward (concat "^[ \t]*\\("
                                                 bibtex-entry-type
                                                 "\\)[ \t]*[({][ \t\n]*\\("
***************
*** 3108,3114 ****
  INDEX is a list (KEY CROSSREF-KEY ENTRY-NAME).
  Move point where the entry KEY should be placed.
  If `bibtex-maintain-sorted-entries' is non-nil, perform a binary
! search to look for place for KEY. This will fail if buffer is not in
  sorted order, see \\[bibtex-validate].)
  Return t if preparation was successful or nil if entry KEY already exists."
    (let ((key (nth 0 index))
--- 3157,3163 ----
  INDEX is a list (KEY CROSSREF-KEY ENTRY-NAME).
  Move point where the entry KEY should be placed.
  If `bibtex-maintain-sorted-entries' is non-nil, perform a binary
! search to look for place for KEY.  This will fail if buffer is not in
  sorted order, see \\[bibtex-validate].)
  Return t if preparation was successful or nil if entry KEY already exists."
    (let ((key (nth 0 index))
***************
*** 3157,3164 ****
                 ;; buffer contains no valid entries or
                 ;; greater than last entry --> append
                 (bibtex-end-of-entry)
!                (if (not (bobp))
!                    (newline (forward-line 2)))
                 (beginning-of-line)))))
      (unless key-exist t)))
  
--- 3206,3212 ----
                 ;; buffer contains no valid entries or
                 ;; greater than last entry --> append
                 (bibtex-end-of-entry)
!                (unless (bobp) (newline (forward-line 2)))
                 (beginning-of-line)))))
      (unless key-exist t)))
  
***************
*** 3233,3241 ****
              (goto-char (point-min))
              (bibtex-progress-message
               "Checking required fields and month fields")
!             (let ((bibtex-sort-ignore-string-entries t)
!                   (questionable-month
!                    (regexp-opt (mapcar 'car 
bibtex-predefined-month-strings))))
                (bibtex-map-entries
                 (lambda (key beg end)
                   (bibtex-progress-message)
--- 3281,3287 ----
              (goto-char (point-min))
              (bibtex-progress-message
               "Checking required fields and month fields")
!             (let ((bibtex-sort-ignore-string-entries t))
                (bibtex-map-entries
                 (lambda (key beg end)
                   (bibtex-progress-message)
***************
*** 3251,3267 ****
                     (while (setq bounds (bibtex-search-forward-field
                                          bibtex-field-name end))
                       (goto-char (bibtex-start-of-text-in-field bounds))
!                      (let ((field-name (downcase (bibtex-name-in-field 
bounds)))
!                            case-fold-search)
!                        (if (and (equal field-name "month")
!                                 (not (string-match questionable-month
!                                                    
(bibtex-text-in-field-bounds bounds))))
                             (push (list (bibtex-current-line)
                                         "Questionable month field")
                                   error-list))
                         (setq req (delete (assoc-string field-name req t) req)
                               creq (delete (assoc-string field-name creq t) 
creq))
!                        (if (equal field-name "crossref")
                             (setq crossref-there t))))
                     (if crossref-there
                         (setq req creq))
--- 3297,3312 ----
                     (while (setq bounds (bibtex-search-forward-field
                                          bibtex-field-name end))
                       (goto-char (bibtex-start-of-text-in-field bounds))
!                      (let ((field-name (bibtex-name-in-field bounds)))
!                        (if (and (bibtex-string= field-name "month")
!                                 (not (assoc-string 
(bibtex-text-in-field-bounds bounds)
!                                                    
bibtex-predefined-month-strings t)))
                             (push (list (bibtex-current-line)
                                         "Questionable month field")
                                   error-list))
                         (setq req (delete (assoc-string field-name req t) req)
                               creq (delete (assoc-string field-name creq t) 
creq))
!                        (if (bibtex-string= field-name "crossref")
                             (setq crossref-there t))))
                     (if crossref-there
                         (setq req creq))
***************
*** 3305,3314 ****
            (dolist (err error-list)
              (insert bufnam ":" (number-to-string (elt err 0))
                      ": " (elt err 1) "\n"))
-           (compilation-parse-errors nil nil)
-           (setq compilation-old-error-list compilation-error-list)
-           ;; this is necessary to avoid reparsing of buffer if you
-           ;; switch to compilation buffer and enter `compile-goto-error'
            (set-buffer-modified-p nil)
            (toggle-read-only 1)
            (goto-char (point-min))
--- 3350,3355 ----
***************
*** 3395,3405 ****
    (interactive)
    (save-excursion
      (bibtex-inside-field)
!     (let ((bounds (bibtex-enclosing-field)))
!       (goto-char (bibtex-start-of-text-in-field bounds))
!       (delete-char 1)
!       (goto-char (1- (bibtex-end-of-text-in-field bounds)))
!       (delete-backward-char 1))))
  
  (defun bibtex-kill-field (&optional copy-only)
    "Kill the entire enclosing BibTeX field.
--- 3436,3448 ----
    (interactive)
    (save-excursion
      (bibtex-inside-field)
!     (let* ((bounds (bibtex-enclosing-field))
!          (end (bibtex-end-of-text-in-field bounds))
!          (start (bibtex-start-of-text-in-field bounds)))
!       (if (memq (char-before end) '(?\} ?\"))
!         (delete-region (1- end) end))
!       (if (memq (char-after start) '(?\{ ?\"))
!         (delete-region start (1+ start))))))
  
  (defun bibtex-kill-field (&optional copy-only)
    "Kill the entire enclosing BibTeX field.
***************
*** 3455,3460 ****
--- 3498,3504 ----
    (setq bibtex-last-kill-command 'entry))
  
  (defun bibtex-copy-entry-as-kill ()
+   "Copy the entire enclosing BibTeX entry to `bibtex-entry-kill-ring'."
    (interactive)
    (bibtex-kill-entry t))
  
***************
*** 3482,3489 ****
  The sequence of kills wraps around, so that after the oldest one
  comes the newest one."
    (interactive "*p")
!   (if (not (eq last-command 'bibtex-yank))
!       (error "Previous command was not a BibTeX yank"))
    (setq this-command 'bibtex-yank)
    (let ((inhibit-read-only t))
      (delete-region (point) (mark t))
--- 3526,3533 ----
  The sequence of kills wraps around, so that after the oldest one
  comes the newest one."
    (interactive "*p")
!   (unless (eq last-command 'bibtex-yank)
!     (error "Previous command was not a BibTeX yank"))
    (setq this-command 'bibtex-yank)
    (let ((inhibit-read-only t))
      (delete-region (point) (mark t))
***************
*** 3519,3525 ****
  Check that no required fields are empty and formats entry dependent
  on the value of `bibtex-entry-format'.
  If the reference key of the entry is empty or a prefix argument is given,
! calculate a new reference key. (Note: this will only work if fields in entry
  begin on separate lines prior to calling `bibtex-clean-entry' or if
  'realign is contained in `bibtex-entry-format'.)
  Don't call `bibtex-clean-entry' on @Preamble entries.
--- 3563,3569 ----
  Check that no required fields are empty and formats entry dependent
  on the value of `bibtex-entry-format'.
  If the reference key of the entry is empty or a prefix argument is given,
! calculate a new reference key.  (Note: this will only work if fields in entry
  begin on separate lines prior to calling `bibtex-clean-entry' or if
  'realign is contained in `bibtex-entry-format'.)
  Don't call `bibtex-clean-entry' on @Preamble entries.
***************
*** 3533,3551 ****
      (bibtex-beginning-of-entry)
      (save-excursion
        (when (re-search-forward bibtex-entry-maybe-empty-head nil t)
!         (setq entry-type (downcase (bibtex-type-in-head)))
          (setq key (bibtex-key-in-head))))
      ;; formatting
!     (cond ((equal entry-type "preamble")
             ;; (bibtex-format-preamble)
             (error "No clean up of @Preamble entries"))
!           ((equal entry-type "string"))
             ;; (bibtex-format-string)
            (t (bibtex-format-entry)))
      ;; set key
      (when (or new-key (not key))
        (setq key (bibtex-generate-autokey))
!       (if bibtex-autokey-edit-before-use
            (setq key (bibtex-read-key "Key to use: " key)))
        (re-search-forward bibtex-entry-maybe-empty-head)
        (if (match-beginning bibtex-key-in-head)
--- 3577,3596 ----
      (bibtex-beginning-of-entry)
      (save-excursion
        (when (re-search-forward bibtex-entry-maybe-empty-head nil t)
!         (setq entry-type (bibtex-type-in-head))
          (setq key (bibtex-key-in-head))))
      ;; formatting
!     (cond ((bibtex-string= entry-type "preamble")
             ;; (bibtex-format-preamble)
             (error "No clean up of @Preamble entries"))
!           ((bibtex-string= entry-type "string"))
             ;; (bibtex-format-string)
            (t (bibtex-format-entry)))
      ;; set key
      (when (or new-key (not key))
        (setq key (bibtex-generate-autokey))
!       ;; Sometimes bibtex-generate-autokey returns an empty string
!       (if (or bibtex-autokey-edit-before-use (string= "" key))
            (setq key (bibtex-read-key "Key to use: " key)))
        (re-search-forward bibtex-entry-maybe-empty-head)
        (if (match-beginning bibtex-key-in-head)
***************
*** 3563,3581 ****
               (entry (buffer-substring start end))
               (index (progn (goto-char start)
                             (bibtex-entry-index)))
!              no-error)
          (if (and bibtex-maintain-sorted-entries
                   (not (and bibtex-sort-ignore-string-entries
!                            (equal entry-type "string"))))
              (progn
                (delete-region start end)
!               (setq no-error (bibtex-prepare-new-entry index))
                (insert entry)
                (forward-char -1)
                (bibtex-beginning-of-entry) ; moves backward
                (re-search-forward bibtex-entry-head))
!           (setq no-error (bibtex-find-entry (car index))))
!         (unless no-error
            (error "New inserted entry yields duplicate key"))))
      ;; final clean up
      (unless called-by-reformat
--- 3608,3628 ----
               (entry (buffer-substring start end))
               (index (progn (goto-char start)
                             (bibtex-entry-index)))
!              error)
          (if (and bibtex-maintain-sorted-entries
                   (not (and bibtex-sort-ignore-string-entries
!                            (bibtex-string= entry-type "string"))))
              (progn
                (delete-region start end)
!               (setq error (not (bibtex-prepare-new-entry index)))
                (insert entry)
                (forward-char -1)
                (bibtex-beginning-of-entry) ; moves backward
                (re-search-forward bibtex-entry-head))
!           (bibtex-find-entry key)
!           (setq error (or (/= (point) start)
!                           (bibtex-find-entry key end))))
!         (if error
            (error "New inserted entry yields duplicate key"))))
      ;; final clean up
      (unless called-by-reformat
***************
*** 3583,3589 ****
          (save-restriction
            (bibtex-narrow-to-entry)
            ;; Only update the list of keys if it has been built already.
!           (cond ((equal entry-type "string")
                   (if (listp bibtex-strings) (bibtex-parse-strings t)))
                  ((listp bibtex-reference-keys) (bibtex-parse-keys t)))
            (run-hooks 'bibtex-clean-entry-hook))))))
--- 3630,3636 ----
          (save-restriction
            (bibtex-narrow-to-entry)
            ;; Only update the list of keys if it has been built already.
!           (cond ((bibtex-string= entry-type "string")
                   (if (listp bibtex-strings) (bibtex-parse-strings t)))
                  ((listp bibtex-reference-keys) (bibtex-parse-keys t)))
            (run-hooks 'bibtex-clean-entry-hook))))))
***************
*** 3752,3779 ****
  (defun bibtex-complete ()
    "Complete word fragment before point according to context.
  If point is inside key or crossref field perform key completion based on
! `bibtex-reference-keys'. Inside any other field perform string
! completion based on `bibtex-strings'. An error is signaled if point
! is outside key or BibTeX field."
    (interactive)
!   (let* ((pnt (point))
!          (case-fold-search t)
!          bounds compl)
      (save-excursion
        (if (and (setq bounds (bibtex-enclosing-field t))
                 (>= pnt (bibtex-start-of-text-in-field bounds))
                 (<= pnt (bibtex-end-of-text-in-field bounds)))
!           (progn
!             (goto-char (bibtex-start-of-name-in-field bounds))
!             (setq compl (if (string= "crossref"
!                                      (downcase
!                                       (buffer-substring-no-properties
!                                        (if (looking-at 
"\\(OPT\\)\\|\\(ALT\\)")
!                                            (match-end 0)
!                                          (point))
!                                        (bibtex-end-of-name-in-field bounds))))
!                             'key
!                           'str)))
          (bibtex-beginning-of-entry)
          (if (and (re-search-forward bibtex-entry-maybe-empty-head nil t)
                   ;; point is inside a key
--- 3799,3827 ----
  (defun bibtex-complete ()
    "Complete word fragment before point according to context.
  If point is inside key or crossref field perform key completion based on
! `bibtex-reference-keys'.  Inside a month field perform key completion
! based on `bibtex-predefined-month-strings'.  Inside any other field
! perform string completion based on `bibtex-strings'.  An error is
! signaled if point is outside key or BibTeX field."
    (interactive)
!   (let ((pnt (point))
!         (case-fold-search t)
!         bounds name compl)
      (save-excursion
        (if (and (setq bounds (bibtex-enclosing-field t))
                 (>= pnt (bibtex-start-of-text-in-field bounds))
                 (<= pnt (bibtex-end-of-text-in-field bounds)))
!           (setq name (bibtex-name-in-field bounds t)
!                 compl (cond ((bibtex-string= name "crossref")
!                              'key)
!                             ((bibtex-string= name "month")
!                              bibtex-predefined-month-strings)
!                             (t (if (listp bibtex-strings)
!                                    bibtex-strings
!                                  ;; so that bibtex-complete-string-cleanup
!                                  ;; can do its job
!                                  (bibtex-parse-strings
!                                   (bibtex-string-files-init))))))
          (bibtex-beginning-of-entry)
          (if (and (re-search-forward bibtex-entry-maybe-empty-head nil t)
                   ;; point is inside a key
***************
*** 3789,3812 ****
             ;; key completion
             (setq choose-completion-string-functions
                   (lambda (choice buffer mini-p base-size)
!                    (bibtex-choose-completion-string choice buffer mini-p 
base-size)
!                    (if bibtex-complete-key-cleanup
!                        (funcall bibtex-complete-key-cleanup choice))
                     ;; return t (required by 
choose-completion-string-functions)
                     t))
!            (let ((choice (bibtex-complete-internal bibtex-reference-keys)))
!              (if bibtex-complete-key-cleanup
!                  (funcall bibtex-complete-key-cleanup choice))))
  
!           ((equal compl 'str)
             ;; string completion
             (setq choose-completion-string-functions
!                  (lambda (choice buffer mini-p base-size)
                     (bibtex-choose-completion-string choice buffer mini-p 
base-size)
!                    (bibtex-complete-string-cleanup choice)
                     ;; return t (required by 
choose-completion-string-functions)
                     t))
!            (bibtex-complete-string-cleanup (bibtex-complete-internal 
bibtex-strings)))
  
            (t (error "Point outside key or BibTeX field")))))
  
--- 3837,3859 ----
             ;; key completion
             (setq choose-completion-string-functions
                   (lambda (choice buffer mini-p base-size)
!                     (bibtex-choose-completion-string choice buffer mini-p 
base-size)
!                    (bibtex-complete-key-cleanup choice)
                     ;; return t (required by 
choose-completion-string-functions)
                     t))
!            (bibtex-complete-key-cleanup (bibtex-complete-internal 
!                                          bibtex-reference-keys)))
  
!           (compl
             ;; string completion
             (setq choose-completion-string-functions
!                  `(lambda (choice buffer mini-p base-size)
                     (bibtex-choose-completion-string choice buffer mini-p 
base-size)
!                    (bibtex-complete-string-cleanup choice ',compl)
                     ;; return t (required by 
choose-completion-string-functions)
                     t))
!            (bibtex-complete-string-cleanup (bibtex-complete-internal compl)
!                                            compl))
  
            (t (error "Point outside key or BibTeX field")))))
  
***************
*** 3880,3887 ****
    (interactive (list (completing-read "String key: " bibtex-strings
                                        nil nil nil 'bibtex-key-history)))
    (let ((bibtex-maintain-sorted-entries
!          (if (not bibtex-sort-ignore-string-entries)
!              bibtex-maintain-sorted-entries))
          endpos)
      (unless (bibtex-prepare-new-entry (list key nil "String"))
        (error "Entry with key `%s' already exists" key))
--- 3927,3934 ----
    (interactive (list (completing-read "String key: " bibtex-strings
                                        nil nil nil 'bibtex-key-history)))
    (let ((bibtex-maintain-sorted-entries
!          (unless bibtex-sort-ignore-string-entries
!            bibtex-maintain-sorted-entries))
          endpos)
      (unless (bibtex-prepare-new-entry (list key nil "String"))
        (error "Entry with key `%s' already exists" key))
***************
*** 3913,3918 ****
--- 3960,4040 ----
              "\n")
      (goto-char endpos)))
  
+ (defun bibtex-url (&optional event)
+   "Browse a URL for the BibTeX entry at position PNT.
+ The URL is generated using the schemes defined in `bibtex-generate-url-list'
+ \(see there\).  Then the URL is passed to `browse-url'."
+   (interactive (list last-input-event))
+   (save-excursion
+     (if event (posn-set-point (event-end event)))
+     (bibtex-beginning-of-entry)
+     (let ((fields-alist (bibtex-parse-entry))
+           (case-fold-search t)
+           (lst bibtex-generate-url-list)
+           field url scheme)
+       (while (setq scheme (car lst))
+         (when (and (setq field (cdr (assoc-string (caar scheme)
+                                                 fields-alist t)))
+                  (progn
+                    (if (string-match "\\`[{\"]\\(.*\\)[}\"]\\'" field)
+                        (setq field (match-string 1 field)))
+                    (string-match (cdar scheme) field)))
+         (setq lst nil)
+         (if (null (cdr scheme))
+             (setq url (match-string 0 field)))
+           (dolist (step (cdr scheme))
+           (cond ((stringp step)
+                  (setq url (concat url step)))
+                 ((setq field (assoc-string (car step) fields-alist t))
+                  ;; always remove field delimiters
+                  (let* ((text (if (string-match "\\`[{\"]\\(.*\\)[}\"]\\'" 
+                                                 (cdr field))
+                                   (match-string 1 (cdr field))
+                                 (cdr field)))
+                         (str (if (string-match (nth 1 step) text)
+                                  (cond
+                                   ((functionp (nth 2 step))
+                                    (funcall (nth 2 step) text))
+                                   ((numberp (nth 2 step))
+                                    (match-string (nth 2 step) text))
+                                   (t
+                                    (replace-match (nth 2 step) nil nil text)))
+                                ;; If the scheme is set up correctly,
+                                ;; we should never reach this point
+                                (error "Match failed: %s" text))))
+                      (setq url (concat url str))))
+                 ;; If the scheme is set up correctly,
+                 ;; we should never reach this point
+                 (t (error "Step failed: %s" step))))
+         (message "%s" url)
+           (browse-url url))
+         (setq lst (cdr lst)))
+     (unless url (message "No URL known.")))))
+ 
+ (defun bibtex-font-lock-url (bound)
+   "Font-lock for URLs."
+   (let ((case-fold-search t)
+         (bounds (bibtex-enclosing-field t))
+         (pnt (point))
+       found field)
+     ;; We use start-of-field as syntax-begin
+     (goto-char (if bounds (bibtex-start-of-field bounds) pnt))
+     (while (and (not found)
+               (prog1 (re-search-forward bibtex-font-lock-url-regexp bound t)
+                 (setq field (match-string-no-properties 1)))
+               (setq bounds (bibtex-parse-field-text))
+               (>= bound (car bounds))
+               (>= (car bounds) pnt))
+       (let ((lst bibtex-generate-url-list) url)
+       (goto-char (car bounds))
+       (while (and (not found)
+                   (setq url (caar lst)))
+         (when (bibtex-string= field (car url))
+           (setq found (re-search-forward (cdr url) (cdr bounds) t)))
+         (setq lst (cdr lst))))
+       (goto-char (cdr bounds)))
+     found))
+ 
  
  ;; Make BibTeX a Feature
  




reply via email to

[Prev in Thread] Current Thread [Next in Thread]