Gnus development mailing list
 help / color / mirror / Atom feed
* Continuation lines for persistent articles
@ 2002-10-13  5:47 TSUCHIYA Masatoshi
  2002-10-13 17:27 ` Kai Großjohann
  0 siblings, 1 reply; 5+ messages in thread
From: TSUCHIYA Masatoshi @ 2002-10-13  5:47 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 461 bytes --]

Hello, Gnus developers.

I found the bug that continuation lines are not treated for persistent
articles.  For example, when an article whose subject consists of
continuation lines is entered to cache, its subject is truncated to
the first new-line.  So, I propose the following change.

2002-10-13  TSUCHIYA Masatoshi  <tsuchiya@namazu.org>

	* gnus-cache.el (gnus-cache-possibly-enter-article): Fold
	continuation lines and turn TAB into SPC before parsing.


[-- Attachment #2: Type: text/plain, Size: 577 bytes --]

--- gnus-cache.el.orig	2002-08-05 16:30:26.000000000 +0900
+++ gnus-cache.el	2002-10-13 14:21:41.000000000 +0900
@@ -179,6 +179,11 @@
 	    (when (> (buffer-size) 0)
 	      (let ((coding-system-for-write gnus-cache-coding-system))
 		(gnus-write-buffer file))
+	      (save-restriction
+		(nnheader-narrow-to-headers)
+		(nnheader-ms-strip-cr)
+		(nnheader-fold-continuation-lines)
+		(subst-char-in-region (point-min) (point-max) ?\t ? ))
 	      (setq headers (nnheader-parse-head t))
 	      (mail-header-set-number headers number)
 	      (gnus-cache-change-buffer group)

[-- Attachment #3: Type: text/plain, Size: 229 bytes --]


I am worry that all functions which call nnheader-parse-head() must
fold continuation lines before calling it.  If this observation is
right, a better approach would make nnheader-parse-head() fold them.

-- 
TSUCHIYA Masatoshi

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Continuation lines for persistent articles
  2002-10-13  5:47 Continuation lines for persistent articles TSUCHIYA Masatoshi
@ 2002-10-13 17:27 ` Kai Großjohann
  2002-10-17 13:19   ` TSUCHIYA Masatoshi
  2002-10-17 13:32   ` TSUCHIYA Masatoshi
  0 siblings, 2 replies; 5+ messages in thread
From: Kai Großjohann @ 2002-10-13 17:27 UTC (permalink / raw)


TSUCHIYA Masatoshi <tsuchiya@namazu.org> writes:

> I am worry that all functions which call nnheader-parse-head() must
> fold continuation lines before calling it.  If this observation is
> right, a better approach would make nnheader-parse-head() fold them.

I think this is a good idea.

kai
-- 
~/.signature is: umop ap!sdn    (Frank Nobis)



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Continuation lines for persistent articles
  2002-10-13 17:27 ` Kai Großjohann
@ 2002-10-17 13:19   ` TSUCHIYA Masatoshi
  2002-10-17 13:32   ` TSUCHIYA Masatoshi
  1 sibling, 0 replies; 5+ messages in thread
From: TSUCHIYA Masatoshi @ 2002-10-17 13:19 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=iso-2022-jp-2, Size: 2102 bytes --]

Hi,

>> On Sun, 13 Oct 2002 19:27:05 +0200
>> Kai.Grossjohann@CS.Uni-Dortmund.DE (Kai Gro^[.A^[N_johann) said as follows:

>> I am worry that all functions which call nnheader-parse-head() must
>> unfold continuation lines before calling it.  If this observation
>> is right, a better approach would be to make nnheader-parse-head()
>> unfold them.

>I think this is a good idea.

I see.

I think that related changes can be splited into 2 parts.

The first part is installed to nnheader.el.  This change introduces
some new functions and makes nnheader-parse-head() unfold continuation
lines.

        nnheader.el (nnheader-parse-naked-head): New function.
        (nnheader-parse-head): Use the above function, in order to
        handle continuation lines properly.
        (nnheader-remove-body): New function.
        (nnheader-remove-cr-followed-by-lf): New function.
        (nnheader-ms-strip-cr): Use the above function.

I hope that this change can be installed to Gnus without ill effects.
However, I suppose that it makes Gnus slow, because the new version of
nnheader-parse-head() copies headers to temporary buffer in order to
avoid side effects.

The second part is required to reduce excessive header copy.  I hope
that these changes will make Gnus as fast as the older version.

        gnus-agent.el (gnus-agent-regenerate-group): Call
        `nnheader-remove-body'; Use `nnheader-parse-naked-head'
        instead of `nnheader-parse-head'.
        gnus-cache.el (gnus-cache-possibly-enter-article): Ditto.
        gnus-msg.el (gnus-inews-yank-articles): Do not unfold
        continuation lines by itself;  Call `nnheader-parse-naked-head'
        instead of `nnheader-parse-head'.
        nndiary.el (nndiary-parse-head): Ditto.
        nnfolder.el (nnfolder-parse-head): Ditto.
        nnimap.el (nnimap-retrieve-headers-progress): Ditto.
        nnmaildir.el (nnmaildir--update-nov): Ditto.
        nnml.el (nnml-parse-head): Ditto.

I checked changes of gnus-cache.el and nnml.el, but the other changes
are not tested.

Thanks to Mr. Yamaoka for his advices about these changes.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 14750 bytes --]

Index: gnus-agent.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/gnus-agent.el,v
retrieving revision 6.82
diff -u -r6.82 gnus-agent.el
--- gnus-agent.el	2002/10/15 10:15:48	6.82
+++ gnus-agent.el	2002/10/17 06:57:36
@@ -2031,11 +2031,8 @@
 	      (mm-with-unibyte-buffer
 		(nnheader-insert-file-contents
 		 (concat dir (number-to-string (car arts))))
-		(goto-char (point-min))
-		(if (search-forward "\n\n" nil t)
-		    (delete-region (point) (point-max))
-		  (goto-char (point-max)))
-		(setq header (nnheader-parse-head t)))
+		(nnheader-remove-body)
+		(setq header (nnheader-parse-naked-head)))
 	      (mail-header-set-number header (car arts))
 	      (nnheader-insert-nov header)
 	      (setq changed t)
Index: gnus-cache.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/gnus-cache.el,v
retrieving revision 6.18
diff -u -r6.18 gnus-cache.el
--- gnus-cache.el	2002/06/16 09:49:28	6.18
+++ gnus-cache.el	2002/10/17 06:57:36
@@ -179,7 +179,8 @@
 	    (when (> (buffer-size) 0)
 	      (let ((coding-system-for-write gnus-cache-coding-system))
 		(gnus-write-buffer file))
-	      (setq headers (nnheader-parse-head t))
+	      (nnheader-remove-body)
+	      (setq headers (nnheader-parse-naked-head))
 	      (mail-header-set-number headers number)
 	      (gnus-cache-change-buffer group)
 	      (set-buffer (cdr gnus-cache-buffer))
Index: gnus-msg.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/gnus-msg.el,v
retrieving revision 6.100
diff -u -r6.100 gnus-msg.el
--- gnus-msg.el	2002/09/25 23:45:17	6.100
+++ gnus-msg.el	2002/10/17 06:57:37
@@ -719,8 +719,7 @@
 	     (with-current-buffer gnus-article-copy
 	       (save-restriction
 		 (nnheader-narrow-to-headers)
-		 (ietf-drums-unfold-fws)
-		 (nnheader-parse-head t)))))
+		 (nnheader-parse-naked-head)))))
 	(message-yank-original)
 	(setq beg (or beg (mark t))))
       (when articles
Index: nndiary.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nndiary.el,v
retrieving revision 1.6
diff -u -r1.6 nndiary.el
--- nndiary.el	2002/05/15 19:55:38	1.6
+++ nndiary.el	2002/10/17 06:57:37
@@ -1123,13 +1123,7 @@
 	(narrow-to-region
 	 (goto-char (point-min))
 	 (if (search-forward "\n\n" nil t) (1- (point)) (point-max))))
-      ;; Fold continuation lines.
-      (goto-char (point-min))
-      (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
-	(replace-match " " t t))
-      ;; Remove any tabs; they are too confusing.
-      (subst-char-in-region (point-min) (point-max) ?\t ? )
-      (let ((headers (nnheader-parse-head t)))
+      (let ((headers (nnheader-parse-naked-head)))
 	(mail-header-set-chars headers chars)
 	(mail-header-set-number headers number)
 	headers))))
Index: nnfolder.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnfolder.el,v
retrieving revision 6.42
diff -u -r6.42 nnfolder.el
--- nnfolder.el	2002/07/20 14:41:21	6.42
+++ nnfolder.el	2002/10/17 06:57:37
@@ -1150,13 +1150,7 @@
 	(if (search-forward "\n\n" e t) (setq e (1- (point)))))
       (with-temp-buffer
 	(insert-buffer-substring buf b e)
-	;; Fold continuation lines.
-	(goto-char (point-min))
-	(while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
-	  (replace-match " " t t))
-	;; Remove any tabs; they are too confusing.
-	(subst-char-in-region (point-min) (point-max) ?\t ? )
-	(let ((headers (nnheader-parse-head t)))
+	(let ((headers (nnheader-parse-naked-head)))
 	  (mail-header-set-chars headers chars)
 	  (mail-header-set-number headers number)
 	  headers)))))
Index: nnheader.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnheader.el,v
retrieving revision 6.28
diff -u -r6.28 nnheader.el
--- nnheader.el	2002/08/20 09:12:50	6.28
+++ nnheader.el	2002/10/17 06:57:37
@@ -213,120 +213,135 @@
 
 ;; Parsing headers and NOV lines.
 
+(defsubst nnheader-remove-cr-followed-by-lf ()
+  (goto-char (point-max))
+  (while (search-backward "\r\n" nil t)
+    (delete-char 1)))
+
 (defsubst nnheader-header-value ()
   (skip-chars-forward " \t")
   (buffer-substring (point) (gnus-point-at-eol)))
 
-(defun nnheader-parse-head (&optional naked)
+(defun nnheader-parse-naked-head (&optional number)
+  ;; This function unfolds continuation lines in this buffer
+  ;; destructively.  When this side effect is unwanted, use
+  ;; `nnheader-parse-head' instead of this function.
   (let ((case-fold-search t)
-	(cur (current-buffer))
 	(buffer-read-only nil)
-	in-reply-to lines p ref)
-    (goto-char (point-min))
-    (when naked
-      (insert "\n"))
-    ;; Search to the beginning of the next header.  Error messages
-    ;; do not begin with 2 or 3.
+	(cur (current-buffer))
+	(p (point-min))
+	in-reply-to lines ref)
+    (nnheader-remove-cr-followed-by-lf)
+    (ietf-drums-unfold-fws)
+    (subst-char-in-region (point-min) (point-max) ?\t ? )
+    (goto-char p)
+    (insert "\n")
     (prog1
-	(when (or naked (re-search-forward "^[23][0-9]+ " nil t))
-	  ;; This implementation of this function, with nine
-	  ;; search-forwards instead of the one re-search-forward and
-	  ;; a case (which basically was the old function) is actually
-	  ;; about twice as fast, even though it looks messier.	 You
-	  ;; can't have everything, I guess.  Speed and elegance
-	  ;; don't always go hand in hand.
-	  (vector
-	   ;; Number.
-	   (if naked
-	       (progn
-		 (setq p (point-min))
-		 0)
-	     (prog1
-		 (read cur)
-	       (end-of-line)
-	       (setq p (point))
-	       (narrow-to-region (point)
-				 (or (and (search-forward "\n.\n" nil t)
-					  (- (point) 2))
-				     (point)))))
-	   ;; Subject.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nsubject:" nil t)
-		 (nnheader-header-value) "(none)"))
-	   ;; From.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nfrom:" nil t)
-		 (nnheader-header-value) "(nobody)"))
-	   ;; Date.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\ndate:" nil t)
-		 (nnheader-header-value) ""))
-	   ;; Message-ID.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nmessage-id:" nil t)
-		 (buffer-substring
-		  (1- (or (search-forward "<" (gnus-point-at-eol) t)
-			  (point)))
-		  (or (search-forward ">" (gnus-point-at-eol) t) (point)))
-	       ;; If there was no message-id, we just fake one to make
-	       ;; subsequent routines simpler.
-	       (nnheader-generate-fake-message-id)))
-	   ;; References.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nreferences:" nil t)
-		 (nnheader-header-value)
-	       ;; Get the references from the in-reply-to header if there
-	       ;; were no references and the in-reply-to header looks
-	       ;; promising.
-	       (if (and (search-forward "\nin-reply-to:" nil t)
-			(setq in-reply-to (nnheader-header-value))
-			(string-match "<[^\n>]+>" in-reply-to))
-		   (let (ref2)
-		     (setq ref (substring in-reply-to (match-beginning 0)
-					  (match-end 0)))
-		     (while (string-match "<[^\n>]+>"
-					  in-reply-to (match-end 0))
-		       (setq ref2 (substring in-reply-to (match-beginning 0)
-					     (match-end 0)))
-		       (when (> (length ref2) (length ref))
-			 (setq ref ref2)))
-		     ref)
-		 nil)))
-	   ;; Chars.
-	   0
-	   ;; Lines.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nlines: " nil t)
-		 (if (numberp (setq lines (read cur)))
-		     lines 0)
-	       0))
-	   ;; Xref.
-	   (progn
-	     (goto-char p)
-	     (and (search-forward "\nxref:" nil t)
-		  (nnheader-header-value)))
-
-	   ;; Extra.
-	   (when nnmail-extra-headers
-	     (let ((extra nnmail-extra-headers)
-		   out)
-	       (while extra
-		 (goto-char p)
-		 (when (search-forward
-			(concat "\n" (symbol-name (car extra)) ":") nil t)
-		   (push (cons (car extra) (nnheader-header-value))
-			 out))
-		 (pop extra))
-	       out))))
-      (when naked
-	(goto-char (point-min))
-	(delete-char 1)))))
+	;; This implementation of this function, with nine
+	;; search-forwards instead of the one re-search-forward and a
+	;; case (which basically was the old function) is actually
+	;; about twice as fast, even though it looks messier.  You
+	;; can't have everything, I guess.  Speed and elegance don't
+	;; always go hand in hand.
+	(vector
+	 ;; Number.
+	 (or number 0)
+	 ;; Subject.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nsubject:" nil t)
+	       (nnheader-header-value) "(none)"))
+	 ;; From.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nfrom:" nil t)
+	       (nnheader-header-value) "(nobody)"))
+	 ;; Date.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\ndate:" nil t)
+	       (nnheader-header-value) ""))
+	 ;; Message-ID.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nmessage-id:" nil t)
+	       (buffer-substring
+		(1- (or (search-forward "<" (gnus-point-at-eol) t)
+			(point)))
+		(or (search-forward ">" (gnus-point-at-eol) t) (point)))
+	     ;; If there was no message-id, we just fake one to make
+	     ;; subsequent routines simpler.
+	     (nnheader-generate-fake-message-id)))
+	 ;; References.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nreferences:" nil t)
+	       (nnheader-header-value)
+	     ;; Get the references from the in-reply-to header if
+	     ;; there were no references and the in-reply-to header
+	     ;; looks promising.
+	     (if (and (search-forward "\nin-reply-to:" nil t)
+		      (setq in-reply-to (nnheader-header-value))
+		      (string-match "<[^\n>]+>" in-reply-to))
+		 (let (ref2)
+		   (setq ref (substring in-reply-to (match-beginning 0)
+					(match-end 0)))
+		   (while (string-match "<[^\n>]+>"
+					in-reply-to (match-end 0))
+		     (setq ref2 (substring in-reply-to (match-beginning 0)
+					   (match-end 0)))
+		     (when (> (length ref2) (length ref))
+		       (setq ref ref2)))
+		   ref)
+	       nil)))
+	 ;; Chars.
+	 0
+	 ;; Lines.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nlines: " nil t)
+	       (if (numberp (setq lines (read cur)))
+		   lines 0)
+	     0))
+	 ;; Xref.
+	 (progn
+	   (goto-char p)
+	   (and (search-forward "\nxref:" nil t)
+		(nnheader-header-value)))
+	 ;; Extra.
+	 (when nnmail-extra-headers
+	   (let ((extra nnmail-extra-headers)
+		 out)
+	     (while extra
+	       (goto-char p)
+	       (when (search-forward
+		      (concat "\n" (symbol-name (car extra)) ":") nil t)
+		 (push (cons (car extra) (nnheader-header-value))
+		       out))
+	       (pop extra))
+	     out)))
+      (goto-char p)
+      (delete-char 1))))
+
+(defun nnheader-parse-head (&optional naked)
+  (let ((cur (current-buffer)) num beg end)
+    (when (if naked
+	      (setq num 0
+		    beg (point-min)
+		    end (point-max))
+	    (goto-char (point-min))
+	    ;; Search to the beginning of the next header.  Error
+	    ;; messages do not begin with 2 or 3.
+	    (when (re-search-forward "^[23][0-9]+ " nil t)
+	      (end-of-line)
+	      (setq num (read cur)
+		    beg (point)
+		    end (if (search-forward "\n.\n" nil t)
+			    (- (point) 2)
+			  (point)))))
+      (with-temp-buffer
+	(insert-buffer-substring cur beg end)
+	(nnheader-parse-naked-head num)))))
 
 (defmacro nnheader-nov-skip-field ()
   '(search-forward "\t" eol 'move))
@@ -615,6 +630,13 @@
      (point-max)))
   (goto-char (point-min)))
 
+(defun nnheader-remove-body ()
+  "Remove the body from an article in this current buffer."
+  (goto-char (point-min))
+  (when (or (search-forward "\n\n" nil t)
+	    (search-forward "\n\r\n" nil t))
+    (delete-region (point) (point-max))))
+
 (defun nnheader-set-temp-buffer (name &optional noerase)
   "Set-buffer to an empty (possibly new) buffer called NAME with undo disabled."
   (set-buffer (get-buffer-create name))
@@ -834,9 +856,7 @@
 (defun nnheader-ms-strip-cr ()
   "Strip ^M from the end of all lines."
   (save-excursion
-    (goto-char (point-min))
-    (while (re-search-forward "\r$" nil t)
-      (delete-backward-char 1))))
+    (nnheader-remove-cr-followed-by-lf)))
 
 (defun nnheader-file-size (file)
   "Return the file size of FILE or 0."
Index: nnimap.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnimap.el,v
retrieving revision 6.48
diff -u -r6.48 nnimap.el
--- nnimap.el	2002/10/10 02:40:50	6.48
+++ nnimap.el	2002/10/17 06:57:38
@@ -528,10 +528,7 @@
        (with-temp-buffer
 	 (buffer-disable-undo)
 	 (insert headers)
-	 (nnheader-ms-strip-cr)
-	 (nnheader-fold-continuation-lines)
-	 (subst-char-in-region (point-min) (point-max) ?\t ? )
-	 (let ((head (nnheader-parse-head 'naked)))
+	 (let ((head (nnheader-parse-naked-head)))
 	   (mail-header-set-number head uid)
 	   (mail-header-set-chars head chars)
 	   (mail-header-set-lines head lines)
Index: nnmaildir.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnmaildir.el,v
retrieving revision 6.21
diff -u -r6.21 nnmaildir.el
--- nnmaildir.el	2002/10/03 18:16:25	6.21
+++ nnmaildir.el	2002/10/17 06:57:38
@@ -371,8 +371,7 @@
 	    (setq nov-mid 0))
 	  (goto-char (point-min))
 	  (delete-char 1)
-	  (nnheader-fold-continuation-lines)
-	  (setq nov (nnheader-parse-head 'naked)
+	  (setq nov (nnheader-parse-naked-head)
 		field (or (mail-header-lines nov) 0)))
 	(unless (or (zerop field) (nnmaildir--param pgname 'distrust-Lines:))
 	  (setq nov-mid field))
Index: nnml.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnml.el,v
retrieving revision 6.40
diff -u -r6.40 nnml.el
--- nnml.el	2002/05/13 15:29:09	6.40
+++ nnml.el	2002/10/17 06:57:38
@@ -701,16 +701,12 @@
       (unless (zerop (buffer-size))
 	(narrow-to-region
 	 (goto-char (point-min))
-	 (if (re-search-forward "\n\r?\n" nil t) (1- (point)) (point-max))))
-      ;; Fold continuation lines.
-      (goto-char (point-min))
-      (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
-	(replace-match " " t t))
-      ;; Remove any tabs; they are too confusing.
-      (subst-char-in-region (point-min) (point-max) ?\t ? )
-      ;; Remove any ^M's; they are too confusing.
-      (subst-char-in-region (point-min) (point-max) ?\r ? )
-      (let ((headers (nnheader-parse-head t)))
+	 (if (search-forward "\n\n" nil t)
+	     (1- (point))
+	   (if (search-forward "\n\r\n" nil t)
+	       (- (point) 2)
+	     (point-max)))))
+      (let ((headers (nnheader-parse-naked-head)))
 	(mail-header-set-chars headers chars)
 	(mail-header-set-number headers number)
 	headers))))

[-- Attachment #3: Type: application/octet-stream, Size: 23 bytes --]

-- 
TSUCHIYA Masatoshi

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Continuation lines for persistent articles
  2002-10-13 17:27 ` Kai Großjohann
  2002-10-17 13:19   ` TSUCHIYA Masatoshi
@ 2002-10-17 13:32   ` TSUCHIYA Masatoshi
  2002-10-17 15:09     ` Katsumi Yamaoka
  1 sibling, 1 reply; 5+ messages in thread
From: TSUCHIYA Masatoshi @ 2002-10-17 13:32 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=iso-2022-jp-2, Size: 2102 bytes --]

Hi,

>> On Sun, 13 Oct 2002 19:27:05 +0200
>> Kai.Grossjohann@CS.Uni-Dortmund.DE (Kai Gro^[.A^[N_johann) said as follows:

>> I am worry that all functions which call nnheader-parse-head() must
>> unfold continuation lines before calling it.  If this observation
>> is right, a better approach would be to make nnheader-parse-head()
>> unfold them.

>I think this is a good idea.

I see.

I think that related changes can be splited into 2 parts.

The first part is installed to nnheader.el.  This change introduces
some new functions and makes nnheader-parse-head() unfold continuation
lines.

        nnheader.el (nnheader-parse-naked-head): New function.
        (nnheader-parse-head): Use the above function, in order to
        handle continuation lines properly.
        (nnheader-remove-body): New function.
        (nnheader-remove-cr-followed-by-lf): New function.
        (nnheader-ms-strip-cr): Use the above function.

I hope that this change can be installed to Gnus without ill effects.
However, I suppose that it makes Gnus slow, because the new version of
nnheader-parse-head() copies headers to temporary buffer in order to
avoid side effects.

The second part is required to reduce excessive header copy.  I hope
that these changes will make Gnus as fast as the older version.

        gnus-agent.el (gnus-agent-regenerate-group): Call
        `nnheader-remove-body'; Use `nnheader-parse-naked-head'
        instead of `nnheader-parse-head'.
        gnus-cache.el (gnus-cache-possibly-enter-article): Ditto.
        gnus-msg.el (gnus-inews-yank-articles): Do not unfold
        continuation lines by itself;  Call `nnheader-parse-naked-head'
        instead of `nnheader-parse-head'.
        nndiary.el (nndiary-parse-head): Ditto.
        nnfolder.el (nnfolder-parse-head): Ditto.
        nnimap.el (nnimap-retrieve-headers-progress): Ditto.
        nnmaildir.el (nnmaildir--update-nov): Ditto.
        nnml.el (nnml-parse-head): Ditto.

I checked changes of gnus-cache.el and nnml.el, but the other changes
are not tested.

Thanks to Mr. Yamaoka for his advices about these changes.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 14750 bytes --]

Index: gnus-agent.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/gnus-agent.el,v
retrieving revision 6.82
diff -u -r6.82 gnus-agent.el
--- gnus-agent.el	2002/10/15 10:15:48	6.82
+++ gnus-agent.el	2002/10/17 06:57:36
@@ -2031,11 +2031,8 @@
 	      (mm-with-unibyte-buffer
 		(nnheader-insert-file-contents
 		 (concat dir (number-to-string (car arts))))
-		(goto-char (point-min))
-		(if (search-forward "\n\n" nil t)
-		    (delete-region (point) (point-max))
-		  (goto-char (point-max)))
-		(setq header (nnheader-parse-head t)))
+		(nnheader-remove-body)
+		(setq header (nnheader-parse-naked-head)))
 	      (mail-header-set-number header (car arts))
 	      (nnheader-insert-nov header)
 	      (setq changed t)
Index: gnus-cache.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/gnus-cache.el,v
retrieving revision 6.18
diff -u -r6.18 gnus-cache.el
--- gnus-cache.el	2002/06/16 09:49:28	6.18
+++ gnus-cache.el	2002/10/17 06:57:36
@@ -179,7 +179,8 @@
 	    (when (> (buffer-size) 0)
 	      (let ((coding-system-for-write gnus-cache-coding-system))
 		(gnus-write-buffer file))
-	      (setq headers (nnheader-parse-head t))
+	      (nnheader-remove-body)
+	      (setq headers (nnheader-parse-naked-head))
 	      (mail-header-set-number headers number)
 	      (gnus-cache-change-buffer group)
 	      (set-buffer (cdr gnus-cache-buffer))
Index: gnus-msg.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/gnus-msg.el,v
retrieving revision 6.100
diff -u -r6.100 gnus-msg.el
--- gnus-msg.el	2002/09/25 23:45:17	6.100
+++ gnus-msg.el	2002/10/17 06:57:37
@@ -719,8 +719,7 @@
 	     (with-current-buffer gnus-article-copy
 	       (save-restriction
 		 (nnheader-narrow-to-headers)
-		 (ietf-drums-unfold-fws)
-		 (nnheader-parse-head t)))))
+		 (nnheader-parse-naked-head)))))
 	(message-yank-original)
 	(setq beg (or beg (mark t))))
       (when articles
Index: nndiary.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nndiary.el,v
retrieving revision 1.6
diff -u -r1.6 nndiary.el
--- nndiary.el	2002/05/15 19:55:38	1.6
+++ nndiary.el	2002/10/17 06:57:37
@@ -1123,13 +1123,7 @@
 	(narrow-to-region
 	 (goto-char (point-min))
 	 (if (search-forward "\n\n" nil t) (1- (point)) (point-max))))
-      ;; Fold continuation lines.
-      (goto-char (point-min))
-      (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
-	(replace-match " " t t))
-      ;; Remove any tabs; they are too confusing.
-      (subst-char-in-region (point-min) (point-max) ?\t ? )
-      (let ((headers (nnheader-parse-head t)))
+      (let ((headers (nnheader-parse-naked-head)))
 	(mail-header-set-chars headers chars)
 	(mail-header-set-number headers number)
 	headers))))
Index: nnfolder.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnfolder.el,v
retrieving revision 6.42
diff -u -r6.42 nnfolder.el
--- nnfolder.el	2002/07/20 14:41:21	6.42
+++ nnfolder.el	2002/10/17 06:57:37
@@ -1150,13 +1150,7 @@
 	(if (search-forward "\n\n" e t) (setq e (1- (point)))))
       (with-temp-buffer
 	(insert-buffer-substring buf b e)
-	;; Fold continuation lines.
-	(goto-char (point-min))
-	(while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
-	  (replace-match " " t t))
-	;; Remove any tabs; they are too confusing.
-	(subst-char-in-region (point-min) (point-max) ?\t ? )
-	(let ((headers (nnheader-parse-head t)))
+	(let ((headers (nnheader-parse-naked-head)))
 	  (mail-header-set-chars headers chars)
 	  (mail-header-set-number headers number)
 	  headers)))))
Index: nnheader.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnheader.el,v
retrieving revision 6.28
diff -u -r6.28 nnheader.el
--- nnheader.el	2002/08/20 09:12:50	6.28
+++ nnheader.el	2002/10/17 06:57:37
@@ -213,120 +213,135 @@
 
 ;; Parsing headers and NOV lines.
 
+(defsubst nnheader-remove-cr-followed-by-lf ()
+  (goto-char (point-max))
+  (while (search-backward "\r\n" nil t)
+    (delete-char 1)))
+
 (defsubst nnheader-header-value ()
   (skip-chars-forward " \t")
   (buffer-substring (point) (gnus-point-at-eol)))
 
-(defun nnheader-parse-head (&optional naked)
+(defun nnheader-parse-naked-head (&optional number)
+  ;; This function unfolds continuation lines in this buffer
+  ;; destructively.  When this side effect is unwanted, use
+  ;; `nnheader-parse-head' instead of this function.
   (let ((case-fold-search t)
-	(cur (current-buffer))
 	(buffer-read-only nil)
-	in-reply-to lines p ref)
-    (goto-char (point-min))
-    (when naked
-      (insert "\n"))
-    ;; Search to the beginning of the next header.  Error messages
-    ;; do not begin with 2 or 3.
+	(cur (current-buffer))
+	(p (point-min))
+	in-reply-to lines ref)
+    (nnheader-remove-cr-followed-by-lf)
+    (ietf-drums-unfold-fws)
+    (subst-char-in-region (point-min) (point-max) ?\t ? )
+    (goto-char p)
+    (insert "\n")
     (prog1
-	(when (or naked (re-search-forward "^[23][0-9]+ " nil t))
-	  ;; This implementation of this function, with nine
-	  ;; search-forwards instead of the one re-search-forward and
-	  ;; a case (which basically was the old function) is actually
-	  ;; about twice as fast, even though it looks messier.	 You
-	  ;; can't have everything, I guess.  Speed and elegance
-	  ;; don't always go hand in hand.
-	  (vector
-	   ;; Number.
-	   (if naked
-	       (progn
-		 (setq p (point-min))
-		 0)
-	     (prog1
-		 (read cur)
-	       (end-of-line)
-	       (setq p (point))
-	       (narrow-to-region (point)
-				 (or (and (search-forward "\n.\n" nil t)
-					  (- (point) 2))
-				     (point)))))
-	   ;; Subject.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nsubject:" nil t)
-		 (nnheader-header-value) "(none)"))
-	   ;; From.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nfrom:" nil t)
-		 (nnheader-header-value) "(nobody)"))
-	   ;; Date.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\ndate:" nil t)
-		 (nnheader-header-value) ""))
-	   ;; Message-ID.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nmessage-id:" nil t)
-		 (buffer-substring
-		  (1- (or (search-forward "<" (gnus-point-at-eol) t)
-			  (point)))
-		  (or (search-forward ">" (gnus-point-at-eol) t) (point)))
-	       ;; If there was no message-id, we just fake one to make
-	       ;; subsequent routines simpler.
-	       (nnheader-generate-fake-message-id)))
-	   ;; References.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nreferences:" nil t)
-		 (nnheader-header-value)
-	       ;; Get the references from the in-reply-to header if there
-	       ;; were no references and the in-reply-to header looks
-	       ;; promising.
-	       (if (and (search-forward "\nin-reply-to:" nil t)
-			(setq in-reply-to (nnheader-header-value))
-			(string-match "<[^\n>]+>" in-reply-to))
-		   (let (ref2)
-		     (setq ref (substring in-reply-to (match-beginning 0)
-					  (match-end 0)))
-		     (while (string-match "<[^\n>]+>"
-					  in-reply-to (match-end 0))
-		       (setq ref2 (substring in-reply-to (match-beginning 0)
-					     (match-end 0)))
-		       (when (> (length ref2) (length ref))
-			 (setq ref ref2)))
-		     ref)
-		 nil)))
-	   ;; Chars.
-	   0
-	   ;; Lines.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nlines: " nil t)
-		 (if (numberp (setq lines (read cur)))
-		     lines 0)
-	       0))
-	   ;; Xref.
-	   (progn
-	     (goto-char p)
-	     (and (search-forward "\nxref:" nil t)
-		  (nnheader-header-value)))
-
-	   ;; Extra.
-	   (when nnmail-extra-headers
-	     (let ((extra nnmail-extra-headers)
-		   out)
-	       (while extra
-		 (goto-char p)
-		 (when (search-forward
-			(concat "\n" (symbol-name (car extra)) ":") nil t)
-		   (push (cons (car extra) (nnheader-header-value))
-			 out))
-		 (pop extra))
-	       out))))
-      (when naked
-	(goto-char (point-min))
-	(delete-char 1)))))
+	;; This implementation of this function, with nine
+	;; search-forwards instead of the one re-search-forward and a
+	;; case (which basically was the old function) is actually
+	;; about twice as fast, even though it looks messier.  You
+	;; can't have everything, I guess.  Speed and elegance don't
+	;; always go hand in hand.
+	(vector
+	 ;; Number.
+	 (or number 0)
+	 ;; Subject.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nsubject:" nil t)
+	       (nnheader-header-value) "(none)"))
+	 ;; From.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nfrom:" nil t)
+	       (nnheader-header-value) "(nobody)"))
+	 ;; Date.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\ndate:" nil t)
+	       (nnheader-header-value) ""))
+	 ;; Message-ID.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nmessage-id:" nil t)
+	       (buffer-substring
+		(1- (or (search-forward "<" (gnus-point-at-eol) t)
+			(point)))
+		(or (search-forward ">" (gnus-point-at-eol) t) (point)))
+	     ;; If there was no message-id, we just fake one to make
+	     ;; subsequent routines simpler.
+	     (nnheader-generate-fake-message-id)))
+	 ;; References.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nreferences:" nil t)
+	       (nnheader-header-value)
+	     ;; Get the references from the in-reply-to header if
+	     ;; there were no references and the in-reply-to header
+	     ;; looks promising.
+	     (if (and (search-forward "\nin-reply-to:" nil t)
+		      (setq in-reply-to (nnheader-header-value))
+		      (string-match "<[^\n>]+>" in-reply-to))
+		 (let (ref2)
+		   (setq ref (substring in-reply-to (match-beginning 0)
+					(match-end 0)))
+		   (while (string-match "<[^\n>]+>"
+					in-reply-to (match-end 0))
+		     (setq ref2 (substring in-reply-to (match-beginning 0)
+					   (match-end 0)))
+		     (when (> (length ref2) (length ref))
+		       (setq ref ref2)))
+		   ref)
+	       nil)))
+	 ;; Chars.
+	 0
+	 ;; Lines.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nlines: " nil t)
+	       (if (numberp (setq lines (read cur)))
+		   lines 0)
+	     0))
+	 ;; Xref.
+	 (progn
+	   (goto-char p)
+	   (and (search-forward "\nxref:" nil t)
+		(nnheader-header-value)))
+	 ;; Extra.
+	 (when nnmail-extra-headers
+	   (let ((extra nnmail-extra-headers)
+		 out)
+	     (while extra
+	       (goto-char p)
+	       (when (search-forward
+		      (concat "\n" (symbol-name (car extra)) ":") nil t)
+		 (push (cons (car extra) (nnheader-header-value))
+		       out))
+	       (pop extra))
+	     out)))
+      (goto-char p)
+      (delete-char 1))))
+
+(defun nnheader-parse-head (&optional naked)
+  (let ((cur (current-buffer)) num beg end)
+    (when (if naked
+	      (setq num 0
+		    beg (point-min)
+		    end (point-max))
+	    (goto-char (point-min))
+	    ;; Search to the beginning of the next header.  Error
+	    ;; messages do not begin with 2 or 3.
+	    (when (re-search-forward "^[23][0-9]+ " nil t)
+	      (end-of-line)
+	      (setq num (read cur)
+		    beg (point)
+		    end (if (search-forward "\n.\n" nil t)
+			    (- (point) 2)
+			  (point)))))
+      (with-temp-buffer
+	(insert-buffer-substring cur beg end)
+	(nnheader-parse-naked-head num)))))
 
 (defmacro nnheader-nov-skip-field ()
   '(search-forward "\t" eol 'move))
@@ -615,6 +630,13 @@
      (point-max)))
   (goto-char (point-min)))
 
+(defun nnheader-remove-body ()
+  "Remove the body from an article in this current buffer."
+  (goto-char (point-min))
+  (when (or (search-forward "\n\n" nil t)
+	    (search-forward "\n\r\n" nil t))
+    (delete-region (point) (point-max))))
+
 (defun nnheader-set-temp-buffer (name &optional noerase)
   "Set-buffer to an empty (possibly new) buffer called NAME with undo disabled."
   (set-buffer (get-buffer-create name))
@@ -834,9 +856,7 @@
 (defun nnheader-ms-strip-cr ()
   "Strip ^M from the end of all lines."
   (save-excursion
-    (goto-char (point-min))
-    (while (re-search-forward "\r$" nil t)
-      (delete-backward-char 1))))
+    (nnheader-remove-cr-followed-by-lf)))
 
 (defun nnheader-file-size (file)
   "Return the file size of FILE or 0."
Index: nnimap.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnimap.el,v
retrieving revision 6.48
diff -u -r6.48 nnimap.el
--- nnimap.el	2002/10/10 02:40:50	6.48
+++ nnimap.el	2002/10/17 06:57:38
@@ -528,10 +528,7 @@
        (with-temp-buffer
 	 (buffer-disable-undo)
 	 (insert headers)
-	 (nnheader-ms-strip-cr)
-	 (nnheader-fold-continuation-lines)
-	 (subst-char-in-region (point-min) (point-max) ?\t ? )
-	 (let ((head (nnheader-parse-head 'naked)))
+	 (let ((head (nnheader-parse-naked-head)))
 	   (mail-header-set-number head uid)
 	   (mail-header-set-chars head chars)
 	   (mail-header-set-lines head lines)
Index: nnmaildir.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnmaildir.el,v
retrieving revision 6.21
diff -u -r6.21 nnmaildir.el
--- nnmaildir.el	2002/10/03 18:16:25	6.21
+++ nnmaildir.el	2002/10/17 06:57:38
@@ -371,8 +371,7 @@
 	    (setq nov-mid 0))
 	  (goto-char (point-min))
 	  (delete-char 1)
-	  (nnheader-fold-continuation-lines)
-	  (setq nov (nnheader-parse-head 'naked)
+	  (setq nov (nnheader-parse-naked-head)
 		field (or (mail-header-lines nov) 0)))
 	(unless (or (zerop field) (nnmaildir--param pgname 'distrust-Lines:))
 	  (setq nov-mid field))
Index: nnml.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnml.el,v
retrieving revision 6.40
diff -u -r6.40 nnml.el
--- nnml.el	2002/05/13 15:29:09	6.40
+++ nnml.el	2002/10/17 06:57:38
@@ -701,16 +701,12 @@
       (unless (zerop (buffer-size))
 	(narrow-to-region
 	 (goto-char (point-min))
-	 (if (re-search-forward "\n\r?\n" nil t) (1- (point)) (point-max))))
-      ;; Fold continuation lines.
-      (goto-char (point-min))
-      (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
-	(replace-match " " t t))
-      ;; Remove any tabs; they are too confusing.
-      (subst-char-in-region (point-min) (point-max) ?\t ? )
-      ;; Remove any ^M's; they are too confusing.
-      (subst-char-in-region (point-min) (point-max) ?\r ? )
-      (let ((headers (nnheader-parse-head t)))
+	 (if (search-forward "\n\n" nil t)
+	     (1- (point))
+	   (if (search-forward "\n\r\n" nil t)
+	       (- (point) 2)
+	     (point-max)))))
+      (let ((headers (nnheader-parse-naked-head)))
 	(mail-header-set-chars headers chars)
 	(mail-header-set-number headers number)
 	headers))))

[-- Attachment #3: Type: text/plain, Size: 23 bytes --]

-- 
TSUCHIYA Masatoshi

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Continuation lines for persistent articles
  2002-10-17 13:32   ` TSUCHIYA Masatoshi
@ 2002-10-17 15:09     ` Katsumi Yamaoka
  0 siblings, 0 replies; 5+ messages in thread
From: Katsumi Yamaoka @ 2002-10-17 15:09 UTC (permalink / raw)
  Cc: ding

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=iso-2022-jp-2, Size: 893 bytes --]

Hi,

>>>>> In <87y98xry0p.fsf@namazu.org>
>>>>>	TSUCHIYA Masatoshi <tsuchiya@namazu.org> wrote:

>>> I am worry that all functions which call nnheader-parse-head() must
>>> unfold continuation lines before calling it.  If this observation
>>> is right, a better approach would be to make nnheader-parse-head()
>>> unfold them.

>> On Sun, 13 Oct 2002 19:27:05 +0200
>> Kai.Grossjohann@CS.Uni-Dortmund.DE (Kai Gro^[.A^[N_johann) said as follows:

>> I think this is a good idea.

> I see.  I think that related changes can be splited into 2 parts.

[...]

> I checked changes of gnus-cache.el and nnml.el, but the other changes
> are not tested.  Thanks to Mr. Yamaoka for his advices about these
> changes.

TSUCHIYA-san, thank you for the posting.  I was also checking
them from yesterday.  Since there's probably no problem, I've
checked it in at once.
-- 
Katsumi Yamaoka <yamaoka@jpl.org>



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2002-10-17 15:09 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-10-13  5:47 Continuation lines for persistent articles TSUCHIYA Masatoshi
2002-10-13 17:27 ` Kai Großjohann
2002-10-17 13:19   ` TSUCHIYA Masatoshi
2002-10-17 13:32   ` TSUCHIYA Masatoshi
2002-10-17 15:09     ` Katsumi Yamaoka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).