[comp.emacs] Gnews 1.3 fix

weemba@garnet.berkeley.edu (Matthew P Wiener) (03/27/88)

The junking of killed articles is handled incorrectly in Gnews 1.3,
leading to both infinite loops and rereading of articles.

The following versions of article-get and article-junk fix the problem.
Other bug fixes are on the way; this is the only one serious enough to
merit posting separately.

ucbvax!garnet!weemba	Matthew P Wiener/Brahms Gang/Berkeley CA 94720
----------------------------------------------------------------------
(defun article-get (number &optional hook interact)
  "Display article NUMBER of the current newsgroup.\n
In ELisp code, optional argument HOOK is a list of per-hooks to apply, and
a non-nil INTERACT means pretend this function was called interactively."
  (interactive "narticle #: ")
  (if (< article-final number)
      (group-last)
    (if (nntp-exec t t "head" number)
	(let ((b (current-buffer))
	      (gnews-hook-continue t)
	      lines)
	  (set-buffer nntp-buffer)
	  (if (or (interactive-p) interact)
	      (article-current-set number))
	  (setq article-field-list)
	  (while (and hook gnews-hook-continue)
	    (if (gnews-hook-do (car hook) nil)	; gnews-hook-junk property
		(progn
		  (gnews-hook-junk-message number hook)
		  (set-buffer b)		; I have to doooo this?
		  (throw 'article-nil t)))	; article KILLed; try again
	    (setq hook (cdr hook)))
	  (article-header-clean t)
	  (setq lines (article-effective-init-display))
	  (nntp-exec nil nil "body" number)
	  (while (and (nntp-run-p)	; catch a broken connection
		      (not nntp-eot)
		      (< (count-lines 1 (point-max))
			 (or lines
			     (window-height
			       (get-buffer-window news-buffer)))))
	    (gnews-accept-process-output nntp))
	  (if (not (nntp-run-p))
	      (news-quit
		(y-or-n-p "Connection died: save the current roster? ")))
	  (save-excursion			; get rid of NNTP info
	    (goto-char 1)
	    (re-search-forward "^222.*$")	; the NNTP info message
	    (setq nntp-info-true (buffer-substring
				    (match-beginning 0) (match-end 0)))
	    (replace-match ""))
	  (if lines (forward-line lines))
	  (setq article-grab-point (if lines (point)))
	  (article-display-init)
	  (nntp-finish)
	  (set-buffer nntp-buffer)
	  (goto-char 1)
	  (insert nntp-info ?\n)		; put back first field
	  (setq nntp-info nntp-info-true)
	  (set-buffer news-buffer)
	  (gnews-exec-1-pending)		; get one out before flushing
	  (if (setq article-junkable (article-done)) (article-quit)))
      (message "%d: null" number)
      (throw 'article-nil t)))			; article not found--give it up
  (gnews-flush))

(defun article-junk (&optional pfx art-no)
  "Mark current article as junked.\n
In ELisp code, non-nil optional argument PFX (the prefix argument)
means do a local junk, and non-nil argument ART-NO is the article
number to junk."
  (interactive "P")
  (setq gnews-hook-continue)			; terminate hook processing
  (if (and (eq article-junkable 'mark) (not (interactive-p))) nil
    (if (and (not pfx) art-no)
	(let ((b (current-buffer)))
	  (save-excursion
	    (set-buffer nntp-buffer)
	    (nntp-exec t t "head" art-no)
	    (article-header-clean t))
	  (set-buffer b)))
    (setcdr (cdr (assoc group-current group-roster)) amark-list)
    (let ((xgp (list nil))
	  (xref (list nil))
	  (str (if (or pfx (string-match "<0>" nntp-info))
		   "" (if article-field-list
			  (article-field "Xref")	; from a read article
			(let ((b (current-buffer)))	; from a per-hook junk
			  (save-excursion
			    (set-buffer nntp-buffer)
			    (goto-char (point-max))
			    (if (re-search-backward "^Xref: \\(.*\\)" nil t)
				(buffer-substring	; cross-posted
				  (match-beginning 1) (match-end 1))
			      ""))))))			; not cross-posted
	  ss)
      (if (string= str "")
	  (setq xref (list nil (or art-no article-current))
		xgp (list nil group-current))
	(while (string-match "\\([^ :]+\\):\\([0-9]+\\)" str ss)
	  (nconc xgp (list (substring
			     str (match-beginning 1) (match-end 1))))
	  (nconc xref (list (string-to-int
			      (substring
				str (match-beginning 2) (match-end 2)))))
	  (setq ss (match-end 0))))
      (gnews-map '(lambda (x y)
		    (let ((ngl (assoc x group-roster)))
		      (if ngl (setcdr (cdr ngl)
				      (amark-list-insert y (cddr ngl))))))
	(cdr xgp)
	(cdr xref)))
    (setq group-checkpoint t
	  amark-list (cddr (assoc group-current group-roster)))
    (if (and (boundp 'index-pop)		; index-mode is around
	     (null art-no))			; but this was direct
	(let ((b (current-buffer)))
	  (save-excursion
	    (set-buffer index-buffer)
	    (goto-char 1)
	    (if (re-search-forward
		  (concat "^\\(^ *" article-current "\\).") nil t)
		(index-junk-line nil)))
	  (set-buffer b))))
  (gnews-flush))