+(defun nnheader-replace-header (header new-value)
+ "Remove HEADER and insert the NEW-VALUE."
+ (save-excursion
+ (save-restriction
+ (nnheader-narrow-to-headers)
+ (prog1
+ (message-remove-header header)
+ (goto-char (point-max))
+ (insert header ": " new-value "\n")))))
+
+(defun nnheader-narrow-to-headers ()
+ "Narrow to the head of an article."
+ (widen)
+ (narrow-to-region
+ (goto-char (point-min))
+ (if (search-forward "\n\n" nil t)
+ (1- (point))
+ (point-max)))
+ (goto-char (point-min)))
+
+(defun nnheader-set-temp-buffer (name)
+ "Set-buffer to an empty (possibly new) buffer called NAME with undo disabled."
+ (set-buffer (get-buffer-create name))
+ (buffer-disable-undo (current-buffer))
+ (erase-buffer)
+ (current-buffer))
+
+(defmacro nnheader-temp-write (file &rest forms)
+ "Create a new buffer, evaluate FORM there, and write the buffer to FILE."
+ `(save-excursion
+ (let ((nnheader-temp-file ,file)
+ (nnheader-temp-cur-buffer
+ (nnheader-set-temp-buffer
+ (generate-new-buffer-name " *nnheader temp*"))))
+ (when (and nnheader-temp-file
+ (not (file-directory-p (file-name-directory
+ nnheader-temp-file))))
+ (make-directory (file-name-directory nnheader-temp-file) t))
+ (unwind-protect
+ (prog1
+ (progn
+ ,@forms)
+ (when nnheader-temp-file
+ (set-buffer nnheader-temp-cur-buffer)
+ (write-region (point-min) (point-max)
+ nnheader-temp-file nil 'nomesg)))
+ (when (buffer-name nnheader-temp-cur-buffer)
+ (kill-buffer nnheader-temp-cur-buffer))))))
+
+(put 'nnheader-temp-write 'lisp-indent-function 1)
+(put 'nnheader-temp-write 'lisp-indent-hook 1)
+(put 'nnheader-temp-write 'edebug-form-spec '(form body))
+
+(defvar jka-compr-compression-info-list)
+(defvar nnheader-numerical-files
+ (if (boundp 'jka-compr-compression-info-list)
+ (concat "\\([0-9]+\\)\\("
+ (mapconcat (lambda (i) (aref i 0))
+ jka-compr-compression-info-list "\\|")
+ "\\)?")
+ "[0-9]+$")
+ "Regexp that match numerical files.")
+
+(defvar nnheader-numerical-short-files (concat "^" nnheader-numerical-files)
+ "Regexp that matches numerical file names.")
+
+(defvar nnheader-numerical-full-files (concat "/" nnheader-numerical-files)
+ "Regexp that matches numerical full file paths.")
+
+(defsubst nnheader-file-to-number (file)
+ "Take a file name and return the article number."
+ (if (not (boundp 'jka-compr-compression-info-list))
+ (string-to-int file)
+ (string-match nnheader-numerical-short-files file)
+ (string-to-int (match-string 0 file))))
+
+(defun nnheader-directory-files-safe (&rest args)
+ ;; It has been reported numerous times that `directory-files'
+ ;; fails with an alarming frequency on NFS mounted file systems.
+ ;; This function executes that function twice and returns
+ ;; the longest result.
+ (let ((first (apply 'directory-files args))
+ (second (apply 'directory-files args)))
+ (if (> (length first) (length second))
+ first
+ second)))
+
+(defun nnheader-directory-articles (dir)
+ "Return a list of all article files in a directory."
+ (mapcar 'nnheader-file-to-number
+ (nnheader-directory-files-safe
+ dir nil nnheader-numerical-short-files t)))
+
+(defun nnheader-article-to-file-alist (dir)
+ "Return an alist of article/file pairs in DIR."
+ (mapcar (lambda (file) (cons (nnheader-file-to-number file) file))
+ (nnheader-directory-files-safe
+ dir nil nnheader-numerical-short-files t)))
+
+(defun nnheader-fold-continuation-lines ()
+ "Fold continuation lines in the current buffer."
+ (goto-char (point-min))
+ (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
+ (replace-match " " t t)))
+
+(defun nnheader-translate-file-chars (file)
+ (if (null nnheader-file-name-translation-alist)
+ ;; No translation is necessary.
+ file
+ ;; We translate -- but only the file name. We leave the directory
+ ;; alone.
+ (let* ((i 0)
+ trans leaf path len)
+ (if (string-match "/[^/]+\\'" file)
+ ;; This is needed on NT's and stuff.
+ (setq leaf (substring file (1+ (match-beginning 0)))
+ path (substring file 0 (1+ (match-beginning 0))))
+ ;; Fall back on this.
+ (setq leaf (file-name-nondirectory file)
+ path (file-name-directory file)))
+ (setq len (length leaf))
+ (while (< i len)
+ (when (setq trans (cdr (assq (aref leaf i)
+ nnheader-file-name-translation-alist)))
+ (aset leaf i trans))
+ (incf i))
+ (concat path leaf))))
+
+(defun nnheader-report (backend &rest args)
+ "Report an error from the BACKEND.
+The first string in ARGS can be a format string."
+ (set (intern (format "%s-status-string" backend))
+ (if (< (length args) 2)
+ (car args)
+ (apply 'format args)))
+ nil)
+
+(defun nnheader-get-report (backend)
+ (message "%s" (symbol-value (intern (format "%s-status-string" backend)))))
+
+(defun nnheader-insert (format &rest args)
+ "Clear the communicaton buffer and insert FORMAT and ARGS into the buffer.
+If FORMAT isn't a format string, it and all ARGS will be inserted
+without formatting."
+ (save-excursion
+ (set-buffer nntp-server-buffer)
+ (erase-buffer)
+ (if (string-match "%" format)
+ (insert (apply 'format format args))
+ (apply 'insert format args))
+ t))
+
+(defun nnheader-mail-file-mbox-p (file)
+ "Say whether FILE looks like an Unix mbox file."
+ (when (and (file-exists-p file)
+ (file-readable-p file)
+ (file-regular-p file))
+ (save-excursion
+ (nnheader-set-temp-buffer " *mail-file-mbox-p*")
+ (nnheader-insert-file-contents-literally file)
+ (goto-char (point-min))
+ (prog1
+ (looking-at message-unix-mail-delimiter)
+ (kill-buffer (current-buffer))))))
+
+(defun nnheader-replace-chars-in-string (string from to)
+ "Replace characters in STRING from FROM to TO."
+ (let ((string (substring string 0)) ;Copy string.
+ (len (length string))
+ (idx 0))
+ ;; Replace all occurrences of FROM with TO.
+ (while (< idx len)
+ (if (= (aref string idx) from)
+ (aset string idx to))
+ (setq idx (1+ idx)))
+ string))
+
+(defun nnheader-file-to-group (file &optional top)
+ "Return a group name based on FILE and TOP."
+ (nnheader-replace-chars-in-string
+ (if (not top)
+ file
+ (condition-case ()
+ (substring (expand-file-name file)
+ (length
+ (expand-file-name
+ (file-name-as-directory top))))
+ (error "")))
+ ?/ ?.))
+
+(defun nnheader-message (level &rest args)
+ "Message if the Gnus backends are talkative."
+ (if (or (not (numberp gnus-verbose-backends))
+ (<= level gnus-verbose-backends))
+ (apply 'message args)
+ (apply 'format args)))
+
+(defun nnheader-be-verbose (level)
+ "Return whether the backends should be verbose on LEVEL."
+ (or (not (numberp gnus-verbose-backends))
+ (<= level gnus-verbose-backends)))
+
+(defun nnheader-group-pathname (group dir &optional file)
+ "Make pathname for GROUP."
+ (concat
+ (let ((dir (file-name-as-directory (expand-file-name dir))))
+ ;; If this directory exists, we use it directly.
+ (if (file-directory-p (concat dir group))
+ (concat dir group "/")
+ ;; If not, we translate dots into slashes.
+ (concat dir (nnheader-replace-chars-in-string group ?. ?/) "/")))
+ (cond ((null file) "")
+ ((numberp file) (int-to-string file))
+ (t file))))
+
+(defun nnheader-functionp (form)
+ "Return non-nil if FORM is funcallable."
+ (or (and (symbolp form) (fboundp form))
+ (and (listp form) (eq (car form) 'lambda))))
+
+(defun nnheader-concat (dir file)
+ "Concat DIR as directory to FILE."
+ (concat (file-name-as-directory dir) file))
+
+(defun nnheader-ms-strip-cr ()
+ "Strip ^M from the end of all lines."
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward "\r$" nil t)
+ (delete-backward-char 1))))
+
+(defun nnheader-file-size (file)
+ "Return the file size of FILE or 0."
+ (or (nth 7 (file-attributes file)) 0))
+
+(defun nnheader-find-etc-directory (package)
+ "Go through the path and find the \".../etc/PACKAGE\" directory."
+ (let ((path load-path)
+ dir result)
+ ;; We try to find the dir by looking at the load path,
+ ;; stripping away the last component and adding "etc/".
+ (while path
+ (if (and (car path)
+ (file-exists-p
+ (setq dir (concat
+ (file-name-directory
+ (directory-file-name (car path)))
+ "etc/" package "/")))
+ (file-directory-p dir))
+ (setq result dir
+ path nil)
+ (setq path (cdr path))))
+ result))
+
+(defvar ange-ftp-path-format)
+(defvar efs-path-regexp)
+(defun nnheader-re-read-dir (path)
+ "Re-read directory PATH if PATH is on a remote system."
+ (if (boundp 'ange-ftp-path-format)
+ (when (string-match (car ange-ftp-path-format) path)
+ (ange-ftp-re-read-dir path))
+ (if (boundp 'efs-path-regexp)
+ (when (string-match efs-path-regexp path)
+ (efs-re-read-dir path)))))
+
+(fset 'nnheader-run-at-time 'run-at-time)
+(fset 'nnheader-cancel-timer 'cancel-timer)
+(fset 'nnheader-find-file-noselect 'find-file-noselect)
+(fset 'nnheader-insert-file-contents-literally
+ 'insert-file-contents-literally)
+
+(when (string-match "XEmacs\\|Lucid" emacs-version)
+ (require 'nnheaderxm))
+
+(run-hooks 'nnheader-load-hook)
+