aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorKenichi Handa2012-09-06 10:49:15 +0900
committerKenichi Handa2012-09-06 10:49:15 +0900
commitfca81a8d405cd4c825e144099c54dd163636aa3b (patch)
treeee09be4b0e079b9c8863c8b570496a169227b218 /lisp
parentf41d6f9db69ce77fe9b3a637de407e8b589e0dc4 (diff)
parent067b39d4296765e83f9530eca456168f6cda95fc (diff)
downloademacs-fca81a8d405cd4c825e144099c54dd163636aa3b.tar.gz
emacs-fca81a8d405cd4c825e144099c54dd163636aa3b.zip
merge trunk
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog31
-rw-r--r--lisp/calendar/holidays.el2
-rw-r--r--lisp/emulation/cua-rect.el2
-rw-r--r--lisp/gnus/ChangeLog51
-rw-r--r--lisp/gnus/gnus-demon.el9
-rw-r--r--lisp/gnus/gnus-group.el5
-rw-r--r--lisp/gnus/gnus-logic.el73
-rw-r--r--lisp/gnus/gnus-score.el231
-rw-r--r--lisp/gnus/gnus-srvr.el3
-rw-r--r--lisp/gnus/gnus.el45
-rw-r--r--lisp/gnus/message.el32
-rw-r--r--lisp/gnus/nnmaildir.el286
-rw-r--r--lisp/help.el35
-rw-r--r--lisp/play/blackbox.el2
-rw-r--r--lisp/progmodes/flymake.el5
-rw-r--r--lisp/progmodes/sh-script.el31
-rw-r--r--lisp/textmodes/picture.el8
-rw-r--r--lisp/window.el82
18 files changed, 682 insertions, 251 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 64dda45276c..23cb32e1464 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,34 @@
12012-09-05 Martin Rudalics <rudalics@gmx.at>
2
3 * help.el (temp-buffer-max-height): New default value.
4 (temp-buffer-resize-frames): New option.
5 (resize-temp-buffer-window): Optionally resize frame.
6
7 * window.el (fit-frame-to-buffer-bottom-margin): New option.
8 (fit-frame-to-buffer): New function.
9
102012-09-05 Glenn Morris <rgm@gnu.org>
11
12 * emulation/cua-rect.el (cua--init-rectangles):
13 * textmodes/picture.el (picture-mode-map):
14 * play/blackbox.el (blackbox-mode-map): Remap right-char and left-char
15 like forward-char and backward-char. (Bug#12317)
16
172012-09-05 Leo Liu <sdl.web@gmail.com>
18
19 * progmodes/flymake.el (flymake-warning-re): New variable.
20 (flymake-parse-line): Use it.
21
222012-09-05 Glenn Morris <rgm@gnu.org>
23
24 * calendar/holidays.el (holiday-christian-holidays):
25 Rename an entry. (Bug#12289)
26
272012-09-05 Stefan Monnier <monnier@iro.umontreal.ca>
28
29 * progmodes/sh-script.el (sh-font-lock-paren): Don't burp at BOB
30 (bug#12222).
31
12012-09-04 Stefan Monnier <monnier@iro.umontreal.ca> 322012-09-04 Stefan Monnier <monnier@iro.umontreal.ca>
2 33
3 * loadup.el: Load macroexp. Remove hack. 34 * loadup.el: Load macroexp. Remove hack.
diff --git a/lisp/calendar/holidays.el b/lisp/calendar/holidays.el
index 043d402f612..9643a1e2905 100644
--- a/lisp/calendar/holidays.el
+++ b/lisp/calendar/holidays.el
@@ -250,7 +250,7 @@ See the documentation for `calendar-holidays' for details."
250 (if calendar-christian-all-holidays-flag 250 (if calendar-christian-all-holidays-flag
251 (append 251 (append
252 (holiday-fixed 1 6 "Epiphany") 252 (holiday-fixed 1 6 "Epiphany")
253 (holiday-julian 12 25 "Eastern Orthodox Christmas") 253 (holiday-julian 12 25 "Christmas (Julian calendar)")
254 (holiday-greek-orthodox-easter) 254 (holiday-greek-orthodox-easter)
255 (holiday-fixed 8 15 "Assumption") 255 (holiday-fixed 8 15 "Assumption")
256 (holiday-advent 0 "Advent"))))) 256 (holiday-advent 0 "Advent")))))
diff --git a/lisp/emulation/cua-rect.el b/lisp/emulation/cua-rect.el
index 39ce5901524..f63d79adf47 100644
--- a/lisp/emulation/cua-rect.el
+++ b/lisp/emulation/cua-rect.el
@@ -1423,7 +1423,9 @@ With prefix arg, indent to that column."
1423 (define-key cua--rectangle-keymap [remap set-mark-command] 'cua-toggle-rectangle-mark) 1423 (define-key cua--rectangle-keymap [remap set-mark-command] 'cua-toggle-rectangle-mark)
1424 1424
1425 (define-key cua--rectangle-keymap [remap forward-char] 'cua-resize-rectangle-right) 1425 (define-key cua--rectangle-keymap [remap forward-char] 'cua-resize-rectangle-right)
1426 (define-key cua--rectangle-keymap [remap right-char] 'cua-resize-rectangle-right)
1426 (define-key cua--rectangle-keymap [remap backward-char] 'cua-resize-rectangle-left) 1427 (define-key cua--rectangle-keymap [remap backward-char] 'cua-resize-rectangle-left)
1428 (define-key cua--rectangle-keymap [remap left-char] 'cua-resize-rectangle-left)
1427 (define-key cua--rectangle-keymap [remap next-line] 'cua-resize-rectangle-down) 1429 (define-key cua--rectangle-keymap [remap next-line] 'cua-resize-rectangle-down)
1428 (define-key cua--rectangle-keymap [remap previous-line] 'cua-resize-rectangle-up) 1430 (define-key cua--rectangle-keymap [remap previous-line] 'cua-resize-rectangle-up)
1429 (define-key cua--rectangle-keymap [remap end-of-line] 'cua-resize-rectangle-eol) 1431 (define-key cua--rectangle-keymap [remap end-of-line] 'cua-resize-rectangle-eol)
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog
index fe025210c2a..0a7866794a8 100644
--- a/lisp/gnus/ChangeLog
+++ b/lisp/gnus/ChangeLog
@@ -3,9 +3,54 @@
3 * qp.el (quoted-printable-decode-region): Fix previous change; handle 3 * qp.el (quoted-printable-decode-region): Fix previous change; handle
4 lowercase a..f. 4 lowercase a..f.
5 5
62012-09-03 Lars Ingebrigtsen <larsi@gnus.org> 62012-09-05 Magnus Henoch <magnus.henoch@gmail.com>
7
8 * nnmaildir.el (nnmaildir--article-set-flags): Fix compilation error.
9
102012-09-05 Martin Stjernholm <mast@lysator.liu.se>
11
12 * gnus-demon.el (gnus-demon-init): Fixed regression when IDLE is t and
13 TIME is set.
14
152012-09-05 Juri Linkov <juri@jurta.org>
16
17 * gnus-group.el (gnus-read-ephemeral-bug-group): Allow opening more
18 than one group at a time (bug#11961).
19
202012-09-05 Julien Danjou <julien@danjou.info>
21
22 * gnus-srvr.el (gnus-server-open-server): Don't message on failure:
23 this hide the real reason with a message giving absolutely no hint.
24
252012-09-05 Lars Ingebrigtsen <larsi@gnus.org>
26
27 * gnus-group.el (gnus-group-mark-article-read): Propagate the read mark
28 to the backend (bug#11804).
29
30 * message.el (message-insert-newsgroups): Don't insert newsgroup
31 duplicates (bug#12275).
7 32
8 * dgnushack.el: XEmacs 21.5 compilation fix. 332012-09-05 John Wiegley <johnw@newartisans.com>
34
35 * gnus.el (gnus-expand-group-parameters): Allow regexp substitutions in
36 sieve rules.
37
382012-09-05 Jan Tatarik <jan.tatarik@gmail.com>
39
40 * gnus-score.el (gnus-score-decode-text-parts): Use #' for the local
41 function.
42
43 * gnus-logic.el (gnus-advanced-body): Allow scoring on decoded bodies.
44
45 * gnus-score.el (gnus-score-decode-text-parts): Ditto.
46
472012-09-05 Magnus Henoch <magnus.henoch@gmail.com>
48
49 * nnmaildir.el: Make nnmaildir understand and write maildir flags.
50 That is, rename files from "unique:2," to "unique:2,S" for "seen", etc.
51 This should make nnmaildir more usable with offlineimap.
52
532012-09-03 Lars Ingebrigtsen <larsi@gnus.org>
9 54
10 * gnus-notifications.el (gnus-notifications-notify): Use it. 55 * gnus-notifications.el (gnus-notifications-notify): Use it.
11 56
@@ -2305,8 +2350,6 @@
2305 2350
23062011-06-30 Lars Magne Ingebrigtsen <larsi@gnus.org> 23512011-06-30 Lars Magne Ingebrigtsen <larsi@gnus.org>
2307 2352
2308 * dgnushack.el: Autoload sha1 on XEmacs.
2309
2310 * gnus-group.el (gnus-read-ephemeral-emacs-bug-group): Take an optional 2353 * gnus-group.el (gnus-read-ephemeral-emacs-bug-group): Take an optional
2311 quit window configuration. 2354 quit window configuration.
2312 2355
diff --git a/lisp/gnus/gnus-demon.el b/lisp/gnus/gnus-demon.el
index 115c5777448..671c566d09f 100644
--- a/lisp/gnus/gnus-demon.el
+++ b/lisp/gnus/gnus-demon.el
@@ -144,9 +144,12 @@ marked with SPECIAL."
144 (* (gnus-demon-time-to-step time) gnus-demon-timestep)) 144 (* (gnus-demon-time-to-step time) gnus-demon-timestep))
145 (t 145 (t
146 (* time gnus-demon-timestep)))) 146 (* time gnus-demon-timestep))))
147 (idle (if (numberp idle) 147 (idle (cond ((numberp idle)
148 (* idle gnus-demon-timestep) 148 (* idle gnus-demon-timestep))
149 idle)) 149 ((and (eq idle t) (numberp time))
150 time)
151 (t
152 idle)))
150 153
151 (timer 154 (timer
152 (cond 155 (cond
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index 2f6fc0ccd19..71af5792d2c 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -2481,7 +2481,8 @@ the bug number, and browsing the URL must return mbox output."
2481 "/.*$" "")))) 2481 "/.*$" ""))))
2482 (write-region (point-min) (point-max) tmpfile) 2482 (write-region (point-min) (point-max) tmpfile)
2483 (gnus-group-read-ephemeral-group 2483 (gnus-group-read-ephemeral-group
2484 "gnus-read-ephemeral-bug" 2484 (format "gnus-read-ephemeral-bug:%s"
2485 (mapconcat 'number-to-string ids ","))
2485 `(nndoc ,tmpfile 2486 `(nndoc ,tmpfile
2486 (nndoc-article-type mbox)) 2487 (nndoc-article-type mbox))
2487 nil window-conf)) 2488 nil window-conf))
@@ -4670,6 +4671,8 @@ you the groups that have both dormant articles and cached articles."
4670 (setq mark gnus-expirable-mark)) 4671 (setq mark gnus-expirable-mark))
4671 (setq mark (gnus-request-update-mark 4672 (setq mark (gnus-request-update-mark
4672 group article mark)) 4673 group article mark))
4674 (gnus-request-set-mark
4675 group (list (list (list article) 'add '(read))))
4673 (gnus-mark-article-as-read article mark) 4676 (gnus-mark-article-as-read article mark)
4674 (setq gnus-newsgroup-active (gnus-active group)) 4677 (setq gnus-newsgroup-active (gnus-active group))
4675 (when active 4678 (when active
diff --git a/lisp/gnus/gnus-logic.el b/lisp/gnus/gnus-logic.el
index 954295438c9..a440b779930 100644
--- a/lisp/gnus/gnus-logic.el
+++ b/lisp/gnus/gnus-logic.el
@@ -180,46 +180,51 @@
180 (setq header "article")) 180 (setq header "article"))
181 (with-current-buffer nntp-server-buffer 181 (with-current-buffer nntp-server-buffer
182 (let* ((request-func (cond ((string= "head" header) 182 (let* ((request-func (cond ((string= "head" header)
183 'gnus-request-head) 183 'gnus-request-head)
184 ((string= "body" header) 184 ;; We need to peek at the headers to detect the
185 'gnus-request-body) 185 ;; content encoding
186 (t 'gnus-request-article))) 186 ((string= "body" header)
187 ofunc article) 187 'gnus-request-article)
188 (t 'gnus-request-article)))
189 ofunc article handles)
188 ;; Not all backends support partial fetching. In that case, we 190 ;; Not all backends support partial fetching. In that case, we
189 ;; just fetch the entire article. 191 ;; just fetch the entire article.
190 (unless (gnus-check-backend-function 192 (unless (gnus-check-backend-function
191 (intern (concat "request-" header)) 193 (intern (concat "request-" header))
192 gnus-newsgroup-name) 194 gnus-newsgroup-name)
193 (setq ofunc request-func) 195 (setq ofunc request-func)
194 (setq request-func 'gnus-request-article)) 196 (setq request-func 'gnus-request-article))
195 (setq article (mail-header-number gnus-advanced-headers)) 197 (setq article (mail-header-number gnus-advanced-headers))
196 (gnus-message 7 "Scoring article %s..." article) 198 (gnus-message 7 "Scoring article %s..." article)
197 (when (funcall request-func article gnus-newsgroup-name) 199 (when (funcall request-func article gnus-newsgroup-name)
198 (goto-char (point-min)) 200 (when (string= "body" header)
199 ;; If just parts of the article is to be searched and the 201 (setq handles (gnus-score-decode-text-parts)))
200 ;; backend didn't support partial fetching, we just narrow to 202 (goto-char (point-min))
201 ;; the relevant parts. 203 ;; If just parts of the article is to be searched and the
202 (when ofunc 204 ;; backend didn't support partial fetching, we just narrow to
203 (if (eq ofunc 'gnus-request-head) 205 ;; the relevant parts.
204 (narrow-to-region 206 (when ofunc
205 (point) 207 (if (eq ofunc 'gnus-request-head)
206 (or (search-forward "\n\n" nil t) (point-max))) 208 (narrow-to-region
207 (narrow-to-region 209 (point)
208 (or (search-forward "\n\n" nil t) (point)) 210 (or (search-forward "\n\n" nil t) (point-max)))
209 (point-max)))) 211 (narrow-to-region
210 (let* ((case-fold-search (not (eq (downcase (symbol-name type)) 212 (or (search-forward "\n\n" nil t) (point))
211 (symbol-name type)))) 213 (point-max))))
212 (search-func 214 (let* ((case-fold-search (not (eq (downcase (symbol-name type))
213 (cond ((memq type '(r R regexp Regexp)) 215 (symbol-name type))))
214 're-search-forward) 216 (search-func
215 ((memq type '(s S string String)) 217 (cond ((memq type '(r R regexp Regexp))
216 'search-forward) 218 're-search-forward)
217 (t 219 ((memq type '(s S string String))
218 (error "Invalid match type: %s" type))))) 220 'search-forward)
219 (goto-char (point-min)) 221 (t
220 (prog1 222 (error "Invalid match type: %s" type)))))
221 (funcall search-func match nil t) 223 (goto-char (point-min))
222 (widen))))))) 224 (prog1
225 (funcall search-func match nil t)
226 (widen)))
227 (when handles (mm-destroy-parts handles))))))
223 228
224(provide 'gnus-logic) 229(provide 'gnus-logic)
225 230
diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el
index f24d889216e..bc35cf3dea5 100644
--- a/lisp/gnus/gnus-score.el
+++ b/lisp/gnus/gnus-score.el
@@ -1717,105 +1717,140 @@ score in `gnus-newsgroup-scored' by SCORE."
1717 (setq entries rest))))) 1717 (setq entries rest)))))
1718 nil) 1718 nil)
1719 1719
1720(defun gnus-score-decode-text-parts ()
1721 (labels ((mm-text-parts (handle)
1722 (cond ((stringp (car handle))
1723 (let ((parts (mapcan 'mm-text-parts (cdr handle))))
1724 (if (equal "multipart/alternative" (car handle))
1725 ;; pick the first supported alternative
1726 (list (car parts))
1727 parts)))
1728
1729 ((bufferp (car handle))
1730 (when (string-match "^text/" (mm-handle-media-type handle))
1731 (list handle)))
1732
1733 (t (mapcan 'mm-text-parts handle))))
1734 (my-mm-display-part (handle)
1735 (when handle
1736 (save-restriction
1737 (narrow-to-region (point) (point))
1738 (mm-display-inline handle)
1739 (goto-char (point-max))))))
1740
1741 (let (;(mm-text-html-renderer 'w3m-standalone)
1742 (handles (mm-dissect-buffer t)))
1743 (save-excursion
1744 (article-goto-body)
1745 (delete-region (point) (point-max))
1746 (mapc #'my-mm-display-part (mm-text-parts handles))
1747 handles))))
1748
1720(defun gnus-score-body (scores header now expire &optional trace) 1749(defun gnus-score-body (scores header now expire &optional trace)
1721 (if gnus-agent-fetching 1750 (if gnus-agent-fetching
1722 nil 1751 nil
1723 (save-excursion 1752 (save-excursion
1724 (setq gnus-scores-articles 1753 (setq gnus-scores-articles
1725 (sort gnus-scores-articles 1754 (sort gnus-scores-articles
1726 (lambda (a1 a2) 1755 (lambda (a1 a2)
1727 (< (mail-header-number (car a1)) 1756 (< (mail-header-number (car a1))
1728 (mail-header-number (car a2)))))) 1757 (mail-header-number (car a2))))))
1729 (set-buffer nntp-server-buffer) 1758 (set-buffer nntp-server-buffer)
1730 (save-restriction 1759 (save-restriction
1731 (let* ((buffer-read-only nil) 1760 (let* ((buffer-read-only nil)
1732 (articles gnus-scores-articles) 1761 (articles gnus-scores-articles)
1733 (all-scores scores) 1762 (all-scores scores)
1734 (request-func (cond ((string= "head" header) 1763 (request-func (cond ((string= "head" header)
1735 'gnus-request-head) 1764 'gnus-request-head)
1736 ((string= "body" header) 1765 ;; We need to peek at the headers to detect
1737 'gnus-request-body) 1766 ;; the content encoding
1738 (t 'gnus-request-article))) 1767 ((string= "body" header)
1739 entries alist ofunc article last) 1768 'gnus-request-article)
1740 (when articles 1769 (t 'gnus-request-article)))
1741 (setq last (mail-header-number (caar (last articles)))) 1770 entries alist ofunc article last)
1742 ;; Not all backends support partial fetching. In that case, 1771 (when articles
1743 ;; we just fetch the entire article. 1772 (setq last (mail-header-number (caar (last articles))))
1744 (unless (gnus-check-backend-function 1773 ;; Not all backends support partial fetching. In that case,
1745 (and (string-match "^gnus-" (symbol-name request-func)) 1774 ;; we just fetch the entire article.
1746 (intern (substring (symbol-name request-func) 1775 (unless (gnus-check-backend-function
1747 (match-end 0)))) 1776 (and (string-match "^gnus-" (symbol-name request-func))
1748 gnus-newsgroup-name) 1777 (intern (substring (symbol-name request-func)
1749 (setq ofunc request-func) 1778 (match-end 0))))
1750 (setq request-func 'gnus-request-article)) 1779 gnus-newsgroup-name)
1751 (while articles 1780 (setq ofunc request-func)
1752 (setq article (mail-header-number (caar articles))) 1781 (setq request-func 'gnus-request-article))
1753 (gnus-message 7 "Scoring article %s of %s..." article last) 1782 (while articles
1754 (widen) 1783 (setq article (mail-header-number (caar articles)))
1755 (when (funcall request-func article gnus-newsgroup-name) 1784 (gnus-message 7 "Scoring article %s of %s..." article last)
1756 (goto-char (point-min)) 1785 (widen)
1757 ;; If just parts of the article is to be searched, but the 1786 (let (handles)
1758 ;; backend didn't support partial fetching, we just narrow 1787 (when (funcall request-func article gnus-newsgroup-name)
1759 ;; to the relevant parts. 1788 (when (string= "body" header)
1760 (when ofunc 1789 (setq handles (gnus-score-decode-text-parts)))
1761 (if (eq ofunc 'gnus-request-head) 1790 (goto-char (point-min))
1762 (narrow-to-region 1791 ;; If just parts of the article is to be searched, but the
1763 (point) 1792 ;; backend didn't support partial fetching, we just narrow
1764 (or (search-forward "\n\n" nil t) (point-max))) 1793 ;; to the relevant parts.
1765 (narrow-to-region 1794 (when ofunc
1766 (or (search-forward "\n\n" nil t) (point)) 1795 (if (eq ofunc 'gnus-request-head)
1767 (point-max)))) 1796 (narrow-to-region
1768 (setq scores all-scores) 1797 (point)
1769 ;; Find matches. 1798 (or (search-forward "\n\n" nil t) (point-max)))
1770 (while scores 1799 (narrow-to-region
1771 (setq alist (pop scores) 1800 (or (search-forward "\n\n" nil t) (point))
1772 entries (assoc header alist)) 1801 (point-max))))
1773 (while (cdr entries) ;First entry is the header index. 1802 (setq scores all-scores)
1774 (let* ((rest (cdr entries)) 1803 ;; Find matches.
1775 (kill (car rest)) 1804 (while scores
1776 (match (nth 0 kill)) 1805 (setq alist (pop scores)
1777 (type (or (nth 3 kill) 's)) 1806 entries (assoc header alist))
1778 (score (or (nth 1 kill) 1807 (while (cdr entries) ;First entry is the header index.
1779 gnus-score-interactive-default-score)) 1808 (let* ((rest (cdr entries))
1780 (date (nth 2 kill)) 1809 (kill (car rest))
1781 (found nil) 1810 (match (nth 0 kill))
1782 (case-fold-search 1811 (type (or (nth 3 kill) 's))
1783 (not (or (eq type 'R) (eq type 'S) 1812 (score (or (nth 1 kill)
1784 (eq type 'Regexp) (eq type 'String)))) 1813 gnus-score-interactive-default-score))
1785 (search-func 1814 (date (nth 2 kill))
1786 (cond ((or (eq type 'r) (eq type 'R) 1815 (found nil)
1787 (eq type 'regexp) (eq type 'Regexp)) 1816 (case-fold-search
1788 're-search-forward) 1817 (not (or (eq type 'R) (eq type 'S)
1789 ((or (eq type 's) (eq type 'S) 1818 (eq type 'Regexp) (eq type 'String))))
1790 (eq type 'string) (eq type 'String)) 1819 (search-func
1791 'search-forward) 1820 (cond ((or (eq type 'r) (eq type 'R)
1792 (t 1821 (eq type 'regexp) (eq type 'Regexp))
1793 (error "Invalid match type: %s" type))))) 1822 're-search-forward)
1794 (goto-char (point-min)) 1823 ((or (eq type 's) (eq type 'S)
1795 (when (funcall search-func match nil t) 1824 (eq type 'string) (eq type 'String))
1796 ;; Found a match, update scores. 1825 'search-forward)
1797 (setcdr (car articles) (+ score (cdar articles))) 1826 (t
1798 (setq found t) 1827 (error "Invalid match type: %s" type)))))
1799 (when trace 1828 (goto-char (point-min))
1800 (push 1829 (when (funcall search-func match nil t)
1801 (cons (car-safe (rassq alist gnus-score-cache)) 1830 ;; Found a match, update scores.
1802 kill) 1831 (setcdr (car articles) (+ score (cdar articles)))
1803 gnus-score-trace))) 1832 (setq found t)
1804 ;; Update expire date 1833 (when trace
1805 (unless trace 1834 (push
1806 (cond 1835 (cons (car-safe (rassq alist gnus-score-cache))
1807 ((null date)) ;Permanent entry. 1836 kill)
1808 ((and found gnus-update-score-entry-dates) 1837 gnus-score-trace)))
1809 ;; Match, update date. 1838 ;; Update expire date
1810 (gnus-score-set 'touched '(t) alist) 1839 (unless trace
1811 (setcar (nthcdr 2 kill) now)) 1840 (cond
1812 ((and expire (< date expire)) ;Old entry, remove. 1841 ((null date)) ;Permanent entry.
1813 (gnus-score-set 'touched '(t) alist) 1842 ((and found gnus-update-score-entry-dates)
1814 (setcdr entries (cdr rest)) 1843 ;; Match, update date.
1815 (setq rest entries)))) 1844 (gnus-score-set 'touched '(t) alist)
1816 (setq entries rest))))) 1845 (setcar (nthcdr 2 kill) now))
1817 (setq articles (cdr articles))))))) 1846 ((and expire (< date expire)) ;Old entry, remove.
1818 nil)) 1847 (gnus-score-set 'touched '(t) alist)
1848 (setcdr entries (cdr rest))
1849 (setq rest entries))))
1850 (setq entries rest))))
1851 (when handles (mm-destroy-parts handles))))
1852 (setq articles (cdr articles)))))))
1853 nil))
1819 1854
1820(defun gnus-score-thread (scores header now expire &optional trace) 1855(defun gnus-score-thread (scores header now expire &optional trace)
1821 (gnus-score-followup scores header now expire trace t)) 1856 (gnus-score-followup scores header now expire trace t))
diff --git a/lisp/gnus/gnus-srvr.el b/lisp/gnus/gnus-srvr.el
index 66509c939dc..f58cb80311a 100644
--- a/lisp/gnus/gnus-srvr.el
+++ b/lisp/gnus/gnus-srvr.el
@@ -490,8 +490,7 @@ The following commands are available:
490 (error "No such server: %s" server)) 490 (error "No such server: %s" server))
491 (gnus-server-set-status method 'ok) 491 (gnus-server-set-status method 'ok)
492 (prog1 492 (prog1
493 (or (gnus-open-server method) 493 (gnus-open-server method)
494 (progn (message "Couldn't open %s" server) nil))
495 (gnus-server-update-server server) 494 (gnus-server-update-server server)
496 (gnus-server-position-point)))) 495 (gnus-server-position-point))))
497 496
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index 5862e7807a2..8fbde5c8ecc 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -3824,12 +3824,28 @@ You should probably use `gnus-find-method-for-group' instead."
3824 "Go through PARAMETERS and expand them according to the match data." 3824 "Go through PARAMETERS and expand them according to the match data."
3825 (let (new) 3825 (let (new)
3826 (dolist (elem parameters) 3826 (dolist (elem parameters)
3827 (if (and (stringp (cdr elem)) 3827 (cond
3828 (string-match "\\\\[0-9&]" (cdr elem))) 3828 ((and (stringp (cdr elem))
3829 (push (cons (car elem) 3829 (string-match "\\\\[0-9&]" (cdr elem)))
3830 (gnus-expand-group-parameter match (cdr elem) group)) 3830 (push (cons (car elem)
3831 new) 3831 (gnus-expand-group-parameter match (cdr elem) group))
3832 (push elem new))) 3832 new))
3833 ;; For `sieve' group parameters, perform substitutions for every
3834 ;; string within the match rule. This allows for parameters such
3835 ;; as:
3836 ;; ("list\\.\\(.*\\)"
3837 ;; (sieve header :is "list-id" "<\\1.domain.org>"))
3838 ((eq 'sieve (car elem))
3839 (push (mapcar (lambda (sieve-elem)
3840 (if (and (stringp sieve-elem)
3841 (string-match "\\\\[0-9&]" sieve-elem))
3842 (gnus-expand-group-parameter match sieve-elem
3843 group)
3844 sieve-elem))
3845 (cdr elem))
3846 new))
3847 (t
3848 (push elem new))))
3833 new)) 3849 new))
3834 3850
3835(defun gnus-group-fast-parameter (group symbol &optional allow-list) 3851(defun gnus-group-fast-parameter (group symbol &optional allow-list)
@@ -3861,9 +3877,20 @@ The function `gnus-group-find-parameter' will do that for you."
3861 (when this-result 3877 (when this-result
3862 (setq result (car this-result)) 3878 (setq result (car this-result))
3863 ;; Expand if necessary. 3879 ;; Expand if necessary.
3864 (if (and (stringp result) (string-match "\\\\[0-9&]" result)) 3880 (cond
3865 (setq result (gnus-expand-group-parameter 3881 ((and (stringp result) (string-match "\\\\[0-9&]" result))
3866 (car head) result group))))))) 3882 (setq result (gnus-expand-group-parameter
3883 (car head) result group)))
3884 ;; For `sieve' group parameters, perform substitutions
3885 ;; for every string within the match rule (see above).
3886 ((eq symbol 'sieve)
3887 (setq result
3888 (mapcar (lambda (elem)
3889 (if (stringp elem)
3890 (gnus-expand-group-parameter (car head)
3891 elem group)
3892 elem))
3893 result))))))))
3867 ;; Done. 3894 ;; Done.
3868 result)))) 3895 result))))
3869 3896
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index 18088423eb0..42911ce0648 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -3292,11 +3292,33 @@ or in the synonym headers, defined by `message-header-synonyms'."
3292(defun message-insert-newsgroups () 3292(defun message-insert-newsgroups ()
3293 "Insert the Newsgroups header from the article being replied to." 3293 "Insert the Newsgroups header from the article being replied to."
3294 (interactive) 3294 (interactive)
3295 (when (and (message-position-on-field "Newsgroups") 3295 (let ((old-newsgroups (mail-fetch-field "newsgroups"))
3296 (mail-fetch-field "newsgroups") 3296 (new-newsgroups (message-fetch-reply-field "newsgroups"))
3297 (not (string-match "\\` *\\'" (mail-fetch-field "newsgroups")))) 3297 (first t)
3298 (insert ",")) 3298 insert-newsgroups)
3299 (insert (or (message-fetch-reply-field "newsgroups") ""))) 3299 (message-position-on-field "Newsgroups")
3300 (cond
3301 ((not new-newsgroups)
3302 (error "No Newsgroups to insert"))
3303 ((not old-newsgroups)
3304 (insert new-newsgroups))
3305 (t
3306 (setq new-newsgroups (split-string new-newsgroups "[, ]+")
3307 old-newsgroups (split-string old-newsgroups "[, ]+"))
3308 (dolist (group new-newsgroups)
3309 (unless (member group old-newsgroups)
3310 (push group insert-newsgroups)))
3311 (if (null insert-newsgroups)
3312 (error "Newgroup%s already in the header"
3313 (if (> (length new-newsgroups) 1)
3314 "s" ""))
3315 (when old-newsgroups
3316 (setq first nil))
3317 (dolist (group insert-newsgroups)
3318 (unless first
3319 (insert ","))
3320 (setq first nil)
3321 (insert group)))))))
3300 3322
3301 3323
3302 3324
diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el
index 7139a528e11..327649d41a1 100644
--- a/lisp/gnus/nnmaildir.el
+++ b/lisp/gnus/nnmaildir.el
@@ -77,6 +77,56 @@
77 77
78(defconst nnmaildir-version "Gnus") 78(defconst nnmaildir-version "Gnus")
79 79
80(defconst nnmaildir-flag-mark-mapping
81 '((?F . tick)
82 (?R . reply)
83 (?S . read))
84 "Alist mapping Maildir filename flags to Gnus marks.
85Maildir filenames are of the form \"unique-id:2,FLAGS\",
86where FLAGS are a string of characters in ASCII order.
87Some of the FLAGS correspond to Gnus marks.")
88
89(defsubst nnmaildir--mark-to-flag (mark)
90 "Find the Maildir flag that corresponds to MARK (an atom).
91Return a character, or `nil' if not found.
92See `nnmaildir-flag-mark-mapping'."
93 (car (rassq mark nnmaildir-flag-mark-mapping)))
94
95(defsubst nnmaildir--flag-to-mark (flag)
96 "Find the Gnus mark that corresponds to FLAG (a character).
97Return an atom, or `nil' if not found.
98See `nnmaildir-flag-mark-mapping'."
99 (cdr (assq flag nnmaildir-flag-mark-mapping)))
100
101(defun nnmaildir--ensure-suffix (filename)
102 "Ensure that FILENAME contains the suffix \":2,\"."
103 (if (string-match-p ":2," filename)
104 filename
105 (concat filename ":2,")))
106
107(defun nnmaildir--add-flag (flag suffix)
108 "Return a copy of SUFFIX where FLAG is set.
109SUFFIX should start with \":2,\"."
110 (unless (string-match-p "^:2," suffix)
111 (error "Invalid suffix `%s'" suffix))
112 (let* ((flags (substring suffix 3))
113 (flags-as-list (append flags nil))
114 (new-flags
115 (concat (gnus-delete-duplicates
116 ;; maildir flags must be sorted
117 (sort (cons flag flags-as-list) '<)))))
118 (concat ":2," new-flags)))
119
120(defun nnmaildir--remove-flag (flag suffix)
121 "Return a copy of SUFFIX where FLAG is cleared.
122SUFFIX should start with \":2,\"."
123 (unless (string-match-p "^:2," suffix)
124 (error "Invalid suffix `%s'" suffix))
125 (let* ((flags (substring suffix 3))
126 (flags-as-list (append flags nil))
127 (new-flags (concat (delq flag flags-as-list))))
128 (concat ":2," new-flags)))
129
80(defvar nnmaildir-article-file-name nil 130(defvar nnmaildir-article-file-name nil
81 "*The filename of the most recently requested article. This variable is set 131 "*The filename of the most recently requested article. This variable is set
82by nnmaildir-request-article.") 132by nnmaildir-request-article.")
@@ -152,6 +202,16 @@ by nnmaildir-request-article.")
152 (gnm nil) ;; flag: split from mail-sources? 202 (gnm nil) ;; flag: split from mail-sources?
153 (target-prefix nil :type string)) ;; symlink target prefix 203 (target-prefix nil :type string)) ;; symlink target prefix
154 204
205(defun nnmaildir--article-set-flags (article new-suffix curdir)
206 (let* ((prefix (nnmaildir--art-prefix article))
207 (suffix (nnmaildir--art-suffix article))
208 (article-file (concat curdir prefix suffix))
209 (new-name (concat curdir prefix new-suffix)))
210 (unless (file-exists-p article-file)
211 (error "Couldn't find article file %s" article-file))
212 (rename-file article-file new-name 'replace)
213 (setf (nnmaildir--art-suffix article) new-suffix)))
214
155(defun nnmaildir--expired-article (group article) 215(defun nnmaildir--expired-article (group article)
156 (setf (nnmaildir--art-nov article) nil) 216 (setf (nnmaildir--art-nov article) nil)
157 (let ((flist (nnmaildir--grp-flist group)) 217 (let ((flist (nnmaildir--grp-flist group))
@@ -208,29 +268,33 @@ by nnmaildir-request-article.")
208 (eval param)) 268 (eval param))
209 269
210(defmacro nnmaildir--with-nntp-buffer (&rest body) 270(defmacro nnmaildir--with-nntp-buffer (&rest body)
271 (declare (debug (body)))
211 `(with-current-buffer nntp-server-buffer 272 `(with-current-buffer nntp-server-buffer
212 ,@body)) 273 ,@body))
213(defmacro nnmaildir--with-work-buffer (&rest body) 274(defmacro nnmaildir--with-work-buffer (&rest body)
275 (declare (debug (body)))
214 `(with-current-buffer (get-buffer-create " *nnmaildir work*") 276 `(with-current-buffer (get-buffer-create " *nnmaildir work*")
215 ,@body)) 277 ,@body))
216(defmacro nnmaildir--with-nov-buffer (&rest body) 278(defmacro nnmaildir--with-nov-buffer (&rest body)
279 (declare (debug (body)))
217 `(with-current-buffer (get-buffer-create " *nnmaildir nov*") 280 `(with-current-buffer (get-buffer-create " *nnmaildir nov*")
218 ,@body)) 281 ,@body))
219(defmacro nnmaildir--with-move-buffer (&rest body) 282(defmacro nnmaildir--with-move-buffer (&rest body)
283 (declare (debug (body)))
220 `(with-current-buffer (get-buffer-create " *nnmaildir move*") 284 `(with-current-buffer (get-buffer-create " *nnmaildir move*")
221 ,@body)) 285 ,@body))
222 286
223(defmacro nnmaildir--subdir (dir subdir) 287(defsubst nnmaildir--subdir (dir subdir)
224 `(file-name-as-directory (concat ,dir ,subdir))) 288 (file-name-as-directory (concat dir subdir)))
225(defmacro nnmaildir--srvgrp-dir (srv-dir gname) 289(defsubst nnmaildir--srvgrp-dir (srv-dir gname)
226 `(nnmaildir--subdir ,srv-dir ,gname)) 290 (nnmaildir--subdir srv-dir gname))
227(defmacro nnmaildir--tmp (dir) `(nnmaildir--subdir ,dir "tmp")) 291(defsubst nnmaildir--tmp (dir) (nnmaildir--subdir dir "tmp"))
228(defmacro nnmaildir--new (dir) `(nnmaildir--subdir ,dir "new")) 292(defsubst nnmaildir--new (dir) (nnmaildir--subdir dir "new"))
229(defmacro nnmaildir--cur (dir) `(nnmaildir--subdir ,dir "cur")) 293(defsubst nnmaildir--cur (dir) (nnmaildir--subdir dir "cur"))
230(defmacro nnmaildir--nndir (dir) `(nnmaildir--subdir ,dir ".nnmaildir")) 294(defsubst nnmaildir--nndir (dir) (nnmaildir--subdir dir ".nnmaildir"))
231(defmacro nnmaildir--nov-dir (dir) `(nnmaildir--subdir ,dir "nov")) 295(defsubst nnmaildir--nov-dir (dir) (nnmaildir--subdir dir "nov"))
232(defmacro nnmaildir--marks-dir (dir) `(nnmaildir--subdir ,dir "marks")) 296(defsubst nnmaildir--marks-dir (dir) (nnmaildir--subdir dir "marks"))
233(defmacro nnmaildir--num-dir (dir) `(nnmaildir--subdir ,dir "num")) 297(defsubst nnmaildir--num-dir (dir) (nnmaildir--subdir dir "num"))
234 298
235(defmacro nnmaildir--unlink (file-arg) 299(defmacro nnmaildir--unlink (file-arg)
236 `(let ((file ,file-arg)) 300 `(let ((file ,file-arg))
@@ -305,6 +369,7 @@ by nnmaildir-request-article.")
305 string) 369 string)
306 370
307(defmacro nnmaildir--condcase (errsym body &rest handler) 371(defmacro nnmaildir--condcase (errsym body &rest handler)
372 (declare (debug (sexp form body)))
308 `(condition-case ,errsym 373 `(condition-case ,errsym
309 (let ((system-messages-locale "C")) ,body) 374 (let ((system-messages-locale "C")) ,body)
310 (error . ,handler))) 375 (error . ,handler)))
@@ -759,7 +824,7 @@ by nnmaildir-request-article.")
759 (dolist (file (funcall ls ndir nil "\\`[^.]" 'nosort)) 824 (dolist (file (funcall ls ndir nil "\\`[^.]" 'nosort))
760 (setq x (concat ndir file)) 825 (setq x (concat ndir file))
761 (and (time-less-p (nth 5 (file-attributes x)) (current-time)) 826 (and (time-less-p (nth 5 (file-attributes x)) (current-time))
762 (rename-file x (concat cdir file ":2,")))) 827 (rename-file x (concat cdir (nnmaildir--ensure-suffix file)))))
763 (setf (nnmaildir--grp-new group) nattr)) 828 (setf (nnmaildir--grp-new group) nattr))
764 (setq cattr (nth 5 (file-attributes cdir))) 829 (setq cattr (nth 5 (file-attributes cdir)))
765 (if (equal cattr (nnmaildir--grp-cur group)) 830 (if (equal cattr (nnmaildir--grp-cur group))
@@ -784,11 +849,23 @@ by nnmaildir-request-article.")
784 cdir (nnmaildir--marks-dir nndir) 849 cdir (nnmaildir--marks-dir nndir)
785 ndir (nnmaildir--subdir cdir "tick") 850 ndir (nnmaildir--subdir cdir "tick")
786 cdir (nnmaildir--subdir cdir "read")) 851 cdir (nnmaildir--subdir cdir "read"))
787 (dolist (file files) 852 (dolist (prefix-suffix files)
788 (setq file (car file)) 853 (let ((prefix (car prefix-suffix))
789 (if (or (not (file-exists-p (concat cdir file))) 854 (suffix (cdr prefix-suffix)))
790 (file-exists-p (concat ndir file))) 855 ;; increase num for each unread or ticked article
791 (setq num (1+ num))))) 856 (when (or
857 ;; first look for marks in suffix, if it's valid...
858 (when (and (stringp suffix)
859 (string-prefix-p ":2," suffix))
860 (or
861 (not (string-match-p
862 (string (nnmaildir--mark-to-flag 'read)) suffix))
863 (string-match-p
864 (string (nnmaildir--mark-to-flag 'tick)) suffix)))
865 ;; then look in marks directories
866 (not (file-exists-p (concat cdir prefix)))
867 (file-exists-p (concat ndir prefix)))
868 (incf num)))))
792 (setf (nnmaildir--grp-cache group) (make-vector num nil)) 869 (setf (nnmaildir--grp-cache group) (make-vector num nil))
793 (let ((inhibit-quit t)) 870 (let ((inhibit-quit t))
794 (set (intern gname groups) group)) 871 (set (intern gname groups) group))
@@ -916,12 +993,15 @@ by nnmaildir-request-article.")
916 "\n"))))) 993 "\n")))))
917 'group) 994 'group)
918 995
919(defun nnmaildir-request-marks (gname info &optional server) 996(defun nnmaildir-request-update-info (gname info &optional server)
920 (let ((group (nnmaildir--prepare server gname)) 997 (let* ((group (nnmaildir--prepare server gname))
921 pgname flist always-marks never-marks old-marks dotfile num dir 998 (curdir (nnmaildir--cur
922 markdirs marks mark ranges markdir article read end new-marks ls 999 (nnmaildir--srvgrp-dir
923 old-mmth new-mmth mtime mark-sym existing missing deactivate-mark 1000 (nnmaildir--srv-dir nnmaildir--cur-server) gname)))
924 article-list) 1001 (curdir-mtime (nth 5 (file-attributes curdir)))
1002 pgname flist always-marks never-marks old-marks dotfile num dir
1003 all-marks marks mark ranges markdir read end new-marks ls
1004 old-mmth new-mmth mtime mark-sym existing missing deactivate-mark)
925 (catch 'return 1005 (catch 'return
926 (unless group 1006 (unless group
927 (setf (nnmaildir--srv-error nnmaildir--cur-server) 1007 (setf (nnmaildir--srv-error nnmaildir--cur-server)
@@ -950,34 +1030,71 @@ by nnmaildir-request-article.")
950 dir (nnmaildir--nndir dir) 1030 dir (nnmaildir--nndir dir)
951 dir (nnmaildir--marks-dir dir) 1031 dir (nnmaildir--marks-dir dir)
952 ls (nnmaildir--group-ls nnmaildir--cur-server pgname) 1032 ls (nnmaildir--group-ls nnmaildir--cur-server pgname)
953 markdirs (funcall ls dir nil "\\`[^.]" 'nosort) 1033 all-marks (gnus-delete-duplicates
954 new-mmth (nnmaildir--up2-1 (length markdirs)) 1034 ;; get mark names from mark dirs and from flag
1035 ;; mappings
1036 (append
1037 (mapcar 'cdr nnmaildir-flag-mark-mapping)
1038 (mapcar 'intern (funcall ls dir nil "\\`[^.]" 'nosort))))
1039 new-mmth (nnmaildir--up2-1 (length all-marks))
955 new-mmth (make-vector new-mmth 0) 1040 new-mmth (make-vector new-mmth 0)
956 old-mmth (nnmaildir--grp-mmth group)) 1041 old-mmth (nnmaildir--grp-mmth group))
957 (dolist (mark markdirs) 1042 (dolist (mark all-marks)
958 (setq markdir (nnmaildir--subdir dir mark) 1043 (setq markdir (nnmaildir--subdir dir (symbol-name mark))
959 mark-sym (intern mark)
960 ranges nil) 1044 ranges nil)
961 (catch 'got-ranges 1045 (catch 'got-ranges
962 (if (memq mark-sym never-marks) (throw 'got-ranges nil)) 1046 (if (memq mark never-marks) (throw 'got-ranges nil))
963 (when (memq mark-sym always-marks) 1047 (when (memq mark always-marks)
964 (setq ranges existing) 1048 (setq ranges existing)
965 (throw 'got-ranges nil)) 1049 (throw 'got-ranges nil))
966 (setq mtime (nth 5 (file-attributes markdir))) 1050 ;; Find the mtime for this mark. If this mark can be expressed as
967 (set (intern mark new-mmth) mtime) 1051 ;; a filename flag, get the later of the mtimes for markdir and
968 (when (equal mtime (symbol-value (intern-soft mark old-mmth))) 1052 ;; curdir, otherwise only the markdir counts.
969 (setq ranges (assq mark-sym old-marks)) 1053 (setq mtime
1054 (let ((markdir-mtime (nth 5 (file-attributes markdir))))
1055 (cond
1056 ((null (nnmaildir--mark-to-flag mark))
1057 markdir-mtime)
1058 ((null markdir-mtime)
1059 curdir-mtime)
1060 ((null curdir-mtime)
1061 ;; this should never happen...
1062 markdir-mtime)
1063 ((time-less-p markdir-mtime curdir-mtime)
1064 curdir-mtime)
1065 (t
1066 markdir-mtime))))
1067 (set (intern (symbol-name mark) new-mmth) mtime)
1068 (when (equal mtime (symbol-value (intern-soft (symbol-name mark) old-mmth)))
1069 (setq ranges (assq mark old-marks))
970 (if ranges (setq ranges (cdr ranges))) 1070 (if ranges (setq ranges (cdr ranges)))
971 (throw 'got-ranges nil)) 1071 (throw 'got-ranges nil))
972 (setq article-list nil) 1072 (let ((article-list nil))
973 (dolist (prefix (funcall ls markdir nil "\\`[^.]" 'nosort)) 1073 ;; Consider the article marked if it either has the flag in the
974 (setq article (nnmaildir--flist-art flist prefix)) 1074 ;; filename, or is in the markdir. As you'd rarely remove a
975 (if article 1075 ;; flag/mark, this should avoid losing information in the most
976 (setq article-list 1076 ;; common usage pattern.
977 (cons (nnmaildir--art-num article) article-list)))) 1077 (or
978 (setq ranges (gnus-add-to-range ranges (sort article-list '<)))) 1078 (let ((flag (nnmaildir--mark-to-flag mark)))
979 (if (eq mark-sym 'read) (setq read ranges) 1079 ;; If this mark has a corresponding maildir flag...
980 (if ranges (setq marks (cons (cons mark-sym ranges) marks))))) 1080 (when flag
1081 (let ((regexp
1082 (concat "\\`[^.].*:2,[A-Z]*" (string flag))))
1083 ;; ...then find all files with that flag.
1084 (dolist (filename (funcall ls curdir nil regexp 'nosort))
1085 (let* ((prefix (car (split-string filename ":2,")))
1086 (article (nnmaildir--flist-art flist prefix)))
1087 (when article
1088 (push (nnmaildir--art-num article) article-list)))))))
1089 ;; Also check Gnus-specific mark directory, if it exists.
1090 (when (file-directory-p markdir)
1091 (dolist (prefix (funcall ls markdir nil "\\`[^.]" 'nosort))
1092 (let ((article (nnmaildir--flist-art flist prefix)))
1093 (when article
1094 (push (nnmaildir--art-num article) article-list))))))
1095 (setq ranges (gnus-add-to-range ranges (sort article-list '<)))))
1096 (if (eq mark 'read) (setq read ranges)
1097 (if ranges (setq marks (cons (cons mark ranges) marks)))))
981 (gnus-info-set-read info (gnus-range-add read missing)) 1098 (gnus-info-set-read info (gnus-range-add read missing))
982 (gnus-info-set-marks info marks 'extend) 1099 (gnus-info-set-marks info marks 'extend)
983 (setf (nnmaildir--grp-mmth group) new-mmth) 1100 (setf (nnmaildir--grp-mmth group) new-mmth)
@@ -1525,39 +1642,63 @@ by nnmaildir-request-article.")
1525 didnt))) 1642 didnt)))
1526 1643
1527(defun nnmaildir-request-set-mark (gname actions &optional server) 1644(defun nnmaildir-request-set-mark (gname actions &optional server)
1528 (let ((group (nnmaildir--prepare server gname)) 1645 (let* ((group (nnmaildir--prepare server gname))
1529 (coding-system-for-write nnheader-file-coding-system) 1646 (curdir (nnmaildir--cur
1530 (buffer-file-coding-system nil) 1647 (nnmaildir--srvgrp-dir
1531 (file-coding-system-alist nil) 1648 (nnmaildir--srv-dir nnmaildir--cur-server)
1532 del-mark del-action add-action set-action marksdir nlist 1649 gname)))
1533 ranges begin end article all-marks todo-marks mdir mfile 1650 (coding-system-for-write nnheader-file-coding-system)
1534 pgname ls permarkfile deactivate-mark) 1651 (buffer-file-coding-system nil)
1652 (file-coding-system-alist nil)
1653 del-mark del-action add-action set-action marksdir nlist
1654 ranges begin end article all-marks todo-marks mdir mfile
1655 pgname ls permarkfile deactivate-mark)
1535 (setq del-mark 1656 (setq del-mark
1536 (lambda (mark) 1657 (lambda (mark)
1537 (setq mfile (nnmaildir--subdir marksdir (symbol-name mark)) 1658 (let ((prefix (nnmaildir--art-prefix article))
1538 mfile (concat mfile (nnmaildir--art-prefix article))) 1659 (suffix (nnmaildir--art-suffix article))
1539 (nnmaildir--unlink mfile)) 1660 (flag (nnmaildir--mark-to-flag mark)))
1661 (when flag
1662 ;; If this mark corresponds to a flag, remove the flag from
1663 ;; the file name.
1664 (nnmaildir--article-set-flags
1665 article (nnmaildir--remove-flag flag suffix) curdir))
1666 ;; We still want to delete the hardlink in the marks dir if
1667 ;; present, regardless of whether this mark has a maildir flag or
1668 ;; not, to avoid getting out of sync.
1669 (setq mfile (nnmaildir--subdir marksdir (symbol-name mark))
1670 mfile (concat mfile prefix))
1671 (nnmaildir--unlink mfile)))
1540 del-action (lambda (article) (mapcar del-mark todo-marks)) 1672 del-action (lambda (article) (mapcar del-mark todo-marks))
1541 add-action 1673 add-action
1542 (lambda (article) 1674 (lambda (article)
1543 (mapcar 1675 (mapcar
1544 (lambda (mark) 1676 (lambda (mark)
1545 (setq mdir (nnmaildir--subdir marksdir (symbol-name mark)) 1677 (let ((prefix (nnmaildir--art-prefix article))
1546 permarkfile (concat mdir ":") 1678 (suffix (nnmaildir--art-suffix article))
1547 mfile (concat mdir (nnmaildir--art-prefix article))) 1679 (flag (nnmaildir--mark-to-flag mark)))
1548 (nnmaildir--condcase err (add-name-to-file permarkfile mfile) 1680 (if flag
1549 (cond 1681 ;; If there is a corresponding maildir flag, just rename
1550 ((nnmaildir--eexist-p err)) 1682 ;; the file.
1551 ((nnmaildir--enoent-p err) 1683 (nnmaildir--article-set-flags
1552 (nnmaildir--mkdir mdir) 1684 article (nnmaildir--add-flag flag suffix) curdir)
1553 (nnmaildir--mkfile permarkfile) 1685 ;; Otherwise, use nnmaildir-specific marks dir.
1554 (add-name-to-file permarkfile mfile)) 1686 (setq mdir (nnmaildir--subdir marksdir (symbol-name mark))
1555 ((nnmaildir--emlink-p err) 1687 permarkfile (concat mdir ":")
1556 (let ((permarkfilenew (concat permarkfile "{new}"))) 1688 mfile (concat mdir prefix))
1557 (nnmaildir--mkfile permarkfilenew) 1689 (nnmaildir--condcase err (add-name-to-file permarkfile mfile)
1558 (rename-file permarkfilenew permarkfile 'replace) 1690 (cond
1559 (add-name-to-file permarkfile mfile))) 1691 ((nnmaildir--eexist-p err))
1560 (t (signal (car err) (cdr err)))))) 1692 ((nnmaildir--enoent-p err)
1693 (nnmaildir--mkdir mdir)
1694 (nnmaildir--mkfile permarkfile)
1695 (add-name-to-file permarkfile mfile))
1696 ((nnmaildir--emlink-p err)
1697 (let ((permarkfilenew (concat permarkfile "{new}")))
1698 (nnmaildir--mkfile permarkfilenew)
1699 (rename-file permarkfilenew permarkfile 'replace)
1700 (add-name-to-file permarkfile mfile)))
1701 (t (signal (car err) (cdr err))))))))
1561 todo-marks)) 1702 todo-marks))
1562 set-action (lambda (article) 1703 set-action (lambda (article)
1563 (funcall add-action article) 1704 (funcall add-action article)
@@ -1581,7 +1722,12 @@ by nnmaildir-request-article.")
1581 pgname (nnmaildir--pgname nnmaildir--cur-server gname) 1722 pgname (nnmaildir--pgname nnmaildir--cur-server gname)
1582 ls (nnmaildir--group-ls nnmaildir--cur-server pgname) 1723 ls (nnmaildir--group-ls nnmaildir--cur-server pgname)
1583 all-marks (funcall ls marksdir nil "\\`[^.]" 'nosort) 1724 all-marks (funcall ls marksdir nil "\\`[^.]" 'nosort)
1584 all-marks (mapcar 'intern all-marks)) 1725 all-marks (gnus-delete-duplicates
1726 ;; get mark names from mark dirs and from flag
1727 ;; mappings
1728 (append
1729 (mapcar 'cdr nnmaildir-flag-mark-mapping)
1730 (mapcar 'intern all-marks))))
1585 (dolist (action actions) 1731 (dolist (action actions)
1586 (setq ranges (car action) 1732 (setq ranges (car action)
1587 todo-marks (caddr action)) 1733 todo-marks (caddr action))
diff --git a/lisp/help.el b/lisp/help.el
index 9740f8996c1..cacbf185963 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -962,7 +962,11 @@ is currently activated with completion."
962 result)) 962 result))
963 963
964;;; Automatic resizing of temporary buffers. 964;;; Automatic resizing of temporary buffers.
965(defcustom temp-buffer-max-height (lambda (buffer) (/ (- (frame-height) 2) 2)) 965(defcustom temp-buffer-max-height
966 (lambda (buffer)
967 (if (eq (selected-window) (frame-root-window))
968 (/ (x-display-pixel-height) (frame-char-height) 2)
969 (/ (- (frame-height) 2) 2)))
966 "Maximum height of a window displaying a temporary buffer. 970 "Maximum height of a window displaying a temporary buffer.
967This is effective only when Temp Buffer Resize mode is enabled. 971This is effective only when Temp Buffer Resize mode is enabled.
968The value is the maximum height (in lines) which 972The value is the maximum height (in lines) which
@@ -973,7 +977,16 @@ buffer, and should return a positive integer. At the time the
973function is called, the window to be resized is selected." 977function is called, the window to be resized is selected."
974 :type '(choice integer function) 978 :type '(choice integer function)
975 :group 'help 979 :group 'help
976 :version "20.4") 980 :version "24.2")
981
982(defcustom temp-buffer-resize-frames nil
983 "Non-nil means `temp-buffer-resize-mode' can resize frames.
984A frame can be resized if and only if its root window is a live
985window. The height of the root window is subject to the values of
986`temp-buffer-max-height' and `window-min-height'."
987 :type 'boolean
988 :version "24.2"
989 :group 'help)
977 990
978(define-minor-mode temp-buffer-resize-mode 991(define-minor-mode temp-buffer-resize-mode
979 "Toggle auto-resizing temporary buffer windows (Temp Buffer Resize Mode). 992 "Toggle auto-resizing temporary buffer windows (Temp Buffer Resize Mode).
@@ -1008,9 +1021,21 @@ view."
1008 (with-selected-window window 1021 (with-selected-window window
1009 (funcall temp-buffer-max-height (window-buffer))) 1022 (funcall temp-buffer-max-height (window-buffer)))
1010 temp-buffer-max-height))) 1023 temp-buffer-max-height)))
1011 (when (and (pos-visible-in-window-p (point-min) window) 1024 (cond
1012 (window-combined-p window)) 1025 ((and (pos-visible-in-window-p (point-min) window)
1013 (fit-window-to-buffer window height)))) 1026 (window-combined-p window))
1027 (fit-window-to-buffer window height))
1028 ((and temp-buffer-resize-frames
1029 (eq window (frame-root-window window))
1030 (memq (car (window-parameter window 'quit-restore))
1031 ;; If 'same is too strong, we might additionally check
1032 ;; whether the second element is 'frame.
1033 '(same frame)))
1034 (let ((frame (window-frame window)))
1035 (fit-frame-to-buffer
1036 frame (+ (frame-height frame)
1037 (- (window-total-size window))
1038 height)))))))
1014 1039
1015;;; Help windows. 1040;;; Help windows.
1016(defcustom help-window-select 'other 1041(defcustom help-window-select 'other
diff --git a/lisp/play/blackbox.el b/lisp/play/blackbox.el
index db2e18188e5..16189600156 100644
--- a/lisp/play/blackbox.el
+++ b/lisp/play/blackbox.el
@@ -97,7 +97,9 @@
97 (let ((map (make-keymap))) 97 (let ((map (make-keymap)))
98 (suppress-keymap map t) 98 (suppress-keymap map t)
99 (blackbox-redefine-key map 'backward-char 'bb-left) 99 (blackbox-redefine-key map 'backward-char 'bb-left)
100 (blackbox-redefine-key map 'left-char 'bb-left)
100 (blackbox-redefine-key map 'forward-char 'bb-right) 101 (blackbox-redefine-key map 'forward-char 'bb-right)
102 (blackbox-redefine-key map 'right-char 'bb-right)
101 (blackbox-redefine-key map 'previous-line 'bb-up) 103 (blackbox-redefine-key map 'previous-line 'bb-up)
102 (blackbox-redefine-key map 'next-line 'bb-down) 104 (blackbox-redefine-key map 'next-line 'bb-down)
103 (blackbox-redefine-key map 'move-end-of-line 'bb-eol) 105 (blackbox-redefine-key map 'move-end-of-line 'bb-eol)
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index ad285274928..10d5fdf9c64 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -977,6 +977,9 @@ from compile.el")
977;; :type '(repeat (string number number number)) 977;; :type '(repeat (string number number number))
978;;) 978;;)
979 979
980(defvar flymake-warning-re "^[wW]arning"
981 "Regexp matching against err-text to detect a warning.")
982
980(defun flymake-parse-line (line) 983(defun flymake-parse-line (line)
981 "Parse LINE to see if it is an error or warning. 984 "Parse LINE to see if it is an error or warning.
982Return its components if so, nil otherwise." 985Return its components if so, nil otherwise."
@@ -997,7 +1000,7 @@ Return its components if so, nil otherwise."
997 (match-string (nth 4 (car patterns)) line) 1000 (match-string (nth 4 (car patterns)) line)
998 (flymake-patch-err-text (substring line (match-end 0))))) 1001 (flymake-patch-err-text (substring line (match-end 0)))))
999 (or err-text (setq err-text "<no error text>")) 1002 (or err-text (setq err-text "<no error text>"))
1000 (if (and err-text (string-match "^[wW]arning" err-text)) 1003 (if (and err-text (string-match flymake-warning-re err-text))
1001 (setq err-type "w") 1004 (setq err-type "w")
1002 ) 1005 )
1003 (flymake-log 3 "parse line: file-idx=%s line-idx=%s file=%s line=%s text=%s" file-idx line-idx 1006 (flymake-log 3 "parse line: file-idx=%s line-idx=%s file=%s line=%s text=%s" file-idx line-idx
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index a422462775d..b4d550bcee0 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -1062,21 +1062,22 @@ subshells can nest."
1062 (backward-char 1)) 1062 (backward-char 1))
1063 (when (eq (char-before) ?|) 1063 (when (eq (char-before) ?|)
1064 (backward-char 1) t))) 1064 (backward-char 1) t)))
1065 (when (progn (backward-char 2) 1065 (and (> (point) (1+ (point-min)))
1066 (if (> start (line-end-position)) 1066 (progn (backward-char 2)
1067 (put-text-property (point) (1+ start) 1067 (if (> start (line-end-position))
1068 'syntax-multiline t)) 1068 (put-text-property (point) (1+ start)
1069 ;; FIXME: The `in' may just be a random argument to 1069 'syntax-multiline t))
1070 ;; a normal command rather than the real `in' keyword. 1070 ;; FIXME: The `in' may just be a random argument to
1071 ;; I.e. we should look back to try and find the 1071 ;; a normal command rather than the real `in' keyword.
1072 ;; corresponding `case'. 1072 ;; I.e. we should look back to try and find the
1073 (and (looking-at ";[;&]\\|\\_<in") 1073 ;; corresponding `case'.
1074 ;; ";; esac )" is a case that looks like a case-pattern 1074 (and (looking-at ";[;&]\\|\\_<in")
1075 ;; but it's really just a close paren after a case 1075 ;; ";; esac )" is a case that looks like a case-pattern
1076 ;; statement. I.e. if we skipped over `esac' just now, 1076 ;; but it's really just a close paren after a case
1077 ;; we're not looking at a case-pattern. 1077 ;; statement. I.e. if we skipped over `esac' just now,
1078 (not (looking-at "..[ \t\n]+esac[^[:word:]_]")))) 1078 ;; we're not looking at a case-pattern.
1079 sh-st-punc)))) 1079 (not (looking-at "..[ \t\n]+esac[^[:word:]_]"))))
1080 sh-st-punc))))
1080 1081
1081(defun sh-font-lock-backslash-quote () 1082(defun sh-font-lock-backslash-quote ()
1082 (if (eq (save-excursion (nth 3 (syntax-ppss (match-beginning 0)))) ?\') 1083 (if (eq (save-excursion (nth 3 (syntax-ppss (match-beginning 0)))) ?\')
diff --git a/lisp/textmodes/picture.el b/lisp/textmodes/picture.el
index 24a4ac1b033..e663c1b45f4 100644
--- a/lisp/textmodes/picture.el
+++ b/lisp/textmodes/picture.el
@@ -612,13 +612,15 @@ Leaves the region surrounding the rectangle."
612 (define-key map [remap self-insert-command] 'picture-self-insert) 612 (define-key map [remap self-insert-command] 'picture-self-insert)
613 (define-key map [remap self-insert-command] 'picture-self-insert) 613 (define-key map [remap self-insert-command] 'picture-self-insert)
614 (define-key map [remap completion-separator-self-insert-command] 614 (define-key map [remap completion-separator-self-insert-command]
615 'picture-self-insert) 615 'picture-self-insert)
616 (define-key map [remap completion-separator-self-insert-autofilling] 616 (define-key map [remap completion-separator-self-insert-autofilling]
617 'picture-self-insert) 617 'picture-self-insert)
618 (define-key map [remap forward-char] 'picture-forward-column) 618 (define-key map [remap forward-char] 'picture-forward-column)
619 (define-key map [remap right-char] 'picture-forward-column)
619 (define-key map [remap backward-char] 'picture-backward-column) 620 (define-key map [remap backward-char] 'picture-backward-column)
621 (define-key map [remap left-char] 'picture-backward-column)
620 (define-key map [remap delete-char] 'picture-clear-column) 622 (define-key map [remap delete-char] 'picture-clear-column)
621 ;; There are two possibilities for what is normally on DEL. 623 ;; There are two possibilities for what is normally on DEL.
622 (define-key map [remap backward-delete-char-untabify] 624 (define-key map [remap backward-delete-char-untabify]
623 'picture-backward-clear-column) 625 'picture-backward-clear-column)
624 (define-key map [remap delete-backward-char] 'picture-backward-clear-column) 626 (define-key map [remap delete-backward-char] 'picture-backward-clear-column)
diff --git a/lisp/window.el b/lisp/window.el
index f73c85e991b..66b86f45e77 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -5918,6 +5918,88 @@ WINDOW was scrolled."
5918 (error (setq delta nil))) 5918 (error (setq delta nil)))
5919 delta)))) 5919 delta))))
5920 5920
5921(defcustom fit-frame-to-buffer-bottom-margin 4
5922 "Bottom margin for `fit-frame-to-buffer'.
5923This is the number of lines `fit-frame-to-buffer' leaves free at the
5924bottom of the display in order to not obscure the system task bar."
5925 :type 'integer
5926 :version "24.2"
5927 :group 'windows)
5928
5929(defun fit-frame-to-buffer (&optional frame max-height min-height)
5930 "Adjust height of FRAME to display its buffer's contents exactly.
5931FRAME can be any live frame and defaults to the selected one.
5932
5933Optional argument MAX-HEIGHT specifies the maximum height of
5934FRAME and defaults to the height of the display below the current
5935top line of FRAME minus FIT-FRAME-TO-BUFFER-BOTTOM-MARGIN.
5936Optional argument MIN-HEIGHT specifies the minimum height of
5937FRAME."
5938 (interactive)
5939 (setq frame (window-normalize-frame frame))
5940 (let* ((root (frame-root-window frame))
5941 (frame-min-height
5942 (+ (- (frame-height frame) (window-total-size root))
5943 window-min-height))
5944 (frame-top (frame-parameter frame 'top))
5945 (top (if (consp frame-top)
5946 (funcall (car frame-top) (cadr frame-top))
5947 frame-top))
5948 (frame-max-height
5949 (- (/ (- (x-display-pixel-height frame) top)
5950 (frame-char-height frame))
5951 fit-frame-to-buffer-bottom-margin))
5952 (compensate 0)
5953 delta)
5954 (when (and (window-live-p root) (not (window-size-fixed-p root)))
5955 (with-selected-window root
5956 (cond
5957 ((not max-height)
5958 (setq max-height frame-max-height))
5959 ((numberp max-height)
5960 (setq max-height (min max-height frame-max-height)))
5961 (t
5962 (error "%s is an invalid maximum height" max-height)))
5963 (cond
5964 ((not min-height)
5965 (setq min-height frame-min-height))
5966 ((numberp min-height)
5967 (setq min-height (min min-height frame-min-height)))
5968 (t
5969 (error "%s is an invalid minimum height" min-height)))
5970 ;; When tool-bar-mode is enabled and we have just created a new
5971 ;; frame, reserve lines for toolbar resizing. This is needed
5972 ;; because for reasons unknown to me Emacs (1) reserves one line
5973 ;; for the toolbar when making the initial frame and toolbars
5974 ;; are enabled, and (2) later adds the remaining lines needed.
5975 ;; Our code runs IN BETWEEN (1) and (2). YMMV when you're on a
5976 ;; system that behaves differently.
5977 (let ((quit-restore (window-parameter root 'quit-restore))
5978 (lines (tool-bar-lines-needed frame)))
5979 (when (and quit-restore (eq (car quit-restore) 'frame)
5980 (not (zerop lines)))
5981 (setq compensate (1- lines))))
5982 (message "%s" compensate)
5983 (setq delta
5984 ;; Always count a final newline - we don't do any
5985 ;; post-processing, so let's play safe.
5986 (+ (count-screen-lines nil nil t)
5987 (- (window-body-size))
5988 compensate)))
5989 ;; Move away from final newline.
5990 (when (and (eobp) (bolp) (not (bobp)))
5991 (set-window-point root (line-beginning-position 0)))
5992 (set-window-start root (point-min))
5993 (set-window-vscroll root 0)
5994 (condition-case nil
5995 (set-frame-height
5996 frame
5997 (min (max (+ (frame-height frame) delta)
5998 min-height)
5999 max-height))
6000 (error (setq delta nil))))
6001 delta))
6002
5921(defun window-safely-shrinkable-p (&optional window) 6003(defun window-safely-shrinkable-p (&optional window)
5922 "Return t if WINDOW can be shrunk without shrinking other windows. 6004 "Return t if WINDOW can be shrunk without shrinking other windows.
5923WINDOW defaults to the selected window." 6005WINDOW defaults to the selected window."