*** empty log message ***
[gnus] / lisp / gnus-sum.el
1 ;;; gnus-sum.el --- summary mode commands for Gnus
2 ;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
3 ;;        Free Software Foundation, Inc.
4
5 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
6 ;; Keywords: news
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;; Commentary:
26
27 ;;; Code:
28
29 (eval-when-compile (require 'cl))
30
31 (require 'gnus)
32 (require 'gnus-group)
33 (require 'gnus-spec)
34 (require 'gnus-range)
35 (require 'gnus-int)
36 (require 'gnus-undo)
37 (require 'gnus-util)
38 (require 'mm-decode)
39 (require 'nnoo)
40
41 (autoload 'gnus-summary-limit-include-cached "gnus-cache" nil t)
42 (autoload 'gnus-cache-write-active "gnus-cache")
43 (autoload 'gnus-mailing-list-insinuate "gnus-ml" nil t)
44 (autoload 'turn-on-gnus-mailing-list-mode "gnus-ml" nil t)
45 (autoload 'mm-uu-dissect "mm-uu")
46
47 (defcustom gnus-kill-summary-on-exit t
48   "*If non-nil, kill the summary buffer when you exit from it.
49 If nil, the summary will become a \"*Dead Summary*\" buffer, and
50 it will be killed sometime later."
51   :group 'gnus-summary-exit
52   :type 'boolean)
53
54 (defcustom gnus-fetch-old-headers nil
55   "*Non-nil means that Gnus will try to build threads by grabbing old headers.
56 If an unread article in the group refers to an older, already read (or
57 just marked as read) article, the old article will not normally be
58 displayed in the Summary buffer.  If this variable is non-nil, Gnus
59 will attempt to grab the headers to the old articles, and thereby
60 build complete threads.  If it has the value `some', only enough
61 headers to connect otherwise loose threads will be displayed.  This
62 variable can also be a number.  In that case, no more than that number
63 of old headers will be fetched.  If it has the value `invisible', all
64 old headers will be fetched, but none will be displayed.
65
66 The server has to support NOV for any of this to work."
67   :group 'gnus-thread
68   :type '(choice (const :tag "off" nil)
69                  (const some)
70                  number
71                  (sexp :menu-tag "other" t)))
72
73 (defcustom gnus-refer-thread-limit 200
74   "*The number of old headers to fetch when doing \\<gnus-summary-mode-map>\\[gnus-summary-refer-thread].
75 If t, fetch all the available old headers."
76   :group 'gnus-thread
77   :type '(choice number
78                  (sexp :menu-tag "other" t)))
79
80 (defcustom gnus-summary-make-false-root 'adopt
81   "*nil means that Gnus won't gather loose threads.
82 If the root of a thread has expired or been read in a previous
83 session, the information necessary to build a complete thread has been
84 lost.  Instead of having many small sub-threads from this original thread
85 scattered all over the summary buffer, Gnus can gather them.
86
87 If non-nil, Gnus will try to gather all loose sub-threads from an
88 original thread into one large thread.
89
90 If this variable is non-nil, it should be one of `none', `adopt',
91 `dummy' or `empty'.
92
93 If this variable is `none', Gnus will not make a false root, but just
94 present the sub-threads after another.
95 If this variable is `dummy', Gnus will create a dummy root that will
96 have all the sub-threads as children.
97 If this variable is `adopt', Gnus will make one of the \"children\"
98 the parent and mark all the step-children as such.
99 If this variable is `empty', the \"children\" are printed with empty
100 subject fields.  (Or rather, they will be printed with a string
101 given by the `gnus-summary-same-subject' variable.)"
102   :group 'gnus-thread
103   :type '(choice (const :tag "off" nil)
104                  (const none)
105                  (const dummy)
106                  (const adopt)
107                  (const empty)))
108
109 (defcustom gnus-summary-gather-exclude-subject "^ *$\\|^(none)$"
110   "*A regexp to match subjects to be excluded from loose thread gathering.
111 As loose thread gathering is done on subjects only, that means that
112 there can be many false gatherings performed.  By rooting out certain
113 common subjects, gathering might become saner."
114   :group 'gnus-thread
115   :type 'regexp)
116
117 (defcustom gnus-summary-gather-subject-limit nil
118   "*Maximum length of subject comparisons when gathering loose threads.
119 Use nil to compare full subjects.  Setting this variable to a low
120 number will help gather threads that have been corrupted by
121 newsreaders chopping off subject lines, but it might also mean that
122 unrelated articles that have subject that happen to begin with the
123 same few characters will be incorrectly gathered.
124
125 If this variable is `fuzzy', Gnus will use a fuzzy algorithm when
126 comparing subjects."
127   :group 'gnus-thread
128   :type '(choice (const :tag "off" nil)
129                  (const fuzzy)
130                  (sexp :menu-tag "on" t)))
131
132 (defcustom gnus-simplify-subject-functions nil
133   "List of functions taking a string argument that simplify subjects.
134 The functions are applied recursively.
135
136 Useful functions to put in this list include: `gnus-simplify-subject-re',
137 `gnus-simplify-subject-fuzzy' and `gnus-simplify-whitespace'."
138   :group 'gnus-thread
139   :type '(repeat function))
140
141 (defcustom gnus-simplify-ignored-prefixes nil
142   "*Regexp, matches for which are removed from subject lines when simplifying fuzzily."
143   :group 'gnus-thread
144   :type '(choice (const :tag "off" nil)
145                  regexp))
146
147 (defcustom gnus-build-sparse-threads nil
148   "*If non-nil, fill in the gaps in threads.
149 If `some', only fill in the gaps that are needed to tie loose threads
150 together.  If `more', fill in all leaf nodes that Gnus can find.  If
151 non-nil and non-`some', fill in all gaps that Gnus manages to guess."
152   :group 'gnus-thread
153   :type '(choice (const :tag "off" nil)
154                  (const some)
155                  (const more)
156                  (sexp :menu-tag "all" t)))
157
158 (defcustom gnus-summary-thread-gathering-function
159   'gnus-gather-threads-by-subject
160   "*Function used for gathering loose threads.
161 There are two pre-defined functions: `gnus-gather-threads-by-subject',
162 which only takes Subjects into consideration; and
163 `gnus-gather-threads-by-references', which compared the References
164 headers of the articles to find matches."
165   :group 'gnus-thread
166   :type '(radio (function-item gnus-gather-threads-by-subject)
167                 (function-item gnus-gather-threads-by-references)
168                 (function :tag "other")))
169
170 (defcustom gnus-summary-same-subject ""
171   "*String indicating that the current article has the same subject as the previous.
172 This variable will only be used if the value of
173 `gnus-summary-make-false-root' is `empty'."
174   :group 'gnus-summary-format
175   :type 'string)
176
177 (defcustom gnus-summary-goto-unread t
178   "*If t, many commands will go to the next unread article.
179 This applies to marking commands as well as other commands that
180 \"naturally\" select the next article, like, for instance, `SPC' at
181 the end of an article.
182
183 If nil, the marking commands do NOT go to the next unread article
184 (they go to the next article instead).  If `never', commands that
185 usually go to the next unread article, will go to the next article,
186 whether it is read or not."
187   :group 'gnus-summary-marks
188   :link '(custom-manual "(gnus)Setting Marks")
189   :type '(choice (const :tag "off" nil)
190                  (const never)
191                  (sexp :menu-tag "on" t)))
192
193 (defcustom gnus-summary-default-score 0
194   "*Default article score level.
195 All scores generated by the score files will be added to this score.
196 If this variable is nil, scoring will be disabled."
197   :group 'gnus-score-default
198   :type '(choice (const :tag "disable")
199                  integer))
200
201 (defcustom gnus-summary-default-high-score 0
202   "*Default threshold for a high scored article.
203 An article will be highlighted as high scored if its score is greater
204 than this score."
205   :group 'gnus-score-default
206   :type 'integer)
207
208 (defcustom gnus-summary-default-low-score 0
209   "*Default threshold for a low scored article.
210 An article will be highlighted as low scored if its score is smaller
211 than this score."
212   :group 'gnus-score-default
213   :type 'integer)
214
215 (defcustom gnus-summary-zcore-fuzz 0
216   "*Fuzziness factor for the zcore in the summary buffer.
217 Articles with scores closer than this to `gnus-summary-default-score'
218 will not be marked."
219   :group 'gnus-summary-format
220   :type 'integer)
221
222 (defcustom gnus-simplify-subject-fuzzy-regexp nil
223   "*Strings to be removed when doing fuzzy matches.
224 This can either be a regular expression or list of regular expressions
225 that will be removed from subject strings if fuzzy subject
226 simplification is selected."
227   :group 'gnus-thread
228   :type '(repeat regexp))
229
230 (defcustom gnus-show-threads t
231   "*If non-nil, display threads in summary mode."
232   :group 'gnus-thread
233   :type 'boolean)
234
235 (defcustom gnus-thread-hide-subtree nil
236   "*If non-nil, hide all threads initially.
237 If threads are hidden, you have to run the command
238 `gnus-summary-show-thread' by hand or use `gnus-select-article-hook'
239 to expose hidden threads."
240   :group 'gnus-thread
241   :type 'boolean)
242
243 (defcustom gnus-thread-hide-killed t
244   "*If non-nil, hide killed threads automatically."
245   :group 'gnus-thread
246   :type 'boolean)
247
248 (defcustom gnus-thread-ignore-subject t
249   "*If non-nil, which is the default, ignore subjects and do all threading based on the Reference header.
250 If nil, articles that have different subjects from their parents will
251 start separate threads."
252   :group 'gnus-thread
253   :type 'boolean)
254
255 (defcustom gnus-thread-operation-ignore-subject t
256   "*If non-nil, subjects will be ignored when doing thread commands.
257 This affects commands like `gnus-summary-kill-thread' and
258 `gnus-summary-lower-thread'.
259
260 If this variable is nil, articles in the same thread with different
261 subjects will not be included in the operation in question.  If this
262 variable is `fuzzy', only articles that have subjects that are fuzzily
263 equal will be included."
264   :group 'gnus-thread
265   :type '(choice (const :tag "off" nil)
266                  (const fuzzy)
267                  (sexp :tag "on" t)))
268
269 (defcustom gnus-thread-indent-level 4
270   "*Number that says how much each sub-thread should be indented."
271   :group 'gnus-thread
272   :type 'integer)
273
274 (defcustom gnus-auto-extend-newsgroup t
275   "*If non-nil, extend newsgroup forward and backward when requested."
276   :group 'gnus-summary-choose
277   :type 'boolean)
278
279 (defcustom gnus-auto-select-first t
280   "*If non-nil, select the article under point.
281 Which article this is is controlled by the `gnus-auto-select-subject'
282 variable.
283
284 If you want to prevent automatic selection of articles in some
285 newsgroups, set the variable to nil in `gnus-select-group-hook'."
286   :group 'gnus-group-select
287   :type '(choice (const :tag "none" nil)
288                  (sexp :menu-tag "first" t)))
289
290 (defcustom gnus-auto-select-subject 'unread
291   "*Says what subject to place under point when entering a group.
292
293 This variable can either be the symbols `first' (place point on the
294 first subject), `unread' (place point on the subject line of the first
295 unread article), `best' (place point on the subject line of the
296 higest-scored article), `unseen' (place point on the subject line of
297 the first unseen article), or a function to be called to place point on
298 some subject line.."
299   :group 'gnus-group-select
300   :type '(choice (const best)
301                  (const unread)
302                  (const first)
303                  (const unseen)))
304
305 (defcustom gnus-auto-select-next t
306   "*If non-nil, offer to go to the next group from the end of the previous.
307 If the value is t and the next newsgroup is empty, Gnus will exit
308 summary mode and go back to group mode.  If the value is neither nil
309 nor t, Gnus will select the following unread newsgroup.  In
310 particular, if the value is the symbol `quietly', the next unread
311 newsgroup will be selected without any confirmation, and if it is
312 `almost-quietly', the next group will be selected without any
313 confirmation if you are located on the last article in the group.
314 Finally, if this variable is `slightly-quietly', the `Z n' command
315 will go to the next group without confirmation."
316   :group 'gnus-summary-maneuvering
317   :type '(choice (const :tag "off" nil)
318                  (const quietly)
319                  (const almost-quietly)
320                  (const slightly-quietly)
321                  (sexp :menu-tag "on" t)))
322
323 (defcustom gnus-auto-select-same nil
324   "*If non-nil, select the next article with the same subject.
325 If there are no more articles with the same subject, go to
326 the first unread article."
327   :group 'gnus-summary-maneuvering
328   :type 'boolean)
329
330 (defcustom gnus-summary-check-current nil
331   "*If non-nil, consider the current article when moving.
332 The \"unread\" movement commands will stay on the same line if the
333 current article is unread."
334   :group 'gnus-summary-maneuvering
335   :type 'boolean)
336
337 (defcustom gnus-auto-center-summary t
338   "*If non-nil, always center the current summary buffer.
339 In particular, if `vertical' do only vertical recentering.  If non-nil
340 and non-`vertical', do both horizontal and vertical recentering."
341   :group 'gnus-summary-maneuvering
342   :type '(choice (const :tag "none" nil)
343                  (const vertical)
344                  (integer :tag "height")
345                  (sexp :menu-tag "both" t)))
346
347 (defcustom gnus-show-all-headers nil
348   "*If non-nil, don't hide any headers."
349   :group 'gnus-article-hiding
350   :group 'gnus-article-headers
351   :type 'boolean)
352
353 (defcustom gnus-summary-ignore-duplicates nil
354   "*If non-nil, ignore articles with identical Message-ID headers."
355   :group 'gnus-summary
356   :type 'boolean)
357
358 (defcustom gnus-single-article-buffer t
359   "*If non-nil, display all articles in the same buffer.
360 If nil, each group will get its own article buffer."
361   :group 'gnus-article-various
362   :type 'boolean)
363
364 (defcustom gnus-break-pages t
365   "*If non-nil, do page breaking on articles.
366 The page delimiter is specified by the `gnus-page-delimiter'
367 variable."
368   :group 'gnus-article-various
369   :type 'boolean)
370
371 (defcustom gnus-move-split-methods nil
372   "*Variable used to suggest where articles are to be moved to.
373 It uses the same syntax as the `gnus-split-methods' variable.
374 However, whereas `gnus-split-methods' specifies file names as targets,
375 this variable specifies group names."
376   :group 'gnus-summary-mail
377   :type '(repeat (choice (list :value (fun) function)
378                          (cons :value ("" "") regexp (repeat string))
379                          (sexp :value nil))))
380
381 (defcustom gnus-unread-mark ?           ;Whitespace
382   "*Mark used for unread articles."
383   :group 'gnus-summary-marks
384   :type 'character)
385
386 (defcustom gnus-ticked-mark ?!
387   "*Mark used for ticked articles."
388   :group 'gnus-summary-marks
389   :type 'character)
390
391 (defcustom gnus-dormant-mark ??
392   "*Mark used for dormant articles."
393   :group 'gnus-summary-marks
394   :type 'character)
395
396 (defcustom gnus-del-mark ?r
397   "*Mark used for del'd articles."
398   :group 'gnus-summary-marks
399   :type 'character)
400
401 (defcustom gnus-read-mark ?R
402   "*Mark used for read articles."
403   :group 'gnus-summary-marks
404   :type 'character)
405
406 (defcustom gnus-expirable-mark ?E
407   "*Mark used for expirable articles."
408   :group 'gnus-summary-marks
409   :type 'character)
410
411 (defcustom gnus-killed-mark ?K
412   "*Mark used for killed articles."
413   :group 'gnus-summary-marks
414   :type 'character)
415
416 (defcustom gnus-souped-mark ?F
417   "*Mark used for souped articles."
418   :group 'gnus-summary-marks
419   :type 'character)
420
421 (defcustom gnus-kill-file-mark ?X
422   "*Mark used for articles killed by kill files."
423   :group 'gnus-summary-marks
424   :type 'character)
425
426 (defcustom gnus-low-score-mark ?Y
427   "*Mark used for articles with a low score."
428   :group 'gnus-summary-marks
429   :type 'character)
430
431 (defcustom gnus-catchup-mark ?C
432   "*Mark used for articles that are caught up."
433   :group 'gnus-summary-marks
434   :type 'character)
435
436 (defcustom gnus-replied-mark ?A
437   "*Mark used for articles that have been replied to."
438   :group 'gnus-summary-marks
439   :type 'character)
440
441 (defcustom gnus-forwarded-mark ?F
442   "*Mark used for articles that have been forwarded."
443   :group 'gnus-summary-marks
444   :type 'character)
445
446 (defcustom gnus-recent-mark ?N
447   "*Mark used for articles that are recent."
448   :group 'gnus-summary-marks
449   :type 'character)
450
451 (defcustom gnus-cached-mark ?*
452   "*Mark used for articles that are in the cache."
453   :group 'gnus-summary-marks
454   :type 'character)
455
456 (defcustom gnus-saved-mark ?S
457   "*Mark used for articles that have been saved."
458   :group 'gnus-summary-marks
459   :type 'character)
460
461 (defcustom gnus-unseen-mark ?.
462   "*Mark used for articles that haven't been seen."
463   :group 'gnus-summary-marks
464   :type 'character)
465
466 (defcustom gnus-no-mark ?               ;Whitespace
467   "*Mark used for articles that have no other secondary mark."
468   :group 'gnus-summary-marks
469   :type 'character)
470
471 (defcustom gnus-ancient-mark ?O
472   "*Mark used for ancient articles."
473   :group 'gnus-summary-marks
474   :type 'character)
475
476 (defcustom gnus-sparse-mark ?Q
477   "*Mark used for sparsely reffed articles."
478   :group 'gnus-summary-marks
479   :type 'character)
480
481 (defcustom gnus-canceled-mark ?G
482   "*Mark used for canceled articles."
483   :group 'gnus-summary-marks
484   :type 'character)
485
486 (defcustom gnus-duplicate-mark ?M
487   "*Mark used for duplicate articles."
488   :group 'gnus-summary-marks
489   :type 'character)
490
491 (defcustom gnus-undownloaded-mark ?@
492   "*Mark used for articles that weren't downloaded."
493   :group 'gnus-summary-marks
494   :type 'character)
495
496 (defcustom gnus-downloadable-mark ?%
497   "*Mark used for articles that are to be downloaded."
498   :group 'gnus-summary-marks
499   :type 'character)
500
501 (defcustom gnus-unsendable-mark ?=
502   "*Mark used for articles that won't be sent."
503   :group 'gnus-summary-marks
504   :type 'character)
505
506 (defcustom gnus-score-over-mark ?+
507   "*Score mark used for articles with high scores."
508   :group 'gnus-summary-marks
509   :type 'character)
510
511 (defcustom gnus-score-below-mark ?-
512   "*Score mark used for articles with low scores."
513   :group 'gnus-summary-marks
514   :type 'character)
515
516 (defcustom gnus-empty-thread-mark ?     ;Whitespace
517   "*There is no thread under the article."
518   :group 'gnus-summary-marks
519   :type 'character)
520
521 (defcustom gnus-not-empty-thread-mark ?=
522   "*There is a thread under the article."
523   :group 'gnus-summary-marks
524   :type 'character)
525
526 (defcustom gnus-view-pseudo-asynchronously nil
527   "*If non-nil, Gnus will view pseudo-articles asynchronously."
528   :group 'gnus-extract-view
529   :type 'boolean)
530
531 (defcustom gnus-auto-expirable-marks
532   (list gnus-killed-mark gnus-del-mark gnus-catchup-mark
533         gnus-low-score-mark gnus-ancient-mark gnus-read-mark
534         gnus-souped-mark gnus-duplicate-mark)
535   "*The list of marks converted into expiration if a group is auto-expirable."
536   :version "21.1"
537   :group 'gnus-summary
538   :type '(repeat character))
539
540 (defcustom gnus-inhibit-user-auto-expire t
541   "*If non-nil, user marking commands will not mark an article as expirable, even if the group has auto-expire turned on."
542   :version "21.1"
543   :group 'gnus-summary
544   :type 'boolean)
545
546 (defcustom gnus-view-pseudos nil
547   "*If `automatic', pseudo-articles will be viewed automatically.
548 If `not-confirm', pseudos will be viewed automatically, and the user
549 will not be asked to confirm the command."
550   :group 'gnus-extract-view
551   :type '(choice (const :tag "off" nil)
552                  (const automatic)
553                  (const not-confirm)))
554
555 (defcustom gnus-view-pseudos-separately t
556   "*If non-nil, one pseudo-article will be created for each file to be viewed.
557 If nil, all files that use the same viewing command will be given as a
558 list of parameters to that command."
559   :group 'gnus-extract-view
560   :type 'boolean)
561
562 (defcustom gnus-insert-pseudo-articles t
563   "*If non-nil, insert pseudo-articles when decoding articles."
564   :group 'gnus-extract-view
565   :type 'boolean)
566
567 (defcustom gnus-summary-dummy-line-format
568   "  %(:                          :%) %S\n"
569   "*The format specification for the dummy roots in the summary buffer.
570 It works along the same lines as a normal formatting string,
571 with some simple extensions.
572
573 %S  The subject"
574   :group 'gnus-threading
575   :type 'string)
576
577 (defcustom gnus-summary-mode-line-format "Gnus: %g [%A] %Z"
578   "*The format specification for the summary mode line.
579 It works along the same lines as a normal formatting string,
580 with some simple extensions:
581
582 %G  Group name
583 %p  Unprefixed group name
584 %A  Current article number
585 %z  Current article score
586 %V  Gnus version
587 %U  Number of unread articles in the group
588 %e  Number of unselected articles in the group
589 %Z  A string with unread/unselected article counts
590 %g  Shortish group name
591 %S  Subject of the current article
592 %u  User-defined spec
593 %s  Current score file name
594 %d  Number of dormant articles
595 %r  Number of articles that have been marked as read in this session
596 %E  Number of articles expunged by the score files"
597   :group 'gnus-summary-format
598   :type 'string)
599
600 (defcustom gnus-list-identifiers nil
601   "Regexp that matches list identifiers to be removed from subject.
602 This can also be a list of regexps."
603   :version "21.1"
604   :group 'gnus-summary-format
605   :group 'gnus-article-hiding
606   :type '(choice (const :tag "none" nil)
607                  (regexp :value ".*")
608                  (repeat :value (".*") regexp)))
609
610 (defcustom gnus-summary-mark-below 0
611   "*Mark all articles with a score below this variable as read.
612 This variable is local to each summary buffer and usually set by the
613 score file."
614   :group 'gnus-score-default
615   :type 'integer)
616
617 (defcustom gnus-article-sort-functions '(gnus-article-sort-by-number)
618   "*List of functions used for sorting articles in the summary buffer.
619
620 Each function takes two articles and returns non-nil if the first
621 article should be sorted before the other.  If you use more than one
622 function, the primary sort function should be the last.  You should
623 probably always include `gnus-article-sort-by-number' in the list of
624 sorting functions -- preferably first.  Also note that sorting by date
625 is often much slower than sorting by number, and the sorting order is
626 very similar.  (Sorting by date means sorting by the time the message
627 was sent, sorting by number means sorting by arrival time.)
628
629 Ready-made functions include `gnus-article-sort-by-number',
630 `gnus-article-sort-by-author', `gnus-article-sort-by-subject',
631 `gnus-article-sort-by-date' and `gnus-article-sort-by-score'.
632
633 When threading is turned on, the variable `gnus-thread-sort-functions'
634 controls how articles are sorted."
635   :group 'gnus-summary-sort
636   :type '(repeat (choice (function-item gnus-article-sort-by-number)
637                          (function-item gnus-article-sort-by-author)
638                          (function-item gnus-article-sort-by-subject)
639                          (function-item gnus-article-sort-by-date)
640                          (function-item gnus-article-sort-by-score)
641                          (function :tag "other"))))
642
643 (defcustom gnus-thread-sort-functions '(gnus-thread-sort-by-number)
644   "*List of functions used for sorting threads in the summary buffer.
645 By default, threads are sorted by article number.
646
647 Each function takes two threads and returns non-nil if the first
648 thread should be sorted before the other.  If you use more than one
649 function, the primary sort function should be the last.  You should
650 probably always include `gnus-thread-sort-by-number' in the list of
651 sorting functions -- preferably first.  Also note that sorting by date
652 is often much slower than sorting by number, and the sorting order is
653 very similar.  (Sorting by date means sorting by the time the message
654 was sent, sorting by number means sorting by arrival time.)
655
656 Ready-made functions include `gnus-thread-sort-by-number',
657 `gnus-thread-sort-by-author', `gnus-thread-sort-by-subject',
658 `gnus-thread-sort-by-date', `gnus-thread-sort-by-score' and
659 `gnus-thread-sort-by-total-score' (see `gnus-thread-score-function').
660
661 When threading is turned off, the variable
662 `gnus-article-sort-functions' controls how articles are sorted."
663   :group 'gnus-summary-sort
664   :type '(repeat (choice (function-item gnus-thread-sort-by-number)
665                          (function-item gnus-thread-sort-by-author)
666                          (function-item gnus-thread-sort-by-subject)
667                          (function-item gnus-thread-sort-by-date)
668                          (function-item gnus-thread-sort-by-score)
669                          (function-item gnus-thread-sort-by-total-score)
670                          (function :tag "other"))))
671
672 (defcustom gnus-thread-score-function '+
673   "*Function used for calculating the total score of a thread.
674
675 The function is called with the scores of the article and each
676 subthread and should then return the score of the thread.
677
678 Some functions you can use are `+', `max', or `min'."
679   :group 'gnus-summary-sort
680   :type 'function)
681
682 (defcustom gnus-summary-expunge-below nil
683   "All articles that have a score less than this variable will be expunged.
684 This variable is local to the summary buffers."
685   :group 'gnus-score-default
686   :type '(choice (const :tag "off" nil)
687                  integer))
688
689 (defcustom gnus-thread-expunge-below nil
690   "All threads that have a total score less than this variable will be expunged.
691 See `gnus-thread-score-function' for en explanation of what a
692 \"thread score\" is.
693
694 This variable is local to the summary buffers."
695   :group 'gnus-threading
696   :group 'gnus-score-default
697   :type '(choice (const :tag "off" nil)
698                  integer))
699
700 (defcustom gnus-summary-mode-hook nil
701   "*A hook for Gnus summary mode.
702 This hook is run before any variables are set in the summary buffer."
703   :options '(turn-on-gnus-mailing-list-mode gnus-pick-mode)
704   :group 'gnus-summary-various
705   :type 'hook)
706
707 ;; Extracted from gnus-xmas-redefine in order to preserve user settings
708 (when (featurep 'xemacs)
709   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-summary-menu-add)
710   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-setup-summary-toolbar)
711   (add-hook 'gnus-summary-mode-hook
712             'gnus-xmas-switch-horizontal-scrollbar-off))
713
714 (defcustom gnus-summary-menu-hook nil
715   "*Hook run after the creation of the summary mode menu."
716   :group 'gnus-summary-visual
717   :type 'hook)
718
719 (defcustom gnus-summary-exit-hook nil
720   "*A hook called on exit from the summary buffer.
721 It will be called with point in the group buffer."
722   :group 'gnus-summary-exit
723   :type 'hook)
724
725 (defcustom gnus-summary-prepare-hook nil
726   "*A hook called after the summary buffer has been generated.
727 If you want to modify the summary buffer, you can use this hook."
728   :group 'gnus-summary-various
729   :type 'hook)
730
731 (defcustom gnus-summary-prepared-hook nil
732   "*A hook called as the last thing after the summary buffer has been generated."
733   :group 'gnus-summary-various
734   :type 'hook)
735
736 (defcustom gnus-summary-generate-hook nil
737   "*A hook run just before generating the summary buffer.
738 This hook is commonly used to customize threading variables and the
739 like."
740   :group 'gnus-summary-various
741   :type 'hook)
742
743 (defcustom gnus-select-group-hook nil
744   "*A hook called when a newsgroup is selected.
745
746 If you'd like to simplify subjects like the
747 `gnus-summary-next-same-subject' command does, you can use the
748 following hook:
749
750  (setq gnus-select-group-hook
751       (list
752         (lambda ()
753           (mapcar (lambda (header)
754                      (mail-header-set-subject
755                       header
756                       (gnus-simplify-subject
757                        (mail-header-subject header) 're-only)))
758                   gnus-newsgroup-headers))))"
759   :group 'gnus-group-select
760   :type 'hook)
761
762 (defcustom gnus-select-article-hook nil
763   "*A hook called when an article is selected."
764   :group 'gnus-summary-choose
765   :type 'hook)
766
767 (defcustom gnus-visual-mark-article-hook
768   (list 'gnus-highlight-selected-summary)
769   "*Hook run after selecting an article in the summary buffer.
770 It is meant to be used for highlighting the article in some way.  It
771 is not run if `gnus-visual' is nil."
772   :group 'gnus-summary-visual
773   :type 'hook)
774
775 (defcustom gnus-parse-headers-hook nil
776   "*A hook called before parsing the headers."
777   :group 'gnus-various
778   :type 'hook)
779
780 (defcustom gnus-exit-group-hook nil
781   "*A hook called when exiting summary mode.
782 This hook is not called from the non-updating exit commands like `Q'."
783   :group 'gnus-various
784   :type 'hook)
785
786 (defcustom gnus-summary-update-hook
787   (list 'gnus-summary-highlight-line)
788   "*A hook called when a summary line is changed.
789 The hook will not be called if `gnus-visual' is nil.
790
791 The default function `gnus-summary-highlight-line' will
792 highlight the line according to the `gnus-summary-highlight'
793 variable."
794   :group 'gnus-summary-visual
795   :type 'hook)
796
797 (defcustom gnus-mark-article-hook '(gnus-summary-mark-read-and-unread-as-read)
798   "*A hook called when an article is selected for the first time.
799 The hook is intended to mark an article as read (or unread)
800 automatically when it is selected."
801   :group 'gnus-summary-choose
802   :type 'hook)
803
804 (defcustom gnus-group-no-more-groups-hook nil
805   "*A hook run when returning to group mode having no more (unread) groups."
806   :group 'gnus-group-select
807   :type 'hook)
808
809 (defcustom gnus-ps-print-hook nil
810   "*A hook run before ps-printing something from Gnus."
811   :group 'gnus-summary
812   :type 'hook)
813
814 (defcustom gnus-summary-display-arrow
815   (and (fboundp 'display-graphic-p)
816        (display-graphic-p))
817   "*If non-nil, display an arrow highlighting the current article."
818   :version "21.1"
819   :group 'gnus-summary
820   :type 'boolean)
821
822 (defcustom gnus-summary-selected-face 'gnus-summary-selected-face
823   "Face used for highlighting the current article in the summary buffer."
824   :group 'gnus-summary-visual
825   :type 'face)
826
827 (defcustom gnus-summary-highlight
828   '(((= mark gnus-canceled-mark)
829      . gnus-summary-cancelled-face)
830     ((and (> score default-high)
831           (or (= mark gnus-dormant-mark)
832               (= mark gnus-ticked-mark)))
833      . gnus-summary-high-ticked-face)
834     ((and (< score default-low)
835           (or (= mark gnus-dormant-mark)
836               (= mark gnus-ticked-mark)))
837      . gnus-summary-low-ticked-face)
838     ((or (= mark gnus-dormant-mark)
839          (= mark gnus-ticked-mark))
840      . gnus-summary-normal-ticked-face)
841     ((and (> score default-high) (= mark gnus-ancient-mark))
842      . gnus-summary-high-ancient-face)
843     ((and (< score default-low) (= mark gnus-ancient-mark))
844      . gnus-summary-low-ancient-face)
845     ((= mark gnus-ancient-mark)
846      . gnus-summary-normal-ancient-face)
847     ((and (> score default-high) (= mark gnus-unread-mark))
848      . gnus-summary-high-unread-face)
849     ((and (< score default-low) (= mark gnus-unread-mark))
850      . gnus-summary-low-unread-face)
851     ((= mark gnus-unread-mark)
852      . gnus-summary-normal-unread-face)
853     ((and (> score default-high) (memq mark (list gnus-downloadable-mark
854                                                   gnus-undownloaded-mark)))
855      . gnus-summary-high-unread-face)
856     ((and (< score default-low) (memq mark (list gnus-downloadable-mark
857                                                  gnus-undownloaded-mark)))
858      . gnus-summary-low-unread-face)
859     ((and (memq mark (list gnus-downloadable-mark gnus-undownloaded-mark))
860           (memq article gnus-newsgroup-unreads))
861      . gnus-summary-normal-unread-face)
862     ((memq mark (list gnus-downloadable-mark gnus-undownloaded-mark))
863      . gnus-summary-normal-read-face)
864     ((> score default-high)
865      . gnus-summary-high-read-face)
866     ((< score default-low)
867      . gnus-summary-low-read-face)
868     (t
869      . gnus-summary-normal-read-face))
870   "*Controls the highlighting of summary buffer lines.
871
872 A list of (FORM . FACE) pairs.  When deciding how a a particular
873 summary line should be displayed, each form is evaluated.  The content
874 of the face field after the first true form is used.  You can change
875 how those summary lines are displayed, by editing the face field.
876
877 You can use the following variables in the FORM field.
878
879 score:        The article's score
880 default:      The default article score.
881 default-high: The default score for high scored articles.
882 default-low:  The default score for low scored articles.
883 below:        The score below which articles are automatically marked as read.
884 mark:         The articles mark."
885   :group 'gnus-summary-visual
886   :type '(repeat (cons (sexp :tag "Form" nil)
887                        face)))
888
889 (defcustom gnus-alter-header-function nil
890   "Function called to allow alteration of article header structures.
891 The function is called with one parameter, the article header vector,
892 which it may alter in any way.")
893
894 (defvar gnus-decode-encoded-word-function 'mail-decode-encoded-word-string
895   "Variable that says which function should be used to decode a string with encoded words.")
896
897 (defcustom gnus-extra-headers nil
898   "*Extra headers to parse."
899   :version "21.1"
900   :group 'gnus-summary
901   :type '(repeat symbol))
902
903 (defcustom gnus-ignored-from-addresses
904   (and user-mail-address (regexp-quote user-mail-address))
905   "*Regexp of From headers that may be suppressed in favor of To headers."
906   :version "21.1"
907   :group 'gnus-summary
908   :type 'regexp)
909
910 (defcustom gnus-newsgroup-ignored-charsets '(unknown-8bit x-unknown)
911   "List of charsets that should be ignored.
912 When these charsets are used in the \"charset\" parameter, the
913 default charset will be used instead."
914   :version "21.1"
915   :type '(repeat symbol)
916   :group 'gnus-charset)
917
918 (gnus-define-group-parameter
919  ignored-charsets
920  :type list
921  :function-document
922  "Return the ignored charsets of GROUP."
923  :variable gnus-group-ignored-charsets-alist
924  :variable-default
925  '(("alt\\.chinese\\.text" iso-8859-1))
926  :variable-document
927  "Alist of regexps (to match group names) and charsets that should be ignored.
928 When these charsets are used in the \"charset\" parameter, the
929 default charset will be used instead."
930  :variable-group gnus-charset
931  :variable-type '(repeat (cons (regexp :tag "Group")
932                                (repeat symbol)))
933  :parameter-type '(choice :tag "Ignored charsets"
934                           :value nil
935                           (repeat (symbol)))
936  :parameter-document       "\
937 List of charsets that should be ignored.
938
939 When these charsets are used in the \"charset\" parameter, the
940 default charset will be used instead.")
941
942 (defcustom gnus-group-highlight-words-alist nil
943   "Alist of group regexps and highlight regexps.
944 This variable uses the same syntax as `gnus-emphasis-alist'."
945   :version "21.1"
946   :type '(repeat (cons (regexp :tag "Group")
947                        (repeat (list (regexp :tag "Highlight regexp")
948                                      (number :tag "Group for entire word" 0)
949                                      (number :tag "Group for displayed part" 0)
950                                      (symbol :tag "Face"
951                                              gnus-emphasis-highlight-words)))))
952   :group 'gnus-summary-visual)
953
954 (defcustom gnus-summary-show-article-charset-alist
955   nil
956   "Alist of number and charset.
957 The article will be shown with the charset corresponding to the
958 numbered argument.
959 For example: ((1 . cn-gb-2312) (2 . big5))."
960   :version "21.1"
961   :type '(repeat (cons (number :tag "Argument" 1)
962                        (symbol :tag "Charset")))
963   :group 'gnus-charset)
964
965 (defcustom gnus-preserve-marks t
966   "Whether marks are preserved when moving, copying and respooling messages."
967   :version "21.1"
968   :type 'boolean
969   :group 'gnus-summary-marks)
970
971 (defcustom gnus-alter-articles-to-read-function nil
972   "Function to be called to alter the list of articles to be selected."
973   :type '(choice (const nil) function)
974   :group 'gnus-summary)
975
976 (defcustom gnus-orphan-score nil
977   "*All orphans get this score added.  Set in the score file."
978   :group 'gnus-score-default
979   :type '(choice (const nil)
980                  integer))
981
982 (defcustom gnus-summary-save-parts-default-mime "image/.*"
983   "*A regexp to match MIME parts when saving multiple parts of a message
984 with gnus-summary-save-parts (X m). This regexp will be used by default
985 when prompting the user for which type of files to save."
986   :group 'gnus-summary
987   :type 'regexp)
988
989
990 (defcustom gnus-summary-save-parts-default-mime "image/.*"
991   "*A regexp to match MIME parts when saving multiple parts of a message
992 with gnus-summary-save-parts (X m). This regexp will be used by default
993 when prompting the user for which type of files to save."
994   :group 'gnus-summary
995   :type 'regexp)
996
997 (defcustom gnus-read-all-available-headers nil
998   "Whether Gnus should parse all headers made available to it.
999 This is mostly relevant for slow backends where the user may
1000 wish to widen the summary buffer to include all headers
1001 that were fetched.  Say, for nnultimate groups."
1002   :group 'gnus-summary
1003   :type '(choice boolean regexp))
1004
1005 (defcustom gnus-summary-muttprint-program "muttprint"
1006   "Command (and optional arguments) used to run Muttprint."
1007   :group 'gnus-summary
1008   :type 'string)
1009
1010 ;;; Internal variables
1011
1012 (defvar gnus-summary-display-cache nil)
1013 (defvar gnus-article-mime-handles nil)
1014 (defvar gnus-article-decoded-p nil)
1015 (defvar gnus-article-charset nil)
1016 (defvar gnus-article-ignored-charsets nil)
1017 (defvar gnus-scores-exclude-files nil)
1018 (defvar gnus-page-broken nil)
1019 (defvar gnus-inhibit-mime-unbuttonizing nil)
1020
1021 (defvar gnus-original-article nil)
1022 (defvar gnus-article-internal-prepare-hook nil)
1023 (defvar gnus-newsgroup-process-stack nil)
1024
1025 (defvar gnus-thread-indent-array nil)
1026 (defvar gnus-thread-indent-array-level gnus-thread-indent-level)
1027 (defvar gnus-sort-gathered-threads-function 'gnus-thread-sort-by-number
1028   "Function called to sort the articles within a thread after it has been gathered together.")
1029
1030 (defvar gnus-summary-save-parts-type-history nil)
1031 (defvar gnus-summary-save-parts-last-directory nil)
1032
1033 (defvar gnus-summary-save-parts-type-history nil)
1034 (defvar gnus-summary-save-parts-last-directory nil)
1035
1036 ;; Avoid highlighting in kill files.
1037 (defvar gnus-summary-inhibit-highlight nil)
1038 (defvar gnus-newsgroup-selected-overlay nil)
1039 (defvar gnus-inhibit-limiting nil)
1040 (defvar gnus-newsgroup-adaptive-score-file nil)
1041 (defvar gnus-current-score-file nil)
1042 (defvar gnus-current-move-group nil)
1043 (defvar gnus-current-copy-group nil)
1044 (defvar gnus-current-crosspost-group nil)
1045 (defvar gnus-newsgroup-display nil)
1046
1047 (defvar gnus-newsgroup-dependencies nil)
1048 (defvar gnus-newsgroup-adaptive nil)
1049 (defvar gnus-summary-display-article-function nil)
1050 (defvar gnus-summary-highlight-line-function nil
1051   "Function called after highlighting a summary line.")
1052
1053 (defvar gnus-summary-line-format-alist
1054   `((?N ,(macroexpand '(mail-header-number gnus-tmp-header)) ?d)
1055     (?S ,(macroexpand '(mail-header-subject gnus-tmp-header)) ?s)
1056     (?s gnus-tmp-subject-or-nil ?s)
1057     (?n gnus-tmp-name ?s)
1058     (?A (car (cdr (funcall gnus-extract-address-components gnus-tmp-from)))
1059         ?s)
1060     (?a (or (car (funcall gnus-extract-address-components gnus-tmp-from))
1061             gnus-tmp-from) ?s)
1062     (?F gnus-tmp-from ?s)
1063     (?x ,(macroexpand '(mail-header-xref gnus-tmp-header)) ?s)
1064     (?D ,(macroexpand '(mail-header-date gnus-tmp-header)) ?s)
1065     (?d (gnus-dd-mmm (mail-header-date gnus-tmp-header)) ?s)
1066     (?o (gnus-date-iso8601 (mail-header-date gnus-tmp-header)) ?s)
1067     (?M ,(macroexpand '(mail-header-id gnus-tmp-header)) ?s)
1068     (?r ,(macroexpand '(mail-header-references gnus-tmp-header)) ?s)
1069     (?c (or (mail-header-chars gnus-tmp-header) 0) ?d)
1070     (?L gnus-tmp-lines ?s)
1071     (?I gnus-tmp-indentation ?s)
1072     (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s)
1073     (?R gnus-tmp-replied ?c)
1074     (?\[ gnus-tmp-opening-bracket ?c)
1075     (?\] gnus-tmp-closing-bracket ?c)
1076     (?\> (make-string gnus-tmp-level ? ) ?s)
1077     (?\< (make-string (max 0 (- 20 gnus-tmp-level)) ? ) ?s)
1078     (?i gnus-tmp-score ?d)
1079     (?z gnus-tmp-score-char ?c)
1080     (?l (bbb-grouplens-score gnus-tmp-header) ?s)
1081     (?V (gnus-thread-total-score (and (boundp 'thread) (car thread))) ?d)
1082     (?U gnus-tmp-unread ?c)
1083     (?f (gnus-summary-from-or-to-or-newsgroups gnus-tmp-header gnus-tmp-from)
1084         ?s)
1085     (?t (gnus-summary-number-of-articles-in-thread
1086          (and (boundp 'thread) (car thread)) gnus-tmp-level)
1087         ?d)
1088     (?e (gnus-summary-number-of-articles-in-thread
1089          (and (boundp 'thread) (car thread)) gnus-tmp-level t)
1090         ?c)
1091     (?u gnus-tmp-user-defined ?s)
1092     (?P (gnus-pick-line-number) ?d)
1093     (?B gnus-tmp-thread-tree-header-string ?s)
1094     (user-date (gnus-user-date
1095                 ,(macroexpand '(mail-header-date gnus-tmp-header))) ?s))
1096   "An alist of format specifications that can appear in summary lines.
1097 These are paired with what variables they correspond with, along with
1098 the type of the variable (string, integer, character, etc).")
1099
1100 (defvar gnus-summary-dummy-line-format-alist
1101   `((?S gnus-tmp-subject ?s)
1102     (?N gnus-tmp-number ?d)
1103     (?u gnus-tmp-user-defined ?s)))
1104
1105 (defvar gnus-summary-mode-line-format-alist
1106   `((?G gnus-tmp-group-name ?s)
1107     (?g (gnus-short-group-name gnus-tmp-group-name) ?s)
1108     (?p (gnus-group-real-name gnus-tmp-group-name) ?s)
1109     (?A gnus-tmp-article-number ?d)
1110     (?Z gnus-tmp-unread-and-unselected ?s)
1111     (?V gnus-version ?s)
1112     (?U gnus-tmp-unread-and-unticked ?d)
1113     (?S gnus-tmp-subject ?s)
1114     (?e gnus-tmp-unselected ?d)
1115     (?u gnus-tmp-user-defined ?s)
1116     (?d (length gnus-newsgroup-dormant) ?d)
1117     (?t (length gnus-newsgroup-marked) ?d)
1118     (?r (length gnus-newsgroup-reads) ?d)
1119     (?z (gnus-summary-article-score gnus-tmp-article-number) ?d)
1120     (?E gnus-newsgroup-expunged-tally ?d)
1121     (?s (gnus-current-score-file-nondirectory) ?s)))
1122
1123 (defvar gnus-last-search-regexp nil
1124   "Default regexp for article search command.")
1125
1126 (defvar gnus-last-shell-command nil
1127   "Default shell command on article.")
1128
1129 (defvar gnus-newsgroup-begin nil)
1130 (defvar gnus-newsgroup-end nil)
1131 (defvar gnus-newsgroup-last-rmail nil)
1132 (defvar gnus-newsgroup-last-mail nil)
1133 (defvar gnus-newsgroup-last-folder nil)
1134 (defvar gnus-newsgroup-last-file nil)
1135 (defvar gnus-newsgroup-auto-expire nil)
1136 (defvar gnus-newsgroup-active nil)
1137
1138 (defvar gnus-newsgroup-data nil)
1139 (defvar gnus-newsgroup-data-reverse nil)
1140 (defvar gnus-newsgroup-limit nil)
1141 (defvar gnus-newsgroup-limits nil)
1142
1143 (defvar gnus-newsgroup-unreads nil
1144   "List of unread articles in the current newsgroup.")
1145
1146 (defvar gnus-newsgroup-unselected nil
1147   "List of unselected unread articles in the current newsgroup.")
1148
1149 (defvar gnus-newsgroup-reads nil
1150   "Alist of read articles and article marks in the current newsgroup.")
1151
1152 (defvar gnus-newsgroup-expunged-tally nil)
1153
1154 (defvar gnus-newsgroup-marked nil
1155   "List of ticked articles in the current newsgroup (a subset of unread art).")
1156
1157 (defvar gnus-newsgroup-killed nil
1158   "List of ranges of articles that have been through the scoring process.")
1159
1160 (defvar gnus-newsgroup-cached nil
1161   "List of articles that come from the article cache.")
1162
1163 (defvar gnus-newsgroup-saved nil
1164   "List of articles that have been saved.")
1165
1166 (defvar gnus-newsgroup-kill-headers nil)
1167
1168 (defvar gnus-newsgroup-replied nil
1169   "List of articles that have been replied to in the current newsgroup.")
1170
1171 (defvar gnus-newsgroup-forwarded nil
1172   "List of articles that have been forwarded in the current newsgroup.")
1173
1174 (defvar gnus-newsgroup-recent nil
1175   "List of articles that have are recent in the current newsgroup.")
1176
1177 (defvar gnus-newsgroup-expirable nil
1178   "List of articles in the current newsgroup that can be expired.")
1179
1180 (defvar gnus-newsgroup-processable nil
1181   "List of articles in the current newsgroup that can be processed.")
1182
1183 (defvar gnus-newsgroup-downloadable nil
1184   "List of articles in the current newsgroup that can be processed.")
1185
1186 (defvar gnus-newsgroup-undownloaded nil
1187   "List of articles in the current newsgroup that haven't been downloaded..")
1188
1189 (defvar gnus-newsgroup-unsendable nil
1190   "List of articles in the current newsgroup that won't be sent.")
1191
1192 (defvar gnus-newsgroup-bookmarks nil
1193   "List of articles in the current newsgroup that have bookmarks.")
1194
1195 (defvar gnus-newsgroup-dormant nil
1196   "List of dormant articles in the current newsgroup.")
1197
1198 (defvar gnus-newsgroup-unseen nil
1199   "List of unseen articles in the current newsgroup.")
1200
1201 (defvar gnus-newsgroup-seen nil
1202   "Range of seen articles in the current newsgroup.")
1203
1204 (defvar gnus-newsgroup-articles nil
1205   "List of articles in the current newsgroup.")
1206
1207 (defvar gnus-newsgroup-scored nil
1208   "List of scored articles in the current newsgroup.")
1209
1210 (defvar gnus-newsgroup-headers nil
1211   "List of article headers in the current newsgroup.")
1212
1213 (defvar gnus-newsgroup-threads nil)
1214
1215 (defvar gnus-newsgroup-prepared nil
1216   "Whether the current group has been prepared properly.")
1217
1218 (defvar gnus-newsgroup-ancient nil
1219   "List of `gnus-fetch-old-headers' articles in the current newsgroup.")
1220
1221 (defvar gnus-newsgroup-sparse nil)
1222
1223 (defvar gnus-current-article nil)
1224 (defvar gnus-article-current nil)
1225 (defvar gnus-current-headers nil)
1226 (defvar gnus-have-all-headers nil)
1227 (defvar gnus-last-article nil)
1228 (defvar gnus-newsgroup-history nil)
1229 (defvar gnus-newsgroup-charset nil)
1230 (defvar gnus-newsgroup-ephemeral-charset nil)
1231 (defvar gnus-newsgroup-ephemeral-ignored-charsets nil)
1232
1233 (defvar gnus-article-before-search nil)
1234
1235 (defconst gnus-summary-local-variables
1236   '(gnus-newsgroup-name
1237     gnus-newsgroup-begin gnus-newsgroup-end
1238     gnus-newsgroup-last-rmail gnus-newsgroup-last-mail
1239     gnus-newsgroup-last-folder gnus-newsgroup-last-file
1240     gnus-newsgroup-auto-expire gnus-newsgroup-unreads
1241     gnus-newsgroup-unselected gnus-newsgroup-marked
1242     gnus-newsgroup-reads gnus-newsgroup-saved
1243     gnus-newsgroup-replied gnus-newsgroup-forwarded
1244     gnus-newsgroup-recent
1245     gnus-newsgroup-expirable
1246     gnus-newsgroup-processable gnus-newsgroup-killed
1247     gnus-newsgroup-downloadable gnus-newsgroup-undownloaded
1248     gnus-newsgroup-unsendable gnus-newsgroup-unseen
1249     gnus-newsgroup-seen gnus-newsgroup-articles
1250     gnus-newsgroup-bookmarks gnus-newsgroup-dormant
1251     gnus-newsgroup-headers gnus-newsgroup-threads
1252     gnus-newsgroup-prepared gnus-summary-highlight-line-function
1253     gnus-current-article gnus-current-headers gnus-have-all-headers
1254     gnus-last-article gnus-article-internal-prepare-hook
1255     gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
1256     gnus-newsgroup-scored gnus-newsgroup-kill-headers
1257     gnus-thread-expunge-below
1258     gnus-score-alist gnus-current-score-file
1259     (gnus-summary-expunge-below . global)
1260     (gnus-summary-mark-below . global)
1261     (gnus-orphan-score . global)
1262     gnus-newsgroup-active gnus-scores-exclude-files
1263     gnus-newsgroup-history gnus-newsgroup-ancient
1264     gnus-newsgroup-sparse gnus-newsgroup-process-stack
1265     (gnus-newsgroup-adaptive . gnus-use-adaptive-scoring)
1266     gnus-newsgroup-adaptive-score-file (gnus-reffed-article-number . -1)
1267     (gnus-newsgroup-expunged-tally . 0)
1268     gnus-cache-removable-articles gnus-newsgroup-cached
1269     gnus-newsgroup-data gnus-newsgroup-data-reverse
1270     gnus-newsgroup-limit gnus-newsgroup-limits
1271     gnus-newsgroup-charset gnus-newsgroup-display)
1272   "Variables that are buffer-local to the summary buffers.")
1273
1274 (defvar gnus-newsgroup-variables nil
1275   "A list of variables that have separate values in different newsgroups.
1276 A list of newsgroup (summary buffer) local variables, or cons of
1277 variables and their default values (when the default values are not
1278 nil), that should be made global while the summary buffer is active.
1279 These variables can be used to set variables in the group parameters
1280 while still allowing them to affect operations done in other
1281 buffers. For example:
1282
1283 \(setq gnus-newsgroup-variables
1284      '(message-use-followup-to
1285        (gnus-visible-headers .
1286          \"^From:\\\\|^Newsgroups:\\\\|^Subject:\\\\|^Date:\\\\|^To:\")))
1287 ")
1288
1289 ;; Byte-compiler warning.
1290 (eval-when-compile (defvar gnus-article-mode-map))
1291
1292 ;; MIME stuff.
1293
1294 (defvar gnus-decode-encoded-word-methods
1295   '(mail-decode-encoded-word-string)
1296   "List of methods used to decode encoded words.
1297
1298 This variable is a list of FUNCTION or (REGEXP . FUNCTION).  If item
1299 is FUNCTION, FUNCTION will be apply to all newsgroups.  If item is a
1300 \(REGEXP . FUNCTION), FUNCTION will be only apply to thes newsgroups
1301 whose names match REGEXP.
1302
1303 For example:
1304 \((\"chinese\" . gnus-decode-encoded-word-string-by-guess)
1305  mail-decode-encoded-word-string
1306  (\"chinese\" . rfc1843-decode-string))")
1307
1308 (defvar gnus-decode-encoded-word-methods-cache nil)
1309
1310 (defun gnus-multi-decode-encoded-word-string (string)
1311   "Apply the functions from `gnus-encoded-word-methods' that match."
1312   (unless (and gnus-decode-encoded-word-methods-cache
1313                (eq gnus-newsgroup-name
1314                    (car gnus-decode-encoded-word-methods-cache)))
1315     (setq gnus-decode-encoded-word-methods-cache (list gnus-newsgroup-name))
1316     (mapcar (lambda (x)
1317               (if (symbolp x)
1318                   (nconc gnus-decode-encoded-word-methods-cache (list x))
1319                 (if (and gnus-newsgroup-name
1320                          (string-match (car x) gnus-newsgroup-name))
1321                     (nconc gnus-decode-encoded-word-methods-cache
1322                            (list (cdr x))))))
1323             gnus-decode-encoded-word-methods))
1324   (let ((xlist gnus-decode-encoded-word-methods-cache))
1325     (pop xlist)
1326     (while xlist
1327       (setq string (funcall (pop xlist) string))))
1328   string)
1329
1330 ;; Subject simplification.
1331
1332 (defun gnus-simplify-whitespace (str)
1333   "Remove excessive whitespace from STR."
1334   (let ((mystr str))
1335     ;; Multiple spaces.
1336     (while (string-match "[ \t][ \t]+" mystr)
1337       (setq mystr (concat (substring mystr 0 (match-beginning 0))
1338                           " "
1339                           (substring mystr (match-end 0)))))
1340     ;; Leading spaces.
1341     (when (string-match "^[ \t]+" mystr)
1342       (setq mystr (substring mystr (match-end 0))))
1343     ;; Trailing spaces.
1344     (when (string-match "[ \t]+$" mystr)
1345       (setq mystr (substring mystr 0 (match-beginning 0))))
1346     mystr))
1347
1348 (defsubst gnus-simplify-subject-re (subject)
1349   "Remove \"Re:\" from subject lines."
1350   (if (string-match message-subject-re-regexp subject)
1351       (substring subject (match-end 0))
1352     subject))
1353
1354 (defun gnus-simplify-subject (subject &optional re-only)
1355   "Remove `Re:' and words in parentheses.
1356 If RE-ONLY is non-nil, strip leading `Re:'s only."
1357   (let ((case-fold-search t))           ;Ignore case.
1358     ;; Remove `Re:', `Re^N:', `Re(n)', and `Re[n]:'.
1359     (when (string-match "\\`\\(re\\([[(^][0-9]+[])]?\\)?:[ \t]*\\)+" subject)
1360       (setq subject (substring subject (match-end 0))))
1361     ;; Remove uninteresting prefixes.
1362     (when (and (not re-only)
1363                gnus-simplify-ignored-prefixes
1364                (string-match gnus-simplify-ignored-prefixes subject))
1365       (setq subject (substring subject (match-end 0))))
1366     ;; Remove words in parentheses from end.
1367     (unless re-only
1368       (while (string-match "[ \t\n]*([^()]*)[ \t\n]*\\'" subject)
1369         (setq subject (substring subject 0 (match-beginning 0)))))
1370     ;; Return subject string.
1371     subject))
1372
1373 ;; Remove any leading "re:"s, any trailing paren phrases, and simplify
1374 ;; all whitespace.
1375 (defsubst gnus-simplify-buffer-fuzzy-step (regexp &optional newtext)
1376   (goto-char (point-min))
1377   (while (re-search-forward regexp nil t)
1378     (replace-match (or newtext ""))))
1379
1380 (defun gnus-simplify-buffer-fuzzy ()
1381   "Simplify string in the buffer fuzzily.
1382 The string in the accessible portion of the current buffer is simplified.
1383 It is assumed to be a single-line subject.
1384 Whitespace is generally cleaned up, and miscellaneous leading/trailing
1385 matter is removed.  Additional things can be deleted by setting
1386 `gnus-simplify-subject-fuzzy-regexp'."
1387   (let ((case-fold-search t)
1388         (modified-tick))
1389     (gnus-simplify-buffer-fuzzy-step "\t" " ")
1390
1391     (while (not (eq modified-tick (buffer-modified-tick)))
1392       (setq modified-tick (buffer-modified-tick))
1393       (cond
1394        ((listp gnus-simplify-subject-fuzzy-regexp)
1395         (mapcar 'gnus-simplify-buffer-fuzzy-step
1396                 gnus-simplify-subject-fuzzy-regexp))
1397        (gnus-simplify-subject-fuzzy-regexp
1398         (gnus-simplify-buffer-fuzzy-step gnus-simplify-subject-fuzzy-regexp)))
1399       (gnus-simplify-buffer-fuzzy-step "^ *\\[[-+?*!][-+?*!]\\] *")
1400       (gnus-simplify-buffer-fuzzy-step
1401        "^ *\\(re\\|fw\\|fwd\\)[[{(^0-9]*[])}]?[:;] *")
1402       (gnus-simplify-buffer-fuzzy-step "^[[].*:\\( .*\\)[]]$" "\\1"))
1403
1404     (gnus-simplify-buffer-fuzzy-step " *[[{(][^()\n]*[]})] *$")
1405     (gnus-simplify-buffer-fuzzy-step "  +" " ")
1406     (gnus-simplify-buffer-fuzzy-step " $")
1407     (gnus-simplify-buffer-fuzzy-step "^ +")))
1408
1409 (defun gnus-simplify-subject-fuzzy (subject)
1410   "Simplify a subject string fuzzily.
1411 See `gnus-simplify-buffer-fuzzy' for details."
1412   (save-excursion
1413     (gnus-set-work-buffer)
1414     (let ((case-fold-search t))
1415       ;; Remove uninteresting prefixes.
1416       (when (and gnus-simplify-ignored-prefixes
1417                  (string-match gnus-simplify-ignored-prefixes subject))
1418         (setq subject (substring subject (match-end 0))))
1419       (insert subject)
1420       (inline (gnus-simplify-buffer-fuzzy))
1421       (buffer-string))))
1422
1423 (defsubst gnus-simplify-subject-fully (subject)
1424   "Simplify a subject string according to gnus-summary-gather-subject-limit."
1425   (cond
1426    (gnus-simplify-subject-functions
1427     (gnus-map-function gnus-simplify-subject-functions subject))
1428    ((null gnus-summary-gather-subject-limit)
1429     (gnus-simplify-subject-re subject))
1430    ((eq gnus-summary-gather-subject-limit 'fuzzy)
1431     (gnus-simplify-subject-fuzzy subject))
1432    ((numberp gnus-summary-gather-subject-limit)
1433     (gnus-limit-string (gnus-simplify-subject-re subject)
1434                        gnus-summary-gather-subject-limit))
1435    (t
1436     subject)))
1437
1438 (defsubst gnus-subject-equal (s1 s2 &optional simple-first)
1439   "Check whether two subjects are equal.
1440 If optional argument simple-first is t, first argument is already
1441 simplified."
1442   (cond
1443    ((null simple-first)
1444     (equal (gnus-simplify-subject-fully s1)
1445            (gnus-simplify-subject-fully s2)))
1446    (t
1447     (equal s1
1448            (gnus-simplify-subject-fully s2)))))
1449
1450 (defun gnus-summary-bubble-group ()
1451   "Increase the score of the current group.
1452 This is a handy function to add to `gnus-summary-exit-hook' to
1453 increase the score of each group you read."
1454   (gnus-group-add-score gnus-newsgroup-name))
1455
1456 \f
1457 ;;;
1458 ;;; Gnus summary mode
1459 ;;;
1460
1461 (put 'gnus-summary-mode 'mode-class 'special)
1462
1463 (defvar gnus-article-commands-menu)
1464
1465 (when t
1466   ;; Non-orthogonal keys
1467
1468   (gnus-define-keys gnus-summary-mode-map
1469     " " gnus-summary-next-page
1470     "\177" gnus-summary-prev-page
1471     [delete] gnus-summary-prev-page
1472     [backspace] gnus-summary-prev-page
1473     "\r" gnus-summary-scroll-up
1474     "\M-\r" gnus-summary-scroll-down
1475     "n" gnus-summary-next-unread-article
1476     "p" gnus-summary-prev-unread-article
1477     "N" gnus-summary-next-article
1478     "P" gnus-summary-prev-article
1479     "\M-\C-n" gnus-summary-next-same-subject
1480     "\M-\C-p" gnus-summary-prev-same-subject
1481     "\M-n" gnus-summary-next-unread-subject
1482     "\M-p" gnus-summary-prev-unread-subject
1483     "." gnus-summary-first-unread-article
1484     "," gnus-summary-best-unread-article
1485     "\M-s" gnus-summary-search-article-forward
1486     "\M-r" gnus-summary-search-article-backward
1487     "<" gnus-summary-beginning-of-article
1488     ">" gnus-summary-end-of-article
1489     "j" gnus-summary-goto-article
1490     "^" gnus-summary-refer-parent-article
1491     "\M-^" gnus-summary-refer-article
1492     "u" gnus-summary-tick-article-forward
1493     "!" gnus-summary-tick-article-forward
1494     "U" gnus-summary-tick-article-backward
1495     "d" gnus-summary-mark-as-read-forward
1496     "D" gnus-summary-mark-as-read-backward
1497     "E" gnus-summary-mark-as-expirable
1498     "\M-u" gnus-summary-clear-mark-forward
1499     "\M-U" gnus-summary-clear-mark-backward
1500     "k" gnus-summary-kill-same-subject-and-select
1501     "\C-k" gnus-summary-kill-same-subject
1502     "\M-\C-k" gnus-summary-kill-thread
1503     "\M-\C-l" gnus-summary-lower-thread
1504     "e" gnus-summary-edit-article
1505     "#" gnus-summary-mark-as-processable
1506     "\M-#" gnus-summary-unmark-as-processable
1507     "\M-\C-t" gnus-summary-toggle-threads
1508     "\M-\C-s" gnus-summary-show-thread
1509     "\M-\C-h" gnus-summary-hide-thread
1510     "\M-\C-f" gnus-summary-next-thread
1511     "\M-\C-b" gnus-summary-prev-thread
1512     [(meta down)] gnus-summary-next-thread
1513     [(meta up)] gnus-summary-prev-thread
1514     "\M-\C-u" gnus-summary-up-thread
1515     "\M-\C-d" gnus-summary-down-thread
1516     "&" gnus-summary-execute-command
1517     "c" gnus-summary-catchup-and-exit
1518     "\C-w" gnus-summary-mark-region-as-read
1519     "\C-t" gnus-summary-toggle-truncation
1520     "?" gnus-summary-mark-as-dormant
1521     "\C-c\M-\C-s" gnus-summary-limit-include-expunged
1522     "\C-c\C-s\C-n" gnus-summary-sort-by-number
1523     "\C-c\C-s\C-l" gnus-summary-sort-by-lines
1524     "\C-c\C-s\C-c" gnus-summary-sort-by-chars
1525     "\C-c\C-s\C-a" gnus-summary-sort-by-author
1526     "\C-c\C-s\C-s" gnus-summary-sort-by-subject
1527     "\C-c\C-s\C-d" gnus-summary-sort-by-date
1528     "\C-c\C-s\C-i" gnus-summary-sort-by-score
1529     "\C-c\C-s\C-o" gnus-summary-sort-by-original
1530     "=" gnus-summary-expand-window
1531     "\C-x\C-s" gnus-summary-reselect-current-group
1532     "\M-g" gnus-summary-rescan-group
1533     "w" gnus-summary-stop-page-breaking
1534     "\C-c\C-r" gnus-summary-caesar-message
1535     "f" gnus-summary-followup
1536     "F" gnus-summary-followup-with-original
1537     "C" gnus-summary-cancel-article
1538     "r" gnus-summary-reply
1539     "R" gnus-summary-reply-with-original
1540     "\C-c\C-f" gnus-summary-mail-forward
1541     "o" gnus-summary-save-article
1542     "\C-o" gnus-summary-save-article-mail
1543     "|" gnus-summary-pipe-output
1544     "\M-k" gnus-summary-edit-local-kill
1545     "\M-K" gnus-summary-edit-global-kill
1546     ;; "V" gnus-version
1547     "\C-c\C-d" gnus-summary-describe-group
1548     "q" gnus-summary-exit
1549     "Q" gnus-summary-exit-no-update
1550     "\C-c\C-i" gnus-info-find-node
1551     gnus-mouse-2 gnus-mouse-pick-article
1552     "m" gnus-summary-mail-other-window
1553     "a" gnus-summary-post-news
1554     "i" gnus-summary-news-other-window
1555     "x" gnus-summary-limit-to-unread
1556     "s" gnus-summary-isearch-article
1557     "t" gnus-summary-toggle-header
1558     "g" gnus-summary-show-article
1559     "l" gnus-summary-goto-last-article
1560     "\C-c\C-v\C-v" gnus-uu-decode-uu-view
1561     "\C-d" gnus-summary-enter-digest-group
1562     "\M-\C-d" gnus-summary-read-document
1563     "\M-\C-e" gnus-summary-edit-parameters
1564     "\M-\C-a" gnus-summary-customize-parameters
1565     "\C-c\C-b" gnus-bug
1566     "*" gnus-cache-enter-article
1567     "\M-*" gnus-cache-remove-article
1568     "\M-&" gnus-summary-universal-argument
1569     "\C-l" gnus-recenter
1570     "I" gnus-summary-increase-score
1571     "L" gnus-summary-lower-score
1572     "\M-i" gnus-symbolic-argument
1573     "h" gnus-summary-select-article-buffer
1574
1575     "b" gnus-article-view-part
1576     "\M-t" gnus-summary-toggle-display-buttonized
1577
1578     "V" gnus-summary-score-map
1579     "X" gnus-uu-extract-map
1580     "S" gnus-summary-send-map)
1581
1582   ;; Sort of orthogonal keymap
1583   (gnus-define-keys (gnus-summary-mark-map "M" gnus-summary-mode-map)
1584     "t" gnus-summary-tick-article-forward
1585     "!" gnus-summary-tick-article-forward
1586     "d" gnus-summary-mark-as-read-forward
1587     "r" gnus-summary-mark-as-read-forward
1588     "c" gnus-summary-clear-mark-forward
1589     " " gnus-summary-clear-mark-forward
1590     "e" gnus-summary-mark-as-expirable
1591     "x" gnus-summary-mark-as-expirable
1592     "?" gnus-summary-mark-as-dormant
1593     "b" gnus-summary-set-bookmark
1594     "B" gnus-summary-remove-bookmark
1595     "#" gnus-summary-mark-as-processable
1596     "\M-#" gnus-summary-unmark-as-processable
1597     "S" gnus-summary-limit-include-expunged
1598     "C" gnus-summary-catchup
1599     "H" gnus-summary-catchup-to-here
1600     "h" gnus-summary-catchup-from-here
1601     "\C-c" gnus-summary-catchup-all
1602     "k" gnus-summary-kill-same-subject-and-select
1603     "K" gnus-summary-kill-same-subject
1604     "P" gnus-uu-mark-map)
1605
1606   (gnus-define-keys (gnus-summary-mscore-map "V" gnus-summary-mark-map)
1607     "c" gnus-summary-clear-above
1608     "u" gnus-summary-tick-above
1609     "m" gnus-summary-mark-above
1610     "k" gnus-summary-kill-below)
1611
1612   (gnus-define-keys (gnus-summary-limit-map "/" gnus-summary-mode-map)
1613     "/" gnus-summary-limit-to-subject
1614     "n" gnus-summary-limit-to-articles
1615     "w" gnus-summary-pop-limit
1616     "s" gnus-summary-limit-to-subject
1617     "a" gnus-summary-limit-to-author
1618     "u" gnus-summary-limit-to-unread
1619     "m" gnus-summary-limit-to-marks
1620     "M" gnus-summary-limit-exclude-marks
1621     "v" gnus-summary-limit-to-score
1622     "*" gnus-summary-limit-include-cached
1623     "D" gnus-summary-limit-include-dormant
1624     "T" gnus-summary-limit-include-thread
1625     "d" gnus-summary-limit-exclude-dormant
1626     "t" gnus-summary-limit-to-age
1627     "x" gnus-summary-limit-to-extra
1628     "p" gnus-summary-limit-to-display-predicate
1629     "E" gnus-summary-limit-include-expunged
1630     "c" gnus-summary-limit-exclude-childless-dormant
1631     "C" gnus-summary-limit-mark-excluded-as-read
1632     "o" gnus-summary-insert-old-articles
1633     "N" gnus-summary-insert-new-articles)
1634
1635   (gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map)
1636     "n" gnus-summary-next-unread-article
1637     "p" gnus-summary-prev-unread-article
1638     "N" gnus-summary-next-article
1639     "P" gnus-summary-prev-article
1640     "\C-n" gnus-summary-next-same-subject
1641     "\C-p" gnus-summary-prev-same-subject
1642     "\M-n" gnus-summary-next-unread-subject
1643     "\M-p" gnus-summary-prev-unread-subject
1644     "f" gnus-summary-first-unread-article
1645     "b" gnus-summary-best-unread-article
1646     "j" gnus-summary-goto-article
1647     "g" gnus-summary-goto-subject
1648     "l" gnus-summary-goto-last-article
1649     "o" gnus-summary-pop-article)
1650
1651   (gnus-define-keys (gnus-summary-thread-map "T" gnus-summary-mode-map)
1652     "k" gnus-summary-kill-thread
1653     "l" gnus-summary-lower-thread
1654     "i" gnus-summary-raise-thread
1655     "T" gnus-summary-toggle-threads
1656     "t" gnus-summary-rethread-current
1657     "^" gnus-summary-reparent-thread
1658     "s" gnus-summary-show-thread
1659     "S" gnus-summary-show-all-threads
1660     "h" gnus-summary-hide-thread
1661     "H" gnus-summary-hide-all-threads
1662     "n" gnus-summary-next-thread
1663     "p" gnus-summary-prev-thread
1664     "u" gnus-summary-up-thread
1665     "o" gnus-summary-top-thread
1666     "d" gnus-summary-down-thread
1667     "#" gnus-uu-mark-thread
1668     "\M-#" gnus-uu-unmark-thread)
1669
1670   (gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map)
1671     "g" gnus-summary-prepare
1672     "c" gnus-summary-insert-cached-articles)
1673
1674   (gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map)
1675     "c" gnus-summary-catchup-and-exit
1676     "C" gnus-summary-catchup-all-and-exit
1677     "E" gnus-summary-exit-no-update
1678     "Q" gnus-summary-exit
1679     "Z" gnus-summary-exit
1680     "n" gnus-summary-catchup-and-goto-next-group
1681     "R" gnus-summary-reselect-current-group
1682     "G" gnus-summary-rescan-group
1683     "N" gnus-summary-next-group
1684     "s" gnus-summary-save-newsrc
1685     "P" gnus-summary-prev-group)
1686
1687   (gnus-define-keys (gnus-summary-article-map "A" gnus-summary-mode-map)
1688     " " gnus-summary-next-page
1689     "n" gnus-summary-next-page
1690     "\177" gnus-summary-prev-page
1691     [delete] gnus-summary-prev-page
1692     "p" gnus-summary-prev-page
1693     "\r" gnus-summary-scroll-up
1694     "\M-\r" gnus-summary-scroll-down
1695     "<" gnus-summary-beginning-of-article
1696     ">" gnus-summary-end-of-article
1697     "b" gnus-summary-beginning-of-article
1698     "e" gnus-summary-end-of-article
1699     "^" gnus-summary-refer-parent-article
1700     "r" gnus-summary-refer-parent-article
1701     "D" gnus-summary-enter-digest-group
1702     "R" gnus-summary-refer-references
1703     "T" gnus-summary-refer-thread
1704     "g" gnus-summary-show-article
1705     "s" gnus-summary-isearch-article
1706     "P" gnus-summary-print-article
1707     "M" gnus-mailing-list-insinuate
1708     "t" gnus-article-babel)
1709
1710   (gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map)
1711     "b" gnus-article-add-buttons
1712     "B" gnus-article-add-buttons-to-head
1713     "o" gnus-article-treat-overstrike
1714     "e" gnus-article-emphasize
1715     "w" gnus-article-fill-cited-article
1716     "Q" gnus-article-fill-long-lines
1717     "C" gnus-article-capitalize-sentences
1718     "c" gnus-article-remove-cr
1719     "q" gnus-article-de-quoted-unreadable
1720     "6" gnus-article-de-base64-unreadable
1721     "Z" gnus-article-decode-HZ
1722     "h" gnus-article-wash-html
1723     "s" gnus-summary-force-verify-and-decrypt
1724     "f" gnus-article-display-x-face
1725     "l" gnus-summary-stop-page-breaking
1726     "r" gnus-summary-caesar-message
1727     "t" gnus-summary-toggle-header
1728     "g" gnus-summary-toggle-smiley
1729     "u" gnus-article-treat-unfold-headers
1730     "n" gnus-article-treat-fold-newsgroups
1731     "v" gnus-summary-verbose-headers
1732     "a" gnus-article-strip-headers-in-body ;; mnemonic: wash archive
1733     "p" gnus-article-verify-x-pgp-sig
1734     "d" gnus-article-treat-dumbquotes)
1735
1736   (gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
1737     "a" gnus-article-hide
1738     "h" gnus-article-hide-headers
1739     "b" gnus-article-hide-boring-headers
1740     "s" gnus-article-hide-signature
1741     "c" gnus-article-hide-citation
1742     "C" gnus-article-hide-citation-in-followups
1743     "l" gnus-article-hide-list-identifiers
1744     "p" gnus-article-hide-pgp
1745     "B" gnus-article-strip-banner
1746     "P" gnus-article-hide-pem
1747     "\C-c" gnus-article-hide-citation-maybe)
1748
1749   (gnus-define-keys (gnus-summary-wash-highlight-map "H" gnus-summary-wash-map)
1750     "a" gnus-article-highlight
1751     "h" gnus-article-highlight-headers
1752     "c" gnus-article-highlight-citation
1753     "s" gnus-article-highlight-signature)
1754
1755   (gnus-define-keys (gnus-summary-wash-display-map "D" gnus-summary-wash-map)
1756     "x" gnus-article-display-x-face
1757     "s" gnus-summary-toggle-smiley
1758     "f" gnus-treat-from-picon
1759     "m" gnus-treat-mail-picon
1760     "n" gnus-treat-newsgroups-picon)
1761
1762   (gnus-define-keys (gnus-summary-wash-mime-map "M" gnus-summary-wash-map)
1763     "w" gnus-article-decode-mime-words
1764     "c" gnus-article-decode-charset
1765     "v" gnus-mime-view-all-parts
1766     "b" gnus-article-view-part)
1767
1768   (gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map)
1769     "z" gnus-article-date-ut
1770     "u" gnus-article-date-ut
1771     "l" gnus-article-date-local
1772     "p" gnus-article-date-english
1773     "e" gnus-article-date-lapsed
1774     "o" gnus-article-date-original
1775     "i" gnus-article-date-iso8601
1776     "s" gnus-article-date-user)
1777
1778   (gnus-define-keys (gnus-summary-wash-empty-map "E" gnus-summary-wash-map)
1779     "t" gnus-article-remove-trailing-blank-lines
1780     "l" gnus-article-strip-leading-blank-lines
1781     "m" gnus-article-strip-multiple-blank-lines
1782     "a" gnus-article-strip-blank-lines
1783     "A" gnus-article-strip-all-blank-lines
1784     "s" gnus-article-strip-leading-space
1785     "e" gnus-article-strip-trailing-space
1786     "w" gnus-article-remove-leading-whitespace)
1787
1788   (gnus-define-keys (gnus-summary-help-map "H" gnus-summary-mode-map)
1789     "v" gnus-version
1790     "f" gnus-summary-fetch-faq
1791     "d" gnus-summary-describe-group
1792     "h" gnus-summary-describe-briefly
1793     "i" gnus-info-find-node)
1794
1795   (gnus-define-keys (gnus-summary-backend-map "B" gnus-summary-mode-map)
1796     "e" gnus-summary-expire-articles
1797     "\M-\C-e" gnus-summary-expire-articles-now
1798     "\177" gnus-summary-delete-article
1799     [delete] gnus-summary-delete-article
1800     [backspace] gnus-summary-delete-article
1801     "m" gnus-summary-move-article
1802     "r" gnus-summary-respool-article
1803     "w" gnus-summary-edit-article
1804     "c" gnus-summary-copy-article
1805     "B" gnus-summary-crosspost-article
1806     "q" gnus-summary-respool-query
1807     "t" gnus-summary-respool-trace
1808     "i" gnus-summary-import-article
1809     "I" gnus-summary-create-article
1810     "p" gnus-summary-article-posted-p)
1811
1812   (gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map)
1813     "o" gnus-summary-save-article
1814     "m" gnus-summary-save-article-mail
1815     "F" gnus-summary-write-article-file
1816     "r" gnus-summary-save-article-rmail
1817     "f" gnus-summary-save-article-file
1818     "b" gnus-summary-save-article-body-file
1819     "h" gnus-summary-save-article-folder
1820     "v" gnus-summary-save-article-vm
1821     "p" gnus-summary-pipe-output
1822     "P" gnus-summary-muttprint
1823     "s" gnus-soup-add-article)
1824
1825   (gnus-define-keys (gnus-summary-mime-map "K" gnus-summary-mode-map)
1826     "b" gnus-summary-display-buttonized
1827     "m" gnus-summary-repair-multipart
1828     "v" gnus-article-view-part
1829     "o" gnus-article-save-part
1830     "c" gnus-article-copy-part
1831     "C" gnus-article-view-part-as-charset
1832     "e" gnus-article-externalize-part
1833     "E" gnus-article-encrypt-body
1834     "i" gnus-article-inline-part
1835     "|" gnus-article-pipe-part))
1836
1837 (defvar gnus-article-post-menu nil)
1838
1839 (defun gnus-summary-make-menu-bar ()
1840   (gnus-turn-off-edit-menu 'summary)
1841
1842   (unless (boundp 'gnus-summary-misc-menu)
1843
1844     (easy-menu-define
1845       gnus-summary-kill-menu gnus-summary-mode-map ""
1846       (cons
1847        "Score"
1848        (nconc
1849         (list
1850          ["Customize" gnus-score-customize t])
1851         (gnus-make-score-map 'increase)
1852         (gnus-make-score-map 'lower)
1853         '(("Mark"
1854            ["Kill below" gnus-summary-kill-below t]
1855            ["Mark above" gnus-summary-mark-above t]
1856            ["Tick above" gnus-summary-tick-above t]
1857            ["Clear above" gnus-summary-clear-above t])
1858           ["Current score" gnus-summary-current-score t]
1859           ["Set score" gnus-summary-set-score t]
1860           ["Switch current score file..." gnus-score-change-score-file t]
1861           ["Set mark below..." gnus-score-set-mark-below t]
1862           ["Set expunge below..." gnus-score-set-expunge-below t]
1863           ["Edit current score file" gnus-score-edit-current-scores t]
1864           ["Edit score file" gnus-score-edit-file t]
1865           ["Trace score" gnus-score-find-trace t]
1866           ["Find words" gnus-score-find-favourite-words t]
1867           ["Rescore buffer" gnus-summary-rescore t]
1868           ["Increase score..." gnus-summary-increase-score t]
1869           ["Lower score..." gnus-summary-lower-score t]))))
1870
1871     ;; Define both the Article menu in the summary buffer and the
1872     ;; equivalent Commands menu in the article buffer here for
1873     ;; consistency.
1874     (let ((innards
1875            `(("Hide"
1876               ["All" gnus-article-hide t]
1877               ["Headers" gnus-article-hide-headers t]
1878               ["Signature" gnus-article-hide-signature t]
1879               ["Citation" gnus-article-hide-citation t]
1880               ["List identifiers" gnus-article-hide-list-identifiers t]
1881               ["PGP" gnus-article-hide-pgp t]
1882               ["Banner" gnus-article-strip-banner t]
1883               ["Boring headers" gnus-article-hide-boring-headers t])
1884              ("Highlight"
1885               ["All" gnus-article-highlight t]
1886               ["Headers" gnus-article-highlight-headers t]
1887               ["Signature" gnus-article-highlight-signature t]
1888               ["Citation" gnus-article-highlight-citation t])
1889              ("MIME"
1890               ["Words" gnus-article-decode-mime-words t]
1891               ["Charset" gnus-article-decode-charset t]
1892               ["QP" gnus-article-de-quoted-unreadable t]
1893               ["Base64" gnus-article-de-base64-unreadable t]
1894               ["View all" gnus-mime-view-all-parts t]
1895               ["Verify and Decrypt" gnus-summary-force-verify-and-decrypt t]
1896               ["Encrypt body" gnus-article-encrypt-body t])
1897              ("Date"
1898               ["Local" gnus-article-date-local t]
1899               ["ISO8601" gnus-article-date-iso8601 t]
1900               ["UT" gnus-article-date-ut t]
1901               ["Original" gnus-article-date-original t]
1902               ["Lapsed" gnus-article-date-lapsed t]
1903               ["User-defined" gnus-article-date-user t])
1904              ("Display"
1905               ["Toggle smiley" gnus-summary-toggle-smiley t]
1906               ["Show X-Face" gnus-article-display-x-face t]
1907               ["Show picons in From" gnus-treat-from-picon t]
1908               ["Show picons in mail headers" gnus-treat-mail-picon t]
1909               ["Show picons in news headers" gnus-treat-newsgroups-picon t])
1910              ("Washing"
1911               ("Remove Blanks"
1912                ["Leading" gnus-article-strip-leading-blank-lines t]
1913                ["Multiple" gnus-article-strip-multiple-blank-lines t]
1914                ["Trailing" gnus-article-remove-trailing-blank-lines t]
1915                ["All of the above" gnus-article-strip-blank-lines t]
1916                ["All" gnus-article-strip-all-blank-lines t]
1917                ["Leading space" gnus-article-strip-leading-space t]
1918                ["Trailing space" gnus-article-strip-trailing-space t]
1919                ["Leading space in headers"
1920                 gnus-article-remove-leading-whitespace t])
1921               ["Overstrike" gnus-article-treat-overstrike t]
1922               ["Dumb quotes" gnus-article-treat-dumbquotes t]
1923               ["Emphasis" gnus-article-emphasize t]
1924               ["Word wrap" gnus-article-fill-cited-article t]
1925               ["Fill long lines" gnus-article-fill-long-lines t]
1926               ["Capitalize sentences" gnus-article-capitalize-sentences t]
1927               ["CR" gnus-article-remove-cr t]
1928               ["Quoted-Printable" gnus-article-de-quoted-unreadable t]
1929               ["Base64" gnus-article-de-base64-unreadable t]
1930               ["Rot 13" gnus-summary-caesar-message
1931                ,@(if (featurep 'xemacs) '(t)
1932                    '(:help "\"Caesar rotate\" article by 13"))]
1933               ["Unix pipe" gnus-summary-pipe-message t]
1934               ["Add buttons" gnus-article-add-buttons t]
1935               ["Add buttons to head" gnus-article-add-buttons-to-head t]
1936               ["Stop page breaking" gnus-summary-stop-page-breaking t]
1937               ["Verbose header" gnus-summary-verbose-headers t]
1938               ["Toggle header" gnus-summary-toggle-header t]
1939               ["Unfold headers" gnus-article-treat-unfold-headers t]
1940               ["Fold newsgroups" gnus-article-treat-fold-newsgroups t]
1941               ["Html" gnus-article-wash-html t]
1942               ["Verify X-PGP-Sig" gnus-article-verify-x-pgp-sig t]
1943               ["HZ" gnus-article-decode-HZ t])
1944              ("Output"
1945               ["Save in default format" gnus-summary-save-article
1946                ,@(if (featurep 'xemacs) '(t)
1947                    '(:help "Save article using default method"))]
1948               ["Save in file" gnus-summary-save-article-file
1949                ,@(if (featurep 'xemacs) '(t)
1950                    '(:help "Save article in file"))]
1951               ["Save in Unix mail format" gnus-summary-save-article-mail t]
1952               ["Save in MH folder" gnus-summary-save-article-folder t]
1953               ["Save in VM folder" gnus-summary-save-article-vm t]
1954               ["Save in RMAIL mbox" gnus-summary-save-article-rmail t]
1955               ["Save body in file" gnus-summary-save-article-body-file t]
1956               ["Pipe through a filter" gnus-summary-pipe-output t]
1957               ["Add to SOUP packet" gnus-soup-add-article t]
1958               ["Print with Muttprint" gnus-summary-muttprint t]
1959               ["Print" gnus-summary-print-article t])
1960              ("Backend"
1961               ["Respool article..." gnus-summary-respool-article t]
1962               ["Move article..." gnus-summary-move-article
1963                (gnus-check-backend-function
1964                 'request-move-article gnus-newsgroup-name)]
1965               ["Copy article..." gnus-summary-copy-article t]
1966               ["Crosspost article..." gnus-summary-crosspost-article
1967                (gnus-check-backend-function
1968                 'request-replace-article gnus-newsgroup-name)]
1969               ["Import file..." gnus-summary-import-article t]
1970               ["Create article..." gnus-summary-create-article t]
1971               ["Check if posted" gnus-summary-article-posted-p t]
1972               ["Edit article" gnus-summary-edit-article
1973                (not (gnus-group-read-only-p))]
1974               ["Delete article" gnus-summary-delete-article
1975                (gnus-check-backend