aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGnus developers2010-10-10 00:15:21 +0000
committerKatsumi Yamaoka2010-10-10 00:15:21 +0000
commitf7aa248a5b1ce15ac2a3b70b4a55833d9d1eb44b (patch)
treeb99adc70fa490b39906ab483b5478066d81d149a
parente836e5cd0462864de01c9873a327169f7706bd3a (diff)
downloademacs-f7aa248a5b1ce15ac2a3b70b4a55833d9d1eb44b.tar.gz
emacs-f7aa248a5b1ce15ac2a3b70b4a55833d9d1eb44b.zip
Merge changes made in Gnus trunk.
nnimap.el (nnimap-open-connection): If we have gnutls loaded, then try to use that for the tls stream. nnimap.el (nnimap-retrieve-group-data-early): Rework the marks code to heed UIDVALIDITY and find out which groups are read-only and not. nnimap.el (nnimap-get-flags): Use the same marks parsing code as the rest of nnimap. nnimap.el (nnmail-expiry-target-group): Say that every expiry target group is the "last". nnir.el (nnir-engines): Fix too many arguments. nnimap.el: Start implementing QRESYNC support. gnus.el (gnus-group-set-parameter): Fix typo. shr.el: Rework the way things are indented by <li> slightly. spam.el (gnus-summary-mode-map): Bind to "$".
-rw-r--r--doc/misc/ChangeLog4
-rw-r--r--doc/misc/gnus.texi10
-rw-r--r--lisp/gnus/ChangeLog28
-rw-r--r--lisp/gnus/gnus.el22
-rw-r--r--lisp/gnus/nnimap.el355
-rw-r--r--lisp/gnus/nnir.el1
-rw-r--r--lisp/gnus/nnmail.el2
-rw-r--r--lisp/gnus/shr.el14
-rw-r--r--lisp/gnus/spam.el3
9 files changed, 294 insertions, 145 deletions
diff --git a/doc/misc/ChangeLog b/doc/misc/ChangeLog
index b3c52d5c36a..d54b3875edf 100644
--- a/doc/misc/ChangeLog
+++ b/doc/misc/ChangeLog
@@ -1,3 +1,7 @@
12010-10-09 Lars Magne Ingebrigtsen <larsi@gnus.org>
2
3 * gnus.texi (Spam Package Introduction): Mention `$'.
4
12010-10-09 Eli Zaretskii <eliz@gnu.org> 52010-10-09 Eli Zaretskii <eliz@gnu.org>
2 6
3 * makefile.w32-in (emacsdir): New variable. 7 * makefile.w32-in (emacsdir): New variable.
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 4b3defaa4a3..1a1f0d48eb9 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -23750,12 +23750,14 @@ yourself, so that the message is processed as spam when you exit the
23750group: 23750group:
23751 23751
23752@table @kbd 23752@table @kbd
23753@item M-d 23753@item $
23754@itemx M-d
23754@itemx M s x 23755@itemx M s x
23755@itemx S x 23756@itemx S x
23756@kindex M-d 23757@kindex $ (Summary)
23757@kindex S x 23758@kindex M-d (Summary)
23758@kindex M s x 23759@kindex S x (Summary)
23760@kindex M s x (Summary)
23759@findex gnus-summary-mark-as-spam 23761@findex gnus-summary-mark-as-spam
23760@findex gnus-summary-mark-as-spam 23762@findex gnus-summary-mark-as-spam
23761Mark current article as spam, showing it with the @samp{$} mark 23763Mark current article as spam, showing it with the @samp{$} mark
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog
index 7947aff31bc..3b2a61e3d3d 100644
--- a/lisp/gnus/ChangeLog
+++ b/lisp/gnus/ChangeLog
@@ -1,3 +1,31 @@
12010-10-09 Lars Magne Ingebrigtsen <larsi@gnus.org>
2
3 * spam.el (gnus-summary-mode-map): Bind to "$". Suggested by Russ
4 Allbery.
5
6 * shr.el: Rework the way things are indented by <li> slightly.
7
8 * gnus.el (gnus-group-set-parameter): Fix typo.
9
10 * nnimap.el: Start implementing QRESYNC support.
11
122010-10-09 Julien Danjou <julien@danjou.info>
13
14 * nnir.el (nnir-engines): Fix too many arguments.
15
162010-10-09 Lars Magne Ingebrigtsen <larsi@gnus.org>
17
18 * nnmail.el (nnmail-expiry-target-group): Say that every expiry target
19 group is the "last", so that the backends like nnfolder actually save
20 their folders.
21
22 * nnimap.el (nnimap-open-connection): If we have gnutls loaded, then
23 try to use that for the tls stream.
24 (nnimap-retrieve-group-data-early): Rework the marks code to heed
25 UIDVALIDITY and find out which groups are read-only and not.
26 (nnimap-get-flags): Use the same marks parsing code as the rest of
27 nnimap.
28
12010-10-09 Julien Danjou <julien@danjou.info> 292010-10-09 Julien Danjou <julien@danjou.info>
2 30
3 * nnir.el (nnir-read-parm): Fix call to gnus-completing-read. 31 * nnir.el (nnir-read-parm): Fix call to gnus-completing-read.
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index f6ffdf64ffb..d4bbfe129c4 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -3391,14 +3391,14 @@ that that variable is buffer-local to the summary buffers."
3391(defun gnus-news-group-p (group &optional article) 3391(defun gnus-news-group-p (group &optional article)
3392 "Return non-nil if GROUP (and ARTICLE) come from a news server." 3392 "Return non-nil if GROUP (and ARTICLE) come from a news server."
3393 (cond ((gnus-member-of-valid 'post group) ;Ordinary news group 3393 (cond ((gnus-member-of-valid 'post group) ;Ordinary news group
3394 t) ;is news of course. 3394 t) ;is news of course.
3395 ((not (gnus-member-of-valid 'post-mail group)) ;Non-combined. 3395 ((not (gnus-member-of-valid 'post-mail group)) ;Non-combined.
3396 nil) ;must be mail then. 3396 nil) ;must be mail then.
3397 ((vectorp article) ;Has header info. 3397 ((vectorp article) ;Has header info.
3398 (eq (gnus-request-type group (mail-header-id article)) 'news)) 3398 (eq (gnus-request-type group (mail-header-id article)) 'news))
3399 ((null article) ;Hasn't header info 3399 ((null article) ;Hasn't header info
3400 (eq (gnus-request-type group) 'news)) ;(unknown ==> mail) 3400 (eq (gnus-request-type group) 'news)) ;(unknown ==> mail)
3401 ((< article 0) ;Virtual message 3401 ((< article 0) ;Virtual message
3402 nil) ;we don't know, guess mail. 3402 nil) ;we don't know, guess mail.
3403 (t ;Has positive number 3403 (t ;Has positive number
3404 (eq (gnus-request-type group article) 'news)))) ;use it. 3404 (eq (gnus-request-type group article) 'news)))) ;use it.
@@ -3923,8 +3923,11 @@ If ALLOW-LIST, also allow list as a result."
3923 group 'params)))) 3923 group 'params))))
3924 3924
3925(defun gnus-group-set-parameter (group name value) 3925(defun gnus-group-set-parameter (group name value)
3926 "Set parameter NAME to VALUE in GROUP." 3926 "Set parameter NAME to VALUE in GROUP.
3927 (let ((info (gnus-get-info group))) 3927GROUP can also be an INFO structure."
3928 (let ((info (if (listp group)
3929 group
3930 (gnus-get-info group))))
3928 (when info 3931 (when info
3929 (gnus-group-remove-parameter group name) 3932 (gnus-group-remove-parameter group name)
3930 (let ((old-params (gnus-info-params info)) 3933 (let ((old-params (gnus-info-params info))
@@ -3934,11 +3937,14 @@ If ALLOW-LIST, also allow list as a result."
3934 (not (eq (caar old-params) name))) 3937 (not (eq (caar old-params) name)))
3935 (setq new-params (append new-params (list (car old-params))))) 3938 (setq new-params (append new-params (list (car old-params)))))
3936 (setq old-params (cdr old-params))) 3939 (setq old-params (cdr old-params)))
3937 (gnus-group-set-info new-params group 'params))))) 3940 (gnus-group-set-info new-params (gnus-info-group info) 'params)))))
3938 3941
3939(defun gnus-group-remove-parameter (group name) 3942(defun gnus-group-remove-parameter (group name)
3940 "Remove parameter NAME from GROUP." 3943 "Remove parameter NAME from GROUP.
3941 (let ((info (gnus-get-info group))) 3944GROUP can also be an INFO structure."
3945 (let ((info (if (listp group)
3946 group
3947 (gnus-get-info group))))
3942 (when info 3948 (when info
3943 (let ((params (gnus-info-params info))) 3949 (let ((params (gnus-info-params info)))
3944 (when params 3950 (when params
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index f8eb6659ad6..b30e5868669 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -317,8 +317,7 @@ textual parts.")
317 'starttls)) 317 'starttls))
318 '("imap")) 318 '("imap"))
319 ((memq nnimap-stream '(ssl tls)) 319 ((memq nnimap-stream '(ssl tls))
320 (funcall (if (and nil 320 (funcall (if (fboundp 'open-gnutls-stream)
321 (fboundp 'open-gnutls-stream))
322 'open-gnutls-stream 321 'open-gnutls-stream
323 'open-tls-stream) 322 'open-tls-stream)
324 "*nnimap*" (current-buffer) nnimap-address 323 "*nnimap*" (current-buffer) nnimap-address
@@ -338,7 +337,8 @@ textual parts.")
338 '(open run)))) 337 '(open run))))
339 (nnheader-report 'nnimap "Unable to contact %s:%s via %s" 338 (nnheader-report 'nnimap "Unable to contact %s:%s via %s"
340 nnimap-address port nnimap-stream) 339 nnimap-address port nnimap-stream)
341 (gnus-set-process-query-on-exit-flag (nnimap-process nnimap-object) nil) 340 (gnus-set-process-query-on-exit-flag
341 (nnimap-process nnimap-object) nil)
342 (if (not (setq connection-result (nnimap-wait-for-connection))) 342 (if (not (setq connection-result (nnimap-wait-for-connection)))
343 (nnheader-report 'nnimap 343 (nnheader-report 'nnimap
344 "%s" (buffer-substring 344 "%s" (buffer-substring
@@ -626,8 +626,10 @@ textual parts.")
626 (setq marks 626 (setq marks
627 (nnimap-flags-to-marks 627 (nnimap-flags-to-marks
628 (nnimap-parse-flags 628 (nnimap-parse-flags
629 (list (list group-sequence flag-sequence 1 group))))) 629 (list (list group-sequence flag-sequence
630 (when info 630 1 group "SELECT")))))
631 (when (and info
632 marks)
631 (nnimap-update-infos marks (list info))) 633 (nnimap-update-infos marks (list info)))
632 (goto-char (point-max)) 634 (goto-char (point-max))
633 (let ((uidnext (nth 5 (car marks)))) 635 (let ((uidnext (nth 5 (car marks))))
@@ -655,7 +657,8 @@ textual parts.")
655(deffoo nnimap-request-rename-group (group new-name &optional server) 657(deffoo nnimap-request-rename-group (group new-name &optional server)
656 (when (nnimap-possibly-change-group nil server) 658 (when (nnimap-possibly-change-group nil server)
657 (with-current-buffer (nnimap-buffer) 659 (with-current-buffer (nnimap-buffer)
658 (car (nnimap-command "RENAME %S %S" (utf7-encode group t) (utf7-encode new-name t)))))) 660 (car (nnimap-command "RENAME %S %S"
661 (utf7-encode group t) (utf7-encode new-name t))))))
659 662
660(deffoo nnimap-request-expunge-group (group &optional server) 663(deffoo nnimap-request-expunge-group (group &optional server)
661 (when (nnimap-possibly-change-group group server) 664 (when (nnimap-possibly-change-group group server)
@@ -664,16 +667,19 @@ textual parts.")
664 667
665(defun nnimap-get-flags (spec) 668(defun nnimap-get-flags (spec)
666 (let ((articles nil) 669 (let ((articles nil)
667 elems) 670 elems end)
668 (with-current-buffer (nnimap-buffer) 671 (with-current-buffer (nnimap-buffer)
669 (erase-buffer) 672 (erase-buffer)
670 (nnimap-wait-for-response (nnimap-send-command 673 (nnimap-wait-for-response (nnimap-send-command
671 "UID FETCH %s FLAGS" spec)) 674 "UID FETCH %s FLAGS" spec))
675 (setq end (point))
676 (subst-char-in-region (point-min) (point-max)
677 ?\\ ?% t)
672 (goto-char (point-min)) 678 (goto-char (point-min))
673 (while (re-search-forward "^\\* [0-9]+ FETCH (\\(.*\\))" nil t) 679 (while (search-forward " FETCH " end t)
674 (setq elems (nnimap-parse-line (match-string 1))) 680 (setq elems (read (current-buffer)))
675 (push (cons (string-to-number (cadr (member "UID" elems))) 681 (push (cons (cadr (memq 'UID elems))
676 (cadr (member "FLAGS" elems))) 682 (cadr (memq 'FLAGS elems)))
677 articles))) 683 articles)))
678 (nreverse articles))) 684 (nreverse articles)))
679 685
@@ -940,41 +946,45 @@ textual parts.")
940(deffoo nnimap-retrieve-group-data-early (server infos) 946(deffoo nnimap-retrieve-group-data-early (server infos)
941 (when (nnimap-possibly-change-group nil server) 947 (when (nnimap-possibly-change-group nil server)
942 (with-current-buffer (nnimap-buffer) 948 (with-current-buffer (nnimap-buffer)
949 (erase-buffer)
950 (setf (nnimap-group nnimap-object) nil)
943 ;; QRESYNC handling isn't implemented. 951 ;; QRESYNC handling isn't implemented.
944 (let ((qresyncp (member "notQRESYNC" (nnimap-capabilities nnimap-object))) 952 (let ((qresyncp (member "notQRESYNC" (nnimap-capabilities nnimap-object)))
945 marks groups sequences) 953 params groups sequences active uidvalidity modseq group)
946 ;; Go through the infos and gather the data needed to know 954 ;; Go through the infos and gather the data needed to know
947 ;; what and how to request the data. 955 ;; what and how to request the data.
948 (dolist (info infos) 956 (dolist (info infos)
949 (setq marks (gnus-info-marks info)) 957 (setq params (gnus-info-params info)
950 (push (list (gnus-group-real-name (gnus-info-group info)) 958 group (gnus-group-real-name (gnus-info-group info))
951 (cdr (assq 'active marks)) 959 active (cdr (assq 'active params))
952 (cdr (assq 'uid marks))) 960 uidvalidity (cdr (assq 'uidvalidity params))
953 groups)) 961 modseq (cdr (assq 'modseq params)))
954 ;; Then request the data.
955 (erase-buffer)
956 (setf (nnimap-group nnimap-object) nil)
957 (dolist (elem groups)
958 (if (and qresyncp 962 (if (and qresyncp
959 (nth 2 elem)) 963 uidvalidity
964 modseq)
960 (push 965 (push
961 (list 'qresync 966 (list (nnimap-send-command "EXAMINE %S (QRESYNC (%s %s))"
962 (nnimap-send-command "EXAMINE %S (QRESYNC (%s %s))" 967 group uidvalidity modseq)
963 (car elem) 968 'qresync
964 (car (nth 2 elem)) 969 nil group 'qresync)
965 (cdr (nth 2 elem)))
966 nil
967 (car elem))
968 sequences) 970 sequences)
969 (let ((start 971 (let ((start
970 (if (nth 1 elem) 972 (if (and active uidvalidity)
971 ;; Fetch the last 100 flags. 973 ;; Fetch the last 100 flags.
972 (max 1 (- (cdr (nth 1 elem)) 100)) 974 (max 1 (- (cdr active) 100))
973 1))) 975 1))
974 (push (list (nnimap-send-command "EXAMINE %S" (car elem)) 976 (command
977 (if uidvalidity
978 "EXAMINE"
979 ;; If we don't have a UIDVALIDITY, then this is
980 ;; the first time we've seen the group, so we
981 ;; have to do a SELECT (which is slower than an
982 ;; examine), but will tell us whether the group
983 ;; is read-only or not.
984 "SELECT")))
985 (push (list (nnimap-send-command "%s %S" command group)
975 (nnimap-send-command "UID FETCH %d:* FLAGS" start) 986 (nnimap-send-command "UID FETCH %d:* FLAGS" start)
976 start 987 start group command)
977 (car elem))
978 sequences))) 988 sequences)))
979 ;; Some servers apparently can't have many outstanding 989 ;; Some servers apparently can't have many outstanding
980 ;; commands, so throttle them. 990 ;; commands, so throttle them.
@@ -988,10 +998,13 @@ textual parts.")
988 (nnimap-possibly-change-group nil server)) 998 (nnimap-possibly-change-group nil server))
989 (with-current-buffer (nnimap-buffer) 999 (with-current-buffer (nnimap-buffer)
990 ;; Wait for the final data to trickle in. 1000 ;; Wait for the final data to trickle in.
991 (when (nnimap-wait-for-response (cadar sequences) t) 1001 (when (nnimap-wait-for-response (if (eq (cadar sequences) 'qresync)
992 ;; Now we should have all the data we need, no matter whether 1002 (caar sequences)
993 ;; we're QRESYNCING, fetching all the flags from scratch, or 1003 (cadar sequences))
994 ;; just fetching the last 100 flags per group. 1004 t)
1005 ;; Now we should have most of the data we need, no matter
1006 ;; whether we're QRESYNCING, fetching all the flags from
1007 ;; scratch, or just fetching the last 100 flags per group.
995 (nnimap-update-infos (nnimap-flags-to-marks 1008 (nnimap-update-infos (nnimap-flags-to-marks
996 (nnimap-parse-flags 1009 (nnimap-parse-flags
997 (nreverse sequences))) 1010 (nreverse sequences)))
@@ -1011,17 +1024,33 @@ textual parts.")
1011 1024
1012(defun nnimap-update-infos (flags infos) 1025(defun nnimap-update-infos (flags infos)
1013 (dolist (info infos) 1026 (dolist (info infos)
1014 (let ((group (gnus-group-real-name (gnus-info-group info)))) 1027 (let* ((group (gnus-group-real-name (gnus-info-group info)))
1015 (nnimap-update-info info (cdr (assoc group flags)))))) 1028 (marks (cdr (assoc group flags))))
1029 (when marks
1030 (nnimap-update-info info marks)))))
1016 1031
1017(defun nnimap-update-info (info marks) 1032(defun nnimap-update-info (info marks)
1018 (when (and marks 1033 (destructuring-bind (existing flags high low uidnext start-article
1019 ;; Ignore groups with no UIDNEXT/marks. This happens for 1034 permanent-flags uidvalidity
1020 ;; completely empty groups. 1035 vanished highestmodseq) marks
1021 (or (car marks) 1036 (cond
1022 (nth 4 marks))) 1037 ;; Ignore groups with no UIDNEXT/marks. This happens for
1023 (destructuring-bind (existing flags high low uidnext start-article 1038 ;; completely empty groups.
1024 permanent-flags) marks 1039 ((and (not existing)
1040 (not uidnext))
1041 )
1042 ;; We have a mismatch between the old and new UIDVALIDITY
1043 ;; identifiers, so we have to re-request the group info (the next
1044 ;; time). This virtually never happens.
1045 ((let ((old-uidvalidity
1046 (cdr (assq 'uidvalidity (gnus-info-params info)))))
1047 (and old-uidvalidity
1048 (not (equal old-uidvalidity uidvalidity))
1049 (> start-article 1)))
1050 (gnus-group-remove-parameter info 'uidvalidity)
1051 (gnus-group-remove-parameter info 'modseq))
1052 ;; We have the data needed to update.
1053 (t
1025 (let ((group (gnus-info-group info)) 1054 (let ((group (gnus-info-group info))
1026 (completep (and start-article 1055 (completep (and start-article
1027 (= start-article 1)))) 1056 (= start-article 1))))
@@ -1046,52 +1075,89 @@ textual parts.")
1046 group 1075 group
1047 (cons (car (gnus-active group)) 1076 (cons (car (gnus-active group))
1048 (or high (1- uidnext))))) 1077 (or high (1- uidnext)))))
1049 ;; Then update the list of read articles. 1078 ;; See whether this is a read-only group.
1050 (let* ((unread 1079 (unless (eq permanent-flags 'not-scanned)
1051 (gnus-compress-sequence 1080 (gnus-group-set-parameter
1052 (gnus-set-difference 1081 info 'permanent-flags
1053 (gnus-set-difference 1082 (if (memq '%* permanent-flags)
1054 existing 1083 t
1055 (cdr (assoc '%Seen flags))) 1084 nil)))
1056 (cdr (assoc '%Flagged flags))))) 1085 ;; Update marks and read articles if this isn't a
1057 (read (gnus-range-difference 1086 ;; read-only IMAP group.
1058 (cons start-article high) unread))) 1087 (when (cdr (assq 'permanent-flags (gnus-info-params info)))
1059 (when (> start-article 1) 1088 (if (and highestmodseq
1060 (setq read 1089 (not start-article))
1061 (gnus-range-nconcat 1090 ;; We've gotten the data by QRESYNCing.
1062 (if (> start-article 1) 1091 (nnimap-update-qresync-info
1063 (gnus-sorted-range-intersection 1092 info (nnimap-imap-ranges-to-gnus-ranges vanished) flags)
1064 (cons 1 (1- start-article)) 1093 ;; Do normal non-QRESYNC flag updates.
1065 (gnus-info-read info)) 1094 ;; Update the list of read articles.
1066 (gnus-info-read info)) 1095 (let* ((unread
1067 read))) 1096 (gnus-compress-sequence
1068 (gnus-info-set-read info read) 1097 (gnus-set-difference
1069 ;; Update the marks. 1098 (gnus-set-difference
1070 (setq marks (gnus-info-marks info)) 1099 existing
1071 ;; Note the active level for the next run-through. 1100 (cdr (assoc '%Seen flags)))
1072 (let ((active (assq 'active marks))) 1101 (cdr (assoc '%Flagged flags)))))
1073 (if active 1102 (read (gnus-range-difference
1074 (setcdr active (gnus-active group)) 1103 (cons start-article high) unread)))
1075 (push (cons 'active (gnus-active group)) marks))) 1104 (when (> start-article 1)
1076 (dolist (type (cdr nnimap-mark-alist)) 1105 (setq read
1077 (let ((old-marks (assoc (car type) marks)) 1106 (gnus-range-nconcat
1078 (new-marks 1107 (if (> start-article 1)
1079 (gnus-compress-sequence 1108 (gnus-sorted-range-intersection
1080 (cdr (or (assoc (caddr type) flags) ; %Flagged 1109 (cons 1 (1- start-article))
1081 (assoc (intern (cadr type) obarray) flags) 1110 (gnus-info-read info))
1082 (assoc (cadr type) flags)))))) ; "\Flagged" 1111 (gnus-info-read info))
1083 (setq marks (delq old-marks marks)) 1112 read)))
1084 (pop old-marks) 1113 (gnus-info-set-read info read)
1085 (when (and old-marks 1114 ;; Update the marks.
1086 (> start-article 1)) 1115 (setq marks (gnus-info-marks info))
1087 (setq old-marks (gnus-range-difference 1116 (dolist (type (cdr nnimap-mark-alist))
1088 old-marks 1117 (let ((old-marks (assoc (car type) marks))
1089 (cons start-article high))) 1118 (new-marks
1090 (setq new-marks (gnus-range-nconcat old-marks new-marks))) 1119 (gnus-compress-sequence
1091 (when new-marks 1120 (cdr (or (assoc (caddr type) flags) ; %Flagged
1092 (push (cons (car type) new-marks) marks))) 1121 (assoc (intern (cadr type) obarray) flags)
1093 (gnus-info-set-marks info marks t) 1122 (assoc (cadr type) flags)))))) ; "\Flagged"
1094 (nnimap-store-info info (gnus-active group)))))))) 1123 (setq marks (delq old-marks marks))
1124 (pop old-marks)
1125 (when (and old-marks
1126 (> start-article 1))
1127 (setq old-marks (gnus-range-difference
1128 old-marks
1129 (cons start-article high)))
1130 (setq new-marks (gnus-range-nconcat old-marks new-marks)))
1131 (when new-marks
1132 (push (cons (car type) new-marks) marks)))
1133 (gnus-info-set-marks info marks t)))))
1134 ;; Note the active level for the next run-through.
1135 (gnus-group-set-parameter info 'active (gnus-active group))
1136 (gnus-group-set-parameter info 'uidvalidity uidvalidity)
1137 (gnus-group-set-parameter info 'modseq highestmodseq)
1138 (nnimap-store-info info (gnus-active group)))))))
1139
1140(defun nnimap-update-qresync-info (info vanished flags)
1141 ;; Add all the vanished articles to the list of read articles.
1142 (gnus-info-set-read
1143 info
1144 (gnus-range-add (gnus-info-read info)
1145 vanished))
1146 )
1147
1148(defun nnimap-imap-ranges-to-gnus-ranges (irange)
1149 (if (zerop (length irange))
1150 nil
1151 (let ((result nil))
1152 (dolist (elem (split-string irange ","))
1153 (push
1154 (if (string-match ":" elem)
1155 (let ((numbers (split-string elem ":")))
1156 (cons (string-to-number (car numbers))
1157 (string-to-number (cadr numbers))))
1158 (string-to-number elem))
1159 result))
1160 (nreverse result))))
1095 1161
1096(defun nnimap-store-info (info active) 1162(defun nnimap-store-info (info active)
1097 (let* ((group (gnus-group-real-name (gnus-info-group info))) 1163 (let* ((group (gnus-group-real-name (gnus-info-group info)))
@@ -1101,13 +1167,17 @@ textual parts.")
1101 (push (list group info active) nnimap-current-infos)))) 1167 (push (list group info active) nnimap-current-infos))))
1102 1168
1103(defun nnimap-flags-to-marks (groups) 1169(defun nnimap-flags-to-marks (groups)
1104 (let (data group totalp uidnext articles start-article mark permanent-flags) 1170 (let (data group totalp uidnext articles start-article mark permanent-flags
1171 uidvalidity vanished highestmodseq)
1105 (dolist (elem groups) 1172 (dolist (elem groups)
1106 (setq group (car elem) 1173 (setq group (car elem)
1107 uidnext (nth 1 elem) 1174 uidnext (nth 1 elem)
1108 start-article (nth 2 elem) 1175 start-article (nth 2 elem)
1109 permanent-flags (nth 3 elem) 1176 permanent-flags (nth 3 elem)
1110 articles (nthcdr 4 elem)) 1177 uidvalidity (nth 4 elem)
1178 vanished (nth 5 elem)
1179 highestmodseq (nth 6 elem)
1180 articles (nthcdr 7 elem))
1111 (let ((high (caar articles)) 1181 (let ((high (caar articles))
1112 marks low existing) 1182 marks low existing)
1113 (dolist (article articles) 1183 (dolist (article articles)
@@ -1119,7 +1189,7 @@ textual parts.")
1119 (push (list flag (car article)) marks) 1189 (push (list flag (car article)) marks)
1120 (setcdr mark (cons (car article) (cdr mark)))))) 1190 (setcdr mark (cons (car article) (cdr mark))))))
1121 (push (list group existing marks high low uidnext start-article 1191 (push (list group existing marks high low uidnext start-article
1122 permanent-flags) 1192 permanent-flags uidvalidity vanished highestmodseq)
1123 data))) 1193 data)))
1124 data)) 1194 data))
1125 1195
@@ -1128,38 +1198,69 @@ textual parts.")
1128 ;; Change \Delete etc to %Delete, so that the reader can read it. 1198 ;; Change \Delete etc to %Delete, so that the reader can read it.
1129 (subst-char-in-region (point-min) (point-max) 1199 (subst-char-in-region (point-min) (point-max)
1130 ?\\ ?% t) 1200 ?\\ ?% t)
1131 (let (start end articles groups uidnext elems permanent-flags) 1201 (let (start end articles groups uidnext elems permanent-flags
1202 uidvalidity vanished highestmodseq)
1132 (dolist (elem sequences) 1203 (dolist (elem sequences)
1133 (destructuring-bind (group-sequence flag-sequence totalp group) elem 1204 (destructuring-bind (group-sequence flag-sequence totalp group command)
1205 elem
1134 (setq start (point)) 1206 (setq start (point))
1135 ;; The EXAMINE was successful. 1207 (when (and
1136 (when (and (search-forward (format "\n%d OK " group-sequence) nil t) 1208 ;; The EXAMINE was successful.
1137 (progn 1209 (search-forward (format "\n%d OK " group-sequence) nil t)
1138 (forward-line 1) 1210 (progn
1139 (setq end (point)) 1211 (forward-line 1)
1140 (goto-char start) 1212 (setq end (point))
1141 (setq permanent-flags 1213 (goto-char start)
1214 (setq permanent-flags
1215 (if (equal command "SELECT")
1142 (and (search-forward "PERMANENTFLAGS " 1216 (and (search-forward "PERMANENTFLAGS "
1143 (or end (point-min)) t) 1217 (or end (point-min)) t)
1144 (read (current-buffer)))) 1218 (read (current-buffer)))
1145 (goto-char start) 1219 'not-scanned))
1146 (setq uidnext 1220 (goto-char start)
1147 (and (search-forward "UIDNEXT " 1221 (setq uidnext
1148 (or end (point-min)) t) 1222 (and (search-forward "UIDNEXT "
1149 (read (current-buffer)))) 1223 (or end (point-min)) t)
1150 (goto-char end) 1224 (read (current-buffer))))
1151 (forward-line -1)) 1225 (goto-char start)
1152 ;; The UID FETCH FLAGS was successful. 1226 (setq uidvalidity
1153 (search-forward (format "\n%d OK " flag-sequence) nil t)) 1227 (and (re-search-forward "UIDVALIDITY \\([0-9]+\\)"
1154 (setq start (point)) 1228 (or end (point-min)) t)
1155 (goto-char end) 1229 ;; Store UIDVALIDITY as a string, as it's
1230 ;; too big for 32-bit Emacsen, usually.
1231 (match-string 1)))
1232 (goto-char start)
1233 (setq vanished
1234 (and (eq flag-sequence 'qresync)
1235 (re-search-forward "VANISHED.* \\([0-9:,]+\\)"
1236 (or end (point-min)) t)
1237 (match-string 1)))
1238 (goto-char start)
1239 (setq highestmodseq
1240 (and (search-forward "HIGHESTMODSEQ "
1241 (or end (point-min)) t)
1242 (read (current-buffer))))
1243 (goto-char end)
1244 (forward-line -1))
1245 ;; The UID FETCH FLAGS was successful.
1246 (or (eq flag-sequence 'qresync)
1247 (search-forward (format "\n%d OK " flag-sequence) nil t)))
1248 (if (eq flag-sequence 'qresync)
1249 (progn
1250 (goto-char start)
1251 (setq start end))
1252 (setq start (point))
1253 (goto-char end))
1156 (while (search-forward " FETCH " start t) 1254 (while (search-forward " FETCH " start t)
1157 (setq elems (read (current-buffer))) 1255 (setq elems (read (current-buffer)))
1158 (push (cons (cadr (memq 'UID elems)) 1256 (push (cons (cadr (memq 'UID elems))
1159 (cadr (memq 'FLAGS elems))) 1257 (cadr (memq 'FLAGS elems)))
1160 articles)) 1258 articles))
1161 (push (nconc (list group uidnext totalp permanent-flags) articles) 1259 (push (nconc (list group uidnext totalp permanent-flags uidvalidity
1260 vanished highestmodseq)
1261 articles)
1162 groups) 1262 groups)
1263 (goto-char end)
1163 (setq articles nil)))) 1264 (setq articles nil))))
1164 groups)) 1265 groups))
1165 1266
@@ -1293,13 +1394,15 @@ textual parts.")
1293 (push 1394 (push
1294 (cond 1395 (cond
1295 ((eql char ?\[) 1396 ((eql char ?\[)
1296 (split-string (buffer-substring 1397 (split-string
1297 (1+ (point)) 1398 (buffer-substring
1298 (1- (search-forward "]" (line-end-position) 'move))))) 1399 (1+ (point))
1400 (1- (search-forward "]" (line-end-position) 'move)))))
1299 ((eql char ?\() 1401 ((eql char ?\()
1300 (split-string (buffer-substring 1402 (split-string
1301 (1+ (point)) 1403 (buffer-substring
1302 (1- (search-forward ")" (line-end-position) 'move))))) 1404 (1+ (point))
1405 (1- (search-forward ")" (line-end-position) 'move)))))
1303 ((eql char ?\") 1406 ((eql char ?\")
1304 (forward-char 1) 1407 (forward-char 1)
1305 (buffer-substring 1408 (buffer-substring
diff --git a/lisp/gnus/nnir.el b/lisp/gnus/nnir.el
index 6d64935550f..86acad16638 100644
--- a/lisp/gnus/nnir.el
+++ b/lisp/gnus/nnir.el
@@ -377,7 +377,6 @@ result, `gnus-retrieve-headers' will be called instead.")
377 ((criteria 377 ((criteria
378 "Search in: " ; Prompt 378 "Search in: " ; Prompt
379 ,(mapcar 'car nnir-imap-search-arguments) ; alist for completing 379 ,(mapcar 'car nnir-imap-search-arguments) ; alist for completing
380 nil ; no filtering
381 nil ; allow any user input 380 nil ; allow any user input
382 nil ; initial value 381 nil ; initial value
383 nnir-imap-search-argument-history ; the history to use 382 nnir-imap-search-argument-history ; the history to use
diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el
index 463f87e44fc..01cab6febe3 100644
--- a/lisp/gnus/nnmail.el
+++ b/lisp/gnus/nnmail.el
@@ -1914,7 +1914,7 @@ If TIME is nil, then return the cutoff time for oldness instead."
1914 (unless (eq target 'delete) 1914 (unless (eq target 'delete)
1915 (when (or (gnus-request-group target) 1915 (when (or (gnus-request-group target)
1916 (gnus-request-create-group target)) 1916 (gnus-request-create-group target))
1917 (let ((group-art (gnus-request-accept-article target nil nil t))) 1917 (let ((group-art (gnus-request-accept-article target nil t t)))
1918 (when (consp group-art) 1918 (when (consp group-art)
1919 (gnus-group-mark-article-read target (cdr group-art)))))))) 1919 (gnus-group-mark-article-read target (cdr group-art))))))))
1920 1920
diff --git a/lisp/gnus/shr.el b/lisp/gnus/shr.el
index 8f246a06e36..0700621a912 100644
--- a/lisp/gnus/shr.el
+++ b/lisp/gnus/shr.el
@@ -230,7 +230,7 @@ redirects somewhere else."
230 230
231(defun shr-ensure-paragraph () 231(defun shr-ensure-paragraph ()
232 (unless (bobp) 232 (unless (bobp)
233 (if (bolp) 233 (if (<= (current-column) shr-indentation)
234 (unless (save-excursion 234 (unless (save-excursion
235 (forward-line -1) 235 (forward-line -1)
236 (looking-at " *$")) 236 (looking-at " *$"))
@@ -242,7 +242,8 @@ redirects somewhere else."
242 (insert "\n\n"))))) 242 (insert "\n\n")))))
243 243
244(defun shr-indent () 244(defun shr-indent ()
245 (insert (make-string shr-indentation ? ))) 245 (when (> shr-indentation 0)
246 (insert (make-string shr-indentation ? ))))
246 247
247(defun shr-fontize-cont (cont &rest types) 248(defun shr-fontize-cont (cont &rest types)
248 (let (shr-start) 249 (let (shr-start)
@@ -332,6 +333,7 @@ Return a string with image data."
332 333
333(defun shr-tag-p (cont) 334(defun shr-tag-p (cont)
334 (shr-ensure-paragraph) 335 (shr-ensure-paragraph)
336 (shr-indent)
335 (shr-generic cont) 337 (shr-generic cont)
336 (shr-ensure-paragraph)) 338 (shr-ensure-paragraph))
337 339
@@ -404,11 +406,13 @@ Return a string with image data."
404(defun shr-tag-pre (cont) 406(defun shr-tag-pre (cont)
405 (let ((shr-folding-mode 'none)) 407 (let ((shr-folding-mode 'none))
406 (shr-ensure-newline) 408 (shr-ensure-newline)
409 (shr-indent)
407 (shr-generic cont) 410 (shr-generic cont)
408 (shr-ensure-newline))) 411 (shr-ensure-newline)))
409 412
410(defun shr-tag-blockquote (cont) 413(defun shr-tag-blockquote (cont)
411 (shr-ensure-paragraph) 414 (shr-ensure-paragraph)
415 (shr-indent)
412 (let ((shr-indentation (+ shr-indentation 4))) 416 (let ((shr-indentation (+ shr-indentation 4)))
413 (shr-generic cont)) 417 (shr-generic cont))
414 (shr-ensure-paragraph)) 418 (shr-ensure-paragraph))
@@ -426,7 +430,8 @@ Return a string with image data."
426 (shr-ensure-paragraph)) 430 (shr-ensure-paragraph))
427 431
428(defun shr-tag-li (cont) 432(defun shr-tag-li (cont)
429 (shr-ensure-newline) 433 (shr-ensure-paragraph)
434 (shr-indent)
430 (let* ((bullet 435 (let* ((bullet
431 (if (numberp shr-list-mode) 436 (if (numberp shr-list-mode)
432 (prog1 437 (prog1
@@ -439,7 +444,8 @@ Return a string with image data."
439 444
440(defun shr-tag-br (cont) 445(defun shr-tag-br (cont)
441 (unless (bobp) 446 (unless (bobp)
442 (insert "\n")) 447 (insert "\n")
448 (shr-indent))
443 (shr-generic cont)) 449 (shr-generic cont))
444 450
445(defun shr-tag-h1 (cont) 451(defun shr-tag-h1 (cont)
diff --git a/lisp/gnus/spam.el b/lisp/gnus/spam.el
index b7908e5507b..9e193ccea84 100644
--- a/lisp/gnus/spam.el
+++ b/lisp/gnus/spam.el
@@ -689,7 +689,8 @@ order for SpamAssassin to recognize the new registered spam."
689 "Sx" gnus-summary-mark-as-spam 689 "Sx" gnus-summary-mark-as-spam
690 "Mst" spam-generic-score 690 "Mst" spam-generic-score
691 "Msx" gnus-summary-mark-as-spam 691 "Msx" gnus-summary-mark-as-spam
692 "\M-d" gnus-summary-mark-as-spam) 692 "\M-d" gnus-summary-mark-as-spam
693 "$" gnus-summary-mark-as-spam)
693 694
694(defvar spam-cache-lookups t 695(defvar spam-cache-lookups t
695 "Whether spam.el will try to cache lookups using `spam-caches'.") 696 "Whether spam.el will try to cache lookups using `spam-caches'.")