*** pub/sgnus/lisp/gnus-cache.el Sun Dec 10 12:08:27 1995 --- sgnus/lisp/gnus-cache.el Tue Dec 12 17:37:42 1995 *************** *** 52,58 **** ;;; Internal variables. (defvar gnus-cache-buffer nil) - (defvar gnus-group-alist nil) (defvar gnus-cache-active-hashtb nil) (defvar gnus-cache-active-altered nil) --- 52,57 ---- *************** *** 67,72 **** --- 66,72 ---- (defun gnus-cache-close () "Shut down the cache." (gnus-cache-write-active) + (gnus-cache-save-buffers) (setq gnus-cache-active-hashtb nil)) (defun gnus-cache-save-buffers () *************** *** 102,166 **** (setq gnus-cache-buffer nil)))) (defun gnus-cache-possibly-enter-article ! (group article headers ticked dormant unread) ! (let ((number (mail-header-number headers)) ! file dir) ! (if (or (not (vectorp headers)) ; This might be a dummy article. ! (< number 0) ; Reffed article. ! (and gnus-uncacheable-groups ! (string-match gnus-uncacheable-groups group)) ! (not (gnus-cache-member-of-class ! gnus-cache-enter-articles ticked dormant unread)) ! (file-exists-p (setq file (gnus-cache-file-name group article)))) ! () ; Do nothing. ! ;; Possibly create the cache directory. ! (or (file-exists-p (setq dir (file-name-directory file))) ! (gnus-make-directory dir)) ! ;; Save the article in the cache. ! (if (file-exists-p file) ! t ; The article already is saved. ! (let ((gnus-use-cache nil)) ! (gnus-summary-select-article)) ! (save-excursion ! (set-buffer gnus-original-article-buffer) ! (save-restriction ! (widen) ! (write-region (point-min) (point-max) file nil 'quiet)) ! (gnus-cache-change-buffer group) ! (set-buffer (cdr gnus-cache-buffer)) ! (goto-char (point-max)) ! (forward-line -1) ! (while (condition-case () ! (and (not (bobp)) ! (> (read (current-buffer)) number)) ! (error ! ;; The line was malformed, so we just remove it!! ! (gnus-delete-line) ! t)) ! (forward-line -1)) ! (if (bobp) ! (if (not (eobp)) ! (progn ! (beginning-of-line) ! (if (< (read (current-buffer)) number) ! (forward-line 1))) ! (beginning-of-line)) ! (forward-line 1)) ! (beginning-of-line) ! ;; [number subject from date id references chars lines xref] ! (insert (format "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n" ! (mail-header-number headers) ! (mail-header-subject headers) ! (mail-header-from headers) ! (mail-header-date headers) ! (mail-header-id headers) ! (or (mail-header-references headers) "") ! (or (mail-header-chars headers) "") ! (or (mail-header-lines headers) "") ! (or (mail-header-xref headers) "")))) ! ;; Update the active info. ! (gnus-cache-update-active group number) ! t)))) (defun gnus-cache-enter-remove-article (article) "Mark ARTICLE for later possible removal." --- 102,169 ---- (setq gnus-cache-buffer nil)))) (defun gnus-cache-possibly-enter-article ! (group article headers ticked dormant unread &optional force) ! (when (or force (not (eq gnus-use-cache 'passive))) ! (let ((number (mail-header-number headers)) ! file dir) ! (when (and (vectorp headers) ; This might be a dummy article. ! (> number 0) ; Reffed article. ! (or (not gnus-uncacheable-groups) ! (not (string-match gnus-uncacheable-groups group))) ! (or force ! (gnus-cache-member-of-class ! gnus-cache-enter-articles ticked dormant unread)) ! (not (file-exists-p (setq file (gnus-cache-file-name ! group article))))) ! ;; Possibly create the cache directory. ! (or (file-exists-p (setq dir (file-name-directory file))) ! (gnus-make-directory dir)) ! ;; Save the article in the cache. ! (if (file-exists-p file) ! t ; The article already is saved. ! (let ((gnus-use-cache nil)) ! (gnus-summary-select-article)) ! (save-excursion ! (set-buffer gnus-original-article-buffer) ! (save-restriction ! (widen) ! (write-region (point-min) (point-max) file nil 'quiet)) ! (gnus-cache-change-buffer group) ! (set-buffer (cdr gnus-cache-buffer)) ! (goto-char (point-max)) ! (forward-line -1) ! (while (condition-case () ! (and (not (bobp)) ! (> (read (current-buffer)) number)) ! (error ! ;; The line was malformed, so we just remove it!! ! (gnus-delete-line) ! t)) ! (forward-line -1)) ! (if (bobp) ! (if (not (eobp)) ! (progn ! (beginning-of-line) ! (if (< (read (current-buffer)) number) ! (forward-line 1))) ! (beginning-of-line)) ! (forward-line 1)) ! (beginning-of-line) ! ;; [number subject from date id references chars lines xref] ! (insert (format "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n" ! (mail-header-number headers) ! (mail-header-subject headers) ! (mail-header-from headers) ! (mail-header-date headers) ! (mail-header-id headers) ! (or (mail-header-references headers) "") ! (or (mail-header-chars headers) "") ! (or (mail-header-lines headers) "") ! (or (mail-header-xref headers) "")))) ! ;; Update the active info. ! (gnus-cache-update-active group number) ! (push number gnus-newsgroup-cached) ! t))))) (defun gnus-cache-enter-remove-article (article) "Mark ARTICLE for later possible removal." *************** *** 169,190 **** (defun gnus-cache-possibly-remove-articles () "Possibly remove some of the removable articles." ! (let ((articles gnus-cache-removeable-articles) ! (cache-articles (gnus-cache-articles-in-group gnus-newsgroup-name)) ! article) ! (gnus-cache-change-buffer gnus-newsgroup-name) ! (while articles ! (if (memq (setq article (pop articles)) cache-articles) ! ;; The article was in the cache, so we see whether we are ! ;; supposed to remove it from the cache. ! (gnus-cache-possibly-remove-article ! article (memq article gnus-newsgroup-marked) ! (memq article gnus-newsgroup-dormant) ! (or (memq article gnus-newsgroup-unreads) ! (memq article gnus-newsgroup-unselected)))))) ! ;; The overview file might have been modified, save it ! ;; safe because we're only called at group exit anyway ! (gnus-cache-save-buffers)) (defun gnus-cache-request-article (article group) "Retrieve ARTICLE in GROUP from the cache." --- 172,194 ---- (defun gnus-cache-possibly-remove-articles () "Possibly remove some of the removable articles." ! (unless (eq gnus-use-cache 'passive) ! (let ((articles gnus-cache-removeable-articles) ! (cache-articles gnus-newsgroup-cached) ! article) ! (gnus-cache-change-buffer gnus-newsgroup-name) ! (while articles ! (if (memq (setq article (pop articles)) cache-articles) ! ;; The article was in the cache, so we see whether we are ! ;; supposed to remove it from the cache. ! (gnus-cache-possibly-remove-article ! article (memq article gnus-newsgroup-marked) ! (memq article gnus-newsgroup-dormant) ! (or (memq article gnus-newsgroup-unreads) ! (memq article gnus-newsgroup-unselected)))))) ! ;; The overview file might have been modified, save it ! ;; safe because we're only called at group exit anyway. ! (gnus-cache-save-buffers))) (defun gnus-cache-request-article (article group) "Retrieve ARTICLE in GROUP from the cache." *************** *** 206,221 **** (> (cdr cache-active) (cdr active)) (setcdr active (cdr cache-active))))) ! (defun gnus-cache-retrieve-headers (articles group) "Retrieve the headers for ARTICLES in GROUP." ! (let* ((cached (gnus-cache-articles-in-group group)) (articles (gnus-sorted-complement articles cached)) (cache-file (gnus-cache-file-name group ".overview")) type) ;; We first retrieve all the headers that we don't have in ;; the cache. (let ((gnus-use-cache nil)) ! (setq type (and articles (gnus-retrieve-headers articles group)))) (gnus-cache-save-buffers) ;; Then we insert the cached headers. (save-excursion --- 210,227 ---- (> (cdr cache-active) (cdr active)) (setcdr active (cdr cache-active))))) ! (defun gnus-cache-retrieve-headers (articles group &optional fetch-old) "Retrieve the headers for ARTICLES in GROUP." ! (let* ((cached ! (setq gnus-newsgroup-cached (gnus-cache-articles-in-group group))) (articles (gnus-sorted-complement articles cached)) (cache-file (gnus-cache-file-name group ".overview")) type) ;; We first retrieve all the headers that we don't have in ;; the cache. (let ((gnus-use-cache nil)) ! (setq type (and articles ! (gnus-retrieve-headers articles group fetch-old)))) (gnus-cache-save-buffers) ;; Then we insert the cached headers. (save-excursion *************** *** 240,245 **** --- 246,290 ---- (gnus-cache-braid-heads group cached) type))))) + (defun gnus-cache-enter-article (n) + "Enter the next N articles into the cache. + If not given a prefix, use the process marked articles instead. + Returns the list of articles entered." + (interactive "P") + (gnus-set-global-variables) + (let ((articles (gnus-summary-work-articles n)) + article out) + (while articles + (setq article (pop articles)) + (when (gnus-cache-possibly-enter-article + gnus-newsgroup-name article (gnus-summary-article-header article) + nil nil nil t) + (push article out)) + (gnus-summary-remove-process-mark article) + (gnus-summary-update-secondary-mark article)) + (gnus-summary-position-point) + (nreverse out))) + + (defun gnus-cache-remove-article (n) + "Remove the next N articles from the cache. + If not given a prefix, use the process marked articles instead. + Returns the list of articles removed." + (interactive "P") + (gnus-set-global-variables) + (let ((articles (gnus-summary-work-articles n)) + article out) + (while articles + (setq article (pop articles)) + (when (gnus-cache-possibly-remove-article article nil nil nil t) + (push article out)) + (gnus-summary-remove-process-mark article) + (gnus-summary-update-secondary-mark article)) + (gnus-summary-position-point) + (nreverse out))) + + (defun gnus-cached-article-p (article) + "Say whether ARTICLE is cached in the current group." + (memq article gnus-newsgroup-cached)) ;;; Internal functions. *************** *** 285,296 **** (if (stringp article) article (int-to-string article)))) (defun gnus-cache-possibly-remove-article ! (article ticked dormant unread) (let ((file (gnus-cache-file-name gnus-newsgroup-name article))) ! (if (or (not (file-exists-p file)) ! (not (gnus-cache-member-of-class ! gnus-cache-remove-articles ticked dormant unread))) ! nil (save-excursion (delete-file file) (set-buffer (cdr gnus-cache-buffer)) --- 330,342 ---- (if (stringp article) article (int-to-string article)))) (defun gnus-cache-possibly-remove-article ! (article ticked dormant unread &optional force) ! "Possibly remove ARTICLE from the cache." (let ((file (gnus-cache-file-name gnus-newsgroup-name article))) ! (when (and (file-exists-p file) ! (or force ! (gnus-cache-member-of-class ! gnus-cache-remove-articles ticked dormant unread))) (save-excursion (delete-file file) (set-buffer (cdr gnus-cache-buffer)) *************** *** 299,318 **** (search-forward (concat "\n" (int-to-string article) "\t") (point-max) t)) (delete-region (progn (beginning-of-line) (point)) ! (progn (forward-line 1) (point)))))))) (defun gnus-cache-articles-in-group (group) (let ((dir (file-name-directory (gnus-cache-file-name group 1))) articles) ! (if (not (file-exists-p dir)) ! nil ! (setq articles (directory-files dir nil "^[0-9]+$" t)) ! (if (not articles) ! nil ! (sort (mapcar (function (lambda (name) ! (string-to-int name))) ! articles) ! '<))))) (defun gnus-cache-braid-nov (group cached) (let ((cache-buf (get-buffer-create " *gnus-cache*")) --- 345,363 ---- (search-forward (concat "\n" (int-to-string article) "\t") (point-max) t)) (delete-region (progn (beginning-of-line) (point)) ! (progn (forward-line 1) (point))))) ! (setq gnus-newsgroup-cached ! (delq article gnus-newsgroup-cached)) ! t))) (defun gnus-cache-articles-in-group (group) + "Return a sorted list of cached articles in GROUP." (let ((dir (file-name-directory (gnus-cache-file-name group 1))) articles) ! (when (file-exists-p dir) ! (sort (mapcar (lambda (name) (string-to-int name)) ! (directory-files dir nil "^[0-9]+$" t)) ! '<)))) (defun gnus-cache-braid-nov (group cached) (let ((cache-buf (get-buffer-create " *gnus-cache*")) *************** *** 420,427 **** (mapatoms (lambda (sym) (when (and sym (boundp sym)) ! (insert (symbol-name sym) " " (cdr (symbol-value sym)) ! " " (car (symbol-value sym)) " y\n"))) gnus-cache-active-hashtb) (write-region (point-min) (point-max) gnus-cache-active-file nil 'silent)) --- 465,473 ---- (mapatoms (lambda (sym) (when (and sym (boundp sym)) ! (insert (format "%s %d %d y\n" ! (symbol-name sym) (cdr (symbol-value sym)) ! (car (symbol-value sym)))))) gnus-cache-active-hashtb) (write-region (point-min) (point-max) gnus-cache-active-file nil 'silent)) *************** *** 445,450 **** --- 491,497 ---- ;;;###autoload (defun gnus-cache-generate-active (&optional directory) "Generate the cache active file." + (interactive) (let* ((top (null directory)) (directory (or directory (expand-file-name gnus-cache-directory))) (files (directory-files directory 'full)) *************** *** 457,462 **** --- 504,510 ---- ?/ ?.))) nums alphs) (when top + (gnus-message 5 "Generating the cache active file...") (setq gnus-cache-active-hashtb (gnus-make-hashtable 123))) ;; Separate articles from all other files and directories. (while files *************** *** 471,483 **** ;; Go through all the other files. (while alphs (when (and (file-directory-p (car alphs)) ! (not (string-match "^\\.\\.?$" (file-name-nondirectory (car alphs))))) ;; We descend directories. (gnus-cache-generate-active (car alphs))) (setq alphs (cdr alphs))) ;; Write the new active file. (when top ! (gnus-cache-write-active t)))) (provide 'gnus-cache) --- 519,542 ---- ;; Go through all the other files. (while alphs (when (and (file-directory-p (car alphs)) ! (not (string-match "^\\.\\.?$" ! (file-name-nondirectory (car alphs))))) ;; We descend directories. (gnus-cache-generate-active (car alphs))) (setq alphs (cdr alphs))) ;; Write the new active file. (when top ! (gnus-cache-write-active t) ! (gnus-message 5 "Generating the cache active file...done")))) ! ! ;;;###autoload ! (defun gnus-cache-generate-nov-databases (dir) ! "Generate NOV files recursively starting in DIR." ! (interactive (list gnus-cache-directory)) ! (gnus-cache-close) ! (require 'nnml) ! (let ((nnml-generate-active-function 'identity)) ! (nnml-generate-nov-databases dir))) (provide 'gnus-cache) *** pub/sgnus/lisp/gnus-cus.el Sun Dec 10 12:08:27 1995 --- sgnus/lisp/gnus-cus.el Mon Dec 11 14:33:34 1995 *************** *** 65,71 **** (summary-highlight article-highlight summary-menu group-menu article-menu ! browse-menu server-menu)) (name . gnus-visual) (type . toggle)) ((tag . "WWW Browser") --- 65,72 ---- (summary-highlight article-highlight summary-menu group-menu article-menu ! browse-menu server-menu ! page-marker)) (name . gnus-visual) (type . toggle)) ((tag . "WWW Browser") *** pub/sgnus/lisp/gnus-mh.el Sun Dec 10 12:08:28 1995 --- sgnus/lisp/gnus-mh.el Tue Dec 12 11:05:49 1995 *************** *** 64,81 **** t)))) (errbuf (get-buffer-create " *Gnus rcvstore*")) ;; Find the rcvstore program. ! (rcvstore ! (expand-file-name ! (mh-search-path ! (if mh-lib (cons mh-lib exec-path) exec-path) ! "rcvstore")))) (gnus-eval-in-buffer-window gnus-original-article-buffer (save-restriction (widen) (unwind-protect (call-process-region ! (point-min) (point-max) rcvstore nil errbuf nil folder) (set-buffer errbuf) (if (zerop (buffer-size)) (message "Article saved in folder: %s" folder) --- 64,77 ---- t)))) (errbuf (get-buffer-create " *Gnus rcvstore*")) ;; Find the rcvstore program. ! (exec-path (if mh-lib (cons mh-lib exec-path) exec-path))) (gnus-eval-in-buffer-window gnus-original-article-buffer (save-restriction (widen) (unwind-protect (call-process-region ! (point-min) (point-max) "rcvstore" nil errbuf nil folder) (set-buffer errbuf) (if (zerop (buffer-size)) (message "Article saved in folder: %s" folder) *** pub/sgnus/lisp/gnus-msg.el Sun Dec 10 12:08:29 1995 --- sgnus/lisp/gnus-msg.el Wed Dec 13 18:20:52 1995 *************** *** 530,536 **** "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) 'post)))) (defun gnus-inews-news (&optional use-group-method) "Send a news message. --- 530,536 ---- "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)))) (defun gnus-inews-news (&optional use-group-method) "Send a news message. *************** *** 1553,1559 **** (interactive "sResend message to: ") (gnus-summary-select-article) (save-excursion ! (let (resent) ;; We first set up a normal mail buffer. (nnheader-set-temp-buffer " *Gnus resend*") ;; This code from sendmail.el --- 1553,1559 ---- (interactive "sResend message to: ") (gnus-summary-select-article) (save-excursion ! (let (resent beg) ;; We first set up a normal mail buffer. (nnheader-set-temp-buffer " *Gnus resend*") ;; This code from sendmail.el *************** *** 1565,1572 **** (insert mail-header-separator "\n") ;; Insert our usual headers. (gnus-inews-narrow-to-headers) ! (let ((headers '(From Date To))) ! (gnus-inews-insert-headers headers)) (goto-char (point-min)) ;; Rename them all to "Resent-*". (while (re-search-forward "^[A-Za-z]" nil t) --- 1565,1571 ---- (insert mail-header-separator "\n") ;; Insert our usual headers. (gnus-inews-narrow-to-headers) ! (gnus-inews-insert-headers '(From Date To)) (goto-char (point-min)) ;; Rename them all to "Resent-*". (while (re-search-forward "^[A-Za-z]" nil t) *************** *** 1575,1586 **** --- 1574,1590 ---- (widen) (forward-line) (delete-region (point) (point-max)) + (setq beg (point)) ;; Insert the message to be resent. (insert-buffer-substring gnus-original-article-buffer) (goto-char (point-min)) (search-forward "\n\n") (forward-char -1) (insert mail-header-separator) + ;; Rename all old ("Also-")Resent headers. + (while (re-search-backward "^\\(Also-\\)?Resent-" beg t) + (beginning-of-line) + (insert "Also-")) ;; Send it. (mail-send) (kill-buffer (current-buffer))))) *************** *** 1628,1633 **** --- 1632,1638 ---- (pop-to-buffer gnus-mail-buffer) (erase-buffer) (gnus-mail-setup 'new to subject) + (gnus-inews-insert-gcc) (run-hooks 'gnus-mail-hook))) (defun gnus-mail-reply (&optional yank to-address followup) *************** *** 1739,1744 **** --- 1744,1750 ---- (setq gnus-in-reply-to message-of) (auto-save-mode auto-save-default) + (gnus-inews-insert-gcc) (if (and follow-to (listp follow-to)) (progn *************** *** 1821,1826 **** --- 1827,1833 ---- (insert "\n\n") (gnus-inews-insert-bfcc) + (gnus-inews-insert-gcc) (gnus-inews-insert-signature) (and gnus-post-prepare-function (gnus-functionp gnus-post-prepare-function) *************** *** 1981,1987 **** (insert to)))) (gnus-inews-insert-bfcc) ! ;; Now the headers should be ok, so we do the yanking. (goto-char (point-min)) (re-search-forward --- 1988,1995 ---- (insert to)))) (gnus-inews-insert-bfcc) ! (gnus-inews-insert-gcc) ! ;; Now the headers should be ok, so we do the yanking. (goto-char (point-min)) (re-search-forward *************** *** 2449,2465 **** (insert gnus-author-copy)))) (defun gnus-inews-insert-gcc () ! (let* ((group gnus-outgoing-message-group) ! (gcc (cond ! ((gnus-functionp group) ! (funcall group)) ! ((or (stringp group) (list group)) ! group)))) ! (when gcc ! (insert "Gcc: " ! (if (stringp group) group ! (mapconcat 'identity group " ")) ! "\n")))) ;;; Handling rejected (and postponed) news. --- 2457,2476 ---- (insert gnus-author-copy)))) (defun gnus-inews-insert-gcc () ! (save-excursion ! (save-restriction ! (gnus-inews-narrow-to-headers) ! (let* ((group gnus-outgoing-message-group) ! (gcc (cond ! ((gnus-functionp group) ! (funcall group)) ! ((or (stringp group) (list group)) ! group)))) ! (when gcc ! (insert "Gcc: " ! (if (stringp group) group ! (mapconcat 'identity group " ")) ! "\n")))))) ;;; Handling rejected (and postponed) news. *** pub/sgnus/lisp/gnus-score.el Sun Dec 10 12:08:30 1995 --- sgnus/lisp/gnus-score.el Wed Dec 13 18:21:22 1995 *************** *** 693,698 **** --- 693,701 ---- (exclude-files (gnus-score-get 'exclude-files alist)) (orphan (car (gnus-score-get 'orphan alist))) (adapt (gnus-score-get 'adapt alist)) + (thread-mark-and-expunge + (car (gnus-score-get 'thread-mark-and-expunge alist))) + (adapt-file (car (gnus-score-get 'adapt-file))) (local (gnus-score-get 'local alist)) (eval (car (gnus-score-get 'eval alist)))) ;; We do not respect eval and files atoms from global score *************** *** 701,707 **** (setq lists (apply 'append lists (mapcar (lambda (file) (gnus-score-load-file file)) ! files)))) (and eval (not global) (eval eval)) ;; We then expand any exclude-file directives. (setq gnus-scores-exclude-files --- 704,711 ---- (setq lists (apply 'append lists (mapcar (lambda (file) (gnus-score-load-file file)) ! (if adapt-file (cons adapt-file files) ! files))))) (and eval (not global) (eval eval)) ;; We then expand any exclude-file directives. (setq gnus-scores-exclude-files *************** *** 734,743 **** (t ;;(setq gnus-newsgroup-adaptive gnus-use-adaptive-scoring) gnus-default-adaptive-score-alist))) (setq gnus-summary-mark-below (or mark mark-and-expunge gnus-summary-mark-below)) (setq gnus-summary-expunge-below ! (or expunge mark-and-expunge gnus-summary-expunge-below))) (setq gnus-current-score-file file) (setq gnus-score-alist alist) lists)) --- 738,751 ---- (t ;;(setq gnus-newsgroup-adaptive gnus-use-adaptive-scoring) gnus-default-adaptive-score-alist))) + (setq gnus-thread-expunge-below + (or thread-mark-and-expunge gnus-thread-expunge-below)) (setq gnus-summary-mark-below (or mark mark-and-expunge gnus-summary-mark-below)) (setq gnus-summary-expunge-below ! (or expunge mark-and-expunge gnus-summary-expunge-below)) ! (setq gnus-newsgroup-adaptive-score-file ! (or adapt-file gnus-newsgroup-adaptive-score-file))) (setq gnus-current-score-file file) (setq gnus-score-alist alist) lists)) *************** *** 1597,1604 **** (setq elem (cdr elem))) (setq malist (cdr malist))) ;; We change the score file to the adaptive score file. ! (gnus-score-load-file (gnus-score-file-name ! gnus-newsgroup-name gnus-adaptive-file-suffix)) ;; The we score away. (while data (setq elem (cdr (assq (gnus-data-mark (car data)) alist))) --- 1605,1614 ---- (setq elem (cdr elem))) (setq malist (cdr malist))) ;; We change the score file to the adaptive score file. ! (gnus-score-load-file ! (or gnus-newsgroup-adaptive-score-file ! (gnus-score-file-name ! gnus-newsgroup-name gnus-adaptive-file-suffix))) ;; The we score away. (while data (setq elem (cdr (assq (gnus-data-mark (car data)) alist))) *************** *** 1837,1882 **** (insert (car sfiles)) (goto-char (point-min)) ;; First remove the suffix itself. ! (re-search-forward (concat "." score-regexp)) ! (replace-match "" t t) ! (goto-char (point-min)) ! (if (looking-at (regexp-quote kill-dir)) ! ;; If the file name was just "SCORE", `klen' is one character ! ;; too much. ! (delete-char (min (1- (point-max)) klen)) ! (goto-char (point-max)) ! (search-backward "/") ! (delete-region (1+ (point)) (point-min))) ! ;; If short file names were used, we have to translate slashes. ! (goto-char (point-min)) ! (while (re-search-forward "[/:]" nil t) ! (replace-match "." t t)) ! ;; Cludge to get rid of "nntp+" problems. ! (goto-char (point-min)) ! (and (looking-at "nn[a-z]+\\+") ! (progn ! (search-forward "+") ! (forward-char -1) ! (insert "\\"))) ! ;; Translate "all" to ".*". ! (while (search-forward "all" nil t) ! (replace-match ".*" t t)) ! (goto-char (point-min)) ! ;; Deal with "not."s. ! (if (looking-at "not.") ! (progn ! (setq not-match t) ! (setq regexp (buffer-substring 5 (point-max)))) ! (setq regexp (buffer-substring 1 (point-max))) ! (setq not-match nil)) ! ;; Finally - if this resulting regexp matches the group name, ! ;; we add this score file to the list of score files ! ;; applicable to this group. ! (if (or (and not-match ! (not (string-match regexp group))) ! (and (not not-match) ! (string-match regexp group))) ! (setq ofiles (cons (car sfiles) ofiles))) (setq sfiles (cdr sfiles))) (kill-buffer (current-buffer)) ;; Slight kludge here - the last score file returned should be --- 1847,1892 ---- (insert (car sfiles)) (goto-char (point-min)) ;; First remove the suffix itself. ! (when (re-search-forward (concat "." score-regexp) nil t) ! (replace-match "" t t) ! (goto-char (point-min)) ! (if (looking-at (regexp-quote kill-dir)) ! ;; If the file name was just "SCORE", `klen' is one character ! ;; too much. ! (delete-char (min (1- (point-max)) klen)) ! (goto-char (point-max)) ! (search-backward "/") ! (delete-region (1+ (point)) (point-min))) ! ;; If short file names were used, we have to translate slashes. ! (goto-char (point-min)) ! (while (re-search-forward "[/:]" nil t) ! (replace-match "." t t)) ! ;; Cludge to get rid of "nntp+" problems. ! (goto-char (point-min)) ! (and (looking-at "nn[a-z]+\\+") ! (progn ! (search-forward "+") ! (forward-char -1) ! (insert "\\"))) ! ;; Translate "all" to ".*". ! (while (search-forward "all" nil t) ! (replace-match ".*" t t)) ! (goto-char (point-min)) ! ;; Deal with "not."s. ! (if (looking-at "not.") ! (progn ! (setq not-match t) ! (setq regexp (buffer-substring 5 (point-max)))) ! (setq regexp (buffer-substring 1 (point-max))) ! (setq not-match nil)) ! ;; Finally - if this resulting regexp matches the group name, ! ;; we add this score file to the list of score files ! ;; applicable to this group. ! (if (or (and not-match ! (not (string-match regexp group))) ! (and (not not-match) ! (string-match regexp group))) ! (setq ofiles (cons (car sfiles) ofiles)))) (setq sfiles (cdr sfiles))) (kill-buffer (current-buffer)) ;; Slight kludge here - the last score file returned should be *** pub/sgnus/lisp/gnus-topic.el Sun Dec 10 12:08:31 1995 --- sgnus/lisp/gnus-topic.el Mon Dec 11 09:19:41 1995 *************** *** 241,251 **** (add-text-properties (point) (prog1 (1+ (point)) ! (eval gnus-topic-line-format-spec)) (list 'gnus-topic name 'gnus-topic-level level ! 'gnus-topic-visible visiblep)) ! (gnus-group-remove-excess-properties))) (defun gnus-topic-previous-topic (topic) "Return the previous topic on the same level as TOPIC." --- 241,251 ---- (add-text-properties (point) (prog1 (1+ (point)) ! (eval gnus-topic-line-format-spec) ! (gnus-group-remove-excess-properties)) (list 'gnus-topic name 'gnus-topic-level level ! 'gnus-topic-visible visiblep)))) (defun gnus-topic-previous-topic (topic) "Return the previous topic on the same level as TOPIC." *************** *** 526,547 **** (defun gnus-topic-kill-group (&optional n discard) "Kill the next N groups." (interactive "P") ! (if (not (gnus-group-topic-p)) ! (gnus-group-kill-group n discard) ! (let ((topic (gnus-group-topic-name))) ! (gnus-topic-remove-topic nil t) ! (push (gnus-topic-find-topology topic nil nil gnus-topic-topology) ! gnus-topic-killed-topics)))) (defun gnus-topic-yank-group (&optional arg) "Yank the last topic." (interactive "p") ! (if (null gnus-topic-killed-topics) ! (gnus-group-yank-group arg) ! (let ((previous (gnus-group-parent-topic)) ! (item (nth 1 (pop gnus-topic-killed-topics)))) ! (gnus-topic-create-topic ! (car item) (gnus-topic-parent-topic previous) previous)))) (defun gnus-topic-hide-topic () "Hide all subtopics under the current topic." --- 526,572 ---- (defun gnus-topic-kill-group (&optional n discard) "Kill the next N groups." (interactive "P") ! (if (gnus-group-topic-p) ! (let ((topic (gnus-group-topic-name))) ! (gnus-topic-remove-topic nil t) ! (push (gnus-topic-find-topology topic nil nil gnus-topic-topology) ! gnus-topic-killed-topics)) ! ;; We first kill the groups the normal way... ! (let ((killed (gnus-group-kill-group n discard)) ! group alist) ! ;; Then we remove the killed groups from the topics they belong to. ! (when (stringp killed) ! (setq killed (list killed))) ! (while killed ! (when (setq alist (assoc (gnus-group-topic (setq group (pop killed))) ! gnus-topic-alist)) ! (setcdr alist (delete group (cdr alist)))))))) (defun gnus-topic-yank-group (&optional arg) "Yank the last topic." (interactive "p") ! (if gnus-topic-killed-topics ! (let ((previous (gnus-group-parent-topic)) ! (item (nth 1 (pop gnus-topic-killed-topics)))) ! (gnus-topic-create-topic ! (car item) (gnus-topic-parent-topic previous) previous)) ! ;; We first yank the groups the normal way... ! (let* ((topic (gnus-group-parent-topic)) ! (prev (gnus-group-group-name)) ! (alist (assoc topic gnus-topic-alist)) ! (yanked (gnus-group-yank-group arg)) ! group) ! ;; Then we enter the yanked groups in the topics they belong to. ! (when (stringp yanked) ! (setq yanked (list yanked))) ! (if (not prev) ! (nconc alist yanked) ! (setq alist (cdr alist)) ! (while (cdr alist) ! (when (equal (car (cdr alist)) prev) ! (setcdr alist (nconc yanked (cdr alist))) ! (setq alist nil)) ! (setq alist (cdr alist))))))) (defun gnus-topic-hide-topic () "Hide all subtopics under the current topic." *** pub/sgnus/lisp/gnus-uu.el Sun Dec 10 12:08:32 1995 --- sgnus/lisp/gnus-uu.el Tue Dec 12 10:15:08 1995 *************** *** 633,639 **** (setq files (gnus-uu-unpack-files files))) (gnus-uu-add-file (mapcar (lambda (file) (cdr (assq 'name file))) files)) (setq files (nreverse (gnus-uu-get-actions files))) ! (or not-insert (gnus-summary-insert-pseudos files save)))) ;; Return a list of files in dir. (defun gnus-uu-scan-directory (dir) --- 633,640 ---- (setq files (gnus-uu-unpack-files files))) (gnus-uu-add-file (mapcar (lambda (file) (cdr (assq 'name file))) files)) (setq files (nreverse (gnus-uu-get-actions files))) ! (or not-insert (not gnus-insert-pseudo-articles) ! (gnus-summary-insert-pseudos files save)))) ;; Return a list of files in dir. (defun gnus-uu-scan-directory (dir) *** pub/sgnus/lisp/gnus-vis.el Sun Dec 10 12:08:32 1995 --- sgnus/lisp/gnus-vis.el Tue Dec 12 21:52:32 1995 *************** *** 956,963 **** (end (progn (end-of-line) (point))) ;; now find out where the line starts and leave point there. (beg (progn (beginning-of-line) (point))) ! (score (or (cdr (assq (or (gnus-summary-article-number) ! gnus-current-article) gnus-newsgroup-scored)) gnus-summary-default-score 0)) (default gnus-summary-default-score) --- 956,963 ---- (end (progn (end-of-line) (point))) ;; now find out where the line starts and leave point there. (beg (progn (beginning-of-line) (point))) ! (article (gnus-summary-article-number)) ! (score (or (cdr (assq (or article gnus-current-article) gnus-newsgroup-scored)) gnus-summary-default-score 0)) (default gnus-summary-default-score) *************** *** 1179,1198 **** (fun (get-text-property (point) 'gnus-callback))) (if fun (funcall fun data)))) ! ;; Suggested by Arne Elofsson ! (defun gnus-article-next-button () ! "Move point to next button." ! (interactive) ! (if (get-text-property (point) 'gnus-callback) ! (goto-char (next-single-property-change (point) 'gnus-callback ! nil (point-max)))) ! (let ((pos (next-single-property-change (point) 'gnus-callback))) ! (if pos ! (goto-char pos) ! (setq pos (next-single-property-change (point-min) 'gnus-callback)) ! (if pos ! (goto-char pos) ! (error "No buttons found"))))) (defun gnus-article-highlight (&optional force) "Highlight current article. --- 1179,1209 ---- (fun (get-text-property (point) 'gnus-callback))) (if fun (funcall fun data)))) ! (defun gnus-article-prev-button (n) ! "Move point to N buttons backward. ! If N is negative, move forward instead." ! (interactive "p") ! (gnus-article-next-button (- n))) ! ! (defun gnus-article-next-button (n) ! "Move point to N buttons forward. ! If N is negative, move backward instead." ! (interactive "p") ! (let ((function (if (< n 0) 'prev-single-property-change ! 'next-single-property-change)) ! (limit (if (< n 0) (point-min) (point-max)))) ! (setq n (abs n)) ! (while (and (not (= limit (point))) ! (> n 0)) ! ;; Skip past the current button. ! (when (get-text-property (point) 'gnus-callback) ! (goto-char (funcall function (point) 'gnus-callback nil limit))) ! ;; Go to the next (or previous) button. ! (funcall function (point) 'gnus-callback nil limit) ! (decf n)) ! (unless (zerop n) ! (gnus-message 5 "No more buttons")) ! n)) (defun gnus-article-highlight (&optional force) "Highlight current article. *************** *** 1466,1471 **** --- 1477,1509 ---- (defun gnus-button-url (address) "Browse ADDRESS." (funcall browse-url-browser-function address)) + + ;;; Next/prev buttons in the article buffer. + + (defvar gnus-next-page-line-format "%{%(Next page...%)%}\n") + (defvar gnus-prev-page-line-format "%{%(Previous page...%)%}\n") + + (defvar gnus-prev-page-map nil) + (unless gnus-prev-page-map + (setq gnus-prev-page-map (make-sparse-keymap)) + (define-key gnus-prev-page-map "\n" 'gnus-article-prev-page)) + + (defun gnus-insert-prev-page-button () + (let ((buffer-read-only nil)) + (gnus-remove-text-with-property 'gnus-prev) + (gnus-eval-format gnus-prev-page-line-format nil + `(gnus-prev t local-map ,gnus-prev-page-map)))) + + (defvar gnus-next-page-map nil) + (unless gnus-next-page-map + (setq gnus-next-page-map (make-sparse-keymap)) + (define-key gnus-next-page-map "\n" 'gnus-article-next-page)) + + (defun gnus-insert-next-page-button () + (let ((buffer-read-only nil)) + (gnus-remove-text-with-property 'gnus-next) + (gnus-eval-format gnus-next-page-line-format nil + `(gnus-next t local-map ,gnus-next-page-map)))) ;;; Compatibility Functions: *** pub/sgnus/lisp/gnus-xmas.el Sun Dec 10 12:08:32 1995 --- sgnus/lisp/gnus-xmas.el Thu Dec 14 11:27:35 1995 *************** *** 224,229 **** --- 224,238 ---- (easy-menu-add gnus-article-article-menu) (easy-menu-add gnus-article-treatment-menu)) + (defun gnus-xmas-read-event-char () + "Get the next event." + (let ((event (next-event))) + (while (timeout-event-p event) + (setq event (next-event))) + (cons (and (key-press-event-p event) + (numberp (event-key event)) + (event-to-character event)) + event))) (defun gnus-xmas-define () (setq gnus-mouse-2 [button2]) *************** *** 244,250 **** (fset 'set-text-properties 'gnus-xmas-set-text-properties) (or (boundp 'standard-display-table) (setq standard-display-table nil)) - (or (boundp 'read-event) (fset 'read-event 'next-command-event)) (defvar gnus-mouse-face-prop 'highlight) --- 253,258 ---- *************** *** 302,309 **** (defun gnus-xmas-redefine () ! ! (fset 'gnus-summary-make-display-table (lambda () nil)) (fset 'gnus-visual-turn-off-edit-menu 'identity) (fset 'gnus-highlight-selected-summary --- 310,316 ---- (defun gnus-xmas-redefine () ! "Redefine lots of Gnus functions for XEmacs." (fset 'gnus-summary-make-display-table (lambda () nil)) (fset 'gnus-visual-turn-off-edit-menu 'identity) (fset 'gnus-highlight-selected-summary *************** *** 316,321 **** --- 323,330 ---- (fset 'gnus-article-add-button 'gnus-xmas-article-add-button) (fset 'gnus-window-top-edge 'gnus-xmas-window-top-edge) (fset 'set-text-properties 'gnus-xmas-set-text-properties) + (fset 'gnus-read-event-char 'gnus-xmas-read-event-char) + (fset 'gnus-group-startup-message 'gnus-xmas-group-startup-message) (or (fboundp 'appt-select-lowest-window) (fset 'appt-select-lowest-window *************** *** 349,404 **** (setq path (cdr path)))) gnus-xmas-glyph-directory))) ! (defun gnus-xmas-group-startup (&optional x y) "Insert startup message in current buffer." ;; Insert the message. (erase-buffer) ! (if (featurep 'xpm) ! (progn ! (set-glyph-property gnus-xmas-logo 'image "~/tmp/gnus.xpm") ! (set-glyph-image gnus-xmas-logo "~/tmp/gnus.xpm" 'global 'x) ! ! (insert " ") ! (set-extent-begin-glyph (make-extent (point) (point)) gnus-xmas-logo) ! (insert " ! Gnus * A newsreader for Emacsen ! A Praxis Release * larsi@ifi.uio.no") ! (goto-char (point-min)) ! (while (not (eobp)) ! (insert (make-string (/ (max (- (window-width) (or x 35)) 0) 2) ! ? )) ! (forward-line 1)) ! (goto-char (point-min)) ! ;; +4 is fuzzy factor. ! (insert-char ?\n (/ (max (- (window-height) (or y 24)) 0) 2))) ! ! (insert ! (format " ! %s ! A newsreader ! for GNU Emacs ! ! Based on GNUS ! written by ! Masanobu UMEDA - A Praxis Release - larsi@ifi.uio.no " ! gnus-version)) ! ;; And then hack it. ! ;; 18 is the longest line. ! (indent-rigidly (point-min) (point-max) ! (/ (max (- (window-width) (or x 28)) 0) 2)) (goto-char (point-min)) ! ;; +4 is fuzzy factor. ! (insert-char ?\n (/ (max (- (window-height) (or y 12)) 0) 2))) - ;; Fontify some. - (goto-char (point-min)) - (search-forward "Praxis") - (put-text-property (match-beginning 0) (match-end 0) 'face 'bold) - (goto-char (point-min))) ;;; The toolbar. --- 358,432 ---- (setq path (cdr path)))) gnus-xmas-glyph-directory))) ! (defun gnus-xmas-group-startup-message (&optional x y) "Insert startup message in current buffer." ;; Insert the message. + (gnus-xmas-find-glyph-directory) (erase-buffer) ! (let ((file (and gnus-xmas-glyph-directory ! (concat ! (file-name-as-directory gnus-xmas-glyph-directory) ! "gnus.xpm")))) ! (if (and (featurep 'xpm) ! file (file-exists-p file)) ! (progn ! (set-glyph-property gnus-xmas-logo 'image file) ! (set-glyph-image gnus-xmas-logo file 'global 'x) ! ! (insert " ") ! (set-extent-begin-glyph (make-extent (point) (point)) gnus-xmas-logo) ! (goto-char (point-min)) ! (while (not (eobp)) ! (insert (make-string (/ (max (- (window-width) (or x 35)) 0) 2) ! ? )) ! (forward-line 1)) ! (goto-char (point-min)) ! (let* ((pheight (+ 20 (count-lines (point-min) (point-max)))) ! (wheight (window-height)) ! (rest (- wheight pheight))) ! (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n)))) ! ! (insert ! (format " %s ! _ ___ _ _ ! _ ___ __ ___ __ _ ___ ! __ _ ___ __ ___ ! _ ___ _ ! _ _ __ _ ! ___ __ _ ! __ _ ! _ _ _ ! _ _ _ ! _ _ _ ! __ ___ ! _ _ _ _ ! _ _ ! _ _ ! _ _ ! _ ! __ " ! "")) ! ;; And then hack it. ! (gnus-indent-rigidly (point-min) (point-max) ! (/ (max (- (window-width) (or x 46)) 0) 2)) ! (goto-char (point-min)) ! (forward-line 1) ! (let* ((pheight (count-lines (point-min) (point-max))) ! (wheight (window-height)) ! (rest (- wheight pheight))) ! (insert (make-string (max 0 (* 2 (/ rest 3))) ?\n)))) ! ;; Fontify some. ! (goto-char (point-min)) ! (and (search-forward "Praxis" nil t) ! (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 ! (list (concat gnus-version (substring (car mode-string) 4)))) ! (set-buffer-modified-p t)))) ;;; The toolbar. *** pub/sgnus/lisp/gnus.el Sun Dec 10 12:08:35 1995 --- sgnus/lisp/gnus.el Thu Dec 14 11:13:13 1995 *************** *** 254,259 **** --- 254,264 ---- (defvar gnus-asynchronous nil "*If non-nil, Gnus will supply backends with data needed for async article fetching.") + (defvar gnus-kill-summary-on-exit t + "*If non-nil, kill the summary buffer when you exit from it. + If nil, the summary will become a \"*Dead Summary*\" buffer, and + it will be killed sometime later.") + (defvar gnus-large-newsgroup 200 "*The number of articles which indicates a large newsgroup. If the number of articles in a newsgroup is greater than this value, *************** *** 320,335 **** The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.") ! (defvar gnus-split-methods nil "*Variable used to suggest where articles are to be saved. - The syntax of this variable is the same as `nnmail-split-methods'. - For instance, if you would like to save articles related to Gnus in the file \"gnus-stuff\", and articles related to VM in \"vm-stuff\", you could set this variable to something like: '((\"^Subject:.*gnus\\|^Newsgroups:.*gnus\" \"gnus-stuff\") ! (\"^Subject:.*vm\\|^Xref:.*vm\" \"vm-stuff\"))") (defvar gnus-save-score nil "*If non-nil, save group scoring info.") --- 325,351 ---- The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.") ! (defvar gnus-split-methods ! '((gnus-article-archive-name)) "*Variable used to suggest where articles are to be saved. For instance, if you would like to save articles related to Gnus in the file \"gnus-stuff\", and articles related to VM in \"vm-stuff\", you could set this variable to something like: '((\"^Subject:.*gnus\\|^Newsgroups:.*gnus\" \"gnus-stuff\") ! (\"^Subject:.*vm\\|^Xref:.*vm\" \"vm-stuff\")) ! ! This variable is an alist where the where the key is the match and the ! value is a list of possible files to save in if the match is non-nil. ! ! If the match is a string, it is used as a regexp match on the ! article. If the match is a symbol, that symbol will be funcalled ! from the buffer of the article to be saved with the newsgroup as the ! parameter. If it is a list, it will be evaled in the same buffer. ! ! If this form or function returns a string, this string will be used as ! a possible file name; and if it returns a non-nil list, that list will ! be used as possible file names.") (defvar gnus-save-score nil "*If non-nil, save group scoring info.") *************** *** 338,344 **** "*If non-nil, use some adaptive scoring scheme.") (defvar gnus-use-cache nil ! "*If non-nil, Gnus will cache (some) articles locally.") (defvar gnus-keep-backlog nil "*If non-nil, Gnus will keep read articles for later re-retrieval. --- 354,363 ---- "*If non-nil, use some adaptive scoring scheme.") (defvar gnus-use-cache nil ! "*If nil, Gnus will ignore the article cache. ! If `passive', it will allow entering (and reading) articles ! explicitly entered into the cache. If anything else, use the ! cache to the full extent of the law.") (defvar gnus-keep-backlog nil "*If non-nil, Gnus will keep read articles for later re-retrieval. *************** *** 514,519 **** --- 533,543 ---- (defvar gnus-level-default-unsubscribed 6 "*New unsubscribed groups will be unsubscribed at this level.") + (defvar gnus-activate-level (1+ gnus-level-subscribed) + "*Groups higher than this level won't be activated on startup. + Setting this variable to something log might save lots of time when + you have many groups that you aren't interested in.") + (defvar gnus-activate-foreign-newsgroups 4 "*If nil, Gnus will not check foreign newsgroups at startup. If it is non-nil, it should be a number between one and nine. Foreign *************** *** 654,663 **** --- 678,689 ---- (defvar gnus-ignored-headers "^Path:\\|^Posting-Version:\\|^Article-I.D.:\\|^Expires:\\|^Date-Received:\\|^References:\\|^Control:\\|^Xref:\\|^Lines:\\|^Posted:\\|^Relay-Version:\\|^Message-ID:\\|^Nf-ID:\\|^Nf-From:\\|^Approved:\\|^Sender:\\|^Received:\\|^Mail-from:" "*All headers that match this regexp will be hidden. + This variable can also be a list of regexps of headers to be ignored. If `gnus-visible-headers' is non-nil, this variable will be ignored.") (defvar gnus-visible-headers "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Resent-" "*All headers that do not match this regexp will be hidden. + This variable can also be a list of regexp of headers to remain visible. If this variable is non-nil, `gnus-ignored-headers' will be ignored.") (defvar gnus-sorted-header-list *************** *** 820,826 **** `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.") ;; Suggested by a bug report by Hallvard B Furuseth. ;; . --- 846,852 ---- `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.") ;; Suggested by a bug report by Hallvard B Furuseth. ;; . *************** *** 884,889 **** --- 910,919 ---- "*Mark used for articles that are caught up.") (defvar gnus-replied-mark ?A "*Mark used for articles that have been replied to.") + (defvar gnus-cached-mark ?* + "*Mark used for articles that are in the cache.") + (defvar gnus-saved-mark ?S + "*Mark used for articles that have been saved to.") (defvar gnus-process-mark ?# "*Process mark.") (defvar gnus-ancient-mark ?O *************** *** 912,917 **** --- 942,950 ---- If nil, all files that use the same viewing command will be given as a list of parameters to that command.") + (defvar gnus-insert-pseudo-articles t + "*If non-nil, insert pseudo-articles when decoding articles.") + (defvar gnus-group-line-format "%M%S%p%P%5y: %(%g%)\n" "*Format of group lines. It works along the same lines as a normal formatting string, *************** *** 1023,1036 **** %S The subject") ! (defvar gnus-summary-mode-line-format "Gnus %G/%A %Z" ! "*The format specification for the summary mode line.") ! (defvar gnus-article-mode-line-format "Gnus %G/%A %S" ! "*The format specification for the article mode line.") ! (defvar gnus-group-mode-line-format "Gnus List of groups {%M:%S} " ! "*The format specification for the group mode line.") (defvar gnus-valid-select-methods '(("nntp" post address prompt-address) --- 1056,1092 ---- %S The subject") ! (defvar gnus-summary-mode-line-format "Gnus: %%b [%A] %Z" ! "*The format specification for the summary mode line. ! It works along the same lines as a normal formatting string, ! with some simple extensions: ! ! %G Group name ! %p Unprefixed group name ! %A Current article number ! %V Gnus version ! %U Number of unread articles in the group ! %e Number of unselected articles in the group ! %Z A string with unread/unselected article counts ! %g Shortish group name ! %S Subject of the current article ! %u User-defined spec ! %s Current score file name ! %d Number of dormant articles ! %r Number of articles that have been marked as read in this session ! %E Number of articles expunged by the score files") ! ! (defvar gnus-article-mode-line-format "Gnus: %%b %S" ! "*The format specification for the article mode line. ! See `gnus-summary-mode-line-format' for a closer description.") ! (defvar gnus-group-mode-line-format "Gnus: %%b {%M:%S}" ! "*The format specification for the group mode line. ! It works along the same lines as a normal formatting string, ! with some simple extensions: ! %S The native news server. ! %M The native select method.") (defvar gnus-valid-select-methods '(("nntp" post address prompt-address) *************** *** 1062,1068 **** If this variable is nil, screen refresh may be quicker.") ;; Added by Keinonen Kari . ! (defvar gnus-mode-non-string-length 25 "*Max length of mode-line non-string contents. If this is nil, Gnus will take space as is needed, leaving the rest of the modeline intact.") --- 1118,1124 ---- If this variable is nil, screen refresh may be quicker.") ;; Added by Keinonen Kari . ! (defvar gnus-mode-non-string-length nil "*Max length of mode-line non-string contents. If this is nil, Gnus will take space as is needed, leaving the rest of the modeline intact.") *************** *** 1077,1082 **** --- 1133,1141 ---- This variable is local to each summary buffer and usually set by the score file.") + (defvar gnus-article-sort-functions '(gnus-article-sort-by-number) + "*List of functions used for sorting articles in the summary buffer.") + (defvar gnus-thread-sort-functions '(gnus-thread-sort-by-number) "*List of functions used for sorting threads in the summary buffer. By default, threads are sorted by article number. *************** *** 1098,1103 **** --- 1157,1170 ---- Some functions you can use are `+', `max', or `min'.") + (defvar gnus-summary-expunge-below nil + "All articles that have a score less than this variable will be expunged.") + + (defvar gnus-thread-expunge-below nil + "All threads that have a total score less than this variable will be expunged. + See `gnus-thread-score-function' for en explanation of what a + \"thread score\" is.") + (defvar gnus-auto-subscribed-groups "^nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl" "*All new groups that match this regexp will be subscribed automatically. *************** *** 1318,1323 **** --- 1385,1391 ---- (defvar gnus-inhibit-hiding nil) (defvar gnus-topic-indentation "") + (defvar gnus-inhibit-limiting nil) (defvar gnus-article-mode-map nil) (defvar gnus-dribble-buffer nil) *************** *** 1329,1334 **** --- 1397,1403 ---- (defvar gnus-nocem-hashtb nil) (defvar gnus-current-score-file nil) + (defvar gnus-newsgroup-adaptive-score-file nil) (defvar gnus-scores-exclude-files nil) (defvar gnus-opened-servers nil) *************** *** 1344,1350 **** (defvar gnus-summary-display-table nil) (defconst gnus-group-line-format-alist ! `((?M gnus-tmp-marked ?c) (?S gnus-tmp-subscribed ?c) (?L gnus-tmp-level ?d) (?N gnus-tmp-number ?s) --- 1413,1419 ---- (defvar gnus-summary-display-table nil) (defconst gnus-group-line-format-alist ! `((?M gnus-tmp-marked-mark ?c) (?S gnus-tmp-subscribed ?c) (?L gnus-tmp-level ?d) (?N gnus-tmp-number ?s) *************** *** 1428,1433 **** --- 1497,1505 ---- (?E gnus-newsgroup-expunged-tally ?d) (?s (gnus-current-score-file-nondirectory) ?s)))) + (defconst gnus-article-mode-line-format-alist + gnus-summary-mode-line-format-alist) + (defconst gnus-group-mode-line-format-alist (` ((?S gnus-tmp-news-server ?s) (?M gnus-tmp-news-method ?s) *************** *** 1439,1445 **** "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)" "The mail address of the Gnus maintainers.") ! (defconst gnus-version "September Gnus v0.21" "Version number for this version of Gnus.") (defvar gnus-info-nodes --- 1511,1517 ---- "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)" "The mail address of the Gnus maintainers.") ! (defconst gnus-version "September Gnus v0.22" "Version number for this version of Gnus.") (defvar gnus-info-nodes *************** *** 1568,1573 **** --- 1640,1651 ---- (defvar gnus-newsgroup-killed nil "List of ranges of articles that have been through the scoring process.") + (defvar gnus-newsgroup-cached nil + "List of articles that come from the article cache.") + + (defvar gnus-newsgroup-saved nil + "List of articles that have been saved.") + (defvar gnus-newsgroup-kill-headers nil) (defvar gnus-newsgroup-replied nil *************** *** 1613,1619 **** (defvar gnus-summary-mark-positions nil) (defvar gnus-group-mark-positions nil) - (defvar gnus-summary-expunge-below nil) (defvar gnus-reffed-article-number nil) ;;; Let the byte-compiler know that we know about this variable. --- 1691,1696 ---- *************** *** 1621,1626 **** --- 1698,1705 ---- (defvar gnus-cache-removeable-articles nil) + (defvar gnus-dead-summary nil) + (defconst gnus-summary-local-variables '(gnus-newsgroup-name gnus-newsgroup-begin gnus-newsgroup-end *************** *** 1628,1634 **** gnus-newsgroup-last-folder gnus-newsgroup-last-file gnus-newsgroup-auto-expire gnus-newsgroup-unreads gnus-newsgroup-unselected gnus-newsgroup-marked ! gnus-newsgroup-reads gnus-newsgroup-replied gnus-newsgroup-expirable gnus-newsgroup-processable gnus-newsgroup-killed gnus-newsgroup-bookmarks gnus-newsgroup-dormant --- 1707,1713 ---- gnus-newsgroup-last-folder gnus-newsgroup-last-file gnus-newsgroup-auto-expire gnus-newsgroup-unreads gnus-newsgroup-unselected gnus-newsgroup-marked ! gnus-newsgroup-reads gnus-newsgroup-saved gnus-newsgroup-replied gnus-newsgroup-expirable gnus-newsgroup-processable gnus-newsgroup-killed gnus-newsgroup-bookmarks gnus-newsgroup-dormant *************** *** 1643,1650 **** gnus-summary-mark-below gnus-newsgroup-active gnus-scores-exclude-files gnus-newsgroup-history gnus-newsgroup-ancient (gnus-newsgroup-adaptive . gnus-use-adaptive-scoring) (gnus-newsgroup-expunged-tally . 0) ! gnus-cache-removeable-articles gnus-newsgroup-data gnus-newsgroup-data-reverse gnus-newsgroup-limit gnus-newsgroup-limits) "Variables that are buffer-local to the summary buffers.") --- 1722,1730 ---- gnus-summary-mark-below gnus-newsgroup-active gnus-scores-exclude-files gnus-newsgroup-history gnus-newsgroup-ancient (gnus-newsgroup-adaptive . gnus-use-adaptive-scoring) + gnus-newsgroup-adaptive-score-file (gnus-newsgroup-expunged-tally . 0) ! gnus-cache-removeable-articles gnus-newsgroup-cached gnus-newsgroup-data gnus-newsgroup-data-reverse gnus-newsgroup-limit gnus-newsgroup-limits) "Variables that are buffer-local to the summary buffers.") *************** *** 1715,1728 **** gnus-server-make-menu-bar gnus-article-make-menu-bar gnus-browse-make-menu-bar gnus-highlight-selected-summary gnus-summary-highlight-line gnus-carpal-setup-buffer ! gnus-article-add-button) ("gnus-vis" :interactive t gnus-article-push-button gnus-article-press-button gnus-article-highlight gnus-article-highlight-some gnus-article-hide gnus-article-hide-signature gnus-article-highlight-headers gnus-article-highlight-signature gnus-article-add-buttons gnus-article-add-buttons-to-head ! gnus-article-next-button) ("gnus-demon" gnus-demon-add-nocem gnus-demon-add-scanmail gnus-demon-add-disconnection gnus-demon-add-handler gnus-demon-remove-handler) --- 1795,1809 ---- gnus-server-make-menu-bar gnus-article-make-menu-bar gnus-browse-make-menu-bar gnus-highlight-selected-summary gnus-summary-highlight-line gnus-carpal-setup-buffer ! gnus-article-add-button gnus-insert-next-page-button ! gnus-insert-prev-page-button) ("gnus-vis" :interactive t gnus-article-push-button gnus-article-press-button gnus-article-highlight gnus-article-highlight-some gnus-article-hide gnus-article-hide-signature gnus-article-highlight-headers gnus-article-highlight-signature gnus-article-add-buttons gnus-article-add-buttons-to-head ! gnus-article-next-button gnus-article-prev-button) ("gnus-demon" gnus-demon-add-nocem gnus-demon-add-scanmail gnus-demon-add-disconnection gnus-demon-add-handler gnus-demon-remove-handler) *************** *** 1739,1747 **** ("gnus-cache" gnus-cache-possibly-enter-article gnus-cache-save-buffers gnus-cache-possibly-remove-articles gnus-cache-request-article gnus-cache-retrieve-headers gnus-cache-possibly-alter-active ! gnus-cache-enter-remove-article gnus-cache-open gnus-cache-close) ! ("gnus-cache" :interactive t gnus-jog-cache) ("gnus-score" :interactive t gnus-summary-increase-score gnus-summary-lower-score gnus-score-flush-cache gnus-score-close --- 1820,1829 ---- ("gnus-cache" gnus-cache-possibly-enter-article gnus-cache-save-buffers gnus-cache-possibly-remove-articles gnus-cache-request-article gnus-cache-retrieve-headers gnus-cache-possibly-alter-active ! gnus-cache-enter-remove-article gnus-cached-article-p gnus-cache-open gnus-cache-close) ! ("gnus-cache" :interactive t gnus-jog-cache gnus-cache-enter-article ! gnus-cache-remove-article) ("gnus-score" :interactive t gnus-summary-increase-score gnus-summary-lower-score gnus-score-flush-cache gnus-score-close *************** *** 1771,1777 **** ("gnus-msg" (gnus-summary-send-map keymap) gnus-mail-yank-original gnus-mail-send-and-exit gnus-sendmail-setup-mail gnus-article-mail ! gnus-inews-message-id gnus-news-mail gnus-mail-reply) ("gnus-msg" :interactive t gnus-group-post-news gnus-group-mail gnus-summary-post-news gnus-summary-followup gnus-summary-followup-with-original --- 1853,1859 ---- ("gnus-msg" (gnus-summary-send-map keymap) gnus-mail-yank-original gnus-mail-send-and-exit gnus-sendmail-setup-mail gnus-article-mail ! gnus-inews-message-id gnus-new-mail gnus-mail-reply) ("gnus-msg" :interactive t gnus-group-post-news gnus-group-mail gnus-summary-post-news gnus-summary-followup gnus-summary-followup-with-original *************** *** 1990,1995 **** --- 2072,2078 ---- (defvar gnus-tmp-subject-or-nil) (defvar gnus-tmp-subject) (defvar gnus-tmp-marked) + (defvar gnus-tmp-marked-mark) (defvar gnus-tmp-subscribed) (defvar gnus-tmp-process-marked) (defvar gnus-tmp-number-of-unread) *************** *** 2038,2044 **** (gnus-byte-code 'gnus-summary-dummy-line-format-spec)) (defun gnus-group-line-format-spec () ! (insert gnus-tmp-marked gnus-tmp-subscribed gnus-tmp-process-marked gnus-topic-indentation (format "%5s: " gnus-tmp-number-of-unread)) --- 2121,2127 ---- (gnus-byte-code 'gnus-summary-dummy-line-format-spec)) (defun gnus-group-line-format-spec () ! (insert gnus-tmp-marked-mark gnus-tmp-subscribed gnus-tmp-process-marked gnus-topic-indentation (format "%5s: " gnus-tmp-number-of-unread)) *************** *** 2051,2082 **** (defvar gnus-group-line-format-spec (gnus-byte-code 'gnus-group-line-format-spec)) - (defun gnus-summary-mode-line-format-spec () - (format "Gnus %s/%d %s" gnus-tmp-group-name - gnus-tmp-article-number gnus-tmp-unread-and-unselected)) - (defvar gnus-summary-mode-line-format-spec - (gnus-byte-code 'gnus-summary-mode-line-format-spec)) - - (defun gnus-group-mode-line-format-spec () - (format "Gnus List of groups {%s:%s} " - gnus-tmp-news-method gnus-tmp-news-server)) - (defvar gnus-group-mode-line-format-spec - (gnus-byte-code 'gnus-group-mode-line-format-spec)) - - (defun gnus-article-mode-line-format-spec () - (format "Gnus %s/%d %s" gnus-tmp-group-name - gnus-tmp-article-number gnus-tmp-subject)) - (defvar gnus-article-mode-line-format-spec - (gnus-byte-code 'gnus-article-mode-line-format-spec)) - (defvar gnus-old-specs ! '((article-mode . "Gnus %G/%A %S") ! (group-mode . "Gnus List of groups {%M:%S} ") ! (summary-mode . "Gnus %G/%A %Z") ! (group . "%M%S%p%5y: %(%g%)\n") (summary-dummy . "* : : %S\n") (summary . "%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n"))) ;;; Phew. All that gruft is over, fortunately. --- 2134,2148 ---- (defvar gnus-group-line-format-spec (gnus-byte-code 'gnus-group-line-format-spec)) (defvar gnus-old-specs ! '((group . "%M%S%p%5y: %(%g%)\n") (summary-dummy . "* : : %S\n") (summary . "%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n"))) + (defvar gnus-article-mode-line-format-spec nil) + (defvar gnus-summary-mode-line-format-spec nil) + (defvar gnus-group-mode-line-format-spec nil) + ;;; Phew. All that gruft is over, fortunately. *************** *** 2328,2364 **** (goto-char (point-min)) (while (re-search-forward "%[-0-9]*\\(,[0-9]+\\)?\\([^0-9]\\)\\(.\\)?" nil t) ! (setq spec (string-to-char (match-string 2))) ! ;; First check if there are any specs that look anything like ! ;; "%12,12A", ie. with a "max width specification". These have ! ;; to be treated specially. ! (if (setq beg (match-beginning 1)) ! (setq max-width ! (string-to-int ! (buffer-substring (1+ (match-beginning 1)) (match-end 1)))) ! (setq max-width 0) ! (setq beg (match-beginning 2))) ! ;; Find the specification from `spec-alist'. ! (unless (setq elem (cdr (assq spec spec-alist))) ! (setq elem '("*" ?s))) ! ;; Treat user defined format specifiers specially. ! (when (eq (car elem) 'gnus-tmp-user-defined) ! (setq elem ! (list ! (list (intern (concat "gnus-user-format-function-" ! (match-string 3))) ! 'gnus-tmp-header) ?s)) ! (delete-region (match-beginning 3) (match-end 3))) ! (if (not (zerop max-width)) ! (let ((el (car elem))) ! (cond ((= (car (cdr elem)) ?c) ! (setq el (list 'char-to-string el))) ! ((= (car (cdr elem)) ?d) ! (numberp el) (setq el (list 'int-to-string el)))) ! (setq flist (cons (gnus-max-width-function el max-width) ! flist)) ! (setq newspec ?s)) ! (setq flist (cons (car elem) flist)) (setq newspec (car (cdr elem)))) ;; Remove the old specification (and possibly a ",12" string). (delete-region beg (match-end 2)) --- 2394,2433 ---- (goto-char (point-min)) (while (re-search-forward "%[-0-9]*\\(,[0-9]+\\)?\\([^0-9]\\)\\(.\\)?" nil t) ! (if (= (setq spec (string-to-char (match-string 2))) ?%) ! (setq newspec "%" ! beg (1+ (match-beginning 0))) ! ;; First check if there are any specs that look anything like ! ;; "%12,12A", ie. with a "max width specification". These have ! ;; to be treated specially. ! (if (setq beg (match-beginning 1)) ! (setq max-width ! (string-to-int ! (buffer-substring ! (1+ (match-beginning 1)) (match-end 1)))) ! (setq max-width 0) ! (setq beg (match-beginning 2))) ! ;; Find the specification from `spec-alist'. ! (unless (setq elem (cdr (assq spec spec-alist))) ! (setq elem '("*" ?s))) ! ;; Treat user defined format specifiers specially. ! (when (eq (car elem) 'gnus-tmp-user-defined) ! (setq elem ! (list ! (list (intern (concat "gnus-user-format-function-" ! (match-string 3))) ! 'gnus-tmp-header) ?s)) ! (delete-region (match-beginning 3) (match-end 3))) ! (if (not (zerop max-width)) ! (let ((el (car elem))) ! (cond ((= (car (cdr elem)) ?c) ! (setq el (list 'char-to-string el))) ! ((= (car (cdr elem)) ?d) ! (numberp el) (setq el (list 'int-to-string el)))) ! (setq flist (cons (gnus-max-width-function el max-width) ! flist)) ! (setq newspec ?s)) ! (setq flist (cons (car elem) flist))) (setq newspec (car (cdr elem)))) ;; Remove the old specification (and possibly a ",12" string). (delete-region beg (match-end 2)) *************** *** 2411,2416 **** --- 2480,2502 ---- (cons 'insert result))) (or (car result) "")))) + (defun gnus-eval-format (format &optional alist props) + "Eval the format variable FORMAT, using ALIST. + If INSERT, insert the result." + (let ((form (gnus-parse-format format alist props))) + (if props + (add-text-properties (point) (progn (eval form) (point)) props) + (eval form)))) + + (defun gnus-remove-text-with-property (prop) + "Delete all text in the current buffer with text property PROP." + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (when (get-text-property (point) prop) + (delete-char 1)) + (goto-char (next-single-property-change (point) prop nil (point-max)))))) + (defun gnus-set-work-buffer () (if (get-buffer gnus-work-buffer) (progn *************** *** 2580,2596 **** (substring groupkey (match-beginning 1) (match-end 1))))) (gnus-subscribe-newsgroup newgroup before)))) ! (defun gnus-subscribe-interactively (newsgroup) ! "Subscribe new NEWSGROUP interactively. It is inserted in hierarchical newsgroup order if subscribed. If not, it is killed." ! (if (gnus-y-or-n-p (format "Subscribe new newsgroup: %s " newsgroup)) ! (gnus-subscribe-hierarchically newsgroup) ! (setq gnus-killed-list (cons newsgroup gnus-killed-list)))) ! ! (defun gnus-subscribe-zombies (newsgroup) ! "Make new NEWSGROUP a zombie group." ! (setq gnus-zombie-list (cons newsgroup gnus-zombie-list))) (defun gnus-subscribe-newsgroup (newsgroup &optional next) "Subscribe new NEWSGROUP. --- 2666,2686 ---- (substring groupkey (match-beginning 1) (match-end 1))))) (gnus-subscribe-newsgroup newgroup before)))) ! (defun gnus-subscribe-interactively (group) ! "Subscribe the new GROUP interactively. It is inserted in hierarchical newsgroup order if subscribed. If not, it is killed." ! (if (gnus-y-or-n-p (format "Subscribe new newsgroup: %s " group)) ! (gnus-subscribe-hierarchically group) ! (push group gnus-killed-list))) ! ! (defun gnus-subscribe-zombies (group) ! "Make the new GROUP into a zombie group." ! (push group gnus-zombie-list)) ! ! (defun gnus-subscribe-killed (group) ! "Make the new GROUP a killed group." ! (push group gnus-killed-list)) (defun gnus-subscribe-newsgroup (newsgroup &optional next) "Subscribe new NEWSGROUP. *************** *** 3530,3535 **** --- 3620,3626 ---- (suppress-keymap gnus-group-mode-map) (define-key gnus-group-mode-map " " 'gnus-group-read-group) (define-key gnus-group-mode-map "=" 'gnus-group-select-group) + (define-key gnus-group-mode-map "\M- " 'gnus-group-unhidden-select-group) (define-key gnus-group-mode-map "\r" 'gnus-group-select-group) (define-key gnus-group-mode-map "\M-\r" 'gnus-group-quick-select-group) (define-key gnus-group-mode-map "j" 'gnus-group-jump-to-group) *************** *** 3588,3593 **** --- 3679,3685 ---- (define-key gnus-group-mode-map "\C-c\C-b" 'gnus-bug) (define-key gnus-group-mode-map "\C-c\C-s" 'gnus-group-sort-groups) (define-key gnus-group-mode-map "t" 'gnus-topic-mode) + (define-key gnus-group-mode-map "\C-c\M-g" 'gnus-activate-all-groups) (define-key gnus-group-mode-map "#" 'gnus-group-mark-group) (define-key gnus-group-mode-map "\M-#" 'gnus-group-unmark-group) *************** *** 3662,3667 **** --- 3754,3760 ---- (define-key gnus-group-sub-map "k" 'gnus-group-kill-group) (define-key gnus-group-sub-map "y" 'gnus-group-yank-group) (define-key gnus-group-sub-map "w" 'gnus-group-kill-region) + (define-key gnus-group-sub-map "\C-k" 'gnus-group-kill-level) (define-key gnus-group-sub-map "z" 'gnus-group-kill-all-zombies)) (defun gnus-group-mode () *************** *** 3906,3912 **** (goto-char (point-min)) (let* ((mode-string (gnus-group-set-mode-line))) (setq mode-line-buffer-identification ! (concat gnus-version (substring mode-string 4))) (set-buffer-modified-p t))) (defun gnus-group-startup-message-old (&optional x y) --- 3999,4005 ---- (goto-char (point-min)) (let* ((mode-string (gnus-group-set-mode-line))) (setq mode-line-buffer-identification ! (list (concat gnus-version (substring (car mode-string) 4)))) (set-buffer-modified-p t))) (defun gnus-group-startup-message-old (&optional x y) *************** *** 4328,4334 **** (if gnus-tmp-method (format "(%s:%s)" (car gnus-tmp-method) (car (cdr gnus-tmp-method))) "")) ! (gnus-tmp-marked (if (and (numberp number) (zerop number) (cdr (assq 'tick gnus-tmp-marked))) --- 4421,4427 ---- (if gnus-tmp-method (format "(%s:%s)" (car gnus-tmp-method) (car (cdr gnus-tmp-method))) "")) ! (gnus-tmp-marked-mark (if (and (numberp number) (zerop number) (cdr (assq 'tick gnus-tmp-marked))) *************** *** 4352,4358 **** gnus-unread ,(if (numberp number) (string-to-int gnus-tmp-number-of-unread) t) ! gnus-marked ,gnus-tmp-marked gnus-level ,gnus-tmp-level)) ;; Allow XEmacs to remove front-sticky text properties. (gnus-group-remove-excess-properties))) --- 4445,4451 ---- gnus-unread ,(if (numberp number) (string-to-int gnus-tmp-number-of-unread) t) ! gnus-marked ,gnus-tmp-marked-mark gnus-level ,gnus-tmp-level)) ;; Allow XEmacs to remove front-sticky text properties. (gnus-group-remove-excess-properties))) *************** *** 4421,4427 **** (when (> (length mode-string) max-len) (setq mode-string (substring mode-string 0 (- max-len 4)))) (prog1 ! (setq mode-line-buffer-identification mode-string) (set-buffer-modified-p t))))) (defun gnus-group-group-name () --- 4514,4520 ---- (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 () *************** *** 4633,4638 **** --- 4726,4737 ---- gnus-summary-expunge-below) (gnus-group-read-group all t))) + (defun gnus-group-visible-select-group (&optional all) + "Select the current group without hiding any articles." + (interactive "P") + (let ((gnus-inhibit-limiting t)) + (gnus-group-read-group all t))) + ;;;###autoload (defun gnus-fetch-group (group) "Start Gnus if necessary and enter GROUP. *************** *** 4667,4673 **** (gnus-group-read-group t t group) (error nil) (quit nil)) - ; (debug (current-buffer)) (not (equal (current-buffer) cur)))) (defun gnus-group-jump-to-group (group) --- 4766,4771 ---- *************** *** 5011,5027 **** (defun gnus-group-make-help-group () "Create the Gnus documentation group." (interactive) ! (let ((path (cons (concat installation-directory "etc/") load-path)) (name (gnus-group-prefixed-name "gnus-help" '(nndoc "gnus-help"))) ! file) (and (gnus-gethash name gnus-newsrc-hashtb) (error "Documentation group already exists")) ! (while (and path ! (not (file-exists-p ! (setq file (concat (file-name-as-directory (car path)) ! "gnus-tut.txt"))))) ! (setq path (cdr path))) ! (if (not path) (message "Couldn't find doc group") (gnus-group-make-group (gnus-group-real-name name) --- 5109,5129 ---- (defun gnus-group-make-help-group () "Create the Gnus documentation group." (interactive) ! (let ((path load-path) (name (gnus-group-prefixed-name "gnus-help" '(nndoc "gnus-help"))) ! file dir) (and (gnus-gethash name gnus-newsrc-hashtb) (error "Documentation group already exists")) ! (while path ! (setq dir (file-name-as-directory (expand-file-name (pop path))) ! file nil) ! (when (or (file-exists-p (setq file (concat dir "gnus-tut.txt"))) ! (file-exists-p ! (setq file (concat (file-name-directory ! (directory-file-name dir)) ! "etc/gnus-tut.txt")))) ! (setq path nil))) ! (if (not file) (message "Couldn't find doc group") (gnus-group-make-group (gnus-group-real-name name) *************** *** 5503,5518 **** The killed newsgroups can be yanked by using \\[gnus-group-yank-group]. However, only groups that were alive can be yanked; already killed groups or zombie groups can't be yanked. ! The return value is the name of the (last) group that was killed." (interactive "P") (let ((buffer-read-only nil) (groups (gnus-group-process-prefix n)) ! group entry level) ! (if (or t (< (length groups) 10)) ;; This is faster when there are few groups. (while groups ! (setq group (car groups) ! groups (cdr groups)) (gnus-group-remove-mark group) (setq level (gnus-group-group-level)) (gnus-delete-line) --- 5605,5620 ---- The killed newsgroups can be yanked by using \\[gnus-group-yank-group]. However, only groups that were alive can be yanked; already killed groups or zombie groups can't be yanked. ! The return value is the name of the group that was killed, or a list ! of groups killed." (interactive "P") (let ((buffer-read-only nil) (groups (gnus-group-process-prefix n)) ! group entry level out) ! (if (< (length groups) 10) ;; This is faster when there are few groups. (while groups ! (push (setq group (pop groups)) out) (gnus-group-remove-mark group) (setq level (gnus-group-group-level)) (gnus-delete-line) *************** *** 5525,5548 **** (if entry entry group) gnus-level-killed (if entry nil level))) ;; If there are lots and lots of groups to be killed, we use ;; this thing instead. ! ;; !!! Not written. ! ) ! (gnus-group-position-point) ! group)) (defun gnus-group-yank-group (&optional arg) "Yank the last newsgroups killed with \\[gnus-group-kill-group], inserting it before the current newsgroup. The numeric ARG specifies ! how many newsgroups are to be yanked. The name of the (last) ! newsgroup yanked is returned." (interactive "p") ! (if (not arg) (setq arg 1)) ! (let (info group prev) ! (while (>= (setq arg (1- arg)) 0) ! (if (not (setq info (car gnus-list-of-killed-groups))) (error "No more newsgroups to yank")) ! (setq group (nth 1 info)) ;; Find which newsgroup to insert this one before - search ;; backward until something suitable is found. If there are no ;; other newsgroups in this buffer, just make this newsgroup the --- 5627,5659 ---- (if entry entry group) gnus-level-killed (if entry nil level))) ;; If there are lots and lots of groups to be killed, we use ;; this thing instead. ! (let (entry) ! (setq groups (nreverse groups)) ! (while groups ! (gnus-group-remove-mark (car groups)) ! (gnus-delete-line) ! (setq entry (gnus-gethash (pop groups) gnus-newsrc-hashtb)) ! (push (cons (car entry) (nth 2 entry)) ! gnus-list-of-killed-groups) ! (setcdr (cdr entry) (cdr (cdr (cdr entry))))) ! (gnus-make-hashtable-from-newsrc-alist))) ! (gnus-group-position-point) ! (if (< (length out) 2) (car out) (nreverse out)))) (defun gnus-group-yank-group (&optional arg) "Yank the last newsgroups killed with \\[gnus-group-kill-group], inserting it before the current newsgroup. The numeric ARG specifies ! how many newsgroups are to be yanked. The name of the newsgroup yanked ! is returned, or (if several groups are yanked) a list of yanked groups ! is returned." (interactive "p") ! (setq arg (or arg 1)) ! (let (info group prev out) ! (while (>= (decf arg) 0) ! (if (not (setq info (pop gnus-list-of-killed-groups))) (error "No more newsgroups to yank")) ! (push (setq group (nth 1 info)) out) ;; Find which newsgroup to insert this one before - search ;; backward until something suitable is found. If there are no ;; other newsgroups in this buffer, just make this newsgroup the *************** *** 5552,5563 **** info (nth 2 info) gnus-level-killed (and prev (gnus-gethash prev gnus-newsrc-hashtb)) t) ! (gnus-group-insert-group-line-info group) ! (setq gnus-list-of-killed-groups ! (cdr gnus-list-of-killed-groups))) (forward-line -1) (gnus-group-position-point) ! group)) (defun gnus-group-list-all-groups (&optional arg) "List all newsgroups with level ARG or lower. --- 5663,5699 ---- info (nth 2 info) gnus-level-killed (and prev (gnus-gethash prev gnus-newsrc-hashtb)) t) ! (gnus-group-insert-group-line-info group)) (forward-line -1) (gnus-group-position-point) ! (if (< (length out) 2) (car out) (nreverse out)))) ! ! (defun gnus-group-kill-level (level) ! "Kill all groups that is on a certain LEVEL." ! (interactive "nKill all groups on level: ") ! (cond ! ((= level gnus-level-zombie) ! (setq gnus-killed-list ! (nconc gnus-zombie-list gnus-killed-list)) ! (setq gnus-zombie-list nil)) ! ((and (< level gnus-level-zombie) ! (> level 0) ! (or gnus-expert-user ! (gnus-yes-or-no-p ! (format ! "Do you really want to kill all groups on level %d? " ! level)))) ! (let* ((prev gnus-newsrc-alist) ! (alist (cdr prev))) ! (while alist ! (if (= (gnus-info-level level) level) ! (setcdr prev (cdr alist)) ! (setq prev alist)) ! (setq alist (cdr alist))) ! (gnus-make-hashtable-from-newsrc-alist) ! (gnus-group-list-groups))) ! (t ! (error "Can't kill; illegal level: %d" level)))) (defun gnus-group-list-all-groups (&optional arg) "List all newsgroups with level ARG or lower. *************** *** 5641,5646 **** --- 5777,5789 ---- (setq groups (cdr groups))) (goto-char (point-min)))) + (defun gnus-activate-all-groups (level) + "Activate absolutely all groups." + (interactive (list 7)) + (let ((gnus-activate-level level) + (gnus-activate-foreign-newsgroups level)) + (gnus-group-get-new-news))) + (defun gnus-group-get-new-news (&optional arg) "Get newly arrived articles. If ARG is a number, it specifies which levels you are interested in *************** *** 5662,5670 **** (if (and gnus-read-active-file (not arg)) (progn (gnus-read-active-file) ! (gnus-get-unread-articles (or arg (1+ gnus-level-subscribed)))) (let ((gnus-read-active-file (if arg nil gnus-read-active-file))) ! (gnus-get-unread-articles (or arg (1+ gnus-level-subscribed))))) (gnus-group-list-groups)) (defun gnus-group-get-new-news-this-group (&optional n) --- 5805,5813 ---- (if (and gnus-read-active-file (not arg)) (progn (gnus-read-active-file) ! (gnus-get-unread-articles arg)) (let ((gnus-read-active-file (if arg nil gnus-read-active-file))) ! (gnus-get-unread-articles arg))) (gnus-group-list-groups)) (defun gnus-group-get-new-news-this-group (&optional n) *************** *** 5904,5910 **** (defun gnus-group-clear-dribble () "Clear all information from the dribble buffer." (interactive) ! (gnus-dribble-clear)) (defun gnus-group-exit () "Quit reading news after updating .newsrc.eld and .newsrc. --- 6047,6054 ---- (defun gnus-group-clear-dribble () "Clear all information from the dribble buffer." (interactive) ! (gnus-dribble-clear) ! (gnus-message 7 "Cleared dribble buffer")) (defun gnus-group-exit () "Quit reading news after updating .newsrc.eld and .newsrc. *************** *** 6079,6086 **** (erase-buffer)) (gnus-browse-mode) (setq mode-line-buffer-identification ! (format ! "Gnus Browse Server {%s:%s}" (car method) (car (cdr method)))) (save-excursion (set-buffer nntp-server-buffer) (let ((cur (current-buffer))) --- 6223,6231 ---- (erase-buffer)) (gnus-browse-mode) (setq mode-line-buffer-identification ! (list ! (format ! "Gnus: %%b {%s:%s}" (car method) (car (cdr method))))) (save-excursion (set-buffer nntp-server-buffer) (let ((cur (current-buffer))) *************** *** 6357,6362 **** --- 6502,6509 ---- (define-key gnus-summary-mode-map "v" 'gnus-summary-verbose-headers) (define-key gnus-summary-mode-map "\C-c\C-b" 'gnus-bug) + (define-key gnus-summary-mode-map "*" 'gnus-cache-enter-article) + (define-key gnus-summary-mode-map "\M-*" 'gnus-cache-remove-article) ;; Sort of orthogonal keymap (define-prefix-command 'gnus-summary-mark-map) *************** *** 6404,6409 **** --- 6551,6557 ---- (define-key gnus-summary-limit-map "v" 'gnus-summary-limit-to-score) (define-key gnus-summary-limit-map "D" 'gnus-summary-limit-include-dormant) (define-key gnus-summary-limit-map "d" 'gnus-summary-limit-exclude-dormant) + ; (define-key gnus-summary-limit-map "t" 'gnus-summary-limit-exclude-thread) (define-key gnus-summary-mark-map "E" 'gnus-summary-limit-include-expunged) (define-key gnus-summary-limit-map "c" 'gnus-summary-limit-exclude-childless-dormant) *************** *** 6788,6796 **** '(progn (gnus-summary-skip-intangible) (or (get-text-property (point) 'gnus-number) ! (progn ! (forward-line -1) ! gnus-newsgroup-end)))) (defmacro gnus-summary-article-header (&optional number) `(gnus-data-header (gnus-data-find --- 6936,6942 ---- '(progn (gnus-summary-skip-intangible) (or (get-text-property (point) 'gnus-number) ! (gnus-summary-last-subject)))) (defmacro gnus-summary-article-header (&optional number) `(gnus-data-header (gnus-data-find *************** *** 6936,6942 **** --- 7082,7092 ---- (if (< gnus-tmp-score gnus-summary-default-score) gnus-score-below-mark gnus-score-over-mark))) (gnus-tmp-replied (cond (gnus-tmp-process gnus-process-mark) + ((memq gnus-tmp-current gnus-newsgroup-cached) + gnus-cached-mark) (gnus-tmp-replied gnus-replied-mark) + ((memq gnus-tmp-current gnus-newsgroup-saved) + gnus-saved-mark) (t gnus-unread-mark))) (gnus-tmp-from (mail-header-from gnus-tmp-header)) (gnus-tmp-name *************** *** 7044,7050 **** ;; This summary buffer exists already, so we just select it. ((not new-group) (gnus-set-global-variables) ! (gnus-kill-buffer kill-buffer) (gnus-configure-windows 'summary 'force) (gnus-set-mode-line 'summary) (gnus-summary-position-point) --- 7194,7200 ---- ;; This summary buffer exists already, so we just select it. ((not new-group) (gnus-set-global-variables) ! (gnus-kill-or-deaden-summary kill-buffer) (gnus-configure-windows 'summary 'force) (gnus-set-mode-line 'summary) (gnus-summary-position-point) *************** *** 7074,7080 **** (and (eq major-mode 'gnus-summary-mode) (not (equal (current-buffer) kill-buffer)) (kill-buffer (current-buffer))) ! (gnus-kill-buffer kill-buffer) (if (not quit-config) (progn (set-buffer gnus-group-buffer) --- 7224,7230 ---- (and (eq major-mode 'gnus-summary-mode) (not (equal (current-buffer) kill-buffer)) (kill-buffer (current-buffer))) ! (gnus-kill-or-deaden-summary kill-buffer) (if (not quit-config) (progn (set-buffer gnus-group-buffer) *************** *** 7124,7130 **** ;; This newsgroup is empty. (gnus-summary-catchup-and-exit nil t) ;Without confirmations. (gnus-message 6 "No unread news") ! (gnus-kill-buffer kill-buffer) ;; Return nil from this function. nil) ;; Hide conversation thread subtrees. We cannot do this in --- 7274,7280 ---- ;; This newsgroup is empty. (gnus-summary-catchup-and-exit nil t) ;Without confirmations. (gnus-message 6 "No unread news") ! (gnus-kill-or-deaden-summary kill-buffer) ;; Return nil from this function. nil) ;; Hide conversation thread subtrees. We cannot do this in *************** *** 7150,7156 **** ;; If we are in async mode, we send some info to the backend. (when gnus-newsgroup-async (gnus-request-asynchronous gnus-newsgroup-name gnus-newsgroup-data)) ! (gnus-kill-buffer kill-buffer) (when (get-buffer-window gnus-group-buffer) ;; Gotta use windows, because recenter does wierd stuff if ;; the current buffer ain't the displayed window. --- 7300,7306 ---- ;; If we are in async mode, we send some info to the backend. (when gnus-newsgroup-async (gnus-request-asynchronous gnus-newsgroup-name gnus-newsgroup-data)) ! (gnus-kill-or-deaden-summary kill-buffer) (when (get-buffer-window gnus-group-buffer) ;; Gotta use windows, because recenter does wierd stuff if ;; the current buffer ain't the displayed window. *************** *** 7420,7466 **** (list 'byte-code "\10\211:\203\17\0\211@;\203\16\0A@@\207" ; (vector thread) 2)) (defun gnus-thread-sort-by-number (h1 h2) "Sort threads by root article number." ! (< (mail-header-number (gnus-thread-header h1)) ! (mail-header-number (gnus-thread-header h2)))) ! (defun gnus-thread-sort-by-author (h1 h2) ! "Sort threads by root author." (string-lessp (let ((extract (funcall gnus-extract-address-components ! (mail-header-from (gnus-thread-header h1))))) (or (car extract) (cdr extract))) (let ((extract (funcall gnus-extract-address-components ! (mail-header-from (gnus-thread-header h2))))) (or (car extract) (cdr extract))))) (defun gnus-thread-sort-by-subject (h1 h2) "Sort threads by root subject." (string-lessp ! (downcase (gnus-simplify-subject-re ! (mail-header-subject (gnus-thread-header h1)))) ! (downcase (gnus-simplify-subject-re ! (mail-header-subject (gnus-thread-header h2)))))) (defun gnus-thread-sort-by-date (h1 h2) "Sort threads by root article date." ! (string-lessp ! (gnus-sortable-date (mail-header-date (gnus-thread-header h1))) ! (gnus-sortable-date (mail-header-date (gnus-thread-header h2))))) ! (defun gnus-thread-sort-by-score (h1 h2) ! "Sort threads by root article score. Unscored articles will be counted as having a score of zero." ! (> (or (cdr (assq (mail-header-number (gnus-thread-header h1)) gnus-newsgroup-scored)) gnus-summary-default-score 0) ! (or (cdr (assq (mail-header-number (gnus-thread-header h2)) gnus-newsgroup-scored)) gnus-summary-default-score 0))) (defun gnus-thread-sort-by-total-score (h1 h2) "Sort threads by the sum of all scores in the thread. Unscored articles will be counted as having a score of zero." --- 7570,7639 ---- (list 'byte-code "\10\211:\203\17\0\211@;\203\16\0A@@\207" ; (vector thread) 2)) + (defsubst gnus-article-sort-by-number (h1 h2) + "Sort articles by article number." + (< (mail-header-number h1) + (mail-header-number h2))) + (defun gnus-thread-sort-by-number (h1 h2) "Sort threads by root article number." ! (gnus-article-sort-by-number ! (gnus-thread-header h1) (gnus-thread-header h2))) ! (defsubst gnus-article-sort-by-author (h1 h2) ! "Sort articles by root author." (string-lessp (let ((extract (funcall gnus-extract-address-components ! (mail-header-from h1)))) (or (car extract) (cdr extract))) (let ((extract (funcall gnus-extract-address-components ! (mail-header-from h2)))) (or (car extract) (cdr extract))))) + (defun gnus-thread-sort-by-author (h1 h2) + "Sort threads by root author." + (gnus-article-sort-by-author + (gnus-thread-header h1) (gnus-thread-header h2))) + + (defsubst gnus-article-sort-by-subject (h1 h2) + "Sort articles by root subject." + (string-lessp + (downcase (gnus-simplify-subject-re (mail-header-subject h1))) + (downcase (gnus-simplify-subject-re (mail-header-subject h2))))) + (defun gnus-thread-sort-by-subject (h1 h2) "Sort threads by root subject." + (gnus-article-sort-by-subject + (gnus-thread-header h1) (gnus-thread-header h2))) + + (defsubst gnus-article-sort-by-date (h1 h2) + "Sort articles by root article date." (string-lessp ! (gnus-sortable-date (mail-header-date h1)) ! (gnus-sortable-date (mail-header-date h2)))) (defun gnus-thread-sort-by-date (h1 h2) "Sort threads by root article date." ! (gnus-article-sort-by-date ! (gnus-thread-header h1) (gnus-thread-header h2))) ! (defsubst gnus-article-sort-by-score (h1 h2) ! "Sort articles by root article score. Unscored articles will be counted as having a score of zero." ! (> (or (cdr (assq (mail-header-number h1) gnus-newsgroup-scored)) gnus-summary-default-score 0) ! (or (cdr (assq (mail-header-number h2) gnus-newsgroup-scored)) gnus-summary-default-score 0))) + (defun gnus-thread-sort-by-score (h1 h2) + "Sort threads by root article score." + (gnus-article-sort-by-score + (gnus-thread-header h1) (gnus-thread-header h2))) + (defun gnus-thread-sort-by-total-score (h1 h2) "Sort threads by the sum of all scores in the thread. Unscored articles will be counted as having a score of zero." *************** *** 7696,7701 **** --- 7869,7876 ---- gnus-tmp-replied (cond ((memq number gnus-newsgroup-processable) gnus-process-mark) + ((memq number gnus-newsgroup-cached) + gnus-cached-mark) ((memq number gnus-newsgroup-replied) gnus-replied-mark) (t gnus-unread-mark)) *************** *** 7948,7954 **** (types '((marked . tick) (replied . reply) (expirable . expire) (killed . killed) (bookmarks . bookmark) (dormant . dormant) ! (scored . score))) (uncompressed '(score bookmark)) marks var articles article mark) --- 8123,8129 ---- (types '((marked . tick) (replied . reply) (expirable . expire) (killed . killed) (bookmarks . bookmark) (dormant . dormant) ! (scored . score) (saved . save))) (uncompressed '(score bookmark)) marks var articles article mark) *************** *** 7965,7971 **** ;; All articles have to be subsets of the active articles. (cond ;; Adjust "simple" lists. ! ((memq mark '(tick dormant expirable reply killed)) (while articles (when (or (< (setq article (pop articles)) min) (> article max)) (set var (delq article (symbol-value var)))))) --- 8140,8146 ---- ;; All articles have to be subsets of the active articles. (cond ;; Adjust "simple" lists. ! ((memq mark '(tick dormant expirable reply killed save)) (while articles (when (or (< (setq article (pop articles)) min) (> article max)) (set var (delq article (symbol-value var)))))) *************** *** 7981,7987 **** (let ((types '((marked . tick) (replied . reply) (expirable . expire) (killed . killed) (bookmarks . bookmark) (dormant . dormant) ! (scored . score))) (info (gnus-get-info gnus-newsgroup-name)) (uncompressed '(score bookmark killed)) var type list newmarked symbol) --- 8156,8162 ---- (let ((types '((marked . tick) (replied . reply) (expirable . expire) (killed . killed) (bookmarks . bookmark) (dormant . dormant) ! (scored . score) (saved . save))) (info (gnus-get-info gnus-newsgroup-name)) (uncompressed '(score bookmark killed)) var type list newmarked symbol) *************** *** 8081,8087 **** ;; Pad the mode string a bit. (setq mode-string (format (format "%%-%ds" max-len) mode-string)))) ;; Update the mode line. ! (setq mode-line-buffer-identification mode-string) (set-buffer-modified-p t)))) (defun gnus-create-xref-hashtb (from-newsgroup headers unreads) --- 8256,8262 ---- ;; Pad the mode string a bit. (setq mode-string (format (format "%%-%ds" max-len) mode-string)))) ;; Update the mode line. ! (setq mode-line-buffer-identification (list mode-string)) (set-buffer-modified-p t)))) (defun gnus-create-xref-hashtb (from-newsgroup headers unreads) *************** *** 8610,8624 **** (not (gnus-data-unread-p (car arts)))) (setq arts (cdr arts))) (when (setq result ! (if unread ! (progn ! (while arts ! (when (gnus-data-unread-p (car arts)) ! (setq result (car arts) ! arts nil)) ! (setq arts (cdr arts))) ! result) ! (car arts))) (goto-char (gnus-data-pos result)) (gnus-data-number result))))) --- 8785,8799 ---- (not (gnus-data-unread-p (car arts)))) (setq arts (cdr arts))) (when (setq result ! (if unread ! (progn ! (while arts ! (when (gnus-data-unread-p (car arts)) ! (setq result (car arts) ! arts nil)) ! (setq arts (cdr arts))) ! result) ! (car arts))) (goto-char (gnus-data-pos result)) (gnus-data-number result))))) *************** *** 8823,8829 **** (let ((current-subject (gnus-summary-article-number)) (group gnus-newsgroup-name)) (setq gnus-newsgroup-begin nil) ! (gnus-summary-exit t) ;; We have to adjust the point of group mode buffer because the ;; current point was moved to the next unread newsgroup by ;; exiting. --- 8998,9004 ---- (let ((current-subject (gnus-summary-article-number)) (group gnus-newsgroup-name)) (setq gnus-newsgroup-begin nil) ! (gnus-summary-exit) ;; We have to adjust the point of group mode buffer because the ;; current point was moved to the next unread newsgroup by ;; exiting. *************** *** 8896,8902 **** ;; Make all changes in this group permanent. (gnus-summary-update-info) (set-buffer buf) ! (and gnus-use-cache (gnus-cache-possibly-remove-articles)) ;; Make sure where I was, and go to next newsgroup. (set-buffer gnus-group-buffer) (or quit-config --- 9071,9079 ---- ;; Make all changes in this group permanent. (gnus-summary-update-info) (set-buffer buf) ! (when gnus-use-cache ! (gnus-cache-possibly-remove-articles) ! (gnus-cache-save-buffers)) ;; Make sure where I was, and go to next newsgroup. (set-buffer gnus-group-buffer) (or quit-config *************** *** 8905,8925 **** (gnus-group-next-unread-group 1))) (if temporary nil ;Nothing to do. ! ;; We set all buffer-local variables to nil. It is unclear why ! ;; this is needed, but if we don't, buffer-local variables are ! ;; not garbage-collected, it seems. This would the lead to en ! ;; ever-growing Emacs. ! (set-buffer buf) ! (gnus-summary-clear-local-variables) ! ;; We clear the global counterparts of the buffer-local ! ;; variables as well, just to be on the safe side. ! (gnus-configure-windows 'group 'force) ! (gnus-summary-clear-local-variables) ! ;; Return to group mode buffer. ! (if (eq mode 'gnus-summary-mode) ! (gnus-kill-buffer buf)) ! (if (get-buffer gnus-article-buffer) ! (bury-buffer gnus-article-buffer)) (setq gnus-current-select-method gnus-select-method) (pop-to-buffer gnus-group-buffer) ;; Clear the current group name. --- 9082,9102 ---- (gnus-group-next-unread-group 1))) (if temporary nil ;Nothing to do. ! (if (not gnus-kill-summary-on-exit) ! (gnus-deaden-summary) ! ;; We set all buffer-local variables to nil. It is unclear why ! ;; this is needed, but if we don't, buffer-local variables are ! ;; not garbage-collected, it seems. This would the lead to en ! ;; ever-growing Emacs. ! (set-buffer buf) ! (gnus-summary-clear-local-variables) ! ;; We clear the global counterparts of the buffer-local ! ;; variables as well, just to be on the safe side. ! (gnus-configure-windows 'group 'force) ! (gnus-summary-clear-local-variables) ! ;; Return to group mode buffer. ! (if (eq mode 'gnus-summary-mode) ! (gnus-kill-buffer buf))) (setq gnus-current-select-method gnus-select-method) (pop-to-buffer gnus-group-buffer) ;; Clear the current group name. *************** *** 8946,8963 **** (when (or no-questions gnus-expert-user (gnus-y-or-n-p "Do you really wanna quit reading this group? ")) ! (gnus-close-group group) ! (gnus-summary-clear-local-variables) ! (set-buffer gnus-group-buffer) ! (gnus-summary-clear-local-variables) ;; Return to the group buffer. (gnus-configure-windows 'group 'force) ;; Clear the current group name. (setq gnus-newsgroup-name nil) - (when (get-buffer gnus-summary-buffer) - (kill-buffer gnus-summary-buffer)) - (when (get-buffer gnus-article-buffer) - (bury-buffer gnus-article-buffer)) (when (equal (gnus-group-group-name) group) (gnus-group-next-unread-group 1)) (when quit-config --- 9123,9140 ---- (when (or no-questions gnus-expert-user (gnus-y-or-n-p "Do you really wanna quit reading this group? ")) ! (if (not gnus-kill-summary-on-exit) ! (gnus-deaden-summary) ! (gnus-close-group group) ! (gnus-summary-clear-local-variables) ! (set-buffer gnus-group-buffer) ! (gnus-summary-clear-local-variables) ! (when (get-buffer gnus-summary-buffer) ! (kill-buffer gnus-summary-buffer))) ;; Return to the group buffer. (gnus-configure-windows 'group 'force) ;; Clear the current group name. (setq gnus-newsgroup-name nil) (when (equal (gnus-group-group-name) group) (gnus-group-next-unread-group 1)) (when quit-config *************** *** 8968,8973 **** --- 9145,9222 ---- (gnus-set-global-variables)) (gnus-configure-windows (cdr quit-config))))))) + ;;; Dead summaries. + + (defvar gnus-dead-summary-mode-map nil) + + (if gnus-dead-summary-mode-map + nil + (setq gnus-dead-summary-map (make-keymap)) + (suppress-keymap gnus-dead-summary-map) + (substitute-key-definition + 'undefined 'gnus-summary-wake-up-the-dead gnus-dead-summary-map) + (let ((keys '("\C-d" "\r" "\177"))) + (while keys + (define-key gnus-dead-summary-map + (pop keys) 'gnus-summary-wake-up-the-dead)))) + + (defvar gnus-dead-summary-mode nil + "Minor mode for Gnus summary buffers.") + + (defun gnus-dead-summary-mode (&optional arg) + "Minor mode for Gnus summary buffers." + (interactive "P") + (when (eq major-mode 'gnus-summary-mode) + (make-local-variable 'gnus-dead-summary-mode) + (setq gnus-dead-summary-mode + (if (null arg) (not gnus-dead-summary-mode) + (> (prefix-numeric-value arg) 0))) + (when gnus-dead-summary-mode + (unless (assq 'gnus-dead-summary-mode minor-mode-alist) + (push '(gnus-dead-summary-mode " Dead") minor-mode-alist)) + (unless (assq 'gnus-dead-summary-mode minor-mode-map-alist) + (push (cons 'gnus-dead-summary-mode gnus-dead-summary-mode-map) + minor-mode-map-alist))))) + + (defun gnus-deaden-summary () + "Make the current summary buffer into a dead summary buffer." + ;; Kill any previous dead summary buffer. + (when (and gnus-dead-summary + (buffer-name gnus-dead-summary)) + (save-excursion + (set-buffer gnus-dead-summary) + (when gnus-dead-summary-mode + (kill-buffer (current-buffer))))) + ;; Make this the current dead summary. + (setq gnus-dead-summary (current-buffer)) + (gnus-dead-summary-mode 1) + (let ((name (buffer-name))) + (when (string-match "Summary" name) + (rename-buffer + (concat (substring name 0 (match-beginning 0)) "Dead " + (substring name (match-beginning 0))) t)))) + + (defun gnus-kill-or-deaden-summary (buffer) + "Kill or deaden the summary BUFFER." + (cond (gnus-kill-summary-on-exit + (gnus-kill-buffer buffer)) + ((and (get-buffer buffer) + (buffer-name (get-buffer buffer))) + (save-excursion + (set-buffer buffer) + (gnus-deaden-summary))))) + + (defun gnus-summary-wake-up-the-dead (&rest args) + "Wake up the dead summary buffer." + (interactive) + (gnus-dead-summary-mode -1) + (let ((name (buffer-name))) + (when (string-match "Dead " name) + (rename-buffer + (concat (substring name 0 (match-beginning 0)) + (substring name (match-end 0))) t))) + (gnus-message 3 "This dead summary is now alive again")) + ;; Suggested by Andrew Eskilsson . (defun gnus-summary-fetch-faq (&optional faq-dir) "Fetch the FAQ for the current group. *************** *** 9239,9246 **** ;; For some reason, the group window gets selected. We change ;; it back. (select-window (get-buffer-window (current-buffer))) - ;; Keep just the event type of CMD. - ;(and (listp cmd) (setq cmd (car cmd))) ;; Select next unread newsgroup automagically. (cond ((not gnus-auto-select-next) --- 9488,9493 ---- *************** *** 9257,9297 **** "exiting")) (gnus-summary-next-group nil group backward))) (t ! (let ((keystrokes '(?\C-n ?\C-p)) ! key) ! (while (or (null key) (memq key keystrokes)) ! (gnus-message ! 7 "No more%s articles%s" (if unread " unread" "") ! (if (and group ! (not (gnus-ephemeral-group-p gnus-newsgroup-name))) ! (format " (Type %s for %s [%s])" ! (single-key-description cmd) group ! (car (gnus-gethash group gnus-newsrc-hashtb))) ! (format " (Type %s to exit %s)" ! (single-key-description cmd) ! gnus-newsgroup-name))) ! ;; Confirm auto selection. ! (let* ((event (read-char-exclusive))) ! (setq key (if (listp event) (car event) event)) ! (if (memq key keystrokes) ! (let ((obuf (current-buffer))) ! (switch-to-buffer gnus-group-buffer) ! (and group ! (gnus-group-jump-to-group group)) ! (condition-case () ! (cond ((= key ?\C-n) ! (gnus-group-next-unread-group 1)) ! ((= key ?\C-p) ! (gnus-group-prev-unread-group 1))) ! (error (ding) nil)) ! (setq group (gnus-group-group-name)) ! (switch-to-buffer obuf))))) ! (if (equal key cmd) ! (if (or (not group) ! (gnus-ephemeral-group-p gnus-newsgroup-name)) ! (gnus-summary-exit) ! (gnus-summary-next-group nil group backward)) ! (execute-kbd-macro (char-to-string key))))))))))) (defun gnus-summary-next-unread-article () "Select unread article after current one." --- 9504,9555 ---- "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)) ! (?\C-p (gnus-group-prev-unread-group 1)))) ! keve key group ended) ! (while (not ended) ! (save-excursion ! (set-buffer gnus-group-buffer) ! (setq group (gnus-group-group-name))) ! (gnus-message ! 7 "No more%s articles%s" (if unread " unread" "") ! (if (and group ! (not (gnus-ephemeral-group-p gnus-newsgroup-name))) ! (format " (Type %s for %s [%s])" ! (single-key-description cmd) group ! (car (gnus-gethash group gnus-newsrc-hashtb))) ! (format " (Type %s to exit %s)" ! (single-key-description cmd) ! gnus-newsgroup-name))) ! ;; Confirm auto selection. ! (setq key (car (setq keve (gnus-read-event-char)))) ! (setq ended t) ! (cond ! ((assq key keystrokes) ! (let ((obuf (current-buffer))) ! (switch-to-buffer gnus-group-buffer) ! (and group ! (gnus-group-jump-to-group group)) ! (eval (car (cdr (assq key keystrokes)))) ! (setq group (gnus-group-group-name)) ! (switch-to-buffer obuf)) ! (setq ended nil)) ! ((equal key cmd) ! (if (or (not group) ! (gnus-ephemeral-group-p gnus-newsgroup-name)) ! (gnus-summary-exit) ! (gnus-summary-next-group nil group backward))) ! (t ! (push (cdr keve) unread-command-events)))))) ! ! (defun gnus-read-event-char () ! "Get the next event." ! (let ((event (read-event))) ! (cons (and (numberp event) event) event))) (defun gnus-summary-next-unread-article () "Select unread article after current one." *************** *** 9435,9440 **** --- 9693,9704 ---- (error "No unread articles")) (gnus-summary-position-point))) + (defun gnus-summary-last-subject () + "Go to the last displayed subject line in the group." + (let ((article (gnus-data-number (car (gnus-data-list t))))) + (when article + (gnus-summary-goto-subject article)))) + (defun gnus-summary-goto-article (article &optional all-headers force) "Fetch ARTICLE and display it if it exists. If ALL-HEADERS is non-nil, no header lines are hidden." *************** *** 9645,9664 **** This entails weeding out unwanted dormants, low-scored articles, fetch-old-headers verbiage, and so on." ;; Most groups have nothing to remove. ! (if (and (null gnus-newsgroup-dormant) ! (not (eq gnus-fetch-old-headers 'some)) ! (null gnus-summary-expunge-below)) () ; Do nothing. ! (setq gnus-newsgroup-limits ! (cons gnus-newsgroup-limit gnus-newsgroup-limits)) (setq gnus-newsgroup-limit nil) (mapatoms (lambda (node) ! (if (null (car (symbol-value node))) ! (let ((nodes (cdr (symbol-value node)))) ! (while nodes ! (gnus-summary-limit-children (car nodes)) ! (setq nodes (cdr nodes)))))) gnus-newsgroup-dependencies) (when (not gnus-newsgroup-limit) (setq gnus-newsgroup-limit (pop gnus-newsgroup-limits))) --- 9909,9933 ---- This entails weeding out unwanted dormants, low-scored articles, fetch-old-headers verbiage, and so on." ;; Most groups have nothing to remove. ! (if (or gnus-inhibit-limiting ! (and (null gnus-newsgroup-dormant) ! (not (eq gnus-fetch-old-headers 'some)) ! (null gnus-summary-expunge-below) ! (null gnus-thread-expunge-below))) () ; Do nothing. ! (push gnus-newsgroup-limit gnus-newsgroup-limits) (setq gnus-newsgroup-limit nil) (mapatoms (lambda (node) ! (unless (car (symbol-value node)) ! ;; These threads have no parents -- they are roots. ! (let ((nodes (cdr (symbol-value node)))) ! (while nodes ! (if (and gnus-thread-expunge-below ! (< (gnus-thread-total-score (car nodes)) ! gnus-thread-expunge-below)) ! (gnus-expunge-thread (pop nodes)) ! (gnus-summary-limit-children (pop nodes))))))) gnus-newsgroup-dependencies) (when (not gnus-newsgroup-limit) (setq gnus-newsgroup-limit (pop gnus-newsgroup-limits))) *************** *** 9672,9679 **** ;; working its way up towards the root. (let ((children (if (cdr thread) ! (apply '+ (mapcar (lambda (th) ! (gnus-summary-limit-children th)) (cdr thread))) 0)) (number (mail-header-number (car thread))) --- 9941,9947 ---- ;; working its way up towards the root. (let ((children (if (cdr thread) ! (apply '+ (mapcar 'gnus-summary-limit-children (cdr thread))) 0)) (number (mail-header-number (car thread))) *************** *** 9715,9720 **** --- 9983,10002 ---- (setq gnus-newsgroup-limit (cons number gnus-newsgroup-limit)) 1))) + (defun gnus-expunge-thread (thread) + "Mark all articles in THREAD as read." + (let* ((number (mail-header-number (car thread)))) + (incf gnus-newsgroup-expunged-tally) + ;; We also mark as read here, if that's wanted. + (setq gnus-newsgroup-unreads + (delq number gnus-newsgroup-unreads)) + (if gnus-newsgroup-auto-expire + (push number gnus-newsgroup-expirable) + (push (cons number gnus-low-score-mark) + gnus-newsgroup-reads))) + ;; Go recursively through all subthreads. + (mapcar 'gnus-expunge-thread (cdr thread))) + ;; Summary article oriented commands (defun gnus-summary-refer-parent-article (n) *************** *** 10051,10061 **** (goto-char (point-min)) (setq e (1- (or (search-forward "\n\n" nil t) (point-max))))) (insert-buffer-substring gnus-original-article-buffer 1 e) ! (let ((hook (delq 'gnus-article-hide-headers-if-wanted ! (delq 'gnus-article-hide-headers ! (copy-sequence gnus-article-display-hook)))) ! (gnus-inhibit-hiding t)) ! (run-hooks 'hook)) (if (or (not hidden) (and (numberp arg) (< arg 0))) (gnus-article-hide-headers))))) --- 10333,10340 ---- (goto-char (point-min)) (setq e (1- (or (search-forward "\n\n" nil t) (point-max))))) (insert-buffer-substring gnus-original-article-buffer 1 e) ! (let ((gnus-inhibit-hiding t)) ! (run-hooks 'gnus-article-display-hook)) (if (or (not hidden) (and (numberp arg) (< arg 0))) (gnus-article-hide-headers))))) *************** *** 10184,10189 **** --- 10463,10469 ---- (dormant . gnus-newsgroup-dormant) (expire . gnus-newsgroup-expirable) (bookmark . gnus-newsgroup-bookmarks) + (save . gnus-newsgroup-saved) (reply . gnus-newsgroup-replied))) (to-article (cdr art-group))) *************** *** 10323,10328 **** --- 10603,10609 ---- (dormant . gnus-newsgroup-dormant) (expire . gnus-newsgroup-expirable) (bookmark . gnus-newsgroup-bookmarks) + (save . gnus-newsgroup-saved) (reply . gnus-newsgroup-replied))) (to-article (cdr art-group))) *************** *** 10698,10707 **** "Mark ARTICLE replied and update the summary line." (setq gnus-newsgroup-replied (cons article gnus-newsgroup-replied)) (let ((buffer-read-only nil)) ! (if (gnus-summary-goto-subject article) ! (progn ! (gnus-summary-update-mark gnus-replied-mark 'replied) ! t)))) (defun gnus-summary-set-bookmark (article) "Set a bookmark in current article." --- 10979,10986 ---- "Mark ARTICLE replied and update the summary line." (setq gnus-newsgroup-replied (cons article gnus-newsgroup-replied)) (let ((buffer-read-only nil)) ! (when (gnus-summary-goto-subject article) ! (gnus-summary-update-secondary-mark article)))) (defun gnus-summary-set-bookmark (article) "Set a bookmark in current article." *************** *** 10760,10783 **** (setq gnus-newsgroup-processable (cons article (delq article gnus-newsgroup-processable))) ! (let ((buffer-read-only nil)) ! (if (gnus-summary-goto-subject article) ! (progn ! (gnus-summary-show-thread) ! (gnus-summary-update-mark gnus-process-mark 'replied) ! t)))) (defun gnus-summary-remove-process-mark (article) "Remove the process mark from ARTICLE and update the summary line." (setq gnus-newsgroup-processable (delq article gnus-newsgroup-processable)) ! (let ((buffer-read-only nil)) ! (if (gnus-summary-goto-subject article) ! (progn ! (gnus-summary-show-thread) ! (gnus-summary-update-mark ? 'replied) ! (if (memq article gnus-newsgroup-replied) ! (gnus-summary-update-mark gnus-replied-mark 'replied)) ! t)))) (defun gnus-summary-mark-forward (n &optional mark no-expire) "Mark N articles as read forwards. --- 11039,11060 ---- (setq gnus-newsgroup-processable (cons article (delq article gnus-newsgroup-processable))) ! (when (gnus-summary-goto-subject article) ! (gnus-summary-show-thread) ! (gnus-summary-update-secondary-mark article))) (defun gnus-summary-remove-process-mark (article) "Remove the process mark from ARTICLE and update the summary line." (setq gnus-newsgroup-processable (delq article gnus-newsgroup-processable)) ! (when (gnus-summary-goto-subject article) ! (gnus-summary-show-thread) ! (gnus-summary-update-secondary-mark article))) ! ! (defun gnus-summary-set-saved-mark (article) ! "Set the process mark on ARTICLE and update the summary line." ! (push article gnus-newsgroup-saved) ! (when (gnus-summary-goto-subject article) ! (gnus-summary-update-secondary-mark article))) (defun gnus-summary-mark-forward (n &optional mark no-expire) "Mark N articles as read forwards. *************** *** 10905,10910 **** --- 11182,11204 ---- (gnus-summary-update-mark mark 'unread) t)))) + (defun gnus-summary-update-secondary-mark (article) + "Update the secondary (read, process, cache) mark." + (gnus-summary-update-mark + (cond ((memq article gnus-newsgroup-processable) + gnus-process-mark) + ((memq article gnus-newsgroup-cached) + gnus-cached-mark) + ((memq article gnus-newsgroup-replied) + gnus-replied-mark) + ((memq article gnus-newsgroup-saved) + gnus-saved-mark) + (t gnus-unread-mark)) + 'replied) + (when (gnus-visual-p 'summary-highlight 'highlight) + (run-hooks 'gnus-summary-update-hook)) + t) + (defun gnus-summary-update-mark (mark type) (beginning-of-line) (let ((forward (cdr (assq type gnus-summary-mark-positions))) *************** *** 11196,11202 **** (interactive "P") (gnus-set-global-variables) (gnus-summary-catchup all) ! (gnus-summary-next-group)) ;; Thread-based commands. --- 11490,11496 ---- (interactive "P") (gnus-set-global-variables) (gnus-summary-catchup all) ! (gnus-summary-next-article t)) ;; Thread-based commands. *************** *** 11431,11530 **** "Sort summary buffer by article number. Argument REVERSE means reverse order." (interactive "P") ! (gnus-set-global-variables) ! (gnus-summary-sort ! ;; `gnus-summary-article-number' is a macro, and `sort-subr' wants ! ;; a function, so we wrap it. ! (cons (lambda () (gnus-summary-article-number)) ! 'gnus-thread-sort-by-number) reverse)) (defun gnus-summary-sort-by-author (&optional reverse) "Sort summary buffer by author name alphabetically. If case-fold-search is non-nil, case of letters is ignored. Argument REVERSE means reverse order." (interactive "P") ! (gnus-set-global-variables) ! (gnus-summary-sort ! (cons ! (lambda () ! (let* ((header (gnus-summary-article-header)) ! extract) ! (if (not (vectorp header)) ! "" ! (setq extract (funcall gnus-extract-address-components ! (mail-header-from header))) ! (concat (or (car extract) (cdr extract)) ! "\r" (mail-header-subject header))))) ! 'gnus-thread-sort-by-author) ! reverse)) (defun gnus-summary-sort-by-subject (&optional reverse) "Sort summary buffer by subject alphabetically. `Re:'s are ignored. If case-fold-search is non-nil, case of letters is ignored. Argument REVERSE means reverse order." (interactive "P") ! (gnus-set-global-variables) ! (gnus-summary-sort ! (cons ! (lambda () ! (let* ((header (gnus-summary-article-header)) ! extract) ! (if (not (vectorp header)) ! "" ! (setq extract (funcall gnus-extract-address-components ! (mail-header-from header))) ! (concat ! (downcase (gnus-simplify-subject (gnus-summary-article-subject) t)) ! "\r" (or (car extract) (cdr extract)))))) ! 'gnus-thread-sort-by-subject) ! reverse)) (defun gnus-summary-sort-by-date (&optional reverse) "Sort summary buffer by date. Argument REVERSE means reverse order." (interactive "P") ! (gnus-set-global-variables) ! (gnus-summary-sort ! (cons ! (lambda () ! (gnus-sortable-date ! (mail-header-date ! (gnus-summary-article-header)))) ! 'gnus-thread-sort-by-date) ! reverse)) (defun gnus-summary-sort-by-score (&optional reverse) "Sort summary buffer by score. Argument REVERSE means reverse order." (interactive "P") ! (gnus-set-global-variables) ! (gnus-summary-sort ! (cons (lambda () (gnus-summary-article-score)) ! 'gnus-thread-sort-by-score) ! (not reverse))) (defun gnus-summary-sort (predicate reverse) ! "Sort summary buffer by PREDICATE. REVERSE means reverse order. ! PREDICATE is a cons of `(unthreaded-func . threaded-func)'." ! (let (buffer-read-only) ! (if (not gnus-show-threads) ! ;; We do untreaded sorting... ! (progn ! (goto-char (point-min)) ! (sort-subr reverse 'forward-line 'end-of-line (car predicate)) ! (gnus-data-compute-positions)) ! ;; ... or we do threaded sorting. ! (let ((gnus-thread-sort-functions (list (cdr predicate))) ! (gnus-summary-prepare-hook nil)) ! ;; We do that by simply regenerating the threads. ! (gnus-summary-prepare) ! ;; Hide subthreads if needed. ! (when gnus-thread-hide-subtree ! (gnus-summary-hide-all-threads)))) ! ;; If in async mode, we send some info to the backend. ! (when gnus-newsgroup-async ! (gnus-request-asynchronous ! gnus-newsgroup-name gnus-newsgroup-data)))) (defun gnus-sortable-date (date) "Make sortable string by string-lessp from DATE. --- 11725,11776 ---- "Sort summary buffer by article number. Argument REVERSE means reverse order." (interactive "P") ! (gnus-summary-sort 'number reverse)) (defun gnus-summary-sort-by-author (&optional reverse) "Sort summary buffer by author name alphabetically. If case-fold-search is non-nil, case of letters is ignored. Argument REVERSE means reverse order." (interactive "P") ! (gnus-summary-sort 'author reverse)) (defun gnus-summary-sort-by-subject (&optional reverse) "Sort summary buffer by subject alphabetically. `Re:'s are ignored. If case-fold-search is non-nil, case of letters is ignored. Argument REVERSE means reverse order." (interactive "P") ! (gnus-summary-sort 'subject reverse)) (defun gnus-summary-sort-by-date (&optional reverse) "Sort summary buffer by date. Argument REVERSE means reverse order." (interactive "P") ! (gnus-summary-sort 'date reverse)) (defun gnus-summary-sort-by-score (&optional reverse) "Sort summary buffer by score. Argument REVERSE means reverse order." (interactive "P") ! (gnus-summary-sort 'score reverse)) (defun gnus-summary-sort (predicate reverse) ! "Sort summary buffer by PREDICATE. REVERSE means reverse order." ! (gnus-set-global-variables) ! (let* ((gnus-thread-sort-functions ! (list (intern (format "gnus-thread-sort-by-%s" predicate)))) ! (gnus-article-sort-functions ! (list (intern (format "gnus-article-sort-by-%s" predicate)))) ! (buffer-read-only) ! (gnus-summary-prepare-hook nil)) ! ;; We do the sorting by regenerating the threads. ! (gnus-summary-prepare) ! ;; Hide subthreads if needed. ! (when (and gnus-show-threads gnus-thread-hide-subtree) ! (gnus-summary-hide-all-threads))) ! ;; If in async mode, we send some info to the backend. ! (when gnus-newsgroup-async ! (gnus-request-asynchronous ! gnus-newsgroup-name gnus-newsgroup-data))) (defun gnus-sortable-date (date) "Make sortable string by string-lessp from DATE. *************** *** 11541,11547 **** ;; Summary saving commands. ! (defun gnus-summary-save-article (&optional n) "Save the current article using the default saver function. If N is a positive number, save the N next articles. If N is a negative number, save the N previous articles. --- 11787,11793 ---- ;; Summary saving commands. ! (defun gnus-summary-save-article (&optional n not-saved) "Save the current article using the default saver function. If N is a positive number, save the N next articles. If N is a negative number, save the N previous articles. *************** *** 11551,11597 **** (interactive "P") (gnus-set-global-variables) (let ((articles (gnus-summary-work-articles n)) ! file) (while articles ! (let ((header (gnus-summary-article-header (car articles)))) ! (if (vectorp header) ! (progn ! (save-window-excursion ! (gnus-summary-select-article t nil nil (car articles))) ! (or gnus-save-all-headers ! ;; Remove headers accoring to `gnus-saved-headers'. ! (let ((gnus-visible-headers ! (or gnus-saved-headers gnus-visible-headers))) ! (gnus-article-hide-headers t))) ! ;; Remove any X-Gnus lines. ! (save-excursion ! (save-restriction ! (set-buffer gnus-article-buffer) ! (let ((buffer-read-only nil)) ! (goto-char (point-min)) ! (narrow-to-region (point) (or (search-forward "\n\n" nil t) ! (point-max))) ! (while (re-search-forward "^X-Gnus" nil t) ! (beginning-of-line) ! (delete-region (point) ! (progn (forward-line 1) (point)))) ! (widen)))) ! (save-window-excursion ! (if gnus-default-article-saver ! (setq file (funcall ! gnus-default-article-saver ! (cond ! ((not gnus-prompt-before-saving) ! 'default) ! ((eq gnus-prompt-before-saving 'always) ! nil) ! (t file)))) ! (error "No default saver is defined.")))) (if (assq 'name header) (gnus-copy-file (cdr (assq 'name header))) ! (gnus-message 1 "Article %d is unsaveable" (car articles))))) ! (gnus-summary-remove-process-mark (car articles)) ! (setq articles (cdr articles))) (gnus-summary-position-point) n)) --- 11797,11841 ---- (interactive "P") (gnus-set-global-variables) (let ((articles (gnus-summary-work-articles n)) ! file header article) (while articles ! (setq header (gnus-summary-article-header ! (setq article (pop articles)))) ! (if (not (vectorp header)) ! ;; This is a pseudo-article. (if (assq 'name header) (gnus-copy-file (cdr (assq 'name header))) ! (gnus-message 1 "Article %d is unsaveable" article)) ! ;; This is a real article. ! (save-window-excursion ! (gnus-summary-select-article t nil nil article)) ! (unless gnus-save-all-headers ! ;; Remove headers accoring to `gnus-saved-headers'. ! (let ((gnus-visible-headers ! (or gnus-saved-headers gnus-visible-headers))) ! (gnus-article-hide-headers t))) ! ;; Remove any X-Gnus lines. ! (save-excursion ! (set-buffer gnus-article-buffer) ! (save-restriction ! (let ((buffer-read-only nil)) ! (gnus-narrow-to-headers) ! (while (re-search-forward "^X-Gnus" nil t) ! (gnus-delete-line))))) ! (save-window-excursion ! (if (not gnus-default-article-saver) ! (error "No default saver is defined.") ! (setq file (funcall ! gnus-default-article-saver ! (cond ! ((not gnus-prompt-before-saving) ! 'default) ! ((eq gnus-prompt-before-saving 'always) ! nil) ! (t file)))))) ! (gnus-summary-remove-process-mark article) ! (unless not-saved ! (gnus-summary-set-saved-mark article)))) (gnus-summary-position-point) n)) *************** *** 11604,11610 **** (interactive "P") (gnus-set-global-variables) (let ((gnus-default-article-saver 'gnus-summary-save-in-pipe)) ! (gnus-summary-save-article arg)) (gnus-configure-windows 'pipe)) (defun gnus-summary-save-article-mail (&optional arg) --- 11848,11854 ---- (interactive "P") (gnus-set-global-variables) (let ((gnus-default-article-saver 'gnus-summary-save-in-pipe)) ! (gnus-summary-save-article arg t)) (gnus-configure-windows 'pipe)) (defun gnus-summary-save-article-mail (&optional arg) *************** *** 11653,11679 **** (defun gnus-read-save-file-name (prompt default-name) (let ((methods gnus-split-methods) ! split-name method) ;; Let the split methods have their say. (when gnus-split-methods (save-excursion (set-buffer gnus-original-article-buffer) ! (gnus-narrow-to-headers) ! (while methods ! (goto-char (point-min)) ! (setq method (pop methods)) ! (when (cond ((stringp (car method)) ! (condition-case () ! (re-search-forward (car method) nil t) ! (error nil))) ! ((gnus-functionp (car method)) ! (funcall (car method))) ! ((consp (car method)) ! (eval (car method)))) ! (setq split-name (cons (nth 1 methods) split-name)))) ! (widen))) (cond ! ;; No split name was found ((null split-name) (read-file-name (concat prompt " (default " (file-name-nondirectory default-name) ") ") --- 11897,11934 ---- (defun gnus-read-save-file-name (prompt default-name) (let ((methods gnus-split-methods) ! split-name method result match) ;; Let the split methods have their say. (when gnus-split-methods (save-excursion (set-buffer gnus-original-article-buffer) ! (save-restriction ! (gnus-narrow-to-headers) ! (while methods ! (goto-char (point-min)) ! (setq method (pop methods)) ! (setq match (pop method)) ! (when (cond ! ((stringp match) ! ;; Regular expression. ! (condition-case () ! (re-search-forward match nil t) ! (error nil))) ! ((gnus-functionp match) ! (save-restriction ! (widen) ! (setq result (funcall match gnus-newsgroup-name)))) ! ((consp match) ! (save-restriction ! (widen) ! (setq result (eval match))))) ! (setq split-name (append (cdr methods) split-name)) ! (cond ((stringp result) ! (push result split-name)) ! ((consp result) ! (setq split-name (append result split-name))))))))) (cond ! ;; No split name was found. ((null split-name) (read-file-name (concat prompt " (default " (file-name-nondirectory default-name) ") ") *************** *** 11694,11699 **** --- 11949,11960 ---- (car (car split-name)) result))))))) + (defun gnus-article-archive-name (group) + "Return the first instance of an \"Archive-name\" in the current buffer." + (let ((case-fold-search t)) + (when (re-search-forward "archive-name: *\\([^ \n\t]+\\)[ \t]*$" nil t) + (match-string 1)))) + (defun gnus-summary-save-in-rmail (&optional filename) "Append this article to Rmail file. Optional argument FILENAME specifies file name. *************** *** 11966,11971 **** --- 12227,12233 ---- (define-key gnus-article-mode-map gnus-mouse-2 'gnus-article-push-button) (define-key gnus-article-mode-map "\r" 'gnus-article-press-button) (define-key gnus-article-mode-map "\t" 'gnus-article-next-button) + (define-key gnus-article-mode-map "\M-\t" 'gnus-article-prev-button) (define-key gnus-article-mode-map "\C-c\C-b" 'gnus-bug) ;; Duplicate almost all summary keystrokes in the article mode map. *************** *** 12371,12382 **** (defun gnus-article-hide-headers (&optional delete) "Hide unwanted headers and possibly sort them as well." (interactive "P") (unless gnus-inhibit-hiding (save-excursion (set-buffer gnus-article-buffer) (save-restriction ! (let ((sorted gnus-sorted-header-list) ! (buffer-read-only nil) want-list beg want-l) ;; First we narrow to just the headers. (widen) --- 12633,12655 ---- (defun gnus-article-hide-headers (&optional delete) "Hide unwanted headers and possibly sort them as well." (interactive "P") + ;; This function might be inhibited. (unless gnus-inhibit-hiding (save-excursion (set-buffer gnus-article-buffer) (save-restriction ! (let ((buffer-read-only nil) ! (ignored (when (not (stringp gnus-visible-headers)) ! (cond ((stringp gnus-ignored-headers) ! gnus-ignored-headers) ! ((listp gnus-ignored-headers) ! (mapconcat 'identity gnus-ignored-headers ! "\\|"))))) ! (visible (cond ((stringp gnus-visible-headers) ! gnus-visible-headers) ! ((listp gnus-visible-headers) ! (mapconcat 'identity gnus-visible-headers ! "\\|")))) want-list beg want-l) ;; First we narrow to just the headers. (widen) *************** *** 12384,12391 **** ;; Hide any "From " lines at the beginning of (mail) articles. (while (looking-at "From ") (forward-line 1)) ! (or (bobp) ! (add-text-properties (point-min) (point) gnus-hidden-properties)) ;; Then treat the rest of the header lines. (narrow-to-region (point) --- 12657,12664 ---- ;; Hide any "From " lines at the beginning of (mail) articles. (while (looking-at "From ") (forward-line 1)) ! (unless (bobp) ! (add-text-properties (point-min) (point) gnus-hidden-properties)) ;; Then treat the rest of the header lines. (narrow-to-region (point) *************** *** 12399,12445 **** (beginning-of-line) ;; We add the headers we want to keep to a list and delete ;; them from the buffer. ! (if (or (and (stringp gnus-visible-headers) ! (looking-at gnus-visible-headers)) ! (and (not (stringp gnus-visible-headers)) ! (stringp gnus-ignored-headers) ! (not (looking-at gnus-ignored-headers)))) (progn ! (setq beg (point)) ! (forward-line 1) ! ;; Be sure to get multi-line headers... ! (re-search-forward "^[^ \t]*:" nil t) ! (beginning-of-line) ! (setq want-list ! (cons (buffer-substring beg (point)) want-list)) ! (delete-region beg (point)) ! (goto-char beg)) (forward-line 1))) ! ;; Next we perform the sorting by looking at ! ;; `gnus-sorted-header-list'. (goto-char (point-min)) - (while (and sorted want-list) - (setq want-l want-list) - (while (and want-l - (not (string-match (car sorted) (car want-l)))) - (setq want-l (cdr want-l))) - (if want-l - (progn - (insert (car want-l)) - (setq want-list (delq (car want-l) want-list)))) - (setq sorted (cdr sorted))) - ;; Any headers that were not matched by the sorted list we - ;; just tack on the end of the visible header list. (while want-list ! (insert (car want-list)) ! (setq want-list (cdr want-list))) ! ;; And finally we make the unwanted headers invisible. (if delete ! (delete-region (point) (point-max)) ;; Suggested by Sudish Joseph . (add-text-properties (point) (point-max) gnus-hidden-properties))))))) ;; Written by Per Abrahamsen . (defun gnus-article-treat-overstrike () "Translate overstrikes into bold text." --- 12672,12719 ---- (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 . (add-text-properties (point) (point-max) 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))) + ;; Written by Per Abrahamsen . (defun gnus-article-treat-overstrike () "Translate overstrikes into bold text." *************** *** 12633,12642 **** If TYPE is `local', convert to local time; if it is `lapsed', output how much time has lapsed since DATE." (interactive (list 'ut t)) ! (let ((date (mail-header-date (or gnus-current-headers ! (gnus-summary-article-header) ""))) ! (date-regexp "^Date: \\|^X-Sent: ") ! (inhibit-point-motion-hooks t)) (when (and date (not (string= date ""))) (save-excursion (set-buffer gnus-article-buffer) --- 12907,12917 ---- If TYPE is `local', convert to local time; if it is `lapsed', output how much time has lapsed since DATE." (interactive (list 'ut t)) ! (let* ((header (or gnus-current-headers ! (gnus-summary-article-header) "")) ! (date (and (vectorp header) (mail-header-date header))) ! (date-regexp "^Date: \\|^X-Sent: ") ! (inhibit-point-motion-hooks t)) (when (and date (not (string= date ""))) (save-excursion (set-buffer gnus-article-buffer) *************** *** 12823,12879 **** (insert "\^_"))) (defun gnus-narrow-to-page (&optional arg) ! "Make text outside current page invisible except for page delimiter. ! A numeric arg specifies to move forward or backward by that many pages, ! thus showing a page other than the one point was originally in." (interactive "P") (setq arg (if arg (prefix-numeric-value arg) 0)) (save-excursion ! (forward-page -1) ;Beginning of current page. (widen) ! (if (> arg 0) ! (forward-page arg) ! (if (< arg 0) ! (forward-page (1- arg)))) ! ;; Find the end of the page. ! (forward-page) ! ;; If we stopped due to end of buffer, stay there. ! ;; If we stopped after a page delimiter, put end of restriction ! ;; at the beginning of that line. ! ;; These are commented out. ! ;; (if (save-excursion (beginning-of-line) ! ;; (looking-at page-delimiter)) ! ;; (beginning-of-line)) ! (narrow-to-region (point) ! (progn ! ;; Find the top of the page. ! (forward-page -1) ! ;; If we found beginning of buffer, stay there. ! ;; If extra text follows page delimiter on same line, ! ;; include it. ! ;; Otherwise, show text starting with following line. ! (if (and (eolp) (not (bobp))) ! (forward-line 1)) ! (point))))) ! ! (defun gnus-gmt-to-local () ! "Rewrite Date header described in GMT to local in current buffer. ! Intended to be used with gnus-article-prepare-hook." ! (save-excursion ! (save-restriction ! (widen) ! (goto-char (point-min)) ! (narrow-to-region (point-min) ! (progn (search-forward "\n\n" nil 'move) (point))) ! (goto-char (point-min)) ! (if (re-search-forward "^Date:[ \t]\\(.*\\)$" nil t) ! (let ((buffer-read-only nil) ! (date (buffer-substring-no-properties ! (match-beginning 1) (match-end 1)))) ! (delete-region (match-beginning 1) (match-end 1)) ! (insert ! (timezone-make-date-arpa-standard ! date nil (current-time-zone)))))))) ;; Article mode commands --- 13098,13128 ---- (insert "\^_"))) (defun gnus-narrow-to-page (&optional arg) ! "Narrow the article buffer to a page. ! If given a numerical ARG, move forward ARG pages." (interactive "P") (setq arg (if arg (prefix-numeric-value arg) 0)) (save-excursion ! (set-buffer gnus-article-buffer) ! (goto-char (point-min)) (widen) ! (when ! (cond ((< arg 0) ! (re-search-backward page-delimiter nil 'move (1+ (abs arg)))) ! ((> arg 0) ! (re-search-forward page-delimiter nil 'move arg))) ! (goto-char (match-end 0))) ! (when (and (gnus-visual-p 'page-marker) ! (not (bolp))) ! (gnus-insert-prev-page-button)) ! (narrow-to-region ! (point) ! (if (re-search-forward page-delimiter nil 'move) ! (prog1 (match-beginning 0) ! (when (and (gnus-visual-p 'page-marker) ! (not (bolp))) ! (gnus-insert-next-page-button))) ! (point))))) ;; Article mode commands *************** *** 12916,12922 **** (gnus-narrow-to-page -1) ;Go to previous page. (goto-char (point-max)) (recenter -1)) ! (scroll-down lines))) (defun gnus-article-refer-article () "Read article specified by message-id around point." --- 13165,13173 ---- (gnus-narrow-to-page -1) ;Go to previous page. (goto-char (point-max)) (recenter -1)) ! (condition-case () ! (scroll-down lines) ! (error nil)))) (defun gnus-article-refer-article () "Read article specified by message-id around point." *************** *** 13334,13340 **** If FETCH-OLD, retrieve all headers (or some subset thereof) in the group." (let ((method (gnus-find-method-for-group group))) (if (and gnus-use-cache (numberp (car articles))) ! (gnus-cache-retrieve-headers articles group) (funcall (gnus-get-function method 'retrieve-headers) articles (gnus-group-real-name group) (nth 1 method) fetch-old)))) --- 13585,13591 ---- If FETCH-OLD, retrieve all headers (or some subset thereof) in the group." (let ((method (gnus-find-method-for-group group))) (if (and gnus-use-cache (numberp (car articles))) ! (gnus-cache-retrieve-headers articles group fetch-old) (funcall (gnus-get-function method 'retrieve-headers) articles (gnus-group-real-name group) (nth 1 method) fetch-old)))) *************** *** 13346,13352 **** (defun gnus-request-type (group &optional article) "Return the type (`post' or `mail') of GROUP (and ARTICLE)." (let ((method (gnus-find-method-for-group group))) ! (if (not (gnus-check-backend-function 'request-type method)) 'unknown (funcall (gnus-get-function method 'request-type) (gnus-group-real-name group) article)))) --- 13597,13603 ---- (defun gnus-request-type (group &optional article) "Return the type (`post' or `mail') of GROUP (and ARTICLE)." (let ((method (gnus-find-method-for-group group))) ! (if (not (gnus-check-backend-function 'request-type (car method))) 'unknown (funcall (gnus-get-function method 'request-type) (gnus-group-real-name group) article)))) *************** *** 13603,13609 **** ;; 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 (or level (1+ gnus-level-subscribed)))) (if (and init gnus-check-bogus-newsgroups gnus-read-active-file (not level) --- 13854,13860 ---- ;; 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)) (if (and init gnus-check-bogus-newsgroups gnus-read-active-file (not level) *************** *** 13970,13976 **** ;; 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 (1+ gnus-level-subscribed))) (foreign-level (min (cond ((and gnus-activate-foreign-newsgroups --- 14221,14227 ---- ;; 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 *** pub/sgnus/lisp/nndoc.el Sun Dec 10 12:08:35 1995 --- sgnus/lisp/nndoc.el Tue Dec 12 21:52:14 1995 *************** *** 128,156 **** ;;; Interface functions (defun nndoc-retrieve-headers (articles &optional newsgroup server fetch-old) ! (nndoc-possibly-change-buffer newsgroup server) ! (save-excursion ! (set-buffer nntp-server-buffer) ! (erase-buffer) ! (let (article entry) ! (if (stringp (car articles)) ! 'headers ! (while articles ! (setq entry (cdr (assq (setq article (pop articles)) ! nndoc-dissection-alist))) ! (insert (format "221 %d Article retrieved.\n" article)) ! (insert-buffer-substring ! nndoc-current-buffer (car entry) (nth 1 entry)) ! (goto-char (point-max)) ! (or (= (char-after (1- (point))) ?\n) (insert "\n")) ! (insert (format "Lines: %d\n" (nth 4 entry))) ! (insert ".\n")) ! ! ;; Fold continuation lines. ! (goto-char (point-min)) ! (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t) ! (replace-match " " t t)) ! 'headers)))) (defun nndoc-open-server (server &optional defs) (nnheader-init-server-buffer) --- 128,156 ---- ;;; Interface functions (defun nndoc-retrieve-headers (articles &optional newsgroup server fetch-old) ! (when (nndoc-possibly-change-buffer newsgroup server) ! (save-excursion ! (set-buffer nntp-server-buffer) ! (erase-buffer) ! (let (article entry) ! (if (stringp (car articles)) ! 'headers ! (while articles ! (setq entry (cdr (assq (setq article (pop articles)) ! nndoc-dissection-alist))) ! (insert (format "221 %d Article retrieved.\n" article)) ! (insert-buffer-substring ! nndoc-current-buffer (car entry) (nth 1 entry)) ! (goto-char (point-max)) ! (or (= (char-after (1- (point))) ?\n) (insert "\n")) ! (insert (format "Lines: %d\n" (nth 4 entry))) ! (insert ".\n")) ! ! ;; Fold continuation lines. ! (goto-char (point-min)) ! (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t) ! (replace-match " " t t)) ! 'headers))))) (defun nndoc-open-server (server &optional defs) (nnheader-init-server-buffer) *************** *** 277,288 **** (if (stringp nndoc-address) (insert-file-contents nndoc-address) (insert-buffer-substring nndoc-address))))) ! (save-excursion ! (set-buffer nndoc-current-buffer) ! (nndoc-set-delims) ! (nndoc-dissect-buffer)) ! t)) ! ;; MIME (RFC 1341) digest hack by Ulrik Dickow . (defun nndoc-guess-digest-type () --- 277,288 ---- (if (stringp nndoc-address) (insert-file-contents nndoc-address) (insert-buffer-substring nndoc-address))))) ! (when nndoc-current-buffer ! (save-excursion ! (set-buffer nndoc-current-buffer) ! (nndoc-set-delims) ! (nndoc-dissect-buffer)) ! t))) ;; MIME (RFC 1341) digest hack by Ulrik Dickow . (defun nndoc-guess-digest-type () *************** *** 427,434 **** (defun nndoc-rnews-body-end () (save-excursion (and (re-search-backward nndoc-article-begin nil t) ! (goto-char (+ (point) (string-to-int (match-string 1))))))) ! (provide 'nndoc) --- 427,433 ---- (defun nndoc-rnews-body-end () (save-excursion (and (re-search-backward nndoc-article-begin nil t) ! (goto-char (+ (point) (string-to-int (match-string 1))))))) (provide 'nndoc) *** pub/sgnus/lisp/nnfolder.el Sun Dec 10 12:08:35 1995 --- sgnus/lisp/nnfolder.el Wed Dec 13 16:19:54 1995 *************** *** 221,246 **** (defun nnfolder-request-group (group &optional server dont-check) (save-excursion (nnmail-activate 'nnfolder) ! (nnfolder-possibly-change-group group) ! (and (assoc group nnfolder-group-alist) ! (progn ! (if dont-check ! t ! (let* ((active (assoc group nnfolder-group-alist)) ! (group (car active)) ! (range (car (cdr active))) ! (minactive (car range)) ! (maxactive (cdr range))) ! ;; I've been getting stray 211 lines in my nnfolder active ! ;; file. So, let's make sure that doesn't happen. -SLB ! (set-buffer nntp-server-buffer) ! (erase-buffer) ! (if (not active) ! () ! (insert (format "211 %d %d %d %s\n" ! (1+ (- maxactive minactive)) ! minactive maxactive group)) ! t))))))) (defun nnfolder-request-scan (&optional group server) (nnmail-get-new-mail --- 221,241 ---- (defun nnfolder-request-group (group &optional server dont-check) (save-excursion (nnmail-activate 'nnfolder) ! (when (assoc group nnfolder-group-alist) ! (if dont-check ! t ! (let* ((active (assoc group nnfolder-group-alist)) ! (group (car active)) ! (range (car (cdr active))) ! (minactive (car range)) ! (maxactive (cdr range))) ! (set-buffer nntp-server-buffer) ! (erase-buffer) ! (when active ! (insert (format "211 %d %d %d %s\n" ! (1+ (- maxactive minactive)) ! minactive maxactive group)) ! t)))))) (defun nnfolder-request-scan (&optional group server) (nnmail-get-new-mail *** pub/sgnus/lisp/nnheader.el Sun Dec 10 12:08:35 1995 --- sgnus/lisp/nnheader.el Thu Dec 14 09:25:15 1995 *************** *** 394,399 **** --- 394,425 ---- (buffer-disable-undo (current-buffer)) (erase-buffer)) + (defvar jka-compr-compression-info-list) + (defvar nnheader-numerical-files + (if (boundp 'jka-compr-compression-info-list) + (concat "\\([0-9]+\\)\\(" + (mapconcat (lambda (i) (aref i 0)) + jka-compr-compression-info-list "\\|") + "\\)?") + "[0-9]+$") + "Regexp that match numerical files.") + + (defvar nnheader-numerical-short-files (concat "^" nnheader-numerical-files) + "Regexp that matches numerical file names.") + + (defvar nnheader-numerical-full-files (concat "/" nnheader-numerical-files) + "Regexp that matches numerical full file paths.") + + (defun nnheader-file-to-number (file) + (if (not (boundp 'jka-compr-compression-info-list)) + (string-to-int file) + (string-match nnheader-numerical-short-files file) + (match-string 1 file))) + + (defun nnheader-directory-articles (dir) + (mapcar 'nnheader-file-to-number + (directory-files dir nil nnheader-numerical-short-files t))) + (provide 'nnheader) ;;; nnheader.el ends here *** pub/sgnus/lisp/nnkiboze.el Sun Dec 10 12:08:35 1995 --- sgnus/lisp/nnkiboze.el Mon Dec 11 17:01:14 1995 *************** *** 190,195 **** --- 190,208 ---- (defalias 'nnkiboze-request-post 'nntp-request-post) + (defun nnkiboze-request-delete-group (group &optional force server) + (nnkiboze-possibly-change-newsgroups group) + (when force + (let ((files (list (nnkiboze-nov-file-name) + (concat nnkiboze-directory group ".newsrc") + (nnkiboze-score-file group)))) + (while files + (and (file-exists-p (car files)) + (file-writable-p (car files)) + (delete-file (car files))) + (setq files (cdr files))))) + (setq nnkiboze-current-group nil)) + ;;; Internal functions. *** pub/sgnus/lisp/nnmail.el Sun Dec 10 12:08:35 1995 --- sgnus/lisp/nnmail.el Tue Dec 12 21:52:25 1995 *************** *** 300,308 **** (defun nnmail-days-to-time (days) "Convert DAYS into time." ! (let ((seconds (round (* days 60 60 24))) (rest (expt 2 16))) ! (list (/ seconds rest) (% seconds rest)))) (defun nnmail-time-since (time) "Return the time since DATE." --- 300,312 ---- (defun nnmail-days-to-time (days) "Convert DAYS into time." ! (let ((seconds (* 1.0 days 60 60 24)) (rest (expt 2 16))) ! (list (round (/ seconds rest)) ! ;;;!!!Error error error. I'm not a mathematician, though. ! (condition-case () ! (% (round seconds) rest) ! (error 0))))) (defun nnmail-time-since (time) "Return the time since DATE." *************** *** 840,851 **** (file-truename nnmail-crash-box))) 0)) (list nnmail-crash-box)))) ;; Remove any directories that inadvertantly match the procmail ! ;; suffix, which might happen if the suffix is "". We also ! ;; ditch symlinks. (while p ! (and (or (file-directory-p (car p)) ! (file-symlink-p (car p))) ! (setq procmails (delete (car p) procmails))) (setq p (cdr p))) ;; Return the list of spools. (append --- 844,853 ---- (file-truename nnmail-crash-box))) 0)) (list nnmail-crash-box)))) ;; Remove any directories that inadvertantly match the procmail ! ;; suffix, which might happen if the suffix is "". (while p ! (when (file-directory-p (car p)) ! (setq procmails (delete (car p) procmails))) (setq p (cdr p))) ;; Return the list of spools. (append *** pub/sgnus/lisp/nnml.el Sun Dec 10 12:08:36 1995 --- sgnus/lisp/nnml.el Thu Dec 14 10:33:15 1995 *************** *** 70,75 **** --- 70,77 ---- (defvar nnml-group-alist nil) (defvar nnml-active-timestamp nil) + (defvar nnml-generate-active-function 'nnml-generate-active-info) + ;; Server variables. *************** *** 231,241 **** nnml-group-alist)) (nnml-possibly-create-directory group) (nnml-possibly-change-directory group) ! (let ((articles (mapcar ! (lambda (file) ! (string-to-int file)) ! (directory-files ! nnml-current-directory nil "^[0-9]+$")))) (and articles (progn (setcar active (apply 'min articles)) --- 233,240 ---- nnml-group-alist)) (nnml-possibly-create-directory group) (nnml-possibly-change-directory group) ! (let ((articles ! (nnheader-directory-articles nnml-current-directory ))) (and articles (progn (setcar active (apply 'min articles)) *************** *** 261,271 **** (defun nnml-request-expire-articles (articles newsgroup &optional server force) (nnml-possibly-change-directory newsgroup) (let* ((active-articles ! (mapcar ! (function ! (lambda (name) ! (string-to-int name))) ! (directory-files nnml-current-directory nil "^[0-9]+$" t))) (max-article (and active-articles (apply 'max active-articles))) (is-old t) article rest mod-time number) --- 260,266 ---- (defun nnml-request-expire-articles (articles newsgroup &optional server force) (nnml-possibly-change-directory newsgroup) (let* ((active-articles ! (nnheader-directory-articles nnml-current-directory)) (max-article (and active-articles (apply 'max active-articles))) (is-old t) article rest mod-time number) *************** *** 386,406 **** (defun nnml-request-delete-group (group &optional force server) (nnml-possibly-change-directory group) ! ;; Delete all articles in GROUP. ! (if (not force) ! () ; Don't delete the articles. (let ((articles (directory-files nnml-current-directory t ! (concat "^[0-9]+$\\|" (regexp-quote nnml-nov-file-name) "$")))) (while articles ! (and (file-writable-p (car articles)) ! (progn ! (and gnus-verbose-backends ! (message (message "Deleting article %s in %s..." ! (car articles) group))) ! (funcall nnmail-delete-file-function (car articles)))) ! (setq articles (cdr articles)))) ;; Try to delete the directory itself. (condition-case () (delete-directory nnml-current-directory) --- 381,400 ---- (defun nnml-request-delete-group (group &optional force server) (nnml-possibly-change-directory group) ! (when force ! ;; Delete all articles in GROUP. (let ((articles (directory-files nnml-current-directory t ! (concat nnheader-numerical-short-files ! "\\|" (regexp-quote nnml-nov-file-name) "$"))) ! article) (while articles ! (setq article (pop articles)) ! (when (file-writable-p article) ! (when gnus-verbose-backends ! (message "Deleting article %s in %s..." article group)) ! (funcall nnmail-delete-file-function article)))) ;; Try to delete the directory itself. (condition-case () (delete-directory nnml-current-directory) *************** *** 685,759 **** (setq nnml-nov-buffer-alist (cdr nnml-nov-buffer-alist))))) ;;;###autoload ! (defun nnml-generate-nov-databases (dir) "Generate nov databases in all nnml directories." ! (interactive ! (progn ! (setq nnml-group-alist nil) ! (list nnml-directory))) (nnml-open-server (or nnml-current-server "")) ! (let ((dirs (directory-files dir t nil t))) (while dirs ! (if (and (not (string-match "/\\.\\.$" (car dirs))) ! (not (string-match "/\\.$" (car dirs))) ! (file-directory-p (car dirs))) ! (nnml-generate-nov-databases (car dirs))) ! (setq dirs (cdr dirs)))) (let ((files (sort (mapcar ! (function ! (lambda (name) ! (string-to-int name))) (directory-files dir nil "^[0-9]+$" t)) ! (function <))) ! (nov (concat dir "/" nnml-nov-file-name)) ! (nov-buffer (get-buffer-create "*nov*")) nov-line chars) ! (if files ! (setq nnml-group-alist ! (cons (list (nnmail-replace-chars-in-string ! (substring (expand-file-name dir) ! (length (expand-file-name ! nnml-directory))) ! ?/ ?.) ! (cons (car files) ! (let ((f files)) ! (while (cdr f) (setq f (cdr f))) ! (car f)))) ! nnml-group-alist))) ! (if files ! (save-excursion ! (set-buffer nntp-server-buffer) ! (if (file-exists-p nov) ! (funcall nnmail-delete-file-function nov)) ! (save-excursion ! (set-buffer nov-buffer) ! (buffer-disable-undo (current-buffer)) ! (erase-buffer)) ! (while files ! (erase-buffer) ! (insert-file-contents (concat dir "/" (int-to-string (car files)))) ! (narrow-to-region ! (goto-char (point-min)) ! (save-excursion ! (search-forward "\n\n" nil t) ! (setq chars (- (point-max) (point))) ! (point))) ! (when (and (not (= 0 chars)) ; none of them empty files... ! (not (= (point-min) (point-max)))) ! (setq nov-line (nnml-make-nov-line chars)) ! (save-excursion ! (set-buffer nov-buffer) ! (goto-char (point-max)) ! (insert (int-to-string (car files)) nov-line))) ! (widen) ! (setq files (cdr files))) (save-excursion (set-buffer nov-buffer) ! (write-region 1 (point-max) (expand-file-name nov) nil ! 'nomesg) ! (kill-buffer (current-buffer))))) ! (nnmail-save-active nnml-group-alist nnml-active-file))) (defun nnml-nov-delete-article (group article) (save-excursion --- 679,768 ---- (setq nnml-nov-buffer-alist (cdr nnml-nov-buffer-alist))))) ;;;###autoload ! (defun nnml-generate-nov-databases () "Generate nov databases in all nnml directories." ! (interactive) ! ;; Read the active file to make sure we don't re-use articles ! ;; numbers in empty groups. ! (nnmail-activate 'nnml) (nnml-open-server (or nnml-current-server "")) ! (setq nnml-directory (expand-file-name nnml-directory)) ! ;; Recurse down the directories. ! (nnml-generate-nov-databases-1 nnml-directory) ! ;; Save the active file. ! (nnmail-save-active nnml-group-alist nnml-active-file)) ! ! (defun nnml-generate-nov-databases-1 (dir) ! (setq dir (file-name-as-directory dir)) ! ;; We descend recursively ! (let ((dirs (directory-files dir t nil t)) ! dir) (while dirs ! (setq dir (pop dirs)) ! (when (and (not (string-match "/\\.\\.?$" dir)) ! (file-directory-p dir)) ! (nnml-generate-nov-databases-1 dir)))) ! ;; Do this directory. (let ((files (sort (mapcar ! (lambda (name) (string-to-int name)) (directory-files dir nil "^[0-9]+$" t)) ! '<))) ! (when files ! (funcall nnml-generate-active-function dir) ! ;; Generate the nov file. ! (nnml-generate-nov-file dir files)))) ! ! (defun nnml-generate-active-info (dir) ! ;; Update the active info for this group. ! (let ((group (nnmail-replace-chars-in-string ! (substring dir (length nnml-directory)) ! ?/ ?.))) ! (setq nnml-group-alist (delq (assoc group nnml-group-alist))) ! (push (list group ! (cons (car files) ! (let ((f files)) ! (while (cdr f) (setq f (cdr f))) ! (car f)))) ! nnml-group-alist))) ! ! (defun nnml-generate-nov-file (dir files) ! (let ((nov (concat dir "/" nnml-nov-file-name)) ! (nov-buffer (get-buffer-create " *nov*")) nov-line chars) ! (save-excursion ! ;; Init the nov buffer. ! (set-buffer nov-buffer) ! (buffer-disable-undo (current-buffer)) ! (erase-buffer) ! (set-buffer nntp-server-buffer) ! ;; Delete the old NOV file. ! (when (file-exists-p nov) ! (funcall nnmail-delete-file-function nov)) ! (while files ! (erase-buffer) ! (insert-file-contents (concat dir "/" (int-to-string (car files)))) ! (narrow-to-region ! (goto-char (point-min)) ! (progn ! (search-forward "\n\n" nil t) ! (setq chars (- (point-max) (point))) ! (1- (point)))) ! (when (and (not (= 0 chars)) ; none of them empty files... ! (not (= (point-min) (point-max)))) ! (goto-char (point-min)) ! (setq nov-line (nnml-make-nov-line chars)) (save-excursion (set-buffer nov-buffer) ! (goto-char (point-max)) ! (insert (int-to-string (car files)) nov-line))) ! (widen) ! (setq files (cdr files))) ! (save-excursion ! (set-buffer nov-buffer) ! (write-region 1 (point-max) (expand-file-name nov) nil ! 'nomesg) ! (kill-buffer (current-buffer)))))) (defun nnml-nov-delete-article (group article) (save-excursion *** pub/sgnus/lisp/nntp.el Sun Dec 10 12:08:36 1995 --- sgnus/lisp/nntp.el Wed Dec 13 18:21:17 1995 *************** *** 613,618 **** --- 613,627 ---- reading." (nntp-send-command "^.*\r?\n" "MODE READER")) + (defun nntp-send-nosy-authinfo () + "Send the AUTHINFO to the nntp server. + This function is supposed to be called from `nntp-server-opened-hook'. + It will prompt for a password." + (nntp-send-command "^.*\r?\n" "AUTHINFO USER" + (read-string "NNTP user name: ")) + (nntp-send-command "^.*\r?\n" "AUTHINFO PASS" + (read-string "NNTP password: "))) + (defun nntp-send-authinfo () "Send the AUTHINFO to the nntp server. This function is supposed to be called from `nntp-server-opened-hook'. *** pub/sgnus/lisp/ChangeLog Sun Dec 10 12:08:42 1995 --- sgnus/lisp/ChangeLog Thu Dec 14 10:53:54 1995 *************** *** 1,5 **** ! Sun Dec 10 10:38:47 1995 Lars Magne Ingebrigtsen * gnus.el (gnus-backlog-shutdown): New function. (gnus-backlog-buffer): Would return a list the first time called. --- 1,164 ---- ! Thu Dec 14 10:48:51 1995 Lars Magne Ingebrigtsen + * gnus.el (gnus-summary-toggle-header): Don't do that hook dance. + + Thu Dec 14 10:02:08 1995 Lars Magne Ingebrigtsen + + * gnus-xmas.el (gnus-xmas-read-event-char): New function. + + * gnus.el (gnus-summary-last-subject): New function. + (gnus-summary-next-article): Understand all key events. + (gnus-summary-walk-group-buffer): New function. + (gnus-read-event-char): New function. + + Wed Dec 13 16:06:29 1995 Lars Ingebrigtsen + + * gnus-msg.el (gnus-new-mail, gnus-mail-reply): Didn't insert + Gcc. + + * gnus-score.el (gnus-score-load-file): Allow `adapt-file' atom. + (gnus-score-adaptive): Use it. + + * gnus.el (gnus-group-visible-select-group): New command and + keystroke. + (gnus-read-save-file-name): Extend the syntax of + `gnus-split-methods'. + (gnus-article-archive-name): New function. + (gnus-split-methods): New default; use function above. + (gnus-summary-update-secondary-mark): Update highlighting after + setting secondary marks. + + * nnfolder.el (nnfolder-request-group): Don't load all nnfolder + groups on startup. + + Tue Dec 12 19:48:55 1995 Lars Ingebrigtsen + + * gnus.el (gnus-group-insert-group-line): Number of marked (etc) + didn't work. + + Tue Dec 12 19:37:05 1995 Timo Metzemakers + + * gnus.el (gnus-summary-reselect-current-group): Really reselect + the group. + + Tue Dec 12 10:38:05 1995 Lars Ingebrigtsen + + * nnmail.el (nnmail-days-to-time): Would result in short expiry + times in groups with veeery long expiry times. + + * gnus-vis.el (gnus-summary-highlight-line): Bind `number'. + + * gnus-score.el (gnus-score-find-bnews): Protect agains bogus + score file names. + + * gnus.el (gnus-activate-all-groups): New command and keystroke. + + * gnus-vis.el (gnus-article-prev-button): New command and keystroke. + + * gnus-cache.el (gnus-cache-generate-nov-databases): New command. + + * gnus-score.el (gnus-score-load-file): Accept + `thread-mark-and-expunge' atom. + + * gnus.el (gnus-newsgroup-saved): New variable. + (gnus-summary-set-saved-mark): New function. + (gnus-kill-summary-on-exit): New variable. + (gnus-dead-summary-mode): New minor mode. + (gnus-deaden-summary, gnus-summary-wake-up-the-dead): New + functions. + (gnus-summary-catchup-and-goto-next-group): Respect + `gnus-auto-select-next', etc. + (gnus-article-hide-headers): New implementation. + (gnus-article-header-rank): New function. + (gnus-article-header-less): Ditto. + (gnus-visible-headers, gnus-ignored-headers): Can now be lists of + regexps. + (gnus-thread-expunge-below): New variable. + (gnus-expunge-thread): New variable. + + * gnus-mh.el (gnus-summary-save-in-folder): There is no + `mh-search-path'. + + Mon Dec 11 07:21:25 1995 Lars Ingebrigtsen + + * gnus.el (gnus-article-sort-functions): New variable. + (gnus-article-sort-by-number, gnus-article-sort-by-author, + gnus-article-sort-by-subject, gnus-article-sort-by-date, + (gnus-article-sort-by-score): New functions. + (gnus-thread-sort-by-number, gnus-thread-sort-by-author, + gnus-thread-sort-by-subject, gnus-thread-sort-by-date, + gnus-thread-sort-by-score, gnus-summary-sort-by-number, + gnus-summary-sort-by-author, gnus-summary-sort-by-subject, + gnus-summary-sort-by-date, gnus-summary-sort-by-score, + gnus-summary-sort): New implementations. + (gnus-summary-mode-line-format): Doc fix. + (gnus-insert-pseudo-articles): New variable. + (gnus-activate-level): New variable. + (gnus-get-unread-articles): Use it. + + * nnkiboze.el (nnkiboze-request-delete-group): New function. + + * gnus.el (gnus-subscribe-killed): New function. + (gnus-group-kill-group): Make mass group slaughter faster. + (gnus-group-kill-level): New command and keystroke. + + * gnus-cache.el (gnus-cache-generate-active): Messed up the active + file. + + * gnus.el (gnus-summary-update-secondary-mark): New function. + (gnus-cached-mark): New variable. + (gnus-gmt-to-local): Removed function. + (gnus-narrow-to-page): New implementation. + + * gnus-cache.el (gnus-cache-enter-article): New command and + keystroke. + (gnus-cache-remove-article): Ditto. + (gnus-passive-cache): New variable. + (gnus-cached-article-p): New function. + + * gnus.el (gnus-summary-mode-line-format, + gnus-article-mode-line-format, gnus-group-mode-line-format): + Include the buffer name in all mode lines. + + * gnus-topic.el (gnus-topic-yank-group, gnus-topic-kill-group): + Allow kill/yank inside and in between topics. + + * gnus.el (gnus-request-type): Wouldn't work. + + Sun Dec 10 13:16:49 1995 Lars Ingebrigtsen + + * gnus-topic.el (gnus-topic-insert-topic-line): Remove old text + properties before setting new. + + * nnml.el: Understand jka-compr. + (nnml-generate-nov-databases): Would make empty group disappear. + + * nnheader.el (nnheader-numerical-short-files): New variable. + (nnheader-numerical-full-files): Ditto. + + * gnus-msg.el (gnus-summary-resend-message): Rename old Resent-* + headers. + + * gnus-cache.el (gnus-cache-retrieve-headers): Allow fetching of + old headers. + + * nnmail.el (nnmail-get-spool-files): Don't ditch procmail + symlinks. + + * gnus-msg.el (gnus-inews-insert-signature): Don't insert + signature if mail-signature. + + * gnus.el (gnus-group-make-help-group): Find gnus-tut in the etc + directory. + + Sun Dec 10 12:29:54 1995 Lars Magne Ingebrigtsen + + * gnus.el (gnus-article-date-ut): Bugged out on pseudos. + + Sun Dec 10 10:38:47 1995 Lars Magne Ingebrigtsen + + * gnus.el: 0.21 is released. + * gnus.el (gnus-backlog-shutdown): New function. (gnus-backlog-buffer): Would return a list the first time called. *** pub/sgnus/texi/Makefile Sun Dec 10 12:08:44 1995 --- sgnus/texi/Makefile Sun Dec 10 12:32:44 1995 *************** *** 17,19 **** --- 17,22 ---- clean: rm -f gnus.*.bak gnus.ky gnus.cp gnus.aux gnus.fn gnus.dvi gnus.cps gnus.kys gnus.log gnus.pg gnus.tp gnus.vr gnus.toc + + makeinfo: + makeinfo -o gnus.info gnus.texi *** pub/sgnus/texi/gnus.texi Sun Dec 10 12:08:44 1995 --- sgnus/texi/gnus.texi Thu Dec 14 10:43:50 1995 *************** *** 491,496 **** --- 491,499 ---- You can click on buttons instead of using the keyboard (@pxref{Buttons}). + @item + Gnus can use NoCeM files to weed out spam (@pxref{NoCeM}). + @end itemize This is, of course, just a @emph{short} overview of the @emph{most} *************** *** 516,527 **** @item @code{nn}-like pick-and-read summary interface. @item - NoCeM support. - @item Frame configuration. @item - Floating point group levels and group bubbling. - @item Automatic re-scan of incoming mail. @item Buttonize more stuff in the article buffer. --- 519,526 ---- *************** *** 529,536 **** A better and simpler method for specifying mail composing methods. @item Marks for saved, forwarded, etc articles. - @item - Speed up caching and adaptive scoring. @item Gather thread by filling in missing Message-IDs. @item --- 528,533 ---- *************** *** 538,563 **** @item Allow posting through mail-to-news gateways. @item - Speed up massive group massacres. - @item @code{jka-compr} isn't fully supported. @item - Create better digests. - @item Do better word-wrap on cited text. @item Better X-Face support with X-Face databases and stuff. @item - Support SELF-DISCIPLINE pins. - @item Really do unbinhexing. @item - Listing of all active groups. - @item XEmacs toolbar. @item - Do the X-Receipt-To thing. - @item Don't kill summary buffers upon exit from the groups. @item Allow adaption on secondary marks. --- 535,550 ---- *************** *** 570,575 **** --- 557,563 ---- up-to-the-second todo list is located, so if you're really curious, you could point your Web browser over that-a-way. + @node Terminology @chapter Terminology *************** *** 868,873 **** --- 856,865 ---- Subscribe new groups interactively. This means that Gnus will ask you about @strong{all} new groups. + @item gnus-subscribe-killed + @vindex gnus-subscribe-killed + Kill all new groups. + @item gnus-subscribe-zombies @vindex gnus-subscribe-zombies Make all new groups zombies. You can browse the zombies later (with *************** *** 1039,1047 **** Before examining the active file, Gnus deletes all lines that match the regexp @code{gnus-ignored-newsgroups}. This is done primarily to reject any groups with bogus names, but you can use this variable to make Gnus ! ignore hierarchies you aren't ever interested in. This variable is ! @code{nil} by default, and will slow down active file handling somewhat ! if you set it to anything else. @vindex gnus-read-active-file The active file can be rather Huge, so if you have a slow network, you --- 1031,1040 ---- Before examining the active file, Gnus deletes all lines that match the regexp @code{gnus-ignored-newsgroups}. This is done primarily to reject any groups with bogus names, but you can use this variable to make Gnus ! ignore hierarchies you aren't ever interested in. ! @c This variable is ! @c @code{nil} by default, and will slow down active file handling somewhat ! @c if you set it to anything else. @vindex gnus-read-active-file The active file can be rather Huge, so if you have a slow network, you *************** *** 1238,1246 **** @table @samp @item S ! Default news server. @item M ! Default select method. @end table @node Group Maneuvering --- 1231,1239 ---- @table @samp @item S ! The native news server. @item M ! The native select method. @end table @node Group Maneuvering *************** *** 1346,1351 **** --- 1339,1351 ---- expunging. This might be useful if you're in a real hurry and have to enter some humongous groups. + @item M-SPACE + @kindex M-RET (Group) + @findex gnus-group-visible-select-group + This is yet one more command that does the same as the one above, but + this one does it without expunging and hiding dormants + (@code{gnus-group-visible-select-group}). + @item c @kindex c (Group) @findex gnus-group-catchup-current *************** *** 1403,1409 **** By default, sorting is done on article numbers. Ready-made sorting functions include @code{gnus-thread-sort-by-number}, @code{gnus-thread-sort-by-author}, @code{gnus-thread-sort-by-subject}, ! @code{gnus-thread-sort-by-date}, @code{gnus-thread-sort-by-score}, @code{gnus-thread-sort-by-total-score}. Each function takes two threads and return non-@code{nil} if the first --- 1403,1409 ---- By default, sorting is done on article numbers. Ready-made sorting functions include @code{gnus-thread-sort-by-number}, @code{gnus-thread-sort-by-author}, @code{gnus-thread-sort-by-subject}, ! @code{gnus-thread-sort-by-date}, @code{gnus-thread-sort-by-score}, and @code{gnus-thread-sort-by-total-score}. Each function takes two threads and return non-@code{nil} if the first *************** *** 1426,1431 **** --- 1426,1445 ---- functions might be @code{max}, @code{min}, or squared means, or whatever tickles you fancy. + @findex gnus-article-sort-functions + @findex gnus-article-sort-by-date + @findex gnus-article-sort-by-score + @findex gnus-article-sort-by-subject + @findex gnus-article-sort-by-author + @findex gnus-article-sort-by-number + If you are using an unthreaded display for some strange reason or other, + you have to fiddle with the @code{gnus-article-sort-functions} + variable. It is very similar to the @code{gnus-thread-sort-functions}, + except that is uses slightly different functions for article + comparison. Available functions are @code{gnus-article-sort-by-number}, + @code{gnus-article-sort-by-author}, @code{gnus-article-sort-by-subject}, + @code{gnus-article-sort-by-date}, and @code{gnus-article-sort-by-score}. + @node Subscription Commands @section Subscription Commands *************** *** 1469,1474 **** --- 1483,1499 ---- @kindex S z (Group) @findex gnus-group-kill-all-zombies Kill all zombie groups (@code{gnus-group-kill-all-zombies}). + @item S C-k + @kindex S C-k (Group) + @findex gnus-group-kill-level + Kill all groups on a certain level (@code{gnus-group-kill-level}). + These groups can't be yanked back after killing, so this command should + be used with some caution. The only thing where this command comes in + really handy is when you have a @file{.newsrc} with lots of unsubscribed + groups that you want to get rid off. @kbd{S C-k} on level @code{7} will + kill off all unsubscribed groups that do not have message numbers in the + @file{.newsrc} file. + @end table Also @xref{Group Levels}. *************** *** 1541,1546 **** --- 1566,1577 ---- give a level prefix to @kbd{g} or @kbd{l}, all subsequent commands will use this level as the "work" level. + @vindex gnus-activate-level + Gnus will normally just activate groups that are on level + @code{gnus-activate-level} or less. If you don't want to activate + unsubscribed groups, for instance, you might set this variable to + @samp{5}. + @node Group Score @section Group Score *************** *** 2268,2281 **** want. @item ! You do the @kbd{G S r} command to pack these replies into a @sc{soup} packet. @item You transfer this packet to the server. @item ! You use Gnus to mail this packet out with the @kbd{G S s} command. @item You then repeat until you die. --- 2299,2312 ---- want. @item ! You do the @kbd{G s r} command to pack these replies into a @sc{soup} packet. @item You transfer this packet to the server. @item ! You use Gnus to mail this packet out with the @kbd{G s s} command. @item You then repeat until you die. *************** *** 2440,2446 **** @node SOUP Replies ! @subsubsection SOUP Replies Just using @code{nnsoup} won't mean that your postings and mailings end up in @sc{soup} reply packets automagically. You have to work a bit --- 2471,2477 ---- @node SOUP Replies ! @subsubsection @sc{SOUP} Replies Just using @code{nnsoup} won't mean that your postings and mailings end up in @sc{soup} reply packets automagically. You have to work a bit *************** *** 3026,3036 **** @item nnmh-be-safe @vindex nnmh-be-safe If non-@code{nil}, @code{nnmh} will go to ridiculous lengths to make ! sure that the articles in the folder is actually what Gnus think they ! are. It will check date stamps, and stat everything in sight, so setting this to @code{t} will mean a serious slow-down. If you never ! use anything by Gnus to read the @code{nnmh} articles, you do not have to set ! this variable to @code{t}. @end table @node nnfolder --- 3057,3067 ---- @item nnmh-be-safe @vindex nnmh-be-safe If non-@code{nil}, @code{nnmh} will go to ridiculous lengths to make ! sure that the articles in the folder are actually what Gnus thinks they ! are. It will check date stamps and stat everything in sight, so setting this to @code{t} will mean a serious slow-down. If you never ! use anything but Gnus to read the @code{nnmh} articles, you do not have ! to set this variable to @code{t}. @end table @node nnfolder *************** *** 3405,3412 **** @findex gnus-group-prev-group Go to the previous group (@code{gnus-group-prev-group}). ! @item SPC ! @kindex SPC (Browse) @findex gnus-browse-read-group Enter the current group and display the first article (@code{gnus-browse-read-group}). --- 3436,3443 ---- @findex gnus-group-prev-group Go to the previous group (@code{gnus-group-prev-group}). ! @item SPACE ! @kindex SPACE (Browse) @findex gnus-browse-read-group Enter the current group and display the first article (@code{gnus-browse-read-group}). *************** *** 3510,3519 **** (add-hook 'gnus-group-mode-hook 'gnus-topic-mode) @end lisp - There are, in general, two methods for dividing the groups into topics. - You can either sniff around some variables, or you can use some handy - commands. - @menu * Topic Variables:: How to customize the topics the Lisp Way. * Topic Commands:: Interactive E-Z commands. --- 3541,3546 ---- *************** *** 3525,3546 **** @subsection Topic Variables @cindex topic variables - @vindex gnus-group-topics - - @code{gnus-group-topics} is the main variable that specifies what topics - each group belong to. That is an alist where each entry looks like - this: - - @lisp - (TOPIC REGEXP SHOW) - @end lisp - - As you've already guessed (only geniļ read manuals anyway), all - groups that match @var{regexp} gets put into a section called - @var{topic}. If @var{show} is non-@code{nil}, it overrides - @code{gnus-group-topic-topics-only}. In specific, if @var{show} is - @code{t}, all groups with this topic are always shown, and if it is a - number, these groups are never shown. @vindex gnus-group-topic-topics-only Whoo, this is complicated. If @code{gnus-group-topic-topics-only} is --- 3552,3557 ---- *************** *** 3555,3575 **** of (tops) one topic each. If this is @code{nil}, each group might end up being a member of several topics. - You can also put a @code{topic} in the group parameters (@pxref{Group - Parameters}). - Now, if you select a topic, if will fold/unfold that topic, which is really neat, I think. - Here's an example @code{gnus-group-topics}: - - @lisp - (("Emacs - the Spice of Life" "^gnu.emacs\\|comp.emacs" t) - ("Alternativeness" "^alt" 0) - ("Hard Stuff" "^comp" nil) - ("The Rest" "." nil)) - @end lisp - @vindex gnus-topic-line-format The topic lines themselves are created according to the @code{gnus-topic-line-format} variable. @xref{Formatting Variables}. --- 3566,3574 ---- *************** *** 3736,3741 **** --- 3735,3745 ---- Check whether new articles have arrived in the current group (@code{gnus-group-get-new-news-this-group}). + @findex gnus-activate-all-groups + @item C-c M-g + @kindex C-c M-g (Group) + Activate absolutely all groups (@code{gnus-activate-all-groups}). + @item ^ @kindex ^ (Group) @findex gnus-group-enter-server-mode *************** *** 3840,3845 **** --- 3844,3850 ---- * Threading:: How threads are made. * Asynchronous Fetching:: Gnus might be able to pre-fetch articles. * Article Caching:: You may store articles in a cache. + * Persistent Articles:: Making articles expiry-resistant. * Article Backlog:: Having already read articles hang around. * Exiting the Summary Buffer:: Returning to the Group buffer. * Process/Prefix:: A convention used by many treatment commands. *************** *** 5268,5289 **** There are some marks that have nothing to do with whether the article is read or not. You can set a bookmark in the current article. Say you are reading a ! long thesis on cat's urinary tracts, and have to go home for dinner before you've finished reading the thesis. You can then set a bookmark in the article, and Gnus will jump to this bookmark the next time it encounters the article. All articles that you have replied to or made a followup to (i.e., have answered) will be marked with an @samp{A} in the second column (@code{gnus-replied-mark}). @vindex gnus-not-empty-thread-mark @vindex gnus-empty-thread-mark It the @samp{%e} spec is used, the presence of threads or not will be marked with @code{gnus-not-empty-thread-mark} and ! @code{gnus-empty-thread-mark}, respectively. @vindex gnus-process-mark Finally we have the @dfn{process mark} (@code{gnus-process-mark}. A variety of commands react to the presence of the process mark. For --- 5273,5309 ---- There are some marks that have nothing to do with whether the article is read or not. + @itemize @bullet + + @item You can set a bookmark in the current article. Say you are reading a ! long thesis on cats' urinary tracts, and have to go home for dinner before you've finished reading the thesis. You can then set a bookmark in the article, and Gnus will jump to this bookmark the next time it encounters the article. + @item All articles that you have replied to or made a followup to (i.e., have answered) will be marked with an @samp{A} in the second column (@code{gnus-replied-mark}). + @item + Articles that are stored in the article cache will be marked with an + @samp{*} in the second column (@code{gnus-cached-mark}). + + @item + Articles that are "saved" (in some manner or other; not necessarily + religously) are marked with an @samp{S} in the second column + (@code{gnus-saved-mark}. + + @item @vindex gnus-not-empty-thread-mark @vindex gnus-empty-thread-mark It the @samp{%e} spec is used, the presence of threads or not will be marked with @code{gnus-not-empty-thread-mark} and ! @code{gnus-empty-thread-mark} in the third column, respectively. + @item @vindex gnus-process-mark Finally we have the @dfn{process mark} (@code{gnus-process-mark}. A variety of commands react to the presence of the process mark. For *************** *** 5291,5296 **** --- 5311,5327 ---- all articles that have been marked with the process mark. Articles marked with the process mark have a @samp{#} in the second column. + @end itemize + + You might have noticed that most of these "non-readedness" marks appear + in the second column by default. So if you have a cached, saved, + replied article that you have process-marked, what will that look like? + + Nothing much. The presedence rules go as follows: process -> cache -> + replied -> saved. So if the article is in the cache and is replied, + you'll only see the cache mark and not the replied mark. + + @node Setting Marks @subsection Setting Marks @cindex setting marks *************** *** 5904,5909 **** --- 5935,5992 ---- default, since caching doesn't really work in @code{nnvirtual} groups, since @code{nnvirtual} assigns random article numbers to its articles. + @findex gnus-cache-generate-nov-databases + @findex gnus-cache-generate-active + If your cache becomes all messed up for some reason or other, Gnus + offers two functions that will try to set things right. @kbd{M-x + gnus-cache-generate-nov-databases} will (re)build all the @sc{nov} + files, and @kbd{gnus-cache-generate-active} will (re)generate the active + file. + + + @node Persistent Articles + @section Persistent Articles + @cindex persistent articles + + Closely related to article caching, we have @dfn{persistent articles}. + In fact, it's just a different way of looking at caching, and much more + useful in my opinion. + + Say you're reading a newsgroup, and you happen on to some valuable gem + that you want to keep and treasure forever. You'd normally just save it + (using one of the many saving commands) in some file. The problem with + that is that it's just, well, yucky. Ideally you'd prefer just having + the article remain in the group where you found it forever; untouched by + the expiry going on at the news server. + + This is what a @dfn{persistent article} is---an article that just won't + be deleted. It's implemented using the normal cache functions, but + you use two explicit commands for managing persistent articles: + + @table @kbd + @item * + @kindex * (Summary) + @findex gnus-cache-enter-article + Make the current article persistent (@code{gnus-cache-enter-article}). + + @item M-* + @kindex M-* (Summary) + @findex gnus-cache-remove-article + Remove the current article from the persistent articles + (@code{gnus-cache-remove-article}). This will normally delete the + article. + @end table + + Both these commands understand the process/prefix convention. + + To avoid having all ticked articles (and stuff) entered into the cache, + you should set @code{gnus-use-cache} to @code{passive} if you're just + interested in persistent articles: + + @lisp + (setq gnus-use-cache 'passive) + @end lisp + @node Article Backlog @section Article Backlog *************** *** 6005,6010 **** --- 6088,6108 ---- @code{gnus-exit-group-hook} is called when you exit the current group. + @findex gnus-summary-wake-up-the-dead + @findex gnus-dead-summary-mode + @vindex gnus-kill-summary-on-exit + If you're in the habit of exiting groups, and then changing your mind + about it, you might set @code{gnus-kill-summary-on-exit} to @code{nil}. + If you do that, Gnus won't kill the summary buffer when you exit it. + (Quelle surprise!) Instead it will change the name of the buffer to + something like @samp{"*Dead Summary ... *"} and install a minor mode + called @code{gnus-dead-summary-mode}. Now, if you switch back to this + buffer, you'll find that all keys are mapped to a function called + @code{gnus-summary-wake-up-the-dead}. So tapping any keys in a dead + summary buffer will result in a live, normal summary buffer. + + There will never be more than one dead summary buffer at any one time. + @vindex gnus-use-cross-reference The data on the current group will be updated (which articles you have read, which articles you have replied to, etc.) when you exit the *************** *** 6250,6256 **** head); it can be a symbol (which will be called as a function); or it can be a list (which will be @code{eval}ed). If any of these actions have a non-@code{nil} result, the @dfn{file} will be used as a default ! prompt. @vindex gnus-use-long-file-name Finally, you have the @code{gnus-use-long-file-name} variable. If it is --- 6348,6365 ---- head); it can be a symbol (which will be called as a function); or it can be a list (which will be @code{eval}ed). If any of these actions have a non-@code{nil} result, the @dfn{file} will be used as a default ! prompt. In addition, the result of the operation itself will be used if ! the function or form called returns a string or a list of strings. ! ! You basically end up with a list of file names that might be used when ! saving the current article. (All "matches" will be used.) You will ! then be prompted for what you really want to use as a name, with file ! name completion over the results from applying this variable. ! ! This variable is @code{((gnus-article-archive-name))} by default, which ! means that Gnus will look at the articles it saves for an ! @samp{Archive-name} line and use that as a suggestion for the file ! name. @vindex gnus-use-long-file-name Finally, you have the @code{gnus-use-long-file-name} variable. If it is *************** *** 6598,6603 **** --- 6707,6715 ---- @code{nil}, all files that use the same viewing command will be given as a list of parameters to that command. + If @code{gnus-insert-pseudo-articles} is non-@code{nil}, insert + pseudo-articles when decoding. It is @code{t} by default. + So; there you are, reading your @emph{pseudo-articles} in your @emph{virtual newsgroup} from the @emph{virtual server}; and you think: Why isn't anything real anymore? How did we get here? *************** *** 7298,7303 **** --- 7410,7418 ---- (setq gnus-visible-headers "^From:\\|^Subject:") @end lisp + This variable can also be a list of regexps to match headers that are to + remain visible. + @item gnus-ignored-headers @vindex gnus-ignored-headers This variable is the reverse of @code{gnus-visible-headers}. If this *************** *** 7312,7319 **** --- 7427,7438 ---- (setq gnus-ignored-headers "^References:\\|^Xref:") @end lisp + This variable can also be a list of regexps to match headers that are to + be removed. + Note that if @code{gnus-visible-headers} is non-@code{nil}, this variable will have no effect. + @end table @vindex gnus-sorted-header-list *************** *** 7403,7439 **** --- 7522,7577 ---- A few additional keystrokes are available: @table @kbd + @item SPACE @kindex SPACE (Article) @findex gnus-article-next-page Scroll forwards one page (@code{gnus-article-next-page}). + @item DEL @kindex DEL (Article) @findex gnus-article-prev-page Scroll backwards one page (@code{gnus-article-prev-page}). + @item C-c ^ @kindex C-c ^ (Article) @findex gnus-article-refer-article If point is in the neighborhood of a @code{Message-ID} and you press @kbd{r}, Gnus will try to get that article from the server (@code{gnus-article-refer-article}). + @item C-c C-m @kindex C-c C-m (Article) @findex gnus-article-mail Send a reply to the address near point (@code{gnus-article-mail}). If given a prefix, include the mail. + @item s @kindex s (Article) @findex gnus-article-show-summary Reconfigure the buffers so that the summary buffer becomes visible (@code{gnus-article-show-summary}). + @item ? @kindex ? (Article) @findex gnus-article-describe-briefly Give a very brief description of the available keystrokes (@code{gnus-article-describe-briefly}). + + @item TAB + @kindex TAB (Article) + @findex gnus-article-next-button + Go to the next button, if any (@code{gnus-article-next-button}. This + only makes sense if you have buttonizing turned on. + + @item M-TAB + @kindex M-TAB (Article) + @findex gnus-article-prev-button + Go to the previous button, if any (@code{gnus-article-prev-button}. + @end table + @node Misc Article @section Misc Article *************** *** 8152,8181 **** --- 8290,8333 ---- @item mark The value of this entry should be a number. Any articles with a score lower than this number will be marked as read. + @item expunge The value of this entry should be a number. Any articles with a score lower than this number will be removed from the summary buffer. + @item mark-and-expunge The value of this entry should be a number. Any articles with a score lower than this number will be marked as read and removed from the summary buffer. + + @item thread-mark-and-expunge + The value of this entry should be a number. All articles that belong to + a thread that has a total score below this number will be marked as read + and removed from the summary buffer. @code{gnus-thread-score-function} + says how to compute the total score for a thread. + @item files The value of this entry should be any number of file names. These files are assumed to be score files as well, and will be loaded the same way this one was. + @item exclude-files The clue of this entry should be any number of files. This files will not be loaded, even though they would normally be so, for some reason or other. + @item eval The value of this entry will be @code{eval}el. This element will be ignored when handling global score files. + @item read-only Read-only score files will not be updated or saved. Global score files should feature this atom (@pxref{Global Score Files}). + @item orphan The value of this entry should be a number. Articles that do not have parents will get this number added to their scores. + @item adapt This entry controls the adaptive scoring. If it is @code{t}, the default adaptive scoring rules will be used. If it is @code{ignore}, no *************** *** 8189,8194 **** --- 8341,8353 ---- groups, you'd set @code{gnus-use-adaptive-scoring} to @code{nil}, and insert @code{(adapt t)} in the score files of the groups where you want it. + + @item adapt-file + All adaptive score entries will go to the file named by this entry. It + will also be applied when entering the group. This atom might be handy + if you want to adapt on several groups at once, using the same adaptive + file for a number of groups. + @item local @cindex local variables The value of this entry should be a list of @code{(VAR VALUE)} pairs. *************** *** 8948,8953 **** --- 9107,9113 ---- variable says how long the other elements on the line is (i.e., the non-info part). If you put additional elements on the mode line (eg. a clock), you should modify this variable: + @c Hook written by Keinonen Kari . @lisp (add-hook 'display-time-hook *************** *** 8955,8960 **** --- 9115,9123 ---- (setq gnus-mode-non-string-length (+ 21 (length display-time-string))))) @end lisp + + If this variable is @code{nil} (which is the default), the mode line + strings won't be chopped off, and they won't be padded either. @item gnus-visual @vindex gnus-visual *** pub/sgnus/texi/ChangeLog Sun Dec 10 12:08:42 1995 --- sgnus/texi/ChangeLog Wed Dec 13 18:21:44 1995 *************** *** 1,3 **** --- 1,33 ---- + Wed Dec 13 16:13:56 1995 Lars Ingebrigtsen + + * gnus.texi (Selecting a Group): Addition. + (Saving Articles): Addition. + (Score File Format): Addition. + + Tue Dec 12 11:04:14 1995 Lars Ingebrigtsen + + * gnus.texi (Other Marks): Addition; change. + (Exiting the Summary Buffer): Addition. + (Hiding Headers): Addition. + (Score File Format): Addition. + (Article Caching): Addition. + (Misc Group Stuff): Addition. + + Mon Dec 11 09:52:34 1995 Lars Ingebrigtsen + + * gnus.texi (Persistent Articles): New. + (Other Marks): Addition. + (Topic Variables): Deletia. + (New Groups): Addition. + (Subscription Commands): Addition. + (Selecting a Group): Addition. + (Viewing Files): Addition. + (Group Levels): Addition. + + Sun Dec 10 13:51:16 1995 Lars Ingebrigtsen + + * gnus.texi (The Active File): Change. + Sat Dec 9 16:55:29 1995 Lars Ingebrigtsen * gnus.texi (nndoc): Change.