Commit a93e672e authored by Stefan Monnier's avatar Stefan Monnier

* lisp/gnus: Remove assumptions about mail-header being a vector

Use `mail-header-p` and `make-full-mail-header` instead of `vectorp` and
`vector`, respectively.

* lisp/gnus/message.el (message-cite-original-1, message-reply)
(message-followup):
* lisp/gnus/gnus-sum.el (gnus-get-newsgroup-headers):
Use make-full-mail-header instead of `vector`.
(gnus--dummy-mail-header): New const, using make-full-mail-header.
(gnus-update-summary-mark-positions): Use it instead of
an immediate vector.
(gnus-set-mode-line, gnus-summary-article-pseudo-p)
(gnus-summary-article-subject, gnus-summary-insert-subject)
(gnus-summary-find-subject, gnus-summary-goto-subject)
(gnus-summary-limit-to-age, gnus-summary-find-matching)
(gnus-summary-mark-article-as-unread, gnus-summary-mark-article)
(gnus-summary-save-article):
* lisp/gnus/gnus.el (gnus-news-group-p): Use mail-header-p instead
of vectorp.
parent 9843e7b6
Pipeline #1699 failed with stage
in 90 minutes and 1 second
......@@ -3267,7 +3267,7 @@ The following commands are available:
(defun gnus-summary-article-pseudo-p (article)
"Say whether this article is a pseudo article or not."
(not (vectorp (gnus-data-header (gnus-data-find article)))))
(not (mail-header-p (gnus-data-header (gnus-data-find article)))))
(defmacro gnus-summary-article-sparse-p (article)
"Say whether this article is a sparse article or not."
......@@ -3343,7 +3343,7 @@ article number."
'(gnus-data-header (assq (gnus-summary-article-number)
gnus-newsgroup-data)))))
(and headers
(vectorp headers)
(mail-header-p headers)
(mail-header-subject headers))))
(defmacro gnus-summary-article-score (&optional number)
......@@ -3600,6 +3600,9 @@ buffer that was in action when the last article was fetched."
t
(not (cdr (gnus-data-find-list article)))))
(defconst gnus--dummy-mail-header
(make-full-mail-header 0 "" "" "05 Apr 2001 23:33:09 +0400" "" "" 0 0 "" nil))
(defun gnus-make-thread-indent-array (&optional n)
(when (or n
(progn (setq n 200) nil)
......@@ -3628,10 +3631,9 @@ buffer that was in action when the last article was fetched."
(gnus-undownloaded-mark ?Z)
(gnus-summary-line-format-spec spec)
(gnus-newsgroup-downloadable '(0))
(header [0 "" "" "05 Apr 2001 23:33:09 +0400" "" "" 0 0 "" nil])
case-fold-search ignores)
;; Here, all marks are bound to Z.
(gnus-summary-insert-line header
(gnus-summary-insert-line gnus--dummy-mail-header
0 nil t gnus-tmp-unread t nil "" nil 1)
(goto-char (point-min))
;; Memorize the positions of the same characters as dummy marks.
......@@ -3645,7 +3647,7 @@ buffer that was in action when the last article was fetched."
gnus-score-below-mark ?C
gnus-score-over-mark ?C
gnus-undownloaded-mark ?D)
(gnus-summary-insert-line header
(gnus-summary-insert-line gnus--dummy-mail-header
0 nil t gnus-tmp-unread t nil "" nil 1)
;; Ignore characters which aren't dummy marks.
(dolist (p ignores)
......@@ -6219,7 +6221,7 @@ If WHERE is `summary', the summary mode line format will be used."
gnus-tmp-unselected))))
(gnus-tmp-subject
(if (and gnus-current-headers
(vectorp gnus-current-headers))
(mail-header-p gnus-current-headers))
(gnus-mode-string-quote
(mail-header-subject gnus-current-headers))
""))
......@@ -6436,7 +6438,7 @@ The resulting hash table is returned, or nil if no Xrefs were found."
;; doesn't always go hand in hand.
(setq
header
(vector
(make-full-mail-header
;; Number.
(prog1
(setq number (read cur))
......@@ -6649,7 +6651,7 @@ If USE-OLD-HEADER is non-nil, then OLD-HEADER should be a header,
and OLD-HEADER will be used when the summary line is inserted,
too, instead of trying to fetch new headers."
(let* ((line (and (numberp old-header) old-header))
(old-header (and (vectorp old-header) old-header))
(old-header (and (mail-header-p old-header) old-header))
(header (cond ((and old-header use-old-header)
old-header)
((and (numberp id)
......@@ -6887,7 +6889,7 @@ If EXCLUDE-GROUP, do not go to this group."
(while arts
(and (or (not unread)
(gnus-data-unread-p (car arts)))
(vectorp (gnus-data-header (car arts)))
(mail-header-p (gnus-data-header (car arts)))
(gnus-subject-equal
simp-subject (mail-header-subject (gnus-data-header (car arts))) t)
(setq result (car arts)
......@@ -7724,7 +7726,7 @@ If FORCE, also allow jumping to articles not currently shown."
force
(gnus-summary-insert-subject
article
(if (or (numberp force) (vectorp force)) force)
(if (or (numberp force) (mail-header-p force)) force)
t)
(setq data (gnus-data-find article)))
(goto-char b)
......@@ -8469,7 +8471,7 @@ articles that are younger than AGE days."
(cutoff (days-to-time age))
articles d date is-younger)
(while (setq d (pop data))
(when (and (vectorp (gnus-data-header d))
(when (and (mail-header-p (gnus-data-header d))
(setq date (mail-header-date (gnus-data-header d))))
(setq is-younger (time-less-p
(time-since (gnus-date-get-time date))
......@@ -9614,7 +9616,7 @@ not match REGEXP on HEADER."
(gnus-data-list backward))))
(when (and (or (not unread) ; We want all articles...
(gnus-data-unread-p d)) ; Or just unreads.
(vectorp (gnus-data-header d)) ; It's not a pseudo.
(mail-header-p (gnus-data-header d)) ; It's not a pseudo.
(if not-matching
(not (string-match
regexp
......@@ -11151,7 +11153,7 @@ If NO-EXPIRE, auto-expiry will be inhibited."
;; See whether the article is to be put in the cache.
(and gnus-use-cache
(vectorp (gnus-summary-article-header article))
(mail-header-p (gnus-summary-article-header article))
(save-excursion
(gnus-cache-possibly-enter-article
gnus-newsgroup-name article
......@@ -11198,7 +11200,7 @@ If NO-EXPIRE, auto-expiry will be inhibited."
;; See whether the article is to be put in the cache.
(and gnus-use-cache
(not (= mark gnus-canceled-mark))
(vectorp (gnus-summary-article-header article))
(mail-header-p (gnus-summary-article-header article))
(save-excursion
(gnus-cache-possibly-enter-article
gnus-newsgroup-name article
......@@ -12147,7 +12149,7 @@ performed."
header file)
(dolist (article articles)
(setq header (gnus-summary-article-header article))
(if (not (vectorp header))
(if (not (mail-header-p header))
;; This is a pseudo-article.
(if (assq 'name header)
(gnus-copy-file (cdr (assq 'name header)))
......
......@@ -3143,7 +3143,7 @@ that that variable is buffer-local to the summary buffers."
t) ;is news of course.
((not (gnus-member-of-valid 'post-mail group)) ;Non-combined.
nil) ;must be mail then.
((vectorp article) ;Has header info.
((mail-header-p article) ;Has header info.
(eq (gnus-request-type group (mail-header-id article)) 'news))
((null article) ;Hasn't header info
(eq (gnus-request-type group) 'news)) ;(unknown ==> mail)
......
......@@ -3819,13 +3819,14 @@ This function uses `mail-citation-hook' if that is non-nil."
(narrow-to-region start end)
(message-narrow-to-head-1)
(setq x-no-archive (message-fetch-field "x-no-archive"))
(vector 0
(or (message-fetch-field "subject") "none")
(or (message-fetch-field "from") "nobody")
(message-fetch-field "date")
(message-fetch-field "message-id" t)
(message-fetch-field "references")
0 0 ""))))
(make-full-mail-header
0
(or (message-fetch-field "subject") "none")
(or (message-fetch-field "from") "nobody")
(message-fetch-field "date")
(message-fetch-field "message-id" t)
(message-fetch-field "references")
0 0 ""))))
(mml-quote-region start end)
(when strip-signature
;; Allow undoing.
......@@ -6977,8 +6978,8 @@ specified by FUNCTIONS, if non-nil, or by the variable
(if wide to-address nil))
switch-function))
(setq message-reply-headers
(vector 0 (cdr (assq 'Subject headers))
from date message-id references 0 0 ""))
(make-full-mail-header 0 (cdr (assq 'Subject headers))
from date message-id references 0 0 ""))
(message-setup headers cur))))
;;;###autoload
......@@ -7035,7 +7036,8 @@ If TO-NEWSGROUPS, use that as the new Newsgroups line."
(message-pop-to-buffer (message-buffer-name "followup" from newsgroups))
(setq message-reply-headers
(vector 0 subject from date message-id references 0 0 ""))
(make-full-mail-header
0 subject from date message-id references 0 0 ""))
(message-setup
`((Subject . ,subject)
......
......@@ -136,6 +136,7 @@ on your system, you could say something like:
;; (That next-to-last entry is defined as "misc" in the NOV format,
;; but Gnus uses it for xrefs.)
(defalias 'mail-header-p #'vectorp) ;For lack of tag, it's all we have.
(cl-defstruct (mail-header
(:type vector)
(:constructor nil)
......
......@@ -491,9 +491,9 @@ If UPDATE-P is not nil, call gnus-group-update-group on the components."
;;; This is currently O(kn^2) to merge n lists of length k.
;;; You could do it in O(knlogn), but we have a small n, and the
;;; overhead of the other approach is probably greater.
;; This is currently O(kn^2) to merge n lists of length k.
;; You could do it in O(knlogn), but we have a small n, and the
;; overhead of the other approach is probably greater.
(defun nnvirtual-merge-sorted-lists (&rest lists)
"Merge many sorted lists of numbers."
(if (null (cdr lists))
......@@ -501,68 +501,68 @@ If UPDATE-P is not nil, call gnus-group-update-group on the components."
(sort (apply 'nconc lists) '<)))
;;; We map between virtual articles and real articles in a manner
;;; which keeps the size of the virtual active list the same as the
;;; sum of the component active lists.
;;; To achieve fair mixing of the groups, the last article in each of
;;; N component groups will be in the last N articles in the virtual
;;; group.
;;; If you have 3 components A, B and C, with articles 1-8, 1-5, and
;;; 6-7 respectively, then the virtual article numbers look like:
;;;
;;; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
;;; A1 A2 A3 A4 B1 A5 B2 A6 B3 A7 B4 C6 A8 B5 C7
;;; To compute these mappings we generate a couple tables and then
;;; do some fast operations on them. Tables for the example above:
;;;
;;; Offsets - [(A 0) (B -3) (C -1)]
;;;
;;; a b c d e
;;; Mapping - ([ 3 0 1 3 0 ]
;;; [ 6 3 2 9 3 ]
;;; [ 8 6 3 15 9 ])
;;;
;;; (note column 'e' is different in real algorithm, which is slightly
;;; different than described here, but this gives you the methodology.)
;;;
;;; The basic idea is this, when going from component->virtual, apply
;;; the appropriate offset to the article number. Then search the first
;;; column of the table for a row where 'a' is less than or equal to the
;;; modified number. You can see that only group A can therefore go to
;;; the first row, groups A and B to the second, and all to the last.
;;; The third column of the table is telling us the number of groups
;;; which might be able to reach that row (it might increase by more than
;;; 1 if several groups have the same size).
;;; Then column 'b' provides an additional offset you apply when you have
;;; found the correct row. You then multiply by 'c' and add on the groups
;;; _position_ in the offset table. The basic idea here is that on
;;; any given row we are going to map back and forth using X'=X*c+Y and
;;; X=(X'/c), Y=(X' mod c). Then once you've done this transformation,
;;; you apply a final offset from column 'e' to give the virtual article.
;;;
;;; Going the other direction, you instead search on column 'd' instead
;;; of 'a', and apply everything in reverse order.
;;; Convert component -> virtual:
;;; set num = num - Offset(group)
;;; find first row in Mapping where num <= 'a'
;;; num = (num-'b')*c + Position(group) + 'e'
;;; Convert virtual -> component:
;;; find first row in Mapping where num <= 'd'
;;; num = num - 'e'
;;; group_pos = num mod 'c'
;;; num = (num / 'c') + 'b' + Offset(group_pos)
;;; Easy no? :)
;;;
;;; Well actually, you need to keep column e offset smaller by the 'c'
;;; column for that line, and always add 1 more when going from
;;; component -> virtual. Otherwise you run into a problem with
;;; unique reverse mapping.
;; We map between virtual articles and real articles in a manner
;; which keeps the size of the virtual active list the same as the
;; sum of the component active lists.
;; To achieve fair mixing of the groups, the last article in each of
;; N component groups will be in the last N articles in the virtual
;; group.
;; If you have 3 components A, B and C, with articles 1-8, 1-5, and
;; 6-7 respectively, then the virtual article numbers look like:
;;
;; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
;; A1 A2 A3 A4 B1 A5 B2 A6 B3 A7 B4 C6 A8 B5 C7
;; To compute these mappings we generate a couple tables and then
;; do some fast operations on them. Tables for the example above:
;;
;; Offsets - [(A 0) (B -3) (C -1)]
;;
;; a b c d e
;; Mapping - ([ 3 0 1 3 0 ]
;; [ 6 3 2 9 3 ]
;; [ 8 6 3 15 9 ])
;;
;; (note column 'e' is different in real algorithm, which is slightly
;; different than described here, but this gives you the methodology.)
;;
;; The basic idea is this, when going from component->virtual, apply
;; the appropriate offset to the article number. Then search the first
;; column of the table for a row where 'a' is less than or equal to the
;; modified number. You can see that only group A can therefore go to
;; the first row, groups A and B to the second, and all to the last.
;; The third column of the table is telling us the number of groups
;; which might be able to reach that row (it might increase by more than
;; 1 if several groups have the same size).
;; Then column 'b' provides an additional offset you apply when you have
;; found the correct row. You then multiply by 'c' and add on the groups
;; _position_ in the offset table. The basic idea here is that on
;; any given row we are going to map back and forth using X'=X*c+Y and
;; X=(X'/c), Y=(X' mod c). Then once you've done this transformation,
;; you apply a final offset from column 'e' to give the virtual article.
;;
;; Going the other direction, you instead search on column 'd' instead
;; of 'a', and apply everything in reverse order.
;; Convert component -> virtual:
;; set num = num - Offset(group)
;; find first row in Mapping where num <= 'a'
;; num = (num-'b')*c + Position(group) + 'e'
;; Convert virtual -> component:
;; find first row in Mapping where num <= 'd'
;; num = num - 'e'
;; group_pos = num mod 'c'
;; num = (num / 'c') + 'b' + Offset(group_pos)
;; Easy no? :)
;;
;; Well actually, you need to keep column e offset smaller by the 'c'
;; column for that line, and always add 1 more when going from
;; component -> virtual. Otherwise you run into a problem with
;; unique reverse mapping.
(defun nnvirtual-map-article (article)
"Return a cons of the component group and article corresponding to the given virtual ARTICLE."
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment