+ (nth 2 bounds))
+(defsubst bibtex-end-of-field (bounds)
+ (nth 3 bounds))
+
+(defun bibtex-search-forward-field (name &optional bound)
+ "Search forward to find a BibTeX field of name NAME.
+If a syntactically correct field is found, return a pair containing
+the boundaries of the name and text parts of the field. The search
+is limited by optional arg BOUND. If BOUND is t the search is limited
+by the end of the current entry. Do not move point."
+ (save-match-data
+ (save-excursion
+ (if (eq bound t)
+ (let ((regexp (concat bibtex-name-part "[ \t\n]*=\\|"
+ bibtex-any-entry-maybe-empty-head))
+ (case-fold-search t) bounds)
+ (catch 'done
+ (if (looking-at "[ \t]*@") (goto-char (match-end 0)))
+ (while (and (not bounds)
+ (re-search-forward regexp nil t))
+ (if (match-beginning 2)
+ ;; We found a new entry
+ (throw 'done nil)
+ ;; We found a field
+ (goto-char (match-beginning 0))
+ (setq bounds (bibtex-parse-field))))
+ ;; Step through all fields so that we cannot overshoot.
+ (while bounds
+ (goto-char (bibtex-start-of-name-in-field bounds))
+ (if (looking-at name) (throw 'done bounds))
+ (goto-char (bibtex-end-of-field bounds))
+ (setq bounds (bibtex-parse-field)))))
+ ;; Bounded search or bound is nil (i.e. we cannot overshoot).
+ ;; Indeed, the search is bounded when `bibtex-search-forward-field'
+ ;; is called many times. So we optimize this part of this function.
+ (let ((name-part (concat ",[ \t\n]*\\(" name "\\)[ \t\n]*=[ \t\n]*"))
+ (case-fold-search t) left right)
+ (while (and (not right)
+ (re-search-forward name-part bound t))
+ (setq left (list (match-beginning 0) (match-beginning 1)
+ (match-end 1))
+ ;; Don't worry that the field text could be past bound.
+ right (bibtex-parse-field-text)))
+ (if right (cons left right)))))))
+
+(defun bibtex-search-backward-field (name &optional bound)
+ "Search backward to find a BibTeX field of name NAME.
+If a syntactically correct field is found, return a pair containing
+the boundaries of the name and text parts of the field. The search
+is limited by the optional arg BOUND. If BOUND is t the search is
+limited by the beginning of the current entry. Do not move point."
+ (save-match-data
+ (if (eq bound t)
+ (setq bound (save-excursion (bibtex-beginning-of-entry))))
+ (let ((name-part (concat ",[ \t\n]*\\(" name "\\)[ \t\n]*=[ \t\n]*"))
+ (case-fold-search t) left right)
+ (save-excursion
+ ;; the parsing functions are not designed for parsing backwards :-(
+ (when (search-backward "," bound t)
+ (or (save-excursion
+ (when (looking-at name-part)
+ (setq left (list (match-beginning 0) (match-beginning 1)
+ (match-end 1)))
+ (goto-char (match-end 0))
+ (setq right (bibtex-parse-field-text))))
+ (while (and (not right)
+ (re-search-backward name-part bound t))
+ (setq left (list (match-beginning 0) (match-beginning 1)
+ (match-end 1)))
+ (save-excursion
+ (goto-char (match-end 0))
+ (setq right (bibtex-parse-field-text)))))
+ (if right (cons left right)))))))