diff options
| author | Gnus developers | 2010-12-02 22:21:31 +0000 |
|---|---|---|
| committer | Katsumi Yamaoka | 2010-12-02 22:21:31 +0000 |
| commit | ed797193995dc845b70a32c82eee63a39c40011f (patch) | |
| tree | da7623c16afe017ab7e33b2d9116a5f5644c4bb6 | |
| parent | 66feec8bbe23ad4979905e9f6fae807b27cc33de (diff) | |
| download | emacs-ed797193995dc845b70a32c82eee63a39c40011f.tar.gz emacs-ed797193995dc845b70a32c82eee63a39c40011f.zip | |
Merge changes made in Gnus trunk.
nnir.el: Batch header retrieval.
proto-stream.el: New library to provide protocol-specific TLS/STARTTLS connections for IMAP, NNTP, SMTP, POP3 and similar protocols.
nnimap.el (nnimap-open-connection): Use it.
proto-stream.el (open-proto-stream): Complete the documentation.
nnimap.el (nnimap-open-connection): Check for "OK" from the greeting.
nntp.el: Use proto-streams for the relevant connections types.
nntp.el (nntp-open-connection): Switch on STARTTLS on supported servers.
proto-stream.el (open-proto-stream): Add a way to specify what the end of a command is.
proto-stream.el (proto-stream-open-tls): Delete output from openssl if we're using tls.el.
proto-stream.el (proto-stream-open-network): If we don't have gnutls-cli or gnutls built in, then don't try to establish a STARTTLS connection.
color.el (color-lab->srgb): Fix function call name.
proto-stream.el: Fix the syntax in the comment.
nntp.el (nntp-open-connection): Fix the STARTTLS command syntax.
proto-stream.el (proto-stream-open-starttls): Actually implement the starttls.el STARTTLS.
proto-stream.el (proto-stream-always-use-starttls): New variable.
proto-stream.el (proto-stream-open-starttls): De-duplicate the starttls code.
proto-stream.el (proto-stream-open-starttls): Folded back into the main function.
proto-stream.el (proto-stream-command): Refactor out.
nnimap.el (nnimap-stream): Change default to `undecided'.
nnimap.el (nnimap-open-connection): If `nnimap-stream' is `undecided', try ssl first, and then network.
nnimap.el (nnimap-open-connection-1): Respect nnimap-server-port.
nnimap.el (nnimap-open-connection): Be more backwards-compatible.
proto-stream.el (open-protocol-stream): Renamed from open-proto-stream.
proto-stream.el (proto-stream-open-network): When doing opportunistic TLS upgrades we don't really care about the identity of the peer.
gnus.texi (Customizing the IMAP Connection): Note the new defaults.
gnus.texi (Direct Functions): Note the STARTTLS upgrade.
proto-stream.el (proto-stream-open-network): Force starttls.el to use gnutls-cli, since that what we've checked for.
proto-stream.el (proto-stream-always-use-starttls): Only default to t if open-gnutls-stream exists.
proto-stream.el (proto-stream-open-network): If STARTTLS failed, then just open a normal connection.
proto-stream.el (proto-stream-open-network): Wait until the greeting before doing STARTTLS.
nnimap.el (nnimap-open-connection-1): Always upgrade to STARTTLS (for backwards compatibility).
nnimap.el (nnimap-open-connection-1): Really respect nnimap-server-port.
nntp.el (nntp-open-connection): Provide a :success condition.
nnimap.el (nnimap-open-connection-1): Ditto.
proto-stream.el (proto-stream-open-network): See what the response to the STARTTLS command is.
proto-stream.el (proto-stream-open-network): Add some comments.
proto-stream.el: Fix example.
proto-stream.el (open-protocol-stream): Actually mention the STARTTLS upgrade.
nnir.el (nnir-get-active): Skip nnir-ignored-newsgroups when searching.
nnir.el (nnir-ignore-newsgroups): Fix default value.
nnir.el (nnir-run-gmane): Use mm-delete-duplicates instead of delete-dups that is not available in XEmacs 21.4.
mm-util.el (mm-delete-duplicates): Add comment.
gnus-sum.el (gnus-summary-delete-article): If delete fails don't change the registry.
nnimap.el (nnimap-open-connection-1): w32 open-network-stream doesn't seem to accept strings-with-numbers as port numbers.
color.el: fix docstring to use English rather than math notation for intervals.
shr.el (shr-find-fill-point): Don't break before apostrophes.
nnir.el (nnir-request-move-article): Bail out if no move support in group.
color.el (color-rgb->hsv): Fix docstring.
nnir.el (nnir-get-active): Improve active list retrieval.
shr.el (shr-find-fill-point): Work better for kinsoku chars and apostrophes.
gnus-gravatar.el (gnus-gravatar-size): Set gnus-gravatar-size to nil.
nnimap.el (nnimap-open-connection-1): Use gnus-string-match-p.
nnimap.el (nnimap-open-connection-1): Fix PREAUTH.
proto-stream.el (open-protocol-stream): All starttls connections are handled by the network handler.
gnus-gravatar.el (gnus-gravatar-insert): Delete unnecessary binding to t of inhibit-read-only since it is inside gnus-with-article-headers.
gnus-gravatar.el (gnus-gravatar-transform-address): Use mail-extract-address-components that supports non-ASCII names rather than mail-header-parse-addresses.
shr.el (shr-find-fill-point): Don't break line between kinsoku-bol characters.
gnus-gravatar.el (gnus-gravatar-insert): Allow LWSP in the middle of names.
nnmaildir.el (nnmaildir-request-set-mark): Add article to add-mark funcall.
gnus-msg.el: Remove nastygram thing.
message.el (message-from-style): Fix comment.
message.el (message-user-organization): Do not use gnus-local-organization.
gnus.el: Remove gnus-local-organization.
rtree.el: New file to handle range trees.
nnir.el, gnus-sum.el: Redo the way nnir handles registry updates.
rtree.el (rtree-extract): Simplify.
gnus-win.el (gnus-configure-windows): Remove Gnus 3.x setting support.
gnus-msg.el: Mark gnus-outgoing-message-group as obsolete.
gnus.texi (Archived Messages): Remove gnus-outgoing-message-group.
gnus-win.el (gnus-configure-frame): Remove old compatibility code.
rtree.el (rtree-memq): Rewrite it as a non-recursive function.
rtree.el (rtree-add, rtree-delq, rtree-length): Implement.
rtree.el (rtree-add): Make code slightly faster.
nnir.el: Allow modified summary-line-format in nnir summary buffers.
| -rw-r--r-- | doc/misc/ChangeLog | 9 | ||||
| -rw-r--r-- | doc/misc/gnus.texi | 30 | ||||
| -rw-r--r-- | lisp/gnus/ChangeLog | 225 | ||||
| -rw-r--r-- | lisp/gnus/color.el | 13 | ||||
| -rw-r--r-- | lisp/gnus/gnus-gravatar.el | 47 | ||||
| -rw-r--r-- | lisp/gnus/gnus-msg.el | 67 | ||||
| -rw-r--r-- | lisp/gnus/gnus-sum.el | 425 | ||||
| -rw-r--r-- | lisp/gnus/gnus-win.el | 142 | ||||
| -rw-r--r-- | lisp/gnus/gnus.el | 4 | ||||
| -rw-r--r-- | lisp/gnus/message.el | 17 | ||||
| -rw-r--r-- | lisp/gnus/mm-util.el | 1 | ||||
| -rw-r--r-- | lisp/gnus/nnimap.el | 193 | ||||
| -rw-r--r-- | lisp/gnus/nnir.el | 424 | ||||
| -rw-r--r-- | lisp/gnus/nnmaildir.el | 2 | ||||
| -rw-r--r-- | lisp/gnus/nntp.el | 67 | ||||
| -rw-r--r-- | lisp/gnus/proto-stream.el | 262 | ||||
| -rw-r--r-- | lisp/gnus/rtree.el | 279 | ||||
| -rw-r--r-- | lisp/gnus/shr.el | 160 |
18 files changed, 1532 insertions, 835 deletions
diff --git a/doc/misc/ChangeLog b/doc/misc/ChangeLog index 91ac5f74b0e..8d47de4f2a0 100644 --- a/doc/misc/ChangeLog +++ b/doc/misc/ChangeLog | |||
| @@ -1,3 +1,12 @@ | |||
| 1 | 2010-12-02 Julien Danjou <julien@danjou.info> | ||
| 2 | |||
| 3 | * gnus.texi (Archived Messages): Remove gnus-outgoing-message-group. | ||
| 4 | |||
| 5 | 2010-11-28 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 6 | |||
| 7 | * gnus.texi (Customizing the IMAP Connection): Note the new defaults. | ||
| 8 | (Direct Functions): Note the STARTTLS upgrade. | ||
| 9 | |||
| 1 | 2010-11-27 Glenn Morris <rgm@gnu.org> | 10 | 2010-11-27 Glenn Morris <rgm@gnu.org> |
| 2 | James Clark <none@example.com> | 11 | James Clark <none@example.com> |
| 3 | 12 | ||
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index ad9be300a1d..9e2e0b817b6 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi | |||
| @@ -13342,21 +13342,6 @@ case you should set @code{gnus-message-archive-group} to @code{nil}; | |||
| 13342 | this will disable archiving. | 13342 | this will disable archiving. |
| 13343 | 13343 | ||
| 13344 | @table @code | 13344 | @table @code |
| 13345 | @item gnus-outgoing-message-group | ||
| 13346 | @vindex gnus-outgoing-message-group | ||
| 13347 | All outgoing messages will be put in this group. If you want to store | ||
| 13348 | all your outgoing mail and articles in the group @samp{nnml:archive}, | ||
| 13349 | you set this variable to that value. This variable can also be a list of | ||
| 13350 | group names. | ||
| 13351 | |||
| 13352 | If you want to have greater control over what group to put each | ||
| 13353 | message in, you can set this variable to a function that checks the | ||
| 13354 | current newsgroup name and then returns a suitable group name (or list | ||
| 13355 | of names). | ||
| 13356 | |||
| 13357 | This variable can be used instead of @code{gnus-message-archive-group}, | ||
| 13358 | but the latter is the preferred method. | ||
| 13359 | |||
| 13360 | @item gnus-gcc-mark-as-read | 13345 | @item gnus-gcc-mark-as-read |
| 13361 | @vindex gnus-gcc-mark-as-read | 13346 | @vindex gnus-gcc-mark-as-read |
| 13362 | If non-@code{nil}, automatically mark @code{Gcc} articles as read. | 13347 | If non-@code{nil}, automatically mark @code{Gcc} articles as read. |
| @@ -14453,7 +14438,9 @@ functions is also affected by commonly understood variables | |||
| 14453 | @findex nntp-open-network-stream | 14438 | @findex nntp-open-network-stream |
| 14454 | @item nntp-open-network-stream | 14439 | @item nntp-open-network-stream |
| 14455 | This is the default, and simply connects to some port or other on the | 14440 | This is the default, and simply connects to some port or other on the |
| 14456 | remote system. | 14441 | remote system. If both Emacs and the server supports it, the |
| 14442 | connection will be upgraded to an encrypted @acronym{STARTTLS} | ||
| 14443 | connection automatically. | ||
| 14457 | 14444 | ||
| 14458 | @findex nntp-open-tls-stream | 14445 | @findex nntp-open-tls-stream |
| 14459 | @item nntp-open-tls-stream | 14446 | @item nntp-open-tls-stream |
| @@ -14887,12 +14874,17 @@ typical port would be @code{"imap"} or @code{"imaps"}. | |||
| 14887 | How @code{nnimap} should connect to the server. Possible values are: | 14874 | How @code{nnimap} should connect to the server. Possible values are: |
| 14888 | 14875 | ||
| 14889 | @table @code | 14876 | @table @code |
| 14877 | @item undecided | ||
| 14878 | This is the default, and this first tries the @code{ssl} setting, and | ||
| 14879 | then tries the @code{network} setting. | ||
| 14880 | |||
| 14890 | @item ssl | 14881 | @item ssl |
| 14891 | This is the default, and this uses standard | 14882 | This uses standard @acronym{TLS}/@acronym{SSL} connections. |
| 14892 | @acronym{TLS}/@acronym{SSL} connection. | ||
| 14893 | 14883 | ||
| 14894 | @item network | 14884 | @item network |
| 14895 | Non-encrypted and unsafe straight socket connection. | 14885 | Non-encrypted and unsafe straight socket connection, but will upgrade |
| 14886 | to encrypted @acronym{STARTTLS} if both Emacs and the server | ||
| 14887 | supports it. | ||
| 14896 | 14888 | ||
| 14897 | @item starttls | 14889 | @item starttls |
| 14898 | Encrypted @acronym{STARTTLS} over the normal @acronym{IMAP} port. | 14890 | Encrypted @acronym{STARTTLS} over the normal @acronym{IMAP} port. |
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index 651cfef7f00..8d4b14fa456 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,3 +1,228 @@ | |||
| 1 | 2010-12-02 Andrew Cohen <cohen@andy.bu.edu> | ||
| 2 | |||
| 3 | * nnir.el (nnir-summary-line-format): New variable. | ||
| 4 | (nnir-mode): Use it. | ||
| 5 | (nnir-artlist-*,nnir-aritem-*): Reimplement as macros. | ||
| 6 | (nnir-article-ids): Reimplement as defsubst. | ||
| 7 | (nnir-retrieve-headers): Don't mangle the subject header. | ||
| 8 | (nnir-run-imap): Use 100 as RSV score. | ||
| 9 | (nnir-run-find-grep): Fix for full server searching. | ||
| 10 | (nnir-run-gmane): Better restriction to gmane groups. | ||
| 11 | |||
| 12 | * gnus-sum.el (gnus-summary-line-format-alist): Add specs for nnir | ||
| 13 | summary buffers. | ||
| 14 | |||
| 15 | 2010-12-02 Julien Danjou <julien@danjou.info> | ||
| 16 | |||
| 17 | * gnus-win.el (gnus-configure-frame): Remove old compatibility code. | ||
| 18 | |||
| 19 | * gnus-msg.el: Mark gnus-outgoing-message-group as obsolete. | ||
| 20 | |||
| 21 | * gnus-win.el (gnus-configure-windows): Remove Gnus 3.x setting | ||
| 22 | support. | ||
| 23 | |||
| 24 | 2010-12-01 Andrew Cohen <cohen@andy.bu.edu> | ||
| 25 | |||
| 26 | * nnir.el: Update to handle the registry better. | ||
| 27 | (autoload): Silence byte-compiler. | ||
| 28 | (nnir-open-server): Add a hook for nnir groups. | ||
| 29 | (nnir-request-move-article): Don't mangle the header. Better to use | ||
| 30 | formating variables (which will be added in the future). | ||
| 31 | (nnir-registry-action): Update the registry using the original article | ||
| 32 | group name. | ||
| 33 | (nnir-mode): Install nnir-specific hooks for updating the registry. | ||
| 34 | |||
| 35 | * gnus-sum.el | ||
| 36 | (gnus-article-original-subject,gnus-newsgroup-original-name): Remove | ||
| 37 | obsolete variables. | ||
| 38 | (gnus-summary-move-article): Remove use of obsolete variables. | ||
| 39 | (gnus-summary-local-variables): Make move and delete hooks local to | ||
| 40 | summary buffers. | ||
| 41 | |||
| 42 | 2010-12-01 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 43 | |||
| 44 | * rtree.el: New file. | ||
| 45 | |||
| 46 | 2010-12-01 Julien Danjou <julien@danjou.info> | ||
| 47 | |||
| 48 | * message.el (message-user-organization): Do not use | ||
| 49 | gnus-local-organization. | ||
| 50 | |||
| 51 | * gnus.el: Remove gnus-local-organization. | ||
| 52 | |||
| 53 | * gnus-msg.el: Remove nastygram thing. | ||
| 54 | |||
| 55 | 2010-12-01 Teodor Zlatanov <tzz@lifelogs.com> | ||
| 56 | |||
| 57 | * nnmaildir.el (nnmaildir-request-set-mark): Add article to add-mark | ||
| 58 | funcall. | ||
| 59 | |||
| 60 | 2010-12-01 Katsumi Yamaoka <yamaoka@jpl.org> | ||
| 61 | |||
| 62 | * gnus-gravatar.el (gnus-gravatar-insert): Allow LWSP in the middle of | ||
| 63 | names. | ||
| 64 | |||
| 65 | * shr.el (shr-find-fill-point): Don't break line between kinsoku-bol | ||
| 66 | characters. | ||
| 67 | |||
| 68 | * gnus-gravatar.el (gnus-gravatar-insert): Delete unnecessary binding | ||
| 69 | to t of inhibit-read-only since it is inside gnus-with-article-headers. | ||
| 70 | Suggested by Štěpán Němec <stepnem@gmail.com>. | ||
| 71 | (gnus-gravatar-transform-address): Use mail-extract-address-components | ||
| 72 | that supports non-ASCII names rather than mail-header-parse-addresses. | ||
| 73 | |||
| 74 | 2010-11-30 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 75 | |||
| 76 | * proto-stream.el (open-protocol-stream): All starttls connections are | ||
| 77 | handled by the network handler. | ||
| 78 | |||
| 79 | 2010-11-30 Julien Danjou <julien@danjou.info> | ||
| 80 | |||
| 81 | * nnimap.el (nnimap-open-connection-1): Use gnus-string-match-p. | ||
| 82 | (nnimap-open-connection-1): Fix PREAUTH. | ||
| 83 | |||
| 84 | * gnus-gravatar.el (gnus-gravatar-size): Set gnus-gravatar-size to nil. | ||
| 85 | |||
| 86 | 2010-11-30 Katsumi Yamaoka <yamaoka@jpl.org> | ||
| 87 | |||
| 88 | * shr.el (shr-char-breakable-p, shr-char-nospace-p) | ||
| 89 | (shr-char-kinsoku-bol-p, shr-char-kinsoku-eol-p): New macros. | ||
| 90 | (shr-insert): Use them. | ||
| 91 | (shr-find-fill-point): Work better for kinsoku chars and apostrophes. | ||
| 92 | |||
| 93 | 2010-11-29 Andrew Cohen <cohen@andy.bu.edu> | ||
| 94 | |||
| 95 | * nnir.el (nnir-request-move-article): Bail out if original group | ||
| 96 | doesn't support article moves. | ||
| 97 | (nnir-get-active): Improve active list retrieval. | ||
| 98 | |||
| 99 | 2010-11-29 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 100 | |||
| 101 | * shr.el (shr-find-fill-point): Don't break before apostrophes. | ||
| 102 | |||
| 103 | 2010-11-29 Binjo <binjo.cn@gmail.com> (tiny change) | ||
| 104 | |||
| 105 | * nnimap.el (nnimap-open-connection-1): w32 open-network-stream doesn't | ||
| 106 | seem to accept strings-with-numbers as port numbers, | ||
| 107 | |||
| 108 | 2010-11-29 Andrew Cohen <cohen@andy.bu.edu> | ||
| 109 | |||
| 110 | * gnus-sum.el (gnus-summary-delete-article): If delete fails don't | ||
| 111 | change the registry. | ||
| 112 | |||
| 113 | 2010-11-29 Katsumi Yamaoka <yamaoka@jpl.org> | ||
| 114 | |||
| 115 | * nnir.el (nnir-run-gmane): Use mm-delete-duplicates instead of | ||
| 116 | delete-dups that is not available in XEmacs 21.4. | ||
| 117 | |||
| 118 | * mm-util.el (mm-delete-duplicates): Add comment. | ||
| 119 | |||
| 120 | 2010-11-28 Andrew Cohen <cohen@andy.bu.edu> | ||
| 121 | |||
| 122 | * nnir.el (nnir-ignored-newsgroups): New variable. | ||
| 123 | (nnir-get-active): Use it. | ||
| 124 | |||
| 125 | 2010-11-28 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 126 | |||
| 127 | * proto-stream.el (proto-stream-open-network): Add some comments. | ||
| 128 | |||
| 129 | * nntp.el (nntp-open-connection): Provide a :success condition. | ||
| 130 | |||
| 131 | * nnimap.el (nnimap-open-connection-1): Ditto. | ||
| 132 | |||
| 133 | * proto-stream.el (proto-stream-open-network): See what the response to | ||
| 134 | the STARTTLS command is. | ||
| 135 | |||
| 136 | * nnimap.el (nnimap-open-connection-1): Always upgrade to STARTTLS (for | ||
| 137 | backwards compatibility). | ||
| 138 | (nnimap-open-connection-1): Really respect nnimap-server-port. | ||
| 139 | |||
| 140 | * proto-stream.el (proto-stream-open-network): When doing opportunistic | ||
| 141 | TLS upgrades we don't really care about the identity of the peer. | ||
| 142 | (proto-stream-open-network): Force starttls.el to use gnutls-cli, since | ||
| 143 | that what we've checked for. | ||
| 144 | (proto-stream-always-use-starttls): Only default to t if | ||
| 145 | open-gnutls-stream exists. | ||
| 146 | (proto-stream-open-network): If STARTTLS failed, then just open a | ||
| 147 | normal connection. | ||
| 148 | (proto-stream-open-network): Wait until the greeting before doing | ||
| 149 | STARTTLS. | ||
| 150 | |||
| 151 | * nntp.el (nntp-open-connection): Report what the connection error is. | ||
| 152 | |||
| 153 | * proto-stream.el (open-protocol-stream): Renamed from | ||
| 154 | open-proto-stream. | ||
| 155 | |||
| 156 | 2010-11-27 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 157 | |||
| 158 | * nnimap.el (nnimap-stream): Change default to `undecided'. | ||
| 159 | (nnimap-open-connection): If `nnimap-stream' is `undecided', try ssl | ||
| 160 | first, and then network. | ||
| 161 | (nnimap-open-connection-1): Respect nnimap-server-port. | ||
| 162 | (nnimap-open-connection): Be more backwards-compatible. | ||
| 163 | |||
| 164 | * proto-stream.el (proto-stream-always-use-starttls): New variable. | ||
| 165 | (proto-stream-open-starttls): De-duplicate the starttls code. | ||
| 166 | (proto-stream-open-starttls): Folded back into the main function. | ||
| 167 | (proto-stream-open-network): Fix typo in the gnutls path. | ||
| 168 | (proto-stream-command): Refactor out. | ||
| 169 | |||
| 170 | * nntp.el (nntp-open-connection): Fix the STARTTLS command syntax. | ||
| 171 | |||
| 172 | * proto-stream.el (proto-stream-open-starttls): Actually implement the | ||
| 173 | starttls.el STARTTLS. | ||
| 174 | |||
| 175 | * color.el (color-lab->srgb): Fix function call name. | ||
| 176 | |||
| 177 | * proto-stream.el (proto-stream-open-tls): Delete output from openssl | ||
| 178 | if we're using tls.el. | ||
| 179 | (proto-stream-open-network): If we don't have gnutls-cli or gnutls | ||
| 180 | built in, then don't try to establish a STARTTLS connection. | ||
| 181 | |||
| 182 | * nntp.el (nntp-open-connection): Switch on STARTTLS on supported | ||
| 183 | servers. | ||
| 184 | |||
| 185 | * proto-stream.el (open-proto-stream): Use network, not stream. | ||
| 186 | (open-proto-stream): Add a way to specify what the end of a command is. | ||
| 187 | |||
| 188 | * nntp.el (nntp-open-connection): Use proto-streams for the relevant | ||
| 189 | connections types. | ||
| 190 | (nntp-open-network-stream): Remove. | ||
| 191 | (nntp-open-ssl-stream): Remove. | ||
| 192 | (nntp-open-tls-stream): Remove. | ||
| 193 | (nntp-ssl-program): Remove. | ||
| 194 | |||
| 195 | * nnimap.el (nnimap-open-connection): Check for "OK" from the greeting. | ||
| 196 | |||
| 197 | 2010-11-27 Andrew Cohen <cohen@andy.bu.edu> | ||
| 198 | |||
| 199 | * nnir.el: Fix typos. | ||
| 200 | (nnir-retrieve-headers-override-function): Rename variable to reflect | ||
| 201 | new semantics. | ||
| 202 | (nnir-article-group, nnir-article-number, nnir-article-rsv): New helper | ||
| 203 | macros. | ||
| 204 | (nnir-request-article, nnir-request-move-article): Use them. | ||
| 205 | (nnir-categorize): New function. | ||
| 206 | (nnir-run-query): Use it. | ||
| 207 | (nnir-retrieve-headers): Rewrite to batch header retrieval. | ||
| 208 | (nnir-run-gmane): nnir-retrieve-headers now returns the headers already | ||
| 209 | sorted. | ||
| 210 | (nnir-group-full-name): Use gnus-group-full-name instead. | ||
| 211 | (nnir-artlist-artitem-group, nnir-artlist-artitem-number) | ||
| 212 | (nnir-artlist-artitem-rsv, nnir-sort-groups-by-server): Obsolete. | ||
| 213 | |||
| 214 | 2010-11-27 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 215 | |||
| 216 | * nnimap.el (nnimap-open-connection): Fix typo in STARTTLS command. | ||
| 217 | |||
| 218 | * proto-stream.el: New library to provide protocol-specific | ||
| 219 | TLS/STARTTLS connections for IMAP, NNTP, SMTP, POP3 and similar | ||
| 220 | protocols. | ||
| 221 | (open-proto-stream): Complete the documentation. | ||
| 222 | (proto-stream-open-network): Fix some typos. | ||
| 223 | |||
| 224 | * nnimap.el (nnimap-open-connection): Use it. | ||
| 225 | |||
| 1 | 2010-11-27 Yuri Karaban <tech@askold.net> (tiny change) | 226 | 2010-11-27 Yuri Karaban <tech@askold.net> (tiny change) |
| 2 | 227 | ||
| 3 | * pop3.el (pop3-open-server): Read server greeting before starting TLS | 228 | * pop3.el (pop3-open-server): Read server greeting before starting TLS |
diff --git a/lisp/gnus/color.el b/lisp/gnus/color.el index 4d3718bc8df..07044333c4b 100644 --- a/lisp/gnus/color.el +++ b/lisp/gnus/color.el | |||
| @@ -36,7 +36,7 @@ | |||
| 36 | 36 | ||
| 37 | (defun color-rgb->hex (red green blue) | 37 | (defun color-rgb->hex (red green blue) |
| 38 | "Return hexadecimal notation for RED GREEN BLUE color. | 38 | "Return hexadecimal notation for RED GREEN BLUE color. |
| 39 | RED GREEN BLUE must be values between [0,1]." | 39 | RED GREEN BLUE must be values between 0 and 1 inclusively." |
| 40 | (format "#%02x%02x%02x" | 40 | (format "#%02x%02x%02x" |
| 41 | (* red 255) (* green 255) (* blue 255))) | 41 | (* red 255) (* green 255) (* blue 255))) |
| 42 | 42 | ||
| @@ -53,7 +53,8 @@ RED GREEN BLUE must be values between [0,1]." | |||
| 53 | 53 | ||
| 54 | (defun color-rgb->hsv (red green blue) | 54 | (defun color-rgb->hsv (red green blue) |
| 55 | "Convert RED GREEN BLUE values to HSV representation. | 55 | "Convert RED GREEN BLUE values to HSV representation. |
| 56 | Hue is in radian. Saturation and values are between [0,1]." | 56 | Hue is in radians. Saturation and values are between 0 and 1 |
| 57 | inclusively." | ||
| 57 | (let* ((r (float red)) | 58 | (let* ((r (float red)) |
| 58 | (g (float green)) | 59 | (g (float green)) |
| 59 | (b (float blue)) | 60 | (b (float blue)) |
| @@ -80,7 +81,7 @@ Hue is in radian. Saturation and values are between [0,1]." | |||
| 80 | 81 | ||
| 81 | (defun color-rgb->hsl (red green blue) | 82 | (defun color-rgb->hsl (red green blue) |
| 82 | "Convert RED GREEN BLUE colors to their HSL representation. | 83 | "Convert RED GREEN BLUE colors to their HSL representation. |
| 83 | RED, GREEN and BLUE must be between [0,1]." | 84 | RED, GREEN and BLUE must be between 0 and 1 inclusively." |
| 84 | (let* ((r red) | 85 | (let* ((r red) |
| 85 | (g green) | 86 | (g green) |
| 86 | (b blue) | 87 | (b blue) |
| @@ -108,7 +109,7 @@ RED, GREEN and BLUE must be between [0,1]." | |||
| 108 | 109 | ||
| 109 | (defun color-srgb->xyz (red green blue) | 110 | (defun color-srgb->xyz (red green blue) |
| 110 | "Converts RED GREEN BLUE colors from the sRGB color space to CIE XYZ. | 111 | "Converts RED GREEN BLUE colors from the sRGB color space to CIE XYZ. |
| 111 | RED, BLUE and GREEN must be between [0,1]." | 112 | RED, BLUE and GREEN must be between 0 and 1 inclusively." |
| 112 | (let ((r (if (<= red 0.04045) | 113 | (let ((r (if (<= red 0.04045) |
| 113 | (/ red 12.95) | 114 | (/ red 12.95) |
| 114 | (expt (/ (+ red 0.055) 1.055) 2.4))) | 115 | (expt (/ (+ red 0.055) 1.055) 2.4))) |
| @@ -191,12 +192,12 @@ none is set, `color-d65-xyz' is used." | |||
| 191 | (apply 'color-xyz->lab (color-srgb->xyz red green blue))) | 192 | (apply 'color-xyz->lab (color-srgb->xyz red green blue))) |
| 192 | 193 | ||
| 193 | (defun color-rgb->normalize (color) | 194 | (defun color-rgb->normalize (color) |
| 194 | "Normalize a RGB color to values between [0,1]." | 195 | "Normalize a RGB color to values between 0 and 1 inclusively." |
| 195 | (mapcar (lambda (x) (/ x 65535.0)) (x-color-values color))) | 196 | (mapcar (lambda (x) (/ x 65535.0)) (x-color-values color))) |
| 196 | 197 | ||
| 197 | (defun color-lab->srgb (L a b) | 198 | (defun color-lab->srgb (L a b) |
| 198 | "Converts CIE L*a*b* to RGB." | 199 | "Converts CIE L*a*b* to RGB." |
| 199 | (apply 'color-xyz->rgb (color-lab->xyz L a b))) | 200 | (apply 'color-xyz->srgb (color-lab->xyz L a b))) |
| 200 | 201 | ||
| 201 | (defun color-cie-de2000 (color1 color2 &optional kL kC kH) | 202 | (defun color-cie-de2000 (color1 color2 &optional kL kC kH) |
| 202 | "Computes the CIEDE2000 color distance between COLOR1 and COLOR2. | 203 | "Computes the CIEDE2000 color distance between COLOR1 and COLOR2. |
diff --git a/lisp/gnus/gnus-gravatar.el b/lisp/gnus/gnus-gravatar.el index fd62f175a2a..27f65c04094 100644 --- a/lisp/gnus/gnus-gravatar.el +++ b/lisp/gnus/gnus-gravatar.el | |||
| @@ -26,13 +26,15 @@ | |||
| 26 | 26 | ||
| 27 | (require 'gravatar) | 27 | (require 'gravatar) |
| 28 | (require 'gnus-art) | 28 | (require 'gnus-art) |
| 29 | (require 'mail-extr) ;; Because of binding `mail-extr-disable-voodoo'. | ||
| 29 | 30 | ||
| 30 | (defgroup gnus-gravatar nil | 31 | (defgroup gnus-gravatar nil |
| 31 | "Gnus Gravatar." | 32 | "Gnus Gravatar." |
| 32 | :group 'gnus-visual) | 33 | :group 'gnus-visual) |
| 33 | 34 | ||
| 34 | (defcustom gnus-gravatar-size 32 | 35 | (defcustom gnus-gravatar-size nil |
| 35 | "How big should gravatars be displayed." | 36 | "How big should gravatars be displayed. |
| 37 | If nil, default to `gravatar-size'." | ||
| 36 | :type 'integer | 38 | :type 'integer |
| 37 | :version "24.1" | 39 | :version "24.1" |
| 38 | :group 'gnus-gravatar) | 40 | :group 'gnus-gravatar) |
| @@ -51,30 +53,25 @@ | |||
| 51 | 53 | ||
| 52 | (defun gnus-gravatar-transform-address (header category &optional force) | 54 | (defun gnus-gravatar-transform-address (header category &optional force) |
| 53 | (gnus-with-article-headers | 55 | (gnus-with-article-headers |
| 54 | (let ((addresses | 56 | (let* ((mail-extr-disable-voodoo t) |
| 55 | (mail-header-parse-addresses | 57 | (addresses (mail-extract-address-components |
| 56 | ;; mail-header-parse-addresses does not work (reliably) on | 58 | (or (mail-fetch-field header) "") t)) |
| 57 | ;; decoded headers. | 59 | (gravatar-size gnus-gravatar-size) |
| 58 | (or | 60 | name) |
| 59 | (ignore-errors | ||
| 60 | (mail-encode-encoded-word-string | ||
| 61 | (or (mail-fetch-field header) ""))) | ||
| 62 | (mail-fetch-field header)))) | ||
| 63 | (gravatar-size gnus-gravatar-size) | ||
| 64 | name) | ||
| 65 | (dolist (address addresses) | 61 | (dolist (address addresses) |
| 66 | (when (setq name (cdr address)) | 62 | (when (and (setq name (car address)) |
| 67 | (setcdr address (setq name (mail-decode-encoded-word-string name)))) | 63 | (string-match "\\` +" name)) |
| 64 | (setcar address (setq name (substring name (match-end 0))))) | ||
| 68 | (when (or force | 65 | (when (or force |
| 69 | (not (and gnus-gravatar-too-ugly | 66 | (not (and gnus-gravatar-too-ugly |
| 70 | (or (string-match gnus-gravatar-too-ugly | 67 | (or (string-match gnus-gravatar-too-ugly |
| 71 | (car address)) | 68 | (cadr address)) |
| 72 | (and name | 69 | (and name |
| 73 | (string-match gnus-gravatar-too-ugly | 70 | (string-match gnus-gravatar-too-ugly |
| 74 | name)))))) | 71 | name)))))) |
| 75 | (ignore-errors | 72 | (ignore-errors |
| 76 | (gravatar-retrieve | 73 | (gravatar-retrieve |
| 77 | (car address) | 74 | (cadr address) |
| 78 | 'gnus-gravatar-insert | 75 | 'gnus-gravatar-insert |
| 79 | (list header address category)))))))) | 76 | (list header address category)))))))) |
| 80 | 77 | ||
| @@ -87,12 +84,15 @@ Set image category to CATEGORY." | |||
| 87 | (when (buffer-live-p (current-buffer)) | 84 | (when (buffer-live-p (current-buffer)) |
| 88 | (gnus-article-goto-header header) | 85 | (gnus-article-goto-header header) |
| 89 | (mail-header-narrow-to-field) | 86 | (mail-header-narrow-to-field) |
| 90 | (let ((real-name (cdr address)) | 87 | (let ((real-name (car address)) |
| 91 | (mail-address (car address))) | 88 | (mail-address (cadr address))) |
| 92 | (when (if real-name | 89 | (when (if real-name |
| 93 | (re-search-forward (concat (regexp-quote real-name) "\\|" | 90 | (re-search-forward |
| 94 | (regexp-quote mail-address)) | 91 | (concat (gnus-replace-in-string |
| 95 | nil t) | 92 | (regexp-quote real-name) "[\t ]+" "[\t\n ]+") |
| 93 | "\\|" | ||
| 94 | (regexp-quote mail-address)) | ||
| 95 | nil t) | ||
| 96 | (search-forward mail-address nil t)) | 96 | (search-forward mail-address nil t)) |
| 97 | (goto-char (1- (match-beginning 0))) | 97 | (goto-char (1- (match-beginning 0))) |
| 98 | ;; If we're on the " quoting the name, go backward | 98 | ;; If we're on the " quoting the name, go backward |
| @@ -103,8 +103,7 @@ Set image category to CATEGORY." | |||
| 103 | ;; example we were fetching someaddress, and then we change to | 103 | ;; example we were fetching someaddress, and then we change to |
| 104 | ;; another mail with the same someaddress. | 104 | ;; another mail with the same someaddress. |
| 105 | (unless (memq 'gnus-gravatar (text-properties-at (point))) | 105 | (unless (memq 'gnus-gravatar (text-properties-at (point))) |
| 106 | (let ((inhibit-read-only t) | 106 | (let ((point (point))) |
| 107 | (point (point))) | ||
| 108 | (unless (featurep 'xemacs) | 107 | (unless (featurep 'xemacs) |
| 109 | (setq gravatar (append gravatar gnus-gravatar-properties))) | 108 | (setq gravatar (append gravatar gnus-gravatar-properties))) |
| 110 | (gnus-put-image gravatar nil category) | 109 | (gnus-put-image gravatar nil category) |
diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el index 544aa7776a8..d77abfa1c61 100644 --- a/lisp/gnus/gnus-msg.el +++ b/lisp/gnus/gnus-msg.el | |||
| @@ -55,7 +55,7 @@ method to use when posting." | |||
| 55 | (sexp :tag "Methods" ,gnus-select-method))) | 55 | (sexp :tag "Methods" ,gnus-select-method))) |
| 56 | 56 | ||
| 57 | (defcustom gnus-outgoing-message-group nil | 57 | (defcustom gnus-outgoing-message-group nil |
| 58 | "*All outgoing messages will be put in this group. | 58 | "All outgoing messages will be put in this group. |
| 59 | If you want to store all your outgoing mail and articles in the group | 59 | If you want to store all your outgoing mail and articles in the group |
| 60 | \"nnml:archive\", you set this variable to that value. This variable | 60 | \"nnml:archive\", you set this variable to that value. This variable |
| 61 | can also be a list of group names. | 61 | can also be a list of group names. |
| @@ -70,6 +70,8 @@ of names)." | |||
| 70 | (string :tag "Group") | 70 | (string :tag "Group") |
| 71 | (repeat :tag "List of groups" (string :tag "Group")))) | 71 | (repeat :tag "List of groups" (string :tag "Group")))) |
| 72 | 72 | ||
| 73 | (make-obsolete-variable 'gnus-outgoing-message-group 'gnus-message-archive-group "24.1") | ||
| 74 | |||
| 73 | (defcustom gnus-mailing-list-groups nil | 75 | (defcustom gnus-mailing-list-groups nil |
| 74 | "*If non-nil a regexp matching groups that are really mailing lists. | 76 | "*If non-nil a regexp matching groups that are really mailing lists. |
| 75 | This is useful when you're reading a mailing list that has been | 77 | This is useful when you're reading a mailing list that has been |
| @@ -397,7 +399,6 @@ Thank you for your help in stamping out bugs. | |||
| 397 | (message-mode-hook (copy-sequence message-mode-hook))) | 399 | (message-mode-hook (copy-sequence message-mode-hook))) |
| 398 | (setq mml-buffer-list nil) | 400 | (setq mml-buffer-list nil) |
| 399 | (add-hook 'message-header-setup-hook 'gnus-inews-insert-gcc) | 401 | (add-hook 'message-header-setup-hook 'gnus-inews-insert-gcc) |
| 400 | (add-hook 'message-header-setup-hook 'gnus-inews-insert-archive-gcc) | ||
| 401 | ;; message-newsreader and message-mailer were formerly set in | 402 | ;; message-newsreader and message-mailer were formerly set in |
| 402 | ;; gnus-inews-add-send-actions, but this is too late when | 403 | ;; gnus-inews-add-send-actions, but this is too late when |
| 403 | ;; message-generate-headers-first is used. --ansel | 404 | ;; message-generate-headers-first is used. --ansel |
| @@ -826,7 +827,6 @@ header line with the old Message-ID." | |||
| 826 | (gnus-summary-mark-as-read ,article gnus-canceled-mark))))) | 827 | (gnus-summary-mark-as-read ,article gnus-canceled-mark))))) |
| 827 | message-send-actions) | 828 | message-send-actions) |
| 828 | ;; Add Gcc header. | 829 | ;; Add Gcc header. |
| 829 | (gnus-inews-insert-archive-gcc) | ||
| 830 | (gnus-inews-insert-gcc)))) | 830 | (gnus-inews-insert-gcc)))) |
| 831 | 831 | ||
| 832 | 832 | ||
| @@ -1294,7 +1294,6 @@ composing a new message." | |||
| 1294 | (goto-char (point-max)) | 1294 | (goto-char (point-max)) |
| 1295 | (insert mail-header-separator) | 1295 | (insert mail-header-separator) |
| 1296 | ;; Add Gcc header. | 1296 | ;; Add Gcc header. |
| 1297 | (gnus-inews-insert-archive-gcc) | ||
| 1298 | (gnus-inews-insert-gcc) | 1297 | (gnus-inews-insert-gcc) |
| 1299 | (goto-char (point-min)) | 1298 | (goto-char (point-min)) |
| 1300 | (when (re-search-forward "^To:\\|^Newsgroups:" nil 'move) | 1299 | (when (re-search-forward "^To:\\|^Newsgroups:" nil 'move) |
| @@ -1307,24 +1306,6 @@ See `gnus-summary-mail-forward' for ARG." | |||
| 1307 | (interactive "P") | 1306 | (interactive "P") |
| 1308 | (gnus-summary-mail-forward arg t)) | 1307 | (gnus-summary-mail-forward arg t)) |
| 1309 | 1308 | ||
| 1310 | (defvar gnus-nastygram-message | ||
| 1311 | "The following article was inappropriately posted to %s.\n\n" | ||
| 1312 | "Format string to insert in nastygrams. | ||
| 1313 | The current group name will be inserted at \"%s\".") | ||
| 1314 | |||
| 1315 | (defun gnus-summary-mail-nastygram (n) | ||
| 1316 | "Send a nastygram to the author of the current article." | ||
| 1317 | (interactive "P") | ||
| 1318 | (when (or gnus-expert-user | ||
| 1319 | (gnus-y-or-n-p | ||
| 1320 | "Really send a nastygram to the author of the current article? ")) | ||
| 1321 | (let ((group gnus-newsgroup-name)) | ||
| 1322 | (gnus-summary-reply-with-original n) | ||
| 1323 | (set-buffer gnus-message-buffer) | ||
| 1324 | (message-goto-body) | ||
| 1325 | (insert (format gnus-nastygram-message group)) | ||
| 1326 | (message-send-and-exit)))) | ||
| 1327 | |||
| 1328 | (defun gnus-summary-mail-crosspost-complaint (n) | 1309 | (defun gnus-summary-mail-crosspost-complaint (n) |
| 1329 | "Send a complaint about crossposting to the current article(s)." | 1310 | "Send a complaint about crossposting to the current article(s)." |
| 1330 | (interactive "P") | 1311 | (interactive "P") |
| @@ -1580,7 +1561,6 @@ this is a reply." | |||
| 1580 | (gnus-setup-message 'compose-bounce | 1561 | (gnus-setup-message 'compose-bounce |
| 1581 | (message-bounce) | 1562 | (message-bounce) |
| 1582 | ;; Add Gcc header. | 1563 | ;; Add Gcc header. |
| 1583 | (gnus-inews-insert-archive-gcc) | ||
| 1584 | (gnus-inews-insert-gcc) | 1564 | (gnus-inews-insert-gcc) |
| 1585 | ;; If there are references, we fetch the article we answered to. | 1565 | ;; If there are references, we fetch the article we answered to. |
| 1586 | (when parent | 1566 | (when parent |
| @@ -1694,44 +1674,13 @@ this is a reply." | |||
| 1694 | (gnus-group-mark-article-read group (cdr group-art))) | 1674 | (gnus-group-mark-article-read group (cdr group-art))) |
| 1695 | (kill-buffer (current-buffer))))))))) | 1675 | (kill-buffer (current-buffer))))))))) |
| 1696 | 1676 | ||
| 1697 | (defun gnus-inews-insert-gcc () | 1677 | (defun gnus-inews-insert-gcc (&optional group) |
| 1698 | "Insert Gcc headers based on `gnus-outgoing-message-group'." | ||
| 1699 | (save-excursion | ||
| 1700 | (save-restriction | ||
| 1701 | (message-narrow-to-headers) | ||
| 1702 | (let* ((group gnus-outgoing-message-group) | ||
| 1703 | (gcc (cond | ||
| 1704 | ((functionp group) | ||
| 1705 | (funcall group)) | ||
| 1706 | ((or (stringp group) (listp group)) | ||
| 1707 | group)))) | ||
| 1708 | (when gcc | ||
| 1709 | (insert "Gcc: " | ||
| 1710 | (if (stringp gcc) | ||
| 1711 | (if (string-match " " gcc) | ||
| 1712 | (concat "\"" gcc "\"") | ||
| 1713 | gcc) | ||
| 1714 | (mapconcat (lambda (group) | ||
| 1715 | (if (string-match " " group) | ||
| 1716 | (concat "\"" group "\"") | ||
| 1717 | group)) | ||
| 1718 | gcc " ")) | ||
| 1719 | "\n")))))) | ||
| 1720 | |||
| 1721 | (defun gnus-inews-insert-archive-gcc (&optional group) | ||
| 1722 | "Insert the Gcc to say where the article is to be archived." | 1678 | "Insert the Gcc to say where the article is to be archived." |
| 1723 | (setq group (cond (group | 1679 | (let* ((group (or group gnus-newsgroup-name)) |
| 1724 | (gnus-group-decoded-name group)) | 1680 | (group (when group (gnus-group-decoded-name group))) |
| 1725 | (gnus-newsgroup-name | 1681 | (var (or gnus-outgoing-message-group gnus-message-archive-group)) |
| 1726 | (gnus-group-decoded-name gnus-newsgroup-name)) | ||
| 1727 | (t | ||
| 1728 | ""))) | ||
| 1729 | (let* ((var gnus-message-archive-group) | ||
| 1730 | (gcc-self-val | 1682 | (gcc-self-val |
| 1731 | (and gnus-newsgroup-name | 1683 | (and group (gnus-group-find-parameter group 'gcc-self))) |
| 1732 | (not (equal gnus-newsgroup-name "")) | ||
| 1733 | (gnus-group-find-parameter | ||
| 1734 | gnus-newsgroup-name 'gcc-self))) | ||
| 1735 | result | 1684 | result |
| 1736 | (groups | 1685 | (groups |
| 1737 | (cond | 1686 | (cond |
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index 2d679dab246..840e7d5a000 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el | |||
| @@ -1310,7 +1310,6 @@ the normal Gnus MIME machinery." | |||
| 1310 | (defvar gnus-article-decoded-p nil) | 1310 | (defvar gnus-article-decoded-p nil) |
| 1311 | (defvar gnus-article-charset nil) | 1311 | (defvar gnus-article-charset nil) |
| 1312 | (defvar gnus-article-ignored-charsets nil) | 1312 | (defvar gnus-article-ignored-charsets nil) |
| 1313 | (defvar gnus-article-original-subject nil) | ||
| 1314 | (defvar gnus-scores-exclude-files nil) | 1313 | (defvar gnus-scores-exclude-files nil) |
| 1315 | (defvar gnus-page-broken nil) | 1314 | (defvar gnus-page-broken nil) |
| 1316 | 1315 | ||
| @@ -1336,7 +1335,6 @@ the normal Gnus MIME machinery." | |||
| 1336 | (defvar gnus-current-copy-group nil) | 1335 | (defvar gnus-current-copy-group nil) |
| 1337 | (defvar gnus-current-crosspost-group nil) | 1336 | (defvar gnus-current-crosspost-group nil) |
| 1338 | (defvar gnus-newsgroup-display nil) | 1337 | (defvar gnus-newsgroup-display nil) |
| 1339 | (defvar gnus-newsgroup-original-name nil) | ||
| 1340 | 1338 | ||
| 1341 | (defvar gnus-newsgroup-dependencies nil) | 1339 | (defvar gnus-newsgroup-dependencies nil) |
| 1342 | (defvar gnus-newsgroup-adaptive nil) | 1340 | (defvar gnus-newsgroup-adaptive nil) |
| @@ -1363,6 +1361,16 @@ the normal Gnus MIME machinery." | |||
| 1363 | (?c (or (mail-header-chars gnus-tmp-header) 0) ?d) | 1361 | (?c (or (mail-header-chars gnus-tmp-header) 0) ?d) |
| 1364 | (?k (gnus-summary-line-message-size gnus-tmp-header) ?s) | 1362 | (?k (gnus-summary-line-message-size gnus-tmp-header) ?s) |
| 1365 | (?L gnus-tmp-lines ?s) | 1363 | (?L gnus-tmp-lines ?s) |
| 1364 | (?Z (or ,(macroexpand-all | ||
| 1365 | '(nnir-article-rsv (mail-header-number gnus-tmp-header))) | ||
| 1366 | 0) ?d) | ||
| 1367 | (?G (or ,(macroexpand-all | ||
| 1368 | '(nnir-article-group (mail-header-number gnus-tmp-header))) | ||
| 1369 | "") ?s) | ||
| 1370 | (?g (or ,(macroexpand-all | ||
| 1371 | '(gnus-group-short-name | ||
| 1372 | (nnir-article-group (mail-header-number gnus-tmp-header)))) | ||
| 1373 | "") ?s) | ||
| 1366 | (?O gnus-tmp-downloaded ?c) | 1374 | (?O gnus-tmp-downloaded ?c) |
| 1367 | (?I gnus-tmp-indentation ?s) | 1375 | (?I gnus-tmp-indentation ?s) |
| 1368 | (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s) | 1376 | (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s) |
| @@ -1583,6 +1591,8 @@ This list will always be a subset of gnus-newsgroup-undownloaded.") | |||
| 1583 | gnus-newsgroup-prepared gnus-summary-highlight-line-function | 1591 | gnus-newsgroup-prepared gnus-summary-highlight-line-function |
| 1584 | gnus-current-article gnus-current-headers gnus-have-all-headers | 1592 | gnus-current-article gnus-current-headers gnus-have-all-headers |
| 1585 | gnus-last-article gnus-article-internal-prepare-hook | 1593 | gnus-last-article gnus-article-internal-prepare-hook |
| 1594 | (gnus-summary-article-delete-hook . global) | ||
| 1595 | (gnus-summary-article-move-hook . global) | ||
| 1586 | gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay | 1596 | gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay |
| 1587 | gnus-newsgroup-scored gnus-newsgroup-kill-headers | 1597 | gnus-newsgroup-scored gnus-newsgroup-kill-headers |
| 1588 | gnus-thread-expunge-below | 1598 | gnus-thread-expunge-below |
| @@ -9731,210 +9741,203 @@ ACTION can be either `move' (the default), `crosspost' or `copy'." | |||
| 9731 | ;; Set any marks that may have changed in the summary buffer. | 9741 | ;; Set any marks that may have changed in the summary buffer. |
| 9732 | (when gnus-preserve-marks | 9742 | (when gnus-preserve-marks |
| 9733 | (gnus-summary-push-marks-to-backend article)) | 9743 | (gnus-summary-push-marks-to-backend article)) |
| 9734 | (let ((gnus-newsgroup-original-name gnus-newsgroup-name) | 9744 | (setq |
| 9735 | (gnus-article-original-subject | 9745 | art-group |
| 9736 | (mail-header-subject | 9746 | (cond |
| 9737 | (gnus-data-header (assoc article (gnus-data-list nil)))))) | 9747 | ;; Move the article. |
| 9738 | (setq | 9748 | ((eq action 'move) |
| 9739 | art-group | 9749 | ;; Remove this article from future suppression. |
| 9740 | (cond | 9750 | (gnus-dup-unsuppress-article article) |
| 9741 | ;; Move the article. | 9751 | (let* ((from-method (gnus-find-method-for-group |
| 9742 | ((eq action 'move) | 9752 | gnus-newsgroup-name)) |
| 9743 | ;; Remove this article from future suppression. | 9753 | (to-method (or select-method |
| 9744 | (gnus-dup-unsuppress-article article) | 9754 | (gnus-find-method-for-group to-newsgroup))) |
| 9745 | (let* ((from-method (gnus-find-method-for-group | 9755 | (move-is-internal (gnus-server-equal from-method to-method))) |
| 9746 | gnus-newsgroup-name)) | 9756 | (gnus-request-move-article |
| 9747 | (to-method (or select-method | 9757 | article ; Article to move |
| 9748 | (gnus-find-method-for-group to-newsgroup))) | 9758 | gnus-newsgroup-name ; From newsgroup |
| 9749 | (move-is-internal (gnus-server-equal from-method to-method))) | 9759 | (nth 1 (gnus-find-method-for-group |
| 9750 | (gnus-request-move-article | 9760 | gnus-newsgroup-name)) ; Server |
| 9751 | article ; Article to move | 9761 | (list 'gnus-request-accept-article |
| 9752 | gnus-newsgroup-name ; From newsgroup | 9762 | to-newsgroup (list 'quote select-method) |
| 9753 | (nth 1 (gnus-find-method-for-group | 9763 | (not articles) t) ; Accept form |
| 9754 | gnus-newsgroup-name)) ; Server | 9764 | (not articles) ; Only save nov last time |
| 9755 | (list 'gnus-request-accept-article | 9765 | (and move-is-internal |
| 9756 | to-newsgroup (list 'quote select-method) | 9766 | to-newsgroup ; Not respooling |
| 9757 | (not articles) t) ; Accept form | ||
| 9758 | (not articles) ; Only save nov last time | ||
| 9759 | (and move-is-internal | ||
| 9760 | to-newsgroup ; Not respooling | ||
| 9761 | ; Is this move internal? | 9767 | ; Is this move internal? |
| 9762 | (gnus-group-real-name to-newsgroup))))) | 9768 | (gnus-group-real-name to-newsgroup))))) |
| 9763 | ;; Copy the article. | 9769 | ;; Copy the article. |
| 9764 | ((eq action 'copy) | 9770 | ((eq action 'copy) |
| 9771 | (with-current-buffer copy-buf | ||
| 9772 | (when (gnus-request-article-this-buffer article | ||
| 9773 | gnus-newsgroup-name) | ||
| 9774 | (save-restriction | ||
| 9775 | (nnheader-narrow-to-headers) | ||
| 9776 | (dolist (hdr gnus-copy-article-ignored-headers) | ||
| 9777 | (message-remove-header hdr t))) | ||
| 9778 | (gnus-request-accept-article | ||
| 9779 | to-newsgroup select-method (not articles) t)))) | ||
| 9780 | ;; Crosspost the article. | ||
| 9781 | ((eq action 'crosspost) | ||
| 9782 | (let ((xref (message-tokenize-header | ||
| 9783 | (mail-header-xref (gnus-summary-article-header | ||
| 9784 | article)) | ||
| 9785 | " "))) | ||
| 9786 | (setq new-xref (concat (gnus-group-real-name gnus-newsgroup-name) | ||
| 9787 | ":" (number-to-string article))) | ||
| 9788 | (unless xref | ||
| 9789 | (setq xref (list (system-name)))) | ||
| 9790 | (setq new-xref | ||
| 9791 | (concat | ||
| 9792 | (mapconcat 'identity | ||
| 9793 | (delete "Xref:" (delete new-xref xref)) | ||
| 9794 | " ") | ||
| 9795 | " " new-xref)) | ||
| 9765 | (with-current-buffer copy-buf | 9796 | (with-current-buffer copy-buf |
| 9766 | (when (gnus-request-article-this-buffer article | 9797 | ;; First put the article in the destination group. |
| 9767 | gnus-newsgroup-name) | 9798 | (gnus-request-article-this-buffer article gnus-newsgroup-name) |
| 9768 | (save-restriction | 9799 | (when (consp (setq art-group |
| 9769 | (nnheader-narrow-to-headers) | 9800 | (gnus-request-accept-article |
| 9770 | (dolist (hdr gnus-copy-article-ignored-headers) | 9801 | to-newsgroup select-method (not articles) |
| 9771 | (message-remove-header hdr t))) | 9802 | t))) |
| 9772 | (gnus-request-accept-article | 9803 | (setq new-xref (concat new-xref " " (car art-group) |
| 9773 | to-newsgroup select-method (not articles) t)))) | 9804 | ":" |
| 9774 | ;; Crosspost the article. | 9805 | (number-to-string (cdr art-group)))) |
| 9775 | ((eq action 'crosspost) | 9806 | ;; Now we have the new Xrefs header, so we insert |
| 9776 | (let ((xref (message-tokenize-header | 9807 | ;; it and replace the new article. |
| 9777 | (mail-header-xref (gnus-summary-article-header | 9808 | (nnheader-replace-header "Xref" new-xref) |
| 9778 | article)) | 9809 | (gnus-request-replace-article |
| 9779 | " "))) | 9810 | (cdr art-group) to-newsgroup (current-buffer) t) |
| 9780 | (setq new-xref (concat (gnus-group-real-name gnus-newsgroup-name) | 9811 | art-group)))))) |
| 9781 | ":" (number-to-string article))) | 9812 | (cond |
| 9782 | (unless xref | 9813 | ((not art-group) |
| 9783 | (setq xref (list (system-name)))) | 9814 | (gnus-message 1 "Couldn't %s article %s: %s" |
| 9784 | (setq new-xref | 9815 | (cadr (assq action names)) article |
| 9785 | (concat | 9816 | (nnheader-get-report (car to-method)))) |
| 9786 | (mapconcat 'identity | 9817 | ((eq art-group 'junk) |
| 9787 | (delete "Xref:" (delete new-xref xref)) | 9818 | (when (eq action 'move) |
| 9788 | " ") | 9819 | (gnus-summary-mark-article article gnus-canceled-mark) |
| 9789 | " " new-xref)) | 9820 | (gnus-message 4 "Deleted article %s" article) |
| 9790 | (with-current-buffer copy-buf | 9821 | ;; run the delete hook |
| 9791 | ;; First put the article in the destination group. | 9822 | (run-hook-with-args 'gnus-summary-article-delete-hook |
| 9792 | (gnus-request-article-this-buffer article gnus-newsgroup-name) | 9823 | action |
| 9793 | (when (consp (setq art-group | 9824 | (gnus-data-header |
| 9794 | (gnus-request-accept-article | 9825 | (assoc article (gnus-data-list nil))) |
| 9795 | to-newsgroup select-method (not articles) | 9826 | gnus-newsgroup-name nil |
| 9796 | t))) | 9827 | select-method))) |
| 9797 | (setq new-xref (concat new-xref " " (car art-group) | 9828 | (t |
| 9798 | ":" | 9829 | (let* ((pto-group (gnus-group-prefixed-name |
| 9799 | (number-to-string (cdr art-group)))) | 9830 | (car art-group) to-method)) |
| 9800 | ;; Now we have the new Xrefs header, so we insert | 9831 | (info (gnus-get-info pto-group)) |
| 9801 | ;; it and replace the new article. | 9832 | (to-group (gnus-info-group info)) |
| 9802 | (nnheader-replace-header "Xref" new-xref) | 9833 | to-marks) |
| 9803 | (gnus-request-replace-article | 9834 | ;; Update the group that has been moved to. |
| 9804 | (cdr art-group) to-newsgroup (current-buffer) t) | 9835 | (when (and info |
| 9805 | art-group)))))) | 9836 | (memq action '(move copy))) |
| 9806 | (cond | 9837 | (unless (member to-group to-groups) |
| 9807 | ((not art-group) | 9838 | (push to-group to-groups)) |
| 9808 | (gnus-message 1 "Couldn't %s article %s: %s" | 9839 | |
| 9809 | (cadr (assq action names)) article | 9840 | (unless (memq article gnus-newsgroup-unreads) |
| 9810 | (nnheader-get-report (car to-method)))) | 9841 | (push 'read to-marks) |
| 9811 | ((eq art-group 'junk) | 9842 | (gnus-info-set-read |
| 9812 | (when (eq action 'move) | 9843 | info (gnus-add-to-range (gnus-info-read info) |
| 9813 | (gnus-summary-mark-article article gnus-canceled-mark) | 9844 | (list (cdr art-group))))) |
| 9814 | (gnus-message 4 "Deleted article %s" article) | 9845 | |
| 9815 | ;; run the delete hook | 9846 | ;; See whether the article is to be put in the cache. |
| 9816 | (run-hook-with-args 'gnus-summary-article-delete-hook | 9847 | (let* ((expirable (gnus-group-auto-expirable-p to-group)) |
| 9817 | action | 9848 | (marks (if expirable |
| 9818 | (gnus-data-header | 9849 | gnus-article-mark-lists |
| 9819 | (assoc article (gnus-data-list nil))) | 9850 | (delete '(expirable . expire) |
| 9820 | gnus-newsgroup-original-name nil | 9851 | (copy-sequence |
| 9821 | select-method))) | 9852 | gnus-article-mark-lists)))) |
| 9822 | (t | 9853 | (to-article (cdr art-group))) |
| 9823 | (let* ((pto-group (gnus-group-prefixed-name | 9854 | |
| 9824 | (car art-group) to-method)) | 9855 | ;; Enter the article into the cache in the new group, |
| 9825 | (info (gnus-get-info pto-group)) | 9856 | ;; if that is required. |
| 9826 | (to-group (gnus-info-group info)) | 9857 | (when gnus-use-cache |
| 9827 | to-marks) | 9858 | (gnus-cache-possibly-enter-article |
| 9828 | ;; Update the group that has been moved to. | 9859 | to-group to-article |
| 9829 | (when (and info | 9860 | (memq article gnus-newsgroup-marked) |
| 9830 | (memq action '(move copy))) | 9861 | (memq article gnus-newsgroup-dormant) |
| 9831 | (unless (member to-group to-groups) | 9862 | (memq article gnus-newsgroup-unreads))) |
| 9832 | (push to-group to-groups)) | 9863 | |
| 9833 | 9864 | (when gnus-preserve-marks | |
| 9834 | (unless (memq article gnus-newsgroup-unreads) | 9865 | ;; Copy any marks over to the new group. |
| 9835 | (push 'read to-marks) | 9866 | (when (and (equal to-group gnus-newsgroup-name) |
| 9836 | (gnus-info-set-read | 9867 | (not (memq article gnus-newsgroup-unreads))) |
| 9837 | info (gnus-add-to-range (gnus-info-read info) | 9868 | ;; Mark this article as read in this group. |
| 9838 | (list (cdr art-group))))) | 9869 | (push (cons to-article gnus-read-mark) |
| 9839 | 9870 | gnus-newsgroup-reads) | |
| 9840 | ;; See whether the article is to be put in the cache. | 9871 | ;; Increase the active status of this group. |
| 9841 | (let* ((expirable (gnus-group-auto-expirable-p to-group)) | 9872 | (setcdr (gnus-active to-group) to-article) |
| 9842 | (marks (if expirable | 9873 | (setcdr gnus-newsgroup-active to-article)) |
| 9843 | gnus-article-mark-lists | 9874 | |
| 9844 | (delete '(expirable . expire) | 9875 | (while marks |
| 9845 | (copy-sequence | 9876 | (when (eq (gnus-article-mark-to-type (cdar marks)) 'list) |
| 9846 | gnus-article-mark-lists)))) | 9877 | (when (memq article (symbol-value |
| 9847 | (to-article (cdr art-group))) | 9878 | (intern (format "gnus-newsgroup-%s" |
| 9848 | 9879 | (caar marks))))) | |
| 9849 | ;; Enter the article into the cache in the new group, | 9880 | (push (cdar marks) to-marks) |
| 9850 | ;; if that is required. | 9881 | ;; If the other group is the same as this group, |
| 9851 | (when gnus-use-cache | 9882 | ;; then we have to add the mark to the list. |
| 9852 | (gnus-cache-possibly-enter-article | 9883 | (when (equal to-group gnus-newsgroup-name) |
| 9853 | to-group to-article | 9884 | (set (intern (format "gnus-newsgroup-%s" |
| 9854 | (memq article gnus-newsgroup-marked) | 9885 | (caar marks))) |
| 9855 | (memq article gnus-newsgroup-dormant) | 9886 | (cons to-article |
| 9856 | (memq article gnus-newsgroup-unreads))) | 9887 | (symbol-value |
| 9857 | 9888 | (intern (format "gnus-newsgroup-%s" | |
| 9858 | (when gnus-preserve-marks | 9889 | (caar marks))))))) |
| 9859 | ;; Copy any marks over to the new group. | 9890 | ;; Copy the marks to other group. |
| 9860 | (when (and (equal to-group gnus-newsgroup-name) | 9891 | (gnus-add-marked-articles |
| 9861 | (not (memq article gnus-newsgroup-unreads))) | 9892 | to-group (cdar marks) (list to-article) info))) |
| 9862 | ;; Mark this article as read in this group. | 9893 | (setq marks (cdr marks))) |
| 9863 | (push (cons to-article gnus-read-mark) | 9894 | |
| 9864 | gnus-newsgroup-reads) | 9895 | (when (and expirable |
| 9865 | ;; Increase the active status of this group. | 9896 | gnus-mark-copied-or-moved-articles-as-expirable |
| 9866 | (setcdr (gnus-active to-group) to-article) | 9897 | (not (memq 'expire to-marks))) |
| 9867 | (setcdr gnus-newsgroup-active to-article)) | 9898 | ;; Mark this article as expirable. |
| 9868 | 9899 | (push 'expire to-marks) | |
| 9869 | (while marks | 9900 | (when (equal to-group gnus-newsgroup-name) |
| 9870 | (when (eq (gnus-article-mark-to-type (cdar marks)) 'list) | 9901 | (push to-article gnus-newsgroup-expirable)) |
| 9871 | (when (memq article (symbol-value | 9902 | ;; Copy the expirable mark to other group. |
| 9872 | (intern (format "gnus-newsgroup-%s" | 9903 | (gnus-add-marked-articles |
| 9873 | (caar marks))))) | 9904 | to-group 'expire (list to-article) info)) |
| 9874 | (push (cdar marks) to-marks) | 9905 | |
| 9875 | ;; If the other group is the same as this group, | 9906 | (when to-marks |
| 9876 | ;; then we have to add the mark to the list. | 9907 | (gnus-request-set-mark |
| 9877 | (when (equal to-group gnus-newsgroup-name) | 9908 | to-group (list (list (list to-article) 'add to-marks))))) |
| 9878 | (set (intern (format "gnus-newsgroup-%s" | 9909 | |
| 9879 | (caar marks))) | 9910 | (gnus-dribble-enter |
| 9880 | (cons to-article | 9911 | (concat "(gnus-group-set-info '" |
| 9881 | (symbol-value | 9912 | (gnus-prin1-to-string (gnus-get-info to-group)) |
| 9882 | (intern (format "gnus-newsgroup-%s" | 9913 | ")")))) |
| 9883 | (caar marks))))))) | 9914 | |
| 9884 | ;; Copy the marks to other group. | 9915 | ;; Update the Xref header in this article to point to |
| 9885 | (gnus-add-marked-articles | 9916 | ;; the new crossposted article we have just created. |
| 9886 | to-group (cdar marks) (list to-article) info))) | 9917 | (when (eq action 'crosspost) |
| 9887 | (setq marks (cdr marks))) | 9918 | (with-current-buffer copy-buf |
| 9888 | 9919 | (gnus-request-article-this-buffer article gnus-newsgroup-name) | |
| 9889 | (when (and expirable | 9920 | (nnheader-replace-header "Xref" new-xref) |
| 9890 | gnus-mark-copied-or-moved-articles-as-expirable | 9921 | (gnus-request-replace-article |
| 9891 | (not (memq 'expire to-marks))) | 9922 | article gnus-newsgroup-name (current-buffer) t))) |
| 9892 | ;; Mark this article as expirable. | 9923 | |
| 9893 | (push 'expire to-marks) | 9924 | ;; run the move/copy/crosspost/respool hook |
| 9894 | (when (equal to-group gnus-newsgroup-name) | 9925 | (run-hook-with-args 'gnus-summary-article-move-hook |
| 9895 | (push to-article gnus-newsgroup-expirable)) | 9926 | action |
| 9896 | ;; Copy the expirable mark to other group. | 9927 | (gnus-data-header |
| 9897 | (gnus-add-marked-articles | 9928 | (assoc article (gnus-data-list nil))) |
| 9898 | to-group 'expire (list to-article) info)) | 9929 | gnus-newsgroup-name |
| 9899 | 9930 | to-newsgroup | |
| 9900 | (when to-marks | 9931 | select-method)) |
| 9901 | (gnus-request-set-mark | 9932 | |
| 9902 | to-group (list (list (list to-article) 'add to-marks))))) | 9933 | ;;;!!!Why is this necessary? |
| 9903 | 9934 | (set-buffer gnus-summary-buffer) | |
| 9904 | (gnus-dribble-enter | 9935 | |
| 9905 | (concat "(gnus-group-set-info '" | 9936 | (when (eq action 'move) |
| 9906 | (gnus-prin1-to-string (gnus-get-info to-group)) | 9937 | (save-excursion |
| 9907 | ")")))) | 9938 | (gnus-summary-goto-subject article) |
| 9908 | 9939 | (gnus-summary-mark-article article gnus-canceled-mark))))) | |
| 9909 | ;; Update the Xref header in this article to point to | 9940 | (push article articles-to-update-marks)) |
| 9910 | ;; the new crossposted article we have just created. | ||
| 9911 | (when (eq action 'crosspost) | ||
| 9912 | (with-current-buffer copy-buf | ||
| 9913 | (gnus-request-article-this-buffer article gnus-newsgroup-name) | ||
| 9914 | (nnheader-replace-header "Xref" new-xref) | ||
| 9915 | (gnus-request-replace-article | ||
| 9916 | article gnus-newsgroup-name (current-buffer) t))) | ||
| 9917 | |||
| 9918 | ;; run the move/copy/crosspost/respool hook | ||
| 9919 | (let ((header (gnus-data-header | ||
| 9920 | (assoc article (gnus-data-list nil))))) | ||
| 9921 | (mail-header-set-subject header gnus-article-original-subject) | ||
| 9922 | (run-hook-with-args 'gnus-summary-article-move-hook | ||
| 9923 | action | ||
| 9924 | (gnus-data-header | ||
| 9925 | (assoc article (gnus-data-list nil))) | ||
| 9926 | gnus-newsgroup-original-name | ||
| 9927 | to-newsgroup | ||
| 9928 | select-method))) | ||
| 9929 | |||
| 9930 | ;;;!!!Why is this necessary? | ||
| 9931 | (set-buffer gnus-summary-buffer) | ||
| 9932 | |||
| 9933 | (when (eq action 'move) | ||
| 9934 | (save-excursion | ||
| 9935 | (gnus-summary-goto-subject article) | ||
| 9936 | (gnus-summary-mark-article article gnus-canceled-mark))))) | ||
| 9937 | (push article articles-to-update-marks))) | ||
| 9938 | 9941 | ||
| 9939 | (save-excursion | 9942 | (save-excursion |
| 9940 | (apply 'gnus-summary-remove-process-mark articles-to-update-marks)) | 9943 | (apply 'gnus-summary-remove-process-mark articles-to-update-marks)) |
| @@ -10213,13 +10216,13 @@ confirmation before the articles are deleted." | |||
| 10213 | ;; The backend might not have been able to delete the article | 10216 | ;; The backend might not have been able to delete the article |
| 10214 | ;; after all. | 10217 | ;; after all. |
| 10215 | (unless (memq (car articles) not-deleted) | 10218 | (unless (memq (car articles) not-deleted) |
| 10216 | (gnus-summary-mark-article (car articles) gnus-canceled-mark)) | 10219 | (gnus-summary-mark-article (car articles) gnus-canceled-mark) |
| 10217 | (let* ((article (car articles)) | 10220 | (let* ((article (car articles)) |
| 10218 | (ghead (gnus-data-header | 10221 | (ghead (gnus-data-header |
| 10219 | (assoc article (gnus-data-list nil))))) | 10222 | (assoc article (gnus-data-list nil))))) |
| 10220 | (run-hook-with-args 'gnus-summary-article-delete-hook | 10223 | (run-hook-with-args 'gnus-summary-article-delete-hook |
| 10221 | 'delete ghead gnus-newsgroup-name nil | 10224 | 'delete ghead gnus-newsgroup-name nil |
| 10222 | nil)) | 10225 | nil))) |
| 10223 | (setq articles (cdr articles)))) | 10226 | (setq articles (cdr articles)))) |
| 10224 | (when not-deleted | 10227 | (when not-deleted |
| 10225 | (gnus-message 4 "Couldn't delete articles %s" not-deleted))) | 10228 | (gnus-message 4 "Couldn't delete articles %s" not-deleted))) |
diff --git a/lisp/gnus/gnus-win.el b/lisp/gnus/gnus-win.el index 809e4c339be..652d9fda94c 100644 --- a/lisp/gnus/gnus-win.el +++ b/lisp/gnus/gnus-win.el | |||
| @@ -228,50 +228,6 @@ See the Gnus manual for an explanation of the syntax used.") | |||
| 228 | (pop list)) | 228 | (pop list)) |
| 229 | (cadr (assq (car list) gnus-window-configuration))) | 229 | (cadr (assq (car list) gnus-window-configuration))) |
| 230 | 230 | ||
| 231 | (defun gnus-windows-old-to-new (setting) | ||
| 232 | ;; First we take care of the really, really old Gnus 3 actions. | ||
| 233 | (when (symbolp setting) | ||
| 234 | (setq setting | ||
| 235 | ;; Take care of ooold GNUS 3.x values. | ||
| 236 | (cond ((eq setting 'SelectArticle) 'article) | ||
| 237 | ((memq setting '(SelectNewsgroup SelectSubject ExpandSubject)) | ||
| 238 | 'summary) | ||
| 239 | ((memq setting '(ExitNewsgroup)) 'group) | ||
| 240 | (t setting)))) | ||
| 241 | (if (or (listp setting) | ||
| 242 | (not (and gnus-window-configuration | ||
| 243 | (memq setting '(group summary article))))) | ||
| 244 | setting | ||
| 245 | (let* ((elem | ||
| 246 | (cond | ||
| 247 | ((eq setting 'group) | ||
| 248 | (gnus-window-configuration-element | ||
| 249 | '(group newsgroups ExitNewsgroup))) | ||
| 250 | ((eq setting 'summary) | ||
| 251 | (gnus-window-configuration-element | ||
| 252 | '(summary SelectNewsgroup SelectSubject ExpandSubject))) | ||
| 253 | ((eq setting 'article) | ||
| 254 | (gnus-window-configuration-element | ||
| 255 | '(article SelectArticle))))) | ||
| 256 | (total (apply '+ elem)) | ||
| 257 | (types '(group summary article)) | ||
| 258 | (pbuf (if (eq setting 'newsgroups) 'group 'summary)) | ||
| 259 | (i 0) | ||
| 260 | perc out) | ||
| 261 | (while (< i 3) | ||
| 262 | (or (not (numberp (nth i elem))) | ||
| 263 | (zerop (nth i elem)) | ||
| 264 | (progn | ||
| 265 | (setq perc (if (= i 2) | ||
| 266 | 1.0 | ||
| 267 | (/ (float (nth i elem)) total))) | ||
| 268 | (push (if (eq pbuf (nth i types)) | ||
| 269 | (list (nth i types) perc 'point) | ||
| 270 | (list (nth i types) perc)) | ||
| 271 | out))) | ||
| 272 | (incf i)) | ||
| 273 | `(vertical 1.0 ,@(nreverse out))))) | ||
| 274 | |||
| 275 | ;;;###autoload | 231 | ;;;###autoload |
| 276 | (defun gnus-add-configuration (conf) | 232 | (defun gnus-add-configuration (conf) |
| 277 | "Add the window configuration CONF to `gnus-buffer-configuration'." | 233 | "Add the window configuration CONF to `gnus-buffer-configuration'." |
| @@ -293,18 +249,9 @@ See the Gnus manual for an explanation of the syntax used.") | |||
| 293 | 249 | ||
| 294 | (defun gnus-configure-frame (split &optional window) | 250 | (defun gnus-configure-frame (split &optional window) |
| 295 | "Split WINDOW according to SPLIT." | 251 | "Split WINDOW according to SPLIT." |
| 296 | (let ((current-window | 252 | (let* ((current-window (or (get-buffer-window (current-buffer)) (selected-window))) |
| 297 | (or (get-buffer-window (current-buffer)) (selected-window)))) | 253 | (window (or window current-window))) |
| 298 | (unless window | ||
| 299 | (setq window current-window)) | ||
| 300 | (select-window window) | 254 | (select-window window) |
| 301 | ;; This might be an old-style buffer config. | ||
| 302 | (when (vectorp split) | ||
| 303 | (setq split (append split nil))) | ||
| 304 | (when (or (consp (car split)) | ||
| 305 | (vectorp (car split))) | ||
| 306 | (push 1.0 split) | ||
| 307 | (push 'vertical split)) | ||
| 308 | ;; The SPLIT might be something that is to be evaled to | 255 | ;; The SPLIT might be something that is to be evaled to |
| 309 | ;; return a new SPLIT. | 256 | ;; return a new SPLIT. |
| 310 | (while (and (not (assq (car split) gnus-window-to-buffer)) | 257 | (while (and (not (assq (car split) gnus-window-to-buffer)) |
| @@ -423,56 +370,55 @@ See the Gnus manual for an explanation of the syntax used.") | |||
| 423 | (set-window-configuration setting) | 370 | (set-window-configuration setting) |
| 424 | (setq gnus-current-window-configuration setting) | 371 | (setq gnus-current-window-configuration setting) |
| 425 | (setq force (or force gnus-always-force-window-configuration)) | 372 | (setq force (or force gnus-always-force-window-configuration)) |
| 426 | (setq setting (gnus-windows-old-to-new setting)) | ||
| 427 | (let ((split (if (symbolp setting) | 373 | (let ((split (if (symbolp setting) |
| 428 | (cadr (assq setting gnus-buffer-configuration)) | 374 | (cadr (assq setting gnus-buffer-configuration)) |
| 429 | setting)) | 375 | setting)) |
| 430 | all-visible) | 376 | all-visible) |
| 431 | 377 | ||
| 432 | (setq gnus-frame-split-p nil) | 378 | (setq gnus-frame-split-p nil) |
| 433 | 379 | ||
| 434 | (unless split | 380 | (unless split |
| 435 | (error "No such setting in `gnus-buffer-configuration': %s" setting)) | 381 | (error "No such setting in `gnus-buffer-configuration': %s" setting)) |
| 436 | 382 | ||
| 437 | (if (and (setq all-visible (gnus-all-windows-visible-p split)) | 383 | (if (and (setq all-visible (gnus-all-windows-visible-p split)) |
| 438 | (not force)) | 384 | (not force)) |
| 439 | ;; All the windows mentioned are already visible, so we just | 385 | ;; All the windows mentioned are already visible, so we just |
| 440 | ;; put point in the assigned buffer, and do not touch the | 386 | ;; put point in the assigned buffer, and do not touch the |
| 441 | ;; winconf. | 387 | ;; winconf. |
| 442 | (select-window all-visible) | 388 | (select-window all-visible) |
| 443 | 389 | ||
| 444 | ;; Make sure "the other" buffer, nntp-server-buffer, is live. | 390 | ;; Make sure "the other" buffer, nntp-server-buffer, is live. |
| 445 | (unless (gnus-buffer-live-p nntp-server-buffer) | 391 | (unless (gnus-buffer-live-p nntp-server-buffer) |
| 446 | (nnheader-init-server-buffer)) | 392 | (nnheader-init-server-buffer)) |
| 447 | 393 | ||
| 448 | ;; Either remove all windows or just remove all Gnus windows. | 394 | ;; Either remove all windows or just remove all Gnus windows. |
| 449 | (let ((frame (selected-frame))) | 395 | (let ((frame (selected-frame))) |
| 450 | (unwind-protect | 396 | (unwind-protect |
| 451 | (if gnus-use-full-window | 397 | (if gnus-use-full-window |
| 452 | ;; We want to remove all other windows. | 398 | ;; We want to remove all other windows. |
| 453 | (if (not gnus-frame-split-p) | 399 | (if (not gnus-frame-split-p) |
| 454 | ;; This is not a `frame' split, so we ignore the | 400 | ;; This is not a `frame' split, so we ignore the |
| 455 | ;; other frames. | 401 | ;; other frames. |
| 456 | (delete-other-windows) | 402 | (delete-other-windows) |
| 457 | ;; This is a `frame' split, so we delete all windows | 403 | ;; This is a `frame' split, so we delete all windows |
| 458 | ;; on all frames. | 404 | ;; on all frames. |
| 459 | (gnus-delete-windows-in-gnusey-frames)) | 405 | (gnus-delete-windows-in-gnusey-frames)) |
| 460 | ;; Just remove some windows. | 406 | ;; Just remove some windows. |
| 461 | (gnus-remove-some-windows) | 407 | (gnus-remove-some-windows) |
| 462 | (if (featurep 'xemacs) | 408 | (if (featurep 'xemacs) |
| 463 | (switch-to-buffer nntp-server-buffer) | 409 | (switch-to-buffer nntp-server-buffer) |
| 464 | (set-buffer nntp-server-buffer))) | 410 | (set-buffer nntp-server-buffer))) |
| 465 | (select-frame frame))) | 411 | (select-frame frame))) |
| 466 | 412 | ||
| 467 | (let (gnus-window-frame-focus) | 413 | (let (gnus-window-frame-focus) |
| 468 | (if (featurep 'xemacs) | 414 | (if (featurep 'xemacs) |
| 469 | (switch-to-buffer nntp-server-buffer) | 415 | (switch-to-buffer nntp-server-buffer) |
| 470 | (set-buffer nntp-server-buffer)) | 416 | (set-buffer nntp-server-buffer)) |
| 471 | (gnus-configure-frame split) | 417 | (gnus-configure-frame split) |
| 472 | (run-hooks 'gnus-configure-windows-hook) | 418 | (run-hooks 'gnus-configure-windows-hook) |
| 473 | (when gnus-window-frame-focus | 419 | (when gnus-window-frame-focus |
| 474 | (gnus-select-frame-set-input-focus | 420 | (gnus-select-frame-set-input-focus |
| 475 | (window-frame gnus-window-frame-focus)))))))) | 421 | (window-frame gnus-window-frame-focus)))))))) |
| 476 | 422 | ||
| 477 | (defun gnus-delete-windows-in-gnusey-frames () | 423 | (defun gnus-delete-windows-in-gnusey-frames () |
| 478 | "Do a `delete-other-windows' in all frames that have Gnus windows." | 424 | "Do a `delete-other-windows' in all frames that have Gnus windows." |
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el index 20ce72d8855..d32ecac5dc3 100644 --- a/lisp/gnus/gnus.el +++ b/lisp/gnus/gnus.el | |||
| @@ -1401,10 +1401,6 @@ no need to set this variable." | |||
| 1401 | string)) | 1401 | string)) |
| 1402 | (make-obsolete-variable 'gnus-local-domain nil "Emacs 24.1") | 1402 | (make-obsolete-variable 'gnus-local-domain nil "Emacs 24.1") |
| 1403 | 1403 | ||
| 1404 | (defvar gnus-local-organization nil | ||
| 1405 | "String with a description of what organization (if any) the user belongs to. | ||
| 1406 | Obsolete variable; use `message-user-organization' instead.") | ||
| 1407 | |||
| 1408 | ;; Customization variables | 1404 | ;; Customization variables |
| 1409 | 1405 | ||
| 1410 | (defcustom gnus-refer-article-method 'current | 1406 | (defcustom gnus-refer-article-method 'current |
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 1ee07a2d5ee..feb5102055c 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el | |||
| @@ -160,8 +160,12 @@ If this variable is nil, no such courtesy message will be added." | |||
| 160 | :group 'message-interface | 160 | :group 'message-interface |
| 161 | :type 'regexp) | 161 | :type 'regexp) |
| 162 | 162 | ||
| 163 | (defcustom message-from-style mail-from-style | 163 | (defcustom message-from-style 'default |
| 164 | "*Specifies how \"From\" headers look. | 164 | ;; In Emacs 24.1 this defaults to the value of `mail-from-style' |
| 165 | ;; that defaults to: | ||
| 166 | ;; `angles' in Emacs 22.1~23.1, XEmacs 21.4, 21.5, and SXEmacs 22.1; | ||
| 167 | ;; `system-default' in Emacs 23.2, and 24.1 | ||
| 168 | "Specifies how \"From\" headers look. | ||
| 165 | 169 | ||
| 166 | If nil, they contain just the return address like: | 170 | If nil, they contain just the return address like: |
| 167 | king@grassland.com | 171 | king@grassland.com |
| @@ -507,14 +511,9 @@ This is used by `message-kill-buffer'." | |||
| 507 | :group 'message-buffers | 511 | :group 'message-buffers |
| 508 | :type 'boolean) | 512 | :type 'boolean) |
| 509 | 513 | ||
| 510 | (defvar gnus-local-organization) | ||
| 511 | (defcustom message-user-organization | 514 | (defcustom message-user-organization |
| 512 | (or (and (boundp 'gnus-local-organization) | 515 | (or (getenv "ORGANIZATION") t) |
| 513 | (stringp gnus-local-organization) | 516 | "String to be used as an Organization header. |
| 514 | gnus-local-organization) | ||
| 515 | (getenv "ORGANIZATION") | ||
| 516 | t) | ||
| 517 | "*String to be used as an Organization header. | ||
| 518 | If t, use `message-user-organization-file'." | 517 | If t, use `message-user-organization-file'." |
| 519 | :group 'message-headers | 518 | :group 'message-headers |
| 520 | :type '(choice string | 519 | :type '(choice string |
diff --git a/lisp/gnus/mm-util.el b/lisp/gnus/mm-util.el index 700c1a6bb64..2f6464d43f2 100644 --- a/lisp/gnus/mm-util.el +++ b/lisp/gnus/mm-util.el | |||
| @@ -974,6 +974,7 @@ If the charset is `composition', return the actual one." | |||
| 974 | ;; This is for XEmacs. | 974 | ;; This is for XEmacs. |
| 975 | (mm-mule-charset-to-mime-charset charset))) | 975 | (mm-mule-charset-to-mime-charset charset))) |
| 976 | 976 | ||
| 977 | ;; `delete-dups' is not available in XEmacs 21.4. | ||
| 977 | (if (fboundp 'delete-dups) | 978 | (if (fboundp 'delete-dups) |
| 978 | (defalias 'mm-delete-duplicates 'delete-dups) | 979 | (defalias 'mm-delete-duplicates 'delete-dups) |
| 979 | (defun mm-delete-duplicates (list) | 980 | (defun mm-delete-duplicates (list) |
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index cb4c9f0108c..a53f9ac468d 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | (require 'tls) | 45 | (require 'tls) |
| 46 | (require 'parse-time) | 46 | (require 'parse-time) |
| 47 | (require 'nnmail) | 47 | (require 'nnmail) |
| 48 | (require 'proto-stream) | ||
| 48 | 49 | ||
| 49 | (eval-when-compile | 50 | (eval-when-compile |
| 50 | (require 'gnus-sum)) | 51 | (require 'gnus-sum)) |
| @@ -62,9 +63,10 @@ | |||
| 62 | If nnimap-stream is `ssl', this will default to `imaps'. If not, | 63 | If nnimap-stream is `ssl', this will default to `imaps'. If not, |
| 63 | it will default to `imap'.") | 64 | it will default to `imap'.") |
| 64 | 65 | ||
| 65 | (defvoo nnimap-stream 'ssl | 66 | (defvoo nnimap-stream 'undecided |
| 66 | "How nnimap will talk to the IMAP server. | 67 | "How nnimap will talk to the IMAP server. |
| 67 | Values are `ssl', `network', `starttls' or `shell'.") | 68 | Values are `ssl', `network', `starttls' or `shell'. |
| 69 | The default is to try `ssl' first, and then `network'.") | ||
| 68 | 70 | ||
| 69 | (defvoo nnimap-shell-program (if (boundp 'imap-shell-program) | 71 | (defvoo nnimap-shell-program (if (boundp 'imap-shell-program) |
| 70 | (if (listp imap-shell-program) | 72 | (if (listp imap-shell-program) |
| @@ -271,16 +273,6 @@ textual parts.") | |||
| 271 | (push (current-buffer) nnimap-process-buffers) | 273 | (push (current-buffer) nnimap-process-buffers) |
| 272 | (current-buffer))) | 274 | (current-buffer))) |
| 273 | 275 | ||
| 274 | (defun nnimap-open-shell-stream (name buffer host port) | ||
| 275 | (let ((process-connection-type nil)) | ||
| 276 | (start-process name buffer shell-file-name | ||
| 277 | shell-command-switch | ||
| 278 | (format-spec | ||
| 279 | nnimap-shell-program | ||
| 280 | (format-spec-make | ||
| 281 | ?s host | ||
| 282 | ?p port))))) | ||
| 283 | |||
| 284 | (defun nnimap-credentials (address ports &optional inhibit-create) | 276 | (defun nnimap-credentials (address ports &optional inhibit-create) |
| 285 | (let (port credentials) | 277 | (let (port credentials) |
| 286 | ;; Request the credentials from all ports, but only query on the | 278 | ;; Request the credentials from all ports, but only query on the |
| @@ -310,111 +302,79 @@ textual parts.") | |||
| 310 | (* 5 60))) | 302 | (* 5 60))) |
| 311 | (nnimap-send-command "NOOP"))))))) | 303 | (nnimap-send-command "NOOP"))))))) |
| 312 | 304 | ||
| 313 | (declare-function gnutls-negotiate "gnutls" | ||
| 314 | (proc type &optional priority-string trustfiles keyfiles)) | ||
| 315 | |||
| 316 | (defun nnimap-open-connection (buffer) | 305 | (defun nnimap-open-connection (buffer) |
| 306 | ;; Be backwards-compatible -- the earlier value of nnimap-stream was | ||
| 307 | ;; `ssl' when nnimap-server-port was nil. Sort of. | ||
| 308 | (when (and nnimap-server-port | ||
| 309 | (eq nnimap-stream 'undecided)) | ||
| 310 | (setq nnimap-stream 'ssl)) | ||
| 311 | (let ((stream | ||
| 312 | (if (eq nnimap-stream 'undecided) | ||
| 313 | (loop for type in '(ssl network) | ||
| 314 | for stream = (let ((nnimap-stream type)) | ||
| 315 | (nnimap-open-connection-1 buffer)) | ||
| 316 | while (eq stream 'no-connect) | ||
| 317 | finally (return stream)) | ||
| 318 | (nnimap-open-connection-1 buffer)))) | ||
| 319 | (if (eq stream 'no-connect) | ||
| 320 | nil | ||
| 321 | stream))) | ||
| 322 | |||
| 323 | (defun nnimap-open-connection-1 (buffer) | ||
| 317 | (unless nnimap-keepalive-timer | 324 | (unless nnimap-keepalive-timer |
| 318 | (setq nnimap-keepalive-timer (run-at-time (* 60 15) (* 60 15) | 325 | (setq nnimap-keepalive-timer (run-at-time (* 60 15) (* 60 15) |
| 319 | 'nnimap-keepalive))) | 326 | 'nnimap-keepalive))) |
| 320 | (block nil | 327 | (with-current-buffer (nnimap-make-process-buffer buffer) |
| 321 | (with-current-buffer (nnimap-make-process-buffer buffer) | 328 | (let* ((coding-system-for-read 'binary) |
| 322 | (let* ((coding-system-for-read 'binary) | 329 | (coding-system-for-write 'binary) |
| 323 | (coding-system-for-write 'binary) | 330 | (port nil) |
| 324 | (port nil) | 331 | (ports |
| 325 | (ports | ||
| 326 | (cond | ||
| 327 | ((or (eq nnimap-stream 'network) | ||
| 328 | (and (eq nnimap-stream 'starttls) | ||
| 329 | (fboundp 'open-gnutls-stream))) | ||
| 330 | (nnheader-message 7 "Opening connection to %s..." | ||
| 331 | nnimap-address) | ||
| 332 | (open-network-stream | ||
| 333 | "*nnimap*" (current-buffer) nnimap-address | ||
| 334 | (setq port | ||
| 335 | (or nnimap-server-port | ||
| 336 | (if (netrc-find-service-number "imap") | ||
| 337 | "imap" | ||
| 338 | "143")))) | ||
| 339 | '("143" "imap")) | ||
| 340 | ((eq nnimap-stream 'shell) | ||
| 341 | (nnheader-message 7 "Opening connection to %s via shell..." | ||
| 342 | nnimap-address) | ||
| 343 | (nnimap-open-shell-stream | ||
| 344 | "*nnimap*" (current-buffer) nnimap-address | ||
| 345 | (setq port (or nnimap-server-port "imap"))) | ||
| 346 | '("imap")) | ||
| 347 | ((eq nnimap-stream 'starttls) | ||
| 348 | (nnheader-message 7 "Opening connection to %s via starttls..." | ||
| 349 | nnimap-address) | ||
| 350 | (let ((tls-program | ||
| 351 | '("openssl s_client -connect %h:%p -no_ssl2 -ign_eof -starttls imap"))) | ||
| 352 | (open-tls-stream | ||
| 353 | "*nnimap*" (current-buffer) nnimap-address | ||
| 354 | (setq port (or nnimap-server-port "imap")))) | ||
| 355 | '("imap")) | ||
| 356 | ((memq nnimap-stream '(ssl tls)) | ||
| 357 | (nnheader-message 7 "Opening connection to %s via tls..." | ||
| 358 | nnimap-address) | ||
| 359 | (funcall (if (fboundp 'open-gnutls-stream) | ||
| 360 | 'open-gnutls-stream | ||
| 361 | 'open-tls-stream) | ||
| 362 | "*nnimap*" (current-buffer) nnimap-address | ||
| 363 | (setq port | ||
| 364 | (or nnimap-server-port | ||
| 365 | (if (netrc-find-service-number "imaps") | ||
| 366 | "imaps" | ||
| 367 | "993")))) | ||
| 368 | '("143" "993" "imap" "imaps")) | ||
| 369 | (t | ||
| 370 | (error "Unknown stream type: %s" nnimap-stream)))) | ||
| 371 | connection-result login-result credentials) | ||
| 372 | (setf (nnimap-process nnimap-object) | ||
| 373 | (get-buffer-process (current-buffer))) | ||
| 374 | (if (not (and (nnimap-process nnimap-object) | ||
| 375 | (memq (process-status (nnimap-process nnimap-object)) | ||
| 376 | '(open run)))) | ||
| 377 | (nnheader-report 'nnimap "Unable to contact %s:%s via %s" | ||
| 378 | nnimap-address port nnimap-stream) | ||
| 379 | (gnus-set-process-query-on-exit-flag | ||
| 380 | (nnimap-process nnimap-object) nil) | ||
| 381 | (if (not (setq connection-result (nnimap-wait-for-connection))) | ||
| 382 | (nnheader-report 'nnimap | ||
| 383 | "%s" (buffer-substring | ||
| 384 | (point) (line-end-position))) | ||
| 385 | ;; Store the greeting (for debugging purposes). | ||
| 386 | (setf (nnimap-greeting nnimap-object) | ||
| 387 | (buffer-substring (line-beginning-position) | ||
| 388 | (line-end-position))) | ||
| 389 | (nnimap-get-capabilities) | ||
| 390 | (when nnimap-server-port | ||
| 391 | (push (format "%s" nnimap-server-port) ports)) | ||
| 392 | ;; If this is a STARTTLS-capable server, then sever the | ||
| 393 | ;; connection and start a STARTTLS connection instead. | ||
| 394 | (cond | 332 | (cond |
| 395 | ((and (or (and (eq nnimap-stream 'network) | 333 | ((or (eq nnimap-stream 'network) |
| 396 | (nnimap-capability "STARTTLS")) | 334 | (eq nnimap-stream 'starttls)) |
| 397 | (eq nnimap-stream 'starttls)) | 335 | (nnheader-message 7 "Opening connection to %s..." |
| 398 | (fboundp 'open-gnutls-stream)) | 336 | nnimap-address) |
| 399 | (nnimap-command "STARTTLS") | 337 | '("143" "imap")) |
| 400 | (gnutls-negotiate (nnimap-process nnimap-object) nil) | 338 | ((eq nnimap-stream 'shell) |
| 401 | ;; Get the capabilities again -- they may have changed | 339 | (nnheader-message 7 "Opening connection to %s via shell..." |
| 402 | ;; after doing STARTTLS. | 340 | nnimap-address) |
| 403 | (nnimap-get-capabilities)) | 341 | '("imap")) |
| 404 | ((and (eq nnimap-stream 'network) | 342 | ((memq nnimap-stream '(ssl tls)) |
| 405 | (nnimap-capability "STARTTLS")) | 343 | (nnheader-message 7 "Opening connection to %s via tls..." |
| 406 | (let ((nnimap-stream 'starttls)) | 344 | nnimap-address) |
| 407 | (let ((tls-process | 345 | '("143" "993" "imap" "imaps")) |
| 408 | (nnimap-open-connection buffer))) | 346 | (t |
| 409 | ;; If the STARTTLS connection was successful, we | 347 | (error "Unknown stream type: %s" nnimap-stream)))) |
| 410 | ;; kill our first non-encrypted connection. If it | 348 | (proto-stream-always-use-starttls t) |
| 411 | ;; wasn't successful, we just use our unencrypted | 349 | login-result credentials) |
| 412 | ;; connection. | 350 | (when nnimap-server-port |
| 413 | (when (memq (process-status tls-process) '(open run)) | 351 | (setq ports (append ports (list nnimap-server-port)))) |
| 414 | (delete-process (nnimap-process nnimap-object)) | 352 | (destructuring-bind (stream greeting capabilities) |
| 415 | (kill-buffer (current-buffer)) | 353 | (open-protocol-stream |
| 416 | (return tls-process)))))) | 354 | "*nnimap*" (current-buffer) nnimap-address (car (last ports)) |
| 417 | (unless (equal connection-result "PREAUTH") | 355 | :type nnimap-stream |
| 356 | :shell-command nnimap-shell-program | ||
| 357 | :capability-command "1 CAPABILITY\r\n" | ||
| 358 | :success " OK " | ||
| 359 | :starttls-function | ||
| 360 | (lambda (capabilities) | ||
| 361 | (when (gnus-string-match-p "STARTTLS" capabilities) | ||
| 362 | "1 STARTTLS\r\n"))) | ||
| 363 | (setf (nnimap-process nnimap-object) stream) | ||
| 364 | (if (not stream) | ||
| 365 | (progn | ||
| 366 | (nnheader-report 'nnimap "Unable to contact %s:%s via %s" | ||
| 367 | nnimap-address port nnimap-stream) | ||
| 368 | 'no-connect) | ||
| 369 | (gnus-set-process-query-on-exit-flag stream nil) | ||
| 370 | (if (not (gnus-string-match-p "[*.] \\(OK\\|PREAUTH\\)" greeting)) | ||
| 371 | (nnheader-report 'nnimap "%s" greeting) | ||
| 372 | ;; Store the greeting (for debugging purposes). | ||
| 373 | (setf (nnimap-greeting nnimap-object) greeting) | ||
| 374 | (setf (nnimap-capabilities nnimap-object) | ||
| 375 | (mapcar #'upcase | ||
| 376 | (split-string capabilities))) | ||
| 377 | (unless (gnus-string-match-p "[*.] PREAUTH" greeting) | ||
| 418 | (if (not (setq credentials | 378 | (if (not (setq credentials |
| 419 | (if (eq nnimap-authenticator 'anonymous) | 379 | (if (eq nnimap-authenticator 'anonymous) |
| 420 | (list "anonymous" | 380 | (list "anonymous" |
| @@ -456,13 +416,6 @@ textual parts.") | |||
| 456 | (nnimap-command "ENABLE QRESYNC")) | 416 | (nnimap-command "ENABLE QRESYNC")) |
| 457 | (nnimap-process nnimap-object)))))))) | 417 | (nnimap-process nnimap-object)))))))) |
| 458 | 418 | ||
| 459 | (defun nnimap-get-capabilities () | ||
| 460 | (setf (nnimap-capabilities nnimap-object) | ||
| 461 | (mapcar | ||
| 462 | #'upcase | ||
| 463 | (nnimap-find-parameter | ||
| 464 | "CAPABILITY" (cdr (nnimap-command "CAPABILITY")))))) | ||
| 465 | |||
| 466 | (defun nnimap-quote-specials (string) | 419 | (defun nnimap-quote-specials (string) |
| 467 | (with-temp-buffer | 420 | (with-temp-buffer |
| 468 | (insert string) | 421 | (insert string) |
| @@ -1110,7 +1063,7 @@ textual parts.") | |||
| 1110 | uidvalidity | 1063 | uidvalidity |
| 1111 | modseq) | 1064 | modseq) |
| 1112 | (push | 1065 | (push |
| 1113 | (list (nnimap-send-command "EXAMINE %S (QRESYNC (%s %s))" | 1066 | (list (nnimap-send-command "EXAMINE %S (QRESYNC (%s %s))" |
| 1114 | (utf7-encode group t) | 1067 | (utf7-encode group t) |
| 1115 | uidvalidity modseq) | 1068 | uidvalidity modseq) |
| 1116 | 'qresync | 1069 | 'qresync |
diff --git a/lisp/gnus/nnir.el b/lisp/gnus/nnir.el index e5ba3c60620..889d6ff7da5 100644 --- a/lisp/gnus/nnir.el +++ b/lisp/gnus/nnir.el | |||
| @@ -42,7 +42,7 @@ | |||
| 42 | 42 | ||
| 43 | ;; When looking at the retrieval result (in the Summary buffer) you | 43 | ;; When looking at the retrieval result (in the Summary buffer) you |
| 44 | ;; can type `A W' (aka M-x gnus-warp-to-article RET) on an article. You | 44 | ;; can type `A W' (aka M-x gnus-warp-to-article RET) on an article. You |
| 45 | ;; will be warped into the group this article came from. Typing `A W' | 45 | ;; will be warped into the group this article came from. Typing `A T' |
| 46 | ;; (aka M-x gnus-summary-refer-thread RET) will warp to the group and | 46 | ;; (aka M-x gnus-summary-refer-thread RET) will warp to the group and |
| 47 | ;; also show the thread this article is part of. | 47 | ;; also show the thread this article is part of. |
| 48 | 48 | ||
| @@ -181,7 +181,8 @@ | |||
| 181 | (eval-when-compile | 181 | (eval-when-compile |
| 182 | (autoload 'nnimap-buffer "nnimap") | 182 | (autoload 'nnimap-buffer "nnimap") |
| 183 | (autoload 'nnimap-command "nnimap") | 183 | (autoload 'nnimap-command "nnimap") |
| 184 | (autoload 'nnimap-possibly-change-group "nnimap")) | 184 | (autoload 'nnimap-possibly-change-group "nnimap") |
| 185 | (autoload 'gnus-registry-action "gnus-registry")) | ||
| 185 | 186 | ||
| 186 | (nnoo-declare nnir) | 187 | (nnoo-declare nnir) |
| 187 | (nnoo-define-basics nnir) | 188 | (nnoo-define-basics nnir) |
| @@ -198,14 +199,34 @@ | |||
| 198 | (defcustom nnir-method-default-engines | 199 | (defcustom nnir-method-default-engines |
| 199 | '((nnimap . imap) | 200 | '((nnimap . imap) |
| 200 | (nntp . gmane)) | 201 | (nntp . gmane)) |
| 201 | "*Alist of default search engines keyed by server method" | 202 | "*Alist of default search engines keyed by server method." |
| 202 | :type '(alist) | 203 | :type '(alist) |
| 203 | :group 'nnir) | 204 | :group 'nnir) |
| 204 | 205 | ||
| 206 | (defcustom nnir-ignored-newsgroups "" | ||
| 207 | "*A regexp to match newsgroups in the active file that should | ||
| 208 | be skipped when searching." | ||
| 209 | :type '(regexp) | ||
| 210 | :group 'nnir) | ||
| 211 | |||
| 212 | (defcustom nnir-summary-line-format nil | ||
| 213 | "*The format specification of the lines in an nnir summary buffer. | ||
| 214 | |||
| 215 | All the items from `gnus-summary-line-format' are available, along | ||
| 216 | with three items unique to nnir summary buffers: | ||
| 217 | |||
| 218 | %Z Search retrieval score value (integer) | ||
| 219 | %G Article original full group name (string) | ||
| 220 | %g Article original short group name (string) | ||
| 221 | |||
| 222 | If nil this will use `gnus-summary-line-format'." | ||
| 223 | :type '(regexp) | ||
| 224 | :group 'nnir) | ||
| 225 | |||
| 205 | (defcustom nnir-imap-default-search-key "Whole message" | 226 | (defcustom nnir-imap-default-search-key "Whole message" |
| 206 | "*The default IMAP search key for an nnir search. Must be one of | 227 | "*The default IMAP search key for an nnir search. Must be one of |
| 207 | the keys in `nnir-imap-search-arguments'. To use raw imap queries | 228 | the keys in `nnir-imap-search-arguments'. To use raw imap queries |
| 208 | by default set this to \"Imap\"" | 229 | by default set this to \"Imap\"." |
| 209 | :type '(string) | 230 | :type '(string) |
| 210 | :group 'nnir) | 231 | :group 'nnir) |
| 211 | 232 | ||
| @@ -423,9 +444,11 @@ needs the variables `nnir-namazu-program', | |||
| 423 | 444 | ||
| 424 | Add an entry here when adding a new search engine.") | 445 | Add an entry here when adding a new search engine.") |
| 425 | 446 | ||
| 426 | (defvar nnir-get-article-nov-override-function nil | 447 | (defvar nnir-retrieve-headers-override-function nil |
| 427 | "If non-nil, a function that will be passed each search result. This | 448 | "If non-nil, a function that accepts an article list and group |
| 428 | should return a message's headers in NOV format. | 449 | and populates the `nntp-server-buffer' with the retrieved |
| 450 | headers. Must return either 'nov or 'headers indicating the | ||
| 451 | retrieved header format. | ||
| 429 | 452 | ||
| 430 | If this variable is nil, or if the provided function returns nil for a search | 453 | If this variable is nil, or if the provided function returns nil for a search |
| 431 | result, `gnus-retrieve-headers' will be called instead.") | 454 | result, `gnus-retrieve-headers' will be called instead.") |
| @@ -455,6 +478,68 @@ result, `gnus-retrieve-headers' will be called instead.") | |||
| 455 | 478 | ||
| 456 | ;;; Code: | 479 | ;;; Code: |
| 457 | 480 | ||
| 481 | ;;; Helper macros | ||
| 482 | |||
| 483 | ;; Data type article list. | ||
| 484 | |||
| 485 | (defmacro nnir-artlist-length (artlist) | ||
| 486 | "Returns number of articles in artlist." | ||
| 487 | `(length ,artlist)) | ||
| 488 | |||
| 489 | (defmacro nnir-artlist-article (artlist n) | ||
| 490 | "Returns from ARTLIST the Nth artitem (counting starting at 1)." | ||
| 491 | `(when (> ,n 0) | ||
| 492 | (elt ,artlist (1- ,n)))) | ||
| 493 | |||
| 494 | (defmacro nnir-artitem-group (artitem) | ||
| 495 | "Returns the group from the ARTITEM." | ||
| 496 | `(elt ,artitem 0)) | ||
| 497 | |||
| 498 | (defmacro nnir-artitem-number (artitem) | ||
| 499 | "Returns the number from the ARTITEM." | ||
| 500 | `(elt ,artitem 1)) | ||
| 501 | |||
| 502 | (defmacro nnir-artitem-rsv (artitem) | ||
| 503 | "Returns the Retrieval Status Value (RSV, score) from the ARTITEM." | ||
| 504 | `(elt ,artitem 2)) | ||
| 505 | |||
| 506 | (defmacro nnir-article-group (article) | ||
| 507 | "Returns the group for ARTICLE" | ||
| 508 | `(nnir-artitem-group (nnir-artlist-article nnir-artlist ,article))) | ||
| 509 | |||
| 510 | (defmacro nnir-article-number (article) | ||
| 511 | "Returns the number for ARTICLE" | ||
| 512 | `(nnir-artitem-number (nnir-artlist-article nnir-artlist ,article))) | ||
| 513 | |||
| 514 | (defmacro nnir-article-rsv (article) | ||
| 515 | "Returns the rsv for ARTICLE" | ||
| 516 | `(nnir-artitem-rsv (nnir-artlist-article nnir-artlist ,article))) | ||
| 517 | |||
| 518 | (defsubst nnir-article-ids (article) | ||
| 519 | "Returns the pair `(nnir id . real id)' of ARTICLE" | ||
| 520 | (cons article (nnir-article-number article))) | ||
| 521 | |||
| 522 | (defmacro nnir-categorize (sequence keyfunc &optional valuefunc) | ||
| 523 | "Sorts a sequence into categories and returns a list of the form | ||
| 524 | `((key1 (element11 element12)) (key2 (element21 element22))'. | ||
| 525 | The category key for a member of the sequence is obtained | ||
| 526 | as `(keyfunc member)' and the corresponding element is just | ||
| 527 | `member'. If `valuefunc' is non-nil, the element of the list | ||
| 528 | is `(valuefunc member)'." | ||
| 529 | `(unless (null ,sequence) | ||
| 530 | (let (value) | ||
| 531 | (mapcar | ||
| 532 | (lambda (member) | ||
| 533 | (let ((y (,keyfunc member)) | ||
| 534 | (x ,(if valuefunc | ||
| 535 | `(,valuefunc member) | ||
| 536 | 'member))) | ||
| 537 | (if (assoc y value) | ||
| 538 | (push x (cadr (assoc y value))) | ||
| 539 | (push (list y (list x)) value)))) | ||
| 540 | ,sequence) | ||
| 541 | value))) | ||
| 542 | |||
| 458 | ;; Gnus glue. | 543 | ;; Gnus glue. |
| 459 | 544 | ||
| 460 | (defun gnus-group-make-nnir-group (nnir-extra-parms) | 545 | (defun gnus-group-make-nnir-group (nnir-extra-parms) |
| @@ -479,6 +564,7 @@ result, `gnus-retrieve-headers' will be called instead.") | |||
| 479 | 564 | ||
| 480 | (deffoo nnir-open-server (server &optional definitions) | 565 | (deffoo nnir-open-server (server &optional definitions) |
| 481 | ;; Just set the server variables appropriately. | 566 | ;; Just set the server variables appropriately. |
| 567 | (add-hook 'gnus-summary-mode-hook 'nnir-mode) | ||
| 482 | (nnoo-change-server 'nnir server definitions)) | 568 | (nnoo-change-server 'nnir server definitions)) |
| 483 | 569 | ||
| 484 | (deffoo nnir-request-group (group &optional server fast info) | 570 | (deffoo nnir-request-group (group &optional server fast info) |
| @@ -506,77 +592,76 @@ result, `gnus-retrieve-headers' will be called instead.") | |||
| 506 | group)))) ; group name | 592 | group)))) ; group name |
| 507 | 593 | ||
| 508 | (deffoo nnir-retrieve-headers (articles &optional group server fetch-old) | 594 | (deffoo nnir-retrieve-headers (articles &optional group server fetch-old) |
| 509 | (save-excursion | 595 | (with-current-buffer nntp-server-buffer |
| 510 | (let ((artlist (copy-sequence articles)) | 596 | (let ((gnus-inhibit-demon t) |
| 511 | art artitem artgroup artno artrsv artfullgroup | 597 | (articles-by-group (nnir-categorize |
| 512 | novitem novdata foo server) | 598 | articles nnir-article-group nnir-article-ids)) |
| 513 | (while (not (null artlist)) | 599 | headers) |
| 514 | (setq art (car artlist)) | 600 | (while (not (null articles-by-group)) |
| 515 | (or (numberp art) | 601 | (let* ((group-articles (pop articles-by-group)) |
| 516 | (nnheader-report | 602 | (artgroup (car group-articles)) |
| 517 | 'nnir | 603 | (articleids (cadr group-articles)) |
| 518 | "nnir-retrieve-headers doesn't grok message ids: %s" | 604 | (artlist (sort (mapcar 'cdr articleids) '<)) |
| 519 | art)) | 605 | (server (gnus-group-server artgroup)) |
| 520 | (setq artitem (nnir-artlist-article nnir-artlist art)) | 606 | (gnus-override-method (gnus-server-to-method server)) |
| 521 | (setq artrsv (nnir-artitem-rsv artitem)) | 607 | parsefunc) |
| 522 | (setq artfullgroup (nnir-artitem-group artitem)) | 608 | ;; (or (numberp art) |
| 523 | (setq artno (nnir-artitem-number artitem)) | 609 | ;; (nnheader-report |
| 524 | (setq artgroup (gnus-group-real-name artfullgroup)) | 610 | ;; 'nnir |
| 525 | (setq server (gnus-group-server artfullgroup)) | 611 | ;; "nnir-retrieve-headers doesn't grok message ids: %s" |
| 526 | ;; retrieve NOV or HEAD data for this article, transform into | 612 | ;; art)) |
| 527 | ;; NOV data and prepend to `novdata' | 613 | (nnir-possibly-change-server server) |
| 528 | (set-buffer nntp-server-buffer) | 614 | ;; is this needed? |
| 529 | (nnir-possibly-change-server server) | 615 | (erase-buffer) |
| 530 | (let ((gnus-override-method | 616 | (case (setq gnus-headers-retrieved-by |
| 531 | (gnus-server-to-method server))) | 617 | (or |
| 532 | ;; if nnir-get-article-nov-override-function is set, use it | 618 | (and |
| 533 | (if nnir-get-article-nov-override-function | 619 | nnir-retrieve-headers-override-function |
| 534 | (setq novitem (funcall nnir-get-article-nov-override-function | 620 | (funcall nnir-retrieve-headers-override-function |
| 535 | artitem)) | 621 | artlist artgroup)) |
| 536 | ;; else, set novitem through nnheader-parse-nov/nnheader-parse-head | 622 | (gnus-retrieve-headers artlist artgroup nil))) |
| 537 | (case (setq foo (gnus-retrieve-headers (list artno) | 623 | (nov |
| 538 | artfullgroup nil)) | 624 | (setq parsefunc 'nnheader-parse-nov)) |
| 539 | (nov | 625 | (headers |
| 540 | (goto-char (point-min)) | 626 | (setq parsefunc 'nnheader-parse-head)) |
| 541 | (setq novitem (nnheader-parse-nov))) | 627 | (t (error "Unknown header type %s while requesting articles \ |
| 542 | (headers | 628 | of group %s" gnus-headers-retrieved-by artgroup))) |
| 543 | (goto-char (point-min)) | 629 | (goto-char (point-min)) |
| 544 | (setq novitem (nnheader-parse-head))) | 630 | (while (not (eobp)) |
| 545 | (t (error "Unknown header type %s while requesting article %s of group %s" | 631 | (let* ((novitem (funcall parsefunc)) |
| 546 | foo artno artfullgroup))))) | 632 | (artno (mail-header-number novitem)) |
| 547 | ;; replace article number in original group with article number | 633 | (art (car (rassoc artno articleids)))) |
| 548 | ;; in nnir group | 634 | (when art |
| 549 | (when novitem | 635 | (mail-header-set-number novitem art) |
| 550 | (mail-header-set-number novitem art) | 636 | ;; (mail-header-set-subject |
| 551 | (mail-header-set-subject | 637 | ;; novitem |
| 552 | novitem | 638 | ;; (format "[%d: %s/%d] %s" |
| 553 | (format "[%d: %s/%d] %s" | 639 | ;; (nnir-article-rsv art) artgroup artno |
| 554 | artrsv artgroup artno | 640 | ;; (mail-header-subject novitem))) |
| 555 | (mail-header-subject novitem))) | 641 | (push novitem headers)) |
| 556 | (push novitem novdata) | 642 | (forward-line 1))))) |
| 557 | (setq artlist (cdr artlist)))) | 643 | (setq headers |
| 558 | (setq novdata (nreverse novdata)) | 644 | (sort headers |
| 559 | (set-buffer nntp-server-buffer) (erase-buffer) | 645 | (lambda (x y) |
| 560 | (mapc 'nnheader-insert-nov novdata) | 646 | (< (mail-header-number x) (mail-header-number y))))) |
| 647 | (erase-buffer) | ||
| 648 | (mapc 'nnheader-insert-nov headers) | ||
| 561 | 'nov))) | 649 | 'nov))) |
| 562 | 650 | ||
| 563 | (deffoo nnir-request-article (article | 651 | (deffoo nnir-request-article (article &optional group server to-buffer) |
| 564 | &optional group server to-buffer) | ||
| 565 | (if (stringp article) | 652 | (if (stringp article) |
| 566 | (nnheader-report | 653 | (nnheader-report |
| 567 | 'nnir | 654 | 'nnir |
| 568 | "nnir-retrieve-headers doesn't grok message ids: %s" | 655 | "nnir-retrieve-headers doesn't grok message ids: %s" |
| 569 | article) | 656 | article) |
| 570 | (save-excursion | 657 | (save-excursion |
| 571 | (let* ((artitem (nnir-artlist-article nnir-artlist | 658 | (let ((artfullgroup (nnir-article-group article)) |
| 572 | article)) | 659 | (artno (nnir-article-number article)) |
| 573 | (artfullgroup (nnir-artitem-group artitem)) | 660 | ;; Bug? |
| 574 | (artno (nnir-artitem-number artitem)) | 661 | ;; Why must we bind nntp-server-buffer here? It won't |
| 575 | ;; Bug? | 662 | ;; work if `buf' is used, say. (Of course, the set-buffer |
| 576 | ;; Why must we bind nntp-server-buffer here? It won't | 663 | ;; line below must then be updated, too.) |
| 577 | ;; work if `buf' is used, say. (Of course, the set-buffer | 664 | (nntp-server-buffer (or to-buffer nntp-server-buffer))) |
| 578 | ;; line below must then be updated, too.) | ||
| 579 | (nntp-server-buffer (or to-buffer nntp-server-buffer))) | ||
| 580 | (set-buffer nntp-server-buffer) | 665 | (set-buffer nntp-server-buffer) |
| 581 | (erase-buffer) | 666 | (erase-buffer) |
| 582 | (message "Requesting article %d from group %s" | 667 | (message "Requesting article %d from group %s" |
| @@ -586,10 +671,8 @@ result, `gnus-retrieve-headers' will be called instead.") | |||
| 586 | 671 | ||
| 587 | (deffoo nnir-request-move-article (article group server accept-form | 672 | (deffoo nnir-request-move-article (article group server accept-form |
| 588 | &optional last internal-move-group) | 673 | &optional last internal-move-group) |
| 589 | (let* ((artitem (nnir-artlist-article nnir-artlist | 674 | (let* ((artfullgroup (nnir-article-group article)) |
| 590 | article)) | 675 | (artno (nnir-article-number article)) |
| 591 | (artfullgroup (nnir-artitem-group artitem)) | ||
| 592 | (artno (nnir-artitem-number artitem)) | ||
| 593 | (to-newsgroup (nth 1 accept-form)) | 676 | (to-newsgroup (nth 1 accept-form)) |
| 594 | (to-method (gnus-find-method-for-group to-newsgroup)) | 677 | (to-method (gnus-find-method-for-group to-newsgroup)) |
| 595 | (from-method (gnus-find-method-for-group artfullgroup)) | 678 | (from-method (gnus-find-method-for-group artfullgroup)) |
| @@ -597,9 +680,9 @@ result, `gnus-retrieve-headers' will be called instead.") | |||
| 597 | (artsubject (mail-header-subject | 680 | (artsubject (mail-header-subject |
| 598 | (gnus-data-header | 681 | (gnus-data-header |
| 599 | (assoc article (gnus-data-list nil)))))) | 682 | (assoc article (gnus-data-list nil)))))) |
| 600 | (setq gnus-newsgroup-original-name artfullgroup) | 683 | (unless (gnus-check-backend-function |
| 601 | (string-match "^\\[[0-9]+:.+/[0-9]+\\] " artsubject) | 684 | 'request-move-article artfullgroup) |
| 602 | (setq gnus-article-original-subject (substring artsubject (match-end 0))) | 685 | (error "The group %s does not support article moving" artfullgroup)) |
| 603 | (gnus-request-move-article | 686 | (gnus-request-move-article |
| 604 | artno | 687 | artno |
| 605 | artfullgroup | 688 | artfullgroup |
| @@ -614,8 +697,8 @@ result, `gnus-retrieve-headers' will be called instead.") | |||
| 614 | (let* ((cur (if (> (gnus-summary-article-number) 0) | 697 | (let* ((cur (if (> (gnus-summary-article-number) 0) |
| 615 | (gnus-summary-article-number) | 698 | (gnus-summary-article-number) |
| 616 | (error "This is not a real article."))) | 699 | (error "This is not a real article."))) |
| 617 | (gnus-newsgroup-name (nnir-artlist-artitem-group nnir-artlist cur)) | 700 | (gnus-newsgroup-name (nnir-article-group cur)) |
| 618 | (backend-number (nnir-artlist-artitem-number nnir-artlist cur))) | 701 | (backend-number (nnir-article-number cur))) |
| 619 | (gnus-summary-read-group-1 gnus-newsgroup-name t t gnus-summary-buffer | 702 | (gnus-summary-read-group-1 gnus-newsgroup-name t t gnus-summary-buffer |
| 620 | nil (list backend-number)))) | 703 | nil (list backend-number)))) |
| 621 | 704 | ||
| @@ -654,7 +737,7 @@ ready to be added to the list of search results." | |||
| 654 | (gnus-replace-in-string dirnam "^[./\\]" "" t) | 737 | (gnus-replace-in-string dirnam "^[./\\]" "" t) |
| 655 | "[/\\]" "." t))) | 738 | "[/\\]" "." t))) |
| 656 | 739 | ||
| 657 | (vector (nnir-group-full-name group server) | 740 | (vector (gnus-group-full-name group server) |
| 658 | (if (string= (gnus-group-server server) "nnmaildir") | 741 | (if (string= (gnus-group-server server) "nnmaildir") |
| 659 | (nnmaildir-base-name-to-article-number | 742 | (nnmaildir-base-name-to-article-number |
| 660 | (substring article 0 (string-match ":" article)) | 743 | (substring article 0 (string-match ":" article)) |
| @@ -696,7 +779,7 @@ details on the language and supported extensions" | |||
| 696 | (nnir-imap-make-query | 779 | (nnir-imap-make-query |
| 697 | criteria qstring))))) | 780 | criteria qstring))))) |
| 698 | (mapc | 781 | (mapc |
| 699 | (lambda (artnum) (push (vector group artnum 1) artlist) | 782 | (lambda (artnum) (push (vector group artnum 100) artlist) |
| 700 | (setq arts (1+ arts))) | 783 | (setq arts (1+ arts))) |
| 701 | (and (car result) | 784 | (and (car result) |
| 702 | (delete 0 (mapcar #'string-to-number | 785 | (delete 0 (mapcar #'string-to-number |
| @@ -1056,7 +1139,7 @@ Tested with swish-e-2.0.1 on Windows NT 4.0." | |||
| 1056 | ;; Windows "\\" -> "." | 1139 | ;; Windows "\\" -> "." |
| 1057 | (setq group (gnus-replace-in-string group "\\\\" ".")) | 1140 | (setq group (gnus-replace-in-string group "\\\\" ".")) |
| 1058 | 1141 | ||
| 1059 | (push (vector (nnir-group-full-name group server) | 1142 | (push (vector (gnus-group-full-name group server) |
| 1060 | (string-to-number artno) | 1143 | (string-to-number artno) |
| 1061 | (string-to-number score)) | 1144 | (string-to-number score)) |
| 1062 | artlist)))) | 1145 | artlist)))) |
| @@ -1125,7 +1208,7 @@ Tested with swish-e-2.0.1 on Windows NT 4.0." | |||
| 1125 | score (match-string 3)) | 1208 | score (match-string 3)) |
| 1126 | (when (string-match prefix dirnam) | 1209 | (when (string-match prefix dirnam) |
| 1127 | (setq dirnam (replace-match "" t t dirnam))) | 1210 | (setq dirnam (replace-match "" t t dirnam))) |
| 1128 | (push (vector (nnir-group-full-name | 1211 | (push (vector (gnus-group-full-name |
| 1129 | (gnus-replace-in-string dirnam "/" ".") server) | 1212 | (gnus-replace-in-string dirnam "/" ".") server) |
| 1130 | (string-to-number artno) | 1213 | (string-to-number artno) |
| 1131 | (string-to-number score)) | 1214 | (string-to-number score)) |
| @@ -1218,6 +1301,7 @@ Tested with Namazu 2.0.6 on a GNU/Linux system." | |||
| 1218 | (directory (cadr (assoc sym (cddr method)))) | 1301 | (directory (cadr (assoc sym (cddr method)))) |
| 1219 | (regexp (cdr (assoc 'query query))) | 1302 | (regexp (cdr (assoc 'query query))) |
| 1220 | (grep-options (cdr (assoc 'grep-options query))) | 1303 | (grep-options (cdr (assoc 'grep-options query))) |
| 1304 | (grouplist (or grouplist (nnir-get-active server))) | ||
| 1221 | artlist) | 1305 | artlist) |
| 1222 | (unless directory | 1306 | (unless directory |
| 1223 | (error "No directory found in method specification of server %s" | 1307 | (error "No directory found in method specification of server %s" |
| @@ -1283,7 +1367,7 @@ Tested with Namazu 2.0.6 on a GNU/Linux system." | |||
| 1283 | (nreverse res)) | 1367 | (nreverse res)) |
| 1284 | "."))) | 1368 | "."))) |
| 1285 | (push | 1369 | (push |
| 1286 | (vector (nnir-group-full-name group server) art 0) | 1370 | (vector (gnus-group-full-name group server) art 0) |
| 1287 | artlist)) | 1371 | artlist)) |
| 1288 | (forward-line 1))) | 1372 | (forward-line 1))) |
| 1289 | (message "Searching %s using find-grep...done" | 1373 | (message "Searching %s using find-grep...done" |
| @@ -1297,15 +1381,14 @@ Tested with Namazu 2.0.6 on a GNU/Linux system." | |||
| 1297 | ;; gmane interface | 1381 | ;; gmane interface |
| 1298 | (defun nnir-run-gmane (query srv &optional groups) | 1382 | (defun nnir-run-gmane (query srv &optional groups) |
| 1299 | "Run a search against a gmane back-end server." | 1383 | "Run a search against a gmane back-end server." |
| 1300 | (if (gnus-string-match-p "gmane" srv) | 1384 | (if (gnus-string-match-p "gmane.org$" srv) |
| 1301 | (let* ((case-fold-search t) | 1385 | (let* ((case-fold-search t) |
| 1302 | (qstring (cdr (assq 'query query))) | 1386 | (qstring (cdr (assq 'query query))) |
| 1303 | (server (cadr (gnus-server-to-method srv))) | 1387 | (server (cadr (gnus-server-to-method srv))) |
| 1304 | (groupspec (if groups | 1388 | (groupspec (if groups |
| 1305 | (mapconcat | 1389 | (mapconcat |
| 1306 | (function (lambda (x) | 1390 | (lambda (x) |
| 1307 | (format "group:%s" | 1391 | (format "group:%s" (gnus-group-short-name x))) |
| 1308 | (gnus-group-short-name x)))) | ||
| 1309 | groups " ") "")) | 1392 | groups " ") "")) |
| 1310 | (authorspec | 1393 | (authorspec |
| 1311 | (if (assq 'author query) | 1394 | (if (assq 'author query) |
| @@ -1341,12 +1424,7 @@ Tested with Namazu 2.0.6 on a GNU/Linux system." | |||
| 1341 | (string-to-number (match-string 2 xref)) xscore) | 1424 | (string-to-number (match-string 2 xref)) xscore) |
| 1342 | artlist))))) | 1425 | artlist))))) |
| 1343 | (forward-line 1))) | 1426 | (forward-line 1))) |
| 1344 | ;; Sort by score | 1427 | (apply 'vector (nreverse (mm-delete-duplicates artlist)))) |
| 1345 | (apply 'vector | ||
| 1346 | (sort artlist | ||
| 1347 | (function (lambda (x y) | ||
| 1348 | (> (nnir-artitem-rsv x) | ||
| 1349 | (nnir-artitem-rsv y))))))) | ||
| 1350 | (message "Can't search non-gmane nntp groups") | 1428 | (message "Can't search non-gmane nntp groups") |
| 1351 | nil)) | 1429 | nil)) |
| 1352 | 1430 | ||
| @@ -1380,33 +1458,34 @@ Tested with Namazu 2.0.6 on a GNU/Linux system." | |||
| 1380 | (groups (if (string= "all-ephemeral" nserver) | 1458 | (groups (if (string= "all-ephemeral" nserver) |
| 1381 | (with-current-buffer gnus-server-buffer | 1459 | (with-current-buffer gnus-server-buffer |
| 1382 | (list (list (gnus-server-server-name)))) | 1460 | (list (list (gnus-server-server-name)))) |
| 1383 | (nnir-sort-groups-by-server | 1461 | (nnir-categorize |
| 1384 | (or gnus-group-marked | 1462 | (or gnus-group-marked |
| 1385 | (if (gnus-group-group-name) | 1463 | (if (gnus-group-group-name) |
| 1386 | (list (gnus-group-group-name)) | 1464 | (list (gnus-group-group-name)) |
| 1387 | (cdr (assoc (gnus-group-topic-name) | 1465 | (cdr (assoc (gnus-group-topic-name) |
| 1388 | gnus-topic-alist)))))))) | 1466 | gnus-topic-alist)))) |
| 1467 | gnus-group-server)))) | ||
| 1389 | (apply 'vconcat | 1468 | (apply 'vconcat |
| 1390 | (mapcar (lambda (x) | 1469 | (mapcar |
| 1391 | (let* ((server (car x)) | 1470 | (lambda (x) |
| 1392 | (nnir-search-engine | 1471 | (let* ((server (car x)) |
| 1393 | (or (nnir-read-server-parm 'nnir-search-engine | 1472 | (nnir-search-engine |
| 1394 | server) | 1473 | (or (nnir-read-server-parm 'nnir-search-engine |
| 1395 | (cdr (assoc (car | 1474 | server) |
| 1396 | (gnus-server-to-method server)) | 1475 | (cdr (assoc (car |
| 1397 | nnir-method-default-engines)))) | 1476 | (gnus-server-to-method server)) |
| 1398 | search-func) | 1477 | nnir-method-default-engines)))) |
| 1399 | (setq search-func (cadr | 1478 | search-func) |
| 1400 | (assoc nnir-search-engine | 1479 | (setq search-func (cadr (assoc nnir-search-engine |
| 1401 | nnir-engines))) | 1480 | nnir-engines))) |
| 1402 | (if search-func | 1481 | (if search-func |
| 1403 | (funcall search-func | 1482 | (funcall search-func |
| 1404 | (if nnir-extra-parms | 1483 | (if nnir-extra-parms |
| 1405 | (nnir-read-parms q nnir-search-engine) | 1484 | (nnir-read-parms q nnir-search-engine) |
| 1406 | q) | 1485 | q) |
| 1407 | server (cdr x)) | 1486 | server (cadr x)) |
| 1408 | nil))) | 1487 | nil))) |
| 1409 | groups)))) | 1488 | groups)))) |
| 1410 | 1489 | ||
| 1411 | (defun nnir-read-server-parm (key server) | 1490 | (defun nnir-read-server-parm (key server) |
| 1412 | "Returns the parameter value of key for the given server, where | 1491 | "Returns the parameter value of key for the given server, where |
| @@ -1416,50 +1495,11 @@ server is of form 'backend:name'." | |||
| 1416 | (nth 1 (assq key (cddr method)))) | 1495 | (nth 1 (assq key (cddr method)))) |
| 1417 | (t nil)))) | 1496 | (t nil)))) |
| 1418 | 1497 | ||
| 1419 | (defun nnir-group-full-name (shortname server) | ||
| 1420 | "For the given group name, return a full Gnus group name. | ||
| 1421 | The Gnus backend/server information is added." | ||
| 1422 | (gnus-group-prefixed-name shortname (gnus-server-to-method server))) | ||
| 1423 | |||
| 1424 | (defun nnir-possibly-change-server (server) | 1498 | (defun nnir-possibly-change-server (server) |
| 1425 | (unless (and server (nnir-server-opened server)) | 1499 | (unless (and server (nnir-server-opened server)) |
| 1426 | (nnir-open-server server))) | 1500 | (nnir-open-server server))) |
| 1427 | 1501 | ||
| 1428 | 1502 | ||
| 1429 | ;; Data type article list. | ||
| 1430 | |||
| 1431 | (defun nnir-artlist-length (artlist) | ||
| 1432 | "Returns number of articles in artlist." | ||
| 1433 | (length artlist)) | ||
| 1434 | |||
| 1435 | (defun nnir-artlist-article (artlist n) | ||
| 1436 | "Returns from ARTLIST the Nth artitem (counting starting at 1)." | ||
| 1437 | (elt artlist (1- n))) | ||
| 1438 | |||
| 1439 | (defun nnir-artitem-group (artitem) | ||
| 1440 | "Returns the group from the ARTITEM." | ||
| 1441 | (elt artitem 0)) | ||
| 1442 | |||
| 1443 | (defun nnir-artlist-artitem-group (artlist n) | ||
| 1444 | "Returns from ARTLIST the group of the Nth artitem (counting from 1)." | ||
| 1445 | (nnir-artitem-group (nnir-artlist-article artlist n))) | ||
| 1446 | |||
| 1447 | (defun nnir-artitem-number (artitem) | ||
| 1448 | "Returns the number from the ARTITEM." | ||
| 1449 | (elt artitem 1)) | ||
| 1450 | |||
| 1451 | (defun nnir-artlist-artitem-number (artlist n) | ||
| 1452 | "Returns from ARTLIST the number of the Nth artitem (counting from 1)." | ||
| 1453 | (nnir-artitem-number (nnir-artlist-article artlist n))) | ||
| 1454 | |||
| 1455 | (defun nnir-artitem-rsv (artitem) | ||
| 1456 | "Returns the Retrieval Status Value (RSV, score) from the ARTITEM." | ||
| 1457 | (elt artitem 2)) | ||
| 1458 | |||
| 1459 | (defun nnir-artlist-artitem-rsv (artlist n) | ||
| 1460 | "Returns from ARTLIST the Retrieval Status Value of the Nth | ||
| 1461 | artitem (counting from 1)." | ||
| 1462 | (nnir-artitem-rsv (nnir-artlist-article artlist n))) | ||
| 1463 | 1503 | ||
| 1464 | ;; unused? | 1504 | ;; unused? |
| 1465 | (defun nnir-artlist-groups (artlist) | 1505 | (defun nnir-artlist-groups (artlist) |
| @@ -1473,18 +1513,6 @@ artitem (counting from 1)." | |||
| 1473 | with-dups) | 1513 | with-dups) |
| 1474 | res)) | 1514 | res)) |
| 1475 | 1515 | ||
| 1476 | (defun nnir-sort-groups-by-server (groups) | ||
| 1477 | "sorts a list of groups into an alist keyed by server" | ||
| 1478 | (if (car groups) | ||
| 1479 | (let (value) | ||
| 1480 | (dolist (var groups value) | ||
| 1481 | (let ((server (gnus-group-server var))) | ||
| 1482 | (if (assoc server value) | ||
| 1483 | (nconc (cdr (assoc server value)) (list var)) | ||
| 1484 | (push (cons server (list var)) value)))) | ||
| 1485 | value) | ||
| 1486 | nil)) | ||
| 1487 | |||
| 1488 | (defun nnir-get-active (srv) | 1516 | (defun nnir-get-active (srv) |
| 1489 | (let ((method (gnus-server-to-method srv)) | 1517 | (let ((method (gnus-server-to-method srv)) |
| 1490 | groups) | 1518 | groups) |
| @@ -1493,19 +1521,59 @@ artitem (counting from 1)." | |||
| 1493 | (let ((cur (current-buffer)) | 1521 | (let ((cur (current-buffer)) |
| 1494 | name) | 1522 | name) |
| 1495 | (goto-char (point-min)) | 1523 | (goto-char (point-min)) |
| 1496 | (unless (string= gnus-ignored-newsgroups "") | 1524 | (unless (string= nnir-ignored-newsgroups "") |
| 1497 | (delete-matching-lines gnus-ignored-newsgroups)) | 1525 | (delete-matching-lines nnir-ignored-newsgroups)) |
| 1498 | (while (not (eobp)) | 1526 | (if (eq (car method) 'nntp) |
| 1499 | (ignore-errors | 1527 | (while (not (eobp)) |
| 1500 | (push (mm-string-as-unibyte | 1528 | (ignore-errors |
| 1501 | (let ((p (point))) | 1529 | (push (mm-string-as-unibyte |
| 1502 | (skip-chars-forward "^ \t\\\\") | 1530 | (gnus-group-full-name |
| 1503 | (setq name (buffer-substring (+ p 1) (- (point) 1))) | 1531 | (buffer-substring |
| 1504 | (gnus-group-full-name name method))) | 1532 | (point) |
| 1505 | groups)) | 1533 | (progn |
| 1506 | (forward-line)))) | 1534 | (skip-chars-forward "^ \t") |
| 1535 | (point))) method)) | ||
| 1536 | groups)) | ||
| 1537 | (forward-line)) | ||
| 1538 | (while (not (eobp)) | ||
| 1539 | (ignore-errors | ||
| 1540 | (push (mm-string-as-unibyte | ||
| 1541 | (if (eq (char-after) ?\") | ||
| 1542 | (gnus-group-full-name (read cur) method) | ||
| 1543 | (let ((p (point)) (name "")) | ||
| 1544 | (skip-chars-forward "^ \t\\\\") | ||
| 1545 | (setq name (buffer-substring p (point))) | ||
| 1546 | (while (eq (char-after) ?\\) | ||
| 1547 | (setq p (1+ (point))) | ||
| 1548 | (forward-char 2) | ||
| 1549 | (skip-chars-forward "^ \t\\\\") | ||
| 1550 | (setq name (concat name (buffer-substring | ||
| 1551 | p (point))))) | ||
| 1552 | (gnus-group-full-name name method)))) | ||
| 1553 | groups)) | ||
| 1554 | (forward-line))))) | ||
| 1507 | groups)) | 1555 | groups)) |
| 1508 | 1556 | ||
| 1557 | (defun nnir-registry-action (action data-header from &optional to method) | ||
| 1558 | "Call `gnus-registry-action' with the original article group." | ||
| 1559 | (gnus-registry-action | ||
| 1560 | action | ||
| 1561 | data-header | ||
| 1562 | (nnir-article-group (mail-header-number data-header)) | ||
| 1563 | to | ||
| 1564 | method)) | ||
| 1565 | |||
| 1566 | (defun nnir-mode () | ||
| 1567 | (when (eq (car (gnus-find-method-for-group gnus-newsgroup-name)) 'nnir) | ||
| 1568 | (setq gnus-summary-line-format | ||
| 1569 | (or nnir-summary-line-format gnus-summary-line-format)) | ||
| 1570 | (remove-hook 'gnus-summary-article-delete-hook 'gnus-registry-action t) | ||
| 1571 | (remove-hook 'gnus-summary-article-move-hook 'gnus-registry-action t) | ||
| 1572 | (add-hook 'gnus-summary-article-delete-hook 'nnir-registry-action t t) | ||
| 1573 | (add-hook 'gnus-summary-article-move-hook 'nnir-registry-action t t))) | ||
| 1574 | |||
| 1575 | |||
| 1576 | |||
| 1509 | ;; The end. | 1577 | ;; The end. |
| 1510 | (provide 'nnir) | 1578 | (provide 'nnir) |
| 1511 | 1579 | ||
diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el index 65f33411297..8e2cd4bdde3 100644 --- a/lisp/gnus/nnmaildir.el +++ b/lisp/gnus/nnmaildir.el | |||
| @@ -1559,7 +1559,7 @@ by nnmaildir-request-article.") | |||
| 1559 | (t (signal (car err) (cdr err)))))) | 1559 | (t (signal (car err) (cdr err)))))) |
| 1560 | todo-marks)) | 1560 | todo-marks)) |
| 1561 | set-action (lambda (article) | 1561 | set-action (lambda (article) |
| 1562 | (funcall add-action) | 1562 | (funcall add-action article) |
| 1563 | (mapcar (lambda (mark) | 1563 | (mapcar (lambda (mark) |
| 1564 | (unless (memq mark todo-marks) | 1564 | (unless (memq mark todo-marks) |
| 1565 | (funcall del-mark mark))) | 1565 | (funcall del-mark mark))) |
diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el index f37a1c8c48f..6504f05c9d2 100644 --- a/lisp/gnus/nntp.el +++ b/lisp/gnus/nntp.el | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | (require 'nnoo) | 34 | (require 'nnoo) |
| 35 | (require 'gnus-util) | 35 | (require 'gnus-util) |
| 36 | (require 'gnus) | 36 | (require 'gnus) |
| 37 | (require 'proto-stream) | ||
| 37 | (require 'gnus-group) ;; gnus-group-name-charset | 38 | (require 'gnus-group) ;; gnus-group-name-charset |
| 38 | 39 | ||
| 39 | (nnoo-declare nntp) | 40 | (nnoo-declare nntp) |
| @@ -305,13 +306,6 @@ update their active files often, this can help.") | |||
| 305 | (defvar nntp-async-timer nil) | 306 | (defvar nntp-async-timer nil) |
| 306 | (defvar nntp-async-process-list nil) | 307 | (defvar nntp-async-process-list nil) |
| 307 | 308 | ||
| 308 | (defvar nntp-ssl-program | ||
| 309 | "openssl s_client -quiet -ssl3 -connect %s:%p" | ||
| 310 | "A string containing commands for SSL connections. | ||
| 311 | Within a string, %s is replaced with the server address and %p with | ||
| 312 | port number on server. The program should accept IMAP commands on | ||
| 313 | stdin and return responses to stdout.") | ||
| 314 | |||
| 315 | (defvar nntp-authinfo-rejected nil | 309 | (defvar nntp-authinfo-rejected nil |
| 316 | "A custom error condition used to report 'Authentication Rejected' errors. | 310 | "A custom error condition used to report 'Authentication Rejected' errors. |
| 317 | Condition handlers that match just this condition ensure that the nntp | 311 | Condition handlers that match just this condition ensure that the nntp |
| @@ -1268,11 +1262,28 @@ password contained in '~/.nntp-authinfo'." | |||
| 1268 | `(lambda () | 1262 | `(lambda () |
| 1269 | (nntp-kill-buffer ,pbuffer))))) | 1263 | (nntp-kill-buffer ,pbuffer))))) |
| 1270 | (process | 1264 | (process |
| 1271 | (condition-case () | 1265 | (condition-case err |
| 1272 | (let ((coding-system-for-read nntp-coding-system-for-read) | 1266 | (let ((coding-system-for-read nntp-coding-system-for-read) |
| 1273 | (coding-system-for-write nntp-coding-system-for-write)) | 1267 | (coding-system-for-write nntp-coding-system-for-write) |
| 1274 | (funcall nntp-open-connection-function pbuffer)) | 1268 | (map '((nntp-open-network-stream network) |
| 1275 | (error nil) | 1269 | (nntp-open-ssl-stream tls) |
| 1270 | (nntp-open-tls-stream tls)))) | ||
| 1271 | (if (assoc nntp-open-connection-function map) | ||
| 1272 | (car (open-protocol-stream | ||
| 1273 | "nntpd" pbuffer nntp-address nntp-port-number | ||
| 1274 | :type (cadr | ||
| 1275 | (assoc nntp-open-connection-function map)) | ||
| 1276 | :end-of-command "^\\([2345]\\|[.]\\).*\n" | ||
| 1277 | :capability-command "CAPABILITIES\r\n" | ||
| 1278 | :success "^3" | ||
| 1279 | :starttls-function | ||
| 1280 | (lambda (capabilities) | ||
| 1281 | (if (not (string-match "STARTTLS" capabilities)) | ||
| 1282 | nil | ||
| 1283 | "STARTTLS\r\n")))) | ||
| 1284 | (funcall nntp-open-connection-function pbuffer))) | ||
| 1285 | (error | ||
| 1286 | (nnheader-report 'nntp "%s" err)) | ||
| 1276 | (quit | 1287 | (quit |
| 1277 | (message "Quit opening connection to %s" nntp-address) | 1288 | (message "Quit opening connection to %s" nntp-address) |
| 1278 | (nntp-kill-buffer pbuffer) | 1289 | (nntp-kill-buffer pbuffer) |
| @@ -1300,40 +1311,6 @@ password contained in '~/.nntp-authinfo'." | |||
| 1300 | (nntp-kill-buffer (process-buffer process)) | 1311 | (nntp-kill-buffer (process-buffer process)) |
| 1301 | nil)))) | 1312 | nil)))) |
| 1302 | 1313 | ||
| 1303 | (defun nntp-open-network-stream (buffer) | ||
| 1304 | (open-network-stream "nntpd" buffer nntp-address nntp-port-number)) | ||
| 1305 | |||
| 1306 | (autoload 'format-spec "format-spec") | ||
| 1307 | (autoload 'format-spec-make "format-spec") | ||
| 1308 | (autoload 'open-tls-stream "tls") | ||
| 1309 | |||
| 1310 | (defun nntp-open-ssl-stream (buffer) | ||
| 1311 | (let* ((process-connection-type nil) | ||
| 1312 | (proc (start-process "nntpd" buffer | ||
| 1313 | shell-file-name | ||
| 1314 | shell-command-switch | ||
| 1315 | (format-spec nntp-ssl-program | ||
| 1316 | (format-spec-make | ||
| 1317 | ?s nntp-address | ||
| 1318 | ?p nntp-port-number))))) | ||
| 1319 | (gnus-set-process-query-on-exit-flag proc nil) | ||
| 1320 | (with-current-buffer buffer | ||
| 1321 | (let ((nntp-connection-alist (list proc buffer nil))) | ||
| 1322 | (nntp-wait-for-string "^\r*20[01]")) | ||
| 1323 | (beginning-of-line) | ||
| 1324 | (delete-region (point-min) (point)) | ||
| 1325 | proc))) | ||
| 1326 | |||
| 1327 | (defun nntp-open-tls-stream (buffer) | ||
| 1328 | (let ((proc (open-tls-stream "nntpd" buffer nntp-address nntp-port-number))) | ||
| 1329 | (gnus-set-process-query-on-exit-flag proc nil) | ||
| 1330 | (with-current-buffer buffer | ||
| 1331 | (let ((nntp-connection-alist (list proc buffer nil))) | ||
| 1332 | (nntp-wait-for-string "^\r*20[01]")) | ||
| 1333 | (beginning-of-line) | ||
| 1334 | (delete-region (point-min) (point)) | ||
| 1335 | proc))) | ||
| 1336 | |||
| 1337 | (defun nntp-read-server-type () | 1314 | (defun nntp-read-server-type () |
| 1338 | "Find out what the name of the server we have connected to is." | 1315 | "Find out what the name of the server we have connected to is." |
| 1339 | ;; Wait for the status string to arrive. | 1316 | ;; Wait for the status string to arrive. |
diff --git a/lisp/gnus/proto-stream.el b/lisp/gnus/proto-stream.el new file mode 100644 index 00000000000..d402a876456 --- /dev/null +++ b/lisp/gnus/proto-stream.el | |||
| @@ -0,0 +1,262 @@ | |||
| 1 | ;;; proto-stream.el --- negotiating TLS, STARTTLS and other connections | ||
| 2 | ;; Copyright (C) 2010 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 5 | ;; Keywords: network | ||
| 6 | |||
| 7 | ;; This file is part of GNU Emacs. | ||
| 8 | |||
| 9 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;; the Free Software Foundation; either version 3, or (at your option) | ||
| 12 | ;; any later version. | ||
| 13 | |||
| 14 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;; GNU General Public License for more details. | ||
| 18 | |||
| 19 | ;; You should have received a copy of the GNU General Public License | ||
| 20 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
| 22 | ;; Boston, MA 02110-1301, USA. | ||
| 23 | |||
| 24 | ;;; Commentary: | ||
| 25 | |||
| 26 | ;; This library is meant to provide the glue between modules that want | ||
| 27 | ;; to establish a network connection to a server for protocols such as | ||
| 28 | ;; IMAP, NNTP, SMTP and POP3. | ||
| 29 | |||
| 30 | ;; The main problem is that there's more than a couple of interfaces | ||
| 31 | ;; towards doing this. You have normal, plain connections, which are | ||
| 32 | ;; no trouble at all, but you also have TLS/SSL connections, and you | ||
| 33 | ;; have STARTTLS. Negotiating this for each protocol can be rather | ||
| 34 | ;; tedious, so this library provides a single entry point, and hides | ||
| 35 | ;; much of the ugliness. | ||
| 36 | |||
| 37 | ;; Usage example: | ||
| 38 | |||
| 39 | ;; (open-protocol-stream | ||
| 40 | ;; "*nnimap*" buffer address port | ||
| 41 | ;; :type 'network | ||
| 42 | ;; :capability-command "1 CAPABILITY\r\n" | ||
| 43 | ;; :success " OK " | ||
| 44 | ;; :starttls-function | ||
| 45 | ;; (lambda (capabilities) | ||
| 46 | ;; (if (not (string-match "STARTTLS" capabilities)) | ||
| 47 | ;; nil | ||
| 48 | ;; "1 STARTTLS\r\n"))) | ||
| 49 | |||
| 50 | ;;; Code: | ||
| 51 | |||
| 52 | (eval-when-compile | ||
| 53 | (require 'cl)) | ||
| 54 | (require 'tls) | ||
| 55 | (require 'starttls) | ||
| 56 | (require 'format-spec) | ||
| 57 | |||
| 58 | (defcustom proto-stream-always-use-starttls (fboundp 'open-gnutls-stream) | ||
| 59 | "If non-nil, always try to upgrade network connections with STARTTLS." | ||
| 60 | :version "24.1" | ||
| 61 | :type 'boolean | ||
| 62 | :group 'comm) | ||
| 63 | |||
| 64 | (declare-function gnutls-negotiate "gnutls" | ||
| 65 | (proc type &optional priority-string trustfiles keyfiles)) | ||
| 66 | |||
| 67 | ;;;###autoload | ||
| 68 | (defun open-protocol-stream (name buffer host service &rest parameters) | ||
| 69 | "Open a network stream to HOST, upgrading to STARTTLS if possible. | ||
| 70 | The first four parameters have the same meaning as in | ||
| 71 | `open-network-stream'. The function returns a list where the | ||
| 72 | first element is the stream, the second element is the greeting | ||
| 73 | the server replied with after connecting, and the third element | ||
| 74 | is a string representing the capabilities of the server (if any). | ||
| 75 | |||
| 76 | The PARAMETERS is a keyword list that can have the following | ||
| 77 | values: | ||
| 78 | |||
| 79 | :type -- either `network', `tls', `shell' or `starttls'. If | ||
| 80 | omitted, the default is `network'. `network' will be | ||
| 81 | opportunistically upgraded to STARTTLS if both the server and | ||
| 82 | Emacs supports it. | ||
| 83 | |||
| 84 | :end-of-command -- a regexp saying what the end of a command is. | ||
| 85 | This defaults to \"\\n\". | ||
| 86 | |||
| 87 | :success -- a regexp saying whether the STARTTLS command was | ||
| 88 | successful or not. For instance, for NNTP this is \"^3\". | ||
| 89 | |||
| 90 | :capability-command -- a string representing the command used to | ||
| 91 | query server for capabilities. For instance, for IMAP this is | ||
| 92 | \"1 CAPABILITY\\r\\n\". | ||
| 93 | |||
| 94 | :starttls-function -- a function that takes one parameter, which | ||
| 95 | is the response to the capaibility command. It should return nil | ||
| 96 | if it turns out that the server doesn't support STARTTLS, or the | ||
| 97 | command to switch on STARTTLS otherwise." | ||
| 98 | (let ((type (or (cadr (memq :type parameters)) 'network))) | ||
| 99 | (cond | ||
| 100 | ((eq type 'starttls) | ||
| 101 | (setq type 'network)) | ||
| 102 | ((eq type 'ssl) | ||
| 103 | (setq type 'tls))) | ||
| 104 | (destructuring-bind (stream greeting capabilities) | ||
| 105 | (funcall (intern (format "proto-stream-open-%s" type) obarray) | ||
| 106 | name buffer host service parameters) | ||
| 107 | (list (and stream | ||
| 108 | (memq (process-status stream) | ||
| 109 | '(open run)) | ||
| 110 | stream) | ||
| 111 | greeting capabilities)))) | ||
| 112 | |||
| 113 | (defun proto-stream-open-network (name buffer host service parameters) | ||
| 114 | (let* ((start (with-current-buffer buffer (point))) | ||
| 115 | (stream (open-network-stream name buffer host service)) | ||
| 116 | (capability-command (cadr (memq :capability-command parameters))) | ||
| 117 | (eoc (proto-stream-eoc parameters)) | ||
| 118 | (type (cadr (memq :type parameters))) | ||
| 119 | (greeting (proto-stream-get-response stream start eoc)) | ||
| 120 | success) | ||
| 121 | (if (not capability-command) | ||
| 122 | (list stream greeting nil) | ||
| 123 | (let* ((capabilities | ||
| 124 | (proto-stream-command stream capability-command eoc)) | ||
| 125 | (starttls-command | ||
| 126 | (funcall (cadr (memq :starttls-function parameters)) | ||
| 127 | capabilities))) | ||
| 128 | (cond | ||
| 129 | ;; If this server doesn't support STARTTLS, but we have | ||
| 130 | ;; requested it explicitly, then close the connection and | ||
| 131 | ;; return nil. | ||
| 132 | ((or (not starttls-command) | ||
| 133 | (and (not (eq type 'starttls)) | ||
| 134 | (not proto-stream-always-use-starttls))) | ||
| 135 | (if (eq type 'starttls) | ||
| 136 | (progn | ||
| 137 | (delete-process stream) | ||
| 138 | nil) | ||
| 139 | ;; Otherwise, just return this plain network connection. | ||
| 140 | (list stream greeting capabilities))) | ||
| 141 | ;; We have some kind of STARTTLS support, so we try to | ||
| 142 | ;; upgrade the connection opportunistically. | ||
| 143 | ((or (fboundp 'open-gnutls-stream) | ||
| 144 | (executable-find "gnutls-cli")) | ||
| 145 | (unless (fboundp 'open-gnutls-stream) | ||
| 146 | (delete-process stream) | ||
| 147 | (setq start (with-current-buffer buffer (point-max))) | ||
| 148 | (let* ((starttls-use-gnutls t) | ||
| 149 | (starttls-extra-arguments | ||
| 150 | (if (not (eq type 'starttls)) | ||
| 151 | ;; When doing opportunistic TLS upgrades we | ||
| 152 | ;; don't really care about the identity of the | ||
| 153 | ;; peer. | ||
| 154 | (cons "--insecure" starttls-extra-arguments) | ||
| 155 | starttls-extra-arguments))) | ||
| 156 | (setq stream (starttls-open-stream name buffer host service))) | ||
| 157 | (proto-stream-get-response stream start eoc)) | ||
| 158 | (if (not | ||
| 159 | (string-match | ||
| 160 | (cadr (memq :success parameters)) | ||
| 161 | (proto-stream-command stream starttls-command eoc))) | ||
| 162 | ;; We got an error back from the STARTTLS command. | ||
| 163 | (progn | ||
| 164 | (if (eq type 'starttls) | ||
| 165 | (progn | ||
| 166 | (delete-process stream) | ||
| 167 | nil) | ||
| 168 | (list stream greeting capabilities))) | ||
| 169 | ;; The server said it was OK to start doing STARTTLS negotiations. | ||
| 170 | (if (fboundp 'open-gnutls-stream) | ||
| 171 | (gnutls-negotiate stream nil) | ||
| 172 | (unless (starttls-negotiate stream) | ||
| 173 | (delete-process stream) | ||
| 174 | (setq stream nil))) | ||
| 175 | (when (or (null stream) | ||
| 176 | (not (memq (process-status stream) | ||
| 177 | '(open run)))) | ||
| 178 | ;; It didn't successfully negotiate STARTTLS, so we reopen | ||
| 179 | ;; the connection. | ||
| 180 | (setq stream (open-network-stream name buffer host service)) | ||
| 181 | (proto-stream-get-response stream start eoc)) | ||
| 182 | ;; Re-get the capabilities, since they may have changed | ||
| 183 | ;; after switching to TLS. | ||
| 184 | (list stream greeting | ||
| 185 | (proto-stream-command stream capability-command eoc)))) | ||
| 186 | ;; We don't have STARTTLS support available, but the caller | ||
| 187 | ;; requested a STARTTLS connection, so we give up. | ||
| 188 | ((eq (cadr (memq :type parameters)) 'starttls) | ||
| 189 | (delete-process stream) | ||
| 190 | nil) | ||
| 191 | ;; Fall back on using a plain network stream. | ||
| 192 | (t | ||
| 193 | (list stream greeting capabilities))))))) | ||
| 194 | |||
| 195 | (defun proto-stream-command (stream command eoc) | ||
| 196 | (let ((start (with-current-buffer (process-buffer stream) (point-max)))) | ||
| 197 | (process-send-string stream command) | ||
| 198 | (proto-stream-get-response stream start eoc))) | ||
| 199 | |||
| 200 | (defun proto-stream-get-response (stream start end-of-command) | ||
| 201 | (with-current-buffer (process-buffer stream) | ||
| 202 | (save-excursion | ||
| 203 | (goto-char start) | ||
| 204 | (while (and (memq (process-status stream) | ||
| 205 | '(open run)) | ||
| 206 | (not (re-search-forward end-of-command nil t))) | ||
| 207 | (accept-process-output stream 0 50) | ||
| 208 | (goto-char start)) | ||
| 209 | (if (= start (point)) | ||
| 210 | ;; The process died; return nil. | ||
| 211 | nil | ||
| 212 | ;; Return the data we got back. | ||
| 213 | (buffer-substring start (point)))))) | ||
| 214 | |||
| 215 | (defun proto-stream-open-tls (name buffer host service parameters) | ||
| 216 | (with-current-buffer buffer | ||
| 217 | (let ((start (point-max)) | ||
| 218 | (stream | ||
| 219 | (funcall (if (fboundp 'open-gnutls-stream) | ||
| 220 | 'open-gnutls-stream | ||
| 221 | 'open-tls-stream) | ||
| 222 | name buffer host service))) | ||
| 223 | ;; If we're using tls.el, we have to delete the output from | ||
| 224 | ;; openssl/gnutls-cli. | ||
| 225 | (unless (fboundp 'open-gnutls-stream) | ||
| 226 | (proto-stream-get-response | ||
| 227 | stream start (proto-stream-eoc parameters)) | ||
| 228 | (goto-char (point-min)) | ||
| 229 | (when (re-search-forward (proto-stream-eoc parameters) nil t) | ||
| 230 | (goto-char (match-beginning 0)) | ||
| 231 | (delete-region (point-min) (line-beginning-position)))) | ||
| 232 | (proto-stream-capability-open start stream parameters)))) | ||
| 233 | |||
| 234 | (defun proto-stream-open-shell (name buffer host service parameters) | ||
| 235 | (proto-stream-capability-open | ||
| 236 | (with-current-buffer buffer (point)) | ||
| 237 | (let ((process-connection-type nil)) | ||
| 238 | (start-process name buffer shell-file-name | ||
| 239 | shell-command-switch | ||
| 240 | (format-spec | ||
| 241 | (cadr (memq :shell-command parameters)) | ||
| 242 | (format-spec-make | ||
| 243 | ?s host | ||
| 244 | ?p service)))) | ||
| 245 | parameters)) | ||
| 246 | |||
| 247 | (defun proto-stream-capability-open (start stream parameters) | ||
| 248 | (let ((capability-command (cadr (memq :capability-command parameters))) | ||
| 249 | (greeting (proto-stream-get-response | ||
| 250 | stream start (proto-stream-eoc parameters)))) | ||
| 251 | (list stream greeting | ||
| 252 | (and capability-command | ||
| 253 | (proto-stream-command | ||
| 254 | stream capability-command (proto-stream-eoc parameters)))))) | ||
| 255 | |||
| 256 | (defun proto-stream-eoc (parameters) | ||
| 257 | (or (cadr (memq :end-of-command parameters)) | ||
| 258 | "\r\n")) | ||
| 259 | |||
| 260 | (provide 'proto-stream) | ||
| 261 | |||
| 262 | ;;; proto-stream.el ends here | ||
diff --git a/lisp/gnus/rtree.el b/lisp/gnus/rtree.el new file mode 100644 index 00000000000..d2aa91848e8 --- /dev/null +++ b/lisp/gnus/rtree.el | |||
| @@ -0,0 +1,279 @@ | |||
| 1 | ;;; rtree.el --- functions for manipulating range trees | ||
| 2 | ;; Copyright (C) 2010 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 5 | |||
| 6 | ;; This file is part of GNU Emacs. | ||
| 7 | |||
| 8 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 9 | ;; it under the terms of the GNU General Public License as published by | ||
| 10 | ;; the Free Software Foundation; either version 3, or (at your option) | ||
| 11 | ;; any later version. | ||
| 12 | |||
| 13 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | ;; GNU General Public License for more details. | ||
| 17 | |||
| 18 | ;; You should have received a copy of the GNU General Public License | ||
| 19 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 20 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
| 21 | ;; Boston, MA 02110-1301, USA. | ||
| 22 | |||
| 23 | ;;; Commentary: | ||
| 24 | |||
| 25 | ;; A "range tree" is a binary tree that stores ranges. They are | ||
| 26 | ;; similar to interval trees, but do not allow overlapping intervals. | ||
| 27 | |||
| 28 | ;; A range is an ordered list of number intervals, like this: | ||
| 29 | |||
| 30 | ;; ((10 . 25) 56 78 (98 . 201)) | ||
| 31 | |||
| 32 | ;; Common operations, like lookup, deletion and insertion are O(n) in | ||
| 33 | ;; a range, but an rtree is O(log n) in all these operations. | ||
| 34 | ;; Transformation between a range and an rtree is O(n). | ||
| 35 | |||
| 36 | ;; The rtrees are quite simple. The structure of each node is | ||
| 37 | |||
| 38 | ;; (cons (cons low high) (cons left right)) | ||
| 39 | |||
| 40 | ;; That is, they are three cons cells, where the car of the top cell | ||
| 41 | ;; is the actual range, and the cdr has the left and right child. The | ||
| 42 | ;; rtrees aren't automatically balanced, but are balanced when | ||
| 43 | ;; created, and can be rebalanced when deemed necessary. | ||
| 44 | |||
| 45 | ;;; Code: | ||
| 46 | |||
| 47 | (eval-when-compile | ||
| 48 | (require 'cl)) | ||
| 49 | |||
| 50 | (defmacro rtree-make-node () | ||
| 51 | `(list (list nil) nil)) | ||
| 52 | |||
| 53 | (defmacro rtree-set-left (node left) | ||
| 54 | `(setcar (cdr ,node) ,left)) | ||
| 55 | |||
| 56 | (defmacro rtree-set-right (node right) | ||
| 57 | `(setcdr (cdr ,node) ,right)) | ||
| 58 | |||
| 59 | (defmacro rtree-set-range (node range) | ||
| 60 | `(setcar ,node ,range)) | ||
| 61 | |||
| 62 | (defmacro rtree-low (node) | ||
| 63 | `(caar ,node)) | ||
| 64 | |||
| 65 | (defmacro rtree-high (node) | ||
| 66 | `(cdar ,node)) | ||
| 67 | |||
| 68 | (defmacro rtree-set-low (node number) | ||
| 69 | `(setcar (car ,node) ,number)) | ||
| 70 | |||
| 71 | (defmacro rtree-set-high (node number) | ||
| 72 | `(setcdr (car ,node) ,number)) | ||
| 73 | |||
| 74 | (defmacro rtree-left (node) | ||
| 75 | `(cadr ,node)) | ||
| 76 | |||
| 77 | (defmacro rtree-right (node) | ||
| 78 | `(cddr ,node)) | ||
| 79 | |||
| 80 | (defmacro rtree-range (node) | ||
| 81 | `(car ,node)) | ||
| 82 | |||
| 83 | (defsubst rtree-normalise-range (range) | ||
| 84 | (when (numberp range) | ||
| 85 | (setq range (cons range range))) | ||
| 86 | range) | ||
| 87 | |||
| 88 | (defun rtree-make (range) | ||
| 89 | "Make an rtree from RANGE." | ||
| 90 | ;; Normalize the range. | ||
| 91 | (unless (listp (cdr-safe range)) | ||
| 92 | (setq range (list range))) | ||
| 93 | (rtree-make-1 (cons nil range) (length range))) | ||
| 94 | |||
| 95 | (defun rtree-make-1 (range length) | ||
| 96 | (let ((mid (/ length 2)) | ||
| 97 | (node (rtree-make-node))) | ||
| 98 | (when (> mid 0) | ||
| 99 | (rtree-set-left node (rtree-make-1 range mid))) | ||
| 100 | (rtree-set-range node (rtree-normalise-range (cadr range))) | ||
| 101 | (setcdr range (cddr range)) | ||
| 102 | (when (> (- length mid 1) 0) | ||
| 103 | (rtree-set-right node (rtree-make-1 range (- length mid 1)))) | ||
| 104 | node)) | ||
| 105 | |||
| 106 | (defun rtree-memq (tree number) | ||
| 107 | "Return non-nil if NUMBER is present in TREE." | ||
| 108 | (while (and tree | ||
| 109 | (not (and (>= number (rtree-low tree)) | ||
| 110 | (<= number (rtree-high tree))))) | ||
| 111 | (setq tree | ||
| 112 | (if (< number (rtree-low tree)) | ||
| 113 | (rtree-left tree) | ||
| 114 | (rtree-right tree)))) | ||
| 115 | tree) | ||
| 116 | |||
| 117 | (defun rtree-add (tree number) | ||
| 118 | "Add NUMBER to TREE." | ||
| 119 | (while tree | ||
| 120 | (cond | ||
| 121 | ;; It's already present, so we don't have to do anything. | ||
| 122 | ((and (>= number (rtree-low tree)) | ||
| 123 | (<= number (rtree-high tree))) | ||
| 124 | (setq tree nil)) | ||
| 125 | ((< number (rtree-low tree)) | ||
| 126 | (cond | ||
| 127 | ;; Extend the low range. | ||
| 128 | ((= number (1- (rtree-low tree))) | ||
| 129 | (rtree-set-low tree number) | ||
| 130 | ;; Check whether we need to merge this node with the child. | ||
| 131 | (when (and (rtree-left tree) | ||
| 132 | (= (rtree-high (rtree-left tree)) (1- number))) | ||
| 133 | ;; Extend the range to the low from the child. | ||
| 134 | (rtree-set-low tree (rtree-low (rtree-left tree))) | ||
| 135 | ;; The child can't have a right child, so just transplant the | ||
| 136 | ;; child's left tree to our left tree. | ||
| 137 | (rtree-set-left tree (rtree-left (rtree-left tree)))) | ||
| 138 | (setq tree nil)) | ||
| 139 | ;; Descend further to the left. | ||
| 140 | ((rtree-left tree) | ||
| 141 | (setq tree (rtree-left tree))) | ||
| 142 | ;; Add a new node. | ||
| 143 | (t | ||
| 144 | (let ((new-node (rtree-make-node))) | ||
| 145 | (rtree-set-low new-node number) | ||
| 146 | (rtree-set-high new-node number) | ||
| 147 | (rtree-set-left tree new-node) | ||
| 148 | (setq tree nil))))) | ||
| 149 | (t | ||
| 150 | (cond | ||
| 151 | ;; Extend the high range. | ||
| 152 | ((= number (1+ (rtree-high tree))) | ||
| 153 | (rtree-set-high tree number) | ||
| 154 | ;; Check whether we need to merge this node with the child. | ||
| 155 | (when (and (rtree-right tree) | ||
| 156 | (= (rtree-low (rtree-right tree)) (1+ number))) | ||
| 157 | ;; Extend the range to the high from the child. | ||
| 158 | (rtree-set-high tree (rtree-high (rtree-right tree))) | ||
| 159 | ;; The child can't have a left child, so just transplant the | ||
| 160 | ;; child's left right to our right tree. | ||
| 161 | (rtree-set-right tree (rtree-right (rtree-right tree)))) | ||
| 162 | (setq tree nil)) | ||
| 163 | ;; Descend further to the right. | ||
| 164 | ((rtree-right tree) | ||
| 165 | (setq tree (rtree-right tree))) | ||
| 166 | ;; Add a new node. | ||
| 167 | (t | ||
| 168 | (let ((new-node (rtree-make-node))) | ||
| 169 | (rtree-set-low new-node number) | ||
| 170 | (rtree-set-high new-node number) | ||
| 171 | (rtree-set-right tree new-node) | ||
| 172 | (setq tree nil)))))))) | ||
| 173 | |||
| 174 | (defun rtree-delq (tree number) | ||
| 175 | "Remove NUMBER from TREE destructively. Returns the new tree." | ||
| 176 | (let ((result tree) | ||
| 177 | prev) | ||
| 178 | (while tree | ||
| 179 | (cond | ||
| 180 | ((< number (rtree-low tree)) | ||
| 181 | (setq prev tree | ||
| 182 | tree (rtree-left tree))) | ||
| 183 | ((> number (rtree-high tree)) | ||
| 184 | (setq prev tree | ||
| 185 | tree (rtree-right tree))) | ||
| 186 | ;; The number is in this node. | ||
| 187 | (t | ||
| 188 | (cond | ||
| 189 | ;; The only entry; delete the node. | ||
| 190 | ((= (rtree-low tree) (rtree-high tree)) | ||
| 191 | (cond | ||
| 192 | ;; Two children. Replace with successor value. | ||
| 193 | ((and (rtree-left tree) (rtree-right tree)) | ||
| 194 | (let ((parent tree) | ||
| 195 | (successor (rtree-right tree))) | ||
| 196 | (while (rtree-left successor) | ||
| 197 | (setq parent successor | ||
| 198 | successor (rtree-left successor))) | ||
| 199 | ;; We now have the leftmost child of our right child. | ||
| 200 | (rtree-set-range tree (rtree-range successor)) | ||
| 201 | ;; Transplant the child (if any) to the parent. | ||
| 202 | (rtree-set-left parent (rtree-right successor)))) | ||
| 203 | (t | ||
| 204 | (let ((rest (or (rtree-left tree) | ||
| 205 | (rtree-right tree)))) | ||
| 206 | ;; One or zero children. Remove the node. | ||
| 207 | (cond | ||
| 208 | ((null prev) | ||
| 209 | (setq result rest)) | ||
| 210 | ((eq (rtree-left prev) tree) | ||
| 211 | (rtree-set-left prev rest)) | ||
| 212 | (t | ||
| 213 | (rtree-set-right prev rest))))))) | ||
| 214 | ;; The lowest in the range; just adjust. | ||
| 215 | ((= number (rtree-low tree)) | ||
| 216 | (rtree-set-low tree (1+ number))) | ||
| 217 | ;; The highest in the range; just adjust. | ||
| 218 | ((= number (rtree-high tree)) | ||
| 219 | (rtree-set-high tree (1- number))) | ||
| 220 | ;; We have to split this range. | ||
| 221 | (t | ||
| 222 | (let ((new-node (rtree-make-node))) | ||
| 223 | (rtree-set-low new-node (rtree-low tree)) | ||
| 224 | (rtree-set-high new-node (1- number)) | ||
| 225 | (rtree-set-low tree (1+ number)) | ||
| 226 | (cond | ||
| 227 | ;; Two children; insert the new node as the predecessor | ||
| 228 | ;; node. | ||
| 229 | ((and (rtree-left tree) (rtree-right tree)) | ||
| 230 | (let ((predecessor (rtree-left tree))) | ||
| 231 | (while (rtree-right predecessor) | ||
| 232 | (setq predecessor (rtree-right predecessor))) | ||
| 233 | (rtree-set-right predecessor new-node))) | ||
| 234 | ((rtree-left tree) | ||
| 235 | (rtree-set-right new-node tree) | ||
| 236 | (rtree-set-left new-node (rtree-left tree)) | ||
| 237 | (rtree-set-left tree nil) | ||
| 238 | (cond | ||
| 239 | ((null prev) | ||
| 240 | (setq result new-node)) | ||
| 241 | ((eq (rtree-left prev) tree) | ||
| 242 | (rtree-set-left prev new-node)) | ||
| 243 | (t | ||
| 244 | (rtree-set-right prev new-node)))) | ||
| 245 | (t | ||
| 246 | (rtree-set-left tree new-node)))))) | ||
| 247 | (setq tree nil)))) | ||
| 248 | result)) | ||
| 249 | |||
| 250 | (defun rtree-extract (tree) | ||
| 251 | "Convert TREE to range form." | ||
| 252 | (let (stack result) | ||
| 253 | (while (or stack | ||
| 254 | tree) | ||
| 255 | (if tree | ||
| 256 | (progn | ||
| 257 | (push tree stack) | ||
| 258 | (setq tree (rtree-right tree))) | ||
| 259 | (setq tree (pop stack)) | ||
| 260 | (push (if (= (rtree-low tree) | ||
| 261 | (rtree-high tree)) | ||
| 262 | (rtree-low tree) | ||
| 263 | (rtree-range tree)) | ||
| 264 | result) | ||
| 265 | (setq tree (rtree-left tree)))) | ||
| 266 | result)) | ||
| 267 | |||
| 268 | (defun rtree-length (tree) | ||
| 269 | "Return the number of numbers stored in TREE." | ||
| 270 | (if (null tree) | ||
| 271 | 0 | ||
| 272 | (+ (rtree-length (rtree-left tree)) | ||
| 273 | (1+ (- (rtree-high tree) | ||
| 274 | (rtree-low tree))) | ||
| 275 | (rtree-length (rtree-right tree))))) | ||
| 276 | |||
| 277 | (provide 'rtree) | ||
| 278 | |||
| 279 | ;;; rtree.el ends here | ||
diff --git a/lisp/gnus/shr.el b/lisp/gnus/shr.el index 69973fbfb50..c07bb34ef8d 100644 --- a/lisp/gnus/shr.el +++ b/lisp/gnus/shr.el | |||
| @@ -32,8 +32,6 @@ | |||
| 32 | 32 | ||
| 33 | (eval-when-compile (require 'cl)) | 33 | (eval-when-compile (require 'cl)) |
| 34 | (require 'browse-url) | 34 | (require 'browse-url) |
| 35 | (unless (aref (char-category-set (make-char 'japanese-jisx0208 33 35)) ?>) | ||
| 36 | (load "kinsoku" nil t)) | ||
| 37 | 35 | ||
| 38 | (defgroup shr nil | 36 | (defgroup shr nil |
| 39 | "Simple HTML Renderer" | 37 | "Simple HTML Renderer" |
| @@ -214,6 +212,26 @@ redirects somewhere else." | |||
| 214 | ((listp (cdr sub)) | 212 | ((listp (cdr sub)) |
| 215 | (shr-descend sub))))) | 213 | (shr-descend sub))))) |
| 216 | 214 | ||
| 215 | (defmacro shr-char-breakable-p (char) | ||
| 216 | "Return non-nil if a line can be broken before and after CHAR." | ||
| 217 | `(aref fill-find-break-point-function-table ,char)) | ||
| 218 | (defmacro shr-char-nospace-p (char) | ||
| 219 | "Return non-nil if no space is required before and after CHAR." | ||
| 220 | `(aref fill-nospace-between-words-table ,char)) | ||
| 221 | |||
| 222 | ;; KINSOKU is a Japanese word meaning a rule that should not be violated. | ||
| 223 | ;; In Emacs, it is a term used for characters, e.g. punctuation marks, | ||
| 224 | ;; parentheses, and so on, that should not be placed in the beginning | ||
| 225 | ;; of a line or the end of a line. | ||
| 226 | (defmacro shr-char-kinsoku-bol-p (char) | ||
| 227 | "Return non-nil if a line ought not to begin with CHAR." | ||
| 228 | `(aref (char-category-set ,char) ?>)) | ||
| 229 | (defmacro shr-char-kinsoku-eol-p (char) | ||
| 230 | "Return non-nil if a line ought not to end with CHAR." | ||
| 231 | `(aref (char-category-set ,char) ?<)) | ||
| 232 | (unless (shr-char-kinsoku-bol-p (make-char 'japanese-jisx0208 33 35)) | ||
| 233 | (load "kinsoku" nil t)) | ||
| 234 | |||
| 217 | (defun shr-insert (text) | 235 | (defun shr-insert (text) |
| 218 | (when (and (eq shr-state 'image) | 236 | (when (and (eq shr-state 'image) |
| 219 | (not (string-match "\\`[ \t\n]+\\'" text))) | 237 | (not (string-match "\\`[ \t\n]+\\'" text))) |
| @@ -242,12 +260,11 @@ redirects somewhere else." | |||
| 242 | (let (prev) | 260 | (let (prev) |
| 243 | (when (and (eq (preceding-char) ? ) | 261 | (when (and (eq (preceding-char) ? ) |
| 244 | (or (= (line-beginning-position) (1- (point))) | 262 | (or (= (line-beginning-position) (1- (point))) |
| 245 | (and (aref fill-find-break-point-function-table | 263 | (and (shr-char-breakable-p |
| 246 | (setq prev (char-after (- (point) 2)))) | 264 | (setq prev (char-after (- (point) 2)))) |
| 247 | (aref (char-category-set prev) ?>)) | 265 | (shr-char-kinsoku-bol-p prev)) |
| 248 | (and (aref fill-nospace-between-words-table prev) | 266 | (and (shr-char-nospace-p prev) |
| 249 | (aref fill-nospace-between-words-table | 267 | (shr-char-nospace-p (aref elem 0))))) |
| 250 | (aref elem 0))))) | ||
| 251 | (delete-char -1))) | 268 | (delete-char -1))) |
| 252 | (insert elem) | 269 | (insert elem) |
| 253 | (let (found) | 270 | (let (found) |
| @@ -273,67 +290,88 @@ redirects somewhere else." | |||
| 273 | (defun shr-find-fill-point () | 290 | (defun shr-find-fill-point () |
| 274 | (when (> (move-to-column shr-width) shr-width) | 291 | (when (> (move-to-column shr-width) shr-width) |
| 275 | (backward-char 1)) | 292 | (backward-char 1)) |
| 276 | (let (failed) | 293 | (let ((bp (point)) |
| 277 | (while (not | 294 | failed) |
| 278 | (or (setq failed (= (current-column) shr-indentation)) | 295 | (while (not (or (setq failed (= (current-column) shr-indentation)) |
| 279 | (eq (preceding-char) ? ) | 296 | (eq (preceding-char) ? ) |
| 280 | (eq (following-char) ? ) | 297 | (eq (following-char) ? ) |
| 281 | (aref fill-find-break-point-function-table (preceding-char)) | 298 | (shr-char-breakable-p (preceding-char)) |
| 282 | (aref (char-category-set (preceding-char)) ?>))) | 299 | (shr-char-breakable-p (following-char)) |
| 300 | (and (eq (preceding-char) ?') | ||
| 301 | (not (memq (char-after (- (point) 2)) | ||
| 302 | (list nil ?\n ? )))) | ||
| 303 | ;; There're some kinsoku CJK chars that aren't breakable. | ||
| 304 | (and (shr-char-kinsoku-bol-p (preceding-char)) | ||
| 305 | (not (shr-char-kinsoku-bol-p (following-char)))) | ||
| 306 | (shr-char-kinsoku-eol-p (following-char)))) | ||
| 283 | (backward-char 1)) | 307 | (backward-char 1)) |
| 308 | (if (and (not (or failed (eolp))) | ||
| 309 | (eq (preceding-char) ?')) | ||
| 310 | (while (not (or (setq failed (eolp)) | ||
| 311 | (eq (following-char) ? ) | ||
| 312 | (shr-char-breakable-p (following-char)) | ||
| 313 | (shr-char-kinsoku-eol-p (following-char)))) | ||
| 314 | (forward-char 1))) | ||
| 284 | (if failed | 315 | (if failed |
| 285 | ;; There's no breakable point, so we give it up. | 316 | ;; There's no breakable point, so we give it up. |
| 286 | (progn | 317 | (let (found) |
| 287 | (end-of-line) | 318 | (goto-char bp) |
| 288 | (while (aref fill-find-break-point-function-table (preceding-char)) | 319 | (unless shr-kinsoku-shorten |
| 289 | (backward-char 1)) | 320 | (while (and (setq found (re-search-forward |
| 290 | nil) | 321 | "\\(\\c>\\)\\| \\|\\c<\\|\\c|" |
| 322 | (line-end-position) 'move)) | ||
| 323 | (eq (preceding-char) ?'))) | ||
| 324 | (if (and found (not (match-beginning 1))) | ||
| 325 | (goto-char (match-beginning 0))))) | ||
| 291 | (or | 326 | (or |
| 292 | (eolp) | 327 | (eolp) |
| 293 | (progn | 328 | ;; Don't put kinsoku-bol characters at the beginning of a line, |
| 294 | ;; Don't put kinsoku-bol characters at the beginning of a line, | 329 | ;; or kinsoku-eol characters at the end of a line. |
| 295 | ;; or kinsoku-eol characters at the end of a line. | 330 | (cond |
| 296 | (cond | 331 | (shr-kinsoku-shorten |
| 297 | (shr-kinsoku-shorten | 332 | (while (and (not (memq (preceding-char) (list ?\C-@ ?\n ? ))) |
| 298 | (while (and | 333 | (shr-char-kinsoku-eol-p (preceding-char))) |
| 299 | (not (memq (preceding-char) (list ?\C-@ ?\n ? ))) | 334 | (backward-char 1)) |
| 300 | (not (or (aref (char-category-set (preceding-char)) ?>) | 335 | (when (setq failed (= (current-column) shr-indentation)) |
| 301 | (aref (char-category-set (following-char)) ?<))) | 336 | ;; There's no breakable point that doesn't violate kinsoku, |
| 302 | (or (aref (char-category-set (preceding-char)) ?<) | 337 | ;; so we look for the second best position. |
| 303 | (aref (char-category-set (following-char)) ?>))) | 338 | (while (and (progn |
| 304 | (backward-char 1))) | 339 | (forward-char 1) |
| 305 | ((aref (char-category-set (preceding-char)) ?<) | 340 | (<= (current-column) shr-width)) |
| 306 | (let ((count 3)) | 341 | (progn |
| 307 | (while (progn | 342 | (setq bp (point)) |
| 308 | (backward-char 1) | 343 | (shr-char-kinsoku-eol-p (following-char))))) |
| 309 | (and | 344 | (goto-char bp))) |
| 310 | (> (setq count (1- count)) 0) | 345 | ((shr-char-kinsoku-eol-p (preceding-char)) |
| 311 | (not (memq (preceding-char) (list ?\C-@ ?\n ? ))) | 346 | (if (shr-char-kinsoku-eol-p (following-char)) |
| 312 | (or (aref (char-category-set (preceding-char)) ?<) | 347 | ;; There are consecutive kinsoku-eol characters. |
| 313 | (aref (char-category-set (following-char)) ?>)))))) | 348 | (setq failed t) |
| 314 | (if (and (setq failed (= (current-column) shr-indentation)) | 349 | (let ((count 4)) |
| 315 | (re-search-forward "\\c|" (line-end-position) 'move)) | 350 | (while |
| 351 | (progn | ||
| 352 | (backward-char 1) | ||
| 353 | (and (> (setq count (1- count)) 0) | ||
| 354 | (not (memq (preceding-char) (list ?\C-@ ?\n ? ))) | ||
| 355 | (or (shr-char-kinsoku-eol-p (preceding-char)) | ||
| 356 | (shr-char-kinsoku-bol-p (following-char))))))) | ||
| 357 | (if (setq failed (= (current-column) shr-indentation)) | ||
| 316 | ;; There's no breakable point that doesn't violate kinsoku, | 358 | ;; There's no breakable point that doesn't violate kinsoku, |
| 317 | ;; so we look for the second best position. | 359 | ;; so we go to the second best position. |
| 318 | (let (bp) | 360 | (if (looking-at "\\(\\c<+\\)\\c<") |
| 319 | (while (and (<= (current-column) shr-width) | 361 | (goto-char (match-end 1)) |
| 320 | (progn | 362 | (forward-char 1))))) |
| 321 | (setq bp (point)) | 363 | (t |
| 322 | (not (eolp))) | 364 | (if (shr-char-kinsoku-bol-p (preceding-char)) |
| 323 | (aref fill-find-break-point-function-table | 365 | ;; There are consecutive kinsoku-bol characters. |
| 324 | (following-char))) | 366 | (setq failed t) |
| 325 | (forward-char 1)) | ||
| 326 | (goto-char (or bp (line-end-position)))))) | ||
| 327 | (t | ||
| 328 | (let ((count 4)) | 367 | (let ((count 4)) |
| 329 | (while (and (>= (setq count (1- count)) 0) | 368 | (while (and (>= (setq count (1- count)) 0) |
| 330 | (aref (char-category-set (following-char)) ?>) | 369 | (shr-char-kinsoku-bol-p (following-char)) |
| 331 | (aref fill-find-break-point-function-table | 370 | (shr-char-breakable-p (following-char))) |
| 332 | (following-char))) | 371 | (forward-char 1)))))) |
| 333 | (forward-char 1))))) | 372 | (when (eq (following-char) ? ) |
| 334 | (when (eq (following-char) ? ) | 373 | (forward-char 1)))) |
| 335 | (forward-char 1)) | 374 | (not failed))) |
| 336 | (not failed)))))) | ||
| 337 | 375 | ||
| 338 | (defun shr-ensure-newline () | 376 | (defun shr-ensure-newline () |
| 339 | (unless (zerop (current-column)) | 377 | (unless (zerop (current-column)) |