925e7968e8f4a68db5c21a266ff800df2f7590f4
[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 ;; Recursive :-(.
40 ;; (require 'gnus-art)
41 (require 'nnoo)
42 (autoload 'gnus-summary-limit-include-cached "gnus-cache" nil t)
43 (autoload 'gnus-cache-write-active "gnus-cache")
44 (autoload 'gnus-mailing-list-insinuate "gnus-ml" nil t)
45 (autoload 'turn-on-gnus-mailing-list-mode "gnus-ml" nil t)
46 (autoload 'mm-uu-dissect "mm-uu")
47
48 (defcustom gnus-kill-summary-on-exit t
49   "*If non-nil, kill the summary buffer when you exit from it.
50 If nil, the summary will become a \"*Dead Summary*\" buffer, and
51 it will be killed sometime later."
52   :group 'gnus-summary-exit
53   :type 'boolean)
54
55 (defcustom gnus-fetch-old-headers nil
56   "*Non-nil means that Gnus will try to build threads by grabbing old headers.
57 If an unread article in the group refers to an older, already read (or
58 just marked as read) article, the old article will not normally be
59 displayed in the Summary buffer.  If this variable is non-nil, Gnus
60 will attempt to grab the headers to the old articles, and thereby
61 build complete threads.  If it has the value `some', only enough
62 headers to connect otherwise loose threads will be displayed.  This
63 variable can also be a number.  In that case, no more than that number
64 of old headers will be fetched.  If it has the value `invisible', all
65 old headers will be fetched, but none will be displayed.
66
67 The server has to support NOV for any of this to work."
68   :group 'gnus-thread
69   :type '(choice (const :tag "off" nil)
70                  (const some)
71                  number
72                  (sexp :menu-tag "other" t)))
73
74 (defcustom gnus-refer-thread-limit 200
75   "*The number of old headers to fetch when doing \\<gnus-summary-mode-map>\\[gnus-summary-refer-thread].
76 If t, fetch all the available old headers."
77   :group 'gnus-thread
78   :type '(choice number
79                  (sexp :menu-tag "other" t)))
80
81 (defcustom gnus-summary-make-false-root 'adopt
82   "*nil means that Gnus won't gather loose threads.
83 If the root of a thread has expired or been read in a previous
84 session, the information necessary to build a complete thread has been
85 lost.  Instead of having many small sub-threads from this original thread
86 scattered all over the summary buffer, Gnus can gather them.
87
88 If non-nil, Gnus will try to gather all loose sub-threads from an
89 original thread into one large thread.
90
91 If this variable is non-nil, it should be one of `none', `adopt',
92 `dummy' or `empty'.
93
94 If this variable is `none', Gnus will not make a false root, but just
95 present the sub-threads after another.
96 If this variable is `dummy', Gnus will create a dummy root that will
97 have all the sub-threads as children.
98 If this variable is `adopt', Gnus will make one of the \"children\"
99 the parent and mark all the step-children as such.
100 If this variable is `empty', the \"children\" are printed with empty
101 subject fields.  (Or rather, they will be printed with a string
102 given by the `gnus-summary-same-subject' variable.)"
103   :group 'gnus-thread
104   :type '(choice (const :tag "off" nil)
105                  (const none)
106                  (const dummy)
107                  (const adopt)
108                  (const empty)))
109
110 (defcustom gnus-summary-gather-exclude-subject "^ *$\\|^(none)$"
111   "*A regexp to match subjects to be excluded from loose thread gathering.
112 As loose thread gathering is done on subjects only, that means that
113 there can be many false gatherings performed.  By rooting out certain
114 common subjects, gathering might become saner."
115   :group 'gnus-thread
116   :type 'regexp)
117
118 (defcustom gnus-summary-gather-subject-limit nil
119   "*Maximum length of subject comparisons when gathering loose threads.
120 Use nil to compare full subjects.  Setting this variable to a low
121 number will help gather threads that have been corrupted by
122 newsreaders chopping off subject lines, but it might also mean that
123 unrelated articles that have subject that happen to begin with the
124 same few characters will be incorrectly gathered.
125
126 If this variable is `fuzzy', Gnus will use a fuzzy algorithm when
127 comparing subjects."
128   :group 'gnus-thread
129   :type '(choice (const :tag "off" nil)
130                  (const fuzzy)
131                  (sexp :menu-tag "on" t)))
132
133 (defcustom gnus-simplify-subject-functions nil
134   "List of functions taking a string argument that simplify subjects.
135 The functions are applied recursively.
136
137 Useful functions to put in this list include: `gnus-simplify-subject-re',
138 `gnus-simplify-subject-fuzzy' and `gnus-simplify-whitespace'."
139   :group 'gnus-thread
140   :type '(repeat function))
141
142 (defcustom gnus-simplify-ignored-prefixes nil
143   "*Regexp, matches for which are removed from subject lines when simplifying fuzzily."
144   :group 'gnus-thread
145   :type '(choice (const :tag "off" nil)
146                  regexp))
147
148 (defcustom gnus-build-sparse-threads nil
149   "*If non-nil, fill in the gaps in threads.
150 If `some', only fill in the gaps that are needed to tie loose threads
151 together.  If `more', fill in all leaf nodes that Gnus can find.  If
152 non-nil and non-`some', fill in all gaps that Gnus manages to guess."
153   :group 'gnus-thread
154   :type '(choice (const :tag "off" nil)
155                  (const some)
156                  (const more)
157                  (sexp :menu-tag "all" t)))
158
159 (defcustom gnus-summary-thread-gathering-function
160   'gnus-gather-threads-by-subject
161   "*Function used for gathering loose threads.
162 There are two pre-defined functions: `gnus-gather-threads-by-subject',
163 which only takes Subjects into consideration; and
164 `gnus-gather-threads-by-references', which compared the References
165 headers of the articles to find matches."
166   :group 'gnus-thread
167   :type '(radio (function-item gnus-gather-threads-by-subject)
168                 (function-item gnus-gather-threads-by-references)
169                 (function :tag "other")))
170
171 (defcustom gnus-summary-same-subject ""
172   "*String indicating that the current article has the same subject as the previous.
173 This variable will only be used if the value of
174 `gnus-summary-make-false-root' is `empty'."
175   :group 'gnus-summary-format
176   :type 'string)
177
178 (defcustom gnus-summary-goto-unread t
179   "*If t, many commands will go to the next unread article.
180 This applies to marking commands as well as other commands that
181 \"naturally\" select the next article, like, for instance, `SPC' at
182 the end of an article.
183
184 If nil, the marking commands do NOT go to the next unread article
185 (they go to the next article instead).  If `never', commands that
186 usually go to the next unread article, will go to the next article,
187 whether it is read or not."
188   :group 'gnus-summary-marks
189   :link '(custom-manual "(gnus)Setting Marks")
190   :type '(choice (const :tag "off" nil)
191                  (const never)
192                  (sexp :menu-tag "on" t)))
193
194 (defcustom gnus-summary-default-score 0
195   "*Default article score level.
196 All scores generated by the score files will be added to this score.
197 If this variable is nil, scoring will be disabled."
198   :group 'gnus-score-default
199   :type '(choice (const :tag "disable")
200                  integer))
201
202 (defcustom gnus-summary-zcore-fuzz 0
203   "*Fuzziness factor for the zcore in the summary buffer.
204 Articles with scores closer than this to `gnus-summary-default-score'
205 will not be marked."
206   :group 'gnus-summary-format
207   :type 'integer)
208
209 (defcustom gnus-simplify-subject-fuzzy-regexp nil
210   "*Strings to be removed when doing fuzzy matches.
211 This can either be a regular expression or list of regular expressions
212 that will be removed from subject strings if fuzzy subject
213 simplification is selected."
214   :group 'gnus-thread
215   :type '(repeat regexp))
216
217 (defcustom gnus-show-threads t
218   "*If non-nil, display threads in summary mode."
219   :group 'gnus-thread
220   :type 'boolean)
221
222 (defcustom gnus-thread-hide-subtree nil
223   "*If non-nil, hide all threads initially.
224 If threads are hidden, you have to run the command
225 `gnus-summary-show-thread' by hand or use `gnus-select-article-hook'
226 to expose hidden threads."
227   :group 'gnus-thread
228   :type 'boolean)
229
230 (defcustom gnus-thread-hide-killed t
231   "*If non-nil, hide killed threads automatically."
232   :group 'gnus-thread
233   :type 'boolean)
234
235 (defcustom gnus-thread-ignore-subject t
236   "*If non-nil, which is the default, ignore subjects and do all threading based on the Reference header.
237 If nil, articles that have different subjects from their parents will
238 start separate threads."
239   :group 'gnus-thread
240   :type 'boolean)
241
242 (defcustom gnus-thread-operation-ignore-subject t
243   "*If non-nil, subjects will be ignored when doing thread commands.
244 This affects commands like `gnus-summary-kill-thread' and
245 `gnus-summary-lower-thread'.
246
247 If this variable is nil, articles in the same thread with different
248 subjects will not be included in the operation in question.  If this
249 variable is `fuzzy', only articles that have subjects that are fuzzily
250 equal will be included."
251   :group 'gnus-thread
252   :type '(choice (const :tag "off" nil)
253                  (const fuzzy)
254                  (sexp :tag "on" t)))
255
256 (defcustom gnus-thread-indent-level 4
257   "*Number that says how much each sub-thread should be indented."
258   :group 'gnus-thread
259   :type 'integer)
260
261 (defcustom gnus-auto-extend-newsgroup t
262   "*If non-nil, extend newsgroup forward and backward when requested."
263   :group 'gnus-summary-choose
264   :type 'boolean)
265
266 (defcustom gnus-auto-select-first t
267   "*If nil, don't select the first unread article when entering a group.
268 If this variable is `best', select the highest-scored unread article
269 in the group.  If t, select the first unread article.
270
271 This variable can also be a function to place point on a likely
272 subject line.  Useful values include `gnus-summary-first-unread-subject',
273 `gnus-summary-first-unread-article' and
274 `gnus-summary-best-unread-article'.
275
276 If you want to prevent automatic selection of the first unread article
277 in some newsgroups, set the variable to nil in
278 `gnus-select-group-hook'."
279   :group 'gnus-group-select
280   :type '(choice (const :tag "none" nil)
281                  (const best)
282                  (sexp :menu-tag "first" t)
283                  (function-item gnus-summary-first-unread-subject)
284                  (function-item gnus-summary-first-unread-article)
285                  (function-item gnus-summary-best-unread-article)))
286
287 (defcustom gnus-auto-select-next t
288   "*If non-nil, offer to go to the next group from the end of the previous.
289 If the value is t and the next newsgroup is empty, Gnus will exit
290 summary mode and go back to group mode.  If the value is neither nil
291 nor t, Gnus will select the following unread newsgroup.  In
292 particular, if the value is the symbol `quietly', the next unread
293 newsgroup will be selected without any confirmation, and if it is
294 `almost-quietly', the next group will be selected without any
295 confirmation if you are located on the last article in the group.
296 Finally, if this variable is `slightly-quietly', the `Z n' command
297 will go to the next group without confirmation."
298   :group 'gnus-summary-maneuvering
299   :type '(choice (const :tag "off" nil)
300                  (const quietly)
301                  (const almost-quietly)
302                  (const slightly-quietly)
303                  (sexp :menu-tag "on" t)))
304
305 (defcustom gnus-auto-select-same nil
306   "*If non-nil, select the next article with the same subject.
307 If there are no more articles with the same subject, go to
308 the first unread article."
309   :group 'gnus-summary-maneuvering
310   :type 'boolean)
311
312 (defcustom gnus-summary-check-current nil
313   "*If non-nil, consider the current article when moving.
314 The \"unread\" movement commands will stay on the same line if the
315 current article is unread."
316   :group 'gnus-summary-maneuvering
317   :type 'boolean)
318
319 (defcustom gnus-auto-center-summary t
320   "*If non-nil, always center the current summary buffer.
321 In particular, if `vertical' do only vertical recentering.  If non-nil
322 and non-`vertical', do both horizontal and vertical recentering."
323   :group 'gnus-summary-maneuvering
324   :type '(choice (const :tag "none" nil)
325                  (const vertical)
326                  (integer :tag "height")
327                  (sexp :menu-tag "both" t)))
328
329 (defcustom gnus-show-all-headers nil
330   "*If non-nil, don't hide any headers."
331   :group 'gnus-article-hiding
332   :group 'gnus-article-headers
333   :type 'boolean)
334
335 (defcustom gnus-summary-ignore-duplicates nil
336   "*If non-nil, ignore articles with identical Message-ID headers."
337   :group 'gnus-summary
338   :type 'boolean)
339
340 (defcustom gnus-single-article-buffer t
341   "*If non-nil, display all articles in the same buffer.
342 If nil, each group will get its own article buffer."
343   :group 'gnus-article-various
344   :type 'boolean)
345
346 (defcustom gnus-break-pages t
347   "*If non-nil, do page breaking on articles.
348 The page delimiter is specified by the `gnus-page-delimiter'
349 variable."
350   :group 'gnus-article-various
351   :type 'boolean)
352
353 (defcustom gnus-move-split-methods nil
354   "*Variable used to suggest where articles are to be moved to.
355 It uses the same syntax as the `gnus-split-methods' variable.
356 However, whereas `gnus-split-methods' specifies file names as targets,
357 this variable specifies group names."
358   :group 'gnus-summary-mail
359   :type '(repeat (choice (list :value (fun) function)
360                          (cons :value ("" "") regexp (repeat string))
361                          (sexp :value nil))))
362
363 (defcustom gnus-unread-mark ?  ;Whitespace
364   "*Mark used for unread articles."
365   :group 'gnus-summary-marks
366   :type 'character)
367
368 (defcustom gnus-ticked-mark ?!
369   "*Mark used for ticked articles."
370   :group 'gnus-summary-marks
371   :type 'character)
372
373 (defcustom gnus-dormant-mark ??
374   "*Mark used for dormant articles."
375   :group 'gnus-summary-marks
376   :type 'character)
377
378 (defcustom gnus-del-mark ?r
379   "*Mark used for del'd articles."
380   :group 'gnus-summary-marks
381   :type 'character)
382
383 (defcustom gnus-read-mark ?R
384   "*Mark used for read articles."
385   :group 'gnus-summary-marks
386   :type 'character)
387
388 (defcustom gnus-expirable-mark ?E
389   "*Mark used for expirable articles."
390   :group 'gnus-summary-marks
391   :type 'character)
392
393 (defcustom gnus-killed-mark ?K
394   "*Mark used for killed articles."
395   :group 'gnus-summary-marks
396   :type 'character)
397
398 (defcustom gnus-souped-mark ?F
399   "*Mark used for killed articles."
400   :group 'gnus-summary-marks
401   :type 'character)
402
403 (defcustom gnus-kill-file-mark ?X
404   "*Mark used for articles killed by kill files."
405   :group 'gnus-summary-marks
406   :type 'character)
407
408 (defcustom gnus-low-score-mark ?Y
409   "*Mark used for articles with a low score."
410   :group 'gnus-summary-marks
411   :type 'character)
412
413 (defcustom gnus-catchup-mark ?C
414   "*Mark used for articles that are caught up."
415   :group 'gnus-summary-marks
416   :type 'character)
417
418 (defcustom gnus-replied-mark ?A
419   "*Mark used for articles that have been replied to."
420   :group 'gnus-summary-marks
421   :type 'character)
422
423 (defcustom gnus-cached-mark ?*
424   "*Mark used for articles that are in the cache."
425   :group 'gnus-summary-marks
426   :type 'character)
427
428 (defcustom gnus-saved-mark ?S
429   "*Mark used for articles that have been saved to."
430   :group 'gnus-summary-marks
431   :type 'character)
432
433 (defcustom gnus-no-mark ?  ;Whitespace
434   "*Mark used for articles that have no other secondary mark."
435   :group 'gnus-summary-marks
436   :type 'character)
437
438 (defcustom gnus-ancient-mark ?O
439   "*Mark used for ancient articles."
440   :group 'gnus-summary-marks
441   :type 'character)
442
443 (defcustom gnus-sparse-mark ?Q
444   "*Mark used for sparsely reffed articles."
445   :group 'gnus-summary-marks
446   :type 'character)
447
448 (defcustom gnus-canceled-mark ?G
449   "*Mark used for canceled articles."
450   :group 'gnus-summary-marks
451   :type 'character)
452
453 (defcustom gnus-duplicate-mark ?M
454   "*Mark used for duplicate articles."
455   :group 'gnus-summary-marks
456   :type 'character)
457
458 (defcustom gnus-undownloaded-mark ?@
459   "*Mark used for articles that weren't downloaded."
460   :group 'gnus-summary-marks
461   :type 'character)
462
463 (defcustom gnus-downloadable-mark ?%
464   "*Mark used for articles that are to be downloaded."
465   :group 'gnus-summary-marks
466   :type 'character)
467
468 (defcustom gnus-unsendable-mark ?=
469   "*Mark used for articles that won't be sent."
470   :group 'gnus-summary-marks
471   :type 'character)
472
473 (defcustom gnus-score-over-mark ?+
474   "*Score mark used for articles with high scores."
475   :group 'gnus-summary-marks
476   :type 'character)
477
478 (defcustom gnus-score-below-mark ?-
479   "*Score mark used for articles with low scores."
480   :group 'gnus-summary-marks
481   :type 'character)
482
483 (defcustom gnus-empty-thread-mark ?  ;Whitespace
484   "*There is no thread under the article."
485   :group 'gnus-summary-marks
486   :type 'character)
487
488 (defcustom gnus-not-empty-thread-mark ?=
489   "*There is a thread under the article."
490   :group 'gnus-summary-marks
491   :type 'character)
492
493 (defcustom gnus-view-pseudo-asynchronously nil
494   "*If non-nil, Gnus will view pseudo-articles asynchronously."
495   :group 'gnus-extract-view
496   :type 'boolean)
497
498 (defcustom gnus-auto-expirable-marks
499   (list gnus-killed-mark gnus-del-mark gnus-catchup-mark
500         gnus-low-score-mark gnus-ancient-mark gnus-read-mark
501         gnus-souped-mark gnus-duplicate-mark)
502   "*The list of marks converted into expiration if a group is auto-expirable."
503   :version "21.1"
504   :group 'gnus-summary
505   :type '(repeat character))
506
507 (defcustom gnus-inhibit-user-auto-expire t
508   "*If non-nil, user marking commands will not mark an article as expirable, even if the group has auto-expire turned on."
509   :version "21.1"
510   :group 'gnus-summary
511   :type 'boolean)
512
513 (defcustom gnus-view-pseudos nil
514   "*If `automatic', pseudo-articles will be viewed automatically.
515 If `not-confirm', pseudos will be viewed automatically, and the user
516 will not be asked to confirm the command."
517   :group 'gnus-extract-view
518   :type '(choice (const :tag "off" nil)
519                  (const automatic)
520                  (const not-confirm)))
521
522 (defcustom gnus-view-pseudos-separately t
523   "*If non-nil, one pseudo-article will be created for each file to be viewed.
524 If nil, all files that use the same viewing command will be given as a
525 list of parameters to that command."
526   :group 'gnus-extract-view
527   :type 'boolean)
528
529 (defcustom gnus-insert-pseudo-articles t
530   "*If non-nil, insert pseudo-articles when decoding articles."
531   :group 'gnus-extract-view
532   :type 'boolean)
533
534 (defcustom gnus-summary-dummy-line-format
535   "  %(:                          :%) %S\n"
536   "*The format specification for the dummy roots in the summary buffer.
537 It works along the same lines as a normal formatting string,
538 with some simple extensions.
539
540 %S  The subject"
541   :group 'gnus-threading
542   :type 'string)
543
544 (defcustom gnus-summary-mode-line-format "Gnus: %g [%A] %Z"
545   "*The format specification for the summary mode line.
546 It works along the same lines as a normal formatting string,
547 with some simple extensions:
548
549 %G  Group name
550 %p  Unprefixed group name
551 %A  Current article number
552 %z  Current article score
553 %V  Gnus version
554 %U  Number of unread articles in the group
555 %e  Number of unselected articles in the group
556 %Z  A string with unread/unselected article counts
557 %g  Shortish group name
558 %S  Subject of the current article
559 %u  User-defined spec
560 %s  Current score file name
561 %d  Number of dormant articles
562 %r  Number of articles that have been marked as read in this session
563 %E  Number of articles expunged by the score files"
564   :group 'gnus-summary-format
565   :type 'string)
566
567 (defcustom gnus-list-identifiers nil
568   "Regexp that matches list identifiers to be removed from subject.
569 This can also be a list of regexps."
570   :version "21.1"
571   :group 'gnus-summary-format
572   :group 'gnus-article-hiding
573   :type '(choice (const :tag "none" nil)
574                  (regexp :value ".*")
575                  (repeat :value (".*") regexp)))
576
577 (defcustom gnus-summary-mark-below 0
578   "*Mark all articles with a score below this variable as read.
579 This variable is local to each summary buffer and usually set by the
580 score file."
581   :group 'gnus-score-default
582   :type 'integer)
583
584 (defcustom gnus-article-sort-functions '(gnus-article-sort-by-number)
585   "*List of functions used for sorting articles in the summary buffer.
586 This variable is only used when not using a threaded display."
587   :group 'gnus-summary-sort
588   :type '(repeat (choice (function-item gnus-article-sort-by-number)
589                          (function-item gnus-article-sort-by-author)
590                          (function-item gnus-article-sort-by-subject)
591                          (function-item gnus-article-sort-by-date)
592                          (function-item gnus-article-sort-by-score)
593                          (function :tag "other"))))
594
595 (defcustom gnus-thread-sort-functions '(gnus-thread-sort-by-number)
596   "*List of functions used for sorting threads in the summary buffer.
597 By default, threads are sorted by article number.
598
599 Each function takes two threads and return non-nil if the first thread
600 should be sorted before the other.  If you use more than one function,
601 the primary sort function should be the last.  You should probably
602 always include `gnus-thread-sort-by-number' in the list of sorting
603 functions -- preferably first.
604
605 Ready-made functions include `gnus-thread-sort-by-number',
606 `gnus-thread-sort-by-author', `gnus-thread-sort-by-subject',
607 `gnus-thread-sort-by-date', `gnus-thread-sort-by-score' and
608 `gnus-thread-sort-by-total-score' (see `gnus-thread-score-function')."
609   :group 'gnus-summary-sort
610   :type '(repeat (choice (function-item gnus-thread-sort-by-number)
611                          (function-item gnus-thread-sort-by-author)
612                          (function-item gnus-thread-sort-by-subject)
613                          (function-item gnus-thread-sort-by-date)
614                          (function-item gnus-thread-sort-by-score)
615                          (function-item gnus-thread-sort-by-total-score)
616                          (function :tag "other"))))
617
618 (defcustom gnus-thread-score-function '+
619   "*Function used for calculating the total score of a thread.
620
621 The function is called with the scores of the article and each
622 subthread and should then return the score of the thread.
623
624 Some functions you can use are `+', `max', or `min'."
625   :group 'gnus-summary-sort
626   :type 'function)
627
628 (defcustom gnus-summary-expunge-below nil
629   "All articles that have a score less than this variable will be expunged.
630 This variable is local to the summary buffers."
631   :group 'gnus-score-default
632   :type '(choice (const :tag "off" nil)
633                  integer))
634
635 (defcustom gnus-thread-expunge-below nil
636   "All threads that have a total score less than this variable will be expunged.
637 See `gnus-thread-score-function' for en explanation of what a
638 \"thread score\" is.
639
640 This variable is local to the summary buffers."
641   :group 'gnus-threading
642   :group 'gnus-score-default
643   :type '(choice (const :tag "off" nil)
644                  integer))
645
646 (defcustom gnus-summary-mode-hook nil
647   "*A hook for Gnus summary mode.
648 This hook is run before any variables are set in the summary buffer."
649   :options '(turn-on-gnus-mailing-list-mode)
650   :group 'gnus-summary-various
651   :type 'hook)
652
653 ;; Extracted from gnus-xmas-redefine in order to preserve user settings
654 (when (featurep 'xemacs)
655   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-summary-menu-add)
656   (add-hook 'gnus-summary-mode-hook 'gnus-xmas-setup-summary-toolbar)
657   (add-hook 'gnus-summary-mode-hook
658             'gnus-xmas-switch-horizontal-scrollbar-off))
659
660 (defcustom gnus-summary-menu-hook nil
661   "*Hook run after the creation of the summary mode menu."
662   :group 'gnus-summary-visual
663   :type 'hook)
664
665 (defcustom gnus-summary-exit-hook nil
666   "*A hook called on exit from the summary buffer.
667 It will be called with point in the group buffer."
668   :group 'gnus-summary-exit
669   :type 'hook)
670
671 (defcustom gnus-summary-prepare-hook nil
672   "*A hook called after the summary buffer has been generated.
673 If you want to modify the summary buffer, you can use this hook."
674   :group 'gnus-summary-various
675   :type 'hook)
676
677 (defcustom gnus-summary-prepared-hook nil
678   "*A hook called as the last thing after the summary buffer has been generated."
679   :group 'gnus-summary-various
680   :type 'hook)
681
682 (defcustom gnus-summary-generate-hook nil
683   "*A hook run just before generating the summary buffer.
684 This hook is commonly used to customize threading variables and the
685 like."
686   :group 'gnus-summary-various
687   :type 'hook)
688
689 (defcustom gnus-select-group-hook nil
690   "*A hook called when a newsgroup is selected.
691
692 If you'd like to simplify subjects like the
693 `gnus-summary-next-same-subject' command does, you can use the
694 following hook:
695
696  (setq gnus-select-group-hook
697       (list
698         (lambda ()
699           (mapcar (lambda (header)
700                      (mail-header-set-subject
701                       header
702                       (gnus-simplify-subject
703                        (mail-header-subject header) 're-only)))
704                   gnus-newsgroup-headers))))"
705   :group 'gnus-group-select
706   :type 'hook)
707
708 (defcustom gnus-select-article-hook nil
709   "*A hook called when an article is selected."
710   :group 'gnus-summary-choose
711   :type 'hook)
712
713 (defcustom gnus-visual-mark-article-hook
714   (list 'gnus-highlight-selected-summary)
715   "*Hook run after selecting an article in the summary buffer.
716 It is meant to be used for highlighting the article in some way.  It
717 is not run if `gnus-visual' is nil."
718   :group 'gnus-summary-visual
719   :type 'hook)
720
721 (defcustom gnus-parse-headers-hook nil
722   "*A hook called before parsing the headers."
723   :group 'gnus-various
724   :type 'hook)
725
726 (defcustom gnus-exit-group-hook nil
727   "*A hook called when exiting summary mode.
728 This hook is not called from the non-updating exit commands like `Q'."
729   :group 'gnus-various
730   :type 'hook)
731
732 (defcustom gnus-summary-update-hook
733   (list 'gnus-summary-highlight-line)
734   "*A hook called when a summary line is changed.
735 The hook will not be called if `gnus-visual' is nil.
736
737 The default function `gnus-summary-highlight-line' will
738 highlight the line according to the `gnus-summary-highlight'
739 variable."
740   :group 'gnus-summary-visual
741   :type 'hook)
742
743 (defcustom gnus-mark-article-hook '(gnus-summary-mark-read-and-unread-as-read)
744   "*A hook called when an article is selected for the first time.
745 The hook is intended to mark an article as read (or unread)
746 automatically when it is selected."
747   :group 'gnus-summary-choose
748   :type 'hook)
749
750 (defcustom gnus-group-no-more-groups-hook nil
751   "*A hook run when returning to group mode having no more (unread) groups."
752   :group 'gnus-group-select
753   :type 'hook)
754
755 (defcustom gnus-ps-print-hook nil
756   "*A hook run before ps-printing something from Gnus."
757   :group 'gnus-summary
758   :type 'hook)
759
760 (defcustom gnus-summary-selected-face 'gnus-summary-selected-face
761   "Face used for highlighting the current article in the summary buffer."
762   :group 'gnus-summary-visual
763   :type 'face)
764
765 (defcustom gnus-summary-highlight
766   '(((= mark gnus-canceled-mark)
767      . gnus-summary-cancelled-face)
768     ((and (> score default)
769           (or (= mark gnus-dormant-mark)
770               (= mark gnus-ticked-mark)))
771      . gnus-summary-high-ticked-face)
772     ((and (< score default)
773           (or (= mark gnus-dormant-mark)
774               (= mark gnus-ticked-mark)))
775      . gnus-summary-low-ticked-face)
776     ((or (= mark gnus-dormant-mark)
777          (= mark gnus-ticked-mark))
778      . gnus-summary-normal-ticked-face)
779     ((and (> score default) (= mark gnus-ancient-mark))
780      . gnus-summary-high-ancient-face)
781     ((and (< score default) (= mark gnus-ancient-mark))
782      . gnus-summary-low-ancient-face)
783     ((= mark gnus-ancient-mark)
784      . gnus-summary-normal-ancient-face)
785     ((and (> score default) (= mark gnus-unread-mark))
786      . gnus-summary-high-unread-face)
787     ((and (< score default) (= mark gnus-unread-mark))
788      . gnus-summary-low-unread-face)
789     ((= mark gnus-unread-mark)
790      . gnus-summary-normal-unread-face)
791     ((and (> score default) (memq mark (list gnus-downloadable-mark
792                                              gnus-undownloaded-mark)))
793      . gnus-summary-high-unread-face)
794     ((and (< score default) (memq mark (list gnus-downloadable-mark
795                                              gnus-undownloaded-mark)))
796      . gnus-summary-low-unread-face)
797     ((memq mark (list gnus-downloadable-mark gnus-undownloaded-mark))
798      . gnus-summary-normal-unread-face)
799     ((> score default)
800      . gnus-summary-high-read-face)
801     ((< score default)
802      . gnus-summary-low-read-face)
803     (t
804      . gnus-summary-normal-read-face))
805   "*Controls the highlighting of summary buffer lines.
806
807 A list of (FORM . FACE) pairs.  When deciding how a a particular
808 summary line should be displayed, each form is evaluated.  The content
809 of the face field after the first true form is used.  You can change
810 how those summary lines are displayed, by editing the face field.
811
812 You can use the following variables in the FORM field.
813
814 score:   The articles score
815 default: The default article score.
816 below:   The score below which articles are automatically marked as read.
817 mark:    The articles mark."
818   :group 'gnus-summary-visual
819   :type '(repeat (cons (sexp :tag "Form" nil)
820                        face)))
821
822 (defcustom gnus-alter-header-function nil
823   "Function called to allow alteration of article header structures.
824 The function is called with one parameter, the article header vector,
825 which it may alter in any way.")
826
827 (defvar gnus-decode-encoded-word-function 'mail-decode-encoded-word-string
828   "Variable that says which function should be used to decode a string with encoded words.")
829
830 (defcustom gnus-extra-headers nil
831   "*Extra headers to parse."
832   :version "21.1"
833   :group 'gnus-summary
834   :type '(repeat symbol))
835
836 (defcustom gnus-ignored-from-addresses
837   (and user-mail-address (regexp-quote user-mail-address))
838   "*Regexp of From headers that may be suppressed in favor of To headers."
839   :version "21.1"
840   :group 'gnus-summary
841   :type 'regexp)
842
843 (defcustom gnus-group-charset-alist
844   '(("^hk\\>\\|^tw\\>\\|\\<big5\\>" cn-big5)
845     ("^cn\\>\\|\\<chinese\\>" cn-gb-2312)
846     ("^fj\\>\\|^japan\\>" iso-2022-jp-2)
847     ("^tnn\\>\\|^pin\\>\\|^sci.lang.japan" iso-2022-7bit)
848     ("^relcom\\>" koi8-r)
849     ("^fido7\\>" koi8-r)
850     ("^\\(cz\\|hun\\|pl\\|sk\\|hr\\)\\>" iso-8859-2)
851     ("^israel\\>" iso-8859-1)
852     ("^han\\>" euc-kr)
853     ("^alt.chinese.text.big5\\>" chinese-big5)
854     ("^soc.culture.vietnamese\\>" vietnamese-viqr)
855     ("^\\(comp\\|rec\\|alt\\|sci\\|soc\\|news\\|gnu\\|bofh\\)\\>" iso-8859-1)
856     (".*" iso-8859-1))
857   "Alist of regexps (to match group names) and default charsets to be used when reading."
858   :type '(repeat (list (regexp :tag "Group")
859                        (symbol :tag "Charset")))
860   :group 'gnus-charset)
861
862 (defcustom gnus-newsgroup-ignored-charsets '(unknown-8bit x-unknown)
863   "List of charsets that should be ignored.
864 When these charsets are used in the \"charset\" parameter, the
865 default charset will be used instead."
866   :version "21.1"
867   :type '(repeat symbol)
868   :group 'gnus-charset)
869
870 (defcustom gnus-group-ignored-charsets-alist
871   '(("alt\\.chinese\\.text" iso-8859-1))
872   "Alist of regexps (to match group names) and charsets that should be ignored.
873 When these charsets are used in the \"charset\" parameter, the
874 default charset will be used instead."
875   :type '(repeat (cons (regexp :tag "Group")
876                        (repeat symbol)))
877   :group 'gnus-charset)
878
879 (defcustom gnus-group-highlight-words-alist nil
880   "Alist of group regexps and highlight regexps.
881 This variable uses the same syntax as `gnus-emphasis-alist'."
882   :version "21.1"
883   :type '(repeat (cons (regexp :tag "Group")
884                        (repeat (list (regexp :tag "Highlight regexp")
885                                      (number :tag "Group for entire word" 0)
886                                      (number :tag "Group for displayed part" 0)
887                                      (symbol :tag "Face"
888                                              gnus-emphasis-highlight-words)))))
889   :group 'gnus-summary-visual)
890
891 (defcustom gnus-summary-show-article-charset-alist
892   nil
893   "Alist of number and charset.
894 The article will be shown with the charset corresponding to the
895 numbered argument.
896 For example: ((1 . cn-gb-2312) (2 . big5))."
897   :version "21.1"
898   :type '(repeat (cons (number :tag "Argument" 1)
899                        (symbol :tag "Charset")))
900   :group 'gnus-charset)
901
902 (defcustom gnus-preserve-marks t
903   "Whether marks are preserved when moving, copying and respooling messages."
904   :version "21.1"
905   :type 'boolean
906   :group 'gnus-summary-marks)
907
908 (defcustom gnus-alter-articles-to-read-function nil
909   "Function to be called to alter the list of articles to be selected."
910   :type 'function
911   :group 'gnus-summary)
912
913 (defcustom gnus-orphan-score nil
914   "*All orphans get this score added.  Set in the score file."
915   :group 'gnus-score-default
916   :type '(choice (const nil)
917                  integer))
918
919 (defcustom gnus-summary-save-parts-default-mime "image/.*"
920   "*A regexp to match MIME parts when saving multiple parts of a message
921 with gnus-summary-save-parts (X m). This regexp will be used by default
922 when prompting the user for which type of files to save."
923   :group 'gnus-summary
924   :type 'regexp)
925
926
927 (defcustom gnus-summary-save-parts-default-mime "image/.*"
928   "*A regexp to match MIME parts when saving multiple parts of a message
929 with gnus-summary-save-parts (X m). This regexp will be used by default
930 when prompting the user for which type of files to save."
931   :group 'gnus-summary
932   :type 'regexp)
933
934
935 ;;; Internal variables
936
937 (defvar gnus-article-mime-handles nil)
938 (defvar gnus-article-decoded-p nil)
939 (defvar gnus-article-charset nil)
940 (defvar gnus-article-ignored-charsets nil)
941 (defvar gnus-scores-exclude-files nil)
942 (defvar gnus-page-broken nil)
943 (defvar gnus-inhibit-mime-unbuttonizing nil)
944
945 (defvar gnus-original-article nil)
946 (defvar gnus-article-internal-prepare-hook nil)
947 (defvar gnus-newsgroup-process-stack nil)
948
949 (defvar gnus-thread-indent-array nil)
950 (defvar gnus-thread-indent-array-level gnus-thread-indent-level)
951 (defvar gnus-sort-gathered-threads-function 'gnus-thread-sort-by-number
952   "Function called to sort the articles within a thread after it has been gathered together.")
953
954 (defvar gnus-summary-save-parts-type-history nil)
955 (defvar gnus-summary-save-parts-last-directory nil)
956
957 (defvar gnus-summary-save-parts-type-history nil)
958 (defvar gnus-summary-save-parts-last-directory nil)
959
960 ;; Avoid highlighting in kill files.
961 (defvar gnus-summary-inhibit-highlight nil)
962 (defvar gnus-newsgroup-selected-overlay nil)
963 (defvar gnus-inhibit-limiting nil)
964 (defvar gnus-newsgroup-adaptive-score-file nil)
965 (defvar gnus-current-score-file nil)
966 (defvar gnus-current-move-group nil)
967 (defvar gnus-current-copy-group nil)
968 (defvar gnus-current-crosspost-group nil)
969
970 (defvar gnus-newsgroup-dependencies nil)
971 (defvar gnus-newsgroup-adaptive nil)
972 (defvar gnus-summary-display-article-function nil)
973 (defvar gnus-summary-highlight-line-function nil
974   "Function called after highlighting a summary line.")
975
976 (defvar gnus-summary-line-format-alist
977   `((?N ,(macroexpand '(mail-header-number gnus-tmp-header)) ?d)
978     (?S ,(macroexpand '(mail-header-subject gnus-tmp-header)) ?s)
979     (?s gnus-tmp-subject-or-nil ?s)
980     (?n gnus-tmp-name ?s)
981     (?A (car (cdr (funcall gnus-extract-address-components gnus-tmp-from)))
982         ?s)
983     (?a (or (car (funcall gnus-extract-address-components gnus-tmp-from))
984             gnus-tmp-from) ?s)
985     (?F gnus-tmp-from ?s)
986     (?x ,(macroexpand '(mail-header-xref gnus-tmp-header)) ?s)
987     (?D ,(macroexpand '(mail-header-date gnus-tmp-header)) ?s)
988     (?d (gnus-dd-mmm (mail-header-date gnus-tmp-header)) ?s)
989     (?o (gnus-date-iso8601 (mail-header-date gnus-tmp-header)) ?s)
990     (?M ,(macroexpand '(mail-header-id gnus-tmp-header)) ?s)
991     (?r ,(macroexpand '(mail-header-references gnus-tmp-header)) ?s)
992     (?c (or (mail-header-chars gnus-tmp-header) 0) ?d)
993     (?L gnus-tmp-lines ?d)
994     (?I gnus-tmp-indentation ?s)
995     (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s)
996     (?R gnus-tmp-replied ?c)
997     (?\[ gnus-tmp-opening-bracket ?c)
998     (?\] gnus-tmp-closing-bracket ?c)
999     (?\> (make-string gnus-tmp-level ? ) ?s)
1000     (?\< (make-string (max 0 (- 20 gnus-tmp-level)) ? ) ?s)
1001     (?i gnus-tmp-score ?d)
1002     (?z gnus-tmp-score-char ?c)
1003     (?l (bbb-grouplens-score gnus-tmp-header) ?s)
1004     (?V (gnus-thread-total-score (and (boundp 'thread) (car thread))) ?d)
1005     (?U gnus-tmp-unread ?c)
1006     (?f (gnus-summary-from-or-to-or-newsgroups gnus-tmp-header) ?s)
1007     (?t (gnus-summary-number-of-articles-in-thread
1008          (and (boundp 'thread) (car thread)) gnus-tmp-level)
1009         ?d)
1010     (?e (gnus-summary-number-of-articles-in-thread
1011          (and (boundp 'thread) (car thread)) gnus-tmp-level t)
1012         ?c)
1013     (?u gnus-tmp-user-defined ?s)
1014     (?P (gnus-pick-line-number) ?d))
1015   "An alist of format specifications that can appear in summary lines.
1016 These are paired with what variables they correspond with, along with
1017 the type of the variable (string, integer, character, etc).")
1018
1019 (defvar gnus-summary-dummy-line-format-alist
1020   `((?S gnus-tmp-subject ?s)
1021     (?N gnus-tmp-number ?d)
1022     (?u gnus-tmp-user-defined ?s)))
1023
1024 (defvar gnus-summary-mode-line-format-alist
1025   `((?G gnus-tmp-group-name ?s)
1026     (?g (gnus-short-group-name gnus-tmp-group-name) ?s)
1027     (?p (gnus-group-real-name gnus-tmp-group-name) ?s)
1028     (?A gnus-tmp-article-number ?d)
1029     (?Z gnus-tmp-unread-and-unselected ?s)
1030     (?V gnus-version ?s)
1031     (?U gnus-tmp-unread-and-unticked ?d)
1032     (?S gnus-tmp-subject ?s)
1033     (?e gnus-tmp-unselected ?d)
1034     (?u gnus-tmp-user-defined ?s)
1035     (?d (length gnus-newsgroup-dormant) ?d)
1036     (?t (length gnus-newsgroup-marked) ?d)
1037     (?r (length gnus-newsgroup-reads) ?d)
1038     (?z (gnus-summary-article-score gnus-tmp-article-number) ?d)
1039     (?E gnus-newsgroup-expunged-tally ?d)
1040     (?s (gnus-current-score-file-nondirectory) ?s)))
1041
1042 (defvar gnus-last-search-regexp nil
1043   "Default regexp for article search command.")
1044
1045 (defvar gnus-last-shell-command nil
1046   "Default shell command on article.")
1047
1048 (defvar gnus-newsgroup-begin nil)
1049 (defvar gnus-newsgroup-end nil)
1050 (defvar gnus-newsgroup-last-rmail nil)
1051 (defvar gnus-newsgroup-last-mail nil)
1052 (defvar gnus-newsgroup-last-folder nil)
1053 (defvar gnus-newsgroup-last-file nil)
1054 (defvar gnus-newsgroup-auto-expire nil)
1055 (defvar gnus-newsgroup-active nil)
1056
1057 (defvar gnus-newsgroup-data nil)
1058 (defvar gnus-newsgroup-data-reverse nil)
1059 (defvar gnus-newsgroup-limit nil)
1060 (defvar gnus-newsgroup-limits nil)
1061
1062 (defvar gnus-newsgroup-unreads nil
1063   "List of unread articles in the current newsgroup.")
1064
1065 (defvar gnus-newsgroup-unselected nil
1066   "List of unselected unread articles in the current newsgroup.")
1067
1068 (defvar gnus-newsgroup-reads nil
1069   "Alist of read articles and article marks in the current newsgroup.")
1070
1071 (defvar gnus-newsgroup-expunged-tally nil)
1072
1073 (defvar gnus-newsgroup-marked nil
1074   "List of ticked articles in the current newsgroup (a subset of unread art).")
1075
1076 (defvar gnus-newsgroup-killed nil
1077   "List of ranges of articles that have been through the scoring process.")
1078
1079 (defvar gnus-newsgroup-cached nil
1080   "List of articles that come from the article cache.")
1081
1082 (defvar gnus-newsgroup-saved nil
1083   "List of articles that have been saved.")
1084
1085 (defvar gnus-newsgroup-kill-headers nil)
1086
1087 (defvar gnus-newsgroup-replied nil
1088   "List of articles that have been replied to in the current newsgroup.")
1089
1090 (defvar gnus-newsgroup-expirable nil
1091   "List of articles in the current newsgroup that can be expired.")
1092
1093 (defvar gnus-newsgroup-processable nil
1094   "List of articles in the current newsgroup that can be processed.")
1095
1096 (defvar gnus-newsgroup-downloadable nil
1097   "List of articles in the current newsgroup that can be processed.")
1098
1099 (defvar gnus-newsgroup-undownloaded nil
1100   "List of articles in the current newsgroup that haven't been downloaded..")
1101
1102 (defvar gnus-newsgroup-unsendable nil
1103   "List of articles in the current newsgroup that won't be sent.")
1104
1105 (defvar gnus-newsgroup-bookmarks nil
1106   "List of articles in the current newsgroup that have bookmarks.")
1107
1108 (defvar gnus-newsgroup-dormant nil
1109   "List of dormant articles in the current newsgroup.")
1110
1111 (defvar gnus-newsgroup-scored nil
1112   "List of scored articles in the current newsgroup.")
1113
1114 (defvar gnus-newsgroup-headers nil
1115   "List of article headers in the current newsgroup.")
1116
1117 (defvar gnus-newsgroup-threads nil)
1118
1119 (defvar gnus-newsgroup-prepared nil
1120   "Whether the current group has been prepared properly.")
1121
1122 (defvar gnus-newsgroup-ancient nil
1123   "List of `gnus-fetch-old-headers' articles in the current newsgroup.")
1124
1125 (defvar gnus-newsgroup-sparse nil)
1126
1127 (defvar gnus-current-article nil)
1128 (defvar gnus-article-current nil)
1129 (defvar gnus-current-headers nil)
1130 (defvar gnus-have-all-headers nil)
1131 (defvar gnus-last-article nil)
1132 (defvar gnus-newsgroup-history nil)
1133 (defvar gnus-newsgroup-charset nil)
1134 (defvar gnus-newsgroup-ephemeral-charset nil)
1135 (defvar gnus-newsgroup-ephemeral-ignored-charsets nil)
1136
1137 (defvar gnus-article-before-search nil)
1138
1139 (defconst gnus-summary-local-variables
1140   '(gnus-newsgroup-name
1141     gnus-newsgroup-begin gnus-newsgroup-end
1142     gnus-newsgroup-last-rmail gnus-newsgroup-last-mail
1143     gnus-newsgroup-last-folder gnus-newsgroup-last-file
1144     gnus-newsgroup-auto-expire gnus-newsgroup-unreads
1145     gnus-newsgroup-unselected gnus-newsgroup-marked
1146     gnus-newsgroup-reads gnus-newsgroup-saved
1147     gnus-newsgroup-replied gnus-newsgroup-expirable
1148     gnus-newsgroup-processable gnus-newsgroup-killed
1149     gnus-newsgroup-downloadable gnus-newsgroup-undownloaded
1150     gnus-newsgroup-unsendable
1151     gnus-newsgroup-bookmarks gnus-newsgroup-dormant
1152     gnus-newsgroup-headers gnus-newsgroup-threads
1153     gnus-newsgroup-prepared gnus-summary-highlight-line-function
1154     gnus-current-article gnus-current-headers gnus-have-all-headers
1155     gnus-last-article gnus-article-internal-prepare-hook
1156     gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
1157     gnus-newsgroup-scored gnus-newsgroup-kill-headers
1158     gnus-thread-expunge-below
1159     gnus-score-alist gnus-current-score-file
1160     (gnus-summary-expunge-below . global)
1161     (gnus-summary-mark-below . global)
1162     (gnus-orphan-score . global)
1163     gnus-newsgroup-active gnus-scores-exclude-files
1164     gnus-newsgroup-history gnus-newsgroup-ancient
1165     gnus-newsgroup-sparse gnus-newsgroup-process-stack
1166     (gnus-newsgroup-adaptive . gnus-use-adaptive-scoring)
1167     gnus-newsgroup-adaptive-score-file (gnus-reffed-article-number . -1)
1168     (gnus-newsgroup-expunged-tally . 0)
1169     gnus-cache-removable-articles gnus-newsgroup-cached
1170     gnus-newsgroup-data gnus-newsgroup-data-reverse
1171     gnus-newsgroup-limit gnus-newsgroup-limits
1172     gnus-newsgroup-charset)
1173   "Variables that are buffer-local to the summary buffers.")
1174
1175 (defvar gnus-newsgroup-variables nil
1176   "Variables that have separate values in the newsgroups.")
1177
1178 ;; Byte-compiler warning.
1179 (eval-when-compile (defvar gnus-article-mode-map))
1180
1181 ;; MIME stuff.
1182
1183 (defvar gnus-decode-encoded-word-methods
1184   '(mail-decode-encoded-word-string)
1185   "List of methods used to decode encoded words.
1186
1187 This variable is a list of FUNCTION or (REGEXP . FUNCTION).  If item is
1188 FUNCTION, FUNCTION will be apply to all newsgroups.  If item is a
1189 (REGEXP . FUNCTION), FUNCTION will be only apply to thes newsgroups
1190 whose names match REGEXP.
1191
1192 For example:
1193 ((\"chinese\" . gnus-decode-encoded-word-string-by-guess)
1194  mail-decode-encoded-word-string
1195  (\"chinese\" . rfc1843-decode-string))")
1196
1197 (defvar gnus-decode-encoded-word-methods-cache nil)
1198
1199 (defun gnus-multi-decode-encoded-word-string (string)
1200   "Apply the functions from `gnus-encoded-word-methods' that match."
1201   (unless (and gnus-decode-encoded-word-methods-cache
1202                (eq gnus-newsgroup-name
1203                    (car gnus-decode-encoded-word-methods-cache)))
1204     (setq gnus-decode-encoded-word-methods-cache (list gnus-newsgroup-name))
1205     (mapcar (lambda (x)
1206               (if (symbolp x)
1207                   (nconc gnus-decode-encoded-word-methods-cache (list x))
1208                 (if (and gnus-newsgroup-name
1209                          (string-match (car x) gnus-newsgroup-name))
1210                     (nconc gnus-decode-encoded-word-methods-cache
1211                            (list (cdr x))))))
1212           gnus-decode-encoded-word-methods))
1213   (let ((xlist gnus-decode-encoded-word-methods-cache))
1214     (pop xlist)
1215     (while xlist
1216       (setq string (funcall (pop xlist) string))))
1217   string)
1218
1219 ;; Subject simplification.
1220
1221 (defun gnus-simplify-whitespace (str)
1222   "Remove excessive whitespace from STR."
1223   (let ((mystr str))
1224     ;; Multiple spaces.
1225     (while (string-match "[ \t][ \t]+" mystr)
1226       (setq mystr (concat (substring mystr 0 (match-beginning 0))
1227                           " "
1228                           (substring mystr (match-end 0)))))
1229     ;; Leading spaces.
1230     (when (string-match "^[ \t]+" mystr)
1231       (setq mystr (substring mystr (match-end 0))))
1232     ;; Trailing spaces.
1233     (when (string-match "[ \t]+$" mystr)
1234       (setq mystr (substring mystr 0 (match-beginning 0))))
1235     mystr))
1236
1237 (defsubst gnus-simplify-subject-re (subject)
1238   "Remove \"Re:\" from subject lines."
1239   (if (string-match message-subject-re-regexp subject)
1240       (substring subject (match-end 0))
1241     subject))
1242
1243 (defun gnus-simplify-subject (subject &optional re-only)
1244   "Remove `Re:' and words in parentheses.
1245 If RE-ONLY is non-nil, strip leading `Re:'s only."
1246   (let ((case-fold-search t))           ;Ignore case.
1247     ;; Remove `Re:', `Re^N:', `Re(n)', and `Re[n]:'.
1248     (when (string-match "\\`\\(re\\([[(^][0-9]+[])]?\\)?:[ \t]*\\)+" subject)
1249       (setq subject (substring subject (match-end 0))))
1250     ;; Remove uninteresting prefixes.
1251     (when (and (not re-only)
1252                gnus-simplify-ignored-prefixes
1253                (string-match gnus-simplify-ignored-prefixes subject))
1254       (setq subject (substring subject (match-end 0))))
1255     ;; Remove words in parentheses from end.
1256     (unless re-only
1257       (while (string-match "[ \t\n]*([^()]*)[ \t\n]*\\'" subject)
1258         (setq subject (substring subject 0 (match-beginning 0)))))
1259     ;; Return subject string.
1260     subject))
1261
1262 ;; Remove any leading "re:"s, any trailing paren phrases, and simplify
1263 ;; all whitespace.
1264 (defsubst gnus-simplify-buffer-fuzzy-step (regexp &optional newtext)
1265   (goto-char (point-min))
1266   (while (re-search-forward regexp nil t)
1267     (replace-match (or newtext ""))))
1268
1269 (defun gnus-simplify-buffer-fuzzy ()
1270   "Simplify string in the buffer fuzzily.
1271 The string in the accessible portion of the current buffer is simplified.
1272 It is assumed to be a single-line subject.
1273 Whitespace is generally cleaned up, and miscellaneous leading/trailing
1274 matter is removed.  Additional things can be deleted by setting
1275 `gnus-simplify-subject-fuzzy-regexp'."
1276   (let ((case-fold-search t)
1277         (modified-tick))
1278     (gnus-simplify-buffer-fuzzy-step "\t" " ")
1279
1280     (while (not (eq modified-tick (buffer-modified-tick)))
1281       (setq modified-tick (buffer-modified-tick))
1282       (cond
1283        ((listp gnus-simplify-subject-fuzzy-regexp)
1284         (mapcar 'gnus-simplify-buffer-fuzzy-step
1285                 gnus-simplify-subject-fuzzy-regexp))
1286        (gnus-simplify-subject-fuzzy-regexp
1287         (gnus-simplify-buffer-fuzzy-step gnus-simplify-subject-fuzzy-regexp)))
1288       (gnus-simplify-buffer-fuzzy-step "^ *\\[[-+?*!][-+?*!]\\] *")
1289       (gnus-simplify-buffer-fuzzy-step
1290        "^ *\\(re\\|fw\\|fwd\\)[[{(^0-9]*[])}]?[:;] *")
1291       (gnus-simplify-buffer-fuzzy-step "^[[].*:\\( .*\\)[]]$" "\\1"))
1292
1293     (gnus-simplify-buffer-fuzzy-step " *[[{(][^()\n]*[]})] *$")
1294     (gnus-simplify-buffer-fuzzy-step "  +" " ")
1295     (gnus-simplify-buffer-fuzzy-step " $")
1296     (gnus-simplify-buffer-fuzzy-step "^ +")))
1297
1298 (defun gnus-simplify-subject-fuzzy (subject)
1299   "Simplify a subject string fuzzily.
1300 See `gnus-simplify-buffer-fuzzy' for details."
1301   (save-excursion
1302     (gnus-set-work-buffer)
1303     (let ((case-fold-search t))
1304       ;; Remove uninteresting prefixes.
1305       (when (and gnus-simplify-ignored-prefixes
1306                  (string-match gnus-simplify-ignored-prefixes subject))
1307         (setq subject (substring subject (match-end 0))))
1308       (insert subject)
1309       (inline (gnus-simplify-buffer-fuzzy))
1310       (buffer-string))))
1311
1312 (defsubst gnus-simplify-subject-fully (subject)
1313   "Simplify a subject string according to gnus-summary-gather-subject-limit."
1314   (cond
1315    (gnus-simplify-subject-functions
1316     (gnus-map-function gnus-simplify-subject-functions subject))
1317    ((null gnus-summary-gather-subject-limit)
1318     (gnus-simplify-subject-re subject))
1319    ((eq gnus-summary-gather-subject-limit 'fuzzy)
1320     (gnus-simplify-subject-fuzzy subject))
1321    ((numberp gnus-summary-gather-subject-limit)
1322     (gnus-limit-string (gnus-simplify-subject-re subject)
1323                        gnus-summary-gather-subject-limit))
1324    (t
1325     subject)))
1326
1327 (defsubst gnus-subject-equal (s1 s2 &optional simple-first)
1328   "Check whether two subjects are equal.
1329 If optional argument simple-first is t, first argument is already
1330 simplified."
1331   (cond
1332    ((null simple-first)
1333     (equal (gnus-simplify-subject-fully s1)
1334            (gnus-simplify-subject-fully s2)))
1335    (t
1336     (equal s1
1337            (gnus-simplify-subject-fully s2)))))
1338
1339 (defun gnus-summary-bubble-group ()
1340   "Increase the score of the current group.
1341 This is a handy function to add to `gnus-summary-exit-hook' to
1342 increase the score of each group you read."
1343   (gnus-group-add-score gnus-newsgroup-name))
1344
1345 \f
1346 ;;;
1347 ;;; Gnus summary mode
1348 ;;;
1349
1350 (put 'gnus-summary-mode 'mode-class 'special)
1351
1352 (defvar gnus-article-commands-menu)
1353
1354 (when t
1355   ;; Non-orthogonal keys
1356
1357   (gnus-define-keys gnus-summary-mode-map
1358     " " gnus-summary-next-page
1359     "\177" gnus-summary-prev-page
1360     [delete] gnus-summary-prev-page
1361     [backspace] gnus-summary-prev-page
1362     "\r" gnus-summary-scroll-up
1363     "\M-\r" gnus-summary-scroll-down
1364     "n" gnus-summary-next-unread-article
1365     "p" gnus-summary-prev-unread-article
1366     "N" gnus-summary-next-article
1367     "P" gnus-summary-prev-article
1368     "\M-\C-n" gnus-summary-next-same-subject
1369     "\M-\C-p" gnus-summary-prev-same-subject
1370     "\M-n" gnus-summary-next-unread-subject
1371     "\M-p" gnus-summary-prev-unread-subject
1372     "." gnus-summary-first-unread-article
1373     "," gnus-summary-best-unread-article
1374     "\M-s" gnus-summary-search-article-forward
1375     "\M-r" gnus-summary-search-article-backward
1376     "<" gnus-summary-beginning-of-article
1377     ">" gnus-summary-end-of-article
1378     "j" gnus-summary-goto-article
1379     "^" gnus-summary-refer-parent-article
1380     "\M-^" gnus-summary-refer-article
1381     "u" gnus-summary-tick-article-forward
1382     "!" gnus-summary-tick-article-forward
1383     "U" gnus-summary-tick-article-backward
1384     "d" gnus-summary-mark-as-read-forward
1385     "D" gnus-summary-mark-as-read-backward
1386     "E" gnus-summary-mark-as-expirable
1387     "\M-u" gnus-summary-clear-mark-forward
1388     "\M-U" gnus-summary-clear-mark-backward
1389     "k" gnus-summary-kill-same-subject-and-select
1390     "\C-k" gnus-summary-kill-same-subject
1391     "\M-\C-k" gnus-summary-kill-thread
1392     "\M-\C-l" gnus-summary-lower-thread
1393     "e" gnus-summary-edit-article
1394     "#" gnus-summary-mark-as-processable
1395     "\M-#" gnus-summary-unmark-as-processable
1396     "\M-\C-t" gnus-summary-toggle-threads
1397     "\M-\C-s" gnus-summary-show-thread
1398     "\M-\C-h" gnus-summary-hide-thread
1399     "\M-\C-f" gnus-summary-next-thread
1400     "\M-\C-b" gnus-summary-prev-thread
1401     [(meta down)] gnus-summary-next-thread
1402     [(meta up)] gnus-summary-prev-thread
1403     "\M-\C-u" gnus-summary-up-thread
1404     "\M-\C-d" gnus-summary-down-thread
1405     "&" gnus-summary-execute-command
1406     "c" gnus-summary-catchup-and-exit
1407     "\C-w" gnus-summary-mark-region-as-read
1408     "\C-t" gnus-summary-toggle-truncation
1409     "?" gnus-summary-mark-as-dormant
1410     "\C-c\M-\C-s" gnus-summary-limit-include-expunged
1411     "\C-c\C-s\C-n" gnus-summary-sort-by-number
1412     "\C-c\C-s\C-l" gnus-summary-sort-by-lines
1413     "\C-c\C-s\C-c" gnus-summary-sort-by-chars
1414     "\C-c\C-s\C-a" gnus-summary-sort-by-author
1415     "\C-c\C-s\C-s" gnus-summary-sort-by-subject
1416     "\C-c\C-s\C-d" gnus-summary-sort-by-date
1417     "\C-c\C-s\C-i" gnus-summary-sort-by-score
1418     "=" gnus-summary-expand-window
1419     "\C-x\C-s" gnus-summary-reselect-current-group
1420     "\M-g" gnus-summary-rescan-group
1421     "w" gnus-summary-stop-page-breaking
1422     "\C-c\C-r" gnus-summary-caesar-message
1423     "f" gnus-summary-followup
1424     "F" gnus-summary-followup-with-original
1425     "C" gnus-summary-cancel-article
1426     "r" gnus-summary-reply
1427     "R" gnus-summary-reply-with-original
1428     "\C-c\C-f" gnus-summary-mail-forward
1429     "o" gnus-summary-save-article
1430     "\C-o" gnus-summary-save-article-mail
1431     "|" gnus-summary-pipe-output
1432     "\M-k" gnus-summary-edit-local-kill
1433     "\M-K" gnus-summary-edit-global-kill
1434     ;; "V" gnus-version
1435     "\C-c\C-d" gnus-summary-describe-group
1436     "q" gnus-summary-exit
1437     "Q" gnus-summary-exit-no-update
1438     "\C-c\C-i" gnus-info-find-node
1439     gnus-mouse-2 gnus-mouse-pick-article
1440     "m" gnus-summary-mail-other-window
1441     "a" gnus-summary-post-news
1442     "x" gnus-summary-limit-to-unread
1443     "s" gnus-summary-isearch-article
1444     "t" gnus-summary-toggle-header
1445     "g" gnus-summary-show-article
1446     "l" gnus-summary-goto-last-article
1447     "\C-c\C-v\C-v" gnus-uu-decode-uu-view
1448     "\C-d" gnus-summary-enter-digest-group
1449     "\M-\C-d" gnus-summary-read-document
1450     "\M-\C-e" gnus-summary-edit-parameters
1451     "\M-\C-a" gnus-summary-customize-parameters
1452     "\C-c\C-b" gnus-bug
1453     "*" gnus-cache-enter-article
1454     "\M-*" gnus-cache-remove-article
1455     "\M-&" gnus-summary-universal-argument
1456     "\C-l" gnus-recenter
1457     "I" gnus-summary-increase-score
1458     "L" gnus-summary-lower-score
1459     "\M-i" gnus-symbolic-argument
1460     "h" gnus-summary-select-article-buffer
1461
1462     "b" gnus-article-view-part
1463     "\M-t" gnus-summary-toggle-display-buttonized
1464
1465     "V" gnus-summary-score-map
1466     "X" gnus-uu-extract-map
1467     "S" gnus-summary-send-map)
1468
1469   ;; Sort of orthogonal keymap
1470   (gnus-define-keys (gnus-summary-mark-map "M" gnus-summary-mode-map)
1471     "t" gnus-summary-tick-article-forward
1472     "!" gnus-summary-tick-article-forward
1473     "d" gnus-summary-mark-as-read-forward
1474     "r" gnus-summary-mark-as-read-forward
1475     "c" gnus-summary-clear-mark-forward
1476     " " gnus-summary-clear-mark-forward
1477     "e" gnus-summary-mark-as-expirable
1478     "x" gnus-summary-mark-as-expirable
1479     "?" gnus-summary-mark-as-dormant
1480     "b" gnus-summary-set-bookmark
1481     "B" gnus-summary-remove-bookmark
1482     "#" gnus-summary-mark-as-processable
1483     "\M-#" gnus-summary-unmark-as-processable
1484     "S" gnus-summary-limit-include-expunged
1485     "C" gnus-summary-catchup
1486     "H" gnus-summary-catchup-to-here
1487     "\C-c" gnus-summary-catchup-all
1488     "k" gnus-summary-kill-same-subject-and-select
1489     "K" gnus-summary-kill-same-subject
1490     "P" gnus-uu-mark-map)
1491
1492   (gnus-define-keys (gnus-summary-mscore-map "V" gnus-summary-mark-map)
1493     "c" gnus-summary-clear-above
1494     "u" gnus-summary-tick-above
1495     "m" gnus-summary-mark-above
1496     "k" gnus-summary-kill-below)
1497
1498   (gnus-define-keys (gnus-summary-limit-map "/" gnus-summary-mode-map)
1499     "/" gnus-summary-limit-to-subject
1500     "n" gnus-summary-limit-to-articles
1501     "w" gnus-summary-pop-limit
1502     "s" gnus-summary-limit-to-subject
1503     "a" gnus-summary-limit-to-author
1504     "u" gnus-summary-limit-to-unread
1505     "m" gnus-summary-limit-to-marks
1506     "M" gnus-summary-limit-exclude-marks
1507     "v" gnus-summary-limit-to-score
1508     "*" gnus-summary-limit-include-cached
1509     "D" gnus-summary-limit-include-dormant
1510     "T" gnus-summary-limit-include-thread
1511     "d" gnus-summary-limit-exclude-dormant
1512     "t" gnus-summary-limit-to-age
1513     "x" gnus-summary-limit-to-extra
1514     "E" gnus-summary-limit-include-expunged
1515     "c" gnus-summary-limit-exclude-childless-dormant
1516     "C" gnus-summary-limit-mark-excluded-as-read)
1517
1518   (gnus-define-keys (gnus-summary-goto-map "G" gnus-summary-mode-map)
1519     "n" gnus-summary-next-unread-article
1520     "p" gnus-summary-prev-unread-article
1521     "N" gnus-summary-next-article
1522     "P" gnus-summary-prev-article
1523     "\C-n" gnus-summary-next-same-subject
1524     "\C-p" gnus-summary-prev-same-subject
1525     "\M-n" gnus-summary-next-unread-subject
1526     "\M-p" gnus-summary-prev-unread-subject
1527     "f" gnus-summary-first-unread-article
1528     "b" gnus-summary-best-unread-article
1529     "j" gnus-summary-goto-article
1530     "g" gnus-summary-goto-subject
1531     "l" gnus-summary-goto-last-article
1532     "o" gnus-summary-pop-article)
1533
1534   (gnus-define-keys (gnus-summary-thread-map "T" gnus-summary-mode-map)
1535     "k" gnus-summary-kill-thread
1536     "l" gnus-summary-lower-thread
1537     "i" gnus-summary-raise-thread
1538     "T" gnus-summary-toggle-threads
1539     "t" gnus-summary-rethread-current
1540     "^" gnus-summary-reparent-thread
1541     "s" gnus-summary-show-thread
1542     "S" gnus-summary-show-all-threads
1543     "h" gnus-summary-hide-thread
1544     "H" gnus-summary-hide-all-threads
1545     "n" gnus-summary-next-thread
1546     "p" gnus-summary-prev-thread
1547     "u" gnus-summary-up-thread
1548     "o" gnus-summary-top-thread
1549     "d" gnus-summary-down-thread
1550     "#" gnus-uu-mark-thread
1551     "\M-#" gnus-uu-unmark-thread)
1552
1553   (gnus-define-keys (gnus-summary-buffer-map "Y" gnus-summary-mode-map)
1554     "g" gnus-summary-prepare
1555     "c" gnus-summary-insert-cached-articles)
1556
1557   (gnus-define-keys (gnus-summary-exit-map "Z" gnus-summary-mode-map)
1558     "c" gnus-summary-catchup-and-exit
1559     "C" gnus-summary-catchup-all-and-exit
1560     "E" gnus-summary-exit-no-update
1561     "Q" gnus-summary-exit
1562     "Z" gnus-summary-exit
1563     "n" gnus-summary-catchup-and-goto-next-group
1564     "R" gnus-summary-reselect-current-group
1565     "G" gnus-summary-rescan-group
1566     "N" gnus-summary-next-group
1567     "s" gnus-summary-save-newsrc
1568     "P" gnus-summary-prev-group)
1569
1570   (gnus-define-keys (gnus-summary-article-map "A" gnus-summary-mode-map)
1571     " " gnus-summary-next-page
1572     "n" gnus-summary-next-page
1573     "\177" gnus-summary-prev-page
1574     [delete] gnus-summary-prev-page
1575     "p" gnus-summary-prev-page
1576     "\r" gnus-summary-scroll-up
1577     "\M-\r" gnus-summary-scroll-down
1578     "<" gnus-summary-beginning-of-article
1579     ">" gnus-summary-end-of-article
1580     "b" gnus-summary-beginning-of-article
1581     "e" gnus-summary-end-of-article
1582     "^" gnus-summary-refer-parent-article
1583     "r" gnus-summary-refer-parent-article
1584     "D" gnus-summary-enter-digest-group
1585     "R" gnus-summary-refer-references
1586     "T" gnus-summary-refer-thread
1587     "g" gnus-summary-show-article
1588     "s" gnus-summary-isearch-article
1589     "P" gnus-summary-print-article
1590     "M" gnus-mailing-list-insinuate
1591     "t" gnus-article-babel)
1592
1593   (gnus-define-keys (gnus-summary-wash-map "W" gnus-summary-mode-map)
1594     "b" gnus-article-add-buttons
1595     "B" gnus-article-add-buttons-to-head
1596     "o" gnus-article-treat-overstrike
1597     "e" gnus-article-emphasize
1598     "w" gnus-article-fill-cited-article
1599     "Q" gnus-article-fill-long-lines
1600     "C" gnus-article-capitalize-sentences
1601     "c" gnus-article-remove-cr
1602     "q" gnus-article-de-quoted-unreadable
1603     "6" gnus-article-de-base64-unreadable
1604     "Z" gnus-article-decode-HZ
1605     "h" gnus-article-wash-html
1606     "s" gnus-summary-force-verify-and-decrypt
1607     "f" gnus-article-display-x-face
1608     "l" gnus-summary-stop-page-breaking
1609     "r" gnus-summary-caesar-message
1610     "t" gnus-summary-toggle-header
1611     "v" gnus-summary-verbose-headers
1612     "H" gnus-article-strip-headers-in-body
1613     "p" gnus-article-verify-x-pgp-sig
1614     "d" gnus-article-treat-dumbquotes)
1615
1616   (gnus-define-keys (gnus-summary-wash-hide-map "W" gnus-summary-wash-map)
1617     "a" gnus-article-hide
1618     "h" gnus-article-hide-headers
1619     "b" gnus-article-hide-boring-headers
1620     "s" gnus-article-hide-signature
1621     "c" gnus-article-hide-citation
1622     "C" gnus-article-hide-citation-in-followups
1623     "l" gnus-article-hide-list-identifiers
1624     "p" gnus-article-hide-pgp
1625     "B" gnus-article-strip-banner
1626     "P" gnus-article-hide-pem
1627     "\C-c" gnus-article-hide-citation-maybe)
1628
1629   (gnus-define-keys (gnus-summary-wash-highlight-map "H" gnus-summary-wash-map)
1630     "a" gnus-article-highlight
1631     "h" gnus-article-highlight-headers
1632     "c" gnus-article-highlight-citation
1633     "s" gnus-article-highlight-signature)
1634
1635   (gnus-define-keys (gnus-summary-wash-mime-map "M" gnus-summary-wash-map)
1636     "w" gnus-article-decode-mime-words
1637     "c" gnus-article-decode-charset
1638     "v" gnus-mime-view-all-parts
1639     "b" gnus-article-view-part)
1640
1641   (gnus-define-keys (gnus-summary-wash-time-map "T" gnus-summary-wash-map)
1642     "z" gnus-article-date-ut
1643     "u" gnus-article-date-ut
1644     "l" gnus-article-date-local
1645     "p" gnus-article-date-english
1646     "e" gnus-article-date-lapsed
1647     "o" gnus-article-date-original
1648     "i" gnus-article-date-iso8601
1649     "s" gnus-article-date-user)
1650
1651   (gnus-define-keys (gnus-summary-wash-empty-map "E" gnus-summary-wash-map)
1652     "t" gnus-article-remove-trailing-blank-lines
1653     "l" gnus-article-strip-leading-blank-lines
1654     "m" gnus-article-strip-multiple-blank-lines
1655     "a" gnus-article-strip-blank-lines
1656     "A" gnus-article-strip-all-blank-lines
1657     "s" gnus-article-strip-leading-space
1658     "e" gnus-article-strip-trailing-space)
1659
1660   (gnus-define-keys (gnus-summary-help-map "H" gnus-summary-mode-map)
1661     "v" gnus-version
1662     "f" gnus-summary-fetch-faq
1663     "d" gnus-summary-describe-group
1664     "h" gnus-summary-describe-briefly
1665     "i" gnus-info-find-node)
1666
1667   (gnus-define-keys (gnus-summary-backend-map "B" gnus-summary-mode-map)
1668     "e" gnus-summary-expire-articles
1669     "\M-\C-e" gnus-summary-expire-articles-now
1670     "\177" gnus-summary-delete-article
1671     [delete] gnus-summary-delete-article
1672     [backspace] gnus-summary-delete-article
1673     "m" gnus-summary-move-article
1674     "r" gnus-summary-respool-article
1675     "w" gnus-summary-edit-article
1676     "c" gnus-summary-copy-article
1677     "B" gnus-summary-crosspost-article
1678     "q" gnus-summary-respool-query
1679     "t" gnus-summary-respool-trace
1680     "i" gnus-summary-import-article
1681     "p" gnus-summary-article-posted-p)
1682
1683   (gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map)
1684     "o" gnus-summary-save-article
1685     "m" gnus-summary-save-article-mail
1686     "F" gnus-summary-write-article-file
1687     "r" gnus-summary-save-article-rmail
1688     "f" gnus-summary-save-article-file
1689     "b" gnus-summary-save-article-body-file
1690     "h" gnus-summary-save-article-folder
1691     "v" gnus-summary-save-article-vm
1692     "p" gnus-summary-pipe-output
1693     "s" gnus-soup-add-article)
1694
1695   (gnus-define-keys (gnus-summary-mime-map "K" gnus-summary-mode-map)
1696     "b" gnus-summary-display-buttonized
1697     "m" gnus-summary-repair-multipart
1698     "v" gnus-article-view-part
1699     "o" gnus-article-save-part
1700     "c" gnus-article-copy-part
1701     "C" gnus-article-view-part-as-charset
1702     "e" gnus-article-externalize-part
1703     "E" gnus-article-encrypt-body
1704     "i" gnus-article-inline-part
1705     "|" gnus-article-pipe-part))
1706
1707 (defun gnus-summary-make-menu-bar ()
1708   (gnus-turn-off-edit-menu 'summary)
1709
1710   (unless (boundp 'gnus-summary-misc-menu)
1711
1712     (easy-menu-define
1713      gnus-summary-kill-menu gnus-summary-mode-map ""
1714      (cons
1715       "Score"
1716       (nconc
1717        (list
1718         ["Customize" gnus-score-customize t])
1719        (gnus-make-score-map 'increase)
1720        (gnus-make-score-map 'lower)
1721        '(("Mark"
1722           ["Kill below" gnus-summary-kill-below t]
1723           ["Mark above" gnus-summary-mark-above t]
1724           ["Tick above" gnus-summary-tick-above t]
1725           ["Clear above" gnus-summary-clear-above t])
1726          ["Current score" gnus-summary-current-score t]
1727          ["Set score" gnus-summary-set-score t]
1728          ["Switch current score file..." gnus-score-change-score-file t]
1729          ["Set mark below..." gnus-score-set-mark-below t]
1730          ["Set expunge below..." gnus-score-set-expunge-below t]
1731          ["Edit current score file" gnus-score-edit-current-scores t]
1732          ["Edit score file" gnus-score-edit-file t]
1733          ["Trace score" gnus-score-find-trace t]
1734          ["Find words" gnus-score-find-favourite-words t]
1735          ["Rescore buffer" gnus-summary-rescore t]
1736          ["Increase score..." gnus-summary-increase-score t]
1737          ["Lower score..." gnus-summary-lower-score t]))))
1738
1739     ;; Define both the Article menu in the summary buffer and the equivalent
1740     ;; Commands menu in the article buffer here for consistency.
1741     (let ((innards
1742            `(("Hide"
1743               ["All" gnus-article-hide t]
1744               ["Headers" gnus-article-hide-headers t]
1745               ["Signature" gnus-article-hide-signature t]
1746               ["Citation" gnus-article-hide-citation t]
1747               ["List identifiers" gnus-article-hide-list-identifiers t]
1748               ["PGP" gnus-article-hide-pgp t]
1749               ["Banner" gnus-article-strip-banner t]
1750               ["Boring headers" gnus-article-hide-boring-headers t])
1751              ("Highlight"
1752               ["All" gnus-article-highlight t]
1753               ["Headers" gnus-article-highlight-headers t]
1754               ["Signature" gnus-article-highlight-signature t]
1755               ["Citation" gnus-article-highlight-citation t])
1756              ("MIME"
1757               ["Words" gnus-article-decode-mime-words t]
1758               ["Charset" gnus-article-decode-charset t]
1759               ["QP" gnus-article-de-quoted-unreadable t]
1760               ["Base64" gnus-article-de-base64-unreadable t]
1761               ["View all" gnus-mime-view-all-parts t]
1762               ["Verify and Decrypt" gnus-summary-force-verify-and-decrypt t]
1763               ["Encrypt body" gnus-article-encrypt-body t])
1764              ("Date"
1765               ["Local" gnus-article-date-local t]
1766               ["ISO8601" gnus-article-date-iso8601 t]
1767               ["UT" gnus-article-date-ut t]
1768               ["Original" gnus-article-date-original t]
1769               ["Lapsed" gnus-article-date-lapsed t]
1770               ["User-defined" gnus-article-date-user t])
1771              ("Washing"
1772               ("Remove Blanks"
1773                ["Leading" gnus-article-strip-leading-blank-lines t]
1774                ["Multiple" gnus-article-strip-multiple-blank-lines t]
1775                ["Trailing" gnus-article-remove-trailing-blank-lines t]
1776                ["All of the above" gnus-article-strip-blank-lines t]
1777                ["All" gnus-article-strip-all-blank-lines t]
1778                ["Leading space" gnus-article-strip-leading-space t]
1779                ["Trailing space" gnus-article-strip-trailing-space t])
1780               ["Overstrike" gnus-article-treat-overstrike t]
1781               ["Dumb quotes" gnus-article-treat-dumbquotes t]
1782               ["Emphasis" gnus-article-emphasize t]
1783               ["Word wrap" gnus-article-fill-cited-article t]
1784               ["Fill long lines" gnus-article-fill-long-lines t]
1785               ["Capitalize sentences" gnus-article-capitalize-sentences t]
1786               ["CR" gnus-article-remove-cr t]
1787               ["Show X-Face" gnus-article-display-x-face t]
1788               ["Quoted-Printable" gnus-article-de-quoted-unreadable t]
1789               ["Base64" gnus-article-de-base64-unreadable t]
1790               ["Rot 13" gnus-summary-caesar-message
1791                ,@(if (featurep 'xemacs) '(t)
1792                    '(:help "\"Caesar rotate\" article by 13"))]
1793               ["Unix pipe" gnus-summary-pipe-message t]
1794               ["Add buttons" gnus-article-add-buttons t]
1795               ["Add buttons to head" gnus-article-add-buttons-to-head t]
1796               ["Stop page breaking" gnus-summary-stop-page-breaking t]
1797               ["Verbose header" gnus-summary-verbose-headers t]
1798               ["Toggle header" gnus-summary-toggle-header t]
1799               ["Html" gnus-article-wash-html t]
1800               ["Verify X-PGP-Sig" gnus-article-verify-x-pgp-sig t]
1801               ["HZ" gnus-article-decode-HZ t])
1802              ("Output"
1803               ["Save in default format" gnus-summary-save-article
1804                ,@(if (featurep 'xemacs) '(t)
1805                    '(:help "Save article using default method"))]
1806               ["Save in file" gnus-summary-save-article-file
1807                ,@(if (featurep 'xemacs) '(t)
1808                    '(:help "Save article in file"))]
1809               ["Save in Unix mail format" gnus-summary-save-article-mail t]
1810               ["Save in MH folder" gnus-summary-save-article-folder t]
1811               ["Save in VM folder" gnus-summary-save-article-vm t]
1812               ["Save in RMAIL mbox" gnus-summary-save-article-rmail t]
1813               ["Save body in file" gnus-summary-save-article-body-file t]
1814               ["Pipe through a filter" gnus-summary-pipe-output t]
1815               ["Add to SOUP packet" gnus-soup-add-article t]
1816               ["Print" gnus-summary-print-article t])
1817              ("Backend"
1818               ["Respool article..." gnus-summary-respool-article t]
1819               ["Move article..." gnus-summary-move-article
1820                (gnus-check-backend-function
1821                 'request-move-article gnus-newsgroup-name)]
1822               ["Copy article..." gnus-summary-copy-article t]
1823               ["Crosspost article..." gnus-summary-crosspost-article
1824                (gnus-check-backend-function
1825                 'request-replace-article gnus-newsgroup-name)]
1826               ["Import file..." gnus-summary-import-article t]
1827               ["Check if posted" gnus-summary-article-posted-p t]
1828               ["Edit article" gnus-summary-edit-article
1829                (not (gnus-group-read-only-p))]
1830               ["Delete article" gnus-summary-delete-article
1831                (gnus-check-backend-function
1832                 'request-expire-articles gnus-newsgroup-name)]
1833               ["Query respool" gnus-summary-respool-query t]
1834               ["Trace respool" gnus-summary-respool-trace t]
1835               ["Delete expirable articles" gnus-summary-expire-articles-now
1836                (gnus-check-backend-function
1837                 'request-expire-articles gnus-newsgroup-name)])
1838              ("Extract"
1839               ["Uudecode" gnus-uu-decode-uu
1840                ,@(if (featurep 'xemacs) '(t)
1841                    '(:help "Decode uuencoded article(s)"))]
1842               ["Uudecode and save" gnus-uu-decode-uu-and-save t]
1843               ["Unshar" gnus-uu-decode-unshar t]
1844               ["Unshar and save" gnus-uu-decode-unshar-and-save t]
1845               ["Save" gnus-uu-decode-save t]
1846               ["Binhex" gnus-uu-decode-binhex t]
1847               ["Postscript" gnus-uu-decode-postscript t])
1848              ("Cache"
1849               ["Enter article" gnus-cache-enter-article t]
1850               ["Remove article" gnus-cache-remove-article t])
1851              ["Translate" gnus-article-babel t]
1852              ["Select article buffer" gnus-summary-select-article-buffer t]
1853              ["Enter digest buffer" gnus-summary-enter-digest-group t]
1854              ["Isearch article..." gnus-summary-isearch-article t]
1855              ["Beginning of the article" gnus-summary-beginning-of-article t]
1856              ["End of the article" gnus-summary-end-of-article t]
1857              ["Fetch parent of article" gnus-summary-refer-parent-article t]
1858              ["Fetch referenced articles" gnus-summary-refer-references t]
1859              ["Fetch current thread" gnus-summary-refer-thread t]
1860              ["Fetch article with id..." gnus-summary-refer-article t]
1861              ["Setup Mailing List Params" gnus-mailing-list-insinuate t]
1862              ["Redisplay" gnus-summary-show-article t])))
1863       (easy-menu-define
1864        gnus-summary-article-menu gnus-summary-mode-map ""
1865        (cons "Article" innards))
1866
1867       (if (not (keymapp gnus-summary-article-menu))
1868           (easy-menu-define
1869             gnus-article-commands-menu gnus-article-mode-map ""
1870             (cons "Commands" innards))
1871         ;; in Emacs, don't share menu.
1872         (setq gnus-article-commands-menu 
1873               (copy-keymap gnus-summary-article-menu))
1874         (define-key gnus-article-mode-map [menu-bar commands]
1875           (cons "Commands" gnus-article-commands-menu))))
1876
1877     (easy-menu-define
1878      gnus-summary-thread-menu gnus-summary-mode-map ""
1879      '("Threads"
1880        ["Toggle threading" gnus-summary-toggle-threads t]
1881        ["Hide threads" gnus-summary-hide-all-threads t]
1882        ["Show threads" gnus-summary-show-all-threads t]
1883        ["Hide thread" gnus-summary-hide-thread t]
1884        ["Show thread" gnus-summary-show-thread t]
1885        ["Go to next thread" gnus-summary-next-thread t]
1886        ["Go to previous thread" gnus-summary-prev-thread t]
1887        ["Go down thread" gnus-summary-down-thread t]
1888        ["Go up thread" gnus-summary-up-thread t]
1889        ["Top of thread" gnus-summary-top-thread t]
1890        ["Mark thread as read" gnus-summary-kill-thread t]
1891        ["Lower thread score" gnus-summary-lower-thread t]
1892        ["Raise thread score" gnus-summary-raise-thread t]
1893        ["Rethread current" gnus-summary-rethread-current t]))
1894
1895     (easy-menu-define
1896      gnus-summary-post-menu gnus-summary-mode-map ""
1897      `("Post"
1898        ["Post an article" gnus-summary-post-news
1899         ,@(if (featurep 'xemacs) '(t)
1900             '(:help "Post an article"))]
1901        ["Followup" gnus-summary-followup
1902         ,@(if (featurep 'xemacs) '(t)
1903             '(:help "Post followup to this article"))]
1904        ["Followup and yank" gnus-summary-followup-with-original
1905         ,@(if (featurep 'xemacs) '(t)
1906             '(:help "Post followup to this article, quoting its contents"))]
1907        ["Supersede article" gnus-summary-supersede-article t]
1908        ["Cancel article" gnus-summary-cancel-article
1909         ,@(if (featurep 'xemacs) '(t)
1910             '(:help "Cancel an article you posted"))]
1911        ["Reply" gnus-summary-reply t]
1912        ["Reply and yank" gnus-summary-reply-with-original t]
1913        ["Wide reply" gnus-summary-wide-reply t]
1914        ["Wide reply and yank" gnus-summary-wide-reply-with-original
1915         ,@(if (featurep 'xemacs) '(t)
1916             '(:help "Mail a reply, quoting this article"))]
1917        ["Mail forward" gnus-summary-mail-forward t]
1918        ["Post forward" gnus-summary-post-forward t]
1919        ["Digest and mail" gnus-uu-digest-mail-forward t]
1920        ["Digest and post" gnus-uu-digest-post-forward t]
1921        ["Resend message" gnus-summary-resend-message t]
1922        ["Send bounced mail" gnus-summary-resend-bounced-mail t]
1923        ["Send a mail" gnus-summary-mail-other-window t]
1924        ["Uuencode and post" gnus-uu-post-news
1925         ,@(if (featurep 'xemacs) '(t)
1926             '(:help "Post a uuencoded article"))]
1927        ["Followup via news" gnus-summary-followup-to-mail t]
1928        ["Followup via news and yank"
1929         gnus-summary-followup-to-mail-with-original t]
1930        ;;("Draft"
1931        ;;["Send" gnus-summary-send-draft t]
1932        ;;["Send bounced" gnus-resend-bounced-mail t])
1933        ))
1934
1935     (easy-menu-define
1936      gnus-summary-misc-menu gnus-summary-mode-map ""
1937      `("Misc"
1938        ("Mark Read"
1939         ["Mark as read" gnus-summary-mark-as-read-forward t]
1940         ["Mark same subject and select"
1941          gnus-summary-kill-same-subject-and-select t]
1942         ["Mark same subject" gnus-summary-kill-same-subject t]
1943         ["Catchup" gnus-summary-catchup
1944          ,@(if (featurep 'xemacs) '(t)
1945              '(:help "Mark unread articles in this group as read"))]
1946         ["Catchup all" gnus-summary-catchup-all t]
1947         ["Catchup to here" gnus-summary-catchup-to-here t]
1948         ["Catchup region" gnus-summary-mark-region-as-read t]
1949         ["Mark excluded" gnus-summary-limit-mark-excluded-as-read t])
1950        ("Mark Various"
1951         ["Tick" gnus-summary-tick-article-forward t]
1952         ["Mark as dormant" gnus-summary-mark-as-dormant t]
1953         ["Remove marks" gnus-summary-clear-mark-forward t]
1954         ["Set expirable mark" gnus-summary-mark-as-expirable t]
1955         ["Set bookmark" gnus-summary-set-bookmark t]
1956         ["Remove bookmark" gnus-summary-remove-bookmark t])
1957        ("Mark Limit"
1958         ["Marks..." gnus-summary-limit-to-marks t]
1959         ["Subject..." gnus-summary-limit-to-subject t]
1960         ["Author..." gnus-summary-limit-to-author t]
1961         ["Age..." gnus-summary-limit-to-age t]
1962         ["Extra..." gnus-summary-limit-to-extra t]
1963         ["Score" gnus-summary-limit-to-score t]
1964         ["Unread" gnus-summary-limit-to-unread t]
1965         ["Non-dormant" gnus-summary-limit-exclude-dormant t]
1966         ["Articles" gnus-summary-limit-to-articles t]
1967         ["Pop limit" gnus-summary-pop-limit t]
1968         ["Show dormant" gnus-summary-limit-include-dormant t]
1969         ["Hide childless dormant"
1970          gnus-summary-limit-exclude-childless-dormant t]
1971         ;;["Hide thread" gnus-summary-limit-exclude-thread t]
1972         ["Hide marked" gnus-summary-limit-exclude-marks t]
1973         ["Show expunged" gnus-summary-show-all-expunged t])
1974        ("Process Mark"
1975         ["Set mark" gnus-summary-mark-as-processable t]
1976         ["Remove mark" gnus-summary-unmark-as-processable t]
1977         ["Remove all marks" gnus-summary-unmark-all-processable t]
1978         ["Mark above" gnus-uu-mark-over t]
1979         ["Mark series" gnus-uu-mark-series t]
1980         ["Mark region" gnus-uu-mark-region t]
1981         ["Unmark region" gnus-uu-unmark-region t]
1982         ["Mark by regexp..." gnus-uu-mark-by-regexp t]
1983         ["Unmark by regexp..." gnus-uu-unmark-by-regexp t]
1984         ["Mark all" gnus-uu-mark-all t]
1985         ["Mark buffer" gnus-uu-mark-buffer t]
1986         ["Mark sparse" gnus-uu-mark-sparse t]
1987         ["Mark thread" gnus-uu-mark-thread t]
1988         ["Unmark thread" gnus-uu-unmark-thread t]
1989         ("Process Mark Sets"
1990          ["Kill" gnus-summary-kill-process-mark t]
1991          ["Yank" gnus-summary-yank-process-mark
1992           gnus-newsgroup-process-stack]
1993          ["Save" gnus-summary-save-process-mark t]))
1994        ("Scroll article"
1995         ["Page forward" gnus-summary-next-page
1996          ,@(if (featurep 'xemacs) '(t)
1997              '(:help "Show next page of article"))]
1998         ["Page backward" gnus-summary-prev-page
1999          ,@(if (featurep 'xemacs) '(t)
2000              '(:help "Show previous page of article"))]
2001         ["Line forward" gnus-summary-scroll-up t])
2002        ("Move"
2003         ["Next unread article" gnus-summary-next-unread-article t]
2004         ["Previous unread article" gnus-summary-prev-unread-article t]
2005         ["Next article" gnus-summary-next-article t]
2006         ["Previous article" gnus-summary-prev-article t]
2007         ["Next unread subject" gnus-summary-next-unread-subject t]
2008         ["Previous unread subject" gnus-summary-prev-unread-subject t]
2009         ["Next article same subject" gnus-summary-next-same-subject t]
2010         ["Previous article same subject" gnus-summary-prev-same-subject t]
2011         ["First unread article" gnus-summary-first-unread-article t]
2012         ["Best unread article" gnus-summary-best-unread-article t]
2013         ["Go to subject number..." gnus-summary-goto-subject t]
2014         ["Go to article number..." gnus-summary-goto-article t]
2015         ["Go to the last article" gnus-summary-goto-last-article t]
2016         ["Pop article off history" gnus-summary-pop-article t])
2017        ("Sort"
2018         ["Sort by number" gnus-summary-sort-by-number t]
2019         ["Sort by author" gnus-summary-sort-by-author t]
2020         ["Sort by subject" gnus-summary-sort-by-subject t]
2021         ["Sort by date" gnus-summary-sort-by-date t]
2022         ["Sort by score" gnus-summary-sort-by-score t]
2023         ["Sort by lines" gnus-summary-sort-by-lines t]
2024         ["Sort by characters" gnus-summary-sort-by-chars t])
2025        ("Help"
2026         ["Fetch group FAQ" gnus-summary-fetch-faq t]
2027         ["Describe group" gnus-summary-describe-group t]
2028         ["Read manual" gnus-info-find-node t])
2029        ("Modes"
2030         ["Pick and read" gnus-pick-mode t]
2031         ["Binary" gnus-binary-mode t])
2032        ("Regeneration"
2033         ["Regenerate" gnus-summary-prepare t]
2034         ["Insert cached articles" gnus-summary-insert-cached-articles t]
2035         ["Toggle threading" gnus-summary-toggle-threads t])
2036        ["Filter articles..." gnus-summary-execute-command t]
2037        ["Run command on subjects..." gnus-summary-universal-argument t]
2038        ["Search articles forward..." gnus-summary-search-article-forward t]
2039        ["Search articles backward..." gnus-summary-search-article-backward t]
2040        ["Toggle line truncation" gnus-summary-toggle-truncation t]
2041        ["Expand window" gnus-summary-expand-window t]
2042        ["Expire expirable articles" gnus-summary-expire-articles
2043         (gnus-check-backend-function
2044          'request-expire-articles gnus-newsgroup-name)]
2045        ["Edit local kill file" gnus-summary-edit-local-kill t]
2046        ["Edit main kill file" gnus-summary-edit-global-kill t]
2047        ["Edit group parameters" gnus-summary-edit-parameters t]
2048        ["Customize group parameters" gnus-summary-customize-parameters t]
2049        ["Send a bug report" gnus-bug t]
2050        ("Exit"
2051         ["Catchup and exit" gnus-summary-catchup-and-exit
2052          ,@(if (featurep 'xemacs) '(t)
2053              '(:help "Mark unread articles in this group as read, then exit"))]
2054         ["Catchup all and exit" gnus-summary-catchup-all-and-exit t]
2055         ["Catchup and goto next" gnus-summary-catchup-and-goto-next-group t]
2056         ["Exit group" gnus-summary-exit
2057          ,@(if (featurep 'xemacs) '(t)
2058              '(:help "Exit current group, return to group selection mode"))]
2059         ["Exit group without updating" gnus-summary-exit-no-update t]
2060         ["Exit and goto next group" gnus-summary-next-group t]
2061         ["Exit and goto prev group" gnus-summary-prev-group t]
2062         ["Reselect group" gnus-summary-reselect-current-group t]
2063         ["Rescan group" gnus-summary-rescan-group t]
2064         ["Update dribble" gnus-summary-save-newsrc t])))
2065
2066     (gnus-run-hooks 'gnus-summary-menu-hook)))
2067
2068 (defvar gnus-summary-tool-bar-map nil)
2069
2070 ;; Emacs 21 tool bar.  Should be no-op otherwise.
2071 (defun gnus-summary-make-tool-bar ()
2072   (if (and (fboundp 'tool-bar-add-item-from-menu)
2073            (default-value 'tool-bar-mode)
2074            (not gnus-summary-tool-bar-map))
2075       (setq gnus-summary-tool-bar-map
2076             (let ((tool-bar-map (make-sparse-keymap))
2077                   (load-path (mm-image-load-path)))
2078               (tool-bar-add-item-from-menu
2079                'gnus-summary-prev-unread "prev-ur" gnus-summary-mode-map)
2080               (tool-bar-add-item-from-menu
2081                'gnus-summary-next-unread "next-ur" gnus-summary-mode-map)
2082               (tool-bar-add-item-from-menu
2083                'gnus-summary-post-news "post" gnus-summary-mode-map)
2084               (tool-bar-add-item-from-menu
2085                'gnus-summary-followup-with-original "fuwo" gnus-summary-mode-map)
2086               (tool-bar-add-item-from-menu
2087                'gnus-summary-followup "followup" gnus-summary-mode-map)
2088               (tool-bar-add-item-from-menu
2089                'gnus-summary-reply-with-original "reply-wo" gnus-summary-mode-map)
2090               (tool-bar-add-item-from-menu
2091                'gnus-summary-reply "reply" gnus-summary-mode-map)
2092               (tool-bar-add-item-from-menu
2093                'gnus-summary-caesar-message "rot13" gnus-summary-mode-map)
2094               (tool-bar-add-item-from-menu
2095                'gnus-uu-decode-uu "uu-decode" gnus-summary-mode-map)
2096               (tool-bar-add-item-from-menu
2097                'gnus-summary-save-article-file "save-aif" gnus-summary-mode-map)
2098               (tool-bar-add-item-from-menu
2099                'gnus-summary-save-article "save-art" gnus-summary-mode-map)
2100               (tool-bar-add-item-from-menu
2101                'gnus-uu-post-news "uu-post" gnus-summary-mode-map)
2102               (tool-bar-add-item-from-menu
2103                'gnus-summary-catchup "catchup" gnus-summary-mode-map)
2104               (tool-bar-add-item-from-menu
2105                'gnus-summary-catchup-and-exit "cu-exit" gnus-summary-mode-map)
2106               (tool-bar-add-item-from-menu
2107                'gnus-summary-exit "exit-summ" gnus-summary-mode-map)
2108               tool-bar-map)))
2109   (if gnus-summary-tool-bar-map
2110       (set (make-local-variable 'tool-bar-map) gnus-summary-tool-bar-map)))
2111
2112 (defun gnus-score-set-default (var value)
2113   "A version of set that updates the GNU Emacs menu-bar."
2114   (set var value)
2115   ;; It is the message that forces the active status to be updated.
2116   (message ""))
2117
2118 (defun gnus-make-score-map (type)
2119   "Make a summary score map of type TYPE."
2120   (if t
2121       nil
2122     (let ((headers '(("author" "from" string)
2123                      ("subject" "subject" string)
2124                      ("article body" "body" string)
2125                      ("article head" "head" string)
2126                      ("xref" "xref" string)
2127                      ("extra header" "extra" string)
2128                      ("lines" "lines" number)
2129                      ("followups to author" "followup" string)))
2130           (types '((number ("less than" <)
2131                            ("greater than" >)
2132                            ("equal" =))
2133                    (string ("substring" s)
2134                            ("exact string" e)
2135                            ("fuzzy string" f)
2136                            ("regexp" r))))
2137           (perms '(("temporary" (current-time-string))
2138                    ("permanent" nil)
2139                    ("immediate" now)))
2140           header)
2141       (list
2142        (apply
2143         'nconc
2144         (list
2145          (if (eq type 'lower)
2146              "Lower score"
2147            "Increase score"))
2148         (let (outh)
2149           (while headers
2150             (setq header (car headers))
2151             (setq outh
2152                   (cons
2153                    (apply
2154                     'nconc
2155                     (list (car header))
2156                     (let ((ts (cdr (assoc (nth 2 header) types)))
2157                           outt)
2158                       (while ts
2159                         (setq outt
2160                               (cons
2161                                (apply
2162                                 'nconc
2163                                 (list (caar ts))
2164                                 (let ((ps perms)
2165                                       outp)
2166                                   (while ps
2167                                     (setq outp
2168                                           (cons
2169                                            (vector
2170                                             (caar ps)
2171                                             (list
2172                                              'gnus-summary-score-entry
2173                                              (nth 1 header)
2174                                              (if (or (string= (nth 1 header)
2175                                                               "head")
2176                                                      (string= (nth 1 header)
2177                                                               "body"))
2178                                                  ""
2179                                                (list 'gnus-summary-header
2180                                                      (nth 1 header)))
2181                                              (list 'quote (nth 1 (car ts)))
2182                                              (list 'gnus-score-delta-default
2183                                                    nil)
2184                                              (nth 1 (car ps))
2185                                              t)
2186                                             t)
2187                                            outp))
2188                                     (setq ps (cdr ps)))
2189                                   (list (nreverse outp))))
2190                                outt))
2191                         (setq ts (cdr ts)))
2192                       (list (nreverse outt))))
2193                    outh))
2194             (setq headers (cdr headers)))
2195           (list (nreverse outh))))))))
2196
2197 \f
2198
2199 (defun gnus-summary-mode (&optional group)
2200   "Major mode for reading articles.
2201
2202 All normal editing commands are switched off.
2203 \\<gnus-summary-mode-map>
2204 Each line in this buffer represents one article.  To read an
2205 article, you can, for instance, type `\\[gnus-summary-next-page]'.  To move forwards
2206 and backwards while displaying articles, type `\\[gnus-summary-next-unread-article]' and `\\[gnus-summary-prev-unread-article]',
2207 respectively.
2208
2209 You can also post articles and send mail from this buffer.  To
2210 follow up an article, type `\\[gnus-summary-followup]'.  To mail a reply to the author
2211 of an article, type `\\[gnus-summary-reply]'.
2212
2213 There are approx. one gazillion commands you can execute in this
2214 buffer; read the info pages for more information (`\\[gnus-info-find-node]').
2215
2216 The following commands are available:
2217
2218 \\{gnus-summary-mode-map}"
2219   (interactive)
2220   (kill-all-local-variables)
2221   (when (gnus-visual-p 'summary-menu 'menu)
2222     (gnus-summary-make-menu-bar)
2223     (gnus-summary-make-tool-bar))
2224   (gnus-summary-make-local-variables)
2225   (let ((gnus-summary-local-variables gnus-newsgroup-variables))
2226     (gnus-summary-make-local-variables))
2227   (gnus-make-thread-indent-array)
2228   (gnus-simplify-mode-line)
2229   (setq major-mode 'gnus-summary-mode)
2230   (setq mode-name "Summary")
2231   (make-local-variable 'minor-mode-alist)
2232   (use-local-map gnus-summary-mode-map)
2233   (buffer-disable-undo)
2234   (setq buffer-read-only t)             ;Disable modification
2235   (setq truncate-lines t)
2236   (setq selective-display t)
2237   (setq selective-display-ellipses t)   ;Display `...'
2238   (gnus-summary-set-display-table)
2239   (gnus-set-default-directory)
2240   (setq gnus-newsgroup-name group)
2241   (make-local-variable 'gnus-summary-line-format)
2242   (make-local-variable 'gnus-summary-line-format-spec)
2243   (make-local-variable 'gnus-summary-dummy-line-format)
2244   (make-local-variable 'gnus-summary-dummy-line-format-spec)
2245   (make-local-variable 'gnus-summary-mark-positions)
2246   (make-local-hook 'pre-command-hook)
2247   (add-hook 'pre-command-hook 'gnus-set-global-variables nil t)
2248   (gnus-run-hooks 'gnus-summary-mode-hook)
2249   (turn-on-gnus-mailing-list-mode)
2250   (mm-enable-multibyte-mule4)
2251   (gnus-update-format-specifications nil 'summary 'summary-mode 'summary-dummy)
2252   (gnus-update-summary-mark-positions))
2253
2254 (defun gnus-summary-make-local-variables ()
2255   "Make all the local summary buffer variables."
2256   (let (global)
2257     (dolist (local gnus-summary-local-variables)
2258       (if (consp local)
2259           (progn
2260             (if (eq (cdr local) 'global)
2261                 ;; Copy the global value of the variable.
2262                 (setq global (symbol-value (car local)))
2263               ;; Use the value from the list.
2264               (setq global (eval (cdr local))))
2265             (set (make-local-variable (car local)) global))
2266         ;; Simple nil-valued local variable.
2267         (set (make-local-variable local) nil)))))
2268
2269 (defun gnus-summary-clear-local-variables ()
2270   (let ((locals gnus-summary-local-variables))
2271     (while locals
2272       (if (consp (car locals))
2273           (and (vectorp (caar locals))
2274                (set (caar locals) nil))
2275         (and (vectorp (car locals))
2276              (set (car locals) nil)))
2277       (setq locals (cdr locals)))))
2278
2279 ;; Summary data functions.
2280
2281 (defmacro gnus-data-number (data)
2282   `(car ,data))
2283
2284 (defmacro gnus-data-set-number (data number)
2285   `(setcar ,data ,number))
2286
2287 (defmacro gnus-data-mark (data)
2288   `(nth 1 ,data))
2289
2290 (defmacro gnus-data-set-mark (data mark)
2291   `(setcar (nthcdr 1 ,data) ,mark))
2292
2293 (defmacro gnus-data-pos (data)
2294   `(nth 2 ,data))
2295
2296 (defmacro gnus-data-set-pos (data pos)
2297   `(setcar (nthcdr 2 ,data) ,pos))
2298
2299 (defmacro gnus-data-header (data)
2300   `(nth 3 ,data))
2301
2302 (defmacro gnus-data-set-header (data header)
2303   `(setf (nth 3 ,data) ,header))
2304
2305 (defmacro gnus-data-level (data)
2306   `(nth 4 ,data))
2307
2308 (defmacro gnus-data-unread-p (data)
2309   `(= (nth 1 ,data) gnus-unread-mark))
2310
2311 (defmacro gnus-data-read-p (data)
2312   `(/= (nth 1 ,data) gnus-unread-mark))
2313
2314 (defmacro gnus-data-pseudo-p (data)
2315   `(consp (nth 3 ,data)))
2316
2317 (defmacro gnus-data-find (number)
2318   `(assq ,number gnus-newsgroup-data))
2319
2320 (defmacro gnus-data-find-list (number &optional data)
2321   `(let ((bdata ,(or data 'gnus-newsgroup-data)))
2322      (memq (assq ,number bdata)
2323            bdata)))
2324
2325 (defmacro gnus-data-make (number mark pos header level)
2326   `(list ,number ,mark ,pos ,header ,level))
2327
2328 (defun gnus-data-enter (after-article number mark pos header level offset)
2329   (let ((data (gnus-data-find-list after-article)))
2330     (unless data
2331       (error "No such article: %d" after-article))
2332     (setcdr data (cons (gnus-data-make number mark pos header level)
2333                        (cdr data)))
2334     (setq gnus-newsgroup-data-reverse nil)
2335     (gnus-data-update-list (cddr data) offset)))
2336
2337 (defun gnus-data-enter-list (after-article list &optional offset)
2338   (when list
2339     (let ((data (and after-article (gnus-data-find-list after-article)))
2340           (ilist list))
2341       (if (not (or data
2342                    after-article))
2343           (let ((odata gnus-newsgroup-data))
2344             (setq gnus-newsgroup-data (nconc list gnus-newsgroup-data))
2345             (when offset
2346               (gnus-data-update-list odata offset)))
2347         ;; Find the last element in the list to be spliced into the main
2348         ;; list.
2349         (while (cdr list)
2350           (setq list (cdr list)))
2351         (if (not data)
2352             (progn
2353               (setcdr list gnus-newsgroup-data)
2354               (setq gnus-newsgroup-data ilist)
2355               (when offset
2356                 (gnus-data-update-list (cdr list) offset)))
2357           (setcdr list (cdr data))
2358           (setcdr data ilist)
2359           (when offset
2360             (gnus-data-update-list (cdr list) offset))))
2361       (setq gnus-newsgroup-data-reverse nil))))
2362
2363 (defun gnus-data-remove (article &optional offset)
2364   (let ((data gnus-newsgroup-data))
2365     (if (= (gnus-data-number (car data)) article)
2366         (progn
2367           (setq gnus-newsgroup-data (cdr gnus-newsgroup-data)
2368                 gnus-newsgroup-data-reverse nil)
2369           (when offset
2370             (gnus-data-update-list gnus-newsgroup-data offset)))
2371       (while (cdr data)
2372         (when (= (gnus-data-number (cadr data)) article)
2373           (setcdr data (cddr data))
2374           (when offset
2375             (gnus-data-update-list (cdr data) offset))
2376           (setq data nil
2377                 gnus-newsgroup-data-reverse nil))
2378         (setq data (cdr data))))))
2379
2380 (defmacro gnus-data-list (backward)
2381   `(if ,backward
2382        (or gnus-newsgroup-data-reverse
2383            (setq gnus-newsgroup-data-reverse
2384                  (reverse gnus-newsgroup-data)))
2385      gnus-newsgroup-data))
2386
2387 (defun gnus-data-update-list (data offset)
2388   "Add OFFSET to the POS of all data entries in DATA."
2389   (setq gnus-newsgroup-data-reverse nil)
2390   (while data
2391     (setcar (nthcdr 2 (car data)) (+ offset (nth 2 (car data))))
2392     (setq data (cdr data))))
2393
2394 (defun gnus-summary-article-pseudo-p (article)
2395   "Say whether this article is a pseudo article or not."
2396   (not (vectorp (gnus-data-header (gnus-data-find article)))))
2397
2398 (defmacro gnus-summary-article-sparse-p (article)
2399   "Say whether this article is a sparse article or not."
2400   `(memq ,article gnus-newsgroup-sparse))
2401
2402 (defmacro gnus-summary-article-ancient-p (article)
2403   "Say whether this article is a sparse article or not."
2404   `(memq ,article gnus-newsgroup-ancient))
2405
2406 (defun gnus-article-parent-p (number)
2407   "Say whether this article is a parent or not."
2408   (let ((data (gnus-data-find-list number)))
2409     (and (cdr data)                     ; There has to be an article after...
2410          (< (gnus-data-level (car data)) ; And it has to have a higher level.
2411             (gnus-data-level (nth 1 data))))))
2412
2413 (defun gnus-article-children (number)
2414   "Return a list of all children to NUMBER."
2415   (let* ((data (gnus-data-find-list number))
2416          (level (gnus-data-level (car data)))
2417          children)
2418     (setq data (cdr data))
2419     (while (and data
2420                 (= (gnus-data-level (car data)) (1+ level)))
2421       (push (gnus-data-number (car data)) children)
2422       (setq data (cdr data)))
2423     children))
2424
2425 (defmacro gnus-summary-skip-intangible ()
2426   "If the current article is intangible, then jump to a different article."
2427   '(let ((to (get-text-property (point) 'gnus-intangible)))
2428      (and to (gnus-summary-goto-subject to))))
2429
2430 (defmacro gnus-summary-article-intangible-p ()
2431   "Say whether this article is intangible or not."
2432   '(get-text-property (point) 'gnus-intangible))
2433
2434 (defun gnus-article-read-p (article)
2435   "Say whether ARTICLE is read or not."
2436   (not (or (memq article gnus-newsgroup-marked)
2437            (memq article gnus-newsgroup-unreads)
2438            (memq article gnus-newsgroup-unselected)
2439            (memq article gnus-newsgroup-dormant))))
2440
2441 ;; Some summary mode macros.
2442
2443 (defmacro gnus-summary-article-number ()
2444   "The article number of the article on the current line.
2445 If there isn's an article number here, then we return the current
2446 article number."
2447   '(progn
2448      (gnus-summary-skip-intangible)
2449      (or (get-text-property (point) 'gnus-number)
2450          (gnus-summary-last-subject))))
2451
2452 (defmacro gnus-