(require 'mail-utils)
(require 'timezone)
(require 'nnheader)
+(require 'message)
(eval-when-compile (require 'cl))
variable, or returned by the function) is a file name, the contents of
this file will be used as the organization.")
-(defvar gnus-use-generic-from nil
- "If nil, the full host name will be the system name prepended to the domain name.
-If this is a string, the full host name will be this string.
-If this is non-nil, non-string, the domain name will be used as the
-full host name.")
-
-(defvar gnus-use-generic-path nil
- "If nil, use the NNTP server name in the Path header.
-If stringp, use this; if non-nil, use no host name (user name only).")
-
;; Customization variables
;; Don't touch this variable.
(defvar gnus-group-faq-directory
'("/ftp@mirrors.aol.com:/pub/rtfm/usenet/"
+ "/ftp@sunsite.auc.dk:/pub/usenet/"
"/ftp@src.doc.ic.ac.uk:/usenet/news-FAQS/"
"/ftp@ftp.seas.gwu.edu:/pub/rtfm/"
- "/ftp@rtfm.mit.edu:/pub/usenet/news.answers/"
+ "/ftp@rtfm.mit.edu:/pub/usenet/"
"/ftp@ftp.uni-paderborn.de:/pub/FAQ/"
"/ftp@ftp.sunet.se:/pub/usenet/"
"/ftp@nctuccca.edu.tw:/USENET/FAQ/"
- "/ftp@hwarang.postech.ac.kr:/pub/usenet/news.answers/"
+ "/ftp@hwarang.postech.ac.kr:/pub/usenet/"
"/ftp@ftp.hk.super.net:/mirror/faqs/")
"*Directory where the group FAQs are stored.
This will most commonly be on a remote machine, and the file will be
North America: mirrors.aol.com /pub/rtfm/usenet
ftp.seas.gwu.edu /pub/rtfm
- rtfm.mit.edu /pub/usenet/news.answers
+ rtfm.mit.edu /pub/usenet
Europe: ftp.uni-paderborn.de /pub/FAQ
src.doc.ic.ac.uk /usenet/news-FAQS
ftp.sunet.se /pub/usenet
+ sunsite.auc.dk /pub/usenet
Asia: nctuccca.edu.tw /USENET/FAQ
- hwarang.postech.ac.kr /pub/usenet/news.answers
+ hwarang.postech.ac.kr /pub/usenet
ftp.hk.super.net /mirror/faqs")
(defvar gnus-group-archive-directory
(vertical 1.0
(browse 1.0 point)
(if gnus-carpal '(browse-carpal 2))))
- (group-mail
- (vertical 1.0
- (mail 1.0 point)))
- (group-post
- (vertical 1.0
- (post 1.0 point)))
- (summary-mail
- (vertical 1.0
- (mail 1.0 point)))
- (summary-reply
+ (message
(vertical 1.0
- (article-copy 0.5)
- (mail 1.0 point)))
+ (message 1.0 point)))
(pick
(vertical 1.0
(article 1.0 point)))
(reply
(vertical 1.0
(article-copy 0.5)
- (mail 1.0 point)))
- (mail-forward
- (vertical 1.0
- (mail 1.0 point)))
- (post-forward
+ (message 1.0 point)))
+ (forward
(vertical 1.0
- (post 1.0 point)))
+ (message 1.0 point)))
(reply-yank
(vertical 1.0
- (mail 1.0 point)))
+ (message 1.0 point)))
(mail-bounce
(vertical 1.0
(article 0.5)
- (mail 1.0 point)))
+ (message 1.0 point)))
(draft
(vertical 1.0
(draft 1.0 point)))
(summary 0.25 point)
(if gnus-carpal '(summary-carpal 4))
("*Shell Command Output*" 1.0)))
- (followup
+ (bug
(vertical 1.0
- (article-copy 0.5)
- (post 1.0 point)))
- (followup-yank
+ ("*Gnus Help Bug*" 0.5)
+ ("*Gnus Bug*" 1.0 point)))
+ (compose-bounce
(vertical 1.0
- (post 1.0 point))))
+ (article 0.5)
+ (message 1.0 point))))
"Window configuration for all possible Gnus buffers.
This variable is a list of lists. Each of these lists has a NAME and
a RULE. The NAMEs are commonsense names like `group', which names a
(server-carpal . gnus-carpal-server-buffer)
(browse-carpal . gnus-carpal-browse-buffer)
(edit-score . gnus-score-edit-buffer)
- (mail . gnus-mail-buffer)
- (post . gnus-post-news-buffer)
+ (message . gnus-message-buffer)
+ (mail . gnus-message-buffer)
+ (post-news . gnus-message-buffer)
(faq . gnus-faq-buffer)
(picons . "*Picons*")
(tree . gnus-tree-buffer)
`gnus-subscribe-alphabetically' inserts new groups in strict
alphabetic order; `gnus-subscribe-hierarchically' inserts new groups
in hierarchical newsgroup order; `gnus-subscribe-interactively' asks
-for your decision; `gnus-subscribe-killed' kills all new groups.")
+for your decision; `gnus-subscribe-killed' kills all new groups;
+`gnus-subscribe-zombies' will make all new groups into zombies.")
;; Suggested by a bug report by Hallvard B Furuseth.
;; <h.b.furuseth@usit.uio.no>.
%z Article zcore (character)
%t Number of articles under the current thread (number).
%e Whether the thread is empty or not (character).
-%l GroupLens score (number)
+%l GroupLens score (string).
%u User defined specifier. The next character in the format string should
be a letter. Gnus will call the function gnus-user-format-function-X,
where X is the letter following %u. The function will be passed the
"Property list to use for hiding text.")
(defvar gnus-modtime-botch nil
- "*Non-nil means .newsrc should be deleted prior to save. Its use is
-due to the bogus appearance that .newsrc was modified on disc.")
+ "*Non-nil means .newsrc should be deleted prior to save.
+Its use is due to the bogus appearance that .newsrc was modified on
+disc.")
;; Hooks.
(defvar gnus-parse-headers-hook nil
"*A hook called before parsing the headers.")
+(add-hook 'gnus-parse-headers-hook 'gnus-decode-rfc1522)
(defvar gnus-exit-group-hook nil
"*A hook called when exiting (not quitting) summary mode.")
(remove-hook 'gnus-summary-prepare-hook
'hilit-rehighlight-buffer-quietly)
(remove-hook 'gnus-summary-prepare-hook 'hilit-install-line-hooks)
- (setq gnus-mark-article-hook '(gnus-summary-mark-read-and-unread-as-read))
+ (setq gnus-mark-article-hook
+ '(gnus-summary-mark-read-and-unread-as-read))
(remove-hook 'gnus-article-prepare-hook
'hilit-rehighlight-buffer-quietly)))
\f
;; Internal variables
+(defvar gnus-tree-buffer "*Tree*"
+ "Buffer where Gnus thread trees are displayed.")
+
+;; Dummy variable.
+(defvar gnus-use-generic-from nil)
+
+(defvar gnus-thread-indent-array nil)
+(defvar gnus-thread-indent-array-level gnus-thread-indent-level)
+
+(defvar gnus-newsrc-file-version nil)
+
+(defvar gnus-method-history nil)
+;; Variable holding the user answers to all method prompts.
+
+(defvar gnus-group-history nil)
+;; Variable holding the user answers to all group prompts.
+
(defvar gnus-server-alist nil
"List of available servers.")
-(defvar gnus-topic-active-topology nil)
-(defvar gnus-topic-active-alist nil)
+(defvar gnus-group-indentation-function nil)
(defvar gnus-topic-indentation "") ;; Obsolete variable.
(defvar gnus-opened-servers nil)
(defvar gnus-current-move-group nil)
+(defvar gnus-current-copy-group nil)
+(defvar gnus-current-crosspost-group nil)
(defvar gnus-newsgroup-dependencies nil)
(defvar gnus-newsgroup-async nil)
"gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)"
"The mail address of the Gnus maintainers.")
-(defconst gnus-version "September Gnus v0.50"
+(defconst gnus-version "September Gnus v0.89"
"Version number for this version of Gnus.")
(defvar gnus-info-nodes
- '((gnus-group-mode "(gnus)The Group Buffer")
- (gnus-summary-mode "(gnus)The Summary Buffer")
- (gnus-article-mode "(gnus)The Article Buffer"))
+ '((gnus-group-mode "(gnus)The Group Buffer")
+ (gnus-summary-mode "(gnus)The Summary Buffer")
+ (gnus-article-mode "(gnus)The Article Buffer"))
"Assoc list of major modes and related Info nodes.")
(defvar gnus-group-buffer "*Group*")
gnus-last-article gnus-article-internal-prepare-hook
gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
gnus-newsgroup-scored gnus-newsgroup-kill-headers
- gnus-newsgroup-async
+ gnus-newsgroup-async gnus-thread-expunge-below
gnus-score-alist gnus-current-score-file gnus-summary-expunge-below
gnus-summary-mark-below gnus-newsgroup-active gnus-scores-exclude-files
gnus-newsgroup-history gnus-newsgroup-ancient
gnus-group-brew-soup gnus-brew-soup gnus-soup-add-article
gnus-soup-send-replies gnus-soup-save-areas gnus-soup-pack-packet)
("nnsoup" nnsoup-pack-replies)
+ ("gnus-scomo" :interactive t gnus-score-mode)
("gnus-mh" gnus-mh-mail-setup gnus-summary-save-article-folder
gnus-Folder-save-name gnus-folder-save-name)
("gnus-mh" :interactive t gnus-summary-save-in-folder)
("gnus-srvr" gnus-browse-foreign-server)
("gnus-cite" :interactive t
gnus-article-highlight-citation gnus-article-hide-citation-maybe
- gnus-article-hide-citation gnus-article-fill-cited-article)
+ gnus-article-hide-citation gnus-article-fill-cited-article
+ gnus-article-hide-citation-in-followups)
("gnus-kill" gnus-kill gnus-apply-kill-file-internal
gnus-kill-file-edit-file gnus-kill-file-raise-followups-to-author
gnus-execute gnus-expunge)
(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")))
- `(let ((,tempvar (selected-window)))
+ (let ((tempvar (make-symbol "GnusStartBufferWindow"))
+ (w (make-symbol "w"))
+ (buf (make-symbol "buf")))
+ `(let* ((,tempvar (selected-window))
+ (,buf ,buffer)
+ (,w (get-buffer-window ,buf 'visible)))
(unwind-protect
(progn
- (pop-to-buffer ,buffer)
+ (if ,w
+ (select-window ,w)
+ (pop-to-buffer ,buf))
,@forms)
(select-window ,tempvar)))))
(substring subject (match-end 0))
subject))
+(defsubst gnus-functionp (form)
+ "Return non-nil if FORM is funcallable."
+ (or (and (symbolp form) (fboundp form))
+ (and (listp form) (eq (car form) 'lambda))))
+
(defsubst gnus-goto-char (point)
(and point (goto-char point)))
(require 'gnus-cus)
(require 'gnus-ems)
+\f
+;;;
+;;; Shutdown
+;;;
+
+(defvar gnus-shutdown-alist nil)
+
+(defun gnus-add-shutdown (function &rest symbols)
+ "Run FUNCTION whenever one of SYMBOLS is shut down."
+ (push (cons function symbols) gnus-shutdown-alist))
+
+(defun gnus-shutdown (symbol)
+ "Shut down everything that waits for SYMBOL."
+ (let ((alist gnus-shutdown-alist)
+ entry)
+ (while (setq entry (pop alist))
+ (when (memq symbol (cdr entry))
+ (funcall (car entry))))))
+
\f
;; Format specs. The chunks below are the machine-generated forms
(defun gnus-summary-line-format-spec ()
(insert gnus-tmp-unread gnus-tmp-replied
gnus-tmp-score-char gnus-tmp-indentation)
- (put-text-property
+ (gnus-put-text-property
(point)
(progn
(insert
(defun gnus-summary-dummy-line-format-spec ()
(insert "* ")
- (put-text-property
+ (gnus-put-text-property
(point)
(progn
(insert ": :")
gnus-tmp-process-marked
gnus-group-indentation
(format "%5s: " gnus-tmp-number-of-unread))
- (put-text-property
+ (gnus-put-text-property
(point)
(progn
(insert gnus-tmp-group "\n")
"Return the value of the header FIELD of current article."
(save-excursion
(save-restriction
- (let ((case-fold-search t))
+ (let ((case-fold-search t)
+ (inhibit-point-motion-hooks t))
(nnheader-narrow-to-headers)
(mail-fetch-field field)))))
(push (list type new-format val) gnus-format-specs))
(set (intern (format "gnus-%s-line-format-spec" type)) val))))
+ (unless (assq 'version gnus-format-specs)
+ (push (cons 'version emacs-version) gnus-format-specs))
+
(gnus-update-group-mark-positions)
(gnus-update-summary-mark-positions))
(defun gnus-update-summary-mark-positions ()
"Compute where the summary marks are to go."
(save-excursion
+ (when (and gnus-summary-buffer
+ (get-buffer gnus-summary-buffer)
+ (buffer-name (get-buffer gnus-summary-buffer)))
+ (set-buffer gnus-summary-buffer))
(let ((gnus-replied-mark 129)
(gnus-score-below-mark 130)
(gnus-score-over-mark 130)
(thread nil)
(gnus-visual nil)
+ (spec gnus-summary-line-format-spec)
pos)
- (gnus-set-work-buffer)
- (gnus-summary-insert-line
- [0 "" "" "" "" "" 0 0 ""] 0 nil 128 t nil "" nil 1)
- (goto-char (point-min))
- (setq pos (list (cons 'unread (and (search-forward "\200" nil t)
- (- (point) 2)))))
- (goto-char (point-min))
- (push (cons 'replied (and (search-forward "\201" nil t) (- (point) 2)))
- pos)
- (goto-char (point-min))
- (push (cons 'score (and (search-forward "\202" nil t) (- (point) 2)))
- pos)
+ (save-excursion
+ (gnus-set-work-buffer)
+ (let ((gnus-summary-line-format-spec spec))
+ (gnus-summary-insert-line
+ [0 "" "" "" "" "" 0 0 ""] 0 nil 128 t nil "" nil 1)
+ (goto-char (point-min))
+ (setq pos (list (cons 'unread (and (search-forward "\200" nil t)
+ (- (point) 2)))))
+ (goto-char (point-min))
+ (push (cons 'replied (and (search-forward "\201" nil t)
+ (- (point) 2)))
+ pos)
+ (goto-char (point-min))
+ (push (cons 'score (and (search-forward "\202" nil t) (- (point) 2)))
+ pos)))
(setq gnus-summary-mark-positions pos))))
(defun gnus-update-group-mark-positions ()
(save-excursion
(let ((gnus-process-mark 128)
- (gnus-group-marked '("dummy.group")))
+ (gnus-group-marked '("dummy.group"))
+ (gnus-active-hashtb (make-vector 10 0)))
(gnus-set-active "dummy.group" '(0 . 0))
(gnus-set-work-buffer)
(gnus-group-insert-group-line "dummy.group" 0 nil 0 nil)
(defvar gnus-mouse-face-4 'highlight)
(defun gnus-mouse-face-function (form type)
- `(put-text-property
+ `(gnus-put-text-property
(point) (progn ,@form (point))
gnus-mouse-face-prop
,(if (equal type 0)
(defvar gnus-face-4 'bold)
(defun gnus-face-face-function (form type)
- `(put-text-property
+ `(gnus-put-text-property
(point) (progn ,@form (point))
'face ',(symbol-value (intern (format "gnus-face-%d" type)))))
If PROPS, insert the result."
(let ((form (gnus-parse-format format alist props)))
(if props
- (add-text-properties (point) (progn (eval form) (point)) props)
+ (gnus-add-text-properties (point) (progn (eval form) (point)) props)
(eval form))))
(defun gnus-remove-text-with-property (prop)
;; Written by Stainless Steel Rat <ratinox@ccs.neu.edu>.
(defun gnus-simplify-buffer-fuzzy ()
(goto-char (point-min))
- (re-search-forward "^[ \t]*\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;][ \t]*" nil t)
+ (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
- (looking-at "^[ \t]*\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;][ \t]*")
- (looking-at "^[[].*:[ \t].*[]]$"))
+ (looking-at "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *")
+ (looking-at "^[[].*: .*[]]$"))
(goto-char (point-min))
- (while (re-search-forward "^[ \t]*\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;][ \t]*"
+ (while (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *"
nil t)
(replace-match "" t t))
(goto-char (point-min))
- (while (re-search-forward "^[[].*:[ \t].*[]]$" nil t)
+ (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 "[ \t\n]*[[{(][^()\n]*[]})][ \t]*$" nil t)
+ (while (re-search-forward " *[[{(][^()\n]*[]})] *$" nil t)
(replace-match "" t t))
(goto-char (point-min))
- (while (re-search-forward "[ \t]+" nil t)
+ (while (re-search-forward " +" nil t)
(replace-match " " t t))
(goto-char (point-min))
- (while (re-search-forward "[ \t]+$" nil t)
+ (while (re-search-forward " $" nil t)
(replace-match "" t t))
(goto-char (point-min))
- (while (re-search-forward "^[ \t]+" nil t)
+ (while (re-search-forward "^ +" nil t)
(replace-match "" t t))
(goto-char (point-min))
- (if gnus-simplify-subject-fuzzy-regexp
- (if (listp gnus-simplify-subject-fuzzy-regexp)
- (let ((list gnus-simplify-subject-fuzzy-regexp))
- (while list
- (goto-char (point-min))
- (while (re-search-forward (car list) nil t)
- (replace-match "" t t))
- (setq list (cdr list))))
- (while (re-search-forward gnus-simplify-subject-fuzzy-regexp nil t)
- (replace-match "" t t)))))
+ (when gnus-simplify-subject-fuzzy-regexp
+ (if (listp gnus-simplify-subject-fuzzy-regexp)
+ (let ((list gnus-simplify-subject-fuzzy-regexp))
+ (while list
+ (goto-char (point-min))
+ (while (re-search-forward (car list) nil t)
+ (replace-match "" t t))
+ (setq list (cdr list))))
+ (while (re-search-forward gnus-simplify-subject-fuzzy-regexp nil t)
+ (replace-match "" t t)))))
(defun gnus-simplify-subject-fuzzy (subject)
"Siplify a subject string fuzzily."
(not (or (string< s1 s2)
(string= s1 s2))))
+(defun gnus-read-active-file-p ()
+ "Say whether the active file has been read from `gnus-select-method'."
+ (memq gnus-select-method gnus-have-read-active-file))
+
;;; General various misc type functions.
(defun gnus-clear-system ()
gnus-active-hashtb nil
gnus-moderated-list nil
gnus-description-hashtb nil
+ gnus-current-headers nil
+ gnus-thread-indent-array nil
gnus-newsgroup-headers nil
gnus-newsgroup-name nil
gnus-server-alist nil
gnus-group-list-mode nil
- gnus-topic-active-topology nil
- gnus-topic-active-alist nil
gnus-opened-servers nil
gnus-current-select-method nil)
- ;; Reset any score variables.
- (when gnus-use-scoring
- (gnus-score-close))
+ (gnus-shutdown 'gnus)
;; Kill the startup file.
(and gnus-current-startup-file
(get-file-buffer gnus-current-startup-file)
(kill-buffer (get-file-buffer gnus-current-startup-file)))
- ;; Save any cache buffers.
- (when gnus-use-cache
- (gnus-cache-save-buffers))
;; Clear the dribble buffer.
(gnus-dribble-clear)
- ;; Close down NoCeM.
- (when gnus-use-nocem
- (gnus-nocem-close))
- ;; Shut down the demons.
- (when gnus-use-demon
- (gnus-demon-cancel))
;; Kill global KILL file buffer.
(when (get-file-buffer (gnus-newsgroup-kill-file nil))
(kill-buffer (get-file-buffer (gnus-newsgroup-kill-file nil))))
(gnus-kill-buffer nntp-server-buffer)
- ;; Backlog.
- (when gnus-keep-backlog
- (gnus-backlog-shutdown))
;; Kill Gnus buffers.
(while gnus-buffer-list
(gnus-kill-buffer (pop gnus-buffer-list)))
(let ((split (if (symbolp setting)
(cadr (assq setting gnus-buffer-configuration))
setting))
- (in-buf (current-buffer))
- rule val w height hor ohor heights sub jump-buffer
- rel total to-buf all-visible)
+ all-visible)
(setq gnus-frame-split-p nil)
(gnus-configure-frame split (get-buffer-window (current-buffer))))))
(defun gnus-all-windows-visible-p (split)
- (when (vectorp split)
- (setq split (append split nil)))
- (when (or (consp (car split))
- (vectorp (car split)))
- (push 1.0 split)
- (push 'vertical split))
- ;; The SPLIT might be something that is to be evaled to
- ;; return a new SPLIT.
- (while (and (not (assq (car split) gnus-window-to-buffer))
- (gnus-functionp (car split)))
- (setq split (eval split)))
- (let* ((type (elt split 0)))
- (cond
- ((null split)
- t)
- ((not (or (eq type 'horizontal) (eq type 'vertical) (eq type 'frame)))
- (let ((buffer (cond ((stringp type) type)
- (t (cdr (assq type gnus-window-to-buffer)))))
- win buf)
+ "Say whether all buffers in SPLIT are currently visible.
+In particular, the value returned will be the window that
+should have point."
+ (let ((stack (list split))
+ (all-visible t)
+ type buffer win buf)
+ (while (and (setq split (pop stack))
+ all-visible)
+ ;; Be backwards compatible.
+ (when (vectorp split)
+ (setq split (append split nil)))
+ (when (or (consp (car split))
+ (vectorp (car split)))
+ (push 1.0 split)
+ (push 'vertical split))
+ ;; The SPLIT might be something that is to be evaled to
+ ;; return a new SPLIT.
+ (while (and (not (assq (car split) gnus-window-to-buffer))
+ (gnus-functionp (car split)))
+ (setq split (eval split)))
+
+ (setq type (elt split 0))
+ (cond
+ ;; Nothing here.
+ ((null split) t)
+ ;; A buffer.
+ ((not (memq type '(horizontal vertical frame)))
+ (setq buffer (cond ((stringp type) type)
+ (t (cdr (assq type gnus-window-to-buffer)))))
(unless buffer
(error "Illegal buffer type: %s" type))
- (when (setq buf (get-buffer (if (symbolp buffer) (symbol-value buffer)
+ (when (setq buf (get-buffer (if (symbolp buffer)
+ (symbol-value buffer)
buffer)))
(setq win (get-buffer-window buf t)))
- (when win
- (if (memq 'point split)
- win
- t))))
- (t
- (when (eq type 'frame)
- (setq gnus-frame-split-p t))
- (let ((n (mapcar 'gnus-all-windows-visible-p
- (cddr split)))
- (win t))
- (while n
- (cond ((windowp (car n))
- (setq win (car n)))
- ((null (car n))
- (setq win nil)))
- (setq n (cdr n)))
- win)))))
+ (if win
+ (when (memq 'point split)
+ (setq all-visible win))
+ (setq all-visible nil)))
+ (t
+ (when (eq type 'frame)
+ (setq gnus-frame-split-p t))
+ (setq stack (append (cddr split) stack)))))
+ (unless (eq all-visible t)
+ all-visible)))
(defun gnus-window-top-edge (&optional window)
(nth 1 (window-edges window)))
(setq lowest-buf buf)))))
(setq buffers (cdr buffers)))
;; Remove windows on *all* summary buffers.
- (let (wins)
- (walk-windows
- (lambda (win)
- (let ((buf (window-buffer win)))
- (if (string-match "^\\*Summary" (buffer-name buf))
- (progn
- (setq bufs (cons buf bufs))
- (pop-to-buffer buf)
- (if (or (not lowest)
- (< (gnus-window-top-edge) lowest))
- (progn
- (setq lowest-buf buf)
- (setq lowest (gnus-window-top-edge))))))))))
+ (walk-windows
+ (lambda (win)
+ (let ((buf (window-buffer win)))
+ (if (string-match "^\\*Summary" (buffer-name buf))
+ (progn
+ (setq bufs (cons buf bufs))
+ (pop-to-buffer buf)
+ (if (or (not lowest)
+ (< (gnus-window-top-edge) lowest))
+ (progn
+ (setq lowest-buf buf)
+ (setq lowest (gnus-window-top-edge)))))))))
(and lowest-buf
(progn
(pop-to-buffer lowest-buf)
(memq 'virtual (assoc (symbol-name (car (gnus-find-method-for-group group)))
gnus-valid-select-methods)))
+(defun gnus-news-group-p (group &optional article)
+ "Return non-nil if GROUP (and ARTICLE) come from a news server."
+ (or (gnus-member-of-valid 'post group) ; Ordinary news group.
+ (and (gnus-member-of-valid 'post-mail group) ; Combined group.
+ (eq (gnus-request-type group article) 'news))))
+
(defsubst gnus-simplify-subject-fully (subject)
"Simplify a subject string according to the user's wishes."
(cond
(push group groups)))
(nreverse groups)))
+(defun gnus-completing-read (default prompt &rest args)
+ ;; Like `completing-read', except that DEFAULT is the default argument.
+ (let* ((prompt (if default
+ (concat prompt " (default " default ") ")
+ (concat prompt " ")))
+ (answer (apply 'completing-read prompt args)))
+ (if (or (null answer) (zerop (length answer)))
+ default
+ answer)))
+
;; Two silly functions to ensure that all `y-or-n-p' questions clear
;; the echo area.
(defun gnus-y-or-n-p (prompt)
;; from `message'.
(apply 'format args)))
-(defun gnus-functionp (form)
- "Return non-nil if FORM is funcallable."
- (or (and (symbolp form) (fboundp form))
- (and (listp form) (eq (car form) 'lambda))))
+(defun gnus-error (level &rest args)
+ "Beep an error if `gnus-verbose' is on LEVEL or less."
+ (when (<= (floor level) gnus-verbose)
+ (apply 'message args)
+ (ding)
+ (let (duration)
+ (when (and (floatp level)
+ (not (zerop (setq duration (* 10 (- level (floor level)))))))
+ (sit-for duration))))
+ nil)
;; Generate a unique new group name.
(defun gnus-generate-new-group-name (leaf)
(setq name (concat leaf "<" (int-to-string (setq num (1+ num))) ">")))
name))
+(defsubst gnus-hide-text (b e props)
+ "Set text PROPS on the B to E region, extending `intangible' 1 past B."
+ (gnus-add-text-properties b e props)
+ (when (memq 'intangible props)
+ (gnus-put-text-property (max (1- b) (point-min))
+ b 'intangible (cddr (memq 'intangible props)))))
+
+(defsubst gnus-unhide-text (b e)
+ "Remove hidden text properties from region between B and E."
+ (remove-text-properties b e gnus-hidden-properties)
+ (when (memq 'intangible gnus-hidden-properties)
+ (gnus-put-text-property (max (1- b) (point-min))
+ b 'intangible nil)))
+
+(defun gnus-hide-text-type (b e type)
+ "Hide text of TYPE between B and E."
+ (gnus-hide-text b e (cons 'gnus-type (cons type gnus-hidden-properties))))
+
;; Find out whether the gnus-visual TYPE is wanted.
(defun gnus-visual-p (&optional type class)
(and gnus-visual ; Has to be non-nil, at least.
(defun gnus-parent-id (references)
"Return the last Message-ID in REFERENCES."
(when (and references
- (string-match "\\(<[^<>]+>\\)[ \t\n]*\\'" references))
+ (string-match "\\(<[^\n<>]+>\\)[ \t\n]*\\'" references))
(substring references (match-beginning 1) (match-end 1))))
(defun gnus-split-references (references)
ids))
(nreverse ids)))
+(defun gnus-buffer-live-p (buffer)
+ "Say whether BUFFER is alive or not."
+ (and buffer
+ (get-buffer buffer)
+ (buffer-name (get-buffer buffer))))
+
(defun gnus-ephemeral-group-p (group)
"Say whether GROUP is ephemeral or not."
(gnus-group-get-parameter group 'quit-config))
(defun gnus-group-default-level (&optional level number-or-nil)
(cond
(gnus-group-use-permanent-levels
- (setq gnus-group-default-list-level
- (or level gnus-group-default-list-level))
- (or gnus-group-default-list-level gnus-level-subscribed))
+ (or (setq gnus-group-use-permanent-levels
+ (or level (if (numberp gnus-group-use-permanent-levels)
+ gnus-group-use-permanent-levels
+ (or gnus-group-default-list-level
+ gnus-level-subscribed))))
+ gnus-group-default-list-level gnus-level-subscribed))
(number-or-nil
level)
(t
As opposed to `gnus', this command will not connect to the local server."
(interactive "P")
(make-local-variable 'gnus-group-use-permanent-levels)
- (setq gnus-group-use-permanent-levels t)
- (gnus (or arg (1- gnus-level-default-subscribed)) t slave))
+ (setq gnus-group-use-permanent-levels
+ (or arg (1- gnus-level-default-subscribed)))
+ (gnus gnus-group-use-permanent-levels t slave))
;;;###autoload
(defun gnus-slave (&optional arg)
;; Fontify some.
(goto-char (point-min))
(and (search-forward "Praxis" nil t)
- (put-text-property (match-beginning 0) (match-end 0) 'face 'bold))
+ (gnus-put-text-property (match-beginning 0) (match-end 0) 'face 'bold))
(goto-char (point-min))
(let* ((mode-string (gnus-group-set-mode-line)))
(setq mode-line-buffer-identification
(<= (setq clevel (gnus-info-level info)) level)
(>= clevel lowest)
(or all ; We list all groups?
- (and gnus-group-list-inactive-groups
- (eq unread t)) ; We list unactivated groups
- (> unread 0) ; We list groups with unread articles
+ (if (eq unread t) ; Unactivated?
+ gnus-group-list-inactive-groups ; We list unactivated
+ (> unread 0)) ; We list groups with unread articles
(and gnus-list-groups-with-ticked-articles
(cdr (assq 'tick (gnus-info-marks info))))
; And groups with tickeds
;; List zombies and killed lists somewhat faster, which was
;; suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>. It does
;; this by ignoring the group format specification altogether.
- (let (group beg)
+ (let (group)
(if regexp
;; This loop is used when listing groups that match some
;; regexp.
(while groups
(setq group (pop groups))
(when (string-match regexp group)
- (add-text-properties
+ (gnus-add-text-properties
(point) (prog1 (1+ (point))
(insert " " mark " *: " group "\n"))
(list 'gnus-group (gnus-intern-safe group gnus-active-hashtb)
'gnus-level level))))
;; This loop is used when listing all groups.
(while groups
- (add-text-properties
+ (gnus-add-text-properties
(point) (prog1 (1+ (point))
(insert " " mark " *: "
(setq group (pop groups)) "\n"))
;; select method, and return a select method.
(cond ((stringp method)
(gnus-server-to-method method))
+ ((equal method gnus-select-method)
+ gnus-select-method)
((and (stringp (car method)) group)
(gnus-server-extend-method group method))
+ ((and method (not group)
+ (equal (cadr method) ""))
+ method)
(t
(gnus-server-add-address method))))
(t m2))))
(gnus-method-equal m1 m2)))
+(defun gnus-servers-using-backend (backend)
+ "Return a list of known servers using BACKEND."
+ (let ((opened gnus-opened-servers)
+ out)
+ (while opened
+ (when (eq backend (caaar opened))
+ (push (caar opened) out))
+ (pop opened))
+ out))
+
(defun gnus-group-prefixed-name (group method)
"Return the whole name from GROUP and METHOD."
(and (stringp method) (setq method (gnus-server-to-method method)))
"Add SCORE to the GROUP score.
If SCORE is nil, add 1 to the score of GROUP."
(let ((info (gnus-get-info group)))
- (gnus-info-set-score info (+ (gnus-info-score info) (or score 1)))))
+ (when info
+ (gnus-info-set-score info (+ (gnus-info-score info) (or score 1))))))
(defun gnus-summary-bubble-group ()
"Increase the score of the current group.
(setq method (gnus-info-method info))
(when (gnus-server-equal method "native")
(setq method nil))
- (if method
- ;; It's a foreign group...
- (gnus-group-make-group
- (gnus-group-real-name (gnus-info-group info))
- (if (stringp method) method
- (prin1-to-string (car method)))
- (and (consp method)
- (nth 1 (gnus-info-method info))))
- ;; It's a native group.
- (gnus-group-make-group (gnus-info-group info)))
+ (save-excursion
+ (set-buffer gnus-group-buffer)
+ (if method
+ ;; It's a foreign group...
+ (gnus-group-make-group
+ (gnus-group-real-name (gnus-info-group info))
+ (if (stringp method) method
+ (prin1-to-string (car method)))
+ (and (consp method)
+ (nth 1 (gnus-info-method info))))
+ ;; It's a native group.
+ (gnus-group-make-group (gnus-info-group info))))
(gnus-message 6 "Note: New group created")
(setq entry
(gnus-gethash (gnus-group-prefixed-name
(setcar (nthcdr 2 entry) info)
(when (and (not (eq (car entry) t))
(gnus-active (gnus-info-group info)))
- (let ((marked (gnus-info-marks info)))
- (setcar entry (length (gnus-list-of-unread-articles
- (car info)))))))
+ (setcar entry (length (gnus-list-of-unread-articles (car info))))))
(error "No such group: %s" (gnus-info-group info)))))
(defun gnus-group-set-method-info (group select-method)
"Update the current line in the group buffer."
(let* ((buffer-read-only nil)
(group (gnus-group-group-name))
- (gnus-group-indentation (gnus-group-group-indentation))
(entry (and group (gnus-gethash group gnus-newsrc-hashtb))))
(and entry
(not (gnus-ephemeral-group-p group))
(- (1+ (cdr active)) (car active)) 0)
nil))))
-(defun gnus-group-insert-group-line
- (gnus-tmp-group gnus-tmp-level gnus-tmp-marked number
- gnus-tmp-method)
+(defun gnus-group-insert-group-line (gnus-tmp-group gnus-tmp-level
+ gnus-tmp-marked number
+ gnus-tmp-method)
"Insert a group line in the group buffer."
(let* ((gnus-tmp-active (gnus-active gnus-tmp-group))
(gnus-tmp-number-total
(buffer-read-only nil)
header gnus-tmp-header) ; passed as parameter to user-funcs.
(beginning-of-line)
- (add-text-properties
+ (gnus-add-text-properties
(point)
(prog1 (1+ (point))
;; Insert the text.
gnus-marked ,gnus-tmp-marked-mark
gnus-indentation ,gnus-group-indentation
gnus-level ,gnus-tmp-level))
- (when (gnus-visual-p 'group-highlight 'highlight)
+ (when (inline (gnus-visual-p 'group-highlight 'highlight))
(forward-line -1)
(run-hooks 'gnus-group-update-hook)
(forward-line))
(widen)
(let ((ident (gnus-intern-safe group gnus-active-hashtb))
(loc (point-min))
- found buffer-read-only visible)
+ found buffer-read-only)
;; Enter the current status into the dribble buffer.
(let ((entry (gnus-gethash group gnus-newsrc-hashtb)))
(if (and entry (not (gnus-ephemeral-group-p group)))
(defun gnus-group-set-mode-line ()
(when (memq 'group gnus-updated-mode-lines)
- (let* ((gformat (or gnus-group-mode-line-format-spec
- (setq gnus-group-mode-line-format-spec
- (gnus-parse-format
- gnus-group-mode-line-format
- gnus-group-mode-line-format-alist))))
- (gnus-tmp-news-server (cadr gnus-select-method))
- (gnus-tmp-news-method (car gnus-select-method))
- (max-len 60)
- gnus-tmp-header ;Dummy binding for user-defined formats
- ;; Get the resulting string.
- (mode-string (eval gformat)))
- ;; If the line is too long, we chop it off.
- (when (> (length mode-string) max-len)
- (setq mode-string (substring mode-string 0 (- max-len 4))))
- (prog1
- (setq mode-line-buffer-identification (list mode-string))
- (set-buffer-modified-p t)))))
+ (save-excursion
+ (set-buffer gnus-group-buffer)
+ (let* ((gformat (or gnus-group-mode-line-format-spec
+ (setq gnus-group-mode-line-format-spec
+ (gnus-parse-format
+ gnus-group-mode-line-format
+ gnus-group-mode-line-format-alist))))
+ (gnus-tmp-news-server (cadr gnus-select-method))
+ (gnus-tmp-news-method (car gnus-select-method))
+ (max-len 60)
+ gnus-tmp-header ;Dummy binding for user-defined formats
+ ;; Get the resulting string.
+ (mode-string (eval gformat)))
+ ;; Say whether the dribble buffer has been modified.
+ (setq mode-line-modified
+ (if (and gnus-dribble-buffer
+ (buffer-name gnus-dribble-buffer)
+ (buffer-modified-p gnus-dribble-buffer)
+ (save-excursion
+ (set-buffer gnus-dribble-buffer)
+ (not (zerop (buffer-size)))))
+ "-* " "-- "))
+ ;; If the line is too long, we chop it off.
+ (when (> (length mode-string) max-len)
+ (setq mode-string (substring mode-string 0 (- max-len 4))))
+ (prog1
+ (setq mode-line-buffer-identification (list mode-string))
+ (set-buffer-modified-p t))))))
(defun gnus-group-group-name ()
"Get the name of the newsgroup on the current line."
(defun gnus-group-group-indentation ()
"Get the indentation of the newsgroup on the current line."
- (or (get-text-property (gnus-point-at-bol) 'gnus-indentation) ""))
+ (or (get-text-property (gnus-point-at-bol) 'gnus-indentation)
+ (and gnus-group-indentation-function
+ (funcall gnus-group-indentation-function))
+ ""))
(defun gnus-group-group-unread ()
"Get the number of unread articles of the newsgroup on the current line."
(interactive "p")
(let ((buffer-read-only nil)
group)
- (while
- (and (> n 0)
- (setq group (gnus-group-group-name))
- (progn
- (beginning-of-line)
- (forward-char
- (or (cdr (assq 'process gnus-group-mark-positions)) 2))
- (delete-char 1)
- (if unmark
- (progn
- (insert " ")
- (setq gnus-group-marked (delete group gnus-group-marked)))
- (insert "#")
- (setq gnus-group-marked
- (cons group (delete group gnus-group-marked))))
- t)
- (or no-advance (zerop (gnus-group-next-group 1))))
- (setq n (1- n)))
+ (while (and (> n 0)
+ (not (eobp)))
+ (when (setq group (gnus-group-group-name))
+ ;; Update the mark.
+ (beginning-of-line)
+ (forward-char
+ (or (cdr (assq 'process gnus-group-mark-positions)) 2))
+ (delete-char 1)
+ (if unmark
+ (progn
+ (insert " ")
+ (setq gnus-group-marked (delete group gnus-group-marked)))
+ (insert "#")
+ (setq gnus-group-marked
+ (cons group (delete group gnus-group-marked))))
+ (or no-advance (zerop (gnus-group-next-group 1))))
+ (decf n))
(gnus-summary-position-point)
n))
(substitute-command-keys
"\\<gnus-group-mode-map>\\[gnus-group-universal-argument]")))))
'undefined)
- (progn
- (message "Undefined key")
- (ding))
+ (gnus-error 1 "Undefined key")
(while groups
(gnus-group-remove-mark (setq group (pop groups)))
(command-execute func))))
(nreverse groups)))
((and (boundp 'transient-mark-mode)
transient-mark-mode
+ (boundp 'mark-active)
mark-active)
;; Work on the region between point and mark.
(let ((max (max (point) (mark)))
(interactive
(list (completing-read
"Group: " gnus-active-hashtb nil
- (memq gnus-select-method gnus-have-read-active-file))))
+ (gnus-read-active-file-p)
+ nil
+ 'gnus-group-history)))
- (if (equal group "")
- (error "Empty group name"))
+ (when (equal group "")
+ (error "Empty group name"))
+
+ (when (string-match "[\000-\032]" group)
+ (error "Control characters in group: %s" group))
(let ((b (text-property-any
(point-min) (point-max)
(goto-char (point-min))
(let ((best 100000)
unread best-point)
- (while (setq unread (get-text-property (point) 'gnus-unread))
+ (while (not (eobp))
+ (setq unread (get-text-property (point) 'gnus-unread))
(if (and (numberp unread) (> unread 0))
(progn
- (if (and (< (get-text-property (point) 'gnus-level) best)
+ (if (and (get-text-property (point) 'gnus-level)
+ (< (get-text-property (point) 'gnus-level) best)
(or (not exclude-group)
(not (equal exclude-group (gnus-group-group-name)))))
(progn
(let ((method
(completing-read
"Method: " (append gnus-valid-select-methods gnus-server-alist)
- nil t)))
- (if (assoc method gnus-valid-select-methods)
- (list method
- (if (memq 'prompt-address
- (assoc method gnus-valid-select-methods))
- (read-string "Address: ")
- ""))
- (list method "")))))
+ nil t nil 'gnus-method-history)))
+ (cond ((assoc method gnus-valid-select-methods)
+ (list method
+ (if (memq 'prompt-address
+ (assoc method gnus-valid-select-methods))
+ (read-string "Address: ")
+ "")))
+ ((assoc method gnus-server-alist)
+ (list method))
+ (t
+ (list method ""))))))
+
+ (let* ((meth (and method (if address (list (intern method) address)
+ method)))
+ (nname (if method (gnus-group-prefixed-name name meth) name))
+ backend info)
+ (when (gnus-gethash nname gnus-newsrc-hashtb)
+ (error "Group %s already exists" nname))
+ ;; Subscribe to the new group.
+ (gnus-group-change-level
+ (setq info (list t nname gnus-level-default-subscribed nil nil meth))
+ gnus-level-default-subscribed gnus-level-killed
+ (and (gnus-group-group-name)
+ (gnus-gethash (gnus-group-group-name)
+ gnus-newsrc-hashtb))
+ t)
+ ;; Make it active.
+ (gnus-set-active nname (cons 1 0))
+ (or (gnus-ephemeral-group-p name)
+ (gnus-dribble-enter
+ (concat "(gnus-group-set-info '" (prin1-to-string (cdr info)) ")")))
+ ;; Insert the line.
+ (gnus-group-insert-group-line-info nname)
+ (forward-line -1)
+ (gnus-group-position-point)
- (save-excursion
- (set-buffer gnus-group-buffer)
- (let* ((meth (and method (if address (list (intern method) address)
- method)))
- (nname (if method (gnus-group-prefixed-name name meth) name))
- info)
- (and (gnus-gethash nname gnus-newsrc-hashtb)
- (error "Group %s already exists" nname))
- (gnus-group-change-level
- (setq info (list t nname gnus-level-default-subscribed nil nil meth))
- gnus-level-default-subscribed gnus-level-killed
- (and (gnus-group-group-name)
- (gnus-gethash (gnus-group-group-name)
- gnus-newsrc-hashtb))
- t)
- (gnus-set-active nname (cons 1 0))
- (or (gnus-ephemeral-group-p name)
- (gnus-dribble-enter
- (concat "(gnus-group-set-info '" (prin1-to-string (cdr info)) ")")))
- (gnus-group-insert-group-line-info nname)
-
- (when (assoc (symbol-name (car meth)) gnus-valid-select-methods)
- (require (car meth)))
- (gnus-check-server meth)
- (and (gnus-check-backend-function 'request-create-group nname)
- (gnus-request-create-group nname))
- t)))
+ ;; Load the backend and try to make the backend create
+ ;; the group as well.
+ (when (assoc (symbol-name (setq backend (car (gnus-server-get-method
+ nil meth))))
+ gnus-valid-select-methods)
+ (require backend))
+ (gnus-check-server meth)
+ (and (gnus-check-backend-function 'request-create-group nname)
+ (gnus-request-create-group nname))
+ t))
(defun gnus-group-delete-group (group &optional force)
"Delete the current group.
() ; Whew!
(gnus-message 6 "Deleting group %s..." group)
(if (not (gnus-request-delete-group group force))
- (progn
- (gnus-message 3 "Couldn't delete group %s" group)
- (ding))
+ (gnus-error 3 "Couldn't delete group %s" group)
(gnus-message 6 "Deleting group %s...done" group)
(gnus-group-goto-group group)
(gnus-group-kill-group 1 t)
+ (gnus-sethash group nil gnus-active-hashtb)
t))
(gnus-group-position-point)))
(gnus-message 6 "Renaming group %s to %s..." group new-name)
(prog1
(if (not (gnus-request-rename-group group new-name))
- (progn
- (gnus-message 3 "Couldn't rename group %s to %s" group new-name)
- (ding))
+ (gnus-error 3 "Couldn't rename group %s to %s" group new-name)
;; We rename the group internally by killing it...
(gnus-group-goto-group group)
(gnus-group-kill-group)
"etc/gnus-tut.txt"))))
(setq path nil)))
(if (not file)
- (message "Couldn't find doc group")
+ (gnus-message 1 "Couldn't find doc group")
(gnus-group-make-group
(gnus-group-real-name name)
- (list 'nndoc name
+ (list 'nndoc "gnus-help"
(list 'nndoc-address file)
(list 'nndoc-article-type 'mbox)))))
(gnus-group-position-point))
(file-name-nondirectory file) '(nndoc "")))))
(gnus-group-make-group
(gnus-group-real-name name)
- (list 'nndoc name
+ (list 'nndoc (file-name-nondirectory file)
(list 'nndoc-address file)
- (list 'nndoc-article-type (or type 'guess))))
- (forward-line -1)
- (gnus-group-position-point)))
+ (list 'nndoc-article-type (or type 'guess))))))
(defun gnus-group-make-archive-group (&optional all)
"Create the (ding) Gnus archive group of the most recent articles.
(list 'nndir (if all "hpc" "edu")
(list 'nndir-directory
(if all gnus-group-archive-directory
- gnus-group-recent-archive-directory)))))
- (forward-line -1)
- (gnus-group-position-point))
+ gnus-group-recent-archive-directory))))))
(defun gnus-group-make-directory-group (dir)
"Create an nndir group.
(setq ext (format "<%d>" (setq i (1+ i)))))
(gnus-group-make-group
(gnus-group-real-name group)
- (list 'nndir group (list 'nndir-directory dir))))
- (forward-line -1)
- (gnus-group-position-point))
+ (list 'nndir group (list 'nndir-directory dir)))))
(defun gnus-group-make-kiboze-group (group address scores)
"Create an nnkiboze group.
(setq scores (cons (cons header regexps) scores)))
scores)))
(gnus-group-make-group group "nnkiboze" address)
- (save-excursion
- (gnus-set-work-buffer)
+ (nnheader-temp-write (gnus-score-file-name (concat "nnkiboze:" group))
(let (emacs-lisp-mode-hook)
- (pp scores (current-buffer)))
- (write-region (point-min) (point-max)
- (gnus-score-file-name (concat "nnkiboze:" group))))
- (forward-line -1)
- (gnus-group-position-point))
+ (pp scores (current-buffer)))))
(defun gnus-group-add-to-virtual (n vgroup)
"Add the current group to a virtual group."
(level2 (gnus-info-level info2)))
(or (< level1 level2)
(and (= level1 level2)
- (< (gnus-info-score info1) (gnus-info-score info2))))))
+ (> (gnus-info-score info1) (gnus-info-score info2))))))
;; Group catching up.
+(defun gnus-group-clear-data (n)
+ "Clear all marks and read ranges from the current group."
+ (interactive "P")
+ (let ((groups (gnus-group-process-prefix n))
+ group info)
+ (while (setq group (pop groups))
+ (setq info (gnus-get-info group))
+ (gnus-info-set-read info nil)
+ (when (gnus-info-marks info)
+ (gnus-info-set-marks info nil))
+ (gnus-get-unread-articles-in-group info (gnus-active group) t)
+ (when (gnus-group-goto-group group)
+ (gnus-group-remove-mark group)
+ (gnus-group-update-group-line)))))
+
(defun gnus-group-catchup-current (&optional n all)
"Mark all articles not marked as unread in current newsgroup as read.
If prefix argument N is numeric, the ARG next newsgroups will be
(nnvirtual-catchup-group
(gnus-group-real-name (car groups)) (nth 1 method) all)))
(gnus-group-remove-mark (car groups))
- (if (prog1
- (gnus-group-goto-group (car groups))
- (gnus-group-catchup (car groups) all))
- (gnus-group-update-group-line)
- (setq ret (1+ ret)))
+ (if (>= (gnus-group-group-level) gnus-level-zombie)
+ (gnus-message 2 "Dead groups can't be caught up")
+ (if (prog1
+ (gnus-group-goto-group (car groups))
+ (gnus-group-catchup (car groups) all))
+ (gnus-group-update-group-line)
+ (setq ret (1+ ret))))
(setq groups (cdr groups)))
(gnus-group-next-unread-group 1)
ret)))
(interactive
(list (completing-read
"Group: " gnus-active-hashtb nil
- (memq gnus-select-method gnus-have-read-active-file))))
+ (gnus-read-active-file-p)
+ nil
+ 'gnus-group-history)))
(let ((newsrc (gnus-gethash group gnus-newsrc-hashtb)))
(cond
((string-match "^[ \t]$" group)
(unless silent
(gnus-group-update-group group)))
((and (stringp group)
- (or (not (memq gnus-select-method gnus-have-read-active-file))
+ (or (not (gnus-read-active-file-p))
(gnus-active group)))
;; Add new newsgroup.
(gnus-group-change-level
(interactive "P")
;; Find all possible killed newsgroups if arg.
(when arg
- ;; First make sure active file has been read.
- (unless gnus-have-read-active-file
- (let ((gnus-read-active-file t))
- (gnus-read-active-file)))
- (or gnus-killed-hashtb (gnus-make-hashtable-from-killed))
- ;; Go through all newsgroups that are known to Gnus - enlarge kill list
- (mapatoms
- (lambda (sym)
- (let ((groups 0)
- (group (symbol-name sym)))
- (if (or (null group)
- (gnus-gethash group gnus-killed-hashtb)
- (gnus-gethash group gnus-newsrc-hashtb))
- ()
- (let ((do-sub (gnus-matches-options-n group)))
- (if (or (eq do-sub 'subscribe) (eq do-sub 'ignore))
- ()
- (setq groups (1+ groups))
- (setq gnus-killed-list
- (cons group gnus-killed-list))
- (gnus-sethash group group gnus-killed-hashtb))))))
- gnus-active-hashtb))
+ (gnus-get-killed-groups))
(if (not gnus-killed-list)
(gnus-message 6 "No killed groups")
(let (gnus-group-list-mode)
"List all groups that are available from the server(s)."
(interactive)
;; First we make sure that we have really read the active file.
- (unless gnus-have-read-active-file
+ (unless (gnus-read-active-file-p)
(let ((gnus-read-active-file t))
(gnus-read-active-file)))
;; Find all groups and sort them.
(buffer-read-only nil))
(erase-buffer)
(while groups
- (gnus-group-insert-group-line-info (car groups))
- (setq groups (cdr groups)))
+ (gnus-group-insert-group-line-info (pop groups)))
(goto-char (point-min))))
(defun gnus-activate-all-groups (level)
(interactive "P")
(let* ((groups (gnus-group-process-prefix n))
(ret (if (numberp n) (- n (length groups)) 0))
+ (beg (unless n (point)))
group)
- (while groups
- (setq group (car groups)
- groups (cdr groups))
+ (while (setq group (pop groups))
(gnus-group-remove-mark group)
- (unless (gnus-get-new-news-in-group group)
- (ding)
- (gnus-message 3 "%s error: %s" group (gnus-status-message group))))
+ (if (gnus-activate-group group 'scan)
+ (progn
+ (gnus-get-unread-articles-in-group
+ (gnus-get-info group) (gnus-active group) t)
+ (unless (gnus-virtual-group-p group)
+ (gnus-close-group group))
+ (gnus-group-update-group group))
+ (gnus-error 3 "%s error: %s" group (gnus-status-message group))))
+ (when beg (goto-char beg))
(when gnus-goto-next-group-when-activating
(gnus-group-next-unread-group 1 t))
(gnus-summary-position-point)
ret))
-(defun gnus-get-new-news-in-group (group)
- (when (and group (gnus-activate-group group 'scan))
- (gnus-get-unread-articles-in-group
- (gnus-get-info group) (gnus-active group) t)
- (gnus-close-group group)
- (when (gnus-group-goto-group group)
- (gnus-group-update-group-line))
- t))
-
(defun gnus-group-fetch-faq (group &optional faq-dir)
"Fetch the FAQ for the current group."
(interactive
gnus-description-hashtb))
(setq desc (gnus-group-get-description group))
(gnus-read-descriptions-file method))
- (message
+ (gnus-message 1
(or desc (gnus-gethash group gnus-description-hashtb)
"No description available")))))
(setq b (point))
(insert (format " *: %-20s %s\n" (symbol-name group)
(symbol-value group)))
- (add-text-properties
+ (gnus-add-text-properties
b (1+ b) (list 'gnus-group group
'gnus-unread t 'gnus-marked nil
'gnus-level (1+ gnus-level-subscribed))))
(string-match regexp (symbol-name group))
(setq groups (cons (symbol-name group) groups))))
gnus-active-hashtb)
- ;; Go through all descriptions that are known to Gnus.
- (if search-description
- (mapatoms
- (lambda (group)
- (and (string-match regexp (symbol-value group))
- (gnus-active (symbol-name group))
- (setq groups (cons (symbol-name group) groups))))
- gnus-description-hashtb))
+ ;; Also go through all descriptions that are known to Gnus.
+ (when search-description
+ (mapatoms
+ (lambda (group)
+ (and (string-match regexp (symbol-value group))
+ (gnus-active (symbol-name group))
+ (setq groups (cons (symbol-name group) groups))))
+ gnus-description-hashtb))
(if (not groups)
(gnus-message 3 "No groups matched \"%s\"." regexp)
;; Print out all the groups.
If the prefix LEVEL is non-nil, it should be a number that says which
level to cut off listing groups.
If ALL, also list groups with no unread articles.
-If LOWEST, don't list groups with level lower than LOWEST."
+If LOWEST, don't list groups with level lower than LOWEST.
+
+This command may read the active file."
(interactive "P\nsList newsgroups matching: ")
+ ;; First make sure active file has been read.
+ (when (and level
+ (>= (prefix-numeric-value level) gnus-level-killed))
+ (gnus-get-killed-groups))
(gnus-group-prepare-flat (or level gnus-level-subscribed)
all (or lowest 1) regexp)
(goto-char (point-min))
gnus-expert-user
(gnus-y-or-n-p "Are you sure you want to quit reading news? "))
(run-hooks 'gnus-exit-gnus-hook)
- ;; Close down GroupLens.
- (when gnus-use-grouplens
- (bbb-logout))
;; Offer to save data from non-quitted summary buffers.
(gnus-offer-save-summaries)
;; Save the newsrc file(s).
(gnus-save-newsrc-file)
;; Kill-em-all.
(gnus-close-backends)
- ;; Shut down the cache.
- (when gnus-use-cache
- (gnus-cache-close))
;; Reset everything.
(gnus-clear-system)
;; Allow the user to do things after cleaning up.
(gnus-remove-some-windows))
(gnus-dribble-save)
(gnus-close-backends)
- ;; Shut down the cache.
- (when gnus-use-cache
- (gnus-cache-close))
(gnus-clear-system)
;; Allow the user to do things after cleaning up.
(run-hooks 'gnus-after-exiting-gnus-hook)))
(list (let ((how (completing-read
"Which backend: "
(append gnus-valid-select-methods gnus-server-alist)
- nil t (cons "nntp" 0))))
+ nil t (cons "nntp" 0) 'gnus-method-history)))
;; We either got a backend name or a virtual server name.
;; If the first, we also need an address.
(if (assoc how gnus-valid-select-methods)
(setq selective-display-ellipses t) ;Display `...'
(setq buffer-display-table gnus-summary-display-table)
(setq gnus-newsgroup-name group)
+ (make-local-variable 'gnus-summary-line-format)
+ (make-local-variable 'gnus-summary-line-format-spec)
+ (make-local-variable 'gnus-summary-mark-positions)
(run-hooks 'gnus-summary-mode-hook))
(defun gnus-summary-make-display-table ()
(defun gnus-summary-article-parent (&optional number)
(let* ((data (gnus-data-find-list (or number (gnus-summary-article-number))
(gnus-data-list t)))
- (level (gnus-data-level (car data)))
- l)
+ (level (gnus-data-level (car data))))
(if (zerop level)
() ; This is a root.
;; We search until we find an article with a level less than
"Return whether ARTICLE is the last article in the buffer."
(if (not (setq article (or article (gnus-summary-article-number))))
t ; All non-existant numbers are the last article. :-)
- (cdr (gnus-data-find-list article))))
+ (not (cdr (gnus-data-find-list article)))))
(defun gnus-summary-insert-dummy-line (gnus-tmp-subject gnus-tmp-number)
"Insert a dummy root in the summary buffer."
(beginning-of-line)
- (add-text-properties
+ (gnus-add-text-properties
(point) (progn (eval gnus-summary-dummy-line-format-spec) (point))
(list 'gnus-number gnus-tmp-number 'gnus-intangible gnus-tmp-number)))
-(defvar gnus-thread-indent-array nil)
-(defvar gnus-thread-indent-array-level gnus-thread-indent-level)
(defun gnus-make-thread-indent-array ()
(let ((n 200))
- (if (and gnus-thread-indent-array
- (= gnus-thread-indent-level gnus-thread-indent-array-level))
- nil
+ (unless (and gnus-thread-indent-array
+ (= gnus-thread-indent-level gnus-thread-indent-array-level))
(setq gnus-thread-indent-array (make-vector 201 "")
gnus-thread-indent-array-level gnus-thread-indent-level)
(while (>= n 0)
(when (string= gnus-tmp-name "")
(setq gnus-tmp-name gnus-tmp-from))
(or (numberp gnus-tmp-lines) (setq gnus-tmp-lines 0))
- (put-text-property
+ (gnus-put-text-property
(point)
(progn (eval gnus-summary-line-format-spec) (point))
'gnus-number gnus-tmp-number)
(make-local-variable (car elem))
(set (car elem) (eval (nth 1 elem))))))))
-(defun gnus-summary-read-group
- (group &optional show-all no-article kill-buffer no-display)
+(defun gnus-summary-read-group (group &optional show-all no-article
+ kill-buffer no-display)
"Start reading news in newsgroup GROUP.
If SHOW-ALL is non-nil, already read articles are also listed.
If NO-ARTICLE is non-nil, no article is selected initially.
(when gnus-build-sparse-threads
(gnus-build-sparse-threads))
;; Find the initial limit.
- (if show-all
- (let ((gnus-newsgroup-dormant nil))
+ (if gnus-show-threads
+ (if show-all
+ (let ((gnus-newsgroup-dormant nil))
+ (gnus-summary-initial-limit show-all))
(gnus-summary-initial-limit show-all))
- (gnus-summary-initial-limit show-all))
+ (setq gnus-newsgroup-limit
+ (mapcar
+ (lambda (header) (mail-header-number header))
+ gnus-newsgroup-headers)))
;; Generate the summary buffer.
(unless no-display
(gnus-summary-prepare))
(not no-display)
gnus-newsgroup-unreads
gnus-auto-select-first)
- (if (eq gnus-auto-select-first 'best)
- (gnus-summary-best-unread-article)
- (gnus-summary-first-unread-article))
+ (unless (if (eq gnus-auto-select-first 'best)
+ (gnus-summary-best-unread-article)
+ (gnus-summary-first-unread-article))
+ (gnus-configure-windows 'summary))
;; Don't select any articles, just move point to the first
;; article in the group.
(goto-char (point-min))
subject hthread whole-subject)
(while threads
(setq whole-subject (mail-header-subject (caar threads)))
+ (setq subject
+ (cond
+ ;; Truncate the subject.
+ ((numberp gnus-summary-gather-subject-limit)
+ (setq subject (gnus-simplify-subject-re whole-subject))
+ (if (> (length subject) gnus-summary-gather-subject-limit)
+ (substring subject 0 gnus-summary-gather-subject-limit)
+ subject))
+ ;; Fuzzily simplify it.
+ ((eq 'fuzzy gnus-summary-gather-subject-limit)
+ (gnus-simplify-subject-fuzzy whole-subject))
+ ;; Just remove the leading "Re:".
+ (t
+ (gnus-simplify-subject-re whole-subject))))
+
(if (and gnus-summary-gather-exclude-subject
(string-match gnus-summary-gather-exclude-subject
- whole-subject))
- () ; We don't want to do anything with this article.
+ subject))
+ () ; We don't want to do anything with this article.
;; We simplify the subject before looking it up in the
;; hash table.
- (setq subject
- (cond
- ;; Truncate the subject.
- ((numberp gnus-summary-gather-subject-limit)
- (setq subject (gnus-simplify-subject-re whole-subject))
- (if (> (length subject) gnus-summary-gather-subject-limit)
- (substring subject 0 gnus-summary-gather-subject-limit)
- subject))
- ;; Fuzzily simplify it.
- ((eq 'fuzzy gnus-summary-gather-subject-limit)
- (gnus-simplify-subject-fuzzy whole-subject))
- ;; Just remove the leading "Re:".
- (t
- (gnus-simplify-subject-re whole-subject))))
(if (setq hthread (gnus-gethash subject hashtb))
(progn
(when (and (setq references (mail-header-references header))
(not (string= references "")))
(insert references)
- (setq child (downcase (mail-header-id header))
+ (setq child (mail-header-id header)
subject (mail-header-subject header))
(setq generation 0)
(while (search-backward ">" nil t)
(setq end (1+ (point)))
(when (search-backward "<" nil t)
(push (list (incf generation)
- child (setq child (downcase
- (buffer-substring (point) end)))
+ child (setq child (buffer-substring (point) end))
subject)
relations)))
(push (list (1+ generation) child nil subject) relations)
(regexp-quote id))))
(or found (beginning-of-line 2)))
(when found
- (let (ref)
- (beginning-of-line)
- (and
- (setq header (gnus-nov-parse-line
- (read (current-buffer)) deps))
- (gnus-parent-id (mail-header-references header))))))
+ (beginning-of-line)
+ (and
+ (setq header (gnus-nov-parse-line
+ (read (current-buffer)) deps))
+ (gnus-parent-id (mail-header-references header)))))
(when header
(let ((number (mail-header-number header)))
(push number gnus-newsgroup-limit)
(defun gnus-summary-update-article (article &optional header)
"Update ARTICLE in the summary buffer."
- (let ((id (mail-header-id (gnus-summary-article-header article)))
- (data (gnus-data-find article)))
- (setcar (gnus-id-to-thread id) nil)
- (gnus-summary-insert-subject id)
- ;; Set the (possibly) new article number in the data structure.
- (gnus-data-set-number data (gnus-id-to-article id))))
+ (set-buffer gnus-summary-buffer)
+ (let* ((header (or header (gnus-summary-article-header article)))
+ (id (mail-header-id header))
+ (data (gnus-data-find article))
+ (thread (gnus-id-to-thread id))
+ (parent
+ (gnus-id-to-thread (or (gnus-parent-id
+ (mail-header-references header))
+ "tull")))
+ (buffer-read-only nil)
+ (old (car thread))
+ (number (mail-header-number header))
+ pos)
+ (when thread
+ (setcar thread nil)
+ (when parent
+ (delq thread parent))
+ (if (gnus-summary-insert-subject id header)
+ ;; Set the (possibly) new article number in the data structure.
+ (gnus-data-set-number data (gnus-id-to-article id))
+ (setcar thread old)
+ nil))))
(defun gnus-rebuild-thread (id)
"Rebuild the thread containing ID."
- (let ((dep gnus-newsgroup-dependencies)
- (buffer-read-only nil)
- current headers refs thread art data)
+ (let ((buffer-read-only nil)
+ current thread data)
(if (not gnus-show-threads)
(setq thread (list (car (gnus-id-to-thread id))))
;; Get the thread this article is part of.
;; All the loose roots are now one solid root.
(setq thread (car roots))
(setq thread (cons subject (gnus-sort-threads roots))))))
- (let ((beg (point))
- threads)
+ (let (threads)
;; We then insert this thread into the summary buffer.
(let (gnus-newsgroup-data gnus-newsgroup-threads)
- (gnus-summary-prepare-threads (list thread))
+ (gnus-summary-prepare-threads (gnus-cut-threads (list thread)))
(setq data (nreverse gnus-newsgroup-data))
(setq threads gnus-newsgroup-threads))
;; We splice the new data into the data structure.
(defun gnus-id-to-thread (id)
"Return the (sub-)thread where ID appears."
- (gnus-gethash (downcase id) gnus-newsgroup-dependencies))
+ (gnus-gethash id gnus-newsgroup-dependencies))
(defun gnus-id-to-article (id)
"Return the article number of ID."
(let ((thread (gnus-id-to-thread id)))
- (when thread
+ (when (and thread
+ (car thread))
(mail-header-number (car thread)))))
(defun gnus-id-to-header (id)
(defun gnus-article-displayed-root-p (article)
"Say whether ARTICLE is a root(ish) article."
(let ((level (gnus-summary-thread-level article))
+ (refs (mail-header-references (gnus-summary-article-header article)))
particle)
(cond
((null level) nil)
((zerop level) t)
+ ((null refs) t)
+ ((null(gnus-parent-id refs)) t)
((and (= 1 level)
(null (setq particle (gnus-id-to-article
- (gnus-parent-id
- (mail-header-references
- (gnus-summary-article-header article))))))
+ (gnus-parent-id refs))))
(null (gnus-summary-thread-level particle)))))))
(defun gnus-root-id (id)
"Return the id of the root of the thread where ID appears."
(let (last-id prev)
- (while (and id (setq prev (car (gnus-gethash
- (downcase id)
- gnus-newsgroup-dependencies))))
+ (while (and id (setq prev (car (gnus-gethash
+ id gnus-newsgroup-dependencies))))
(setq last-id id
id (gnus-parent-id (mail-header-references prev))))
last-id))
(defun gnus-remove-thread (id &optional dont-remove)
"Remove the thread that has ID in it."
(let ((dep gnus-newsgroup-dependencies)
- headers thread prev last-id)
+ headers thread last-id)
;; First go up in this thread until we find the root.
(setq last-id (gnus-root-id id))
(setq headers (list (car (gnus-id-to-thread last-id))
(if thread
(unless dont-remove
(setq gnus-newsgroup-threads (delq thread gnus-newsgroup-threads)))
- (setq thread (gnus-gethash (downcase last-id) dep)))
+ (setq thread (gnus-gethash last-id dep)))
(when thread
(prog1
thread ; We return this thread.
(gnus-data-remove number))
(setq thread (cdr thread))
(while thread
- (gnus-remove-thread-1 (car thread))
- (setq thread (cdr thread)))))
+ (gnus-remove-thread-1 (pop thread)))))
(defun gnus-sort-threads (threads)
"Sort THREADS."
(or (cdr (assq (mail-header-number root) gnus-newsgroup-scored))
gnus-summary-default-score 0)
(mapcar 'gnus-thread-total-score
- (cdr (gnus-gethash (downcase (mail-header-id root))
+ (cdr (gnus-gethash (mail-header-id root)
gnus-newsgroup-dependencies)))))
;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
(when (string= gnus-tmp-name "")
(setq gnus-tmp-name gnus-tmp-from))
(or (numberp gnus-tmp-lines) (setq gnus-tmp-lines 0))
- (put-text-property
+ (gnus-put-text-property
(point)
(progn (eval gnus-summary-line-format-spec) (point))
'gnus-number number)
(let (header number mark)
(while headers
- (setq header (car headers)
- headers (cdr headers)
- number (mail-header-number header))
-
;; We may have to root out some bad articles...
- (when (memq number gnus-newsgroup-limit)
+ (when (memq (setq number (mail-header-number
+ (setq header (pop headers))))
+ gnus-newsgroup-limit)
+ ;; Mark article as read when it has a low score.
(when (and gnus-summary-mark-below
(< (or (cdr (assq number gnus-newsgroup-scored))
gnus-summary-default-score 0)
(setq gnus-newsgroup-dependencies
(gnus-make-hashtable (length articles)))
;; Retrieve the headers and read them in.
- (gnus-message 5 "Fetching headers...")
+ (gnus-message 5 "Fetching headers for %s..." gnus-newsgroup-name)
(setq gnus-newsgroup-headers
(if (eq 'nov
(setq gnus-headers-retrieved-by
(> (length articles) 1))))))
(gnus-get-newsgroup-headers-xover articles)
(gnus-get-newsgroup-headers)))
- (gnus-message 5 "Fetching headers...done")
+ (gnus-message 5 "Fetching headers for %s...done" gnus-newsgroup-name)
;; Kludge to avoid having cached articles nixed out in virtual groups.
(when cached
;; Check whether auto-expire is to be done in this group.
(setq gnus-newsgroup-auto-expire
(gnus-group-auto-expirable-p group))
+ ;; Set up the article buffer now, if necessary.
+ (unless gnus-single-article-buffer
+ (gnus-article-setup-buffer))
;; First and last article in this newsgroup.
(and gnus-newsgroup-headers
(setq gnus-newsgroup-begin
(let ((types gnus-article-mark-lists)
(info (gnus-get-info gnus-newsgroup-name))
(uncompressed '(score bookmark killed))
- var type list newmarked symbol)
+ type list newmarked symbol)
(when info
;; Add all marks lists that are non-nil to the list of marks lists.
(while types
(delq (assq type (car marked)) (car marked)))
(setcdr m (gnus-compress-sequence articles t)))
(setcdr m (gnus-compress-sequence
- (sort (nconc (gnus-uncompress-range m)
+ (sort (nconc (gnus-uncompress-range (cdr m))
(copy-sequence articles)) '<) t))))))
(defun gnus-set-mode-line (where)
gnus-tmp-header);; passed as argument to any user-format-funcs
(setq mode-string (eval mformat))
(setq max-len (max 4 (if gnus-mode-non-string-length
- (- (frame-width)
+ (- (window-width)
gnus-mode-non-string-length)
(length mode-string))))
;; We might have to chop a bit of the string off...
(defun gnus-create-xref-hashtb (from-newsgroup headers unreads)
"Go through the HEADERS list and add all Xrefs to a hash table.
The resulting hash table is returned, or nil if no Xrefs were found."
- (let* ((from-method (gnus-find-method-for-group from-newsgroup))
- (virtual (gnus-virtual-group-p from-newsgroup))
+ (let* ((virtual (gnus-virtual-group-p from-newsgroup))
(prefix (if virtual "" (gnus-group-real-prefix from-newsgroup)))
(xref-hashtb (make-vector 63 0))
start group entry number xrefs header)
(setq start 0)
(while (string-match "\\([^ ]+\\)[:/]\\([0-9]+\\)" xrefs start)
(setq start (match-end 0))
- (setq group (concat prefix (substring xrefs (match-beginning 1)
- (match-end 1))))
+ (setq group (if prefix
+ (concat prefix (substring xrefs (match-beginning 1)
+ (match-end 1)))
+ (substring xrefs (match-beginning 1) (match-end 1))))
(setq number
(string-to-int (substring xrefs (match-beginning 2)
(match-end 2))))
headers id id-dep ref-dep end ref)
(save-excursion
(set-buffer nntp-server-buffer)
+ (run-hooks 'gnus-parse-headers-hook)
(let ((case-fold-search t)
- in-reply-to header number p lines)
+ in-reply-to header p lines)
(goto-char (point-min))
;; Search to the beginning of the next header. Error messages
;; do not begin with 2 or 3.
(setq end (match-end 0))
(save-excursion
(setq ref
- (downcase
- (buffer-substring
- (progn
- (end-of-line)
- (search-backward ">" end t)
- (1+ (point)))
- (progn
- (search-backward "<" end t)
- (point)))))))
+ (buffer-substring
+ (progn
+ (end-of-line)
+ (search-backward ">" end t)
+ (1+ (point)))
+ (progn
+ (search-backward "<" end t)
+ (point))))))
;; Get the references from the in-reply-to header if there
;; were no references and the in-reply-to header looks
;; promising.
(if (and (search-forward "\nin-reply-to: " nil t)
(setq in-reply-to (gnus-header-value))
(string-match "<[^>]+>" in-reply-to))
- (prog1
- (setq ref (substring in-reply-to (match-beginning 0)
- (match-end 0)))
- (setq ref (downcase ref))))
- (setq ref "")))
+ (setq ref (substring in-reply-to (match-beginning 0)
+ (match-end 0)))
+ (setq ref ""))))
;; Chars.
0
;; Lines.
;; the same hash table. Some tippy-toeing around has to be
;; done in case an article has arrived before the article
;; which it refers to.
- (if (boundp (setq id-dep (intern (downcase id) dependencies)))
+ (if (boundp (setq id-dep (intern id dependencies)))
(if (and (car (symbol-value id-dep))
(not force-new))
;; An article with this Message-ID has already
'(buffer-substring (point) (if (gnus-nov-skip-field) (1- (point)) eol)))
;; Goes through the xover lines and returns a list of vectors
-(defun gnus-get-newsgroup-headers-xover (sequence &optional force-new)
+(defun gnus-get-newsgroup-headers-xover (sequence &optional
+ force-new dependencies)
"Parse the news overview data in the server buffer, and return a
list of headers that match SEQUENCE (see `nntp-retrieve-headers')."
;; Get the Xref when the users reads the articles since most/some
;; NNTP servers do not include Xrefs when using XOVER.
(setq gnus-article-internal-prepare-hook '(gnus-article-get-xrefs))
(let ((cur nntp-server-buffer)
- (dependencies gnus-newsgroup-dependencies)
+ (dependencies (or dependencies gnus-newsgroup-dependencies))
number headers header)
(save-excursion
(set-buffer nntp-server-buffer)
;; Allow the user to mangle the headers before parsing them.
(run-hooks 'gnus-parse-headers-hook)
- ;; Allow the user to mangle the headers before parsing them.
- (run-hooks 'gnus-parse-headers-hook)
(goto-char (point-min))
(while (and sequence (not (eobp)))
(setq number (read cur))
(search-forward "\t" eol)
(if (search-backward ">" beg t)
(setq ref
- (downcase
- (buffer-substring
- (1+ (point))
- (progn
- (search-backward "<" beg t)
- (point)))))
+ (buffer-substring
+ (1+ (point))
+ (search-backward "<" beg t)))
(setq ref nil))))
(gnus-nov-field)) ; refs
(gnus-nov-read-integer) ; chars
(gnus-nov-field)) ; misc
))
(error (progn
- (ding)
- (gnus-message 4 "Strange nov line")
+ (gnus-error 4 "Strange nov line")
(setq header nil)
(goto-char eol))))
;; We build the thread tree.
(when header
- (if (boundp (setq id-dep (intern (downcase id) dependencies)))
+ (if (boundp (setq id-dep (intern id dependencies)))
(if (and (car (symbol-value id-dep))
(not force-new))
;; An article with this Message-ID has already been seen,
(progn (end-of-line) (point))))
(mail-header-set-xref headers xref))))))))
-(defun gnus-summary-insert-subject (id)
+(defun gnus-summary-insert-subject (id &optional old-header)
"Find article ID and insert the summary line for that article."
(let ((header (gnus-read-header id))
- (number (and (numberp id) id)))
+ (number (and (numberp id) id))
+ pos)
(when header
;; Rebuild the thread that this article is part of and go to the
;; article we have fetched.
+ (when old-header
+ (when (setq pos (text-property-any
+ (point-min) (point-max) 'gnus-number
+ (mail-header-number old-header)))
+ (goto-char pos)
+ (gnus-delete-line)
+ (gnus-data-remove (mail-header-number old-header))))
+ (when old-header
+ (mail-header-set-number header (mail-header-number old-header)))
+ (setq gnus-newsgroup-sparse
+ (delq (mail-header-number header) gnus-newsgroup-sparse))
(gnus-rebuild-thread (mail-header-id header))
- (gnus-summary-goto-subject (setq number (mail-header-number header))))
+ (gnus-summary-goto-subject (setq number (mail-header-number header))
+ nil t))
(when (and (numberp number)
(> number 0))
;; We have to update the boundaries even if we can't fetch the
(setq gnus-newsgroup-unselected
(delq number gnus-newsgroup-unselected)))
;; Report back a success?
- (and header number)))
+ (and header (mail-header-number header))))
(defun gnus-summary-work-articles (n)
"Return a list of articles to be worked upon. The prefix argument,
(defun gnus-summary-find-next (&optional unread article backward)
(if backward (gnus-summary-find-prev)
- (let* ((article (or article (gnus-summary-article-number)))
+ (let* ((dummy (gnus-summary-article-intangible-p))
+ (article (or article (gnus-summary-article-number)))
(arts (gnus-data-find-list article))
result)
- (when (or (not gnus-summary-check-current)
- (not unread)
- (not (gnus-data-unread-p (car arts))))
+ (when (and (not dummy)
+ (or (not gnus-summary-check-current)
+ (not unread)
+ (not (gnus-data-unread-p (car arts)))))
(setq arts (cdr arts)))
(when (setq result
(if unread
"\\<gnus-summary-mode-map>\\[gnus-summary-universal-argument]"
))))
'undefined)
- (progn
- (message "Undefined key")
- (ding))
+ (gnus-error 1 "Undefined key")
(save-excursion
(while articles
(gnus-summary-goto-subject (setq article (pop articles)))
(run-hooks 'gnus-summary-prepare-exit-hook)
;; If we have several article buffers, we kill them at exit.
(unless gnus-single-article-buffer
- (gnus-kill-buffer gnus-article-buffer)
- (gnus-kill-buffer gnus-original-article-buffer))
+ (gnus-kill-buffer gnus-original-article-buffer)
+ (setq gnus-article-current nil))
(when gnus-use-cache
(gnus-cache-possibly-remove-articles)
(gnus-cache-save-buffers))
;; If we have several article buffers, we kill them at exit.
(unless gnus-single-article-buffer
(gnus-kill-buffer gnus-article-buffer)
- (gnus-kill-buffer gnus-original-article-buffer))
+ (gnus-kill-buffer gnus-original-article-buffer)
+ (setq gnus-article-current nil))
(set-buffer buf)
(if (not gnus-kill-summary-on-exit)
(gnus-deaden-summary)
;; If we have several article buffers, we kill them at exit.
(unless gnus-single-article-buffer
(gnus-kill-buffer gnus-article-buffer)
- (gnus-kill-buffer gnus-original-article-buffer))
+ (gnus-kill-buffer gnus-original-article-buffer)
+ (setq gnus-article-current nil))
(if (not gnus-kill-summary-on-exit)
(gnus-deaden-summary)
(gnus-close-group group)
(gnus-summary-clear-local-variables)
(when (get-buffer gnus-summary-buffer)
(kill-buffer gnus-summary-buffer)))
+ (unless gnus-single-article-buffer
+ (setq gnus-article-current nil))
(when gnus-use-trees
(gnus-tree-close group))
(when (get-buffer gnus-article-buffer)
(defun gnus-kill-or-deaden-summary (buffer)
"Kill or deaden the summary BUFFER."
+ (when (and (buffer-name buffer)
+ (not gnus-single-article-buffer))
+ (save-excursion
+ (set-buffer buffer)
+ (gnus-kill-buffer gnus-article-buffer)
+ (gnus-kill-buffer gnus-original-article-buffer)))
(cond (gnus-kill-summary-on-exit
(when (and gnus-use-trees
(and (get-buffer buffer)
(funcall gnus-summary-display-article-function article all-header)
(gnus-article-prepare article all-header))
(run-hooks 'gnus-select-article-hook)
+ (unless (zerop gnus-current-article)
+ (gnus-summary-goto-subject gnus-current-article))
(gnus-summary-recenter)
- (gnus-summary-goto-subject article)
(when gnus-use-trees
(gnus-possibly-generate-tree article)
(gnus-highlight-selected-tree article))
;; Successfully display article.
(gnus-article-set-window-start
- (cdr (assq article gnus-newsgroup-bookmarks)))
- t)))
+ (cdr (assq article gnus-newsgroup-bookmarks))))))
(defun gnus-summary-select-article (&optional all-headers force pseudo article)
"Select the current article.
non-nil, the article will be re-fetched even if it already present in
the article buffer. If PSEUDO is non-nil, pseudo-articles will also
be displayed."
+ ;; Make sure we are in the summary buffer to work around bbdb bug.
+ (unless (eq major-mode 'gnus-summary-mode)
+ (set-buffer gnus-summary-buffer))
(let ((article (or article (gnus-summary-article-number)))
(all-headers (not (not all-headers))) ;Must be T or NIL.
gnus-summary-display-article-function
(not (equal (car gnus-article-current)
gnus-newsgroup-name))))
(and (not gnus-single-article-buffer)
- (null gnus-current-article))
+ (or (null gnus-current-article)
+ (not (eq gnus-current-article article))))
force)
;; The requested article is different from the current article.
(prog1
If BACKWARD, the previous article is selected instead of the next."
(interactive "P")
(gnus-set-global-variables)
- (let (header)
- (cond
- ;; Is there such an article?
- ((and (gnus-summary-search-forward unread subject backward)
- (or (gnus-summary-display-article (gnus-summary-article-number))
- (eq (gnus-summary-article-mark) gnus-canceled-mark)))
- (gnus-summary-position-point))
- ;; If not, we try the first unread, if that is wanted.
- ((and subject
- gnus-auto-select-same
- (or (gnus-summary-first-unread-article)
- (eq (gnus-summary-article-mark) gnus-canceled-mark)))
- (gnus-summary-position-point)
- (gnus-message 6 "Wrapped"))
- ;; Try to get next/previous article not displayed in this group.
- ((and gnus-auto-extend-newsgroup
- (not unread) (not subject))
- (gnus-summary-goto-article
- (if backward (1- gnus-newsgroup-begin) (1+ gnus-newsgroup-end))
- nil t))
- ;; Go to next/previous group.
- (t
- (or (gnus-ephemeral-group-p gnus-newsgroup-name)
- (gnus-summary-jump-to-group gnus-newsgroup-name))
- (let ((cmd last-command-char)
- (group
- (if (eq gnus-keep-same-level 'best)
- (gnus-summary-best-group gnus-newsgroup-name)
- (gnus-summary-search-group backward gnus-keep-same-level))))
- ;; For some reason, the group window gets selected. We change
- ;; it back.
- (select-window (get-buffer-window (current-buffer)))
- ;; Select next unread newsgroup automagically.
- (cond
- ((not gnus-auto-select-next)
- (gnus-message 7 "No more%s articles" (if unread " unread" "")))
- ((or (eq gnus-auto-select-next 'quietly)
- (and (eq gnus-auto-select-next 'slightly-quietly)
- push)
- (and (eq gnus-auto-select-next 'almost-quietly)
- (gnus-summary-last-article-p)))
- ;; Select quietly.
- (if (gnus-ephemeral-group-p gnus-newsgroup-name)
- (gnus-summary-exit)
- (gnus-message 7 "No more%s articles (%s)..."
- (if unread " unread" "")
- (if group (concat "selecting " group)
- "exiting"))
- (gnus-summary-next-group nil group backward)))
- (t
- (gnus-summary-walk-group-buffer
- gnus-newsgroup-name cmd unread backward))))))))
+ (cond
+ ;; Is there such an article?
+ ((and (gnus-summary-search-forward unread subject backward)
+ (or (gnus-summary-display-article (gnus-summary-article-number))
+ (eq (gnus-summary-article-mark) gnus-canceled-mark)))
+ (gnus-summary-position-point))
+ ;; If not, we try the first unread, if that is wanted.
+ ((and subject
+ gnus-auto-select-same
+ (or (gnus-summary-first-unread-article)
+ (eq (gnus-summary-article-mark) gnus-canceled-mark)))
+ (gnus-summary-position-point)
+ (gnus-message 6 "Wrapped"))
+ ;; Try to get next/previous article not displayed in this group.
+ ((and gnus-auto-extend-newsgroup
+ (not unread) (not subject))
+ (gnus-summary-goto-article
+ (if backward (1- gnus-newsgroup-begin) (1+ gnus-newsgroup-end))
+ nil t))
+ ;; Go to next/previous group.
+ (t
+ (or (gnus-ephemeral-group-p gnus-newsgroup-name)
+ (gnus-summary-jump-to-group gnus-newsgroup-name))
+ (let ((cmd last-command-char)
+ (group
+ (if (eq gnus-keep-same-level 'best)
+ (gnus-summary-best-group gnus-newsgroup-name)
+ (gnus-summary-search-group backward gnus-keep-same-level))))
+ ;; For some reason, the group window gets selected. We change
+ ;; it back.
+ (select-window (get-buffer-window (current-buffer)))
+ ;; Select next unread newsgroup automagically.
+ (cond
+ ((not gnus-auto-select-next)
+ (gnus-message 7 "No more%s articles" (if unread " unread" "")))
+ ((or (eq gnus-auto-select-next 'quietly)
+ (and (eq gnus-auto-select-next 'slightly-quietly)
+ push)
+ (and (eq gnus-auto-select-next 'almost-quietly)
+ (gnus-summary-last-article-p)))
+ ;; Select quietly.
+ (if (gnus-ephemeral-group-p gnus-newsgroup-name)
+ (gnus-summary-exit)
+ (gnus-message 7 "No more%s articles (%s)..."
+ (if unread " unread" "")
+ (if group (concat "selecting " group)
+ "exiting"))
+ (gnus-summary-next-group nil group backward)))
+ (t
+ (gnus-summary-walk-group-buffer
+ gnus-newsgroup-name cmd unread backward)))))))
(defun gnus-summary-walk-group-buffer (from-group cmd unread backward)
(let ((keystrokes '((?\C-n (gnus-group-next-unread-group 1))
(let ((article (gnus-summary-article-number))
(endp nil))
(gnus-configure-windows 'article)
- (if (or (null gnus-current-article)
- (null gnus-article-current)
- (/= article (cdr gnus-article-current))
- (not (equal (car gnus-article-current) gnus-newsgroup-name)))
- ;; Selected subject is different from current article's.
- (gnus-summary-display-article article)
- (gnus-eval-in-buffer-window
- gnus-article-buffer
- (setq endp (gnus-article-next-page lines)))
- (if endp
- (cond (circular
- (gnus-summary-beginning-of-article))
- (lines
- (gnus-message 3 "End of message"))
- ((null lines)
- (if (and (eq gnus-summary-goto-unread 'never)
- (not (eq article gnus-newsgroup-end)))
- (gnus-summary-next-article)
- (gnus-summary-next-unread-article))))))
+ (if (eq (cdr (assq article gnus-newsgroup-reads)) gnus-canceled-mark)
+ (if (and (eq gnus-summary-goto-unread 'never)
+ (not (gnus-summary-last-article-p article)))
+ (gnus-summary-next-article)
+ (gnus-summary-next-unread-article))
+ (if (or (null gnus-current-article)
+ (null gnus-article-current)
+ (/= article (cdr gnus-article-current))
+ (not (equal (car gnus-article-current) gnus-newsgroup-name)))
+ ;; Selected subject is different from current article's.
+ (gnus-summary-display-article article)
+ (gnus-eval-in-buffer-window
+ gnus-article-buffer
+ (setq endp (gnus-article-next-page lines)))
+ (if endp
+ (cond (circular
+ (gnus-summary-beginning-of-article))
+ (lines
+ (gnus-message 3 "End of message"))
+ ((null lines)
+ (if (and (eq gnus-summary-goto-unread 'never)
+ (not (gnus-summary-last-article-p article)))
+ (gnus-summary-next-article)
+ (gnus-summary-next-unread-article)))))))
(gnus-summary-recenter)
(gnus-summary-position-point)))
(interactive "p")
(gnus-set-global-variables)
(gnus-configure-windows 'article)
+ (gnus-summary-show-thread)
(when (eq (gnus-summary-select-article nil nil 'pseudo) 'old)
(gnus-eval-in-buffer-window
gnus-article-buffer
(setq best score
article (gnus-data-number (car data))))
(setq data (cdr data)))
- (if article
- (gnus-summary-goto-article article)
- (error "No unread articles"))
- (gnus-summary-position-point)))
+ (prog1
+ (if article
+ (gnus-summary-goto-article article)
+ (error "No unread articles"))
+ (gnus-summary-position-point))))
(defun gnus-summary-last-subject ()
"Go to the last displayed subject line in the group."
(defsubst gnus-cut-thread (thread)
"Go forwards in the thread until we find an article that we want to display."
- (if (eq gnus-fetch-old-headers 'some)
- (while (and thread
- (memq (mail-header-number (car thread))
- gnus-newsgroup-ancient)
- (<= (length (cdr thread)) 1))
- (setq thread (cadr thread)))
+ (when (eq gnus-fetch-old-headers 'some)
+ ;; Deal with old-fetched headers.
+ (while (and thread
+ (memq (mail-header-number (car thread))
+ gnus-newsgroup-ancient)
+ (<= (length (cdr thread)) 1))
+ (setq thread (cadr thread))))
+ ;; Deal with sparse threads.
+ (when (or (eq gnus-build-sparse-threads 'some)
+ (eq gnus-build-sparse-threads 'more))
(while (and thread
(memq (mail-header-number (car thread)) gnus-newsgroup-sparse)
(= (length (cdr thread)) 1))
(while th
(setcar th (gnus-cut-thread (car th)))
(setq th (cdr th)))))
- threads)
+ ;; Remove nixed out threads.
+ (delq nil threads))
(defun gnus-summary-initial-limit (&optional show-if-empty)
"Figure out what the initial limit is supposed to be on group entry.
(setq message-id (concat "<" message-id)))
(unless (string-match ">$" message-id)
(setq message-id (concat message-id ">")))
- (let ((header (car (gnus-gethash (downcase message-id)
+ (let ((header (car (gnus-gethash message-id
gnus-newsgroup-dependencies))))
(if header
;; The article is present in the buffer, to we just go to it.
(gnus-summary-goto-article (mail-header-number header) nil t)
;; We fetch the article
- (let ((gnus-override-method gnus-refer-article-method)
+ (let ((gnus-override-method
+ (and (gnus-news-group-p gnus-newsgroup-name)
+ gnus-refer-article-method))
number)
;; Start the special refer-article method, if necessary.
- (when gnus-refer-article-method
+ (when (and gnus-refer-article-method
+ (gnus-news-group-p gnus-newsgroup-name))
(gnus-check-server gnus-refer-article-method))
;; Fetch the header, and display the article.
(if (setq number (gnus-summary-insert-subject message-id))
Optional argument BACKWARD means do search for backward.
gnus-select-article-hook is not called during the search."
(let ((gnus-select-article-hook nil) ;Disable hook.
+ (gnus-article-display-hook nil)
(gnus-mark-article-hook nil) ;Inhibit marking as read.
(re-search
(if backward
(let ((gnus-have-all-headers t)
gnus-article-display-hook
gnus-article-prepare-hook
+ gnus-break-pages
gnus-visual)
(gnus-summary-select-article nil 'force)))
+ (gnus-summary-goto-subject gnus-current-article)
; (gnus-configure-windows 'article)
(gnus-summary-position-point))
If N is nil and any articles have been marked with the process mark,
move those articles instead.
If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
-If SELECT-METHOD is symbol, do not move to a specific newsgroup, but
+If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
re-spool using this method.
For this function to work, both the current newsgroup and the
(error "The current group does not support article editing")))
(let ((articles (gnus-summary-work-articles n))
(prefix (gnus-group-real-prefix gnus-newsgroup-name))
- (names '((move "move" "Moving")
- (copy "copy" "Copying")
- (crosspost "crosspost" "Crossposting")))
+ (names '((move "Move" "Moving")
+ (copy "Copy" "Copying")
+ (crosspost "Crosspost" "Crossposting")))
(copy-buf (save-excursion
(nnheader-set-temp-buffer " *copy article*")))
- art-group to-method new-xref article)
+ art-group to-method new-xref article to-groups)
(unless (assq action names)
(error "Unknown action %s" action))
;; Read the newsgroup name.
(setq to-newsgroup
(gnus-read-move-group-name
(cadr (assq action names))
- gnus-current-move-group articles prefix))
+ (symbol-value (intern (format "gnus-current-%s-group" action)))
+ articles prefix))
(set (intern (format "gnus-current-%s-group" action)) to-newsgroup))
- (setq to-method (if select-method (list select-method "")
- (gnus-find-method-for-group to-newsgroup)))
- ;;(when (equal to-newsgroup gnus-newsgroup-name)
- ;;(error "Can't %s to the same group you're already in" action))
+ (setq to-method (or select-method
+ (gnus-find-method-for-group to-newsgroup)))
;; Check the method we are to move this article to...
(or (gnus-check-backend-function 'request-accept-article (car to-method))
(error "%s does not support article copying" (car to-method)))
(error "Can't open server %s" (car to-method)))
(gnus-message 6 "%s to %s: %s..."
(caddr (assq action names))
- (or select-method to-newsgroup) articles)
+ (or (car select-method) to-newsgroup) articles)
(while articles
(setq article (pop articles))
(setq
(nth 1 (gnus-find-method-for-group
gnus-newsgroup-name)) ; Server
(list 'gnus-request-accept-article
- (if select-method
- (list 'quote select-method)
- to-newsgroup)
+ to-newsgroup (list 'quote select-method)
(not articles)) ; Accept form
(not articles))) ; Only save nov last time
;; Copy the article.
(set-buffer copy-buf)
(gnus-request-article-this-buffer article gnus-newsgroup-name)
(gnus-request-accept-article
- (if select-method select-method to-newsgroup)
- (not articles))))
+ to-newsgroup select-method (not articles))))
;; Crosspost the article.
((eq action 'crosspost)
(let ((xref (mail-header-xref (gnus-summary-article-header article))))
(gnus-request-article-this-buffer article gnus-newsgroup-name)
(nnheader-replace-header "xref" new-xref)
(gnus-request-accept-article
- (if select-method select-method to-newsgroup)
- (not articles)))))))
+ to-newsgroup select-method (not articles)))))))
(if (not art-group)
(gnus-message 1 "Couldn't %s article %s"
(cadr (assq action names)) article)
(gnus-gethash
(gnus-group-prefixed-name
(car art-group)
- (if select-method (list select-method "")
- (gnus-find-method-for-group to-newsgroup)))
+ (or select-method
+ (gnus-find-method-for-group to-newsgroup)))
gnus-newsrc-hashtb)))
- (info (nth 2 entry)))
+ (info (nth 2 entry))
+ (to-group (gnus-info-group info)))
;; Update the group that has been moved to.
(when (and info
(memq action '(move copy)))
+ (unless (member to-group to-groups)
+ (push to-group to-groups))
+
(unless (memq article gnus-newsgroup-unreads)
(gnus-info-set-read
info (gnus-add-to-range (gnus-info-read info)
;; See whether the article is to be put in the cache.
(when gnus-use-cache
(gnus-cache-possibly-enter-article
- (gnus-info-group info) to-article
+ to-group to-article
(let ((header (copy-sequence
(gnus-summary-article-header article))))
(mail-header-set-number header to-article)
(when (memq article (symbol-value
(intern (format "gnus-newsgroup-%s"
(caar marks)))))
+ ;; If the other group is the same as this group,
+ ;; then we have to add the mark to the list.
+ (when (equal to-group gnus-newsgroup-name)
+ (set (intern (format "gnus-newsgroup-%s" (caar marks)))
+ (cons to-article
+ (symbol-value
+ (intern (format "gnus-newsgroup-%s"
+ (caar marks)))))))
+ ;; Copy mark to other group.
(gnus-add-marked-articles
- (gnus-info-group info) (cdar marks)
- (list to-article) info))
+ to-group (cdar marks) (list to-article) info))
(setq marks (cdr marks)))))
;; Update the Xref header in this article to point to
(when (eq action 'move)
(gnus-summary-mark-article article gnus-canceled-mark)))
(gnus-summary-remove-process-mark article))
+ ;; Re-activate all groups that have been moved to.
+ (while to-groups
+ (gnus-activate-group (pop to-groups)))
+
(gnus-kill-buffer copy-buf)
(gnus-summary-position-point)
(gnus-set-mode-line 'summary)))
(defun gnus-summary-copy-article (&optional n to-newsgroup select-method)
"Move the current article to a different newsgroup.
If TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.
-If SELECT-METHOD is symbol, do not move to a specific newsgroup, but
+If SELECT-METHOD is non-nil, do not move to a specific newsgroup, but
re-spool using this method."
(interactive "P")
(gnus-summary-move-article n nil select-method 'copy))
(interactive "P")
(gnus-summary-move-article n nil nil 'crosspost))
-(defun gnus-summary-respool-article (&optional n respool-method)
+(defvar gnus-summary-respool-default-method nil
+ "Default method for respooling an article.
+If nil, use to the current newsgroup method.")
+
+(defun gnus-summary-respool-article (&optional n method)
"Respool the current article.
The article will be squeezed through the mail spooling process again,
which means that it will be put in some mail newsgroup or other
In the former case, the articles in question will be moved from the
current group into whatever groups they are destined to. In the
latter case, they will be copied into the relevant groups."
- (interactive "P")
+ (interactive
+ (list current-prefix-arg
+ (let* ((methods (gnus-methods-using 'respool))
+ (methname
+ (symbol-name (or gnus-summary-respool-default-method
+ (car (gnus-find-method-for-group
+ gnus-newsgroup-name)))))
+ (method
+ (gnus-completing-read
+ methname "What backend do you want to use when? "
+ methods nil t nil 'gnus-method-history))
+ ms)
+ (cond
+ ((zerop (length (setq ms (gnus-servers-using-backend method))))
+ (list (intern method) ""))
+ ((= 1 (length ms))
+ (car ms))
+ (t
+ (cdr (completing-read
+ "Server name: "
+ (mapcar (lambda (m) (cons (cadr m) m)) ms) nil t)))))))
(gnus-set-global-variables)
- (let ((respool-methods (gnus-methods-using 'respool))
- (methname
- (symbol-name (car (gnus-find-method-for-group gnus-newsgroup-name)))))
- (or respool-method
- (setq respool-method
- (completing-read
- "What method do you want to use when respooling? "
- respool-methods nil t methname)))
- (or (string= respool-method "")
- (if (assoc (symbol-name
- (car (gnus-find-method-for-group gnus-newsgroup-name)))
- respool-methods)
- (gnus-summary-move-article n nil (intern respool-method))
- (gnus-summary-copy-article n nil (intern respool-method))))))
+ (unless method
+ (error "No method given for respooling"))
+ (if (assoc (symbol-name
+ (car (gnus-find-method-for-group gnus-newsgroup-name)))
+ (gnus-methods-using 'respool))
+ (gnus-summary-move-article n nil method)
+ (gnus-summary-copy-article n nil method)))
(defun gnus-summary-import-article (file)
"Import a random file into a mail newsgroup."
"Message-ID: " (gnus-inews-message-id) "\n"
"Lines: " (int-to-string lines) "\n"
"Chars: " (int-to-string (nth 7 atts)) "\n\n"))
- (gnus-request-accept-article group t)
+ (gnus-request-accept-article group nil t)
(kill-buffer (current-buffer)))))
-(defun gnus-summary-expire-articles ()
+(defun gnus-summary-expire-articles (&optional now)
"Expire all articles that are marked as expirable in the current group."
(interactive)
(gnus-set-global-variables)
(gnus-list-of-read-articles gnus-newsgroup-name)
(setq gnus-newsgroup-expirable
(sort gnus-newsgroup-expirable '<))))
- (expiry-wait (gnus-group-get-parameter
- gnus-newsgroup-name 'expiry-wait))
+ (expiry-wait (if now 'immediate
+ (gnus-group-get-parameter
+ gnus-newsgroup-name 'expiry-wait)))
es)
(when expirable
;; There are expirable articles in this group, so we run them
(gnus-set-global-variables)
(or gnus-expert-user
(gnus-y-or-n-p
- "Are you really, really, really sure you want to expunge? ")
+ "Are you really, really, really sure you want to delete all these messages? ")
(error "Phew!"))
- (let ((nnmail-expiry-wait 'immediate)
- (nnmail-expiry-wait-function nil))
- (gnus-summary-expire-articles)))
+ (gnus-summary-expire-articles t))
;; Suggested by Jack Vinson <vinson@unagi.cis.upenn.edu>.
(defun gnus-summary-delete-article (&optional n)
(if (and gnus-novice-user
(not (gnus-y-or-n-p
(format "Do you really want to delete %s forever? "
- (if (> (length articles) 1) "these articles"
+ (if (> (length articles) 1)
+ (format "these %s articles" (length articles))
"this article")))))
()
;; Delete the articles.
(if (gnus-group-read-only-p)
(progn
(gnus-summary-edit-article-postpone)
- (gnus-message
- 1 "The current newsgroup does not support article editing.")
- (ding))
+ (gnus-error
+ 1 "The current newsgroup does not support article editing."))
(let ((buf (format "%s" (buffer-string))))
(erase-buffer)
(insert buf)
(gnus-summary-update-article (cdr gnus-article-current))
(when gnus-use-cache
(gnus-cache-update-article
- (cdr gnus-article-current) (car gnus-article-current))))
+ (cdr gnus-article-current) (car gnus-article-current)))
+ (when gnus-keep-backlog
+ (gnus-backlog-remove-article
+ (car gnus-article-current) (cdr gnus-article-current))))
+ (save-excursion
+ (when (get-buffer gnus-original-article-buffer)
+ (set-buffer gnus-original-article-buffer)
+ (setq gnus-original-article nil)))
+ (setq gnus-article-current nil
+ gnus-current-article nil)
(run-hooks 'gnus-article-display-hook)
(and (gnus-visual-p 'summary-highlight 'highlight)
(run-hooks 'gnus-visual-mark-article-hook)))))
"Return the score of the current article."
(interactive)
(gnus-set-global-variables)
- (message "%s" (gnus-summary-article-score)))
+ (gnus-message 1 "%s" (gnus-summary-article-score)))
;; Summary marking commands.
(beginning-of-line)
(let ((forward (cdr (assq type gnus-summary-mark-positions)))
(buffer-read-only nil))
- (when forward
+ (when (and forward
+ (<= (+ forward (point)) (point-max)))
;; Go to the right position on the line.
- (forward-char forward)
+ (goto-char (+ forward (point)))
;; Replace the old mark with the new mark.
(subst-char-in-region (point) (1+ (point)) (following-char) mark)
;; Optionally update the marks by some user rule.
(gnus-simplify-subject-fuzzy
(mail-header-subject (gnus-data-header (car data)))))
(t nil)))
+ (end-point (save-excursion
+ (if (gnus-summary-go-to-next-thread)
+ (point) (point-max))))
articles)
- (if (not data)
- () ; This article doesn't exist.
- (while data
- (and (or (not top-subject)
- (string= top-subject
- (if (eq gnus-thread-operation-ignore-subject 'fuzzy)
- (gnus-simplify-subject-fuzzy
- (mail-header-subject
- (gnus-data-header (car data))))
- (gnus-simplify-subject-re
- (mail-header-subject
- (gnus-data-header (car data)))))))
- (setq articles (cons (gnus-data-number (car data)) articles)))
- (if (and (setq data (cdr data))
- (> (gnus-data-level (car data)) top-level))
- ()
- (setq data nil)))
- ;; Return the list of articles.
- (nreverse articles))))
+ (while (and data
+ (< (gnus-data-pos (car data)) end-point))
+ (when (or (not top-subject)
+ (string= top-subject
+ (if (eq gnus-thread-operation-ignore-subject 'fuzzy)
+ (gnus-simplify-subject-fuzzy
+ (mail-header-subject
+ (gnus-data-header (car data))))
+ (gnus-simplify-subject-re
+ (mail-header-subject
+ (gnus-data-header (car data)))))))
+ (push (gnus-data-number (car data)) articles))
+ (unless (and (setq data (cdr data))
+ (> (gnus-data-level (car data)) top-level))
+ (setq data nil)))
+ ;; Return the list of articles.
+ (nreverse articles)))
(defun gnus-summary-rethread-current ()
"Rethread the thread the current article is part of."
(set-buffer gnus-summary-buffer)
(gnus-summary-unmark-all-processable)
(gnus-summary-rethread-current)
- (message "Article %d is now the child of article %d."
- current-article parent-article)))))
+ (gnus-message 3 "Article %d is now the child of article %d."
+ current-article parent-article)))))
(defun gnus-summary-toggle-threads (&optional arg)
"Toggle showing conversation threads.
(gnus-set-global-variables)
(let ((buffer-read-only nil)
(start (point))
- (article (gnus-summary-article-number))
- end)
+ (article (gnus-summary-article-number)))
(goto-char start)
;; Go forward until either the buffer ends or the subthread
;; ends.
(when (and (not (eobp))
(or (zerop (gnus-summary-next-thread 1 t))
(goto-char (point-max))))
- (setq end (point))
(prog1
(if (and (> (point) start)
(search-backward "\n" start t))
(defun gnus-summary-go-to-next-thread (&optional previous)
"Go to the same level (or less) next thread.
If PREVIOUS is non-nil, go to previous thread instead.
+Return the article number moved to, or nil if moving was impossible."
+ (let ((level (gnus-summary-thread-level))
+ (way (if previous -1 1))
+ (beg (point)))
+ (forward-line way)
+ (while (and (not (eobp))
+ (< level (gnus-summary-thread-level)))
+ (forward-line way))
+ (if (eobp)
+ (progn
+ (goto-char beg)
+ nil)
+ (setq beg (point))
+ (prog1
+ (gnus-summary-article-number)
+ (goto-char beg)))))
+
+(defun gnus-summary-go-to-next-thread-old (&optional previous)
+ "Go to the same level (or less) next thread.
+If PREVIOUS is non-nil, go to previous thread instead.
Return the article number moved to, or nil if moving was impossible."
(if (and (eq gnus-summary-make-false-root 'dummy)
(gnus-summary-article-intangible-p))
(let ((beg (point)))
(while (and (zerop (forward-line 1))
- (not (gnus-summary-article-intangible-p))))
+ (not (gnus-summary-article-intangible-p))
+ (not (zerop (save-excursion
+ (gnus-summary-thread-level))))))
(if (eobp)
(progn
(goto-char beg)
(n (abs n))
old dum int)
(while (and (> n 0)
- (setq old (save-excursion
- (forward-line 1)
- (setq int (gnus-summary-article-intangible-p))
- (point)))
- (or int
- (gnus-summary-go-to-next-thread backward)))
- (when (and (eq gnus-summary-make-false-root 'dummy)
- (setq dum (text-property-not-all
- old (point) 'gnus-intangible nil)))
- (goto-char dum))
+ (gnus-summary-go-to-next-thread backward))
(decf n))
(unless silent
(gnus-summary-position-point))
(defun gnus-read-move-group-name (prompt default articles prefix)
"Read a group name."
(let* ((split-name (gnus-get-split-value gnus-move-split-methods))
+ group-map
+ (dum (mapatoms
+ (lambda (g)
+ (and (boundp g)
+ (symbol-name g)
+ (memq 'respool
+ (assoc (symbol-name
+ (car (gnus-find-method-for-group
+ (symbol-name g))))
+ gnus-valid-select-methods))
+ (push (list (symbol-name g)) group-map)))
+ gnus-active-hashtb))
(prom
- (format "Where do you want to %s %s? "
+ (format "%s %s to:"
prompt
(if (> (length articles) 1)
(format "these %d articles" (length articles))
(to-newsgroup
(cond
((null split-name)
- (completing-read
- (concat prom
- (if default
- (format "(default %s) " default)
- ""))
- gnus-active-hashtb nil nil prefix))
+ (gnus-completing-read default prom
+ group-map nil nil prefix
+ 'gnus-group-history))
((= 1 (length split-name))
- (completing-read prom gnus-active-hashtb
- nil nil (cons (car split-name) 0)))
+ (gnus-completing-read (car split-name) prom group-map
+ nil nil nil
+ 'gnus-group-history))
(t
- (completing-read
- prom (mapcar (lambda (el) (list el)) (nreverse split-name)))))))
-
+ (gnus-completing-read nil prom
+ (mapcar (lambda (el) (list el))
+ (nreverse split-name))
+ nil nil nil
+ 'gnus-group-history)))))
(when to-newsgroup
(if (or (string= to-newsgroup "")
(string= to-newsgroup prefix))
(concat gnus-article-save-directory (car split-name))))
;; A list of splits was found.
(t
- (setq split-name (mapcar (lambda (el) (list el))
- (nreverse split-name)))
- (let ((result (completing-read
- (concat prompt " ") split-name nil nil)))
- (concat gnus-article-save-directory
- (if (string= result "")
- (caar split-name)
- result)))))))
+ (setq split-name (nreverse split-name))
+ (let (result)
+ (let ((file-name-history (nconc split-name file-name-history)))
+ (setq result
+ (read-file-name
+ (concat prompt " (`M-p' for defaults) ")
+ gnus-article-save-directory
+ (car split-name))))
+ (car (push result file-name-history)))))))
;; If we have read a directory, we append the default file name.
(when (file-directory-p file)
(setq file (concat (file-name-as-directory file)
(gnus-summary-goto-subject after-article)
(forward-line 1)
(setq b (point))
- (insert " " (file-name-nondirectory
+ (insert " " (file-name-nondirectory
(cdr (assq 'name (car pslist))))
": " (or (cdr (assq 'execute (car pslist))) "") "\n")
(setq e (point))
(forward-line -1) ; back to `b'
- (add-text-properties
+ (gnus-add-text-properties
b e (list 'gnus-number gnus-reffed-article-number
gnus-mouse-face-prop gnus-mouse-face))
(gnus-data-enter
(save-excursion
(gnus-article-setup-buffer)
(set-buffer gnus-article-buffer)
+ (setq buffer-read-only nil)
(let ((command (if automatic command (read-string "Command: " command)))
- (buffer-read-only nil))
+ ;; Just binding this here doesn't help, because there might
+ ;; be output from the process after exiting the scope of
+ ;; this `let'.
+ ;; (buffer-read-only nil)
+ )
(erase-buffer)
(insert "$ " command "\n\n")
(if gnus-view-pseudo-asynchronously
(setq gnus-original-article-buffer original)
(gnus-set-global-variables))
(make-local-variable 'gnus-summary-buffer))
+ ;; Init original article buffer.
+ (save-excursion
+ (set-buffer (get-buffer-create gnus-original-article-buffer))
+ (buffer-disable-undo (current-buffer))
+ (setq major-mode 'gnus-original-article-mode)
+ (make-local-variable 'gnus-original-article))
(if (get-buffer name)
(save-excursion
(set-buffer name)
;; from the head of the article.
(defun gnus-article-set-window-start (&optional line)
(set-window-start
- (get-buffer-window gnus-article-buffer)
+ (get-buffer-window gnus-article-buffer t)
(save-excursion
(set-buffer gnus-article-buffer)
(goto-char (point-min))
(defun gnus-request-article-this-buffer (article group)
"Get an article and insert it into this buffer."
- (prog1
- (save-excursion
- (erase-buffer)
- (gnus-kill-all-overlays)
- (setq group (or group gnus-newsgroup-name))
-
- ;; Open server if it has closed.
- (gnus-check-server (gnus-find-method-for-group group))
-
- ;; Using `gnus-request-article' directly will insert the article into
- ;; `nntp-server-buffer' - so we'll save some time by not having to
- ;; copy it from the server buffer into the article buffer.
-
- ;; We only request an article by message-id when we do not have the
- ;; headers for it, so we'll have to get those.
- (when (stringp article)
- (let ((gnus-override-method gnus-refer-article-method))
- (gnus-read-header article)))
-
- ;; If the article number is negative, that means that this article
- ;; doesn't belong in this newsgroup (possibly), so we find its
- ;; message-id and request it by id instead of number.
- (when (and (numberp article)
- gnus-summary-buffer
- (buffer-name gnus-summary-buffer))
- (save-excursion
- (set-buffer gnus-summary-buffer)
- (let ((header (gnus-summary-article-header article)))
- (if (< article 0)
- (cond
- ((memq article gnus-newsgroup-sparse)
- ;; This is a sparse gap article.
- (setq article (mail-header-id header)))
- ((vectorp header)
- ;; It's a real article.
- (setq article (mail-header-id header)))
- (t
- ;; It is an extracted pseudo-article.
- (setq article 'pseudo)
- (gnus-request-pseudo-article header))))
+ (let (do-update-line)
+ (prog1
+ (save-excursion
+ (erase-buffer)
+ (gnus-kill-all-overlays)
+ (setq group (or group gnus-newsgroup-name))
+
+ ;; Open server if it has closed.
+ (gnus-check-server (gnus-find-method-for-group group))
+
+ ;; Using `gnus-request-article' directly will insert the article into
+ ;; `nntp-server-buffer' - so we'll save some time by not having to
+ ;; copy it from the server buffer into the article buffer.
+
+ ;; We only request an article by message-id when we do not have the
+ ;; headers for it, so we'll have to get those.
+ (when (stringp article)
+ (let ((gnus-override-method gnus-refer-article-method))
+ (gnus-read-header article)))
+
+ ;; If the article number is negative, that means that this article
+ ;; doesn't belong in this newsgroup (possibly), so we find its
+ ;; message-id and request it by id instead of number.
+ (when (and (numberp article)
+ gnus-summary-buffer
+ (get-buffer gnus-summary-buffer)
+ (buffer-name (get-buffer gnus-summary-buffer)))
+ (save-excursion
+ (set-buffer gnus-summary-buffer)
+ (let ((header (gnus-summary-article-header article)))
+ (if (< article 0)
+ (cond
+ ((memq article gnus-newsgroup-sparse)
+ ;; This is a sparse gap article.
+ (setq do-update-line article)
+ (setq article (mail-header-id header))
+ (let ((gnus-override-method gnus-refer-article-method))
+ (gnus-read-header article))
+ (setq gnus-newsgroup-sparse
+ (delq article gnus-newsgroup-sparse)))
+ ((vectorp header)
+ ;; It's a real article.
+ (setq article (mail-header-id header)))
+ (t
+ ;; It is an extracted pseudo-article.
+ (setq article 'pseudo)
+ (gnus-request-pseudo-article header))))
- (let ((method (gnus-find-method-for-group
- gnus-newsgroup-name)))
- (if (not (eq (car method) 'nneething))
- ()
- (let ((dir (concat (file-name-as-directory (nth 1 method))
- (mail-header-subject header))))
- (if (file-directory-p dir)
- (progn
- (setq article 'nneething)
- (gnus-group-enter-directory dir)))))))))
-
- (cond
- ;; We first check `gnus-original-article-buffer'.
- ((and (equal (car gnus-original-article) group)
- (eq (cdr gnus-original-article) article)
- (get-buffer gnus-original-article-buffer))
- (insert-buffer-substring gnus-original-article-buffer)
- 'article)
- ;; Check the backlog.
- ((and gnus-keep-backlog
- (gnus-backlog-request-article group article (current-buffer)))
- 'article)
- ;; Check the cache.
- ((and gnus-use-cache
- (numberp article)
- (gnus-cache-request-article article group))
- 'article)
- ;; Get the article and put into the article buffer.
- ((or (stringp article) (numberp article))
- (let ((gnus-override-method
- (and (stringp article) gnus-refer-article-method))
- (buffer-read-only nil))
+ (let ((method (gnus-find-method-for-group
+ gnus-newsgroup-name)))
+ (if (not (eq (car method) 'nneething))
+ ()
+ (let ((dir (concat (file-name-as-directory (nth 1 method))
+ (mail-header-subject header))))
+ (if (file-directory-p dir)
+ (progn
+ (setq article 'nneething)
+ (gnus-group-enter-directory dir)))))))))
+
+ (cond
+ ;; Refuse to select canceled articles.
+ ((and (numberp article)
+ gnus-summary-buffer
+ (get-buffer gnus-summary-buffer)
+ (buffer-name (get-buffer gnus-summary-buffer))
+ (eq (cdr (save-excursion
+ (set-buffer gnus-summary-buffer)
+ (assq article gnus-newsgroup-reads)))
+ gnus-canceled-mark))
+ nil)
+ ;; We first check `gnus-original-article-buffer'.
+ ((and (get-buffer gnus-original-article-buffer)
+ (numberp article)
+ (save-excursion
+ (set-buffer gnus-original-article-buffer)
+ (and (equal (car gnus-original-article) group)
+ (eq (cdr gnus-original-article) article))))
+ (insert-buffer-substring gnus-original-article-buffer)
+ 'article)
+ ;; Check the backlog.
+ ((and gnus-keep-backlog
+ (gnus-backlog-request-article group article (current-buffer)))
+ 'article)
+ ;; Check the cache.
+ ((and gnus-use-cache
+ (numberp article)
+ (gnus-cache-request-article article group))
+ 'article)
+ ;; Get the article and put into the article buffer.
+ ((or (stringp article) (numberp article))
+ (let ((gnus-override-method
+ (and (stringp article) gnus-refer-article-method))
+ (buffer-read-only nil))
+ (erase-buffer)
+ (gnus-kill-all-overlays)
+ (if (gnus-request-article article group (current-buffer))
+ (progn
+ (and gnus-keep-backlog
+ (numberp article)
+ (gnus-backlog-enter-article
+ group article (current-buffer)))
+ 'article))))
+ ;; It was a pseudo.
+ (t article)))
+
+ ;; Take the article from the original article buffer
+ ;; and place it in the buffer it's supposed to be in.
+ (when (and (get-buffer gnus-article-buffer)
+ (numberp article)
+ (equal (buffer-name (current-buffer))
+ (buffer-name (get-buffer gnus-article-buffer))))
+ (save-excursion
+ (if (get-buffer gnus-original-article-buffer)
+ (set-buffer (get-buffer gnus-original-article-buffer))
+ (set-buffer (get-buffer-create gnus-original-article-buffer))
+ (buffer-disable-undo (current-buffer))
+ (setq major-mode 'gnus-original-article-mode)
+ (setq buffer-read-only t)
+ (gnus-add-current-to-buffer-list))
+ (let (buffer-read-only)
(erase-buffer)
- (gnus-kill-all-overlays)
- (if (gnus-request-article article group (current-buffer))
- (progn
- (and gnus-keep-backlog
- (gnus-backlog-enter-article
- group article (current-buffer)))
- 'article))))
- ;; It was a pseudo.
- (t article)))
-
- ;; Take the article from the original article buffer
- ;; and place it in the buffer it's supposed to be in.
- (setq gnus-original-article (cons group article))
- (when (and (get-buffer gnus-article-buffer)
- (equal (buffer-name (current-buffer))
- (buffer-name (get-buffer gnus-article-buffer))))
- (save-excursion
- (if (get-buffer gnus-original-article-buffer)
- (set-buffer (get-buffer gnus-original-article-buffer))
- (set-buffer (get-buffer-create gnus-original-article-buffer))
- (buffer-disable-undo (current-buffer))
- (setq major-mode 'gnus-original-article-mode)
- (setq buffer-read-only t)
- (gnus-add-current-to-buffer-list))
- (let (buffer-read-only)
- (erase-buffer)
- (insert-buffer-substring gnus-article-buffer))))
+ (insert-buffer-substring gnus-article-buffer))
+ (setq gnus-original-article (cons group article))))
- ;; Update sparse articles.
- (when (memq article gnus-newsgroup-sparse)
- (gnus-summary-update-article article))))
+ ;; Update sparse articles.
+ (when (and do-update-line
+ (or (numberp article)
+ (stringp article)))
+ (let ((buf (current-buffer)))
+ (set-buffer gnus-summary-buffer)
+ (gnus-summary-update-article do-update-line)
+ (gnus-summary-goto-subject do-update-line nil t)
+ (set-window-point (get-buffer-window (current-buffer) t)
+ (point))
+ (set-buffer buf))))))
-(defun gnus-read-header (id)
+(defun gnus-read-header (id &optional header)
"Read the headers of article ID and enter them into the Gnus system."
(let ((group gnus-newsgroup-name)
- (headers gnus-newsgroup-headers)
- header where)
+ (gnus-override-method
+ (and (gnus-news-group-p gnus-newsgroup-name)
+ gnus-refer-article-method))
+ where)
;; First we check to see whether the header in question is already
;; fetched.
(if (stringp id)
;; This is a Message-ID.
- (setq header (gnus-id-to-header id))
+ (setq header (or header (gnus-id-to-header id)))
;; This is an article number.
- (setq header (gnus-summary-article-header id)))
- (if header
+ (setq header (or header (gnus-summary-article-header id))))
+ (if (and header
+ (not (memq (mail-header-number header) gnus-newsgroup-sparse)))
;; We have found the header.
header
;; We have to really fetch the header to this article.
(goto-char (point-max))
(insert ".\n")
(goto-char (point-min))
- (insert "211 "
- (int-to-string
- (cond
- ((numberp id)
- id)
- ((cdr where)
- (cdr where))
- (t
- gnus-reffed-article-number)))
- " Article retrieved.\n"))
+ (insert "211 ")
+ (princ (cond
+ ((numberp id) id)
+ ((cdr where) (cdr where))
+ (header (mail-header-number header))
+ (t gnus-reffed-article-number))
+ (current-buffer))
+ (insert " Article retrieved.\n"))
+ ;(when (and header
+ ; (memq (mail-header-number header) gnus-newsgroup-sparse))
+ ; (setcar (gnus-id-to-thread id) nil))
(if (not (setq header (car (gnus-get-newsgroup-headers))))
- () ; Malformed head.
- (if (and (stringp id)
- (not (string= (gnus-group-real-name group)
- (car where))))
- ;; If we fetched by Message-ID and the article came
- ;; from a different group, we fudge some bogus article
- ;; numbers for this article.
- (mail-header-set-number header gnus-reffed-article-number))
- (decf gnus-reffed-article-number)
- (push header gnus-newsgroup-headers)
- (setq gnus-current-headers header)
- (push (mail-header-number header) gnus-newsgroup-limit)
+ () ; Malformed head.
+ (unless (memq (mail-header-number header) gnus-newsgroup-sparse)
+ (if (and (stringp id)
+ (not (string= (gnus-group-real-name group)
+ (car where))))
+ ;; If we fetched by Message-ID and the article came
+ ;; from a different group, we fudge some bogus article
+ ;; numbers for this article.
+ (mail-header-set-number header gnus-reffed-article-number))
+ (decf gnus-reffed-article-number)
+ (push header gnus-newsgroup-headers)
+ (setq gnus-current-headers header)
+ (push (mail-header-number header) gnus-newsgroup-limit))
header)))))
(defun gnus-article-prepare (article &optional all-headers header)
(setq gnus-current-article article)
(gnus-summary-mark-article article gnus-canceled-mark))
(unless (memq article gnus-newsgroup-sparse)
- (gnus-message
- 1 "No such article (may have expired or been canceled)")
- (ding)
- nil))
+ (gnus-error
+ 1 "No such article (may have expired or been canceled)")))
(if (or (eq result 'pseudo) (eq result 'nneething))
(progn
(save-excursion
(memq article gnus-newsgroup-marked)
(memq article gnus-newsgroup-dormant)
(memq article gnus-newsgroup-unreads)))))
- ;; Hooks for getting information from the article.
- ;; This hook must be called before being narrowed.
- (let (buffer-read-only)
- (run-hooks 'internal-hook)
- (run-hooks 'gnus-article-prepare-hook)
- ;; Decode MIME message.
- (if gnus-show-mime
- (if (or (not gnus-strict-mime)
- (gnus-fetch-field "Mime-Version"))
- (funcall gnus-show-mime-method)
- (funcall gnus-decode-encoded-word-method)))
- ;; Perform the article display hooks.
- (run-hooks 'gnus-article-display-hook))
- ;; Do page break.
- (goto-char (point-min))
- (and gnus-break-pages (gnus-narrow-to-page))
+ (when (or (numberp article)
+ (stringp article))
+ ;; Hooks for getting information from the article.
+ ;; This hook must be called before being narrowed.
+ (let (buffer-read-only)
+ (run-hooks 'internal-hook)
+ (run-hooks 'gnus-article-prepare-hook)
+ ;; Decode MIME message.
+ (if gnus-show-mime
+ (if (or (not gnus-strict-mime)
+ (gnus-fetch-field "Mime-Version"))
+ (funcall gnus-show-mime-method)
+ (funcall gnus-decode-encoded-word-method)))
+ ;; Perform the article display hooks.
+ (run-hooks 'gnus-article-display-hook))
+ ;; Do page break.
+ (goto-char (point-min))
+ (and gnus-break-pages (gnus-narrow-to-page)))
(gnus-set-mode-line 'article)
(gnus-configure-windows 'article)
(goto-char (point-min))
(gnus-article-setup-buffer)
(set-buffer gnus-article-buffer)
(let ((buffer-read-only nil))
- (remove-text-properties (point-min) (point-max)
- gnus-hidden-properties))))
+ (gnus-unhide-text (point-min) (point-max)))))
(defun gnus-article-hide-headers-if-wanted ()
"Hide unwanted headers if `gnus-have-all-headers' is nil.
gnus-inhibit-hiding
(gnus-article-hide-headers)))
+(defsubst gnus-article-header-rank ()
+ "Give the rank of the string HEADER as given by `gnus-sorted-header-list'."
+ (let ((list gnus-sorted-header-list)
+ (i 0))
+ (while list
+ (when (looking-at (car list))
+ (setq list nil))
+ (setq list (cdr list))
+ (incf i))
+ i))
+
(defun gnus-article-hide-headers (&optional arg delete)
"Toggle whether to hide unwanted headers and possibly sort them as well.
If given a negative prefix, always show; if given a positive prefix,
(set-buffer gnus-article-buffer)
(save-restriction
(let ((buffer-read-only nil)
+ (props (nconc (list 'gnus-type 'headers)
+ gnus-hidden-properties))
+ (max (1+ (length gnus-sorted-header-list)))
(ignored (when (not (stringp gnus-visible-headers))
(cond ((stringp gnus-ignored-headers)
gnus-ignored-headers)
((and gnus-visible-headers
(listp gnus-visible-headers))
(mapconcat 'identity gnus-visible-headers "\\|"))))
- want-list beg want-l)
+ want-list beg)
;; First we narrow to just the headers.
(widen)
(goto-char (point-min))
(while (looking-at "From ")
(forward-line 1))
(unless (bobp)
- (add-text-properties
- (point-min) (point)
- (nconc (list 'gnus-type 'headers) gnus-hidden-properties)))
+ (gnus-hide-text (point-min) (point) props))
;; Then treat the rest of the header lines.
(narrow-to-region
(point)
(beginning-of-line)
;; We add the headers we want to keep to a list and delete
;; them from the buffer.
- (if (or (and visible (looking-at visible))
- (and ignored (not (looking-at ignored))))
- (progn
- (push (buffer-substring
- (setq beg (point))
- (progn
- (forward-line 1)
- ;; Be sure to get multi-line headers...
- (re-search-forward "^[^ \t]*:" nil t)
- (beginning-of-line)
- (point)))
- want-list)
- (delete-region beg (point)))
- (forward-line 1)))
- ;; Sort the headers that we want to display.
- (setq want-list (sort want-list 'gnus-article-header-less))
- (goto-char (point-min))
- (while want-list
- (insert (pop want-list)))
- ;; We make the unwanted headers invisible.
- (if delete
- (delete-region (point-min) (point-max))
- ;; Suggested by Sudish Joseph <joseph@cis.ohio-state.edu>.
- (add-text-properties
- (point) (point-max)
- (nconc (list 'gnus-type 'headers)
- gnus-hidden-properties)))))))))
-
-(defsubst gnus-article-header-rank (header)
- "Give the rank of the string HEADER as given by `gnus-sorted-header-list'."
- (let ((list gnus-sorted-header-list)
- (i 0))
- (while list
- (when (string-match (car list) header)
- (setq list nil))
- (setq list (cdr list))
- (incf i))
- i))
-
-(defun gnus-article-header-less (h1 h2)
- "Say whether string H1 is \"less\" than string H2."
- (< (gnus-article-header-rank h1)
- (gnus-article-header-rank h2)))
+ (gnus-put-text-property
+ (point) (1+ (point)) 'message-rank
+ (if (or (and visible (looking-at visible))
+ (and ignored
+ (not (looking-at ignored))))
+ (gnus-article-header-rank)
+ (+ 2 max)))
+ (forward-line 1))
+ (message-sort-headers-1)
+ (when (setq beg (text-property-any
+ (point-min) (point-max) 'message-rank (+ 2 max)))
+ ;; We make the unwanted headers invisible.
+ (if delete
+ (delete-region beg (point-max))
+ ;; Suggested by Sudish Joseph <joseph@cis.ohio-state.edu>.
+ (gnus-hide-text-type beg (point-max) 'headers))
+ ;; Work around XEmacs lossage.
+ (gnus-put-text-property (point-min) beg 'invisible nil))))))))
(defun gnus-article-hide-boring-headers (&optional arg)
"Toggle hiding of headers that aren't very interesting.
((eq elem 'empty)
(while (re-search-forward "^[^:]+:[ \t]\n[^ \t]" nil t)
(forward-line -1)
- (add-text-properties
+ (gnus-hide-text-type
(progn (beginning-of-line) (point))
(progn
(end-of-line)
(if (re-search-forward "^[^ \t]" nil t)
(match-beginning 0)
(point-max)))
- (nconc (list 'gnus-type 'boring-headers)
- gnus-hidden-properties))))
+ 'boring-headers)))
;; Hide boring Newsgroups header.
((eq elem 'newsgroups)
(when (equal (mail-fetch-field "newsgroups")
(when (and
from reply-to
(equal
- (nth 1 (mail-extract-address-components from))
- (nth 1 (mail-extract-address-components reply-to))))
+ (nth 1 (funcall gnus-extract-address-components from))
+ (nth 1 (funcall gnus-extract-address-components
+ reply-to))))
(gnus-article-hide-header "reply-to"))))
((eq elem 'date)
(let ((date (mail-fetch-field "date")))
(save-excursion
(goto-char (point-min))
(when (re-search-forward (concat "^" header ":") nil t)
- (add-text-properties
+ (gnus-hide-text-type
(progn (beginning-of-line) (point))
(progn
(end-of-line)
(if (re-search-forward "^[^ \t]" nil t)
(match-beginning 0)
(point-max)))
- (nconc (list 'gnus-type 'boring-headers)
- gnus-hidden-properties)))))
+ 'boring-headers))))
;; Written by Per Abrahamsen <amanda@iesd.auc.dk>.
(defun gnus-article-treat-overstrike ()
(let ((next (following-char))
(previous (char-after (- (point) 2))))
(cond ((eq next previous)
- (put-text-property (- (point) 2) (point) 'invisible t)
- (put-text-property (point) (1+ (point)) 'face 'bold))
+ (gnus-put-text-property (- (point) 2) (point) 'invisible t)
+ (gnus-put-text-property (point) (1+ (point)) 'face 'bold))
((eq next ?_)
- (put-text-property (1- (point)) (1+ (point)) 'invisible t)
- (put-text-property
+ (gnus-put-text-property (1- (point)) (1+ (point)) 'invisible t)
+ (gnus-put-text-property
(- (point) 2) (1- (point)) 'face 'underline))
((eq previous ?_)
- (put-text-property (- (point) 2) (point) 'invisible t)
- (put-text-property
+ (gnus-put-text-property (- (point) 2) (point) 'invisible t)
+ (gnus-put-text-property
(point) (1+ (point)) 'face 'underline))))))))
(defun gnus-article-word-wrap ()
(interactive)
(save-excursion
(set-buffer gnus-article-buffer)
- (let ((buffer-read-only nil)
- p)
+ (let ((buffer-read-only nil))
(widen)
(goto-char (point-min))
(search-forward "\n\n" nil t)
(process-send-region "gnus-x-face" beg end)
(process-send-eof "gnus-x-face")))))))))
-(defun gnus-headers-decode-quoted-printable ()
+(defalias 'gnus-header-decode-quoted-printable 'gnus-decode-rfc1522)
+(defun gnus-decode-rfc1522 ()
"Hack to remove QP encoding from headers."
(let ((case-fold-search t)
(inhibit-point-motion-hooks t)
+ (buffer-read-only nil)
string)
- (goto-char (point-min))
- (while (re-search-forward "=\\?iso-8859-1\\?q\\?\\([^?\t\n]*\\)\\?=" nil t)
- (setq string (match-string 1))
- (narrow-to-region (match-beginning 0) (match-end 0))
- (delete-region (point-min) (point-max))
- (insert string)
- (gnus-mime-decode-quoted-printable (goto-char (point-min)) (point-max))
- (subst-char-in-region (point-min) (point-max) ?_ ? )
- (widen)
- (goto-char (point-min)))))
+ (save-restriction
+ (narrow-to-region
+ (goto-char (point-min))
+ (or (search-forward "\n\n" nil t) (point-max)))
+
+ (while (re-search-forward
+ "=\\?iso-8859-1\\?q\\?\\([^?\t\n]*\\)\\?=" nil t)
+ (setq string (match-string 1))
+ (narrow-to-region (match-beginning 0) (match-end 0))
+ (delete-region (point-min) (point-max))
+ (insert string)
+ (gnus-mime-decode-quoted-printable (goto-char (point-min)) (point-max))
+ (subst-char-in-region (point-min) (point-max) ?_ ? )
+ (widen)
+ (goto-char (point-min))))))
(defun gnus-article-de-quoted-unreadable (&optional force)
"Do a naive translation of a quoted-printable-encoded article.
(let ((case-fold-search t)
(buffer-read-only nil)
(type (gnus-fetch-field "content-transfer-encoding")))
+ (gnus-decode-rfc1522)
(when (or force
- (and type (string-match "quoted-printable" type)))
- (gnus-headers-decode-quoted-printable)
+ (and type (string-match "quoted-printable" (downcase type))))
(goto-char (point-min))
(search-forward "\n\n" nil 'move)
(gnus-mime-decode-quoted-printable (point) (point-max))))))
(defun gnus-mime-decode-quoted-printable (from to)
"Decode Quoted-Printable in the region between FROM and TO."
+ (interactive "r")
(goto-char from)
(while (search-forward "=" to t)
(cond ((eq (following-char) ?\n)
(delete-char -1)
(delete-char 1))
((looking-at "[0-9A-F][0-9A-F]")
- (delete-char -1)
- (insert (hexl-hex-string-to-integer
- (buffer-substring (point) (+ 2 (point)))))
+ (subst-char-in-region
+ (1- (point)) (point) ?=
+ (hexl-hex-string-to-integer
+ (buffer-substring (point) (+ 2 (point)))))
(delete-char 2))
((looking-at "=")
(delete-char 1))
(goto-char (point-min))
;; Hide the "header".
(and (search-forward "\n-----BEGIN PGP SIGNED MESSAGE-----\n" nil t)
- (add-text-properties (match-beginning 0) (match-end 0) props))
+ (gnus-hide-text (match-beginning 0) (match-end 0) props))
(setq beg (point))
;; Hide the actual signature.
(and (search-forward "\n-----BEGIN PGP SIGNATURE-----\n" nil t)
- (setq end (match-beginning 0))
- (add-text-properties
- (match-beginning 0)
+ (setq end (1+ (match-beginning 0)))
+ (gnus-hide-text
+ end
(if (search-forward "\n-----END PGP SIGNATURE-----\n" nil t)
(match-end 0)
;; Perhaps we shouldn't hide to the end of the buffer
(narrow-to-region beg end)
(goto-char (point-min))
(while (re-search-forward "^- " nil t)
- (add-text-properties (match-beginning 0) (match-end 0) props))
+ (gnus-hide-text (match-beginning 0) (match-end 0) props))
(widen))))))
(defun gnus-article-hide-signature (&optional arg)
(save-restriction
(let ((buffer-read-only nil))
(when (gnus-narrow-to-signature)
- (add-text-properties
- (point-min) (point-max)
- (nconc (list 'gnus-type 'signature)
- gnus-hidden-properties))))))))
+ (gnus-hide-text-type (point-min) (point-max) 'signature)))))))
+
+(defun gnus-article-strip-leading-blank-lines ()
+ "Remove all blank lines from the beginning of the article."
+ (interactive)
+ (save-excursion
+ (set-buffer gnus-article-buffer)
+ (let (buffer-read-only)
+ (goto-char (point-min))
+ (when (search-forward "\n\n" nil t)
+ (while (looking-at "[ \t]$")
+ (gnus-delete-line))))))
(defun gnus-narrow-to-signature ()
"Narrow to the signature."
(defun gnus-article-hidden-text-p (type)
"Say whether the current buffer contains hidden text of type TYPE."
- (let ((pos (text-property-any (point-min) (point-max) 'gnus-type type))
- prop)
+ (let ((pos (text-property-any (point-min) (point-max) 'gnus-type type)))
(when pos
(if (get-text-property pos 'invisible)
'hidden
(setq beg (point))
(forward-char)
(if hide
- (add-text-properties beg (point) gnus-hidden-properties)
- (remove-text-properties beg (point) gnus-hidden-properties))
+ (gnus-hide-text beg (point) gnus-hidden-properties)
+ (gnus-unhide-text beg (point)))
(setq beg (point)))
t)))
(date (and (vectorp header) (mail-header-date header)))
(date-regexp "^Date: \\|^X-Sent: ")
(now (current-time))
- (inhibit-point-motion-hooks t))
+ (inhibit-point-motion-hooks t)
+ bface eface)
(when (and date (not (string= date "")))
(save-excursion
(set-buffer gnus-article-buffer)
(nnheader-narrow-to-headers)
(let ((buffer-read-only nil))
;; Delete any old Date headers.
- (if (zerop (nnheader-remove-header date-regexp t))
- (beginning-of-line)
+ (if (re-search-forward date-regexp nil t)
+ (progn
+ (setq bface (get-text-property (gnus-point-at-bol) 'face)
+ eface (get-text-property (1- (gnus-point-at-eol))
+ 'face))
+ (message-remove-header date-regexp t)
+ (beginning-of-line))
(goto-char (point-max)))
- (insert
- (cond
- ;; Convert to the local timezone. We have to slap a
- ;; `condition-case' round the calls to the timezone
- ;; functions since they aren't particularly resistant to
- ;; buggy dates.
- ((eq type 'local)
- (concat "Date: " (condition-case ()
- (timezone-make-date-arpa-standard date)
- (error date))
- "\n"))
- ;; Convert to Universal Time.
- ((eq type 'ut)
- (concat "Date: "
- (condition-case ()
- (timezone-make-date-arpa-standard date nil "UT")
- (error date))
- "\n"))
- ;; Get the original date from the article.
- ((eq type 'original)
- (concat "Date: " date "\n"))
- ;; Do an X-Sent lapsed format.
- ((eq type 'lapsed)
- ;; If the date is seriously mangled, the timezone
- ;; functions are liable to bug out, so we condition-case
- ;; the entire thing.
- (let* ((real-time
- (condition-case ()
- (gnus-time-minus
- (gnus-encode-date
- (timezone-make-date-arpa-standard
- (current-time-string now)
- (current-time-zone now) "UT"))
- (gnus-encode-date
- (timezone-make-date-arpa-standard
- date nil "UT")))
- (error '(0 0))))
- (real-sec (+ (* (float (car real-time)) 65536)
- (cadr real-time)))
- (sec (abs real-sec))
- num prev)
- (if (zerop sec)
- "X-Sent: Now\n"
- (concat
- "X-Sent: "
- ;; This is a bit convoluted, but basically we go
- ;; through the time units for years, weeks, etc,
- ;; and divide things to see whether that results
- ;; in positive answers.
- (mapconcat
- (lambda (unit)
- (if (zerop (setq num (ffloor (/ sec (cdr unit)))))
- ;; The (remaining) seconds are too few to
- ;; be divided into this time unit.
- ""
- ;; It's big enough, so we output it.
- (setq sec (- sec (* num (cdr unit))))
- (prog1
- (concat (if prev ", " "") (int-to-string
- (floor num))
- " " (symbol-name (car unit))
- (if (> num 1) "s" ""))
- (setq prev t))))
- gnus-article-time-units "")
- ;; If dates are odd, then it might appear like the
- ;; article was sent in the future.
- (if (> real-sec 0)
- " ago\n"
- " in the future\n")))))
- (t
- (error "Unknown conversion type: %s" type)))))
- ;; Do highlighting.
- (when (and highlight (gnus-visual-p 'article-highlight 'highlight))
- (gnus-article-highlight-headers)))))))
+ (insert (gnus-make-date-line date type))
+ ;; Do highlighting.
+ (forward-line -1)
+ (when (and (gnus-visual-p 'article-highlight 'highlight)
+ (looking-at "\\([^:]+\\): *\\(.*\\)$"))
+ (gnus-put-text-property (match-beginning 1) (match-end 1)
+ 'face bface)
+ (gnus-put-text-property (match-beginning 2) (match-end 2)
+ 'face eface))))))))
+
+(defun gnus-make-date-line (date type)
+ "Return a DATE line of TYPE."
+ (cond
+ ;; Convert to the local timezone. We have to slap a
+ ;; `condition-case' round the calls to the timezone
+ ;; functions since they aren't particularly resistant to
+ ;; buggy dates.
+ ((eq type 'local)
+ (concat "Date: " (condition-case ()
+ (timezone-make-date-arpa-standard date)
+ (error date))
+ "\n"))
+ ;; Convert to Universal Time.
+ ((eq type 'ut)
+ (concat "Date: "
+ (condition-case ()
+ (timezone-make-date-arpa-standard date nil "UT")
+ (error date))
+ "\n"))
+ ;; Get the original date from the article.
+ ((eq type 'original)
+ (concat "Date: " date "\n"))
+ ;; Do an X-Sent lapsed format.
+ ((eq type 'lapsed)
+ ;; If the date is seriously mangled, the timezone
+ ;; functions are liable to bug out, so we condition-case
+ ;; the entire thing.
+ (let* ((now (current-time))
+ (real-time
+ (condition-case ()
+ (gnus-time-minus
+ (gnus-encode-date
+ (timezone-make-date-arpa-standard
+ (current-time-string now)
+ (current-time-zone now) "UT"))
+ (gnus-encode-date
+ (timezone-make-date-arpa-standard
+ date nil "UT")))
+ (error '(0 0))))
+ (real-sec (+ (* (float (car real-time)) 65536)
+ (cadr real-time)))
+ (sec (abs real-sec))
+ num prev)
+ (cond
+ ((equal real-time '(0 0))
+ "X-Sent: Unknown\n")
+ ((zerop sec)
+ "X-Sent: Now\n")
+ (t
+ (concat
+ "X-Sent: "
+ ;; This is a bit convoluted, but basically we go
+ ;; through the time units for years, weeks, etc,
+ ;; and divide things to see whether that results
+ ;; in positive answers.
+ (mapconcat
+ (lambda (unit)
+ (if (zerop (setq num (ffloor (/ sec (cdr unit)))))
+ ;; The (remaining) seconds are too few to
+ ;; be divided into this time unit.
+ ""
+ ;; It's big enough, so we output it.
+ (setq sec (- sec (* num (cdr unit))))
+ (prog1
+ (concat (if prev ", " "") (int-to-string
+ (floor num))
+ " " (symbol-name (car unit))
+ (if (> num 1) "s" ""))
+ (setq prev t))))
+ gnus-article-time-units "")
+ ;; If dates are odd, then it might appear like the
+ ;; article was sent in the future.
+ (if (> real-sec 0)
+ " ago\n"
+ " in the future\n"))))))
+ (t
+ (error "Unknown conversion type: %s" type))))
(defun gnus-article-date-local (&optional highlight)
"Convert the current article date to the local timezone."
"Show the next page of the article."
(interactive)
(when (gnus-article-next-page)
- (gnus-article-read-summary-keys nil ?n)))
+ (gnus-article-read-summary-keys nil (gnus-character-to-event ?n))))
(defun gnus-article-goto-prev-page ()
"Show the next page of the article."
(interactive)
- (if (bobp) (gnus-article-read-summary-keys nil ?n)
+ (if (bobp) (gnus-article-read-summary-keys nil (gnus-character-to-event ?n))
(gnus-article-prev-page nil)))
(defun gnus-article-next-page (&optional lines)
"%s (%s) open error: '%s'. Continue? "
(car gnus-select-method) (cadr gnus-select-method)
(gnus-status-message gnus-select-method)))
- (progn
- (gnus-message 1 "Couldn't open server on %s"
- (nth 1 gnus-select-method))
- (ding)
- nil)))))
+ (gnus-error 1 "Couldn't open server on %s"
+ (nth 1 gnus-select-method))))))
(defun gnus-check-group (group)
"Try to make sure that the server where GROUP exists is alive."
(defun gnus-open-server (method)
"Open a connection to METHOD."
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
(let ((elem (assoc method gnus-opened-servers)))
;; If this method was previously denied, we just return nil.
(if (eq (nth 1 elem) 'denied)
(defun gnus-close-server (method)
"Close the connection to METHOD."
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
(funcall (gnus-get-function method 'close-server) (nth 1 method)))
(defun gnus-request-list (method)
"Request the active file from METHOD."
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
(funcall (gnus-get-function method 'request-list) (nth 1 method)))
(defun gnus-request-list-newsgroups (method)
"Request the newsgroups file from METHOD."
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
(funcall (gnus-get-function method 'request-list-newsgroups) (nth 1 method)))
(defun gnus-request-newgroups (date method)
"Request all new groups since DATE from METHOD."
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
(funcall (gnus-get-function method 'request-newgroups)
date (nth 1 method)))
(defun gnus-server-opened (method)
"Check whether a connection to METHOD has been opened."
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
(funcall (gnus-get-function method 'server-opened) (nth 1 method)))
(defun gnus-status-message (method)
(defun gnus-request-group (group &optional dont-check method)
"Request GROUP. If DONT-CHECK, no information is required."
(let ((method (or method (gnus-find-method-for-group group))))
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
(funcall (gnus-get-function method 'request-group)
(gnus-group-real-name group) (nth 1 method) dont-check)))
(defun gnus-retrieve-groups (groups method)
"Request active information on GROUPS from METHOD."
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
(funcall (gnus-get-function method 'retrieve-groups) groups (nth 1 method)))
(defun gnus-request-type (group &optional article)
(defun gnus-request-post (method)
"Post the current buffer using METHOD."
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
(funcall (gnus-get-function method 'request-post) (nth 1 method)))
(defun gnus-request-scan (group method)
(defsubst gnus-request-update-info (info method)
"Request that METHOD update INFO."
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
(when (gnus-check-backend-function 'request-update-info (car method))
(funcall (gnus-get-function method 'request-update-info)
(gnus-group-real-name (gnus-info-group info))
article (gnus-group-real-name group)
(nth 1 method) accept-function last)))
-(defun gnus-request-accept-article (group &optional last method)
+(defun gnus-request-accept-article (group method &optional last)
;; Make sure there's a newline at the end of the article.
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
+ (when (and (not method)
+ (stringp group))
+ (setq method (gnus-find-method-for-group group)))
(goto-char (point-max))
(unless (bolp)
(insert "\n"))
- (let ((func (if (symbolp group) group
- (car (or method (gnus-find-method-for-group group))))))
+ (let ((func (car (or method (gnus-find-method-for-group group)))))
(funcall (intern (format "%s-request-accept-article" func))
(if (stringp group) (gnus-group-real-name group) group)
+ (cadr method)
last)))
(defun gnus-request-replace-article (article group buffer)
article (gnus-group-real-name group) (nth 1 method))))
(defun gnus-request-create-group (group &optional method)
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
(let ((method (or method (gnus-find-method-for-group group))))
(funcall (gnus-get-function method 'request-create-group)
(gnus-group-real-name group) (nth 1 method))))
(defun gnus-method-option-p (method option)
"Return non-nil if select METHOD has OPTION as a parameter."
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
(memq option (assoc (format "%s" (car method))
gnus-valid-select-methods)))
(gnus-server-extend-method group method))
(t
method)))
- (if (equal (cadr method) "")
- method
- (gnus-server-add-address method))))))
+ (cond ((equal (cadr method) "")
+ method)
+ ((null (cadr method))
+ (list (car method) ""))
+ (t
+ (gnus-server-add-address method)))))))
(defun gnus-check-backend-function (func group)
"Check whether GROUP supports function FUNC."
(gnus-check-server gnus-select-method))
(gnus-find-new-newsgroups))
+ ;; We might read in new NoCeM messages here.
+ (when (and gnus-use-nocem
+ (not level)
+ (not dont-connect))
+ (gnus-nocem-scan-groups))
+
;; Find the number of unread articles in each non-dead group.
(let ((gnus-read-active-file (and (not level) gnus-read-active-file)))
(gnus-get-unread-articles level))
(setq hashtb (gnus-make-hashtable 100))
(set-buffer nntp-server-buffer)
;; Enter all the new groups into a hashtable.
- (gnus-active-to-gnus-format method hashtb 'ignore)))
- ;; Now all new groups from `method' are in `hashtb'.
- (mapatoms
- (lambda (group-sym)
- (if (or (null (setq group (symbol-name group-sym)))
- (null (symbol-value group-sym))
- (gnus-gethash group gnus-newsrc-hashtb)
- (member group gnus-zombie-list)
- (member group gnus-killed-list))
- ;; The group is already known.
- ()
- ;; Make this group active.
- (when (symbol-value group-sym)
- (gnus-set-active group (symbol-value group-sym)))
- ;; Check whether we want it or not.
- (let ((do-sub (gnus-matches-options-n group)))
- (cond
- ((eq do-sub 'subscribe)
- (incf groups)
- (gnus-sethash group group gnus-killed-hashtb)
- (funcall gnus-subscribe-options-newsgroup-method group))
- ((eq do-sub 'ignore)
- nil)
- (t
- (incf groups)
- (gnus-sethash group group gnus-killed-hashtb)
- (if gnus-subscribe-hierarchical-interactive
- (push group new-newsgroups)
- (funcall gnus-subscribe-newsgroup-method group)))))))
- hashtb)
+ (gnus-active-to-gnus-format method hashtb 'ignore))
+ ;; Now all new groups from `method' are in `hashtb'.
+ (mapatoms
+ (lambda (group-sym)
+ (if (or (null (setq group (symbol-name group-sym)))
+ (not (boundp group-sym))
+ (null (symbol-value group-sym))
+ (gnus-gethash group gnus-newsrc-hashtb)
+ (member group gnus-zombie-list)
+ (member group gnus-killed-list))
+ ;; The group is already known.
+ ()
+ ;; Make this group active.
+ (when (symbol-value group-sym)
+ (gnus-set-active group (symbol-value group-sym)))
+ ;; Check whether we want it or not.
+ (let ((do-sub (gnus-matches-options-n group)))
+ (cond
+ ((eq do-sub 'subscribe)
+ (incf groups)
+ (gnus-sethash group group gnus-killed-hashtb)
+ (funcall gnus-subscribe-options-newsgroup-method group))
+ ((eq do-sub 'ignore)
+ nil)
+ (t
+ (incf groups)
+ (gnus-sethash group group gnus-killed-hashtb)
+ (if gnus-subscribe-hierarchical-interactive
+ (push group new-newsgroups)
+ (funcall gnus-subscribe-newsgroup-method group)))))))
+ hashtb))
(when new-newsgroups
(gnus-subscribe-hierarchical-interactive new-newsgroups)))
;; Suggested by Per Abrahamsen <amanda@iesd.auc.dk>.
(file-exists-p (concat gnus-startup-file ".eld")))
nil
(gnus-message 6 "First time user; subscribing you to default groups")
- (unless gnus-have-read-active-file
+ (unless (gnus-read-active-file-p)
(gnus-read-active-file))
(setq gnus-newsrc-last-checked-date (current-time-string))
(let ((groups gnus-default-subscribed-newsgroups)
(let ((newsrc (cdr gnus-newsrc-alist))
bogus group entry info)
(gnus-message 5 "Checking bogus newsgroups...")
- (unless gnus-have-read-active-file
+ (unless (gnus-read-active-file-p)
(gnus-read-active-file))
- (when (member gnus-select-method gnus-have-read-active-file)
+ (when (gnus-read-active-file-p)
;; Find all bogus newsgroup that are subscribed.
(while newsrc
(setq info (pop newsrc)
(setcdr killed (delete (car killed) (cdr killed)))
(setq killed (cdr killed)))))
-;; Go though `gnus-newsrc-alist' and compare with `gnus-active-hashtb'
-;; and compute how many unread articles there are in each group.
-(defun gnus-get-unread-articles (&optional level)
- (let* ((newsrc (cdr gnus-newsrc-alist))
- (level (or level gnus-activate-level (1+ gnus-level-subscribed)))
- (foreign-level
- (min
- (cond ((and gnus-activate-foreign-newsgroups
- (not (numberp gnus-activate-foreign-newsgroups)))
- (1+ gnus-level-subscribed))
- ((numberp gnus-activate-foreign-newsgroups)
- gnus-activate-foreign-newsgroups)
- (t 0))
- level))
- info group active method)
- (gnus-message 5 "Checking new news...")
-
- (while newsrc
- (setq active (gnus-active (setq group (gnus-info-group
- (setq info (pop newsrc))))))
-
- ;; Check newsgroups. If the user doesn't want to check them, or
- ;; they can't be checked (for instance, if the news server can't
- ;; be reached) we just set the number of unread articles in this
- ;; newsgroup to t. This means that Gnus thinks that there are
- ;; unread articles, but it has no idea how many.
- (if (and (setq method (gnus-info-method info))
- (not (gnus-server-equal
- gnus-select-method
- (gnus-server-get-method nil method)))
- (not (gnus-secondary-method-p method)))
- ;; These groups are foreign. Check the level.
- (when (<= (gnus-info-level info) foreign-level)
- (setq active (gnus-activate-group group 'scan))
- (gnus-close-group group))
-
- ;; These groups are native or secondary.
- (when (and (<= (gnus-info-level info) level)
- (not gnus-read-active-file))
- (setq active (gnus-activate-group group 'scan))
- (gnus-close-group group)))
-
- (if active
- (gnus-get-unread-articles-in-group info active t)
- ;; The group couldn't be reached, so we nix out the number of
- ;; unread articles and stuff.
- (gnus-set-active group nil)
- (setcar (gnus-gethash group gnus-newsrc-hashtb) t)))
-
- (gnus-message 5 "Checking new news...done")))
-
-;; Create a hash table out of the newsrc alist. The `car's of the
-;; alist elements are used as keys.
-(defun gnus-make-hashtable-from-newsrc-alist ()
- (let ((alist gnus-newsrc-alist)
- (ohashtb gnus-newsrc-hashtb)
- prev)
- (setq gnus-newsrc-hashtb (gnus-make-hashtable (length alist)))
- (setq alist
- (setq prev (setq gnus-newsrc-alist
- (if (equal (caar gnus-newsrc-alist)
- "dummy.group")
- gnus-newsrc-alist
- (cons (list "dummy.group" 0 nil) alist)))))
- (while alist
- (gnus-sethash
- (caar alist)
- (cons (and ohashtb (car (gnus-gethash (caar alist) ohashtb)))
- prev)
- gnus-newsrc-hashtb)
- (setq prev alist
- alist (cdr alist)))))
-
-(defun gnus-make-hashtable-from-killed ()
- "Create a hash table from the killed and zombie lists."
- (let ((lists '(gnus-killed-list gnus-zombie-list))
- list)
- (setq gnus-killed-hashtb
- (gnus-make-hashtable
- (+ (length gnus-killed-list) (length gnus-zombie-list))))
- (while lists
- (setq list (symbol-value (car lists)))
- (setq lists (cdr lists))
- (while list
- (gnus-sethash (car list) (car list) gnus-killed-hashtb)
- (setq list (cdr list))))))
+;; We want to inline a function from gnus-cache, so we cheat here:
+(eval-when-compile
+ (provide 'gnus)
+ (require 'gnus-cache))
(defun gnus-get-unread-articles-in-group (info active &optional update)
(when active
(when (and update
(gnus-request-update-info
info (gnus-find-method-for-group (gnus-info-group info))))
- (gnus-activate-group (gnus-info-group info)))
+ (gnus-activate-group (gnus-info-group info) nil t))
(let* ((range (gnus-info-read info))
- (num 0)
- (marked (gnus-info-marks info)))
+ (num 0))
;; If a cache is present, we may have to alter the active info.
(when (and gnus-use-cache info)
- (gnus-cache-possibly-alter-active (gnus-info-group info) active))
+ (inline (gnus-cache-possibly-alter-active
+ (gnus-info-group info) active)))
;; Modify the list of read articles according to what articles
;; are available; then tally the unread articles and add the
;; number to the group hash table entry.
(setcar (gnus-gethash (gnus-info-group info) gnus-newsrc-hashtb) num))
num)))
-(defun gnus-activate-group (group &optional scan)
+;; Go though `gnus-newsrc-alist' and compare with `gnus-active-hashtb'
+;; and compute how many unread articles there are in each group.
+(defun gnus-get-unread-articles (&optional level)
+ (let* ((newsrc (cdr gnus-newsrc-alist))
+ (level (or level gnus-activate-level (1+ gnus-level-subscribed)))
+ (foreign-level
+ (min
+ (cond ((and gnus-activate-foreign-newsgroups
+ (not (numberp gnus-activate-foreign-newsgroups)))
+ (1+ gnus-level-subscribed))
+ ((numberp gnus-activate-foreign-newsgroups)
+ gnus-activate-foreign-newsgroups)
+ (t 0))
+ level))
+ info group active method)
+ (gnus-message 5 "Checking new news...")
+
+ (while newsrc
+ (setq active (gnus-active (setq group (gnus-info-group
+ (setq info (pop newsrc))))))
+
+ ;; Check newsgroups. If the user doesn't want to check them, or
+ ;; they can't be checked (for instance, if the news server can't
+ ;; be reached) we just set the number of unread articles in this
+ ;; newsgroup to t. This means that Gnus thinks that there are
+ ;; unread articles, but it has no idea how many.
+ (if (and (setq method (gnus-info-method info))
+ (not (gnus-server-equal
+ gnus-select-method
+ (setq method (gnus-server-get-method nil method))))
+ (not (gnus-secondary-method-p method)))
+ ;; These groups are foreign. Check the level.
+ (when (<= (gnus-info-level info) foreign-level)
+ (setq active (gnus-activate-group group 'scan))
+ (unless (inline (gnus-virtual-group-p group))
+ (inline (gnus-close-group group)))
+ (when (fboundp (intern (concat (symbol-name (car method))
+ "-request-update-info")))
+ (inline (gnus-request-update-info info method))))
+ ;; These groups are native or secondary.
+ (when (and (<= (gnus-info-level info) level)
+ (not gnus-read-active-file))
+ (setq active (gnus-activate-group group 'scan))
+ (inline (gnus-close-group group))))
+
+ ;; Get the number of unread articles in the group.
+ (if active
+ (inline (gnus-get-unread-articles-in-group info active))
+ ;; The group couldn't be reached, so we nix out the number of
+ ;; unread articles and stuff.
+ (gnus-set-active group nil)
+ (setcar (gnus-gethash group gnus-newsrc-hashtb) t)))
+
+ (gnus-message 5 "Checking new news...done")))
+
+;; Create a hash table out of the newsrc alist. The `car's of the
+;; alist elements are used as keys.
+(defun gnus-make-hashtable-from-newsrc-alist ()
+ (let ((alist gnus-newsrc-alist)
+ (ohashtb gnus-newsrc-hashtb)
+ prev)
+ (setq gnus-newsrc-hashtb (gnus-make-hashtable (length alist)))
+ (setq alist
+ (setq prev (setq gnus-newsrc-alist
+ (if (equal (caar gnus-newsrc-alist)
+ "dummy.group")
+ gnus-newsrc-alist
+ (cons (list "dummy.group" 0 nil) alist)))))
+ (while alist
+ (gnus-sethash
+ (caar alist)
+ (cons (and ohashtb (car (gnus-gethash (caar alist) ohashtb)))
+ prev)
+ gnus-newsrc-hashtb)
+ (setq prev alist
+ alist (cdr alist)))))
+
+(defun gnus-make-hashtable-from-killed ()
+ "Create a hash table from the killed and zombie lists."
+ (let ((lists '(gnus-killed-list gnus-zombie-list))
+ list)
+ (setq gnus-killed-hashtb
+ (gnus-make-hashtable
+ (+ (length gnus-killed-list) (length gnus-zombie-list))))
+ (while (setq list (pop lists))
+ (setq list (symbol-value list))
+ (while list
+ (gnus-sethash (car list) (pop list) gnus-killed-hashtb)))))
+
+(defun gnus-activate-group (group &optional scan dont-check)
;; Check whether a group has been activated or not.
;; If SCAN, request a scan of that group as well.
(let ((method (gnus-find-method-for-group group))
(gnus-request-scan group method))
t)
(condition-case ()
- (gnus-request-group group)
+ (gnus-request-group group dont-check)
; (error nil)
(quit nil))
(save-excursion
(let* ((active (or gnus-newsgroup-active (gnus-active group)))
(entry (gnus-gethash group gnus-newsrc-hashtb))
(info (nth 2 entry))
- (marked (gnus-info-marks info))
(prev 1)
(unread (sort (copy-sequence unread) '<))
read)
(setq killed (cdr killed)))
(setq lists (cdr lists)))))
+(defun gnus-get-killed-groups ()
+ "Go through the active hashtb and all all unknown groups as killed."
+ ;; First make sure active file has been read.
+ (unless (gnus-read-active-file-p)
+ (let ((gnus-read-active-file t))
+ (gnus-read-active-file)))
+ (or gnus-killed-hashtb (gnus-make-hashtable-from-killed))
+ ;; Go through all newsgroups that are known to Gnus - enlarge kill list.
+ (mapatoms
+ (lambda (sym)
+ (let ((groups 0)
+ (group (symbol-name sym)))
+ (if (or (null group)
+ (gnus-gethash group gnus-killed-hashtb)
+ (gnus-gethash group gnus-newsrc-hashtb))
+ ()
+ (let ((do-sub (gnus-matches-options-n group)))
+ (if (or (eq do-sub 'subscribe) (eq do-sub 'ignore))
+ ()
+ (setq groups (1+ groups))
+ (setq gnus-killed-list
+ (cons group gnus-killed-list))
+ (gnus-sethash group group gnus-killed-hashtb))))))
+ gnus-active-hashtb))
+
;; Get the active file(s) from the backend(s).
(defun gnus-read-active-file ()
(gnus-group-set-mode-line)
((and (eq gnus-read-active-file 'some)
(gnus-check-backend-function 'retrieve-groups (car method)))
(let ((newsrc (cdr gnus-newsrc-alist))
- (gmethod (if (stringp method)
- (gnus-server-get-method nil method)
- method))
+ (gmethod (gnus-server-get-method nil method))
groups info)
(while (setq info (pop newsrc))
(when (gnus-server-equal
(setq list-type (gnus-retrieve-groups groups method))
(cond
((not list-type)
- (gnus-message
- 1 "Cannot read partial active file from %s server."
- (car method))
- (ding)
- (sit-for 2))
+ (gnus-error
+ 1.2 "Cannot read partial active file from %s server."
+ (car method)))
((eq list-type 'active)
(gnus-active-to-gnus-format method gnus-active-hashtb))
(t
(gnus-groups-to-gnus-format method gnus-active-hashtb))))))
(t
(if (not (gnus-request-list method))
- (progn
- (unless (equal method gnus-message-archive-method)
- (gnus-message 1 "Cannot read active file from %s server."
- (car method))
- (ding)))
- (gnus-active-to-gnus-format method)
+ (unless (equal method gnus-message-archive-method)
+ (gnus-error 1 "Cannot read active file from %s server."
+ (car method)))
+ (gnus-active-to-gnus-format method gnus-active-hashtb)
;; We mark this active file as read.
(push method gnus-have-read-active-file)
(gnus-message 5 "%sdone" mesg))))))
(if (equal method gnus-select-method)
(gnus-make-hashtable
(count-lines (point-min) (point-max)))
- (gnus-make-hashtable 4096))))))
- (flag-hashtb (gnus-make-hashtable 60)))
+ (gnus-make-hashtable 4096)))))))
;; Delete unnecessary lines.
(goto-char (point-min))
(while (search-forward "\nto." nil t)
(gnus-message 5 "Reading %s...done" newsrc-file)))
;; Read any slave files.
- (or gnus-slave
- (gnus-master-read-slave-newsrc)))))
+ (unless gnus-slave
+ (gnus-master-read-slave-newsrc))
+
+ ;; Convert old to new.
+ (gnus-convert-old-newsrc))))
+
+(defun gnus-continuum-version (version)
+ "Return VERSION as a floating point number."
+ (when (string-match "^\\([^ ]+\\)? ?Gnus v?\\([0-9.]+\\)$" version)
+ (let* ((alpha (and (match-beginning 1) (match-string 1 version)))
+ (number (match-string 2 version))
+ major minor least)
+ (string-match "\\([0-9]\\)\\.\\([0-9]+\\)\\.?\\([0-9]+\\)?" number)
+ (setq major (string-to-number (match-string 1 number)))
+ (setq minor (string-to-number (match-string 2 number)))
+ (setq least (if (match-beginning 3)
+ (string-to-number (match-string 3 number))
+ 0))
+ (string-to-number
+ (if (zerop major)
+ (format "%s00%02d%02d"
+ (cond
+ ((string= alpha "(ding)") "4.99")
+ ((string= alpha "September") "5.01")
+ ((string= alpha "Red") "5.03"))
+ minor least)
+ (format "%d.%02d%20d" major minor least))))))
+
+(defun gnus-convert-old-newsrc ()
+ "Convert old newsrc into the new format, if needed."
+ (let ((fcv (and gnus-newsrc-file-version
+ (gnus-continuum-version gnus-newsrc-file-version))))
+ (cond
+ ;; No .newsrc.eld file was loaded.
+ ((null fcv) nil)
+ ;; Gnus 5 .newsrc.eld was loaded.
+ ((< fcv (gnus-continuum-version "September Gnus v0.1"))
+ (gnus-convert-old-ticks)))))
+
+(defun gnus-convert-old-ticks ()
+ (let ((newsrc (cdr gnus-newsrc-alist))
+ marks info dormant ticked)
+ (while (setq info (pop newsrc))
+ (when (setq marks (gnus-info-marks info))
+ (setq dormant (cdr (assq 'dormant marks))
+ ticked (cdr (assq 'tick marks)))
+ (when (or dormant ticked)
+ (gnus-info-set-read
+ info
+ (gnus-add-to-range
+ (gnus-info-read info)
+ (nconc (gnus-uncompress-range dormant)
+ (gnus-uncompress-range ticked)))))))))
(defun gnus-read-newsrc-el-file (file)
(let ((ding-file (concat file "d")))
(condition-case nil
(load ding-file t t t)
(error
- (gnus-message 1 "Error in %s" ding-file)
- (ding)))
+ (gnus-error 1 "Error in %s" ding-file)))
(when gnus-newsrc-assoc
(setq gnus-newsrc-alist gnus-newsrc-assoc)))
(gnus-make-hashtable-from-newsrc-alist)
(progn
;; The line was buggy.
(setq group nil)
- (gnus-message 3 "Mangled line: %s"
- (buffer-substring (gnus-point-at-bol)
- (gnus-point-at-eol)))
- (ding)
- (sit-for 1)))
+ (gnus-error 3.1 "Mangled line: %s"
+ (buffer-substring (gnus-point-at-bol)
+ (gnus-point-at-eol)))))
nil))
;; Skip past ", ". Spaces are illegal in these ranges, but
;; we allow them, because it's a common mistake to put a
(kill-buffer (current-buffer))
(gnus-message
5 "Saving %s.eld...done" gnus-current-startup-file))
- (gnus-dribble-delete-file)))))
+ (gnus-dribble-delete-file)
+ (gnus-group-set-mode-line)))))
(defun gnus-gnus-to-quick-newsrc-format ()
"Insert Gnus variables such as gnus-newsrc-alist in lisp format."
(while variables
(when (and (boundp (setq variable (pop variables)))
(symbol-value variable))
- (insert "(setq " (symbol-name variable) " '"
- (prin1-to-string (symbol-value variable)) ")\n")))))
+ (insert "(setq " (symbol-name variable) " '")
+ (prin1 (symbol-value variable) (current-buffer))
+ (insert ")\n")))))
(defun gnus-gnus-to-newsrc-format ()
;; Generate and save the .newsrc file.
- (let ((newsrc (cdr gnus-newsrc-alist))
- info ranges range)
- (save-excursion
- (set-buffer (create-file-buffer gnus-current-startup-file))
+ (save-excursion
+ (set-buffer (create-file-buffer gnus-current-startup-file))
+ (let ((newsrc (cdr gnus-newsrc-alist))
+ (standard-output (current-buffer))
+ info ranges range method)
(setq buffer-file-name gnus-current-startup-file)
(buffer-disable-undo (current-buffer))
(erase-buffer)
;; Write subscribed and unsubscribed.
(while (setq info (pop newsrc))
;; Don't write foreign groups to .newsrc.
- (when (gnus-server-equal (gnus-info-method info) gnus-select-method)
+ (when (or (null (setq method (gnus-info-method info)))
+ (equal method "native")
+ (gnus-server-equal method gnus-select-method))
(insert (gnus-info-group info)
(if (> (gnus-info-level info) gnus-level-subscribed)
"!" ":"))
(insert " ")
(if (not (listp (cdr ranges)))
(if (= (car ranges) (cdr ranges))
- (insert (int-to-string (car ranges)))
- (insert (int-to-string (car ranges)) "-"
- (int-to-string (cdr ranges))))
- (while ranges
- (setq range (car ranges)
- ranges (cdr ranges))
+ (princ (car ranges))
+ (princ (car ranges))
+ (insert "-")
+ (princ (cdr ranges)))
+ (while (setq range (pop ranges))
(if (or (atom range) (= (car range) (cdr range)))
- (insert (int-to-string
- (or (and (atom range) range)
- (car range))))
- (insert (int-to-string (car range)) "-"
- (int-to-string (cdr range))))
+ (princ (or (and (atom range) range) (car range)))
+ (princ (car range))
+ (insert "-")
+ (princ (cdr range)))
(if ranges (insert ",")))))
(insert "\n")))
(make-local-variable 'version-control)
(eval-buffer (current-buffer))
t)
(error
- (gnus-message 3 "Possible error in %s" file)
- (ding)
- (sit-for 2)
+ (gnus-error 3.2 "Possible error in %s" file)
nil))
(or gnus-slave ; Slaves shouldn't delete these files.
(condition-case ()
(unless gnus-backlog-hashtb
(setq gnus-backlog-hashtb (make-vector 1023 0))))
+(gnus-add-shutdown 'gnus-backlog-shutdown 'gnus)
+
(defun gnus-backlog-shutdown ()
"Clear all backlog variables and buffers."
(when (get-buffer gnus-backlog-buffer)
(setq b (point))
(insert-buffer-substring buffer)
;; Tag the beginning of the article with the ident.
- (put-text-property b (1+ b) 'gnus-backlog ident))))))
+ (gnus-put-text-property b (1+ b) 'gnus-backlog ident))))))
(defun gnus-backlog-remove-oldest-article ()
(save-excursion
(point) (next-single-property-change
(1+ (point)) 'gnus-backlog nil (point-max)))))))
+(defun gnus-backlog-remove-article (group number)
+ "Remove article NUMBER in GROUP from the backlog."
+ (when (numberp number)
+ (gnus-backlog-setup)
+ (let ((ident (intern (concat group ":" (int-to-string number))
+ gnus-backlog-hashtb))
+ beg end)
+ (when (memq ident gnus-backlog-articles)
+ ;; It was in the backlog.
+ (save-excursion
+ (set-buffer (gnus-backlog-buffer))
+ (let (buffer-read-only)
+ (when (setq beg (text-property-any
+ (point-min) (point-max) 'gnus-backlog
+ ident))
+ ;; Find the end (i. e., the beginning of the next article).
+ (setq end
+ (next-single-property-change
+ (1+ beg) 'gnus-backlog (current-buffer) (point-max)))
+ (delete-region beg end)
+ ;; Return success.
+ t)))))))
+
(defun gnus-backlog-request-article (group number buffer)
(when (numberp number)
(gnus-backlog-setup)