changeset 27701:5e135f0faf1d

(bibtex-mode): Replaced manual splitting of path at ':' characters by call to split-string. Added RCS version identification. Some temporary comments removed. (bibtex-field-name, bibtex-entry-type): Made the relationship explicit. (bibtex-field-const): Allow capital letters. (bibtex-start-of-string): Deleted because unused. Unified some nomenclature. We no longer use the term 'reference' to describe a bibtex entry as a whole. Further, reference keys are no longer called 'labels'. (bibtex-keys): Renamed to bibtex-reference-keys. (bibtex-reformat-previous-labels): Renamed to bibtex-reformat-previous-reference-keys. (bibtex-reference-type): Renamed to bibtex-entry-type. (bibtex-reference-head): Renamed to bibtex-entry-head. (bibtex-reference-maybe-empty-head): Renamed to bibtex-entry-maybe-empty-head. (bibtex-key-in-reference): Renamed to bibtex-key-in-entry. (bibtex-search-reference): Renamed to bibtex-search-entry. (bibtex-enclosing-reference-maybe-empty-head): Renamed to bibtex-enclosing-entry-maybe-empty-head. (bibtex-entry-field-alist, bibtex-entry-head, bibtex-font-lock-keywords, bibtex-skip-to-valid-entry, bibtex-map-entries, bibtex-search-entry, bibtex-enclosing-entry-maybe-empty-head, bibtex-format-entry, bibtex-generate-autokey, bibtex-parse-keys, bibtex-pop, bibtex-mode, bibtex-submit-bug-report, bibtex-entry, bibtex-print-help-message, bibtex-make-field, bibtex-end-of-entry, bibtex-sort-buffer, bibtex-find-entry-location, bibtex-validate, bibtex-find-text, bibtex-kill-entry, bibtex-clean-entry, bibtex-reformat, bibtex-complete-key, bibtex-String) : Use the new nomenclature. (bibtex-strings, bibtex-keys): Removed redundant comment. (bibtex-format-field-delimiters): New function, functionality extracted from bibtex-format-entry. (bibtex-autokey-get-yearfield-digits): New function, functionality extracted from bibtex-autokey-get-yearfield. Completely reimplemented parsing of bibtex entries in order to avoid stack overflow in the regexp matcher if field contents become large. (bibtex-cfield, bibtex-name-in-cfield, bibtex-text-in-cfield, bibtex-field-string-part-not-braced, bibtex-field-string-part-no-inner-braces, bibtex-field-string-part-1-inner-brace, bibtex-field-string-part-2-inner-braces, bibtex-field-string-part-3-inner-braces, bibtex-field-string-braced, bibtex-field-string-quoted, bibtex-field-string, bibtex-field-string-or-const, bibtex-field-text, bibtex-field, bibtex-name-in-field, bibtex-text-in-field, bibtex-reference-infix, bibtex-string, bibtex-key-in-string, bibtex-text-in-string): Deleted as parsing is now performed by the following functions. (bibtex-parse-nested-braces, bibtex-parse-field-string-braced, bibtex-parse-quoted-string, bibtex-parse-field-string-quoted, bibtex-parse-field-string, bibtex-search-forward-field-string, bibtex-parse-association, bibtex-field-name-for-parsing, bibtex-parse-field-name, bibtex-parse-field-text, bibtex-parse-field, bibtex-search-forward-field, bibtex-search-backward-field, bibtex-start-of-field, bibtex-end-of-field, bibtex-start-of-name-in-field, bibtex-end-of-name-in-field, bibtex-start-of-text-in-field, bibtex-end-of-text-in-field, bibtex-parse-string-prefix, bibtex-parse-string-postfix, bibtex-parse-string, bibtex-search-forward-string, bibtex-search-backward-string, bibtex-start-of-string, bibtex-end-of-string, bibtex-start-of-reference-key-in-string, bibtex-end-of-reference-key-in-string, bibtex-start-of-text-in-string, bibtex-end-of-text-in-string): New functions for the parsing of bibtex entries. Instead of reporting the results of the parsing by match-beginning or match-end, these functions return data structures that hold the corresponding positions. (bibtex-enclosing-field): Changed to also report field boundaries by return values rather than by match-beginning or match-end. The following functions have been adapted to use the new parsing functions. (bibtex-skip-to-valid-entry, bibtex-search-reference, bibtex-enclosing-field, bibtex-format-entry, bibtex-autokey-get-namefield, bibtex-autokey-get-titlestring, bibtex-parse-keys, bibtex-complete, bibtex-pop, bibtex-mode, bibtex-print-help-message, bibtex-end-of-entry, bibtex-ispell-abstract, bibtex-validate, bibtex-next-field, bibtex-find-text, bibtex-remove-OPT-or-ALT, bibtex-remove-delimiters, bibtex-kill-field, bibtex-empty-field, bibtex-fill-entry): Use the new method for parsing. (bibtex-assoc-of-regexp, bibtex-skip-to-valid-entry, bibtex-map-entries, bibtex-flash-head, bibtex-enclosing-reference-maybe-empty-head, bibtex-format-entry, bibtex-autokey-change, bibtex-autokey-get-namefield, bibtex-autokey-get-names, bibtex-autokey-get-titlestring, bibtex-autokey-get-titles, bibtex-parse-keys, bibtex-pop, bibtex-mode, bibtex-end-of-entry, bibtex-ispell-abstract, bibtex-sort-buffer, bibtex-validate, bibtex-remove-OPT-or-ALT, bibtex-remove-delimiters, bibtex-kill-field, bibtex-kill-entry): Use let* instead of let in order to make the new binding of case-fold-search immediately visible. Copyright notice is up to date. Added constant 'bibtex-maintainer-salutation. (bibtex-mode): use with-temp-buffer rather than make-temp-name, use match-string-no-properties and eliminate a quadratic behavior when building bibtex-strings. (bibtex-reference-key): Accept string entries whose reference key contains upper case letters. (bibtex-reference-head): Allow entries to start with a new line. Hiding of entry bodies is not longer provided by bibtex.el directly. Instead the hideshow package can be used. Added a special bibtex entry to hs-special-modes-alist. (bibtex-hs-forward-sexp): Added for hideshow.el. (bibtex-entry-field-alist): Added booktitle field to proceedings entry type (for cross referencing). Thanks to Wagner Toledo Correa for the suggestion. Added `reftex-view-crossref-from-bibtex' to menu.
author Gerd Moellmann <gerd@gnu.org>
date Tue, 15 Feb 2000 09:38:09 +0000
parents f1f85d7d12c1
children 50df459c86d1
files lisp/textmodes/bibtex.el
diffstat 1 files changed, 987 insertions(+), 882 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/textmodes/bibtex.el	Tue Feb 15 09:35:31 2000 +0000
+++ b/lisp/textmodes/bibtex.el	Tue Feb 15 09:38:09 2000 +0000
@@ -365,8 +365,8 @@
                           ("note" "Remarks to be put at the end of the \\bibitem")))))
     ("Misc" . ((()
 		(("author" "Author1 [and Author2 ...] [and others]")
-                 ("title" "Title of the reference (BibTeX converts it to lowercase)")
-                 ("howpublished" "The way in which the reference was published")
+                 ("title" "Title of the work (BibTeX converts it to lowercase)")
+                 ("howpublished" "The way in which the work was published")
                  ("month" "Month of the publication as a string (remove braces)")
                  ("year" "Year of publication")
                  ("note" "Remarks to be put at the end of the \\bibitem")))))
@@ -400,13 +400,13 @@
                        ("month" "Month of the publication as a string (remove braces)")
                        ("note" "Remarks to be put at the end of the \\bibitem")))))
     ("Unpublished" . (((("author" "Author1 [and Author2 ...] [and others]")
-                        ("title" "Title of the unpublished reference (BibTeX converts it to lowercase)")
+                        ("title" "Title of the unpublished work (BibTeX converts it to lowercase)")
                         ("note" "Remarks to be put at the end of the \\bibitem"))
 		       (("month" "Month of the publication as a string (remove braces)")
                         ("year" "Year of publication")))))
     )
 
-  "Defines reference types and their associated fields.
+  "Defines entry types and their associated fields.
 List of
 (ENTRY-NAME (REQUIRED OPTIONAL) (CROSSREF-REQUIRED CROSSREF-OPTIONAL))
 triples.
@@ -930,16 +930,14 @@
 
 (defvar bibtex-strings nil)
 ;; Candidates for bibtex-complete-string. Initialized from
-;; bibtex-predefined-strings and bibtex-string-files. This variable is
-;; buffer-local.
+;; bibtex-predefined-strings and bibtex-string-files.
 (make-variable-buffer-local 'bibtex-strings)
 
-(defvar bibtex-keys nil)
+(defvar bibtex-reference-keys nil)
 ;; Candidates for TAB completion when entering a reference key using
 ;; the minibuffer. Also used for bibtex-complete-key. Initialized in
-;; bibtex-mode and updated for each new entry. This variable is
-;; buffer-local.
-(make-variable-buffer-local 'bibtex-keys)
+;; bibtex-mode and updated for each new entry.
+(make-variable-buffer-local 'bibtex-reference-keys)
 
 (defvar bibtex-buffer-last-parsed-tick nil)
 ;; Remembers the value returned by buffer-modified-tick when buffer
@@ -970,182 +968,354 @@
 (defvar bibtex-reformat-previous-options nil)
 ;; Used to store the last reformat options given
 
-(defvar bibtex-reformat-previous-labels nil)
-;; Used to store the last reformat label option given
+(defvar bibtex-reformat-previous-reference-keys nil)
+;; Used to store the last reformat reference keys option given
 
 
 ;; Functions to Parse the BibTeX Entries
 
-(defun bibtex-cfield (name text)
-  ;; Create a regexp for a BibTeX field of name NAME and text TEXT.
-  (concat ",[ \t\n]*\\("
-	  name
-	  "\\)[ \t\n]*=[ \t\n]*\\("
-	  text
-	  "\\)"))
-(defconst bibtex-name-in-cfield 1)
-;; The regexp subexpression number of the name part in bibtex-cfield.
-
-(defconst bibtex-text-in-cfield 2)
-;; The regexp subexpression number of the text part in bibtex-cfield.
-
-(defconst bibtex-reference-type "@[^\"#%'(),={} \t\n0-9][^\"#%'(),={} \t\n]*")
-;; Regexp defining the type part of a BibTeX reference entry (almost
-;; the same as bibtex-field-name)
+(defconst bibtex-field-name "[^\"#%'(),={} \t\n0-9][^\"#%'(),={} \t\n]*")
+;; Regexp defining the name part of a BibTeX field.
+
+(defconst bibtex-entry-type (concat "@" bibtex-field-name))
+;; Regexp defining the type part of a BibTeX entry.
 
 (defconst bibtex-reference-key "[][a-zA-Z0-9.:;?!`'/*@+=|()<>&_^$-]+")
-;; Regexp defining the label part of a BibTeX reference entry
-
-(defconst bibtex-field-name "[^\"#%'(),={} \t\n0-9][^\"#%'(),={} \t\n]*")
-;; Regexp defining the name part of a BibTeX field (almost the same as
-;; bibtex-reference-type)
-
-(defconst bibtex-field-const "[][a-z0-9.:;?!`'/*@+=|<>&_^$-]+")
+;; Regexp defining the reference key part of a BibTeX entry
+
+(defun bibtex-parse-nested-braces (nesting-level)
+  "*Starting on an opening brace, find the corresponding closing brace.
+When the function is called, NESTING-LEVEL has to be set to `0'."
+  (cond ((looking-at "{")
+	 (search-forward-regexp "{[^{}]*")
+	 (bibtex-parse-nested-braces (+ nesting-level 1)))
+	((looking-at "}")
+	 (forward-char 1)
+	 (if (= nesting-level 1)
+	     (point)
+	   (search-forward-regexp "[^{}]*")
+	   (bibtex-parse-nested-braces (- nesting-level 1))))
+	(t nil)))
+
+(defun bibtex-parse-field-string-braced ()
+  "*Parse a field string enclosed by braces.
+The field string has to be syntactically correct, which means that the number
+of opening and closing braces has to match.  If this is the case, a pair
+containing the start and end position of the field string is returned, nil
+otherwise."
+  (save-match-data
+    (let ((starting-point (point))
+	  (end-point nil))
+      (if (looking-at "{")
+	  (setq end-point (bibtex-parse-nested-braces 0)))
+      (goto-char starting-point)
+      (if end-point
+	  (cons starting-point end-point)
+	nil))))
+
+(defun bibtex-parse-quoted-string ()
+  "*Starting on an opening quote, find the corresponding closing quote."
+  (let ((rx (concat "\""
+		        "\\("
+			    "[^\"\\]"               ;; anything but quote or backslash
+			    "\\|"
+			    "\\(" 
+			        "\\\\\\(.\\|\n\\)"  ;; any backslash quoted character
+			    "\\)"
+			"\\)*"
+		    "\"")))
+    (if (looking-at rx)
+	(search-forward-regexp rx nil t)
+      nil)))
+
+(defun bibtex-parse-field-string-quoted ()
+  "*Parse a field string enclosed by quotes.
+If a syntactically correct string is found, a pair containing the start and
+end position of the field string is returned, nil otherwise."
+  (save-match-data
+    (let ((starting-point (point))
+	  (end-point nil))
+      (if (looking-at "\"")
+	  (setq end-point (bibtex-parse-quoted-string)))
+      (goto-char starting-point)
+      (if end-point 
+	  (cons starting-point end-point)
+	nil))))
+
+(defun bibtex-parse-field-string ()
+  "*Parse a field string enclosed by braces or quotes.
+If a syntactically correct string is found, a pair containing the start and
+end position of the field string is returned, nil otherwise."
+  (save-match-data
+    (let ((starting-point (point))
+	  (boundaries (or (bibtex-parse-field-string-braced)
+			  (bibtex-parse-field-string-quoted))))
+      (goto-char starting-point)
+      boundaries)))
+
+(defun bibtex-search-forward-field-string (bound)
+  "*Search forward to find a field string enclosed by braces or quotes.
+If a syntactically correct string is found, a pair containing the start and
+end position of the field string is returned, nil otherwise.  The search is
+delimited by BOUND."
+  (save-match-data
+    (let ((starting-point (point))
+	  (boundaries nil))
+      (while (and (not boundaries) (< (point) bound))
+	(if (search-forward-regexp "[{\"]" bound 'move)
+	    (progn
+	      (goto-char (match-beginning 0))
+	      (let ((temp-boundaries (or (bibtex-parse-field-string-braced)
+					 (bibtex-parse-field-string-quoted))))
+		(if (and temp-boundaries (<= (cdr temp-boundaries) bound))
+		    (setq boundaries temp-boundaries)
+		  (forward-char 1))))))
+      (goto-char starting-point)
+      boundaries)))
+
+(defun bibtex-parse-association (parse-lhs parse-rhs)
+  "*Parse a string of the format <left hand side = right-hand-side>.
+The functions PARSE-LHS and PARSE-RHS are used to parse the corresponding
+substrings.  These functions are expected to return nil if parsing is not
+successfull.  If both functions return non-nil, a pair containing the returned
+values of the functions PARSE-LHS and PARSE-RHSis returned."
+  (save-match-data
+    (let ((starting-point (point))
+	  (left (funcall parse-lhs))
+	  (right nil))
+      (if (and left (looking-at "[ \t\n]*=[ \t\n]*"))
+	  (progn
+	    (goto-char (match-end 0))
+	    (setq right (funcall parse-rhs))))
+      (goto-char starting-point)
+      (if (and left right)
+	  (cons left right)
+	nil))))
+
+(defvar bibtex-field-name-for-parsing nil)
+;; Temporary variable storing the name string to be parsed by the callback
+;; function bibtex-parse-field-name.
+(make-variable-buffer-local 'bibtex-field-name-for-parsing)
+
+(defun bibtex-parse-field-name ()
+  "*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."
+  (if (looking-at ",[ \t\n]*")
+      (let ((start (point)))
+	(goto-char (match-end 0))
+	(if (looking-at bibtex-field-name-for-parsing)
+	    (let ((boundaries (list start (match-beginning 0) (match-end 0))))
+	      (goto-char (match-end 0))
+	      boundaries)))))
+
+(defconst bibtex-field-const "[][a-zA-Z0-9.:;?!`'/*@+=|<>&_^$-]+")
 ;; Regexp defining a bibtex field constant
 
-(defconst bibtex-field-string-part-not-braced
-  "[^{}]")
-;; Match field string part without braces
-
-(defconst bibtex-field-string-part-no-inner-braces
-  (concat
-   "{"
-   bibtex-field-string-part-not-braced "*"
-   "}"))
-;; Match field string part with no inner braces
-
-(defconst bibtex-field-string-part-1-inner-brace
-  (concat
-   "{"
-   "\\("
-     bibtex-field-string-part-not-braced
-     "\\|"
-     "\\(" bibtex-field-string-part-no-inner-braces "\\)"
-   "\\)*"
-   "}"))
-;; Match field string part with at most 1 inner brace
-
-(defconst bibtex-field-string-part-2-inner-braces
-  (concat
-   "{"
-   "\\("
-     bibtex-field-string-part-not-braced
-     "\\|"
-     "\\(" bibtex-field-string-part-1-inner-brace "\\)"
-   "\\)*"
-   "}"))
-;; Match field string part with at most 2 inner braces
-
-(defconst bibtex-field-string-part-3-inner-braces
-  (concat
-   "{"
-   "\\("
-     bibtex-field-string-part-not-braced
-     "\\|"
-     "\\(" bibtex-field-string-part-2-inner-braces "\\)"
-   "\\)*"
-   "}"))
-;; Match field string part with at most 3 inner braces
-
-(defconst bibtex-field-string-braced
-  bibtex-field-string-part-3-inner-braces)
-;; Match braced field string with inner nesting level of braces at most 3
-
-(defconst bibtex-field-string-quoted
-  (concat
-   "\""
-   "\\("
-     "[^\"\\]"      ;; every character except quote or backslash
-     "\\|"
-;;     "\\(" "\"[a-z-]" "\\)"  ;; a quote followed by a letter or dash
-;;     "\\|"
-;; last two lines commented out until lines like
-;;   author = "Stefan Sch"of"
-;; are supported by BibTeX
-     "\\(" "\\\\\\(.\\|\n\\)"  "\\)" ;; a backslash followed by any character
-   "\\)*"
-   "\""))
-;; Match quoted field string
-
-(defconst bibtex-field-string
-  (concat
-   "\\(" bibtex-field-string-braced "\\)"
-   "\\|"
-   "\\(" bibtex-field-string-quoted "\\)"))
-;; Match a braced or quoted string
-
-(defconst bibtex-field-string-or-const
-  (concat bibtex-field-const "\\|" bibtex-field-string))
-;; Match either bibtex-field-string or bibtex-field-const.
-
-(defconst bibtex-field-text
-  (concat
-    "\\(" bibtex-field-string-or-const "\\)"
-    "\\([ \t\n]+#[ \t\n]+\\(" bibtex-field-string-or-const "\\)\\)*"))
-;; Regexp defining the text part of a BibTeX field: either a string,
-;; or an empty string, or a constant followed by one or more # /
-;; constant pairs.
-
-(defconst bibtex-field
-  (bibtex-cfield bibtex-field-name bibtex-field-text))
-;; Regexp defining the format of a BibTeX field.
-
-(defconst bibtex-name-in-field bibtex-name-in-cfield)
-;; The regexp subexpression number of the name part in BibTeX-field.
-
-(defconst bibtex-text-in-field bibtex-text-in-cfield)
-;; The regexp subexpression number of the text part in BibTeX-field.
-
-(defconst bibtex-reference-head
+(defun bibtex-parse-field-text ()
+  "*Parse the text part of a BibTeX field.
+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."
+  (let ((starting-point (point))
+	(end-point nil)
+	(failure nil))
+    (while (and (not end-point) (not failure))
+      (if (looking-at bibtex-field-const)
+	  (goto-char (match-end 0))
+	(let ((boundaries (bibtex-parse-field-string)))
+	  (if boundaries
+	      (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)
+      nil)))
+
+(defun bibtex-parse-field (name)
+  "*Parse a BibTeX field of regexp NAME.
+If a syntactically correct field is found, a pair containing the boundaries of
+the name and text parts of the field is returned."
+  (setq bibtex-field-name-for-parsing name)
+  (bibtex-parse-association 'bibtex-parse-field-name
+			    'bibtex-parse-field-text))
+
+(defun bibtex-search-forward-field (name bound)
+  "*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
+BOUND."
+  (save-match-data
+    (setq bibtex-field-name-for-parsing name)
+    (let ((starting-point (point))
+	  (boundaries nil))
+      (while (and (not boundaries) 
+		  (< (point) bound)
+		  (search-forward "," bound t))
+	(goto-char (match-beginning 0))
+	(let ((temp-boundaries 
+	       (bibtex-parse-association 'bibtex-parse-field-name
+					 'bibtex-parse-field-text)))
+	  (if (and temp-boundaries (<= (cdr (cdr temp-boundaries)) bound))
+	      (setq boundaries temp-boundaries)
+	    (forward-char 1))))
+      (goto-char starting-point)
+      boundaries)))
+
+(defun bibtex-search-backward-field (name bound)
+  "*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
+BOUND."
+  (save-match-data
+    (setq bibtex-field-name-for-parsing name)
+    (let ((starting-point (point))
+	  (boundaries nil))
+      (while (and (not boundaries)
+		  (>= (point) bound)
+		  (search-backward "," bound t))
+	(let ((temp-boundaries 
+	       (bibtex-parse-association 'bibtex-parse-field-name
+					 'bibtex-parse-field-text)))
+	  (if temp-boundaries
+	      (setq boundaries temp-boundaries))))
+      (goto-char starting-point)
+      boundaries)))
+
+(defun bibtex-start-of-field (bounds)
+  (car (car bounds)))
+(defun bibtex-end-of-field (bounds)
+  (cdr (cdr bounds)))
+(defun bibtex-start-of-name-in-field (bounds)
+  (car (cdr (car bounds))))
+(defun bibtex-end-of-name-in-field (bounds)
+  (car (cdr (cdr (car bounds)))))
+(defun bibtex-start-of-text-in-field (bounds)
+  (car (cdr bounds)))
+(defun bibtex-end-of-text-in-field (bounds)
+  (cdr (cdr bounds)))
+
+(defun bibtex-parse-string-prefix ()
+  "*Parse the prefix part of a bibtex string, including the reference key.
+If the string prefix is found, return a triple consisting of the position of
+the very first character of the match, the actual starting position of the
+reference key and the end position of the match."
+  (let* ((case-fold-search t))
+    (if (looking-at "^[ \t]*@string[ \t\n]*[({][ \t\n]*")
+	(let ((start (point)))
+	  (goto-char (match-end 0))
+	  (if (looking-at bibtex-reference-key)
+	      (let ((boundaries (list start (match-beginning 0) (match-end 0))))
+		(goto-char (match-end 0))
+		boundaries))))))
+
+(defun bibtex-parse-string-postfix ()
+  "*Parse the postfix part of a bibtex string, 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."
+  (let* ((case-fold-search t)
+	 (text-boundaries (bibtex-parse-field-text)))
+    (if text-boundaries
+	(progn
+	  (goto-char (cdr text-boundaries))
+	  (if (looking-at "[ \t\n]*[})]")
+	      (let ((boundaries (list (car text-boundaries) 
+				      (cdr text-boundaries)
+				      (match-end 0))))
+		(goto-char (match-end 0))
+		boundaries))))))
+
+(defun bibtex-parse-string ()
+  "*Parse 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 entry is returned."
+  (bibtex-parse-association 'bibtex-parse-string-prefix
+			    'bibtex-parse-string-postfix))
+
+(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."
+  (save-match-data
+    (let* ((case-fold-search t)
+	   (starting-point (point))
+	   (boundaries nil))
+      (while (and (not boundaries) 
+		  (search-forward-regexp 
+		   "^[ \t]*@string[ \t\n]*[({][ \t\n]*" nil t))
+	(goto-char (match-beginning 0))
+	(let ((temp-boundaries (bibtex-parse-string)))
+	  (if temp-boundaries
+	      (setq boundaries temp-boundaries)
+	    (forward-char 1))))
+      (goto-char starting-point)
+      boundaries)))
+
+(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."
+  (save-match-data
+    (let* ((case-fold-search t)
+	   (starting-point (point))
+	   (boundaries nil))
+      (while (and (not boundaries)
+		  (search-backward-regexp 
+		   "^[ \t]*@string[ \t\n]*[({][ \t\n]*" nil t))
+	(goto-char (match-beginning 0))
+	(let ((temp-boundaries (bibtex-parse-string)))
+	  (if temp-boundaries
+	      (setq boundaries temp-boundaries))))
+      (goto-char starting-point)
+      boundaries)))
+
+(defun bibtex-end-of-string (bounds)
+  (car (cdr (cdr (cdr bounds)))))
+(defun bibtex-start-of-reference-key-in-string (bounds)
+  (car (cdr (car bounds))))
+(defun bibtex-end-of-reference-key-in-string (bounds)
+  (car (cdr (cdr (car bounds)))))
+(defun bibtex-start-of-text-in-string (bounds)
+  (car (cdr bounds)))
+(defun bibtex-end-of-text-in-string (bounds)
+  (car (cdr (cdr bounds))))
+
+(defconst bibtex-entry-head
   (concat "^[ \t]*\\("
-	  bibtex-reference-type
+	  bibtex-entry-type
 	  "\\)[ \t]*[({][ \t\n]*\\("
 	  bibtex-reference-key
 	  "\\)"))
-;; Regexp defining format of the header line of a BibTeX reference
-;; entry.
-
-(defconst bibtex-reference-maybe-empty-head
-  (concat bibtex-reference-head "?"))
+;; Regexp defining format of the header line of a BibTeX entry.
+
+(defconst bibtex-entry-maybe-empty-head
+  (concat bibtex-entry-head "?"))
 ;; Regexp defining format of the header line of a maybe empty
-;; BibTeX reference entry (without reference key).
+;; BibTeX entry (possibly without reference key).
 
 (defconst bibtex-type-in-head 1)
 ;; The regexp subexpression number of the type part in
-;; bibtex-reference-head.
+;; bibtex-entry-head.
 
 (defconst bibtex-key-in-head 2)
 ;; The regexp subexpression number of the key part in
-;; bibtex-reference-head.
-
-(defconst bibtex-reference-infix (concat "[ \t\n]*" bibtex-field))
-;; Regexp defining the (repeatable) infix of a bibtex reference
-
-(defconst bibtex-reference-postfix "[ \t\n]*,?[ \t\n]*[})]")
-;; Regexp defining the postfix of a bibtex reference
-
-(defconst bibtex-key-in-reference bibtex-key-in-head)
-;; The regexp subexpression number of the key part in
-;; bibtex-reference.
-
-(defconst bibtex-string
-  (concat "^[ \t]*@string[ \t\n]*[({][ \t\n]*\\("
-	  bibtex-reference-key
-	  "\\)[ \t\n]*=[ \t\n]*\\("
-	  bibtex-field-text
-	  "\\)[ \t\n]*[})]"))
-;; Regexp defining the format of a BibTeX string entry.
-
-(defconst bibtex-key-in-string 1)
-;; The regexp subexpression of the name part in bibtex-string.
-
-(defconst bibtex-text-in-string 2)
-;; The regexp subexpression of the text part in bibtex-string.
+;; bibtex-entry-head.
+
+(defconst bibtex-entry-postfix "[ \t\n]*,?[ \t\n]*[})]")
+;; Regexp defining the postfix of a bibtex entry
+
+(defconst bibtex-key-in-entry bibtex-key-in-head)
+;; The regexp subexpression number of the key part in a bibtex entry.
 
 (defvar bibtex-font-lock-keywords
   (list
-   ;; reference type and reference label
-   (list bibtex-reference-maybe-empty-head
+   ;; 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))
    ;; comments
@@ -1162,6 +1332,7 @@
    "*Default expressions to highlight in BibTeX mode."))
 ;; now all needed patterns are defined
 
+
 
 ;; Helper Functions
 
@@ -1180,7 +1351,7 @@
   ;; 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)
+  (let* (case-fold-search)
     (while
         (and list (not (string-match (concat "^" (car list) "$") string)))
       (setq list (cdr list)))
@@ -1190,7 +1361,7 @@
   ;; Return non-nil if STRING is exactly matched by the car of an
   ;; element of LIST (case ignored). The value is actually the element
   ;; of LIST whose car matches STRING.
-  (let ((case-fold-search t))
+  (let* ((case-fold-search t))
     (while
         (and alist
              (not (string-match (concat "^" (car (car alist)) "$") string)))
@@ -1204,17 +1375,17 @@
   ;; 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.
-  (let ((case-fold-search t)
-        (valid-bibtex-entry
-         (concat
-          "@[ \t]*\\("
-          (mapconcat
-           (lambda (type)
-             (concat "\\(" (car type) "\\)"))
-           bibtex-entry-field-alist
-           "\\|")
-          "\\)"))
-        found)
+  (let* ((case-fold-search t)
+	 (valid-bibtex-entry
+	  (concat
+	   "@[ \t]*\\("
+	   (mapconcat
+	    (lambda (type)
+	      (concat "\\(" (car type) "\\)"))
+	    bibtex-entry-field-alist
+	    "\\|")
+	   "\\)"))
+	 found)
     (while (and (not found)
                 (not (if backward
                          (bobp)
@@ -1223,11 +1394,11 @@
         (cond
          ((looking-at valid-bibtex-entry)
           (if (and
-               (bibtex-search-reference nil nil t)
+               (bibtex-search-entry nil nil t)
                (equal (match-beginning 0) pnt))
               (setq found t)))
          ((and (not bibtex-sort-ignore-string-entries)
-               (looking-at bibtex-string))
+               (bibtex-parse-string))
           (setq found t)))
         (if found
             (goto-char pnt)
@@ -1246,11 +1417,11 @@
   ;; of the entry, and with point 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))
+  (let* ((case-fold-search t))
     (bibtex-beginning-of-entry)
-    (while (re-search-forward bibtex-reference-maybe-empty-head nil t)
+    (while (re-search-forward bibtex-entry-maybe-empty-head nil t)
       (let ((pnt (point))
-            (reference-type
+            (entry-type
              (downcase (buffer-substring-no-properties
                         (1+ (match-beginning bibtex-type-in-head))
                         (match-end bibtex-type-in-head))))
@@ -1263,8 +1434,8 @@
         (if (or
              (and
               (not bibtex-sort-ignore-string-entries)
-              (string-equal "string" (downcase reference-type)))
-             (assoc-ignore-case reference-type bibtex-entry-field-alist))
+              (string-equal "string" (downcase entry-type)))
+             (assoc-ignore-case entry-type bibtex-entry-field-alist))
             (funcall fun reference-key))
         (goto-char pnt)
         (bibtex-end-of-entry)))))
@@ -1323,33 +1494,31 @@
       "}"
     ")"))
 
-(defun bibtex-search-reference
+(defun bibtex-search-entry
   (empty-head &optional bound noerror backward)
   ;; A helper function necessary since the failure stack size limit for
   ;; regexps was reduced in emacs 19.32.
-  ;; It searches for a BibTeX reference (maybe with an empty head if
+  ;; It searches for a BibTeX entry (maybe without a 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. After
   ;; call to this function MATCH-BEGINNING and MATCH-END functions are
-  ;; defined, but only for the head part of the reference (especially
+  ;; defined, but only for the head part of the entry (especially
   ;; (match-end 0) just gives the end of the head part).
   (let ((pnt (point))
         (prefix (if empty-head
-                    bibtex-reference-maybe-empty-head
-                  bibtex-reference-head))
-        (infix bibtex-reference-infix)
-        (postfix bibtex-reference-postfix))
+                    bibtex-entry-maybe-empty-head
+                  bibtex-entry-head)))
     (if backward
         (let (found)
           (while (and (not found)
                       (re-search-backward prefix bound noerror))
-            (setq found (bibtex-search-reference empty-head pnt t)))
+            (setq found (bibtex-search-entry empty-head pnt t)))
           (if found
               (goto-char (match-beginning 0))
             (if (equal noerror nil)
                 ;; yell
-                (error "Search of BibTeX reference failed"))
+                (error "Search of BibTeX entry failed"))
             (if (equal noerror t)
                 ;; don't move
                 (goto-char pnt))
@@ -1368,20 +1537,29 @@
                      ;; entry opened with parenthesis
                      ")"
                    "}")))
-            (while (and
-                    (looking-at infix)
-                    (<= (match-end 0) limit))
-              (goto-char (match-end 0)))
+	    (let ((infix-start (point))
+		  (finished nil))
+	      (while (not finished)
+		(if (and (looking-at "[ \t\n]*")
+			 (<= (match-end 0) limit))
+		    (goto-char (match-end 0)))
+		(let ((bounds (bibtex-parse-field bibtex-field-name)))
+		  (if (and bounds (<= (bibtex-end-of-field bounds) limit))
+		      (progn
+			(goto-char (bibtex-end-of-field bounds))
+			(setq infix-start (point)))
+		    (goto-char infix-start)
+		    (setq finished t)))))
             ;; This matches the infix* part. The AND construction assures
             ;; that BOUND is respected.
-            (if (and (looking-at postfix)
+            (if (and (looking-at bibtex-entry-postfix)
                      (string-equal
                       (buffer-substring-no-properties
                        (1- (match-end 0)) (match-end 0))
                       entry-closer)
                      (<= (match-end 0) limit))
                 (progn
-                  (re-search-forward postfix)
+                  (re-search-forward bibtex-entry-postfix)
                   (setq found t)))))
         (if found
             (progn
@@ -1390,19 +1568,19 @@
               (point))
           (if (equal noerror nil)
               ;; yell
-              (error "Search of BibTeX reference failed"))
+              (error "Search of BibTeX entry failed"))
           (if (equal noerror t)
               ;; don't move
               (goto-char pnt))
           nil)))))
 
 (defun bibtex-flash-head ()
-  ;; Flash at BibTeX reference head before point, if exists.
-  (let ((case-fold-search t)
-        flash)
-    (cond ((re-search-backward bibtex-reference-head nil t)
+  ;; Flash at BibTeX entry head before point, if exists.
+  (let* ((case-fold-search t)
+	 flash)
+    (cond ((re-search-backward bibtex-entry-head nil t)
 	   (goto-char (match-beginning bibtex-type-in-head))
-	   (setq flash (match-end bibtex-key-in-reference)))
+	   (setq flash (match-end bibtex-key-in-entry)))
 	  (t
 	   (end-of-line)
 	   (skip-chars-backward " \t")
@@ -1468,47 +1646,36 @@
   ;; field. Use match-beginning and match-end to parse the field. If
   ;; NOERR is non-nil, no error is signalled. In this case, t is
   ;; returned on success, nil otherwise.
-  (let ((case-fold-search t)
-        (old-point (point))
-        (boe (bibtex-beginning-of-entry))
-        (success t))
+  (let* ((case-fold-search t)
+	 (old-point (point))
+	 (boe (bibtex-beginning-of-entry)))
     (goto-char old-point)
-    (if (not (re-search-backward
-              (bibtex-cfield bibtex-field-name "")
-              boe t))
-        ;; Search possible beginning of field
-        (progn
-          (goto-char old-point)
-          (if noerr
-              (setq success nil)
-            (error "Can't find enclosing BibTeX field")))
-      (if (or (not (re-search-forward bibtex-field nil t))
-              (< (match-end 0) old-point)
-              (> (match-beginning 0) old-point))
-          (progn
-            (goto-char old-point)
-            (if noerr
-                (setq success nil)
-              (error "Can't find enclosing BibTeX field")))))
-    success))
-
-(defun bibtex-enclosing-reference-maybe-empty-head ()
-  ;; Search for BibTeX reference enclosing point. Point moves to
-  ;; end of reference. Beginning (but not end) of reference is given
+    (let ((bounds (bibtex-search-backward-field bibtex-field-name boe)))
+      (if (and bounds
+	       (<= (bibtex-start-of-field bounds) old-point)
+	       (>= (bibtex-end-of-field bounds) old-point))
+	  bounds
+	(if noerr
+	    nil
+	  (error "Can't find enclosing BibTeX field"))))))
+
+(defun bibtex-enclosing-entry-maybe-empty-head ()
+  ;; Search for BibTeX entry enclosing point. Point moves to
+  ;; end of entry. Beginning (but not end) of entry is given
   ;; by (match-beginning 0).
-  (let ((case-fold-search t)
-        (old-point (point)))
+  (let* ((case-fold-search t)
+	 (old-point (point)))
     (if (not
          (re-search-backward
-          bibtex-reference-maybe-empty-head nil t))
+          bibtex-entry-maybe-empty-head nil t))
         (progn
-          (error "Can't find enclosing BibTeX reference")
+          (error "Can't find enclosing BibTeX entry")
           (goto-char old-point)))
     (goto-char (match-beginning bibtex-type-in-head))
     (if (not
-         (bibtex-search-reference t nil t))
+         (bibtex-search-entry t nil t))
         (progn
-          (error "Can't find enclosing BibTeX reference")
+          (error "Can't find enclosing BibTeX entry")
           (goto-char old-point)))))
 
 (defun bibtex-insert-current-kill (n)
@@ -1545,57 +1712,79 @@
          "Unknown tag field: %s.  Please submit a bug report"
          bibtex-last-kill-command))))))
 
+(defun bibtex-format-field-delimiters (start stop)
+  "*Replaces delimiters for field strings between START and STOP.
+If the current delimiters equal the new delimiters, the buffer is not
+changed."
+  (goto-char start)
+  (let ((boundaries (bibtex-search-forward-field-string stop)))
+    (while boundaries
+      (goto-char (car boundaries))
+      (if (not (looking-at (bibtex-field-left-delimiter)))
+	  (progn
+	    (delete-char 1)
+	    (insert (bibtex-field-left-delimiter))))
+      (goto-char (- (cdr boundaries) 1))
+      (if (not (looking-at (bibtex-field-right-delimiter)))
+	  (progn
+	    (delete-char 1)
+	    (insert (bibtex-field-right-delimiter))))
+      (setq boundaries (bibtex-search-forward-field-string stop)))))
+
 (defun bibtex-format-entry ()
   ;; Helper function for bibtex-clean-entry. Formats current entry
   ;; according to variable bibtex-entry-format.
-  (let ((case-fold-search t)
-        (beg (point))
-        (start (bibtex-beginning-of-entry))
-        crossref-there
-        alternatives-there
-        non-empty-alternative)
+  (let* ((case-fold-search t)
+	 (beg (point))
+	 (start (bibtex-beginning-of-entry))
+	 crossref-there
+	 alternatives-there
+	 non-empty-alternative)
     (let ((end (copy-marker (bibtex-end-of-entry))))
       (if (equal start (marker-position end))
           (error "Not on a known BibTeX entry")
         (goto-char start)
-        (while (re-search-forward bibtex-field end t)
-          ;; determine if reference has crossref entry and if at least
-          ;; one alternative is non-empty
-          (let ((begin-name (match-beginning bibtex-name-in-field))
-                (end-name (match-end bibtex-name-in-field))
-                (begin-text (match-beginning bibtex-text-in-field))
-                (end-text (match-end bibtex-text-in-field)))
-            (goto-char begin-name)
-            (if (looking-at "ALT")
-                (progn
-                  (setq alternatives-there t)
-                  (goto-char begin-text)
-                  (if (not (looking-at "\\(\"\"\\)\\|\\({}\\)"))
-                      (setq non-empty-alternative t))))
-            (if (string-match
-                 "\\(OPT\\)?crossref"
-                 (buffer-substring-no-properties begin-name end-name))
-                (progn
-                  (setq
-                   crossref-there
-                   (buffer-substring-no-properties
-                    (1+ begin-text) (1- end-text)))
-                  (if (equal crossref-there "")
-                      (setq crossref-there nil))))))
+	(let ((bounds (bibtex-search-forward-field bibtex-field-name end)))
+	  (while bounds
+	    ;; determine if entry has crossref field and if at least
+	    ;; one alternative is non-empty
+	    (let ((begin-name (bibtex-start-of-name-in-field bounds))
+		  (end-name (bibtex-end-of-name-in-field bounds))
+		  (begin-text (bibtex-start-of-text-in-field bounds))
+		  (end-text (bibtex-end-of-text-in-field bounds)))
+	      (goto-char begin-name)
+	      (if (looking-at "ALT")
+		  (progn
+		    (setq alternatives-there t)
+		    (goto-char begin-text)
+		    (if (not (looking-at "\\(\"\"\\)\\|\\({}\\)"))
+			(setq non-empty-alternative t))))
+	      (if (string-match
+		   "\\(OPT\\)?crossref"
+		   (buffer-substring-no-properties begin-name end-name))
+		  (progn
+		    (setq
+		     crossref-there
+		     (buffer-substring-no-properties
+		      (1+ begin-text) (1- end-text)))
+		    (if (equal crossref-there "")
+			(setq crossref-there nil)))))
+	    (goto-char (bibtex-end-of-field bounds))
+	    (setq bounds (bibtex-search-forward-field bibtex-field-name end))))
         (if (and alternatives-there
                  (not non-empty-alternative))
             (progn
               (goto-char beg)
               (error "All alternatives are empty")))
         (goto-char start)
-        (re-search-forward bibtex-reference-type end)
+        (re-search-forward bibtex-entry-type end)
         (let* ((begin-type (1+ (match-beginning 0)))
                (end-type (match-end 0))
-               (reference-type
+               (entry-type
                 (downcase
                  (buffer-substring-no-properties begin-type end-type)))
                (entry-list
-                (assoc-ignore-case reference-type bibtex-entry-field-alist))
+                (assoc-ignore-case entry-type bibtex-entry-field-alist))
                (req (elt (elt entry-list 1) 0))
                (creq (elt (elt entry-list 2) 0))
                (format (if (equal bibtex-entry-format t)
@@ -1615,158 +1804,131 @@
                 (delete-char 1)
                 (insert (bibtex-entry-left-delimiter))))
           (goto-char start)
-          (while (re-search-forward bibtex-field end t)
-            (let* ((begin-field
-                    (copy-marker (match-beginning 0)))
-                   (end-field
-                    (copy-marker (match-end 0)))
-                   (begin-name
-                    (copy-marker (match-beginning bibtex-name-in-field)))
-                   (end-name
-                    (copy-marker (match-end bibtex-name-in-field)))
-                   (begin-text
-                    (copy-marker (match-beginning bibtex-text-in-field)))
-                   (end-text
-                    (copy-marker (match-end bibtex-text-in-field)))
-                   (field-name
-                    (buffer-substring-no-properties
-                     (if (string-match
-                          "^OPT\\|ALT$"
-                          (buffer-substring-no-properties
-                           begin-name (+ begin-name 3)))
-                         (+ begin-name 3)
-                       begin-name)
-                     end-name)))
-              (cond
-               ((and
-                 (memq 'opts-or-alts format)
-                 (progn (goto-char begin-name)
-                        (looking-at "OPT\\|ALT")))
-                (goto-char begin-text)
-                (if (looking-at "\\(\"\"\\)\\|\\({}\\)")
-                    ;; empty: delete whole field if really optional
-                    ;; (missing crossref handled) or complain
-                    (if (and
-                         (progn
-                           (goto-char begin-name)
-                           (looking-at "OPT"))
-                         (not crossref-there)
-                         (assoc-ignore-case field-name req))
-                        ;; field is not really optional
-                        (progn
-                          (goto-char begin-name)
-                          (bibtex-remove-OPT-or-ALT)
-                          (error
-                           "Mandatory field ``%s'' is empty" field-name))
-                      ;; field is optional
-                      (delete-region begin-field end-field))
-                  ;; otherwise: not empty, delete "OPT"
-                  (goto-char begin-name)
-                  (bibtex-remove-OPT-or-ALT)))
-               ((and
-                 (memq 'numerical-fields format)
-                 (progn
-                   (goto-char begin-text)
-                   (looking-at "\\(\"[0-9]+\"\\)\\|\\({[0-9]+}\\)")))
-                (goto-char end-text)
-                (delete-char -1)
-                (goto-char begin-text)
-                (delete-char 1))
-               (t
-                (if (memq 'delimiters format)
-                    (progn
-                      (goto-char begin-text)
-                      (while (and
-                              (<= (point) end-text)
-                              (re-search-forward
-                               bibtex-field-string-or-const end-text t))
-                        (let ((end (point)))
-                          (goto-char (match-beginning 0))
-                          (if (or
-                               (and
-                                (equal bibtex-field-delimiters 'double-quotes)
-                                (looking-at bibtex-field-string-braced))
-                               (and
-                                (equal bibtex-field-delimiters 'braces)
-                                (looking-at bibtex-field-string-quoted)))
-                              (progn
-                                (goto-char (match-end 0))
-                                (delete-backward-char 1)
-                                (insert (bibtex-field-right-delimiter))
-                                (goto-char (match-beginning 0))
-                                (delete-char 1)
-                                (insert (bibtex-field-left-delimiter))))
-                          (goto-char end)))))
-                (if (and
-                     (memq 'page-dashes format)
-                     (string-match "^\\(OPT\\)?pages$" (downcase field-name))
-                     (progn
-                       (goto-char begin-text)
-                       (looking-at
-                        "\\([\"{][0-9]+\\)[ \t\n]*--?[ \t\n]*\\([0-9]+[\"}]\\)")))
-                    (replace-match "\\1-\\2"))
-                (if (and
-                     (memq 'inherit-booktitle format)
-                     (equal (downcase field-name) "booktitle")
-                     (progn
-                       (goto-char begin-text)
-                       (looking-at "\\(\"\"\\)\\|\\({}\\)"))
-                     crossref-there
-                     (not (bibtex-find-entry-location crossref-there t)))
-                    ;; booktitle field empty and crossref entry found
-                    ;; --> insert title field of crossreferenced entry if there
-                    (let ((end-of-crefd-entry (bibtex-end-of-entry)))
-                      (bibtex-beginning-of-entry)
-                      (if (re-search-forward
-                           (bibtex-cfield "title" bibtex-field-text)
-                           end-of-crefd-entry t)
-                          (progn
-                            (goto-char begin-text)
-                            (forward-char)
-                            (insert
-                             (buffer-substring-no-properties
-                              (1+ (match-beginning bibtex-text-in-field))
-                              (1- (match-end bibtex-text-in-field))))))))
-                (if (progn
-                      (goto-char begin-text)
-                      (looking-at "\\(\"\"\\)\\|\\({}\\)"))
-                    ;; if empty field, complain
-                    (progn
-                      (forward-char)
-                      (if (or (and
-                               crossref-there
-                               (assoc-ignore-case
-                                field-name creq))
-                              (and
-                               (not crossref-there)
-                               (assoc-ignore-case
-                                field-name req)))
-                          (error
-                           "Mandatory field ``%s'' is empty" field-name))))
-                (if (memq 'unify-case format)
-                    (let* ((fl
-                            (car (cdr (assoc-ignore-case
-                                       reference-type
-                                       bibtex-entry-field-alist))))
-                           (field-list
-                            (append
-                             (elt fl 0)
-                             (elt fl 1)
-                             bibtex-user-optional-fields))
-                           (new-field-name
-                            (car
-                             (assoc-ignore-case field-name field-list))))
-                      (goto-char begin-name)
-                      (if new-field-name
-                          (progn
-                            (delete-region begin-name end-name)
-                            (insert new-field-name))
-                        (downcase-region begin-name end-name))))
-                (setq field-done t)))
-              (if (not field-done)
-                  (goto-char begin-field)
-                (setq field-done nil)
-                (goto-char end-field))))
+          (let ((bounds (bibtex-search-forward-field bibtex-field-name end)))
+	    (while bounds
+	      (let* ((begin-field (copy-marker (bibtex-start-of-field bounds)))
+		     (end-field (copy-marker (bibtex-end-of-field bounds)))
+		     (begin-name (copy-marker (bibtex-start-of-name-in-field bounds)))
+		     (end-name (copy-marker (bibtex-end-of-name-in-field bounds)))
+		     (begin-text (copy-marker (bibtex-start-of-text-in-field bounds)))
+		     (end-text (copy-marker (bibtex-end-of-text-in-field bounds)))
+		     (field-name
+		      (buffer-substring-no-properties
+		       (if (string-match
+			    "^\\(OPT\\)\\|\\(ALT\\)$"
+			    (buffer-substring-no-properties
+			     begin-name (+ begin-name 3)))
+			   (+ begin-name 3)
+			 begin-name)
+		       end-name)))
+		(cond
+		 ((and
+		   (memq 'opts-or-alts format)
+		   (progn (goto-char begin-name)
+			  (looking-at "OPT\\|ALT")))
+		  (goto-char begin-text)
+		  (if (looking-at "\\(\"\"\\)\\|\\({}\\)")
+		      ;; empty: delete whole field if really optional
+		      ;; (missing crossref handled) or complain
+		      (if (and
+			   (progn
+			     (goto-char begin-name)
+			     (looking-at "OPT"))
+			   (not crossref-there)
+			   (assoc-ignore-case field-name req))
+			  ;; field is not really optional
+			  (progn
+			    (goto-char begin-name)
+			    (bibtex-remove-OPT-or-ALT)
+			    (error
+			     "Mandatory field ``%s'' is empty" field-name))
+			;; field is optional
+			(delete-region begin-field end-field))
+		    ;; otherwise: not empty, delete "OPT"
+		    (goto-char begin-name)
+		    (bibtex-remove-OPT-or-ALT)))
+		 ((and
+		   (memq 'numerical-fields format)
+		   (progn
+		     (goto-char begin-text)
+		     (looking-at "\\(\"[0-9]+\"\\)\\|\\({[0-9]+}\\)")))
+		  (goto-char end-text)
+		  (delete-char -1)
+		  (goto-char begin-text)
+		  (delete-char 1))
+		 (t
+		  (if (memq 'delimiters format)
+		      (bibtex-format-field-delimiters begin-text end-text))
+		  (if (and
+		       (memq 'page-dashes format)
+		       (string-match "^\\(OPT\\)?pages$" (downcase field-name))
+		       (progn
+			 (goto-char begin-text)
+			 (looking-at
+			  "\\([\"{][0-9]+\\)[ \t\n]*--?[ \t\n]*\\([0-9]+[\"}]\\)")))
+		      (replace-match "\\1-\\2"))
+		  (if (and
+		       (memq 'inherit-booktitle format)
+		       (equal (downcase field-name) "booktitle")
+		       (progn
+			 (goto-char begin-text)
+			 (looking-at "\\(\"\"\\)\\|\\({}\\)"))
+		       crossref-there
+		       (not (bibtex-find-entry-location crossref-there t)))
+		      ;; booktitle field empty and crossref entry found
+		      ;; --> insert title field of crossreferenced entry if there
+		      (let ((stop (bibtex-end-of-entry)))
+			(bibtex-beginning-of-entry)
+			(let ((bounds (bibtex-search-forward-field "title" stop)))
+			  (if bounds
+			      (progn
+				(goto-char begin-text)
+				(forward-char)
+				(insert
+				 (buffer-substring-no-properties
+				  (1+ (bibtex-start-of-text-in-field bounds))
+				  (1- (bibtex-end-of-text-in-field bounds)))))))))
+		  (if (progn
+			(goto-char begin-text)
+			(looking-at "\\(\"\"\\)\\|\\({}\\)"))
+		      ;; if empty field, complain
+		      (progn
+			(forward-char)
+			(if (or (and
+				 crossref-there
+				 (assoc-ignore-case
+				  field-name creq))
+				(and
+				 (not crossref-there)
+				 (assoc-ignore-case
+				  field-name req)))
+			    (error
+			     "Mandatory field ``%s'' is empty" field-name))))
+		  (if (memq 'unify-case format)
+		      (let* ((fl
+			      (car (cdr (assoc-ignore-case
+					 entry-type
+					 bibtex-entry-field-alist))))
+			     (field-list
+			      (append
+			       (elt fl 0)
+			       (elt fl 1)
+			       bibtex-user-optional-fields))
+			     (new-field-name
+			      (car
+			       (assoc-ignore-case field-name field-list))))
+			(goto-char begin-name)
+			(if new-field-name
+			    (progn
+			      (delete-region begin-name end-name)
+			      (insert new-field-name))
+			  (downcase-region begin-name end-name))))
+		  (setq field-done t)))
+		(if (not field-done)
+		    (goto-char begin-field)
+		  (setq field-done nil)
+		  (goto-char end-field)))
+	      (setq bounds (bibtex-search-forward-field bibtex-field-name end))))
           (if (looking-at (bibtex-field-right-delimiter))
               (forward-char))
           (if (memq 'last-comma format)
@@ -1792,11 +1954,11 @@
   ;; Returns a string where some regexps are changed according to
   ;; change-list. Every item of change-list is an (old-regexp
   ;; new-string) pair.
-  (let (case-fold-search
-        (return-string string)
-        (index 0)
-        (len (length change-list))
-        change-item)
+  (let* (case-fold-search
+	 (return-string string)
+	 (index 0)
+	 (len (length change-list))
+	 change-item)
     (while (< index len)
       (setq change-item (elt change-list index))
       (while (string-match (car change-item) return-string)
@@ -1831,21 +1993,21 @@
   ;; does some modifications based on `bibtex-autokey-name-change-strings'
   ;; and removes newlines unconditionally
   (goto-char min)
-  (let ((case-fold-search t))
-    (if (re-search-forward
-         (bibtex-cfield "\\(author\\)\\|\\(editor\\)" bibtex-field-text)
-         max t)
+  (let* ((case-fold-search t)
+	 (author-or-editor "\\(author\\)\\|\\(editor\\)")
+	 (bounds (bibtex-search-forward-field author-or-editor max)))
+    (if bounds
         (bibtex-autokey-change
          (buffer-substring-no-properties
-          (1+ (match-beginning (+ bibtex-text-in-cfield 2)))
-          (1- (match-end (+ bibtex-text-in-cfield 2))))
+          (1+ (bibtex-start-of-text-in-field bounds))
+          (1- (bibtex-end-of-text-in-field bounds)))
          (append bibtex-autokey-name-change-strings '(("\n" " "))))
       "")))
 
 (defun bibtex-autokey-get-names (namefield)
   ;; gathers all names in namefield into a list
-  (let ((case-fold-search t)
-        names)
+  (let* ((case-fold-search t)
+	 names)
     (while (not (equal namefield ""))
       (let (name)
         (if (string-match "[ \t\n]and[ \t\n]" namefield)
@@ -1911,75 +2073,64 @@
       bibtex-autokey-name-length))
    (bibtex-autokey-get-names namefield)))
 
-(defun bibtex-autokey-get-yearfield (min max)
-  ;; get year field from current or maybe crossreferenced entry
-  (let ((case-fold-search t))
-    (goto-char min)
-    (if (re-search-forward
-         (bibtex-cfield "year" bibtex-field-text) max t)
+(defun bibtex-autokey-get-yearfield-digits (max)
+  ;; get digit substring from year field.
+  (let ((bounds (bibtex-search-forward-field "year" max)))
+    (if bounds
 	(let ((year (buffer-substring-no-properties
-		     (match-beginning bibtex-text-in-cfield)
-		     (match-end bibtex-text-in-cfield))))
+		     (bibtex-start-of-text-in-field bounds)
+		     (bibtex-end-of-text-in-field bounds))))
 	  (string-match "[^0-9]*\\([0-9]+\\)" year)
 	  (substring year (match-beginning 1) (match-end 1)))
-      (if bibtex-autokey-year-use-crossref-entry
-          (let ((crossref-field
-                 (progn
-                   (goto-char min)
-                   (if (re-search-forward
-                        (bibtex-cfield
-                         "\\(OPT\\)?crossref" bibtex-field-text)
-                        max t)
-                       (buffer-substring-no-properties
-                        (1+
-                         (match-beginning (+ bibtex-text-in-cfield 1)))
-                        (1-
-                         (match-end (+ bibtex-text-in-cfield 1))))))))
-            (if (not (bibtex-find-entry-location crossref-field t))
-                (let ((end-of-crefd-entry (bibtex-end-of-entry)))
-                  (bibtex-beginning-of-entry)
-                  (if (re-search-forward
-                       (bibtex-cfield "year" "[0-9]+")
-                       end-of-crefd-entry t)
-                      (buffer-substring-no-properties
-                       (match-beginning bibtex-text-in-cfield)
-                       (match-end bibtex-text-in-cfield))
-                    ""))
-              ""))
-        ""))))
+      "")))
+
+(defun bibtex-autokey-get-yearfield (min max)
+  ;; get year field from current or maybe crossreferenced entry
+  (goto-char min)
+  (let* ((case-fold-search t)
+	 (year (bibtex-autokey-get-yearfield-digits max)))
+    (if (and (string= year "") bibtex-autokey-year-use-crossref-entry)
+	(let* ((bounds 
+		(bibtex-search-forward-field "\\(OPT\\)?crossref" max))
+	       (crossref-field
+		(if bounds
+		    (buffer-substring-no-properties
+		     (1+ (bibtex-start-of-text-in-field bounds))
+		     (1- (bibtex-end-of-text-in-field bounds))))))
+	  (if (not (bibtex-find-entry-location crossref-field t))
+	      (let ((stop (bibtex-end-of-entry)))
+		(bibtex-beginning-of-entry)
+		(bibtex-autokey-get-yearfield-digits stop))
+	    ""))
+      year)))
 
 (defun bibtex-autokey-get-titlestring (min max)
   ;; get title field contents up to a terminator
-  (let ((case-fold-search t))
-    (let ((titlefield
-           (progn
-             (goto-char min)
-             (if (re-search-forward
-                  (bibtex-cfield "title" bibtex-field-text) max t)
-                 (bibtex-autokey-change
-                  (buffer-substring-no-properties
-                   (1+ (match-beginning bibtex-text-in-cfield))
-                   (1- (match-end bibtex-text-in-cfield)))
-                  bibtex-autokey-titleword-change-strings)
-               "")))
-          (index 0)
-          (numberofitems
-           (length bibtex-autokey-title-terminators)))
-      (while (< index numberofitems)
-        (if (string-match
-             (elt bibtex-autokey-title-terminators index) titlefield)
-            (setq
-             titlefield (substring titlefield 0 (match-beginning 0))))
-        (setq index (1+ index)))
-      titlefield)))
+  (goto-char min)
+  (let* ((case-fold-search t)
+	 (bounds (bibtex-search-forward-field "title" max))
+	 (titlefield
+	  (if bounds
+	      (bibtex-autokey-change
+	       (buffer-substring-no-properties
+		(1+ (bibtex-start-of-text-in-field bounds))
+		(1- (bibtex-end-of-text-in-field bounds)))
+	       bibtex-autokey-titleword-change-strings)
+	    ""))
+	 (title-terminators bibtex-autokey-title-terminators))
+    (while (not (null title-terminators))
+      (if (string-match (car title-terminators) titlefield)
+	  (setq titlefield (substring titlefield 0 (match-beginning 0))))
+      (setq title-terminators (cdr title-terminators)))
+    titlefield))
 
 (defun bibtex-autokey-get-titles (titlestring)
   ;; gathers words from titlestring into a list. Ignores
   ;; specific words and uses only a specific amount of words.
-  (let (case-fold-search
-        titlewords
-        titlewords-extra
-        (counter 0))
+  (let* (case-fold-search
+	 titlewords
+	 titlewords-extra
+	 (counter 0))
     (while (and
             (not (equal titlestring ""))
             (or
@@ -2057,7 +2208,7 @@
     variable `bibtex-autokey-year-use-crossref-entry' is non-nil,
     use the year field of the crossreferenced entry instead.
  9. For the title part of the key change the contents of the
-    title field of the reference according to
+    title field of the entry according to
     `bibtex-autokey-titleword-change-strings' to the
     corresponding new one (see documentation of this variable for
     further detail).
@@ -2164,18 +2315,14 @@
     autokey))
 
 (defun bibtex-parse-keys (add verbose &optional abortable)
-  ;; Sets bibtex-keys to the keys used in the whole (possibly
+  ;; Sets bibtex-reference-keys to the keys used in the whole (possibly
   ;; restricted) buffer (either as entry keys or as crossref entries).
-  ;; If ADD is non-nil adds the new keys to bibtex-keys instead of
+  ;; If ADD is non-nil adds the new keys to bibtex-reference-keys instead of
   ;; simply resetting it. If VERBOSE is non-nil gives messages about
   ;; progress. If ABORTABLE is non-nil abort on user input.
   (if bibtex-maintain-sorted-entries
-      (let ((case-fold-search t)
-            (crossref-field
-             (bibtex-cfield
-              "crossref" (concat "[{\"]" bibtex-reference-key "[}\"]")))
-            (labels (if add
-                        bibtex-keys)))
+      (let* ((case-fold-search t)
+	     (reference-keys (if add bibtex-reference-keys)))
         (save-excursion
           (goto-char (point-min))
           (if verbose
@@ -2190,46 +2337,47 @@
                       (throw 'userkey t))
                   (if verbose
                       (bibtex-progress-message))
-                  (let (label
-                        label2)
+                  (let (reference-key
+                        xrefd-reference-key)
                     (cond
-                     ((looking-at bibtex-reference-head)
+                     ((looking-at bibtex-entry-head)
                       (setq
-                       label
+                       reference-key
                        (buffer-substring-no-properties
                         (match-beginning bibtex-key-in-head)
                         (match-end bibtex-key-in-head)))
                       (let ((p (point))
                             (m (bibtex-end-of-entry)))
                         (goto-char p)
-                        (if (re-search-forward crossref-field m t)
-                            (setq
-                             label2
-                             (buffer-substring-no-properties
-                              (1+ (match-beginning bibtex-text-in-cfield))
-                              (1- (match-end bibtex-text-in-cfield)))))
-                        (goto-char p)))
-                     ((looking-at bibtex-string)
-                      (setq
-                       label
-                       (buffer-substring-no-properties
-                        (match-beginning bibtex-key-in-string)
-                        (match-end bibtex-key-in-string)))))
+			(let ((bounds (bibtex-search-forward-field "crossref" m)))
+			  (if bounds
+			      (setq
+			       xrefd-reference-key
+			       (buffer-substring-no-properties
+				(1+ (bibtex-start-of-text-in-field bounds))
+				(1- (bibtex-end-of-text-in-field bounds))))))))
+                     ((bibtex-parse-string)
+		      (let ((bounds (bibtex-parse-string)))
+			(setq
+			 reference-key
+			 (buffer-substring-no-properties
+			  (bibtex-start-of-reference-key-in-string bounds)
+			  (bibtex-end-of-reference-key-in-string bounds))))))
                     (forward-char)
                     (bibtex-skip-to-valid-entry)
-                    (if (not (assoc label labels))
-                        (setq labels
-                              (cons (list label) labels)))
-                    (if (and label2
-                             (not (assoc label2 labels)))
-                        (setq labels
-                              (cons (list label2) labels))))))
+                    (if (not (assoc reference-key reference-keys))
+                        (setq reference-keys
+                              (cons (list reference-key) reference-keys)))
+                    (if (and xrefd-reference-key
+                             (not (assoc xrefd-reference-key reference-keys)))
+                        (setq reference-keys
+                              (cons (list xrefd-reference-key) reference-keys))))))
               ;; user has aborted by typing a key --> return nil
               nil
             ;; successful operation --> return t
             (setq
              bibtex-buffer-last-parsed-tick (buffer-modified-tick)
-             bibtex-keys labels)
+             bibtex-reference-keys reference-keys)
             (if verbose
                 (bibtex-progress-message 'done))
             t)))))
@@ -2273,15 +2421,15 @@
          (completions (copy-sequence string-list))
          (completion (save-excursion
                        (if complete-strings
-                           (while (re-search-backward
-                                   bibtex-string nil t)
-                             (setq completions
-                                   (cons
-                                    (list
-                                     (buffer-substring-no-properties
-                                      (match-beginning bibtex-key-in-string)
-                                      (match-end bibtex-key-in-string)))
-                                    completions))))
+                           (while (bibtex-search-backward-string)
+			     (let ((bounds (bibtex-search-backward-string)))
+			       (setq completions
+				     (cons
+				      (list
+				       (buffer-substring-no-properties
+					(bibtex-start-of-reference-key-in-string bounds)
+					(bibtex-end-of-reference-key-in-string bounds)))
+				      completions)))))
                        (setq completions
                              (sort completions
                                    (lambda(x y)
@@ -2294,13 +2442,11 @@
                ;; remove double-quotes or braces if field is no concatenation
                (save-excursion
                  (bibtex-inside-field)
-                 (bibtex-enclosing-field)
-                 (let ((end (match-end bibtex-text-in-field)))
-                   (goto-char (match-beginning bibtex-text-in-field))
-                   (if (and
-                        (looking-at bibtex-field-string)
-                        (equal (match-end 0) end))
-                       (bibtex-remove-delimiters))))))
+                 (let* ((bounds (bibtex-enclosing-field)))
+		   (goto-char (bibtex-start-of-text-in-field bounds))
+		   (let ((boundaries (bibtex-parse-field-string)))
+		     (if (and boundaries (equal (cdr boundaries) (bibtex-end-of-text-in-field bounds)))
+			 (bibtex-remove-delimiters)))))))
           ((not completion)
            (error "Can't find completion for \"%s\"" part-of-word))
           ((not (string= part-of-word completion))
@@ -2311,13 +2457,11 @@
                ;; remove double-quotes or braces if field is no concatenation
                (save-excursion
                  (bibtex-inside-field)
-                 (bibtex-enclosing-field)
-                 (let ((end (match-end bibtex-text-in-field)))
-                   (goto-char (match-beginning bibtex-text-in-field))
-                   (if (and
-                        (looking-at bibtex-field-string)
-                        (equal (match-end 0) end))
-                       (bibtex-remove-delimiters))))))
+		 (let* ((bounds (bibtex-enclosing-field)))
+		   (goto-char (bibtex-start-of-text-in-field bounds))
+		   (let ((boundaries (bibtex-parse-field-string)))
+		     (if (and boundaries (equal (cdr boundaries) (bibtex-end-of-text-in-field bounds)))
+			 (bibtex-remove-delimiters)))))))
           (t
            (message "Making completion list...")
            (let ((list (all-completions part-of-word completions)))
@@ -2338,31 +2482,27 @@
   (save-excursion
     ;; parse current field
     (bibtex-inside-field)
-    (bibtex-enclosing-field)
-    (let ((case-fold-search t)
-          (start-old-text (match-beginning bibtex-text-in-field))
-	  (stop-old-text  (match-end bibtex-text-in-field))
-	  (start-name (match-beginning bibtex-name-in-field))
-	  (stop-name (match-end bibtex-name-in-field))
-	  (new-text))
+    (let* ((case-fold-search t)
+	   (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))
+	   (new-text))
       (goto-char start-name)
       ;; construct regexp for field with same name as this one,
       ;; ignoring possible OPT's or ALT's
-      (let ((matching-entry
-	     (bibtex-cfield
+      (let* ((field-name
 	      (buffer-substring-no-properties
-               (if (looking-at "OPT\\|ALT")
-                   (+ (point) (length "OPT"))
-                 (point))
-               stop-name)
-	      bibtex-field-text)))
+	       (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
-	(cond ((eq last-command 'bibtex-pop)
-               t
-               )
+	(cond ((eq last-command 'bibtex-pop) t)
 	      (t
-	       (bibtex-enclosing-reference-maybe-empty-head)
+	       (bibtex-enclosing-entry-maybe-empty-head)
 	       (setq
                 bibtex-pop-previous-search-point (match-beginning 0)
                 bibtex-pop-next-search-point (point))))
@@ -2370,54 +2510,36 @@
             (goto-char bibtex-pop-previous-search-point)
           (goto-char bibtex-pop-next-search-point))
         ;; Now search for arg'th previous/next similar field
-	(cond
-         ((if (eq direction 'previous)
-              (re-search-backward matching-entry nil t arg)
-            (re-search-forward matching-entry nil t arg))
-          ;; Found a matching field. Remember boundaries.
-	  (setq bibtex-pop-previous-search-point (match-beginning 0))
-	  (setq bibtex-pop-next-search-point (match-end 0))
-          (setq new-text
-		(buffer-substring-no-properties
-                 (match-beginning bibtex-text-in-field)
-                 (match-end bibtex-text-in-field)))
-          ;; change delimiters, if any changes needed
-          (let ((start 0)
-                old-open
-                new-open
-                old-close
-                new-close)
-            (if (equal bibtex-field-delimiters 'braces)
-                (setq old-open ?\"
-                      new-open ?\{
-                      old-close ?\"
-                      new-close ?\})
-              (setq old-open ?\{
-                    new-open ?\"
-                    old-close ?\}
-                    new-close ?\"))
-            (while (string-match bibtex-field-string new-text start)
-              (let ((beg (match-beginning 0))
-                    (end (1- (match-end 0))))
-                (if (and
-                     (eq (aref new-text beg) old-open)
-                     (eq (aref new-text end) old-close))
-                    (progn
-                      (aset new-text beg new-open)
-                      (aset new-text end new-close))))
-              (setq start (match-end 0))))
-	  (bibtex-flash-head)
-          ;; Go back to where we started, delete old text, and pop new.
-	  (goto-char stop-old-text)
-	  (delete-region start-old-text stop-old-text)
-	  (insert new-text))
-	 (t
-          ;; search failed
-	  (error (concat "No "
-                         (if (eq direction 'previous)
-                             "previous"
-                           "next")
-                         " matching BibTeX field.")))))))
+	(let ((bounds nil)
+	      (failure nil))
+	  (while (and (not failure) (> arg 0))
+	    (cond ((eq direction 'previous)
+		   (setq bounds (bibtex-search-backward-field field-name (point-min)))
+		   (if bounds 
+		       (goto-char (bibtex-start-of-field bounds))
+		     (setq failure t)))
+		  ((eq direction 'next)
+		   (setq bounds (bibtex-search-forward-field field-name (point-max)))
+		   (if bounds 
+		       (goto-char (bibtex-end-of-field bounds))
+		     (setq failure t))))
+	    (setq arg (- arg 1)))
+	  (if failure
+	      (error (if (eq direction 'previous)
+			 "No previous matching BibTeX field."
+		       "No next matching BibTeX field."))
+	    ;; Found a matching field. Remember boundaries.
+	    (setq bibtex-pop-previous-search-point (bibtex-start-of-field bounds))
+	    (setq bibtex-pop-next-search-point (bibtex-end-of-field bounds))
+	    (setq new-text
+		  (buffer-substring-no-properties
+		   (bibtex-start-of-text-in-field bounds)
+		   (bibtex-end-of-text-in-field bounds)))
+	    (bibtex-flash-head)
+	    ;; Go back to where we started, delete old text, and pop new.
+	    (goto-char stop-old-text)
+	    (delete-region start-old-text stop-old-text)
+	    (insert new-text))))))
   (let (bibtex-help-message)
     (bibtex-find-text nil))
   (setq this-command 'bibtex-pop))
@@ -2537,20 +2659,7 @@
      (let* ((path (if bibtex-string-file-path
                       bibtex-string-file-path
                     "."))
-            (dirs
-             (mapcar
-              (lambda (dirname)  ;; strips off trailing slashes
-                (let ((len (length dirname)))
-                  (if (equal (elt dirname (1- len)) "/")
-                      (substring dirname 0 (1- (1- len)))
-                    dirname)))
-              (let (actdirs)
-                (while (string-match ":" path)
-                  (setq actdirs
-                        (append actdirs
-                                (list (substring path 0 (1- (match-end 0)))))
-                        path (substring path (match-end 0))))
-                (append actdirs (list path)))))
+            (dirs (split-string path ":+"))
             (filename (if (string-match "\.bib$" filename)
                           filename
                         (concat filename ".bib")))
@@ -2566,17 +2675,21 @@
          (setq item (1+ item)))
        (if (< item size)
            ;; file was found
-           (let ((case-fold-search t)
-                 (compl nil))
+           (let* ((case-fold-search t)
+		  (compl nil))
 	     (with-temp-buffer
 	       (insert-file-contents fullfilename)
 	       (goto-char (point-min))
-	       (while (re-search-forward bibtex-string nil t)
-		 (setq compl
-		       (cons (list (match-string-no-properties
-				    bibtex-key-in-string))
-			     compl))))
-             (setq bibtex-strings (append bibtex-strings (nreverse compl))))
+	       (let ((bounds (bibtex-search-forward-string)))
+		 (while bounds
+		   (setq compl
+			 (cons (list (buffer-substring-no-properties
+				      (bibtex-start-of-reference-key-in-string bounds)
+				      (bibtex-end-of-reference-key-in-string bounds)))
+			       compl))
+		   (goto-char (bibtex-end-of-string bounds))
+		   (setq bounds (bibtex-search-forward-string)))))
+	     (setq bibtex-strings (append bibtex-strings (nreverse compl))))
          (error
           "File %s not in paths defined by bibtex-string-file-path variable"
           filename))))
@@ -2624,7 +2737,7 @@
 	  (set-mark (bibtex-end-of-entry))
 	  (bibtex-beginning-of-entry)))
   (setq imenu-generic-expression
-	(list (list nil bibtex-reference-head bibtex-key-in-head)))
+	(list (list nil bibtex-entry-head bibtex-key-in-head)))
   (setq imenu-case-fold-search t)
   ;; XEmacs needs easy-menu-add, Emacs does not care
   (easy-menu-add bibtex-edit-menu)
@@ -2640,7 +2753,7 @@
         (let ((reporter-prompt-for-summary-p t))
           (reporter-submit-bug-report
            bibtex-maintainer-address
-           (concat "bibtex.el " bibtex-version)
+           "bibtex.el"
            (list
             'system-configuration
             'system-configuration-options
@@ -2695,7 +2808,7 @@
             'bibtex-autokey-year-title-separator
             'bibtex-autokey-edit-before-use
             'bibtex-autokey-before-presentation-function
-            ;; possible bugs regarding automatic labels
+            ;; possible bugs regarding automatic reference keys
             'bibtex-entry-field-alist
             ;; possible format error
             'bibtex-help-message
@@ -2708,7 +2821,8 @@
            nil nil
            (concat bibtex-maintainer-salutation "
 
-I want to report a bug on Emacs BibTeX mode " bibtex-version ".
+I want to report a bug on Emacs BibTeX mode.
+
 I've read the `Bugs' section in the `Emacs' info page, so I know how
 to make a clear and unambiguous report. I have started a fresh Emacs
 via `"invocation-name " --no-init-file --no-site-file', thereafter (in
@@ -2727,7 +2841,7 @@
                             bibtex-entry-field-alist
                             nil t nil 'bibtex-entry-type-history)))
 		 (list e-t)))
-  (if (not bibtex-keys)
+  (if (not bibtex-reference-keys)
       (bibtex-parse-keys nil t))
   (let* (required
          optional
@@ -2735,7 +2849,7 @@
           (if bibtex-maintain-sorted-entries
               (completing-read
                (format "%s key: " entry-type)
-               bibtex-keys nil nil nil 'bibtex-key-history)))
+               bibtex-reference-keys nil nil nil 'bibtex-key-history)))
          (e (assoc-ignore-case entry-type bibtex-entry-field-alist))
          (r-n-o (elt e 1))
          (c-ref (elt e 2)))
@@ -2782,34 +2896,29 @@
   (let* ((case-fold-search t)
          (pnt (point))
          (field-name
-          (progn
-            (condition-case errname
-                (bibtex-enclosing-field)
-              (search-failed
-               (goto-char pnt)
-               (error "Not on BibTeX field")))
-            (let ((mb (match-beginning bibtex-name-in-field))
-                  (me (match-end bibtex-name-in-field)))
-              (goto-char mb)
-              (buffer-substring-no-properties
-               (if (looking-at "OPT\\|ALT")
-                   (+ 3 mb)
-                 mb)
-               me))))
-         (reference-type
+	  (let* ((bounds (bibtex-enclosing-field))
+		 (mb (bibtex-start-of-name-in-field bounds))
+		 (me (bibtex-end-of-name-in-field bounds)))
+	    (goto-char mb)
+	    (buffer-substring-no-properties
+	     (if (looking-at "OPT\\|ALT")
+		 (+ 3 mb)
+	       mb)
+	     me)))
+         (entry-type
           (progn
             (re-search-backward
-             bibtex-reference-maybe-empty-head nil t)
+             bibtex-entry-maybe-empty-head nil t)
             (buffer-substring-no-properties
              (1+ (match-beginning bibtex-type-in-head))
              (match-end bibtex-type-in-head))))
          (entry-list
-          (assoc-ignore-case reference-type
+          (assoc-ignore-case entry-type
                                bibtex-entry-field-alist))
          (c-r-list (elt entry-list 2))
          (req-opt-list
           (if (and
-               (member reference-type bibtex-include-OPTcrossref)
+               (member entry-type bibtex-include-OPTcrossref)
                c-r-list)
               c-r-list
             (elt entry-list 1)))
@@ -2818,13 +2927,13 @@
                            (elt req-opt-list 1)
                            bibtex-user-optional-fields
                            (if (member
-                                reference-type
+                                entry-type
                                 bibtex-include-OPTcrossref)
                                '(("crossref"
-                                  "Label of the crossreferenced entry")))
+                                  "Reference key of the crossreferenced entry")))
                            (if bibtex-include-OPTkey
                                '(("key"
-                                  "Key used for label creation if author and editor fields are missing"))))))
+                                  "Used for reference key creation if author and editor fields are missing"))))))
     (goto-char pnt)
     (let ((comment (assoc-ignore-case field-name list-of-entries)))
       (if comment
@@ -2840,15 +2949,15 @@
   (if (not e-t)
       (setq
        e-t
-       (let* ((reference-type
+       (let* ((entry-type
                (save-excursion
-                 (bibtex-enclosing-reference-maybe-empty-head)
+                 (bibtex-enclosing-entry-maybe-empty-head)
                  (buffer-substring-no-properties
                   (1+ (match-beginning bibtex-type-in-head))
                   (match-end bibtex-type-in-head))))
               (fl
                (car (cdr (assoc-ignore-case
-                          reference-type bibtex-entry-field-alist))))
+                          entry-type bibtex-entry-field-alist))))
               (field-list
                (append
                 (elt fl 0) (elt fl 1) bibtex-user-optional-fields
@@ -2917,24 +3026,22 @@
 of the previous entry.
 If called from a program, this function returns the new location of point."
   (interactive)
-  (let ((case-fold-search t)
-        (valid-entry-head
-         (concat "[ \t]*@[ \t]*\\("
-                 (mapconcat
-                  (lambda (type)
-                    (concat "\\(" (car type) "\\)"))
-                  bibtex-entry-field-alist
-                  "\\|")
-                 "\\)"))
-        (org (point))
-        (pnt (bibtex-beginning-of-entry))
-        err)
+  (let* ((case-fold-search t)
+	 (valid-entry-head
+	  (concat "[ \t]*@[ \t]*\\("
+		  (mapconcat
+		   (lambda (type)
+		     (concat "\\(" (car type) "\\)"))
+		   bibtex-entry-field-alist
+		   "\\|")
+		  "\\)"))
+	 (org (point))
+	 (pnt (bibtex-beginning-of-entry))
+	 err)
     (cond
-     ((looking-at "[ \t]*@[ \t]*string[ \t\n]*[({]")
-      (if (not (and
-                (re-search-forward bibtex-string nil t)
-                (equal (match-beginning 0) pnt)))
-          (setq err t)))
+     ((bibtex-parse-string)
+      (let ((bounds (bibtex-parse-string)))
+	(goto-char (bibtex-end-of-string bounds))))
      ((looking-at "[ \t]*@[ \t]*preamble[ \t\n]*")
       (goto-char (match-end 0))
       (cond
@@ -2951,7 +3058,7 @@
             (goto-char (match-beginning 0))
             (forward-char))))
      ((looking-at valid-entry-head)
-      (bibtex-search-reference t nil t)
+      (bibtex-search-entry t nil t)
       (if (not (equal (match-beginning 0) pnt))
           (setq err t)))
      (t
@@ -3014,15 +3121,13 @@
 (defun bibtex-ispell-abstract ()
   "Spell abstract of BibTeX entry."
   (interactive)
-  (let ((case-fold-search t)
-        (pnt (bibtex-end-of-entry)))
+  (let* ((case-fold-search t)
+	 (pnt (bibtex-end-of-entry)))
     (bibtex-beginning-of-entry)
-    (if (not
-         (re-search-forward
-          (bibtex-cfield "abstract" bibtex-field-text) pnt t))
-        (error "No abstract in entry")))
-  (ispell-region (match-beginning bibtex-text-in-cfield)
-                 (match-end bibtex-text-in-cfield)))
+    (let ((bounds (bibtex-search-forward-field "abstract" pnt)))
+      (if bounds
+	  (ispell-region (bibtex-start-of-text-in-field bounds) (bibtex-end-of-text-in-field bounds))
+	(error "No abstract in entry")))))
 
 (defun bibtex-narrow-to-entry ()
   "Narrow buffer to current BibTeX entry."
@@ -3052,8 +3157,8 @@
      'bibtex-end-of-entry
      ;; STARTKEY function
      (lambda ()
-       (let ((case-fold-search t))
-         (re-search-forward bibtex-reference-head)
+       (let* ((case-fold-search t))
+         (re-search-forward bibtex-entry-head)
          (buffer-substring-no-properties
           (match-beginning bibtex-key-in-head)
           (match-end bibtex-key-in-head)))))))
@@ -3091,7 +3196,7 @@
       (bibtex-skip-to-valid-entry t)
       (setq actual-key
             (progn
-              (re-search-forward bibtex-reference-head)
+              (re-search-forward bibtex-entry-head)
               (buffer-substring-no-properties
                (match-beginning bibtex-key-in-head)
                (match-end bibtex-key-in-head))))
@@ -3119,10 +3224,10 @@
           nil)
       (goto-char right)
       (setq actual-key
-            (if (looking-at bibtex-reference-head)
+            (if (looking-at bibtex-entry-head)
                 (buffer-substring-no-properties
-                 (match-beginning bibtex-key-in-reference)
-                 (match-end bibtex-key-in-reference))))
+                 (match-beginning bibtex-key-in-entry)
+                 (match-end bibtex-key-in-entry))))
       (if (or
            (not actual-key)
            (string-lessp actual-key entry-name))
@@ -3138,34 +3243,34 @@
 
 (defun bibtex-validate (&optional test-thoroughly)
   "Validate if buffer or region is syntactically correct.
-Only known reference types are checked, so you can put comments
+Only known entry types are checked, so you can put comments
 outside of entries.
 With optional argument TEST-THOROUGHLY non-nil it checks for absence of
 required fields and questionable month fields as well.
 If mark is active, it validates current region, if not whole buffer.
 Returns t if test was successful, nil otherwise."
   (interactive "P")
-  (let (error-list
-        syntax-error
-        (case-fold-search t)
-        (valid-bibtex-entry
-         (concat
-          "@[ \t]*\\(\\(string\\)\\|"
-          (mapconcat
-           (lambda (type)
-             (concat "\\(" (car type) "\\)"))
-           bibtex-entry-field-alist
-           "\\|")
-          "\\)"))
-        (pnt (point))
-        (start-point
-         (if (bibtex-mark-active)
-             (region-beginning)
-           (bibtex-beginning-of-first-entry)))
-        (end-point
-         (if (bibtex-mark-active)
-             (region-end)
-           (point-max))))
+  (let* (error-list
+	 syntax-error
+	 (case-fold-search t)
+	 (valid-bibtex-entry
+	  (concat
+	   "@[ \t]*\\(\\(string\\)\\|"
+	   (mapconcat
+	    (lambda (type)
+	      (concat "\\(" (car type) "\\)"))
+	    bibtex-entry-field-alist
+	    "\\|")
+	   "\\)"))
+	 (pnt (point))
+	 (start-point
+	  (if (bibtex-mark-active)
+	      (region-beginning)
+	    (bibtex-beginning-of-first-entry)))
+	 (end-point
+	  (if (bibtex-mark-active)
+	      (region-end)
+	    (point-max))))
     (save-restriction
       (narrow-to-region start-point end-point)
       ;; looking if entries fit syntactical structure
@@ -3242,7 +3347,7 @@
                           (entry-list
                            (progn
                              (goto-char beg)
-                             (bibtex-search-reference nil end)
+                             (bibtex-search-entry nil end)
                              (assoc-ignore-case
                               (buffer-substring-no-properties
                                (1+ (match-beginning bibtex-type-in-head))
@@ -3252,31 +3357,34 @@
                           (creq (copy-sequence (elt (elt entry-list 2) 0)))
                           crossref-there)
                      (goto-char beg)
-                     (while (re-search-forward bibtex-field end t)
-                       (let ((field-name
-                              (buffer-substring-no-properties
-                               (match-beginning bibtex-name-in-field)
-                               (match-end bibtex-name-in-field))))
-                         (if (and (equal (downcase field-name) "month")
-                                  (string-match
-                                   questionable-month
-                                   (buffer-substring-no-properties
-                                    (match-beginning bibtex-text-in-field)
-                                    (match-end bibtex-text-in-field))))
-                             (setq
-                              error-list
-                              (cons
-                               (list
-                                (bibtex-current-line)
-                                "Questionable month field (delimited string)")
-                               error-list)))
-                         (setq
-                          req
-                          (delete (assoc-ignore-case field-name req) req)
-                          creq
-                          (delete (assoc-ignore-case field-name creq) creq))
-                         (if (equal (downcase field-name) "crossref")
-                             (setq crossref-there t))))
+		     (let ((bounds (bibtex-search-forward-field bibtex-field-name end)))
+		       (while bounds
+			 (let ((field-name
+				(buffer-substring-no-properties
+				 (bibtex-start-of-name-in-field bounds)
+				 (bibtex-end-of-name-in-field bounds))))
+			   (if (and (equal (downcase field-name) "month")
+				    (string-match
+				     questionable-month
+				     (buffer-substring-no-properties
+				      (bibtex-start-of-text-in-field bounds)
+				      (bibtex-end-of-text-in-field bounds))))
+			       (setq
+				error-list
+				(cons
+				 (list
+				  (bibtex-current-line)
+				  "Questionable month field (delimited string)")
+				 error-list)))
+			   (setq
+			    req
+			    (delete (assoc-ignore-case field-name req) req)
+			    creq
+			    (delete (assoc-ignore-case field-name creq) creq))
+			   (if (equal (downcase field-name) "crossref")
+			       (setq crossref-there t)))
+			 (goto-char (bibtex-end-of-field bounds))
+			 (setq bounds (bibtex-search-forward-field bibtex-field-name end))))
                      (if crossref-there
                          (setq req creq))
                      (if (or (> (length req) 1)
@@ -3351,9 +3459,8 @@
   (bibtex-inside-field)
   (let ((start (point)))
     (condition-case ()
-	(progn
-	  (bibtex-enclosing-field)
-	  (goto-char (match-end 0))
+	(let ((bounds (bibtex-enclosing-field)))
+	  (goto-char (bibtex-end-of-field bounds))
 	  (forward-char 2))
       (error
        (goto-char start)
@@ -3365,45 +3472,47 @@
   "Go to end of text of current field; with ARG, go to beginning."
   (interactive "P")
   (bibtex-inside-field)
-  (if (bibtex-enclosing-field (or (interactive-p) as-if-interactive))
-      (progn
-        (if arg
-            (progn
-              (goto-char (match-beginning bibtex-text-in-field))
-              (if (looking-at "[{\"]")
-                  (forward-char)))
-          (goto-char (match-end bibtex-text-in-field))
-          (if (or
-               (= (preceding-char) ?})
-               (= (preceding-char) ?\"))
-              (forward-char -1)))
-        (if bibtex-help-message
-            (bibtex-print-help-message)))
-    (beginning-of-line)
-    (cond
-     ((looking-at bibtex-string)
-      (goto-char
-       (if arg
-           (match-beginning bibtex-text-in-string)
-         (match-end bibtex-text-in-string))))
-     ((looking-at bibtex-reference-maybe-empty-head)
-      (goto-char
-       (if arg
-           (match-beginning bibtex-key-in-head)
-         (match-end 0))))
-     (t
-      (if (not silent)
-          (error "Not on BibTeX field"))))))
+  (let ((bounds (bibtex-enclosing-field (or (interactive-p) as-if-interactive))))
+    (if bounds
+	(progn
+	  (if arg
+	      (progn
+		(goto-char (bibtex-start-of-text-in-field bounds))
+		(if (looking-at "[{\"]")
+		    (forward-char)))
+	    (goto-char (bibtex-end-of-text-in-field bounds))
+	    (if (or
+		 (= (preceding-char) ?})
+		 (= (preceding-char) ?\"))
+		(forward-char -1)))
+	  (if bibtex-help-message
+	      (bibtex-print-help-message)))
+      (beginning-of-line)
+      (cond
+       ((bibtex-parse-string)
+	(let ((bounds (bibtex-parse-string)))
+	  (goto-char
+	   (if arg
+	       (bibtex-start-of-text-in-string bounds)
+	     (bibtex-end-of-text-in-string bounds)))))
+       ((looking-at bibtex-entry-maybe-empty-head)
+	(goto-char
+	 (if arg
+	     (match-beginning bibtex-key-in-head)
+	   (match-end 0))))
+       (t
+	(if (not silent)
+	    (error "Not on BibTeX field")))))))
 
 (defun bibtex-remove-OPT-or-ALT ()
   "Removes the string starting optional/alternative fields.
 Aligns text and goes thereafter to end of text."
   (interactive)
-  (let ((case-fold-search t))
-    (bibtex-inside-field)
-    (bibtex-enclosing-field)
+  (bibtex-inside-field)
+  (let* ((case-fold-search t)
+	 (bounds (bibtex-enclosing-field)))
     (save-excursion
-      (goto-char (match-beginning bibtex-name-in-field))
+      (goto-char (bibtex-start-of-name-in-field bounds))
       (if (looking-at "OPT\\|ALT")
           (progn
             (delete-char (length "OPT"))
@@ -3424,35 +3533,32 @@
 (defun bibtex-remove-delimiters ()
   "Removes \"\" or {} around string."
   (interactive)
-  (let ((case-fold-search t))
-    (save-excursion
-      (bibtex-inside-field)
-      (bibtex-enclosing-field)
-      (let ((start (match-beginning bibtex-text-in-field))
-            (stop (match-end bibtex-text-in-field)))
-        (goto-char start)
-        (while (re-search-forward bibtex-field-string stop t)
-          (let ((beg (copy-marker (match-beginning 0)))
-                (end (copy-marker (match-end 0))))
-            (goto-char beg)
-            (if (looking-at "[{\"]")
-                (delete-char 1))
-            (goto-char end)
-            (forward-char -1)
-            (if (looking-at "[}\"]")
-                (delete-char 1))))))))
+  (save-excursion
+    (bibtex-inside-field)
+    (let* ((case-fold-search t)
+	   (bounds (bibtex-enclosing-field))
+	   (stop (copy-marker (bibtex-end-of-text-in-field bounds))))
+      (goto-char (bibtex-start-of-text-in-field bounds))
+      (let* ((boundaries (bibtex-search-forward-field-string stop)))
+	(while boundaries
+	  (let ((text-end (copy-marker (cdr boundaries))))
+	    (goto-char (car boundaries))
+	    (delete-char 1)
+	    (goto-char text-end)
+	    (delete-backward-char 1)
+	    (setq boundaries (bibtex-search-forward-field-string stop))))))))
 
 (defun bibtex-kill-field (&optional copy-only)
   "Kills the entire enclosing BibTeX field.
 With prefix arg COPY-ONLY, copy the current field to `bibtex-field-kill-ring,'
 but do not actually kill it."
   (interactive "P")
-  (let ((pnt (point))
-        (case-fold-search t))
+  (let* ((pnt (point))
+	 (case-fold-search t))
     (bibtex-inside-field)
-    (bibtex-enclosing-field)
-    (let ((the-end (match-end 0))
-          (the-beginning (match-beginning 0)))
+    (let* ((bounds (bibtex-enclosing-field))
+	   (the-end (bibtex-end-of-field bounds))
+	   (the-beginning (bibtex-start-of-field bounds)))
       (goto-char the-end)
       (skip-chars-forward " \t\n,")
       (setq
@@ -3461,11 +3567,11 @@
         (list
          'field
          (buffer-substring-no-properties
-          (match-beginning bibtex-name-in-field)
-          (match-end bibtex-name-in-field))
+          (bibtex-start-of-name-in-field bounds)
+          (bibtex-end-of-name-in-field bounds))
          (buffer-substring-no-properties
-          (match-beginning bibtex-text-in-field)
-          (match-end bibtex-text-in-field)))
+          (bibtex-start-of-text-in-field bounds)
+          (bibtex-end-of-text-in-field bounds)))
         bibtex-field-kill-ring))
       (if (> (length bibtex-field-kill-ring) bibtex-field-kill-ring-max)
           (setcdr
@@ -3484,20 +3590,20 @@
   (bibtex-kill-field t))
 
 (defun bibtex-kill-entry (&optional copy-only)
-  "Kill the entire enclosing BibTeX reference entry.
-With prefix arg COPY-ONLY the current reference entry to
+  "Kill the entire enclosing BibTeX entry.
+With prefix arg COPY-ONLY the current entry to
 `bibtex-entry-kill-ring', but do not actually kill it."
   (interactive "P")
-  (let ((pnt (point))
-        (case-fold-search t)
-        (beg (bibtex-beginning-of-entry))
-        (end
-         (progn
-           (bibtex-end-of-entry)
-           (if (re-search-forward
-                bibtex-reference-maybe-empty-head nil 'move)
-               (goto-char (match-beginning 0)))
-           (point))))
+  (let* ((pnt (point))
+	 (case-fold-search t)
+	 (beg (bibtex-beginning-of-entry))
+	 (end
+	  (progn
+	    (bibtex-end-of-entry)
+	    (if (re-search-forward
+		 bibtex-entry-maybe-empty-head nil 'move)
+		(goto-char (match-beginning 0)))
+	    (point))))
     (setq
      bibtex-entry-kill-ring
      (cons
@@ -3552,12 +3658,12 @@
   "Delete the text part of the current field, replace with empty text."
   (interactive)
   (bibtex-inside-field)
-  (bibtex-enclosing-field)
-  (goto-char (match-beginning bibtex-text-in-field))
-  (delete-region (point) (match-end bibtex-text-in-field))
-  (insert (concat (bibtex-field-left-delimiter)
-                  (bibtex-field-right-delimiter)) )
-  (bibtex-find-text t))
+  (let ((bounds (bibtex-enclosing-field)))
+    (goto-char (bibtex-start-of-text-in-field bounds))
+    (delete-region (point) (bibtex-end-of-text-in-field bounds))
+    (insert (concat (bibtex-field-left-delimiter)
+		    (bibtex-field-right-delimiter)) )
+    (bibtex-find-text t)))
 
 (defun bibtex-pop-previous (arg)
   "Replace text of current field with the similar field in previous entry.
@@ -3573,13 +3679,13 @@
   (interactive "p")
   (bibtex-pop arg 'next))
 
-(defun bibtex-clean-entry (&optional new-label called-by-reformat)
+(defun bibtex-clean-entry (&optional new-reference-key called-by-reformat)
   "Finish editing the current BibTeX entry and clean it up.
 Checks that no required fields are empty and formats entry dependent
 on the value of bibtex-entry-format.
-If label of entry is empty or a prefix argument is given, calculate a
-new entry label (note: this only will work if fields in entry begin on
-separate lines prior to calling bibtex-clean-entry or if 'realign is
+If the reference key of the entry is empty or a prefix argument is given,
+calculate a new reference key (note: this only will 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 this on `string' or `preamble' entries.
 At end of the cleaning process, the functions in
@@ -3591,12 +3697,12 @@
          (key (progn
                 (bibtex-beginning-of-entry)
                 (if (re-search-forward
-                     bibtex-reference-head eob t)
+                     bibtex-entry-head eob t)
                     (buffer-substring-no-properties
                      (match-beginning bibtex-key-in-head)
                      (match-end bibtex-key-in-head))))))
     (if (or
-         new-label
+         new-reference-key
          (not key))
         (progn
           (let ((autokey
@@ -3606,7 +3712,7 @@
                       'bibtex-key-history)
                    (bibtex-generate-autokey))))
             (bibtex-beginning-of-entry)
-            (re-search-forward bibtex-reference-maybe-empty-head)
+            (re-search-forward bibtex-entry-maybe-empty-head)
             (if (match-beginning bibtex-key-in-head)
                 (delete-region (match-beginning bibtex-key-in-head)
                                (match-end bibtex-key-in-head)))
@@ -3615,7 +3721,7 @@
                    (end (progn
                           (bibtex-end-of-entry)
                           (if (re-search-forward
-                               bibtex-reference-maybe-empty-head nil 'move)
+                               bibtex-entry-maybe-empty-head nil 'move)
                               (goto-char (match-beginning 0)))
                           (point)))
                    (entry (buffer-substring start end)))
@@ -3628,10 +3734,10 @@
                 (insert entry)
                 (forward-char -1)
                 (bibtex-beginning-of-entry)
-                (re-search-forward bibtex-reference-head)
+                (re-search-forward bibtex-entry-head)
                 (if (not success)
                     (error
-                     "New inserted reference yields duplicate key"))))))))
+                     "New inserted entry yields duplicate key"))))))))
   (if (not called-by-reformat)
       (save-excursion
         (save-restriction
@@ -3652,37 +3758,36 @@
     (bibtex-beginning-of-entry)
     (bibtex-delete-whitespace)
     (indent-to-column bibtex-entry-offset)
-    (while (re-search-forward bibtex-field end t)
-      (let* ((begin-field
-              (copy-marker (match-beginning 0)))
-             (end-field
-              (copy-marker (match-end 0)))
-             (begin-name
-              (copy-marker (match-beginning bibtex-name-in-field)))
-             (end-name
-              (copy-marker (match-end bibtex-name-in-field))))
-        (goto-char begin-field)
-        (forward-char)
-        (bibtex-delete-whitespace)
-        (open-line 1)
-        (forward-char)
-        (indent-to-column
-         (+ bibtex-entry-offset bibtex-field-indentation))
-        (re-search-forward "[ \t\n]*=" end)
-        (replace-match "=")
-        (forward-char -1)
-        (if bibtex-align-at-equal-sign
-            (indent-to-column
-             (+ bibtex-entry-offset (- bibtex-text-indentation 2)))
-          (insert " "))
-        (forward-char)
-        (bibtex-delete-whitespace)
-        (if bibtex-align-at-equal-sign
-            (insert " ")
-          (indent-to-column bibtex-text-indentation))
-        (while (re-search-forward "[ \t\n]+" end-field 'move)
-          (replace-match " "))
-        (bibtex-do-auto-fill)))
+    (let ((bounds (bibtex-search-forward-field bibtex-field-name end)))
+      (while bounds
+	(let* ((begin-field (copy-marker (bibtex-start-of-field bounds)))
+	       (end-field (copy-marker (bibtex-end-of-field bounds)))
+	       (begin-name (copy-marker (bibtex-start-of-name-in-field bounds)))
+	       (end-name (copy-marker (bibtex-end-of-name-in-field bounds))))
+	  (goto-char begin-field)
+	  (forward-char)
+	  (bibtex-delete-whitespace)
+	  (open-line 1)
+	  (forward-char)
+	  (indent-to-column
+	   (+ bibtex-entry-offset bibtex-field-indentation))
+	  (re-search-forward "[ \t\n]*=" end)
+	  (replace-match "=")
+	  (forward-char -1)
+	  (if bibtex-align-at-equal-sign
+	      (indent-to-column
+	       (+ bibtex-entry-offset (- bibtex-text-indentation 2)))
+	    (insert " "))
+	  (forward-char)
+	  (bibtex-delete-whitespace)
+	  (if bibtex-align-at-equal-sign
+	      (insert " ")
+	    (indent-to-column bibtex-text-indentation))
+	  (while (re-search-forward "[ \t\n]+" end-field 'move)
+	    (replace-match " "))
+	  (bibtex-do-auto-fill)
+	  (goto-char end-field))
+	(setq bounds (bibtex-search-forward-field bibtex-field-name end))))
     (if (looking-at ",")
         (forward-char))
     (bibtex-delete-whitespace)
@@ -3701,7 +3806,7 @@
          (use-previous-options
           (and (equal (prefix-numeric-value additional-options) 16)
                (or bibtex-reformat-previous-options
-                   bibtex-reformat-previous-labels)))
+                   bibtex-reformat-previous-reference-keys)))
          (bibtex-entry-format
           (if additional-options
               (if use-previous-options
@@ -3738,13 +3843,13 @@
                         "Unify case of entry types and field names? ")
                        'unify-case)))))
             '(realign)))
-         (labels
+         (reformat-reference-keys
              (if additional-options
                  (if use-previous-options
-                     bibtex-reformat-previous-labels
+                     bibtex-reformat-previous-reference-keys
                    (setq
-                    bibtex-reformat-previous-labels
-                    (y-or-n-p "Generate automatically new reference labels? ")))))
+                    bibtex-reformat-previous-reference-keys
+                    (y-or-n-p "Generate new reference keys automatically? ")))))
          bibtex-autokey-edit-before-use
          (bibtex-sort-ignore-string-entries t)
          (start-point
@@ -3779,7 +3884,7 @@
       (bibtex-map-entries
        (lambda (current)
          (bibtex-progress-message)
-         (bibtex-clean-entry labels labels)
+         (bibtex-clean-entry reformat-reference-keys reformat-reference-keys)
          (if (memq 'realign bibtex-entry-format)
              (progn
                (bibtex-end-of-entry)
@@ -3787,12 +3892,12 @@
                (open-line 2)))))
       (bibtex-progress-message 'done))
     (if (and
-         labels
+         reformat-reference-keys
          bibtex-maintain-sorted-entries
          (not called-by-convert-alien))
         (progn
           (bibtex-sort-buffer)
-          (setq bibtex-keys nil)
+          (setq bibtex-reference-keys nil)
           (bibtex-parse-keys nil t t)))
     (goto-char pnt)))
 
@@ -3838,9 +3943,9 @@
 If point is not after the part of a word, all keys are listed.  This
 function is most useful in completing crossref entries."
   (interactive "*")
-  (if (not bibtex-keys)
+  (if (not bibtex-reference-keys)
       (bibtex-parse-keys nil t))
-  (bibtex-complete bibtex-keys))
+  (bibtex-complete bibtex-reference-keys))
 
 (defun bibtex-Article ()
   "Insert a new BibTeX @Article entry; see also `bibtex-entry'."
@@ -3910,14 +4015,14 @@
 (defun bibtex-String ()
   "Insert a new BibTeX @String entry."
   (interactive)
-  (if (not bibtex-keys)
+  (if (not bibtex-reference-keys)
       (bibtex-parse-keys nil t))
   (let ((key
          (if (and
               bibtex-maintain-sorted-entries
               (not bibtex-sort-ignore-string-entries))
              (completing-read
-              "String key: " bibtex-keys nil nil nil 'bibtex-key-history))))
+              "String key: " bibtex-reference-keys nil nil nil 'bibtex-key-history))))
     (if (and
          bibtex-maintain-sorted-entries
          (not bibtex-sort-ignore-string-entries))