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