+Fri Jan 24 05:05:38 1997 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * gnus.el (gnus-article-display-hook): Removed emphasize.
+
+ * gnus-score.el (gnus-score-edit-current-scores): Set global
+ vars.
+
+ * nnml.el (nnml-possibly-change-directory): Return nil when the
+ group can't be selected.
+
+ * gnus-art.el (gnus-emphasis-alist): Don't underline
+ all-underscore words.
+
+ * gnus-topic.el (gnus-topic-unindent): Give the right number of
+ unread articles.
+ (gnus-topic-indent): Ditto.
+
+ * gnus-msg.el (gnus-summary-wide-reply-with-original): New command
+ and keystroke.
+ (gnus-summary-wide-reply): Ditto.
+
+Fri Jan 24 04:57:07 1997 Joe Wells <jbw@cs.bu.edu>
+
+ * gnus-uu.el (gnus-quote-arg-for-sh-or-csh): New function.
+ (gnus-uu-command): Use it.
+
+Fri Jan 24 04:55:10 1997 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * gnus-topic.el (gnus-topic-mark-topic): Also bound to `#'.
+
+Fri Jan 24 04:44:10 1997 Greg Klanderman <greg@alphatech.com>
+
+ * message.el (message-do-send-housekeeping): Check for nil
+ message-buffer-list.
+
+Fri Jan 24 02:55:33 1997 Kurt Swanson <kurt@dna.lth.se>
+
+ * gnus-util.el (gnus-eval-in-buffer-window): Set buffer.
+
+Thu Jan 23 03:39:48 1997 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * nnsoup.el (nnsoup-file-name): New function.
+ (nnsoup-read-areas): Use it.
+ (nnsoup-dissect-buffer): New function.
+ (nnsoup-number-of-articles): Use it.
+ (nnsoup-narrow-to-article): Ditto.
+ (nnsoup-header): Removed.
+
+ * gnus.el (gnus-check-backend-function): Doc fix.
+
+ * gnus-art.el (gnus-article-goto-prev-page): Went to next article,
+ not prev.
+
+ * gnus-group.el (gnus-group-insert-group-line-info): Display "*"
+ on unknown groups.
+
+ * gnus-art.el (article-hide-boring-headers): Ignore errors in
+ `mail-extract-address-components'.
+
+ * nnmail.el (nnmail-date-to-time): Parse zone correctly.
+ (nnmail-date-to-time): Seconds, dammit, seconds!
+
+Tue Jan 21 09:31:55 1997 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * gnus-art.el (gnus-url-mailto): Didn't accept mailto links.
+
+ * gnus-score.el (gnus-summary-score-effect): Doc fix.
+
+ * nnmail.el (nnmail-move-inbox): Don't prin1 password.
+
+Mon Jan 20 18:06:19 1997 Paul Franklin <paul@cs.washington.edu>
+
+ * gnus-sum.el (gnus-simplify-buffer-fuzzy-step): New function.
+ (gnus-simplify-buffer-fuzzy): Use it.
+
+ * gnus-sum.el (gnus-simplify-buffer-fuzzy): Fix while condition.
+ Add self-discipline tags.
+
+Tue Jan 21 05:28:05 1997 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * gnus-sum.el (gnus-get-newsgroup-headers-xover): Would return
+ nil from NoCeM.
+
+Mon Jan 20 04:59:53 1997 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * gnus-art.el (gnus-button-alist): Only on word boundaries.
+
+ * message.el (message-check-news-header-syntax): Don't prompt when
+ not read active file.
+
+ * gnus-msg.el (gnus-setup-message): Always set actions.
+
+Sat Jan 18 07:23:41 1997 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * nntp.el (nntp-have-messaged): New variable.
+ (nntp-accept-process-output): Use it.
+ (nntp-wait-for): Ditto.
+
+Sat Jan 18 02:44:53 1997 Lars Magne Ingebrigtsen <menja.larsi@ifi.uio.no>
+
+ * gnus.el: Red Gnus v0.82 is released.
+
Fri Jan 17 00:04:47 1997 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
* nnheader.el (nnheader-find-nov-line): Do the right thing with
("_\\*" "\\*_" underline-bold)
("\\*/" "/\\*" bold-italic)
("_\\*/" "/\\*_" underline-bold-italic))))
- `(("\\(\\s-\\|^\\)\\(_\\(\\(\\w\\|_\\)+\\)_\\)\\(\\s-\\|[?!.,;]\\)"
+ `(("\\(\\s-\\|^\\)\\(_\\(\\(\\w\\|_[^_]\\)+\\)_\\)\\(\\s-\\|[?!.,;]\\)"
2 3 gnus-emphasis-underline)
,@(mapcar
(lambda (spec)
(reply-to (message-fetch-field "reply-to")))
(when (and
from reply-to
- (equal
- (nth 1 (mail-extract-address-components from))
- (nth 1 (mail-extract-address-components reply-to))))
+ (ignore-errors
+ (equal
+ (nth 1 (mail-extract-address-components from))
+ (nth 1 (mail-extract-address-components reply-to)))))
(gnus-article-hide-header "reply-to"))))
((eq elem 'date)
(let ((date (message-fetch-field "date")))
(defun gnus-article-goto-prev-page ()
"Show the next page of the article."
(interactive)
- (if (bobp) (gnus-article-read-summary-keys nil (gnus-character-to-event ?n))
+ (if (bobp) (gnus-article-read-summary-keys nil (gnus-character-to-event ?p))
(gnus-article-prev-page nil)))
(defun gnus-article-next-page (&optional lines)
:type 'regexp)
(defcustom gnus-button-alist
- `(("\\(<?\\(url: ?\\)?news:\\([^>\n\t ]*\\)>?\\)" 1 t
+ `(("\\(\\b<?\\(url: ?\\)?news:\\([^>\n\t ]*\\)>?\\)" 1 t
gnus-button-message-id 3)
- ("\\(<?\\(url: ?\\)?news:\\(//\\)?\\([^>\n\t ]*\\)>?\\)" 1 t
+ ("\\(\\b<?\\(url: ?\\)?news:\\(//\\)?\\([^>\n\t ]*\\)>?\\)" 1 t
gnus-button-fetch-group 4)
("\\bin\\( +article\\)? +\\(<\\([^\n @<>]+@[^\n @<>]+\\)>\\)" 2
t gnus-button-message-id 3)
(defun gnus-url-mailto (url)
;; Send mail to someone
- (if (not (string-match "mailto:/*\\(.*\\)" url))
- (error "Malformed mailto link: %s" url))
- (setq url (substring url (match-beginning 1) nil))
+ (when (string-match "mailto:/*\\(.*\\)" url)
+ (setq url (substring url (match-beginning 1) nil)))
(let (to args source-url subject func)
(if (string-match (regexp-quote "?") url)
(setq to (gnus-url-unhex-string (substring url 0 (match-beginning 0)))
(if (zerop (cdr active))
0
(- (1+ (cdr active)) (car active)))
- 0)
+ nil)
nil))))
(defun gnus-group-insert-group-line (gnus-tmp-group gnus-tmp-level
"s" gnus-summary-supersede-article
"r" gnus-summary-reply
"R" gnus-summary-reply-with-original
+ "w" gnus-summary-wide-reply
+ "W" gnus-summary-wide-reply-with-original
"n" gnus-summary-followup-to-mail
"N" gnus-summary-followup-to-mail-with-original
"m" gnus-summary-mail-other-window
(copy-sequence message-header-setup-hook)))
(add-hook 'message-header-setup-hook 'gnus-inews-insert-gcc)
(add-hook 'message-header-setup-hook 'gnus-inews-insert-archive-gcc)
- ,@forms
- (gnus-inews-add-send-actions ,winconf ,buffer ,article)
- (setq gnus-message-buffer (current-buffer))
- (make-local-variable 'gnus-newsgroup-name)
+ (unwind-protect
+ ,@forms
+ (gnus-inews-add-send-actions ,winconf ,buffer ,article)
+ (setq gnus-message-buffer (current-buffer))
+ (make-local-variable 'gnus-newsgroup-name))
(gnus-configure-windows ,config t))))
(defun gnus-inews-add-send-actions (winconf buffer article)
;;; Mail reply commands of Gnus summary mode
-(defun gnus-summary-reply (&optional yank)
- "Reply mail to news author.
-If prefix argument YANK is non-nil, original article is yanked automatically."
+(defun gnus-summary-reply (&optional yank wide)
+ "Start composing a reply mail to the current message.
+If prefix argument YANK is non-nil, the original article is yanked
+automatically."
(interactive
(list (and current-prefix-arg
(gnus-summary-work-articles 1))))
- ;; Bug fix by jbw@bigbird.bu.edu (Joe Wells)
;; Stripping headers should be specified with mail-yank-ignored-headers.
(gnus-set-global-variables)
(when yank
(gnus-setup-message (if yank 'reply-yank 'reply)
(gnus-summary-select-article)
(set-buffer (gnus-copy-article-buffer))
- (message-reply nil nil (gnus-group-find-parameter
- gnus-newsgroup-name 'broken-reply-to))
+ (message-reply nil wide (gnus-group-find-parameter
+ gnus-newsgroup-name 'broken-reply-to))
(when yank
(gnus-inews-yank-articles yank)))))
-(defun gnus-summary-reply-with-original (n)
- "Reply mail to news author with original article."
+(defun gnus-summary-reply-with-original (n &optional wide)
+ "Start composing a reply mail to the current message.
+The original article will be yanked."
(interactive "P")
(gnus-summary-reply (gnus-summary-work-articles n)))
+(defun gnus-summary-wide-reply (&optional yank)
+ "Start composing a wide reply mail to the current message.
+If prefix argument YANK is non-nil, the original article is yanked
+automatically."
+ (interactive
+ (list (and current-prefix-arg
+ (gnus-summary-work-articles 1))))
+ (gnus-summary-reply yank t))
+
+(defun gnus-summary-wide-reply-with-original (n)
+ "Start composing a wide reply mail to the current message.
+The original article will be yanked."
+ (interactive "P")
+ (gnus-summary-reply-with-original n t))
+
(defun gnus-summary-mail-forward (&optional full-headers post)
"Forward the current message to another user.
If FULL-HEADERS (the prefix), include full headers when forwarding."
"Simulate the effect of a score file entry.
HEADER is the header being scored.
MATCH is the string we are looking for.
-TYPE is a flag indicating if it is a regexp or substring.
+TYPE is the score type.
SCORE is the score to add."
(interactive (list (completing-read "Header: "
gnus-header-index
(defun gnus-score-edit-current-scores (file)
"Edit the current score alist."
(interactive (list gnus-current-score-file))
+ (gnus-set-global-variables)
(let ((winconf (current-window-configuration)))
(when (buffer-name gnus-summary-buffer)
(gnus-score-save))
(progn (insert prefix)
(zerop (forward-line 1)))))))
;; Store the active file in a hash table.
- ;; dmoore@ucsd.edu 31.10.1996 - use same method for moderation or not
(goto-char (point-min))
(let (group max min)
(while (not (eobp))
;; Remove any leading "re:"s, any trailing paren phrases, and simplify
;; all whitespace.
-;; Written by Stainless Steel Rat <ratinox@ccs.neu.edu>.
+(defsubst gnus-simplify-buffer-fuzzy-step (regexp &optional newtext)
+ (goto-char (point-min))
+ (while (re-search-forward regexp nil t)
+ (replace-match (or newtext ""))))
+
(defun gnus-simplify-buffer-fuzzy ()
- (let ((case-fold-search t))
- (goto-char (point-min))
- (while (search-forward "\t" nil t)
- (replace-match " " t t))
- (goto-char (point-min))
- (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *" nil t)
- (goto-char (match-beginning 0))
- (while (or
- (and
- gnus-simplify-subject-fuzzy-regexp
- (looking-at gnus-simplify-subject-fuzzy-regexp))
- (looking-at "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *")
- (looking-at "^[[].*: .*[]]$"))
- (goto-char (point-min))
- (when gnus-simplify-subject-fuzzy-regexp
- (while (re-search-forward gnus-simplify-subject-fuzzy-regexp
- nil t)
- (replace-match "" t t)))
- (goto-char (point-min))
- (while (re-search-forward "^ *\\(re\\|fw\\|fwd\\)[[{(^0-9]*[])}]?[:;] *"
- nil t)
- (replace-match "" t t))
- (goto-char (point-min))
- (while (re-search-forward "^[[].*: .*[]]$" nil t)
- (goto-char (match-end 0))
- (delete-char -1)
- (delete-region
- (progn (goto-char (match-beginning 0)))
- (re-search-forward ":"))))
- (goto-char (point-min))
- (while (re-search-forward " *[[{(][^()\n]*[]})] *$" nil t)
- (replace-match "" t t))
- (goto-char (point-min))
- (while (re-search-forward " +" nil t)
- (replace-match " " t t))
- (goto-char (point-min))
- (while (re-search-forward " $" nil t)
- (replace-match "" t t))
- (goto-char (point-min))
- (while (re-search-forward "^ +" nil t)
- (replace-match "" t t))))
+ "Simplify string in the buffer fuzzily.
+The string in the accessible portion of the current buffer is simplified.
+It is assumed to be a single-line subject.
+Whitespace is generally cleaned up, and miscellaneous leading/trailing
+matter is removed. Additional things can be deleted by setting
+gnus-simplify-subject-fuzzy-regexp."
+ (let ((case-fold-search t)
+ (modified-tick))
+ (gnus-simplify-buffer-fuzzy-step "\t" " ")
+
+ (while (not (eq modified-tick (buffer-modified-tick)))
+ (setq modified-tick (buffer-modified-tick))
+ (cond
+ ((listp gnus-simplify-subject-fuzzy-regexp)
+ (mapcar 'gnus-simplify-buffer-fuzzy-step
+ gnus-simplify-subject-fuzzy-regexp))
+ (gnus-simplify-subject-fuzzy-regexp
+ (gnus-simplify-buffer-fuzzy-step gnus-simplify-subject-fuzzy-regexp)))
+ (gnus-simplify-buffer-fuzzy-step "^ *\\[[-+?*!][-+?*!]\\] *")
+ (gnus-simplify-buffer-fuzzy-step
+ "^ *\\(re\\|fw\\|fwd\\)[[{(^0-9]*[])}]?[:;] *")
+ (gnus-simplify-buffer-fuzzy-step "^[[].*:\\( .*\\)[]]$" "\\1"))
+
+ (gnus-simplify-buffer-fuzzy-step " *[[{(][^()\n]*[]})] *$")
+ (gnus-simplify-buffer-fuzzy-step " +" " ")
+ (gnus-simplify-buffer-fuzzy-step " $")
+ (gnus-simplify-buffer-fuzzy-step "^ +")))
(defun gnus-simplify-subject-fuzzy (subject)
- "Simplify a subject string fuzzily."
+ "Simplify a subject string fuzzily.
+See gnus-simplify-buffer-fuzzy for details."
(save-excursion
(gnus-set-work-buffer)
(let ((case-fold-search t))
(buffer-string))))
(defsubst gnus-simplify-subject-fully (subject)
- "Simplify a subject string according to the user's wishes."
+ "Simplify a subject string according to gnus-summary-gather-subject-limit."
(cond
((null gnus-summary-gather-subject-limit)
(gnus-simplify-subject-re subject))
["Cancel article" gnus-summary-cancel-article t]
["Reply" gnus-summary-reply t]
["Reply and yank" gnus-summary-reply-with-original t]
+ ["Wide reply" gnus-summary-wide-reply t]
+ ["Wide reply and yank" gnus-summary-wide-reply-with-original t]
["Mail forward" gnus-summary-mail-forward t]
["Post forward" gnus-summary-post-forward t]
["Digest and mail" gnus-uu-digest-mail-forward t]
;; article may not have been generated yet, so this may fail.
;; We work around this problem by retrieving the last few
;; headers using HEAD.
- (when also-fetch-heads
- (if (not sequence)
- (nreverse headers)
- (let ((gnus-nov-is-evil t)
- (nntp-nov-is-evil t))
- (nconc
- (nreverse headers)
- (when (gnus-retrieve-headers sequence group)
- (gnus-get-newsgroup-headers)))))))))
+ (if (or (not also-fetch-heads)
+ (not sequence))
+ (nreverse headers)
+ (let ((gnus-nov-is-evil t)
+ (nntp-nov-is-evil t))
+ (nconc
+ (nreverse headers)
+ (when (gnus-retrieve-headers sequence group)
+ (gnus-get-newsgroup-headers))))))))
(defun gnus-article-get-xrefs ()
"Fill in the Xref value in `gnus-current-headers', if necessary.
"\M-g" gnus-topic-get-new-news-this-topic
"AT" gnus-topic-list-active
"Gp" gnus-topic-edit-parameters
+ "#" gnus-topic-mark-topic
+ "\M-#" gnus-topic-unmark-topic
gnus-mouse-2 gnus-mouse-pick-topic)
;; Define a new submap.
(defun gnus-topic-mark-topic (topic &optional unmark)
"Mark all groups in the topic with the process mark."
(interactive (list (gnus-current-topic)))
- (save-excursion
- (let ((groups (gnus-topic-find-groups topic 9 t)))
- (while groups
- (funcall (if unmark 'gnus-group-remove-mark 'gnus-group-set-mark)
- (gnus-info-group (nth 2 (pop groups))))))))
+ (if (not topic)
+ (call-interactively 'gnus-group-mark-group)
+ (save-excursion
+ (let ((groups (gnus-topic-find-groups topic 9 t)))
+ (while groups
+ (funcall (if unmark 'gnus-group-remove-mark 'gnus-group-set-mark)
+ (gnus-info-group (nth 2 (pop groups)))))))))
(defun gnus-topic-unmark-topic (topic &optional unmark)
"Remove the process mark from all groups in the topic."
(interactive (list (gnus-current-topic)))
- (gnus-topic-mark-topic topic t))
+ (if (not topic)
+ (call-interactively 'gnus-group-mark-group)
+ (gnus-topic-mark-topic topic t)))
(defun gnus-topic-get-new-news-this-topic (&optional n)
"Check for new news in the current topic."
(if unindent
(gnus-topic-unindent)
(let* ((topic (gnus-current-topic))
- (parent (gnus-topic-previous-topic topic)))
+ (parent (gnus-topic-previous-topic topic))
+ (buffer-read-only nil))
(unless parent
(error "Nothing to indent %s into" topic))
(when topic
(gnus-topic-goto-topic topic)
(gnus-topic-kill-group)
+ (push (cdar gnus-topic-killed-topics) gnus-topic-alist)
(gnus-topic-create-topic
topic parent nil (cdaar gnus-topic-killed-topics))
- (push (cdar gnus-topic-killed-topics) gnus-topic-alist)
(pop gnus-topic-killed-topics)
(or (gnus-topic-goto-topic topic)
(gnus-topic-goto-topic parent))))))
(when topic
(gnus-topic-goto-topic topic)
(gnus-topic-kill-group)
+ (push (cdar gnus-topic-killed-topics) gnus-topic-alist)
(gnus-topic-create-topic
topic grandparent (gnus-topic-next-topic parent)
(cdaar gnus-topic-killed-topics))
- (push (cdar gnus-topic-killed-topics) gnus-topic-alist)
(pop gnus-topic-killed-topics)
(gnus-topic-goto-topic topic))))
(defmacro gnus-eval-in-buffer-window (buffer &rest forms)
"Pop to BUFFER, evaluate FORMS, and then return to the original window."
(let ((tempvar (make-symbol "GnusStartBufferWindow"))
- (w (make-symbol "w"))
- (buf (make-symbol "buf")))
+ (w (make-symbol "w"))
+ (buf (make-symbol "buf")))
`(let* ((,tempvar (selected-window))
- (,buf ,buffer)
- (,w (get-buffer-window ,buf 'visible)))
+ (,buf ,buffer)
+ (,w (get-buffer-window ,buf 'visible)))
(unwind-protect
- (progn
- (if ,w
- (select-window ,w)
- (pop-to-buffer ,buf))
- ,@forms)
- (select-window ,tempvar)))))
+ (progn
+ (if ,w
+ (progn
+ (select-window ,w)
+ (set-buffer (window-buffer ,w)))
+ (pop-to-buffer ,buf))
+ ,@forms)
+ (select-window ,tempvar)))))
(put 'gnus-eval-in-buffer-window 'lisp-indent-function 1)
(put 'gnus-eval-in-buffer-window 'edebug-form-spec '(form body))
(when (setq buf (get-buffer gnus-uu-output-buffer-name))
(kill-buffer buf))))
-;; Inputs an action and a file and returns a full command, putting
-;; quotes round the file name and escaping any quotes in the file name.
+(defun gnus-quote-arg-for-sh-or-csh (arg)
+ (let ((pos 0) new-pos accum)
+ ;; *** bug: we don't handle newline characters properly
+ (while (setq new-pos (string-match "[!`\"$\\& \t]" arg pos))
+ (push (substring arg pos new-pos) accum)
+ (push "\\" accum)
+ (push (list (aref arg new-pos)) accum)
+ (setq pos (1+ new-pos)))
+ (if (= pos 0)
+ arg
+ (apply 'concat (nconc (nreverse accum) (list (substring arg pos)))))))
+
+;; Inputs an action and a filename and returns a full command, making sure
+;; that the filename will be treated as a single argument when the shell
+;; executes the command.
(defun gnus-uu-command (action file)
- (let ((ofile ""))
- (while (string-match "!\\|`\\|\"\\|\\$\\|\\\\\\|&" file)
- (progn
- (setq ofile
- (concat ofile (substring file 0 (match-beginning 0)) "\\"
- (substring file (match-beginning 0) (match-end 0))))
- (setq file (substring file (1+ (match-beginning 0))))))
- (setq ofile (concat "\"" ofile file "\""))
+ (let ((quoted-file (gnus-quote-arg-for-sh-or-csh file)))
(if (string-match "%s" action)
- (format action ofile)
- (concat action " " ofile))))
+ (format action quoted-file)
+ (concat action " " quoted-file))))
(defun gnus-uu-delete-work-dir (&optional dir)
"Delete recursively all files and directories under `gnus-uu-work-dir'."
"Score and kill file handling."
:group 'gnus )
-(defconst gnus-version-number "0.82"
+(defconst gnus-version-number "0.83"
"Version number for this version of Gnus.")
(defconst gnus-version (format "Red Gnus v%s" gnus-version-number)
gnus-article-hide-boring-headers
gnus-article-treat-overstrike
gnus-article-maybe-highlight
- gnus-article-emphasize
gnus-article-display-x-face)
'(gnus-article-hide-headers-if-wanted
gnus-article-hide-boring-headers
gnus-article-treat-overstrike
- gnus-article-emphasize
gnus-article-maybe-highlight))
"Controls how the article buffer will look.
""))
(defun gnus-group-method (group)
- "Return the server or method used for selecting GROUP."
+ "Return the server or method used for selecting GROUP.
+You should probably use `gnus-find-method-for-group' instead."
(let ((prefix (gnus-group-real-prefix group)))
(if (equal prefix "")
gnus-select-method
(nth 1 (assoc method gnus-opened-servers)))
(defun gnus-group-name-to-method (group)
- "Return a select method suitable for GROUP."
+ "Guess a select method based on GROUP."
(if (string-match ":" group)
(let ((server (substring group 0 (match-beginning 0))))
(if (string-match "\\+" server)
(gnus-server-add-address method)))))))
(defun gnus-check-backend-function (func group)
- "Check whether GROUP supports function FUNC."
+ "Check whether GROUP supports function FUNC.
+GROUP can either be a string (a group name) or a select method."
(ignore-errors
(let ((method (if (stringp group)
(car (gnus-find-method-for-group group))
;; Byte-compiler warning
(defvar gnus-active-hashtb)
+(defvar gnus-read-active-file)
;;; Regexp matching the delimiter of messages in UNIX mail format
;;; (UNIX From lines), minus the initial ^.
(hashtb (and (boundp 'gnus-active-hashtb)
gnus-active-hashtb))
errors)
- (if (not hashtb)
+ (if (or (not hashtb)
+ (not (boundp 'gnus-read-active-file))
+ (not gnus-read-active-file)
+ (eq gnus-read-active-file 'some))
t
(while groups
(when (and (not (boundp (intern (car groups) hashtb)))
;; list of buffers.
(setq message-buffer-list (delq (current-buffer) message-buffer-list))
(while (and message-max-buffers
+ message-buffer-list
(>= (length message-buffer-list) message-max-buffers))
;; Kill the oldest buffer -- unless it has been changed.
(let ((buffer (pop message-buffer-list)))
;; If not, we translate dots into slashes.
(concat dir (nnheader-replace-chars-in-string group ?. ?/) "/")))
(or file "")))
-
+
(defun nnmail-date-to-time (date)
"Convert DATE into time."
(condition-case ()
(list
(aref t1 2) (aref t1 1) (aref t1 0)
(aref d1 2) (aref d1 1) (aref d1 0)
- (aref d1 4)))))
+ (number-to-string
+ (* 60 (timezone-zone-to-minute (aref d1 4))))))))
;; If we get an error, then we just return a 0 time.
(error (list 0 0))))
'call-process
(append
(list
- (expand-file-name nnmail-movemail-program
- exec-directory)
+ (expand-file-name
+ nnmail-movemail-program exec-directory)
nil errors nil inbox tofile)
(when nnmail-internal-password
- (list (prin1-to-string nnmail-internal-password)))))))
+ (list nnmail-internal-password))))))
(if (not (buffer-modified-p errors))
;; No output => movemail won
(progn
(nnoo-define-basics nnml)
-(deffoo nnml-retrieve-headers (sequence &optional newsgroup server fetch-old)
- (save-excursion
- (set-buffer nntp-server-buffer)
- (erase-buffer)
- (let ((file nil)
- (number (length sequence))
- (count 0)
- beg article)
- (if (stringp (car sequence))
- 'headers
- (nnml-possibly-change-directory newsgroup server)
- (unless nnml-article-file-alist
- (setq nnml-article-file-alist
- (nnheader-article-to-file-alist nnml-current-directory)))
- (if (nnml-retrieve-headers-with-nov sequence fetch-old)
- 'nov
- (while sequence
- (setq article (car sequence))
- (setq file
- (concat nnml-current-directory
- (or (cdr (assq article nnml-article-file-alist))
- "")))
- (when (and (file-exists-p file)
- (not (file-directory-p file)))
- (insert (format "221 %d Article retrieved.\n" article))
- (setq beg (point))
- (nnheader-insert-head file)
- (goto-char beg)
- (if (search-forward "\n\n" nil t)
- (forward-char -1)
- (goto-char (point-max))
- (insert "\n\n"))
- (insert ".\n")
- (delete-region (point) (point-max)))
- (setq sequence (cdr sequence))
- (setq count (1+ count))
+(deffoo nnml-retrieve-headers (sequence &optional group server fetch-old)
+ (when (nnml-possibly-change-directory group server)
+ (save-excursion
+ (set-buffer nntp-server-buffer)
+ (erase-buffer)
+ (let ((file nil)
+ (number (length sequence))
+ (count 0)
+ beg article)
+ (if (stringp (car sequence))
+ 'headers
+ (unless nnml-article-file-alist
+ (setq nnml-article-file-alist
+ (nnheader-article-to-file-alist nnml-current-directory)))
+ (if (nnml-retrieve-headers-with-nov sequence fetch-old)
+ 'nov
+ (while sequence
+ (setq article (car sequence))
+ (setq file
+ (concat nnml-current-directory
+ (or (cdr (assq article nnml-article-file-alist))
+ "")))
+ (when (and (file-exists-p file)
+ (not (file-directory-p file)))
+ (insert (format "221 %d Article retrieved.\n" article))
+ (setq beg (point))
+ (nnheader-insert-head file)
+ (goto-char beg)
+ (if (search-forward "\n\n" nil t)
+ (forward-char -1)
+ (goto-char (point-max))
+ (insert "\n\n"))
+ (insert ".\n")
+ (delete-region (point) (point-max)))
+ (setq sequence (cdr sequence))
+ (setq count (1+ count))
+ (and (numberp nnmail-large-newsgroup)
+ (> number nnmail-large-newsgroup)
+ (zerop (% count 20))
+ (nnheader-message 6 "nnml: Receiving headers... %d%%"
+ (/ (* count 100) number))))
+
(and (numberp nnmail-large-newsgroup)
(> number nnmail-large-newsgroup)
- (zerop (% count 20))
- (nnheader-message 6 "nnml: Receiving headers... %d%%"
- (/ (* count 100) number))))
+ (nnheader-message 6 "nnml: Receiving headers...done"))
- (and (numberp nnmail-large-newsgroup)
- (> number nnmail-large-newsgroup)
- (nnheader-message 6 "nnml: Receiving headers...done"))
-
- (nnheader-fold-continuation-lines)
- 'headers)))))
+ (nnheader-fold-continuation-lines)
+ 'headers))))))
(deffoo nnml-open-server (server &optional defs)
(nnoo-change-server 'nnml server defs)
(nnml-possibly-change-directory nil server)
(nnml-generate-nov-databases))
-(deffoo nnml-request-article (id &optional newsgroup server buffer)
- (nnml-possibly-change-directory newsgroup server)
+(deffoo nnml-request-article (id &optional group server buffer)
+ (nnml-possibly-change-directory group server)
(let* ((nntp-server-buffer (or buffer nntp-server-buffer))
path gpath group-num)
(if (stringp id)
(t
(nnheader-report 'nnml "Article %s retrieved" id)
;; We return the article number.
- (cons newsgroup (string-to-int (file-name-nondirectory path)))))))
+ (cons group (string-to-int (file-name-nondirectory path)))))))
(deffoo nnml-request-group (group &optional server dont-check)
(cond
(save-excursion
(nnmail-find-file nnml-newsgroups-file)))
-(deffoo nnml-request-expire-articles (articles newsgroup
+(deffoo nnml-request-expire-articles (articles group
&optional server force)
- (nnml-possibly-change-directory newsgroup server)
+ (nnml-possibly-change-directory group server)
(let* ((active-articles
(nnheader-directory-articles nnml-current-directory))
(is-old t)
nnml-article-file-alist))
(setq article (concat nnml-current-directory (cdr article)))
(when (setq mod-time (nth 5 (file-attributes article)))
- (if (and (nnml-deletable-article-p newsgroup number)
+ (if (and (nnml-deletable-article-p group number)
(setq is-old
- (nnmail-expired-article-p newsgroup mod-time force
+ (nnmail-expired-article-p group mod-time force
nnml-inhibit-expiry)))
(progn
(nnheader-message 5 "Deleting article %s in %s"
- article newsgroup)
+ article group)
(condition-case ()
(funcall nnmail-delete-file-function article)
(file-error
(push number rest)))
(setq active-articles (delq number active-articles))
- (nnml-nov-delete-article newsgroup number))
+ (nnml-nov-delete-article group number))
(push number rest)))))
- (let ((active (nth 1 (assoc newsgroup nnml-group-alist))))
+ (let ((active (nth 1 (assoc group nnml-group-alist))))
(when active
(setcar active (or (and active-articles
(apply 'min active-articles))
(when (and server
(not (nnml-server-opened server)))
(nnml-open-server server))
- (when group
+ (if (not group)
+ t
(let ((pathname (nnmail-group-pathname group nnml-directory)))
(when (not (equal pathname nnml-current-directory))
(setq nnml-current-directory pathname
nnml-current-group group
- nnml-article-file-alist nil))))
- t)
+ nnml-article-file-alist nil))
+ (file-exists-p nnml-current-directory))))
(defun nnml-possibly-create-directory (group)
(let (dir dirs)
(while (looking-at "From ")
(replace-match "X-From-Line: ")
(forward-line 1))
- ;; We save the article in all the newsgroups it belongs in.
+ ;; We save the article in all the groups it belongs in.
(let ((ga group-art)
first)
(while ga
(defun nnoo-define-skeleton-1 (backend)
(let ((functions '(retrieve-headers
request-close request-article
- open-group request-group close-group
+ request-group close-group
request-list request-post request-list-newsgroups))
function fun)
(while (setq function (pop functions))
(defvoo nnsoup-buffers nil)
(defvoo nnsoup-current-group nil)
(defvoo nnsoup-group-alist-touched nil)
+(defvoo nnsoup-article-alist nil)
\f
;;; Internal functions
(defun nnsoup-possibly-change-group (group &optional force)
- (if group
- (setq nnsoup-current-group group)
- t))
+ (when (and group
+ (not (equal nnsoup-current-group group)))
+ (setq nnsoup-article-alist nil)
+ (setq nnsoup-current-group group))
+ t)
(defun nnsoup-read-active-file ()
(setq nnsoup-group-alist nil)
(incf nnsoup-current-prefix)
prefix))
+(defun nnsoup-file-name (dir file)
+ "Return the full path of FILE (in any case) in DIR."
+ (let* ((case-fold-search t)
+ (files (directory-files dir t (concat (regexp-quote file) "$"))))
+ (car files)))
+
(defun nnsoup-read-areas ()
- (when (file-exists-p (concat nnsoup-tmp-directory "AREAS"))
- (save-excursion
- (set-buffer nntp-server-buffer)
- (let ((areas (gnus-soup-parse-areas
- (concat nnsoup-tmp-directory "AREAS")))
- entry number area lnum cur-prefix file)
- ;; Go through all areas in the new AREAS file.
- (while (setq area (pop areas))
- ;; Change the name to the permanent name and move the files.
- (setq cur-prefix (nnsoup-next-prefix))
- (message "Incorporating file %s..." cur-prefix)
- (when (file-exists-p
- (setq file (concat nnsoup-tmp-directory
- (gnus-soup-area-prefix area) ".IDX")))
- (rename-file file (nnsoup-file cur-prefix)))
- (when (file-exists-p
- (setq file (concat nnsoup-tmp-directory
- (gnus-soup-area-prefix area) ".MSG")))
- (rename-file file (nnsoup-file cur-prefix t))
- (gnus-soup-set-area-prefix area cur-prefix)
- ;; Find the number of new articles in this area.
- (setq number (nnsoup-number-of-articles area))
- (if (not (setq entry (assoc (gnus-soup-area-name area)
- nnsoup-group-alist)))
- ;; If this is a new area (group), we just add this info to
- ;; the group alist.
- (push (list (gnus-soup-area-name area)
- (cons 1 number)
- (list (cons 1 number) area))
- nnsoup-group-alist)
- ;; There are already articles in this group, so we add this
- ;; info to the end of the entry.
- (nconc entry (list (list (cons (1+ (setq lnum (cdadr entry)))
- (+ lnum number))
- area)))
- (setcdr (cadr entry) (+ lnum number))))))
- (nnsoup-write-active-file t)
- (delete-file (concat nnsoup-tmp-directory "AREAS")))))
+ (let ((areas-file (nnsoup-file-name nnsoup-tmp-directory "areas")))
+ (when areas-file
+ (save-excursion
+ (set-buffer nntp-server-buffer)
+ (let ((areas (gnus-soup-parse-areas areas-file))
+ entry number area lnum cur-prefix file)
+ ;; Go through all areas in the new AREAS file.
+ (while (setq area (pop areas))
+ ;; Change the name to the permanent name and move the files.
+ (setq cur-prefix (nnsoup-next-prefix))
+ (message "Incorporating file %s..." cur-prefix)
+ (when (file-exists-p
+ (setq file (concat nnsoup-tmp-directory
+ (gnus-soup-area-prefix area) ".IDX")))
+ (rename-file file (nnsoup-file cur-prefix)))
+ (when (file-exists-p
+ (setq file (concat nnsoup-tmp-directory
+ (gnus-soup-area-prefix area) ".MSG")))
+ (rename-file file (nnsoup-file cur-prefix t))
+ (gnus-soup-set-area-prefix area cur-prefix)
+ ;; Find the number of new articles in this area.
+ (setq number (nnsoup-number-of-articles area))
+ (if (not (setq entry (assoc (gnus-soup-area-name area)
+ nnsoup-group-alist)))
+ ;; If this is a new area (group), we just add this info to
+ ;; the group alist.
+ (push (list (gnus-soup-area-name area)
+ (cons 1 number)
+ (list (cons 1 number) area))
+ nnsoup-group-alist)
+ ;; There are already articles in this group, so we add this
+ ;; info to the end of the entry.
+ (nconc entry (list (list (cons (1+ (setq lnum (cdadr entry)))
+ (+ lnum number))
+ area)))
+ (setcdr (cadr entry) (+ lnum number))))))
+ (nnsoup-write-active-file t)
+ (delete-file areas-file)))))
(defun nnsoup-number-of-articles (area)
(save-excursion
;; buffer.
(t
(set-buffer (nnsoup-message-buffer (gnus-soup-area-prefix area)))
- (goto-char (point-min))
- (let ((regexp (nnsoup-header (gnus-soup-encoding-format
- (gnus-soup-area-encoding area))))
- (num 0))
- (while (re-search-forward regexp nil t)
- (setq num (1+ num)))
- num)))))
+ (unless (assoc (gnus-soup-area-prefix area) nnsoup-article-alist)
+ (nnsoup-dissect-buffer area))
+ (length (cdr (assoc (gnus-soup-area-prefix area)
+ nnsoup-article-alist)))))))
+
+(defun nnsoup-dissect-buffer (area)
+ (let ((mbox-delim (concat "^" message-unix-mail-delimiter))
+ (format (gnus-soup-encoding-format (gnus-soup-area-encoding area)))
+ (i 0)
+ alist len)
+ (goto-char (point-min))
+ (cond
+ ;; rnews batch format
+ ((= format ?n)
+ (while (looking-at "^#! *rnews \\(+[0-9]+\\) *$")
+ (forward-line 1)
+ (push (list
+ (incf i) (point)
+ (progn
+ (forward-char (string-to-number (match-string 1)))
+ (point)))
+ alist)))
+ ;; Unix mbox format
+ ((= format ?m)
+ (while (looking-at mbox-delim)
+ (forward-line 1)
+ (push (list
+ (incf i) (point)
+ (progn
+ (if (re-search-forward mbox-delim nil t)
+ (beginning-of-line)
+ (goto-char (point-max)))
+ (point)))
+ alist)))
+ ;; MMDF format
+ ((= format ?M)
+ (while (looking-at "\^A\^A\^A\^A\n")
+ (forward-line 1)
+ (push (list
+ (incf i) (point)
+ (progn
+ (if (search-forward "\n\^A\^A\^A\^A\n" nil t)
+ (beginning-of-line)
+ (goto-char (point-max)))
+ (point)))
+ alist)))
+ ;; Binary format
+ ((or (= format ?B) (= format ?b))
+ (while (not (eobp))
+ (setq len (+ (* (char-after (point)) (expt 2.0 24))
+ (* (char-after (+ (point) 1)) (expt 2 16))
+ (* (char-after (+ (point) 2)) (expt 2 8))
+ (char-after (+ (point) 3))))
+ (push (list
+ (incf i) (+ (point) 4)
+ (progn
+ (forward-char (floor (+ len 4)))
+ (point)))
+ alist)))
+ (t
+ (error "Unknown format: %c" format)))
+ (push (cons (gnus-soup-area-prefix area) alist) nnsoup-article-alist)))
(defun nnsoup-index-buffer (prefix &optional message)
(let* ((file (concat prefix (if message ".MSG" ".IDX")))
(t
(set-buffer msg-buf)
(widen)
- (goto-char (point-min))
- (let ((header (nnsoup-header
- (gnus-soup-encoding-format
- (gnus-soup-area-encoding (nth 1 area))))))
- (re-search-forward header nil t (- article (caar area)))
- (narrow-to-region
- (match-beginning 0)
- (if (re-search-forward header nil t)
- (match-beginning 0)
- (point-max))))))
+ (unless (assoc (gnus-soup-area-prefix (nth 1 area))
+ nnsoup-article-alist)
+ (nnsoup-dissect-buffer (nth 1 area)))
+ (let ((entry (assq article (cdr (assoc (gnus-soup-area-prefix
+ (nth 1 area))
+ nnsoup-article-alist)))))
+ (when entry
+ (narrow-to-region (cadr entry) (caddr entry))))))
(goto-char (point-min))
(if (not head)
()
(point-max))))
msg-buf))))
-(defun nnsoup-header (format)
- (cond
- ((= format ?n)
- "^#! *rnews +[0-9]+ *$")
- ((= format ?m)
- (concat "^" message-unix-mail-delimiter))
- ((= format ?M)
- "^\^A\^A\^A\^A\n")
- (t
- (error "Unknown format: %c" format))))
-
;;;###autoload
(defun nnsoup-pack-replies ()
"Make an outbound package of SOUP replies."
;;; Internal variables.
+(defvar nntp-have-messaged nil)
+
(defvar nntp-process-wait-for nil)
(defvar nntp-process-to-buffer nil)
(defvar nntp-process-callback nil)
(goto-char (point-max))
(insert-buffer-substring (process-buffer process))
;; Nix out "nntp reading...." message.
- (message "")
+ (when nntp-have-messaged
+ (setq nntp-have-messaged nil)
+ (message ""))
t)))
(unless discard
(erase-buffer)))))
nntp-server-buffer))
(let ((len (/ (point-max) 1024)))
(unless (< len 10)
+ (setq nntp-have-messaged t)
(message "nntp read: %dk" len)))
(accept-process-output process 1)))
+Fri Jan 24 05:07:28 1997 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * gnus.texi (Summary Mail Commands): Addition.
+ (Required Backend Functions): Deletia.
+
+Mon Jan 20 22:19:40 1997 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
+
+ * gnus.texi (Followups To Yourself): Fix.
+
Fri Jan 17 00:55:51 1997 Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
* gnus.texi (NoCeM): Update.
\input texinfo @c -*-texinfo-*-
@setfilename gnus
-@settitle Red Gnus 0.82 Manual
+@settitle Red Gnus 0.83 Manual
@synindex fn cp
@synindex vr cp
@synindex pg cp
@tex
@titlepage
-@title Red Gnus 0.82 Manual
+@title Red Gnus 0.83 Manual
@author by Lars Magne Ingebrigtsen
@page
spool or your mbox file. All at the same time, if you want to push your
luck.
-This manual corresponds to Red Gnus 0.82
+This manual corresponds to Red Gnus 0.83
@end ifinfo
original message (@code{gnus-summary-reply-with-original}). This
command uses the process/prefix convention.
+@item S w
+@kindex S w (Summary)
+@findex gnus-summary-wide-reply
+Mail a wide reply to the author of the current article
+(@code{gnus-summary-wide-reply}).
+
+@item S W
+@kindex S W (Summary)
+@findex gnus-summary-wide-reply-with-original
+Mail a wide reply to the current article and include the original
+message (@code{gnus-summary-reply-with-original}). This command uses
+the process/prefix convention.
+
@item S o m
@kindex S o m (Summary)
@findex gnus-summary-mail-forward
myself:
@lisp
-("references"
- "<x6[0-9a-z]+\\.fsf@@.*eyesore.no>" 1000 nil r)
+("references"
+ ("<x6[0-9a-z]+\\.fsf@.*eyesore.no>" 1000 nil r))
@end lisp
Whether it's the first two or first three characters that are ``yours''
coming from @code{tin} and @code{Netscape} I know not to use either of
those for posting articles. I would not have known that if it wasn't
for the @code{X-Newsreader} header.
-
-@item References
-Gnus does line breaking on this header. I infer from RFC1036 that being
-conservative in what you output is not creating 5000-character lines, so
-it seems like a good idea to me. However, this standard-to-be says that
-whitespace in the @code{References} header is to be preserved, so... It
-doesn't matter one way or the other to Gnus, so if somebody tells me
-what The Way is, I'll change it. Or not.
@end table
@end table
on successful article retrievement.
-@item (nnchoke-open-group GROUP &optional SERVER)
-
-Make @var{group} the current group.
-
-There should be no data returned by this function.
-
-
@item (nnchoke-request-group GROUP &optional SERVER FAST)
Get data on @var{group}. This function also has the side effect of