c672b39c3fb6e108ac1ac8672240a4928e1b86d7
[gnus] / lisp / gnus.el
1 ;;; gnus.el --- a newsreader for GNU Emacs
2 ;; Copyright (C) 1987,88,89,90,93,94,95,96 Free Software Foundation, Inc.
3
4 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
5 ;;      Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
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 '(run-hooks 'gnus-load-hook))
30
31 (require 'mail-utils)
32 (require 'timezone)
33 (require 'nnheader)
34
35 (eval-when-compile (require 'cl))
36
37 ;; Site dependent variables.  These variables should be defined in
38 ;; paths.el.
39
40 (defvar gnus-default-nntp-server nil
41   "Specify a default NNTP server.
42 This variable should be defined in paths.el, and should never be set
43 by the user.
44 If you want to change servers, you should use `gnus-select-method'.
45 See the documentation to that variable.")
46
47 (defvar gnus-backup-default-subscribed-newsgroups
48   '("news.announce.newusers" "news.groups.questions" "gnu.emacs.gnus")
49   "Default default new newsgroups the first time Gnus is run.
50 Should be set in paths.el, and shouldn't be touched by the user.")
51
52 (defvar gnus-local-domain nil
53   "Local domain name without a host name.
54 The DOMAINNAME environment variable is used instead if it is defined.
55 If the `system-name' function returns the full Internet name, there is
56 no need to set this variable.")
57
58 (defvar gnus-local-organization nil
59   "String with a description of what organization (if any) the user belongs to.
60 The ORGANIZATION environment variable is used instead if it is defined.
61 If this variable contains a function, this function will be called
62 with the current newsgroup name as the argument.  The function should
63 return a string.
64
65 In any case, if the string (either in the variable, in the environment
66 variable, or returned by the function) is a file name, the contents of
67 this file will be used as the organization.")
68
69 ;; Customization variables
70
71 ;; Don't touch this variable.
72 (defvar gnus-nntp-service "nntp"
73   "*NNTP service name (\"nntp\" or 119).
74 This is an obsolete variable, which is scarcely used.  If you use an
75 nntp server for your newsgroup and want to change the port number
76 used to 899, you would say something along these lines:
77
78  (setq gnus-select-method '(nntp \"my.nntp.server\" (nntp-port-number 899)))")
79
80 (defvar gnus-nntpserver-file "/etc/nntpserver"
81   "*A file with only the name of the nntp server in it.")
82
83 ;; This function is used to check both the environment variable
84 ;; NNTPSERVER and the /etc/nntpserver file to see whether one can find
85 ;; an nntp server name default.
86 (defun gnus-getenv-nntpserver ()
87   (or (getenv "NNTPSERVER")
88       (and (file-readable-p gnus-nntpserver-file)
89            (save-excursion
90              (set-buffer (get-buffer-create " *gnus nntp*"))
91              (buffer-disable-undo (current-buffer))
92              (insert-file-contents gnus-nntpserver-file)
93              (let ((name (buffer-string)))
94                (prog1
95                    (if (string-match "^[ \t\n]*$" name)
96                        nil
97                      name)
98                  (kill-buffer (current-buffer))))))))
99
100 (defvar gnus-select-method
101   (nconc
102    (list 'nntp (or (condition-case ()
103                        (gnus-getenv-nntpserver)
104                      (error nil))
105                    (if (and gnus-default-nntp-server
106                             (not (string= gnus-default-nntp-server "")))
107                        gnus-default-nntp-server)
108                    (system-name)))
109    (if (or (null gnus-nntp-service)
110            (equal gnus-nntp-service "nntp"))
111        nil
112      (list gnus-nntp-service)))
113   "*Default method for selecting a newsgroup.
114 This variable should be a list, where the first element is how the
115 news is to be fetched, the second is the address.
116
117 For instance, if you want to get your news via NNTP from
118 \"flab.flab.edu\", you could say:
119
120 (setq gnus-select-method '(nntp \"flab.flab.edu\"))
121
122 If you want to use your local spool, say:
123
124 (setq gnus-select-method (list 'nnspool (system-name)))
125
126 If you use this variable, you must set `gnus-nntp-server' to nil.
127
128 There is a lot more to know about select methods and virtual servers -
129 see the manual for details.")
130
131 (defvar gnus-message-archive-method 
132   '(nnfolder "archive" (nnfolder-directory "~/Mail/archive/")
133              (nnfolder-active-file "~/Mail/archive/active")
134              (nnfolder-get-new-mail nil)
135              (nnfolder-inhibit-expiry t))
136   "*Method used for archiving messages you've sent.
137 This should be a mail method.")
138
139 (defvar gnus-refer-article-method nil
140   "*Preferred method for fetching an article by Message-ID.
141 If you are reading news from the local spool (with nnspool), fetching
142 articles by Message-ID is painfully slow.  By setting this method to an
143 nntp method, you might get acceptable results.
144
145 The value of this variable must be a valid select method as discussed
146 in the documentation of `gnus-select-method'.")
147
148 (defvar gnus-secondary-select-methods nil
149   "*A list of secondary methods that will be used for reading news.
150 This is a list where each element is a complete select method (see
151 `gnus-select-method').
152
153 If, for instance, you want to read your mail with the nnml backend,
154 you could set this variable:
155
156 (setq gnus-secondary-select-methods '((nnml \"\")))")
157
158 (defvar gnus-secondary-servers nil
159   "*List of NNTP servers that the user can choose between interactively.
160 To make Gnus query you for a server, you have to give `gnus' a
161 non-numeric prefix - `C-u M-x gnus', in short.")
162
163 (defvar gnus-nntp-server nil
164   "*The name of the host running the NNTP server.
165 This variable is semi-obsolete.  Use the `gnus-select-method'
166 variable instead.")
167
168 (defvar gnus-startup-file "~/.newsrc"
169   "*Your `.newsrc' file.
170 `.newsrc-SERVER' will be used instead if that exists.")
171
172 (defvar gnus-init-file "~/.gnus"
173   "*Your Gnus elisp startup file.
174 If a file with the .el or .elc suffixes exist, it will be read
175 instead.")
176
177 (defvar gnus-group-faq-directory
178   '("/ftp@mirrors.aol.com:/pub/rtfm/usenet/"
179     "/ftp@src.doc.ic.ac.uk:/usenet/news-FAQS/"
180     "/ftp@ftp.seas.gwu.edu:/pub/rtfm/"
181     "/ftp@rtfm.mit.edu:/pub/usenet/news.answers/"
182     "/ftp@ftp.uni-paderborn.de:/pub/FAQ/"
183     "/ftp@ftp.sunet.se:/pub/usenet/"
184     "/ftp@nctuccca.edu.tw:/USENET/FAQ/"
185     "/ftp@hwarang.postech.ac.kr:/pub/usenet/news.answers/"
186     "/ftp@ftp.hk.super.net:/mirror/faqs/")
187   "*Directory where the group FAQs are stored.
188 This will most commonly be on a remote machine, and the file will be
189 fetched by ange-ftp.
190
191 This variable can also be a list of directories.  In that case, the
192 first element in the list will be used by default, and the others will
193 be used as backup sites.
194
195 Note that Gnus uses an aol machine as the default directory.  If this
196 feels fundamentally unclean, just think of it as a way to finally get
197 something of value back from them.
198
199 If the default site is too slow, try one of these:
200
201    North America: mirrors.aol.com                /pub/rtfm/usenet
202                   ftp.seas.gwu.edu               /pub/rtfm
203                   rtfm.mit.edu                   /pub/usenet/news.answers
204    Europe:        ftp.uni-paderborn.de           /pub/FAQ
205                   src.doc.ic.ac.uk               /usenet/news-FAQS
206                   ftp.sunet.se                   /pub/usenet
207    Asia:          nctuccca.edu.tw                /USENET/FAQ
208                   hwarang.postech.ac.kr          /pub/usenet/news.answers
209                   ftp.hk.super.net               /mirror/faqs")
210
211 (defvar gnus-group-archive-directory
212   "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/"
213   "*The address of the (ding) archives.")
214
215 (defvar gnus-group-recent-archive-directory
216   "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list-recent/"
217   "*The address of the most recent (ding) articles.")
218
219 (defvar gnus-default-subscribed-newsgroups nil
220   "*This variable lists what newsgroups should be subscribed the first time Gnus is used.
221 It should be a list of strings.
222 If it is `t', Gnus will not do anything special the first time it is
223 started; it'll just use the normal newsgroups subscription methods.")
224
225 (defvar gnus-use-cross-reference t
226   "*Non-nil means that cross referenced articles will be marked as read.
227 If nil, ignore cross references.  If t, mark articles as read in
228 subscribed newsgroups.  If neither t nor nil, mark as read in all
229 newsgroups.")
230
231 (defvar gnus-single-article-buffer t
232   "*If non-nil, display all articles in the same buffer.
233 If nil, each group will get its own article buffer.")
234
235 (defvar gnus-use-dribble-file t
236   "*Non-nil means that Gnus will use a dribble file to store user updates.
237 If Emacs should crash without saving the .newsrc files, complete
238 information can be restored from the dribble file.")
239
240 (defvar gnus-dribble-directory nil
241   "*The directory where dribble files will be saved.
242 If this variable is nil, the directory where the .newsrc files are
243 saved will be used.")
244
245 (defvar gnus-asynchronous nil
246   "*If non-nil, Gnus will supply backends with data needed for async article fetching.")
247
248 (defvar gnus-kill-summary-on-exit t
249   "*If non-nil, kill the summary buffer when you exit from it.
250 If nil, the summary will become a \"*Dead Summary*\" buffer, and
251 it will be killed sometime later.")
252
253 (defvar gnus-large-newsgroup 200
254   "*The number of articles which indicates a large newsgroup.
255 If the number of articles in a newsgroup is greater than this value,
256 confirmation is required for selecting the newsgroup.")
257
258 ;; Suggested by Andrew Eskilsson <pi92ae@lelle.pt.hk-r.se>.
259 (defvar gnus-no-groups-message "No news is horrible news"
260   "*Message displayed by Gnus when no groups are available.")
261
262 (defvar gnus-use-long-file-name (not (memq system-type '(usg-unix-v xenix)))
263   "*Non-nil means that the default name of a file to save articles in is the group name.
264 If it's nil, the directory form of the group name is used instead.
265
266 If this variable is a list, and the list contains the element
267 `not-score', long file names will not be used for score files; if it
268 contains the element `not-save', long file names will not be used for
269 saving; and if it contains the element `not-kill', long file names
270 will not be used for kill files.")
271
272 (defvar gnus-article-save-directory (or (getenv "SAVEDIR") "~/News/")
273   "*Name of the directory articles will be saved in (default \"~/News\").
274 Initialized from the SAVEDIR environment variable.")
275
276 (defvar gnus-kill-files-directory (or (getenv "SAVEDIR") "~/News/")
277   "*Name of the directory where kill files will be stored (default \"~/News\").
278 Initialized from the SAVEDIR environment variable.")
279
280 (defvar gnus-default-article-saver 'gnus-summary-save-in-rmail
281   "*A function to save articles in your favorite format.
282 The function must be interactively callable (in other words, it must
283 be an Emacs command).
284
285 Gnus provides the following functions:
286
287 * gnus-summary-save-in-rmail (Rmail format)
288 * gnus-summary-save-in-mail (Unix mail format)
289 * gnus-summary-save-in-folder (MH folder)
290 * gnus-summary-save-in-file (article format).
291 * gnus-summary-save-in-vm (use VM's folder format).")
292
293 (defvar gnus-prompt-before-saving 'always
294   "*This variable says how much prompting is to be done when saving articles.
295 If it is nil, no prompting will be done, and the articles will be
296 saved to the default files.  If this variable is `always', each and
297 every article that is saved will be preceded by a prompt, even when
298 saving large batches of articles.  If this variable is neither nil not
299 `always', there the user will be prompted once for a file name for
300 each invocation of the saving commands.")
301
302 (defvar gnus-rmail-save-name (function gnus-plain-save-name)
303   "*A function generating a file name to save articles in Rmail format.
304 The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.")
305
306 (defvar gnus-mail-save-name (function gnus-plain-save-name)
307   "*A function generating a file name to save articles in Unix mail format.
308 The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.")
309
310 (defvar gnus-folder-save-name (function gnus-folder-save-name)
311   "*A function generating a file name to save articles in MH folder.
312 The function is called with NEWSGROUP, HEADERS, and optional LAST-FOLDER.")
313
314 (defvar gnus-file-save-name (function gnus-numeric-save-name)
315   "*A function generating a file name to save articles in article format.
316 The function is called with NEWSGROUP, HEADERS, and optional
317 LAST-FILE.")
318
319 (defvar gnus-split-methods
320   '((gnus-article-archive-name))
321   "*Variable used to suggest where articles are to be saved.
322 For instance, if you would like to save articles related to Gnus in
323 the file \"gnus-stuff\", and articles related to VM in \"vm-stuff\",
324 you could set this variable to something like:
325
326  '((\"^Subject:.*gnus\\|^Newsgroups:.*gnus\" \"gnus-stuff\")
327    (\"^Subject:.*vm\\|^Xref:.*vm\" \"vm-stuff\"))
328
329 This variable is an alist where the where the key is the match and the
330 value is a list of possible files to save in if the match is non-nil.
331
332 If the match is a string, it is used as a regexp match on the
333 article.  If the match is a symbol, that symbol will be funcalled
334 from the buffer of the article to be saved with the newsgroup as the
335 parameter.  If it is a list, it will be evaled in the same buffer.
336
337 If this form or function returns a string, this string will be used as
338 a possible file name; and if it returns a non-nil list, that list will
339 be used as possible file names.")
340
341 (defvar gnus-move-split-methods nil
342   "*Variable used to suggest where articles are to be moved to.
343 It uses the same syntax as the `gnus-split-methods' variable.")
344
345 (defvar gnus-save-score nil
346   "*If non-nil, save group scoring info.")
347
348 (defvar gnus-use-adaptive-scoring nil
349   "*If non-nil, use some adaptive scoring scheme.")
350
351 (defvar gnus-use-cache nil
352   "*If nil, Gnus will ignore the article cache.
353 If `passive', it will allow entering (and reading) articles
354 explicitly entered into the cache.  If anything else, use the
355 cache to the full extent of the law.")
356
357 (defvar gnus-use-trees nil
358   "*If non-nil, display a thread tree buffer.")
359
360 (defvar gnus-use-grouplens nil
361   "*If non-nil, use GroupLens ratings.")
362
363 (defvar gnus-keep-backlog nil
364   "*If non-nil, Gnus will keep read articles for later re-retrieval.
365 If it is a number N, then Gnus will only keep the last N articles
366 read.  If it is neither nil nor a number, Gnus will keep all read
367 articles.  This is not a good idea.")
368
369 (defvar gnus-use-nocem nil
370   "*If non-nil, Gnus will read NoCeM cancel messages.")
371
372 (defvar gnus-use-demon nil
373   "If non-nil, Gnus might use some demons.")
374
375 (defvar gnus-use-scoring t
376   "*If non-nil, enable scoring.")
377
378 (defvar gnus-use-picons nil
379   "*If non-nil, display picons.")
380
381 (defvar gnus-fetch-old-headers nil
382   "*Non-nil means that Gnus will try to build threads by grabbing old headers.
383 If an unread article in the group refers to an older, already read (or
384 just marked as read) article, the old article will not normally be
385 displayed in the Summary buffer.  If this variable is non-nil, Gnus
386 will attempt to grab the headers to the old articles, and thereby
387 build complete threads.  If it has the value `some', only enough
388 headers to connect otherwise loose threads will be displayed.
389 This variable can also be a number.  In that case, no more than that
390 number of old headers will be fetched.
391
392 The server has to support NOV for any of this to work.")
393
394 ;see gnus-cus.el
395 ;(defvar gnus-visual t
396 ;  "*If non-nil, will do various highlighting.
397 ;If nil, no mouse highlights (or any other highlights) will be
398 ;performed.  This might speed up Gnus some when generating large group
399 ;and summary buffers.")
400
401 (defvar gnus-novice-user t
402   "*Non-nil means that you are a usenet novice.
403 If non-nil, verbose messages may be displayed and confirmations may be
404 required.")
405
406 (defvar gnus-expert-user nil
407   "*Non-nil means that you will never be asked for confirmation about anything.
408 And that means *anything*.")
409
410 (defvar gnus-verbose 7
411   "*Integer that says how verbose Gnus should be.
412 The higher the number, the more messages Gnus will flash to say what
413 it's doing.  At zero, Gnus will be totally mute; at five, Gnus will
414 display most important messages; and at ten, Gnus will keep on
415 jabbering all the time.")
416
417 (defvar gnus-keep-same-level nil
418   "*Non-nil means that the next newsgroup after the current will be on the same level.
419 When you type, for instance, `n' after reading the last article in the
420 current newsgroup, you will go to the next newsgroup.  If this variable
421 is nil, the next newsgroup will be the next from the group
422 buffer.
423 If this variable is non-nil, Gnus will either put you in the
424 next newsgroup with the same level, or, if no such newsgroup is
425 available, the next newsgroup with the lowest possible level higher
426 than the current level.
427 If this variable is `best', Gnus will make the next newsgroup the one
428 with the best level.")
429
430 (defvar gnus-summary-make-false-root 'adopt
431   "*nil means that Gnus won't gather loose threads.
432 If the root of a thread has expired or been read in a previous
433 session, the information necessary to build a complete thread has been
434 lost.  Instead of having many small sub-threads from this original thread
435 scattered all over the summary buffer, Gnus can gather them.
436
437 If non-nil, Gnus will try to gather all loose sub-threads from an
438 original thread into one large thread.
439
440 If this variable is non-nil, it should be one of `none', `adopt',
441 `dummy' or `empty'.
442
443 If this variable is `none', Gnus will not make a false root, but just
444 present the sub-threads after another.
445 If this variable is `dummy', Gnus will create a dummy root that will
446 have all the sub-threads as children.
447 If this variable is `adopt', Gnus will make one of the \"children\"
448 the parent and mark all the step-children as such.
449 If this variable is `empty', the \"children\" are printed with empty
450 subject fields.  (Or rather, they will be printed with a string
451 given by the `gnus-summary-same-subject' variable.)")
452
453 (defvar gnus-summary-gather-exclude-subject "^ *$\\|^(none)$"
454   "*A regexp to match subjects to be excluded from loose thread gathering.
455 As loose thread gathering is done on subjects only, that means that
456 there can be many false gatherings performed.  By rooting out certain
457 common subjects, gathering might become saner.")
458
459 (defvar gnus-summary-gather-subject-limit nil
460   "*Maximum length of subject comparisons when gathering loose threads.
461 Use nil to compare full subjects.  Setting this variable to a low
462 number will help gather threads that have been corrupted by
463 newsreaders chopping off subject lines, but it might also mean that
464 unrelated articles that have subject that happen to begin with the
465 same few characters will be incorrectly gathered.
466
467 If this variable is `fuzzy', Gnus will use a fuzzy algorithm when
468 comparing subjects.")
469
470 (defvar gnus-simplify-ignored-prefixes nil
471   "*Regexp, matches for which are removed from subject lines when simplifying.")
472
473 (defvar gnus-build-sparse-threads nil
474   "*If non-nil, fill in the gaps in threads.
475 If `some', only fill in the gaps that are needed to tie loose threads
476 together.  If `more', fill in all leaf nodes that Gnus can find.  If
477 non-nil and non-`some', fill in all gaps that Gnus manages to guess.")
478
479 (defvar gnus-summary-thread-gathering-function 'gnus-gather-threads-by-subject
480   "Function used for gathering loose threads.
481 There are two pre-defined functions: `gnus-gather-threads-by-subject',
482 which only takes Subjects into consideration; and
483 `gnus-gather-threads-by-references', which compared the References
484 headers of the articles to find matches.")
485
486 ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
487 (defvar gnus-summary-same-subject ""
488   "*String indicating that the current article has the same subject as the previous.
489 This variable will only be used if the value of
490 `gnus-summary-make-false-root' is `empty'.")
491
492 (defvar gnus-summary-goto-unread t
493   "*If non-nil, marking commands will go to the next unread article.
494 If `never', \\<gnus-summary-mode-map>\\[gnus-summary-next-page] will go to the next article,
495 whether it is read or not.")
496
497 (defvar gnus-group-goto-unread t
498   "*If non-nil, movement commands will go to the next unread and subscribed group.")
499
500 (defvar gnus-goto-next-group-when-activating t
501   "*If non-nil, the \\<gnus-group-mode-map>\\[gnus-group-get-new-news-this-group] command will advance point to the next group.")
502
503 (defvar gnus-check-new-newsgroups t
504   "*Non-nil means that Gnus will add new newsgroups at startup.
505 If this variable is `ask-server', Gnus will ask the server for new
506 groups since the last time it checked.  This means that the killed list
507 is no longer necessary, so you could set `gnus-save-killed-list' to
508 nil.
509
510 A variant is to have this variable be a list of select methods.  Gnus
511 will then use the `ask-server' method on all these select methods to
512 query for new groups from all those servers.
513
514 Eg.
515   (setq gnus-check-new-newsgroups
516         '((nntp \"some.server\") (nntp \"other.server\")))
517
518 If this variable is nil, then you have to tell Gnus explicitly to
519 check for new newsgroups with \\<gnus-group-mode-map>\\[gnus-find-new-newsgroups].")
520
521 (defvar gnus-check-bogus-newsgroups nil
522   "*Non-nil means that Gnus will check and remove bogus newsgroup at startup.
523 If this variable is nil, then you have to tell Gnus explicitly to
524 check for bogus newsgroups with \\<gnus-group-mode-map>\\[gnus-group-check-bogus-groups].")
525
526 (defvar gnus-read-active-file t
527   "*Non-nil means that Gnus will read the entire active file at startup.
528 If this variable is nil, Gnus will only know about the groups in your
529 `.newsrc' file.
530
531 If this variable is `some', Gnus will try to only read the relevant
532 parts of the active file from the server.  Not all servers support
533 this, and it might be quite slow with other servers, but this should
534 generally be faster than both the t and nil value.
535
536 If you set this variable to nil or `some', you probably still want to
537 be told about new newsgroups that arrive.  To do that, set
538 `gnus-check-new-newsgroups' to `ask-server'.  This may not work
539 properly with all servers.")
540
541 (defvar gnus-level-subscribed 5
542   "*Groups with levels less than or equal to this variable are subscribed.")
543
544 (defvar gnus-level-unsubscribed 7
545   "*Groups with levels less than or equal to this variable are unsubscribed.
546 Groups with levels less than `gnus-level-subscribed', which should be
547 less than this variable, are subscribed.")
548
549 (defvar gnus-level-zombie 8
550   "*Groups with this level are zombie groups.")
551
552 (defvar gnus-level-killed 9
553   "*Groups with this level are killed.")
554
555 (defvar gnus-level-default-subscribed 3
556   "*New subscribed groups will be subscribed at this level.")
557
558 (defvar gnus-level-default-unsubscribed 6
559   "*New unsubscribed groups will be unsubscribed at this level.")
560
561 (defvar gnus-activate-level (1+ gnus-level-subscribed)
562   "*Groups higher than this level won't be activated on startup.
563 Setting this variable to something log might save lots of time when
564 you have many groups that you aren't interested in.")
565
566 (defvar gnus-activate-foreign-newsgroups 4
567   "*If nil, Gnus will not check foreign newsgroups at startup.
568 If it is non-nil, it should be a number between one and nine.  Foreign
569 newsgroups that have a level lower or equal to this number will be
570 activated on startup.  For instance, if you want to active all
571 subscribed newsgroups, but not the rest, you'd set this variable to
572 `gnus-level-subscribed'.
573
574 If you subscribe to lots of newsgroups from different servers, startup
575 might take a while.  By setting this variable to nil, you'll save time,
576 but you won't be told how many unread articles there are in the
577 groups.")
578
579 (defvar gnus-save-newsrc-file t
580   "*Non-nil means that Gnus will save the `.newsrc' file.
581 Gnus always saves its own startup file, which is called
582 \".newsrc.eld\".  The file called \".newsrc\" is in a format that can
583 be readily understood by other newsreaders.  If you don't plan on
584 using other newsreaders, set this variable to nil to save some time on
585 exit.")
586
587 (defvar gnus-save-killed-list t
588   "*If non-nil, save the list of killed groups to the startup file.
589 If you set this variable to nil, you'll save both time (when starting
590 and quitting) and space (both memory and disk), but it will also mean
591 that Gnus has no record of which groups are new and which are old, so
592 the automatic new newsgroups subscription methods become meaningless.
593
594 You should always set `gnus-check-new-newsgroups' to `ask-server' or
595 nil if you set this variable to nil.")
596
597 (defvar gnus-interactive-catchup t
598   "*If non-nil, require your confirmation when catching up a group.")
599
600 (defvar gnus-interactive-post t
601   "*If non-nil, group name will be asked for when posting.")
602
603 (defvar gnus-interactive-exit t
604   "*If non-nil, require your confirmation when exiting Gnus.")
605
606 (defvar gnus-kill-killed t
607   "*If non-nil, Gnus will apply kill files to already killed articles.
608 If it is nil, Gnus will never apply kill files to articles that have
609 already been through the scoring process, which might very well save lots
610 of time.")
611
612 (defvar gnus-extract-address-components 'gnus-extract-address-components
613   "*Function for extracting address components from a From header.
614 Two pre-defined function exist: `gnus-extract-address-components',
615 which is the default, quite fast, and too simplistic solution, and
616 `mail-extract-address-components', which works much better, but is
617 slower.")
618
619 (defvar gnus-summary-default-score 0
620   "*Default article score level.
621 If this variable is nil, scoring will be disabled.")
622
623 (defvar gnus-summary-zcore-fuzz 0
624   "*Fuzziness factor for the zcore in the summary buffer.
625 Articles with scores closer than this to `gnus-summary-default-score'
626 will not be marked.")
627
628 (defvar gnus-simplify-subject-fuzzy-regexp nil
629   "*Strings to be removed when doing fuzzy matches.
630 This can either be a regular expression or list of regular expressions
631 that will be removed from subject strings if fuzzy subject
632 simplification is selected.")
633
634 (defvar gnus-permanently-visible-groups nil
635   "*Regexp to match groups that should always be listed in the group buffer.
636 This means that they will still be listed when there are no unread
637 articles in the groups.")
638
639 (defvar gnus-list-groups-with-ticked-articles t
640   "*If non-nil, list groups that have only ticked articles.
641 If nil, only list groups that have unread articles.")
642
643 (defvar gnus-group-default-list-level gnus-level-subscribed
644   "*Default listing level.
645 Ignored if `gnus-group-use-permanent-levels' is non-nil.")
646
647 (defvar gnus-group-use-permanent-levels nil
648   "*If non-nil, once you set a level, Gnus will use this level.")
649
650 (defvar gnus-group-list-inactive-groups t
651   "*If non-nil, inactive groups will be listed.")
652
653 (defvar gnus-show-mime nil
654   "*If non-nil, do mime processing of articles.
655 The articles will simply be fed to the function given by
656 `gnus-show-mime-method'.")
657
658 (defvar gnus-strict-mime t
659   "*If nil, MIME-decode even if there is no Mime-Version header in the article.")
660
661 (defvar gnus-show-mime-method 'metamail-buffer
662   "*Function to process a MIME message.
663 The function is called from the article buffer.")
664
665 (defvar gnus-decode-encoded-word-method (lambda ())
666   "*Function to decode a MIME encoded-words.
667 The function is called from the article buffer.")
668
669 (defvar gnus-show-threads t
670   "*If non-nil, display threads in summary mode.")
671
672 (defvar gnus-thread-hide-subtree nil
673   "*If non-nil, hide all threads initially.
674 If threads are hidden, you have to run the command
675 `gnus-summary-show-thread' by hand or use `gnus-select-article-hook'
676 to expose hidden threads.")
677
678 (defvar gnus-thread-hide-killed t
679   "*If non-nil, hide killed threads automatically.")
680
681 (defvar gnus-thread-ignore-subject nil
682   "*If non-nil, ignore subjects and do all threading based on the Reference header.
683 If nil, which is the default, articles that have different subjects
684 from their parents will start separate threads.")
685
686 (defvar gnus-thread-operation-ignore-subject t
687   "*If non-nil, subjects will be ignored when doing thread commands.
688 This affects commands like `gnus-summary-kill-thread' and
689 `gnus-summary-lower-thread'.
690
691 If this variable is nil, articles in the same thread with different
692 subjects will not be included in the operation in question.  If this
693 variable is `fuzzy', only articles that have subjects that are fuzzily
694 equal will be included.")
695
696 (defvar gnus-thread-indent-level 4
697   "*Number that says how much each sub-thread should be indented.")
698
699 (defvar gnus-ignored-newsgroups
700   (purecopy (mapconcat 'identity
701                        '("^to\\."       ; not "real" groups
702                          "^[0-9. \t]+ " ; all digits in name
703                          "[][\"#'()]"   ; bogus characters
704                          )
705                        "\\|"))
706   "*A regexp to match uninteresting newsgroups in the active file.
707 Any lines in the active file matching this regular expression are
708 removed from the newsgroup list before anything else is done to it,
709 thus making them effectively non-existent.")
710
711 (defvar gnus-ignored-headers
712   "^Path:\\|^Posting-Version:\\|^Article-I.D.:\\|^Expires:\\|^Date-Received:\\|^References:\\|^Control:\\|^Xref:\\|^Lines:\\|^Posted:\\|^Relay-Version:\\|^Message-ID:\\|^Nf-ID:\\|^Nf-From:\\|^Approved:\\|^Sender:\\|^Received:\\|^Mail-from:"
713   "*All headers that match this regexp will be hidden.
714 This variable can also be a list of regexps of headers to be ignored.
715 If `gnus-visible-headers' is non-nil, this variable will be ignored.")
716
717 (defvar gnus-visible-headers "^From:\\|^Newsgroups:\\|^Subject:\\|^Date:\\|^Followup-To:\\|^Reply-To:\\|^Organization:\\|^Summary:\\|^Keywords:\\|^To:\\|^Cc:\\|^Posted-To:\\|^Mail-Copies-To:\\|^Apparently-To:\\|^Gnus-Warning:\\|^Resent-"
718   "*All headers that do not match this regexp will be hidden.
719 This variable can also be a list of regexp of headers to remain visible.
720 If this variable is non-nil, `gnus-ignored-headers' will be ignored.")
721
722 (defvar gnus-sorted-header-list
723   '("^From:" "^Subject:" "^Summary:" "^Keywords:" "^Newsgroups:" "^To:"
724     "^Cc:" "^Date:" "^Organization:")
725   "*This variable is a list of regular expressions.
726 If it is non-nil, headers that match the regular expressions will
727 be placed first in the article buffer in the sequence specified by
728 this list.")
729
730 (defvar gnus-boring-article-headers
731   '(empty followup-to reply-to)
732   "*Headers that are only to be displayed if they have interesting data.
733 Possible values in this list are `empty', `newsgroups', `followup-to',
734 `reply-to', and `date'.")
735
736 (defvar gnus-show-all-headers nil
737   "*If non-nil, don't hide any headers.")
738
739 (defvar gnus-save-all-headers t
740   "*If non-nil, don't remove any headers before saving.")
741
742 (defvar gnus-saved-headers gnus-visible-headers
743   "*Headers to keep if `gnus-save-all-headers' is nil.
744 If `gnus-save-all-headers' is non-nil, this variable will be ignored.
745 If that variable is nil, however, all headers that match this regexp
746 will be kept while the rest will be deleted before saving.")
747
748 (defvar gnus-inhibit-startup-message nil
749   "*If non-nil, the startup message will not be displayed.")
750
751 (defvar gnus-signature-separator "^-- *$"
752   "Regexp matching signature separator.")
753
754 (defvar gnus-signature-limit nil
755   "Provide a limit to what is considered a signature.
756 If it is a number, no signature may not be longer (in characters) than
757 that number.  If it is a function, the function will be called without
758 any parameters, and if it returns nil, there is no signature in the
759 buffer.  If it is a string, it will be used as a regexp.  If it
760 matches, the text in question is not a signature.")
761
762 (defvar gnus-auto-extend-newsgroup t
763   "*If non-nil, extend newsgroup forward and backward when requested.")
764
765 (defvar gnus-auto-select-first t
766   "*If nil, don't select the first unread article when entering a group.
767 If this variable is `best', select the highest-scored unread article
768 in the group.  If neither nil nor `best', select the first unread
769 article.
770
771 If you want to prevent automatic selection of the first unread article
772 in some newsgroups, set the variable to nil in
773 `gnus-select-group-hook'.")
774
775 (defvar gnus-auto-select-next t
776   "*If non-nil, offer to go to the next group from the end of the previous.
777 If the value is t and the next newsgroup is empty, Gnus will exit
778 summary mode and go back to group mode.  If the value is neither nil
779 nor t, Gnus will select the following unread newsgroup.  In
780 particular, if the value is the symbol `quietly', the next unread
781 newsgroup will be selected without any confirmation, and if it is
782 `almost-quietly', the next group will be selected without any
783 confirmation if you are located on the last article in the group.
784 Finally, if this variable is `slightly-quietly', the `Z n' command
785 will go to the next group without confirmation.")
786
787 (defvar gnus-auto-select-same nil
788   "*If non-nil, select the next article with the same subject.")
789
790 (defvar gnus-summary-check-current nil
791   "*If non-nil, consider the current article when moving.
792 The \"unread\" movement commands will stay on the same line if the
793 current article is unread.")
794
795 (defvar gnus-auto-center-summary t
796   "*If non-nil, always center the current summary buffer.
797 In particular, if `vertical' do only vertical recentering.  If non-nil
798 and non-`vertical', do both horizontal and vertical recentering.")
799
800 (defvar gnus-break-pages t
801   "*If non-nil, do page breaking on articles.
802 The page delimiter is specified by the `gnus-page-delimiter'
803 variable.")
804
805 (defvar gnus-page-delimiter "^\^L"
806   "*Regexp describing what to use as article page delimiters.
807 The default value is \"^\^L\", which is a form linefeed at the
808 beginning of a line.")
809
810 (defvar gnus-use-full-window t
811   "*If non-nil, use the entire Emacs screen.")
812
813 (defvar gnus-window-configuration nil
814   "Obsolete variable.  See `gnus-buffer-configuration'.")
815
816 (defvar gnus-window-min-width 2
817   "*Minimum width of Gnus buffers.")
818
819 (defvar gnus-window-min-height 1
820   "*Minimum height of Gnus buffers.")
821
822 (defvar gnus-buffer-configuration
823   '((group
824      (vertical 1.0
825                (group 1.0 point)
826                (if gnus-carpal '(group-carpal 4))))
827     (summary
828      (vertical 1.0
829                (summary 1.0 point)
830                (if gnus-carpal '(summary-carpal 4))))
831     (article
832      (cond 
833       (gnus-use-picons
834        '(frame 1.0
835                (vertical 1.0
836                          (summary 0.25 point)
837                          (if gnus-carpal '(summary-carpal 4))
838                          (article 1.0))
839                (vertical ((height . 5) (width . 15)
840                           (user-position . t)
841                           (left . -1) (top . 1))
842                          (picons 1.0))))
843       (gnus-use-trees
844        '(vertical 1.0
845                   (summary 0.25 point)
846                   (tree 0.25)
847                   (article 1.0)))
848       (t
849        '(vertical 1.0
850                  (summary 0.25 point)
851                  (if gnus-carpal '(summary-carpal 4))
852                  (if gnus-use-trees '(tree 0.25))
853                  (article 1.0)))))
854     (server
855      (vertical 1.0
856                (server 1.0 point)
857                (if gnus-carpal '(server-carpal 2))))
858     (browse
859      (vertical 1.0
860                (browse 1.0 point)
861                (if gnus-carpal '(browse-carpal 2))))
862     (message
863      (vertical 1.0
864                (message 1.0 point)))
865     (pick
866      (vertical 1.0
867                (article 1.0 point)))
868     (info
869      (vertical 1.0
870                (info 1.0 point)))
871     (summary-faq
872      (vertical 1.0
873                (summary 0.25)
874                (faq 1.0 point)))
875     (edit-group
876      (vertical 1.0
877                (group 0.5)
878                (edit-group 1.0 point)))
879     (edit-server
880      (vertical 1.0
881                (server 0.5)
882                (edit-server 1.0 point)))
883     (edit-score
884      (vertical 1.0
885                (summary 0.25)
886                (edit-score 1.0 point)))
887     (post
888      (vertical 1.0
889                (post 1.0 point)))
890     (reply
891      (vertical 1.0
892                (article-copy 0.5)
893                (message 1.0 point)))
894     (forward
895      (vertical 1.0
896                (message 1.0 point)))
897     (reply-yank
898      (vertical 1.0
899                (message 1.0 point)))
900     (mail-bounce
901      (vertical 1.0
902                (article 0.5)
903                (message 1.0 point)))
904     (draft
905      (vertical 1.0
906                (draft 1.0 point)))
907     (pipe
908      (vertical 1.0
909                (summary 0.25 point)
910                (if gnus-carpal '(summary-carpal 4))
911                ("*Shell Command Output*" 1.0)))
912     (compose-bounce
913      (vertical 1.0
914                (article 0.5)
915                (message 1.0 point))))
916   "Window configuration for all possible Gnus buffers.
917 This variable is a list of lists.  Each of these lists has a NAME and
918 a RULE.  The NAMEs are commonsense names like `group', which names a
919 rule used when displaying the group buffer; `summary', which names a
920 rule for what happens when you enter a group and do not display an
921 article buffer; and so on.  See the value of this variable for a
922 complete list of NAMEs.
923
924 Each RULE is a list of vectors.  The first element in this vector is
925 the name of the buffer to be displayed; the second element is the
926 percentage of the screen this buffer is to occupy (a number in the
927 0.0-0.99 range); the optional third element is `point', which should
928 be present to denote which buffer point is to go to after making this
929 buffer configuration.")
930
931 (defvar gnus-window-to-buffer
932   '((group . gnus-group-buffer)
933     (summary . gnus-summary-buffer)
934     (article . gnus-article-buffer)
935     (server . gnus-server-buffer)
936     (browse . "*Gnus Browse Server*")
937     (edit-group . gnus-group-edit-buffer)
938     (edit-server . gnus-server-edit-buffer)
939     (group-carpal . gnus-carpal-group-buffer)
940     (summary-carpal . gnus-carpal-summary-buffer)
941     (server-carpal . gnus-carpal-server-buffer)
942     (browse-carpal . gnus-carpal-browse-buffer)
943     (edit-score . gnus-score-edit-buffer)
944     (message . gnus-message-buffer)
945     (faq . gnus-faq-buffer)
946     (picons . "*Picons*")
947     (tree . gnus-tree-buffer)
948     (info . gnus-info-buffer)
949     (article-copy . gnus-article-copy)
950     (draft . gnus-draft-buffer))
951   "Mapping from short symbols to buffer names or buffer variables.")
952
953 (defvar gnus-carpal nil
954   "*If non-nil, display clickable icons.")
955
956 (defvar gnus-subscribe-newsgroup-method 'gnus-subscribe-zombies
957   "*Function called with a group name when new group is detected.
958 A few pre-made functions are supplied: `gnus-subscribe-randomly'
959 inserts new groups at the beginning of the list of groups;
960 `gnus-subscribe-alphabetically' inserts new groups in strict
961 alphabetic order; `gnus-subscribe-hierarchically' inserts new groups
962 in hierarchical newsgroup order; `gnus-subscribe-interactively' asks
963 for your decision; `gnus-subscribe-killed' kills all new groups.")
964
965 ;; Suggested by a bug report by Hallvard B Furuseth.
966 ;; <h.b.furuseth@usit.uio.no>.
967 (defvar gnus-subscribe-options-newsgroup-method
968   (function gnus-subscribe-alphabetically)
969   "*This function is called to subscribe newsgroups mentioned on \"options -n\" lines.
970 If, for instance, you want to subscribe to all newsgroups in the
971 \"no\" and \"alt\" hierarchies, you'd put the following in your
972 .newsrc file:
973
974 options -n no.all alt.all
975
976 Gnus will the subscribe all new newsgroups in these hierarchies with
977 the subscription method in this variable.")
978
979 (defvar gnus-subscribe-hierarchical-interactive nil
980   "*If non-nil, Gnus will offer to subscribe hierarchically.
981 When a new hierarchy appears, Gnus will ask the user:
982
983 'alt.binaries': Do you want to subscribe to this hierarchy? ([d]ys):
984
985 If the user pressed `d', Gnus will descend the hierarchy, `y' will
986 subscribe to all newsgroups in the hierarchy and `s' will skip this
987 hierarchy in its entirety.")
988
989 (defvar gnus-group-sort-function 'gnus-group-sort-by-alphabet
990   "*Function used for sorting the group buffer.
991 This function will be called with group info entries as the arguments
992 for the groups to be sorted.  Pre-made functions include
993 `gnus-group-sort-by-alphabet', `gnus-group-sort-by-unread',
994 `gnus-group-sort-by-level', `gnus-group-sort-by-score', and
995 `gnus-group-sort-by-rank'.
996
997 This variable can also be a list of sorting functions.  In that case,
998 the most significant sort function should be the last function in the
999 list.")
1000
1001 ;; Mark variables suggested by Thomas Michanek
1002 ;; <Thomas.Michanek@telelogic.se>.
1003 (defvar gnus-unread-mark ? 
1004   "*Mark used for unread articles.")
1005 (defvar gnus-ticked-mark ?!
1006   "*Mark used for ticked articles.")
1007 (defvar gnus-dormant-mark ??
1008   "*Mark used for dormant articles.")
1009 (defvar gnus-del-mark ?r
1010   "*Mark used for del'd articles.")
1011 (defvar gnus-read-mark ?R
1012   "*Mark used for read articles.")
1013 (defvar gnus-expirable-mark ?E
1014   "*Mark used for expirable articles.")
1015 (defvar gnus-killed-mark ?K
1016   "*Mark used for killed articles.")
1017 (defvar gnus-souped-mark ?F
1018   "*Mark used for killed articles.")
1019 (defvar gnus-kill-file-mark ?X
1020   "*Mark used for articles killed by kill files.")
1021 (defvar gnus-low-score-mark ?Y
1022   "*Mark used for articles with a low score.")
1023 (defvar gnus-catchup-mark ?C
1024   "*Mark used for articles that are caught up.")
1025 (defvar gnus-replied-mark ?A
1026   "*Mark used for articles that have been replied to.")
1027 (defvar gnus-cached-mark ?*
1028   "*Mark used for articles that are in the cache.")
1029 (defvar gnus-saved-mark ?S
1030   "*Mark used for articles that have been saved to.")
1031 (defvar gnus-process-mark ?#
1032   "*Process mark.")
1033 (defvar gnus-ancient-mark ?O
1034   "*Mark used for ancient articles.")
1035 (defvar gnus-sparse-mark ?Q
1036   "*Mark used for sparsely reffed articles.")
1037 (defvar gnus-canceled-mark ?G
1038   "*Mark used for canceled articles.")
1039 (defvar gnus-score-over-mark ?+
1040   "*Score mark used for articles with high scores.")
1041 (defvar gnus-score-below-mark ?-
1042   "*Score mark used for articles with low scores.")
1043 (defvar gnus-empty-thread-mark ? 
1044   "*There is no thread under the article.")
1045 (defvar gnus-not-empty-thread-mark ?=
1046   "*There is a thread under the article.")
1047
1048 (defvar gnus-view-pseudo-asynchronously nil
1049   "*If non-nil, Gnus will view pseudo-articles asynchronously.")
1050
1051 (defvar gnus-view-pseudos nil
1052   "*If `automatic', pseudo-articles will be viewed automatically.
1053 If `not-confirm', pseudos will be viewed automatically, and the user
1054 will not be asked to confirm the command.")
1055
1056 (defvar gnus-view-pseudos-separately t
1057   "*If non-nil, one pseudo-article will be created for each file to be viewed.
1058 If nil, all files that use the same viewing command will be given as a
1059 list of parameters to that command.")
1060
1061 (defvar gnus-insert-pseudo-articles t
1062   "*If non-nil, insert pseudo-articles when decoding articles.")
1063
1064 (defvar gnus-group-line-format "%M%S%p%P%5y: %(%g%)%l\n"
1065   "*Format of group lines.
1066 It works along the same lines as a normal formatting string,
1067 with some simple extensions.
1068
1069 %M    Only marked articles (character, \"*\" or \" \")
1070 %S    Whether the group is subscribed (character, \"U\", \"K\", \"Z\" or \" \")
1071 %L    Level of subscribedness (integer)
1072 %N    Number of unread articles (integer)
1073 %I    Number of dormant articles (integer)
1074 %i    Number of ticked and dormant (integer)
1075 %T    Number of ticked articles (integer)
1076 %R    Number of read articles (integer)
1077 %t    Total number of articles (integer)
1078 %y    Number of unread, unticked articles (integer)
1079 %G    Group name (string)
1080 %g    Qualified group name (string)
1081 %D    Group description (string)
1082 %s    Select method (string)
1083 %o    Moderated group (char, \"m\")
1084 %p    Process mark (char)
1085 %O    Moderated group (string, \"(m)\" or \"\")
1086 %P    Topic indentation (string)
1087 %l    Whether there are GroupLens predictions for this group (string)
1088 %n    Select from where (string)
1089 %z    A string that look like `<%s:%n>' if a foreign select method is used
1090 %u    User defined specifier.  The next character in the format string should
1091       be a letter.  Gnus will call the function gnus-user-format-function-X,
1092       where X is the letter following %u.  The function will be passed the
1093       current header as argument.  The function should return a string, which
1094       will be inserted into the buffer just like information from any other
1095       group specifier.
1096
1097 Text between %( and %) will be highlighted with `gnus-mouse-face' when
1098 the mouse point move inside the area.  There can only be one such area.
1099
1100 Note that this format specification is not always respected.  For
1101 reasons of efficiency, when listing killed groups, this specification
1102 is ignored altogether.  If the spec is changed considerably, your
1103 output may end up looking strange when listing both alive and killed
1104 groups.
1105
1106 If you use %o or %O, reading the active file will be slower and quite
1107 a bit of extra memory will be used. %D will also worsen performance.
1108 Also note that if you change the format specification to include any
1109 of these specs, you must probably re-start Gnus to see them go into
1110 effect.")
1111
1112 (defvar gnus-summary-line-format "%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n"
1113   "*The format specification of the lines in the summary buffer.
1114
1115 It works along the same lines as a normal formatting string,
1116 with some simple extensions.
1117
1118 %N   Article number, left padded with spaces (string)
1119 %S   Subject (string)
1120 %s   Subject if it is at the root of a thread, and \"\" otherwise (string)
1121 %n   Name of the poster (string)
1122 %a   Extracted name of the poster (string)
1123 %A   Extracted address of the poster (string)
1124 %F   Contents of the From: header (string)
1125 %x   Contents of the Xref: header (string)
1126 %D   Date of the article (string)
1127 %d   Date of the article (string) in DD-MMM format
1128 %M   Message-id of the article (string)
1129 %r   References of the article (string)
1130 %c   Number of characters in the article (integer)
1131 %L   Number of lines in the article (integer)
1132 %I   Indentation based on thread level (a string of spaces)
1133 %T   A string with two possible values: 80 spaces if the article
1134      is on thread level two or larger and 0 spaces on level one
1135 %R   \"A\" if this article has been replied to, \" \" otherwise (character)
1136 %U   Status of this article (character, \"R\", \"K\", \"-\" or \" \")
1137 %[   Opening bracket (character, \"[\" or \"<\")
1138 %]   Closing bracket (character, \"]\" or \">\")
1139 %>   Spaces of length thread-level (string)
1140 %<   Spaces of length (- 20 thread-level) (string)
1141 %i   Article score (number)
1142 %z   Article zcore (character)
1143 %t   Number of articles under the current thread (number).
1144 %e   Whether the thread is empty or not (character).
1145 %l   GroupLens score (number)
1146 %u   User defined specifier.  The next character in the format string should
1147      be a letter.  Gnus will call the function gnus-user-format-function-X,
1148      where X is the letter following %u.  The function will be passed the
1149      current header as argument.  The function should return a string, which
1150      will be inserted into the summary just like information from any other
1151      summary specifier.
1152
1153 Text between %( and %) will be highlighted with `gnus-mouse-face'
1154 when the mouse point is placed inside the area.  There can only be one
1155 such area.
1156
1157 The %U (status), %R (replied) and %z (zcore) specs have to be handled
1158 with care.  For reasons of efficiency, Gnus will compute what column
1159 these characters will end up in, and \"hard-code\" that.  This means that
1160 it is illegal to have these specs after a variable-length spec.  Well,
1161 you might not be arrested, but your summary buffer will look strange,
1162 which is bad enough.
1163
1164 The smart choice is to have these specs as for to the left as
1165 possible.
1166
1167 This restriction may disappear in later versions of Gnus.")
1168
1169 (defvar gnus-summary-dummy-line-format
1170   "*  %(:                          :%) %S\n"
1171   "*The format specification for the dummy roots in the summary buffer.
1172 It works along the same lines as a normal formatting string,
1173 with some simple extensions.
1174
1175 %S  The subject")
1176
1177 (defvar gnus-summary-mode-line-format "Gnus: %%b [%A] %Z"
1178   "*The format specification for the summary mode line.
1179 It works along the same lines as a normal formatting string,
1180 with some simple extensions:
1181
1182 %G  Group name
1183 %p  Unprefixed group name
1184 %A  Current article number
1185 %V  Gnus version
1186 %U  Number of unread articles in the group
1187 %e  Number of unselected articles in the group
1188 %Z  A string with unread/unselected article counts
1189 %g  Shortish group name
1190 %S  Subject of the current article
1191 %u  User-defined spec
1192 %s  Current score file name
1193 %d  Number of dormant articles
1194 %r  Number of articles that have been marked as read in this session
1195 %E  Number of articles expunged by the score files")
1196
1197 (defvar gnus-article-mode-line-format "Gnus: %%b %S"
1198   "*The format specification for the article mode line.
1199 See `gnus-summary-mode-line-format' for a closer description.")
1200
1201 (defvar gnus-group-mode-line-format "Gnus: %%b {%M:%S}"
1202   "*The format specification for the group mode line.
1203 It works along the same lines as a normal formatting string,
1204 with some simple extensions:
1205
1206 %S   The native news server.
1207 %M   The native select method.")
1208
1209 (defvar gnus-valid-select-methods
1210   '(("nntp" post address prompt-address)
1211     ("nnspool" post address)
1212     ("nnvirtual" post-mail virtual prompt-address)
1213     ("nnmbox" mail respool address)
1214     ("nnml" mail respool address)
1215     ("nnmh" mail respool address)
1216     ("nndir" post-mail prompt-address address)
1217     ("nneething" none address prompt-address)
1218     ("nndoc" none address prompt-address)
1219     ("nnbabyl" mail address respool)
1220     ("nnkiboze" post address virtual)
1221     ("nnsoup" post-mail address)
1222     ("nndraft" post-mail)
1223     ("nnfolder" mail respool address))
1224   "An alist of valid select methods.
1225 The first element of each list lists should be a string with the name
1226 of the select method.  The other elements may be be the category of
1227 this method (ie. `post', `mail', `none' or whatever) or other
1228 properties that this method has (like being respoolable).
1229 If you implement a new select method, all you should have to change is
1230 this variable.  I think.")
1231
1232 (defvar gnus-updated-mode-lines '(group article summary tree)
1233   "*List of buffers that should update their mode lines.
1234 The list may contain the symbols `group', `article' and `summary'.  If
1235 the corresponding symbol is present, Gnus will keep that mode line
1236 updated with information that may be pertinent.
1237 If this variable is nil, screen refresh may be quicker.")
1238
1239 ;; Added by Keinonen Kari <kk85613@cs.tut.fi>.
1240 (defvar gnus-mode-non-string-length nil
1241   "*Max length of mode-line non-string contents.
1242 If this is nil, Gnus will take space as is needed, leaving the rest
1243 of the modeline intact.")
1244
1245 ;see gnus-cus.el
1246 ;(defvar gnus-mouse-face 'highlight
1247 ;  "*Face used for mouse highlighting in Gnus.
1248 ;No mouse highlights will be done if `gnus-visual' is nil.")
1249
1250 (defvar gnus-summary-mark-below nil
1251   "*Mark all articles with a score below this variable as read.
1252 This variable is local to each summary buffer and usually set by the
1253 score file.")
1254
1255 (defvar gnus-article-sort-functions '(gnus-article-sort-by-number)
1256   "*List of functions used for sorting articles in the summary buffer.
1257 This variable is only used when not using a threaded display.")
1258
1259 (defvar gnus-thread-sort-functions '(gnus-thread-sort-by-number)
1260   "*List of functions used for sorting threads in the summary buffer.
1261 By default, threads are sorted by article number.
1262
1263 Each function takes two threads and return non-nil if the first thread
1264 should be sorted before the other.  If you use more than one function,
1265 the primary sort function should be the last.  You should probably
1266 always include `gnus-thread-sort-by-number' in the list of sorting
1267 functions -- preferably first.
1268
1269 Ready-mady functions include `gnus-thread-sort-by-number',
1270 `gnus-thread-sort-by-author', `gnus-thread-sort-by-subject',
1271 `gnus-thread-sort-by-date', `gnus-thread-sort-by-score' and
1272 `gnus-thread-sort-by-total-score' (see `gnus-thread-score-function').")
1273
1274 (defvar gnus-thread-score-function '+
1275   "*Function used for calculating the total score of a thread.
1276
1277 The function is called with the scores of the article and each
1278 subthread and should then return the score of the thread.
1279
1280 Some functions you can use are `+', `max', or `min'.")
1281
1282 (defvar gnus-summary-expunge-below nil
1283   "All articles that have a score less than this variable will be expunged.")
1284
1285 (defvar gnus-thread-expunge-below nil
1286   "All threads that have a total score less than this variable will be expunged.
1287 See `gnus-thread-score-function' for en explanation of what a
1288 \"thread score\" is.")
1289
1290 (defvar gnus-auto-subscribed-groups
1291   "^nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl"
1292   "*All new groups that match this regexp will be subscribed automatically.
1293 Note that this variable only deals with new groups.  It has no effect
1294 whatsoever on old groups.")
1295
1296 (defvar gnus-options-subscribe nil
1297   "*All new groups matching this regexp will be subscribed unconditionally.
1298 Note that this variable deals only with new newsgroups.  This variable
1299 does not affect old newsgroups.")
1300
1301 (defvar gnus-options-not-subscribe nil
1302   "*All new groups matching this regexp will be ignored.
1303 Note that this variable deals only with new newsgroups.  This variable
1304 does not affect old (already subscribed) newsgroups.")
1305
1306 (defvar gnus-auto-expirable-newsgroups nil
1307   "*Groups in which to automatically mark read articles as expirable.
1308 If non-nil, this should be a regexp that should match all groups in
1309 which to perform auto-expiry.  This only makes sense for mail groups.")
1310
1311 (defvar gnus-total-expirable-newsgroups nil
1312   "*Groups in which to perform expiry of all read articles.
1313 Use with extreme caution.  All groups that match this regexp will be
1314 expiring - which means that all read articles will be deleted after
1315 (say) one week.  (This only goes for mail groups and the like, of
1316 course.)")
1317
1318 (defvar gnus-group-uncollapsed-levels 1
1319   "Number of group name elements to leave alone when making a short group name.")
1320
1321 (defvar gnus-hidden-properties '(invisible t intangible t)
1322   "Property list to use for hiding text.")
1323
1324 (defvar gnus-modtime-botch nil
1325   "*Non-nil means .newsrc should be deleted prior to save.  
1326 Its use is due to the bogus appearance that .newsrc was modified on
1327 disc.")
1328
1329 ;; Hooks.
1330
1331 (defvar gnus-group-mode-hook nil
1332   "*A hook for Gnus group mode.")
1333
1334 (defvar gnus-summary-mode-hook nil
1335   "*A hook for Gnus summary mode.
1336 This hook is run before any variables are set in the summary buffer.")
1337
1338 (defvar gnus-article-mode-hook nil
1339   "*A hook for Gnus article mode.")
1340
1341 (defvar gnus-summary-prepare-exit-hook nil
1342   "*A hook called when preparing to exit from the summary buffer.
1343 It calls `gnus-summary-expire-articles' by default.")
1344 (add-hook 'gnus-summary-prepare-exit-hook 'gnus-summary-expire-articles)
1345
1346 (defvar gnus-summary-exit-hook nil
1347   "*A hook called on exit from the summary buffer.")
1348
1349 (defvar gnus-group-catchup-group-hook nil
1350   "*A hook run when catching up a group from the group buffer.")
1351
1352 (defvar gnus-open-server-hook nil
1353   "*A hook called just before opening connection to the news server.")
1354
1355 (defvar gnus-load-hook nil
1356   "*A hook run while Gnus is loaded.")
1357
1358 (defvar gnus-startup-hook nil
1359   "*A hook called at startup.
1360 This hook is called after Gnus is connected to the NNTP server.")
1361
1362 (defvar gnus-get-new-news-hook nil
1363   "*A hook run just before Gnus checks for new news.")
1364
1365 (defvar gnus-after-getting-new-news-hook nil
1366   "*A hook run after Gnus checks for new news.")
1367
1368 (defvar gnus-group-prepare-function 'gnus-group-prepare-flat
1369   "*A function that is called to generate the group buffer.
1370 The function is called with three arguments: The first is a number;
1371 all group with a level less or equal to that number should be listed,
1372 if the second is non-nil, empty groups should also be displayed.  If
1373 the third is non-nil, it is a number.  No groups with a level lower
1374 than this number should be displayed.
1375
1376 The only current function implemented is `gnus-group-prepare-flat'.")
1377
1378 (defvar gnus-group-prepare-hook nil
1379   "*A hook called after the group buffer has been generated.
1380 If you want to modify the group buffer, you can use this hook.")
1381
1382 (defvar gnus-summary-prepare-hook nil
1383   "*A hook called after the summary buffer has been generated.
1384 If you want to modify the summary buffer, you can use this hook.")
1385
1386 (defvar gnus-summary-generate-hook nil
1387   "*A hook run just before generating the summary buffer.
1388 This hook is commonly used to customize threading variables and the
1389 like.")
1390
1391 (defvar gnus-article-prepare-hook nil
1392   "*A hook called after an article has been prepared in the article buffer.
1393 If you want to run a special decoding program like nkf, use this hook.")
1394
1395 ;(defvar gnus-article-display-hook nil
1396 ;  "*A hook called after the article is displayed in the article buffer.
1397 ;The hook is designed to change the contents of the article
1398 ;buffer.  Typical functions that this hook may contain are
1399 ;`gnus-article-hide-headers' (hide selected headers),
1400 ;`gnus-article-maybe-highlight' (perform fancy article highlighting),
1401 ;`gnus-article-hide-signature' (hide signature) and
1402 ;`gnus-article-treat-overstrike' (turn \"^H_\" into bold characters).")
1403 ;(add-hook 'gnus-article-display-hook 'gnus-article-hide-headers-if-wanted)
1404 ;(add-hook 'gnus-article-display-hook 'gnus-article-treat-overstrike)
1405 ;(add-hook 'gnus-article-display-hook 'gnus-article-maybe-highlight)
1406
1407 (defvar gnus-article-x-face-command
1408   "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | xv -quit -"
1409   "String or function to be executed to display an X-Face header.
1410 If it is a string, the command will be executed in a sub-shell
1411 asynchronously.  The compressed face will be piped to this command.")
1412
1413 (defvar gnus-article-x-face-too-ugly nil
1414   "Regexp matching posters whose face shouldn't be shown automatically.")
1415
1416 (defvar gnus-select-group-hook nil
1417   "*A hook called when a newsgroup is selected.
1418
1419 If you'd like to simplify subjects like the
1420 `gnus-summary-next-same-subject' command does, you can use the
1421 following hook:
1422
1423  (setq gnus-select-group-hook
1424       (list
1425         (lambda ()
1426           (mapcar (lambda (header)
1427                      (mail-header-set-subject
1428                       header
1429                       (gnus-simplify-subject
1430                        (mail-header-subject header) 're-only)))
1431                   gnus-newsgroup-headers))))")
1432
1433 (defvar gnus-select-article-hook nil
1434   "*A hook called when an article is selected.")
1435
1436 (defvar gnus-apply-kill-hook '(gnus-apply-kill-file)
1437   "*A hook called to apply kill files to a group.
1438 This hook is intended to apply a kill file to the selected newsgroup.
1439 The function `gnus-apply-kill-file' is called by default.
1440
1441 Since a general kill file is too heavy to use only for a few
1442 newsgroups, I recommend you to use a lighter hook function.  For
1443 example, if you'd like to apply a kill file to articles which contains
1444 a string `rmgroup' in subject in newsgroup `control', you can use the
1445 following hook:
1446
1447  (setq gnus-apply-kill-hook
1448       (list
1449         (lambda ()
1450           (cond ((string-match \"control\" gnus-newsgroup-name)
1451                  (gnus-kill \"Subject\" \"rmgroup\")
1452                  (gnus-expunge \"X\"))))))")
1453
1454 (defvar gnus-visual-mark-article-hook
1455   (list 'gnus-highlight-selected-summary)
1456   "*Hook run after selecting an article in the summary buffer.
1457 It is meant to be used for highlighting the article in some way.  It
1458 is not run if `gnus-visual' is nil.")
1459
1460 (defvar gnus-parse-headers-hook nil
1461   "*A hook called before parsing the headers.")
1462
1463 (defvar gnus-exit-group-hook nil
1464   "*A hook called when exiting (not quitting) summary mode.")
1465
1466 (defvar gnus-suspend-gnus-hook nil
1467   "*A hook called when suspending (not exiting) Gnus.")
1468
1469 (defvar gnus-exit-gnus-hook nil
1470   "*A hook called when exiting Gnus.")
1471
1472 (defvar gnus-after-exiting-gnus-hook nil
1473   "*A hook called after exiting Gnus.")
1474
1475 (defvar gnus-save-newsrc-hook nil
1476   "*A hook called before saving any of the newsrc files.")
1477
1478 (defvar gnus-save-quick-newsrc-hook nil
1479   "*A hook called just before saving the quick newsrc file.
1480 Can be used to turn version control on or off.")
1481
1482 (defvar gnus-save-standard-newsrc-hook nil
1483   "*A hook called just before saving the standard newsrc file.
1484 Can be used to turn version control on or off.")
1485
1486 (defvar gnus-summary-update-hook
1487   (list 'gnus-summary-highlight-line)
1488   "*A hook called when a summary line is changed.
1489 The hook will not be called if `gnus-visual' is nil.
1490
1491 The default function `gnus-summary-highlight-line' will
1492 highlight the line according to the `gnus-summary-highlight'
1493 variable.")
1494
1495 (defvar gnus-group-update-hook '(gnus-group-highlight-line)
1496   "*A hook called when a group line is changed.
1497 The hook will not be called if `gnus-visual' is nil.
1498
1499 The default function `gnus-group-highlight-line' will
1500 highlight the line according to the `gnus-group-highlight'
1501 variable.")
1502
1503 (defvar gnus-mark-article-hook '(gnus-summary-mark-read-and-unread-as-read)
1504   "*A hook called when an article is selected for the first time.
1505 The hook is intended to mark an article as read (or unread)
1506 automatically when it is selected.")
1507
1508 (defvar gnus-group-change-level-function nil
1509   "Function run when a group level is changed.
1510 It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
1511
1512 ;; Remove any hilit infestation.
1513 (add-hook 'gnus-startup-hook
1514           (lambda ()
1515             (remove-hook 'gnus-summary-prepare-hook
1516                          'hilit-rehighlight-buffer-quietly)
1517             (remove-hook 'gnus-summary-prepare-hook 'hilit-install-line-hooks)
1518             (setq gnus-mark-article-hook '(gnus-summary-mark-read-and-unread-as-read))
1519             (remove-hook 'gnus-article-prepare-hook
1520                          'hilit-rehighlight-buffer-quietly)))
1521
1522 \f
1523 ;; Internal variables
1524
1525 (defvar gnus-server-alist nil
1526   "List of available servers.")
1527
1528 (defvar gnus-group-indentation-function nil)
1529
1530 (defvar gnus-topic-indentation "") ;; Obsolete variable.
1531
1532 (defvar gnus-goto-missing-group-function nil)
1533
1534 (defvar gnus-override-subscribe-method nil)
1535
1536 (defvar gnus-group-goto-next-group-function nil
1537   "Function to override finding the next group after listing groups.")
1538
1539 (defconst gnus-article-mark-lists
1540   '((marked . tick) (replied . reply)
1541     (expirable . expire) (killed . killed)
1542     (bookmarks . bookmark) (dormant . dormant)
1543     (scored . score) (saved . save)
1544     (cached . cache)
1545     ))
1546
1547 ;; Avoid highlighting in kill files.
1548 (defvar gnus-summary-inhibit-highlight nil)
1549 (defvar gnus-newsgroup-selected-overlay nil)
1550
1551 (defvar gnus-inhibit-hiding nil)
1552 (defvar gnus-group-indentation "")
1553 (defvar gnus-inhibit-limiting nil)
1554 (defvar gnus-created-frames nil)
1555
1556 (defvar gnus-article-mode-map nil)
1557 (defvar gnus-dribble-buffer nil)
1558 (defvar gnus-headers-retrieved-by nil)
1559 (defvar gnus-article-reply nil)
1560 (defvar gnus-override-method nil)
1561 (defvar gnus-article-check-size nil)
1562
1563 (defvar gnus-current-score-file nil)
1564 (defvar gnus-newsgroup-adaptive-score-file nil)
1565 (defvar gnus-scores-exclude-files nil)
1566
1567 (defvar gnus-opened-servers nil)
1568
1569 (defvar gnus-current-move-group nil)
1570
1571 (defvar gnus-newsgroup-dependencies nil)
1572 (defvar gnus-newsgroup-async nil)
1573 (defconst gnus-group-edit-buffer "*Gnus edit newsgroup*")
1574
1575 (defvar gnus-newsgroup-adaptive nil)
1576
1577 (defvar gnus-summary-display-table nil)
1578 (defvar gnus-summary-display-article-function nil)
1579
1580 (defvar gnus-summary-highlight-line-function nil
1581   "Function called after highlighting a summary line.")
1582
1583 (defvar gnus-group-line-format-alist
1584   `((?M gnus-tmp-marked-mark ?c)
1585     (?S gnus-tmp-subscribed ?c)
1586     (?L gnus-tmp-level ?d)
1587     (?N (cond ((eq number t) "*" )
1588               ((numberp number) 
1589                (int-to-string
1590                 (+ number
1591                    (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked)))
1592                    (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))))))
1593               (t number)) ?s)
1594     (?R gnus-tmp-number-of-read ?s)
1595     (?t gnus-tmp-number-total ?d)
1596     (?y gnus-tmp-number-of-unread ?s)
1597     (?I (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) ?d)
1598     (?T (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))) ?d)
1599     (?i (+ (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked)))
1600            (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))) ?d)
1601     (?g gnus-tmp-group ?s)
1602     (?G gnus-tmp-qualified-group ?s)
1603     (?c (gnus-short-group-name gnus-tmp-group) ?s)
1604     (?D gnus-tmp-newsgroup-description ?s)
1605     (?o gnus-tmp-moderated ?c)
1606     (?O gnus-tmp-moderated-string ?s)
1607     (?p gnus-tmp-process-marked ?c)
1608     (?s gnus-tmp-news-server ?s)
1609     (?n gnus-tmp-news-method ?s)
1610     (?P gnus-group-indentation ?s)
1611     (?l gnus-tmp-grouplens ?s)
1612     (?z gnus-tmp-news-method-string ?s)
1613     (?u gnus-tmp-user-defined ?s)))
1614
1615 (defvar gnus-summary-line-format-alist
1616   `((?N ,(macroexpand '(mail-header-number gnus-tmp-header)) ?d)
1617     (?S ,(macroexpand '(mail-header-subject gnus-tmp-header)) ?s)
1618     (?s gnus-tmp-subject-or-nil ?s)
1619     (?n gnus-tmp-name ?s)
1620     (?A (car (cdr (funcall gnus-extract-address-components gnus-tmp-from)))
1621         ?s)
1622     (?a (or (car (funcall gnus-extract-address-components gnus-tmp-from))
1623             gnus-tmp-from) ?s)
1624     (?F gnus-tmp-from ?s)
1625     (?x ,(macroexpand '(mail-header-xref gnus-tmp-header)) ?s)
1626     (?D ,(macroexpand '(mail-header-date gnus-tmp-header)) ?s)
1627     (?d (gnus-dd-mmm (mail-header-date gnus-tmp-header)) ?s)
1628     (?M ,(macroexpand '(mail-header-id gnus-tmp-header)) ?s)
1629     (?r ,(macroexpand '(mail-header-references gnus-tmp-header)) ?s)
1630     (?c (or (mail-header-chars gnus-tmp-header) 0) ?d)
1631     (?L gnus-tmp-lines ?d)
1632     (?I gnus-tmp-indentation ?s)
1633     (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s)
1634     (?R gnus-tmp-replied ?c)
1635     (?\[ gnus-tmp-opening-bracket ?c)
1636     (?\] gnus-tmp-closing-bracket ?c)
1637     (?\> (make-string gnus-tmp-level ? ) ?s)
1638     (?\< (make-string (max 0 (- 20 gnus-tmp-level)) ? ) ?s)
1639     (?i gnus-tmp-score ?d)
1640     (?z gnus-tmp-score-char ?c)
1641     (?l (bbb-grouplens-score gnus-tmp-header) ?s)
1642     (?V (gnus-thread-total-score (and (boundp 'thread) (car thread))) ?d)
1643     (?U gnus-tmp-unread ?c)
1644     (?t (gnus-summary-number-of-articles-in-thread
1645          (and (boundp 'thread) (car thread)) gnus-tmp-level)
1646         ?d)
1647     (?e (gnus-summary-number-of-articles-in-thread
1648          (and (boundp 'thread) (car thread)) gnus-tmp-level t)
1649         ?c)
1650     (?u gnus-tmp-user-defined ?s))
1651   "An alist of format specifications that can appear in summary lines,
1652 and what variables they correspond with, along with the type of the
1653 variable (string, integer, character, etc).")
1654
1655 (defvar gnus-summary-dummy-line-format-alist
1656   `((?S gnus-tmp-subject ?s)
1657     (?N gnus-tmp-number ?d)
1658     (?u gnus-tmp-user-defined ?s)))
1659
1660 (defvar gnus-summary-mode-line-format-alist
1661   `((?G gnus-tmp-group-name ?s)
1662     (?g (gnus-short-group-name gnus-tmp-group-name) ?s)
1663     (?p (gnus-group-real-name gnus-tmp-group-name) ?s)
1664     (?A gnus-tmp-article-number ?d)
1665     (?Z gnus-tmp-unread-and-unselected ?s)
1666     (?V gnus-version ?s)
1667     (?U gnus-tmp-unread ?d)
1668     (?S gnus-tmp-subject ?s)
1669     (?e gnus-tmp-unselected ?d)
1670     (?u gnus-tmp-user-defined ?s)
1671     (?d (length gnus-newsgroup-dormant) ?d)
1672     (?t (length gnus-newsgroup-marked) ?d)
1673     (?r (length gnus-newsgroup-reads) ?d)
1674     (?E gnus-newsgroup-expunged-tally ?d)
1675     (?s (gnus-current-score-file-nondirectory) ?s)))
1676
1677 (defvar gnus-article-mode-line-format-alist
1678   gnus-summary-mode-line-format-alist)
1679
1680 (defvar gnus-group-mode-line-format-alist
1681   `((?S gnus-tmp-news-server ?s)
1682     (?M gnus-tmp-news-method ?s)
1683     (?u gnus-tmp-user-defined ?s)))
1684
1685 (defvar gnus-have-read-active-file nil)
1686
1687 (defconst gnus-maintainer
1688   "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)"
1689   "The mail address of the Gnus maintainers.")
1690
1691 (defconst gnus-version "September Gnus v0.62"
1692   "Version number for this version of Gnus.")
1693
1694 (defvar gnus-info-nodes
1695   '((gnus-group-mode            "(gnus)The Group Buffer")
1696     (gnus-summary-mode          "(gnus)The Summary Buffer")
1697     (gnus-article-mode          "(gnus)The Article Buffer"))
1698   "Assoc list of major modes and related Info nodes.")
1699
1700 (defvar gnus-group-buffer "*Group*")
1701 (defvar gnus-summary-buffer "*Summary*")
1702 (defvar gnus-article-buffer "*Article*")
1703 (defvar gnus-server-buffer "*Server*")
1704
1705 (defvar gnus-work-buffer " *gnus work*")
1706
1707 (defvar gnus-original-article-buffer " *Original Article*")
1708 (defvar gnus-original-article nil)
1709
1710 (defvar gnus-buffer-list nil
1711   "Gnus buffers that should be killed on exit.")
1712
1713 (defvar gnus-slave nil
1714   "Whether this Gnus is a slave or not.")
1715
1716 (defvar gnus-variable-list
1717   '(gnus-newsrc-options gnus-newsrc-options-n
1718     gnus-newsrc-last-checked-date
1719     gnus-newsrc-alist gnus-server-alist
1720     gnus-killed-list gnus-zombie-list
1721     gnus-topic-topology gnus-topic-alist
1722     gnus-format-specs)
1723   "Gnus variables saved in the quick startup file.")
1724
1725 (defvar gnus-newsrc-options nil
1726   "Options line in the .newsrc file.")
1727
1728 (defvar gnus-newsrc-options-n nil
1729   "List of regexps representing groups to be subscribed/ignored unconditionally.")
1730
1731 (defvar gnus-newsrc-last-checked-date nil
1732   "Date Gnus last asked server for new newsgroups.")
1733
1734 (defvar gnus-topic-topology nil
1735   "The complete topic hierarchy.")
1736
1737 (defvar gnus-topic-alist nil
1738   "The complete topic-group alist.")
1739
1740 (defvar gnus-newsrc-alist nil
1741   "Assoc list of read articles.
1742 gnus-newsrc-hashtb should be kept so that both hold the same information.")
1743
1744 (defvar gnus-newsrc-hashtb nil
1745   "Hashtable of gnus-newsrc-alist.")
1746
1747 (defvar gnus-killed-list nil
1748   "List of killed newsgroups.")
1749
1750 (defvar gnus-killed-hashtb nil
1751   "Hash table equivalent of gnus-killed-list.")
1752
1753 (defvar gnus-zombie-list nil
1754   "List of almost dead newsgroups.")
1755
1756 (defvar gnus-description-hashtb nil
1757   "Descriptions of newsgroups.")
1758
1759 (defvar gnus-list-of-killed-groups nil
1760   "List of newsgroups that have recently been killed by the user.")
1761
1762 (defvar gnus-active-hashtb nil
1763   "Hashtable of active articles.")
1764
1765 (defvar gnus-moderated-list nil
1766   "List of moderated newsgroups.")
1767
1768 (defvar gnus-group-marked nil)
1769
1770 (defvar gnus-current-startup-file nil
1771   "Startup file for the current host.")
1772
1773 (defvar gnus-last-search-regexp nil
1774   "Default regexp for article search command.")
1775
1776 (defvar gnus-last-shell-command nil
1777   "Default shell command on article.")
1778
1779 (defvar gnus-current-select-method nil
1780   "The current method for selecting a newsgroup.")
1781
1782 (defvar gnus-group-list-mode nil)
1783
1784 (defvar gnus-article-internal-prepare-hook nil)
1785
1786 (defvar gnus-newsgroup-name nil)
1787 (defvar gnus-newsgroup-begin nil)
1788 (defvar gnus-newsgroup-end nil)
1789 (defvar gnus-newsgroup-last-rmail nil)
1790 (defvar gnus-newsgroup-last-mail nil)
1791 (defvar gnus-newsgroup-last-folder nil)
1792 (defvar gnus-newsgroup-last-file nil)
1793 (defvar gnus-newsgroup-auto-expire nil)
1794 (defvar gnus-newsgroup-active nil)
1795
1796 (defvar gnus-newsgroup-data nil)
1797 (defvar gnus-newsgroup-data-reverse nil)
1798 (defvar gnus-newsgroup-limit nil)
1799 (defvar gnus-newsgroup-limits nil)
1800
1801 (defvar gnus-newsgroup-unreads nil
1802   "List of unread articles in the current newsgroup.")
1803
1804 (defvar gnus-newsgroup-unselected nil
1805   "List of unselected unread articles in the current newsgroup.")
1806
1807 (defvar gnus-newsgroup-reads nil
1808   "Alist of read articles and article marks in the current newsgroup.")
1809
1810 (defvar gnus-newsgroup-expunged-tally nil)
1811
1812 (defvar gnus-newsgroup-marked nil
1813   "List of ticked articles in the current newsgroup (a subset of unread art).")
1814
1815 (defvar gnus-newsgroup-killed nil
1816   "List of ranges of articles that have been through the scoring process.")
1817
1818 (defvar gnus-newsgroup-cached nil
1819   "List of articles that come from the article cache.")
1820
1821 (defvar gnus-newsgroup-saved nil
1822   "List of articles that have been saved.")
1823
1824 (defvar gnus-newsgroup-kill-headers nil)
1825
1826 (defvar gnus-newsgroup-replied nil
1827   "List of articles that have been replied to in the current newsgroup.")
1828
1829 (defvar gnus-newsgroup-expirable nil
1830   "List of articles in the current newsgroup that can be expired.")
1831
1832 (defvar gnus-newsgroup-processable nil
1833   "List of articles in the current newsgroup that can be processed.")
1834
1835 (defvar gnus-newsgroup-bookmarks nil
1836   "List of articles in the current newsgroup that have bookmarks.")
1837
1838 (defvar gnus-newsgroup-dormant nil
1839   "List of dormant articles in the current newsgroup.")
1840
1841 (defvar gnus-newsgroup-scored nil
1842   "List of scored articles in the current newsgroup.")
1843
1844 (defvar gnus-newsgroup-headers nil
1845   "List of article headers in the current newsgroup.")
1846
1847 (defvar gnus-newsgroup-threads nil)
1848
1849 (defvar gnus-newsgroup-prepared nil
1850   "Whether the current group has been prepared properly.")
1851
1852 (defvar gnus-newsgroup-ancient nil
1853   "List of `gnus-fetch-old-headers' articles in the current newsgroup.")
1854
1855 (defvar gnus-newsgroup-sparse nil)
1856
1857 (defvar gnus-current-article nil)
1858 (defvar gnus-article-current nil)
1859 (defvar gnus-current-headers nil)
1860 (defvar gnus-have-all-headers nil)
1861 (defvar gnus-last-article nil)
1862 (defvar gnus-newsgroup-history nil)
1863 (defvar gnus-current-kill-article nil)
1864
1865 ;; Save window configuration.
1866 (defvar gnus-prev-winconf nil)
1867
1868 (defvar gnus-summary-mark-positions nil)
1869 (defvar gnus-group-mark-positions nil)
1870
1871 (defvar gnus-reffed-article-number nil)
1872
1873 ;;; Let the byte-compiler know that we know about this variable.
1874 (defvar rmail-default-rmail-file)
1875
1876 (defvar gnus-cache-removable-articles nil)
1877
1878 (defvar gnus-dead-summary nil)
1879
1880 (defconst gnus-summary-local-variables
1881   '(gnus-newsgroup-name
1882     gnus-newsgroup-begin gnus-newsgroup-end
1883     gnus-newsgroup-last-rmail gnus-newsgroup-last-mail
1884     gnus-newsgroup-last-folder gnus-newsgroup-last-file
1885     gnus-newsgroup-auto-expire gnus-newsgroup-unreads
1886     gnus-newsgroup-unselected gnus-newsgroup-marked
1887     gnus-newsgroup-reads gnus-newsgroup-saved
1888     gnus-newsgroup-replied gnus-newsgroup-expirable
1889     gnus-newsgroup-processable gnus-newsgroup-killed
1890     gnus-newsgroup-bookmarks gnus-newsgroup-dormant
1891     gnus-newsgroup-headers gnus-newsgroup-threads
1892     gnus-newsgroup-prepared gnus-summary-highlight-line-function
1893     gnus-current-article gnus-current-headers gnus-have-all-headers
1894     gnus-last-article gnus-article-internal-prepare-hook
1895     gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
1896     gnus-newsgroup-scored gnus-newsgroup-kill-headers
1897     gnus-newsgroup-async 
1898     gnus-score-alist gnus-current-score-file gnus-summary-expunge-below
1899     gnus-summary-mark-below gnus-newsgroup-active gnus-scores-exclude-files
1900     gnus-newsgroup-history gnus-newsgroup-ancient
1901     gnus-newsgroup-sparse
1902     (gnus-newsgroup-adaptive . gnus-use-adaptive-scoring)
1903     gnus-newsgroup-adaptive-score-file
1904     (gnus-newsgroup-expunged-tally . 0)
1905     gnus-cache-removable-articles gnus-newsgroup-cached
1906     gnus-newsgroup-data gnus-newsgroup-data-reverse
1907     gnus-newsgroup-limit gnus-newsgroup-limits)
1908   "Variables that are buffer-local to the summary buffers.")
1909
1910 (defconst gnus-bug-message
1911   "Sending a bug report to the Gnus Towers.
1912 ========================================
1913
1914 The buffer below is a mail buffer.  When you press `C-c C-c', it will
1915 be sent to the Gnus Bug Exterminators.
1916
1917 At the bottom of the buffer you'll see lots of variable settings.
1918 Please do not delete those.  They will tell the Bug People what your
1919 environment is, so that it will be easier to locate the bugs.
1920
1921 If you have found a bug that makes Emacs go \"beep\", set
1922 debug-on-error to t (`M-x set-variable RET debug-on-error RET t RET')
1923 and include the backtrace in your bug report.
1924
1925 Please describe the bug in annoying, painstaking detail.
1926
1927 Thank you for your help in stamping out bugs.
1928 ")
1929
1930 ;;; End of variables.
1931
1932 ;; Define some autoload functions Gnus might use.
1933 (eval-and-compile
1934
1935   ;; This little mapcar goes through the list below and marks the
1936   ;; symbols in question as autoloaded functions.
1937   (mapcar
1938    (lambda (package)
1939      (let ((interactive (nth 1 (memq ':interactive package))))
1940        (mapcar
1941         (lambda (function)
1942           (let (keymap)
1943             (when (consp function)
1944               (setq keymap (car (memq 'keymap function)))
1945               (setq function (car function)))
1946             (autoload function (car package) nil interactive keymap)))
1947         (if (eq (nth 1 package) ':interactive)
1948             (cdddr package)
1949           (cdr package)))))
1950    '(("metamail" metamail-buffer)
1951      ("info" Info-goto-node)
1952      ("hexl" hexl-hex-string-to-integer)
1953      ("pp" pp pp-to-string pp-eval-expression)
1954      ("mail-extr" mail-extract-address-components)
1955      ("nnmail" nnmail-split-fancy nnmail-article-group)
1956      ("nnvirtual" nnvirtual-catchup-group)
1957      ("timezone" timezone-make-date-arpa-standard timezone-fix-time
1958       timezone-make-sortable-date timezone-make-time-string)
1959      ("sendmail" mail-position-on-field mail-setup)
1960      ("rmailout" rmail-output)
1961      ("rnewspost" news-mail-other-window news-reply-yank-original
1962       news-caesar-buffer-body)
1963      ("rmail" rmail-insert-rmail-file-header rmail-count-new-messages
1964       rmail-show-message)
1965      ("gnus-soup" :interactive t
1966       gnus-group-brew-soup gnus-brew-soup gnus-soup-add-article
1967       gnus-soup-send-replies gnus-soup-save-areas gnus-soup-pack-packet)
1968      ("nnsoup" nnsoup-pack-replies)
1969      ("gnus-mh" gnus-mh-mail-setup gnus-summary-save-article-folder
1970       gnus-Folder-save-name gnus-folder-save-name)
1971      ("gnus-mh" :interactive t gnus-summary-save-in-folder)
1972      ("gnus-vis" gnus-group-make-menu-bar gnus-summary-make-menu-bar
1973       gnus-server-make-menu-bar gnus-article-make-menu-bar
1974       gnus-browse-make-menu-bar gnus-highlight-selected-summary
1975       gnus-summary-highlight-line gnus-carpal-setup-buffer
1976       gnus-group-highlight-line
1977       gnus-article-add-button gnus-insert-next-page-button
1978       gnus-insert-prev-page-button gnus-visual-turn-off-edit-menu)
1979      ("gnus-vis" :interactive t
1980       gnus-article-push-button gnus-article-press-button
1981       gnus-article-highlight gnus-article-highlight-some
1982       gnus-article-highlight-headers gnus-article-highlight-signature
1983       gnus-article-add-buttons gnus-article-add-buttons-to-head
1984       gnus-article-next-button gnus-article-prev-button)
1985      ("gnus-demon" gnus-demon-add-nocem gnus-demon-add-scanmail
1986       gnus-demon-add-disconnection gnus-demon-add-handler
1987       gnus-demon-remove-handler)
1988      ("gnus-demon" :interactive t
1989       gnus-demon-init gnus-demon-cancel)
1990      ("gnus-salt" gnus-highlight-selected-tree gnus-possibly-generate-tree
1991       gnus-tree-open gnus-tree-close)
1992      ("gnus-nocem" gnus-nocem-scan-groups gnus-nocem-close
1993       gnus-nocem-unwanted-article-p)
1994      ("gnus-srvr" gnus-enter-server-buffer gnus-server-set-info)
1995      ("gnus-srvr" gnus-browse-foreign-server)
1996      ("gnus-cite" :interactive t
1997       gnus-article-highlight-citation gnus-article-hide-citation-maybe
1998       gnus-article-hide-citation gnus-article-fill-cited-article)
1999      ("gnus-kill" gnus-kill gnus-apply-kill-file-internal
2000       gnus-kill-file-edit-file gnus-kill-file-raise-followups-to-author
2001       gnus-execute gnus-expunge)
2002      ("gnus-cache" gnus-cache-possibly-enter-article gnus-cache-save-buffers
2003       gnus-cache-possibly-remove-articles gnus-cache-request-article
2004       gnus-cache-retrieve-headers gnus-cache-possibly-alter-active
2005       gnus-cache-enter-remove-article gnus-cached-article-p
2006       gnus-cache-open gnus-cache-close gnus-cache-update-article)
2007      ("gnus-cache" :interactive t gnus-jog-cache gnus-cache-enter-article
2008       gnus-cache-remove-article)
2009      ("gnus-score" :interactive t
2010       gnus-summary-increase-score gnus-summary-lower-score
2011       gnus-score-flush-cache gnus-score-close
2012       gnus-score-raise-same-subject-and-select
2013       gnus-score-raise-same-subject gnus-score-default
2014       gnus-score-raise-thread gnus-score-lower-same-subject-and-select
2015       gnus-score-lower-same-subject gnus-score-lower-thread
2016       gnus-possibly-score-headers)
2017      ("gnus-score"
2018       (gnus-summary-score-map keymap) gnus-score-save gnus-score-headers
2019       gnus-current-score-file-nondirectory gnus-score-adaptive
2020       gnus-score-find-trace gnus-score-file-name)
2021      ("gnus-edit" :interactive t gnus-score-customize)
2022      ("gnus-topic" :interactive t gnus-topic-mode)
2023      ("gnus-topic" gnus-topic-remove-group)
2024      ("gnus-salt" :interactive t gnus-pick-mode gnus-binary-mode)
2025      ("gnus-uu" (gnus-uu-extract-map keymap) (gnus-uu-mark-map keymap))
2026      ("gnus-uu" :interactive t
2027       gnus-uu-digest-mail-forward gnus-uu-digest-post-forward
2028       gnus-uu-mark-series gnus-uu-mark-region gnus-uu-mark-buffer
2029       gnus-uu-mark-by-regexp gnus-uu-mark-all
2030       gnus-uu-mark-sparse gnus-uu-mark-thread gnus-uu-decode-uu
2031       gnus-uu-decode-uu-and-save gnus-uu-decode-unshar
2032       gnus-uu-decode-unshar-and-save gnus-uu-decode-save
2033       gnus-uu-decode-binhex gnus-uu-decode-uu-view
2034       gnus-uu-decode-uu-and-save-view gnus-uu-decode-unshar-view
2035       gnus-uu-decode-unshar-and-save-view gnus-uu-decode-save-view
2036       gnus-uu-decode-binhex-view)
2037      ("gnus-msg" (gnus-summary-send-map keymap)
2038       gnus-mail-yank-original gnus-mail-send-and-exit
2039       gnus-sendmail-setup-mail gnus-article-mail
2040       gnus-inews-message-id gnus-new-mail gnus-mail-reply)
2041      ("gnus-msg" :interactive t
2042       gnus-group-post-news gnus-group-mail gnus-summary-post-news
2043       gnus-summary-followup gnus-summary-followup-with-original
2044       gnus-summary-followup-and-reply
2045       gnus-summary-followup-and-reply-with-original
2046       gnus-summary-cancel-article gnus-summary-supersede-article
2047       gnus-post-news gnus-inews-news gnus-cancel-news
2048       gnus-summary-reply gnus-summary-reply-with-original
2049       gnus-summary-mail-forward gnus-summary-mail-other-window
2050       gnus-bug)
2051      ("gnus-picon" :interactive t gnus-article-display-picons
2052       gnus-group-display-picons gnus-picons-article-display-x-face)
2053      ("gnus-gl" bbb-login bbb-logout bbb-grouplens-group-p 
2054       gnus-grouplens-mode)
2055      ("gnus-vm" gnus-vm-mail-setup)
2056      ("gnus-vm" :interactive t gnus-summary-save-in-vm
2057       gnus-summary-save-article-vm gnus-yank-article))))
2058
2059 \f
2060
2061 ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
2062 ;; If you want the cursor to go somewhere else, set these two
2063 ;; functions in some startup hook to whatever you want.
2064 (defalias 'gnus-summary-position-point 'gnus-goto-colon)
2065 (defalias 'gnus-group-position-point 'gnus-goto-colon)
2066
2067 ;;; Various macros and substs.
2068
2069 (defun gnus-header-from (header)
2070   (mail-header-from header))
2071
2072 (defmacro gnus-eval-in-buffer-window (buffer &rest forms)
2073   "Pop to BUFFER, evaluate FORMS, and then return to the original window."
2074   (let ((tempvar (make-symbol "GnusStartBufferWindow")))
2075     `(let ((,tempvar (selected-window)))
2076        (unwind-protect
2077            (progn
2078              (pop-to-buffer ,buffer)
2079              ,@forms)
2080          (select-window ,tempvar)))))
2081
2082 (defmacro gnus-gethash (string hashtable)
2083   "Get hash value of STRING in HASHTABLE."
2084   `(symbol-value (intern-soft ,string ,hashtable)))
2085
2086 (defmacro gnus-sethash (string value hashtable)
2087   "Set hash value.  Arguments are STRING, VALUE, and HASHTABLE."
2088   `(set (intern ,string ,hashtable) ,value))
2089
2090 (defmacro gnus-intern-safe (string hashtable)
2091   "Set hash value.  Arguments are STRING, VALUE, and HASHTABLE."
2092   `(let ((symbol (intern ,string ,hashtable)))
2093      (or (boundp symbol)
2094          (set symbol nil))
2095      symbol))
2096
2097 (defmacro gnus-group-unread (group)
2098   "Get the currently computed number of unread articles in GROUP."
2099   `(car (gnus-gethash ,group gnus-newsrc-hashtb)))
2100
2101 (defmacro gnus-group-entry (group)
2102   "Get the newsrc entry for GROUP."
2103   `(gnus-gethash ,group gnus-newsrc-hashtb))
2104
2105 (defmacro gnus-active (group)
2106   "Get active info on GROUP."
2107   `(gnus-gethash ,group gnus-active-hashtb))
2108
2109 (defmacro gnus-set-active (group active)
2110   "Set GROUP's active info."
2111   `(gnus-sethash ,group ,active gnus-active-hashtb))
2112
2113 ;; modified by MORIOKA Tomohiko <morioka@jaist.ac.jp>
2114 ;;   function `substring' might cut on a middle of multi-octet
2115 ;;   character.
2116 (defun gnus-truncate-string (str width)
2117   (substring str 0 width))
2118
2119 ;; Added by Geoffrey T. Dairiki <dairiki@u.washington.edu>.  A safe way
2120 ;; to limit the length of a string.  This function is necessary since
2121 ;; `(substr "abc" 0 30)' pukes with "Args out of range".
2122 (defsubst gnus-limit-string (str width)
2123   (if (> (length str) width)
2124       (substring str 0 width)
2125     str))
2126
2127 (defsubst gnus-simplify-subject-re (subject)
2128   "Remove \"Re:\" from subject lines."
2129   (if (string-match "^[Rr][Ee]: *" subject)
2130       (substring subject (match-end 0))
2131     subject))
2132
2133 (defsubst gnus-functionp (form)
2134   "Return non-nil if FORM is funcallable."
2135   (or (and (symbolp form) (fboundp form))
2136       (and (listp form) (eq (car form) 'lambda))))
2137
2138 (defsubst gnus-goto-char (point)
2139   (and point (goto-char point)))
2140
2141 (defmacro gnus-buffer-exists-p (buffer)
2142   `(let ((buffer ,buffer))
2143      (and buffer
2144           (funcall (if (stringp buffer) 'get-buffer 'buffer-name)
2145                    buffer))))
2146
2147 (defmacro gnus-kill-buffer (buffer)
2148   `(let ((buf ,buffer))
2149      (if (gnus-buffer-exists-p buf)
2150          (kill-buffer buf))))
2151
2152 (defsubst gnus-point-at-bol ()
2153   "Return point at the beginning of the line."
2154   (let ((p (point)))
2155     (beginning-of-line)
2156     (prog1
2157         (point)
2158       (goto-char p))))
2159
2160 (defsubst gnus-point-at-eol ()
2161   "Return point at the end of the line."
2162   (let ((p (point)))
2163     (end-of-line)
2164     (prog1
2165         (point)
2166       (goto-char p))))
2167
2168 (defun gnus-alive-p ()
2169   "Say whether Gnus is running or not."
2170   (and gnus-group-buffer
2171        (get-buffer gnus-group-buffer)))
2172
2173 ;; Delete the current line (and the next N lines.);
2174 (defmacro gnus-delete-line (&optional n)
2175   `(delete-region (progn (beginning-of-line) (point))
2176                   (progn (forward-line ,(or n 1)) (point))))
2177
2178 ;; Suggested by Brian Edmonds <edmonds@cs.ubc.ca>.
2179 (defvar gnus-init-inhibit nil)
2180 (defun gnus-read-init-file (&optional inhibit-next)
2181   (if gnus-init-inhibit
2182       (setq gnus-init-inhibit nil)
2183     (setq gnus-init-inhibit inhibit-next)
2184     (and gnus-init-file
2185          (or (and (file-exists-p gnus-init-file)
2186                   ;; Don't try to load a directory.
2187                   (not (file-directory-p gnus-init-file)))
2188              (file-exists-p (concat gnus-init-file ".el"))
2189              (file-exists-p (concat gnus-init-file ".elc")))
2190          (condition-case var
2191              (load gnus-init-file nil t)
2192            (error
2193             (error "Error in %s: %s" gnus-init-file var))))))
2194
2195 ;; Info access macros.
2196
2197 (defmacro gnus-info-group (info)
2198   `(nth 0 ,info))
2199 (defmacro gnus-info-rank (info)
2200   `(nth 1 ,info))
2201 (defmacro gnus-info-read (info)
2202   `(nth 2 ,info))
2203 (defmacro gnus-info-marks (info)
2204   `(nth 3 ,info))
2205 (defmacro gnus-info-method (info)
2206   `(nth 4 ,info))
2207 (defmacro gnus-info-params (info)
2208   `(nth 5 ,info))
2209
2210 (defmacro gnus-info-level (info)
2211   `(let ((rank (gnus-info-rank ,info)))
2212      (if (consp rank)
2213          (car rank)
2214        rank)))
2215 (defmacro gnus-info-score (info)
2216   `(let ((rank (gnus-info-rank ,info)))
2217      (or (and (consp rank) (cdr rank)) 0)))
2218
2219 (defmacro gnus-info-set-group (info group)
2220   `(setcar ,info ,group))
2221 (defmacro gnus-info-set-rank (info rank)
2222   `(setcar (nthcdr 1 ,info) ,rank))
2223 (defmacro gnus-info-set-read (info read)
2224   `(setcar (nthcdr 2 ,info) ,read))
2225 (defmacro gnus-info-set-marks (info marks)
2226   `(setcar (nthcdr 3 ,info) ,marks))
2227 (defmacro gnus-info-set-method (info method)
2228   `(setcar (nthcdr 4 ,info) ,method))
2229 (defmacro gnus-info-set-params (info params)
2230   `(setcar (nthcdr 5 ,info) ,params))
2231
2232 (defmacro gnus-info-set-level (info level)
2233   `(let ((rank (cdr ,info)))
2234      (if (consp (car rank))
2235          (setcar (car rank) ,level)
2236        (setcar rank ,level))))
2237 (defmacro gnus-info-set-score (info score)
2238   `(let ((rank (cdr ,info)))
2239      (if (consp (car rank))
2240          (setcdr (car rank) ,score)
2241        (setcar rank (cons (car rank) ,score)))))
2242
2243 (defmacro gnus-get-info (group)
2244   `(nth 2 (gnus-gethash ,group gnus-newsrc-hashtb)))
2245
2246 (defun gnus-byte-code (func)
2247   "Return a form that can be `eval'ed based on FUNC."
2248   (let ((fval (symbol-function func)))
2249     (if (byte-code-function-p fval)
2250         (let ((flist (append fval nil)))
2251           (setcar flist 'byte-code)
2252           flist)
2253       (cons 'progn (cddr fval)))))
2254
2255 ;;; Load the compatability functions.
2256
2257 (require 'gnus-cus)
2258 (require 'gnus-ems)
2259
2260 \f
2261 ;;;
2262 ;;; Shutdown
2263 ;;;
2264
2265 (defvar gnus-shutdown-alist nil)
2266
2267 (defun gnus-add-shutdown (function &rest symbols)
2268   "Run FUNCTION whenever one of SYMBOLS is shut down."
2269   (push (cons function symbols) gnus-shutdown-alist))
2270
2271 (defun gnus-shutdown (symbol)
2272   "Shut down everything that waits for SYMBOL."
2273   (let ((alist gnus-shutdown-alist)
2274         entry)
2275     (while (setq entry (pop alist))
2276       (when (memq symbol (cdr entry))
2277         (funcall (car entry))))))
2278
2279 \f
2280
2281 ;; Format specs.  The chunks below are the machine-generated forms
2282 ;; that are to be evaled as the result of the default format strings.
2283 ;; We write them in here to get them byte-compiled.  That way the
2284 ;; default actions will be quite fast, while still retaining the full
2285 ;; flexibility of the user-defined format specs.
2286
2287 ;; First we have lots of dummy defvars to let the compiler know these
2288 ;; are really dynamic variables.
2289
2290 (defvar gnus-tmp-unread)
2291 (defvar gnus-tmp-replied)
2292 (defvar gnus-tmp-score-char)
2293 (defvar gnus-tmp-indentation)
2294 (defvar gnus-tmp-opening-bracket)
2295 (defvar gnus-tmp-lines)
2296 (defvar gnus-tmp-name)
2297 (defvar gnus-tmp-closing-bracket)
2298 (defvar gnus-tmp-subject-or-nil)
2299 (defvar gnus-tmp-subject)
2300 (defvar gnus-tmp-marked)
2301 (defvar gnus-tmp-marked-mark)
2302 (defvar gnus-tmp-subscribed)
2303 (defvar gnus-tmp-process-marked)
2304 (defvar gnus-tmp-number-of-unread)
2305 (defvar gnus-tmp-group-name)
2306 (defvar gnus-tmp-group)
2307 (defvar gnus-tmp-article-number)
2308 (defvar gnus-tmp-unread-and-unselected)
2309 (defvar gnus-tmp-news-method)
2310 (defvar gnus-tmp-news-server)
2311 (defvar gnus-tmp-article-number)
2312 (defvar gnus-mouse-face)
2313 (defvar gnus-mouse-face-prop)
2314
2315 (defun gnus-summary-line-format-spec ()
2316   (insert gnus-tmp-unread gnus-tmp-replied
2317           gnus-tmp-score-char gnus-tmp-indentation)
2318   (put-text-property
2319    (point)
2320    (progn
2321      (insert
2322       gnus-tmp-opening-bracket
2323       (format "%4d: %-20s"
2324               gnus-tmp-lines
2325               (if (> (length gnus-tmp-name) 20)
2326                   (substring gnus-tmp-name 0 20)
2327                 gnus-tmp-name))
2328       gnus-tmp-closing-bracket)
2329      (point))
2330    gnus-mouse-face-prop gnus-mouse-face)
2331   (insert " " gnus-tmp-subject-or-nil "\n"))
2332
2333 (defvar gnus-summary-line-format-spec
2334   (gnus-byte-code 'gnus-summary-line-format-spec))
2335
2336 (defun gnus-summary-dummy-line-format-spec ()
2337   (insert "*  ")
2338   (put-text-property
2339    (point)
2340    (progn
2341      (insert ":                          :")
2342      (point))
2343    gnus-mouse-face-prop gnus-mouse-face)
2344   (insert " " gnus-tmp-subject "\n"))
2345
2346 (defvar gnus-summary-dummy-line-format-spec
2347   (gnus-byte-code 'gnus-summary-dummy-line-format-spec))
2348
2349 (defun gnus-group-line-format-spec ()
2350   (insert gnus-tmp-marked-mark gnus-tmp-subscribed
2351           gnus-tmp-process-marked
2352           gnus-group-indentation
2353           (format "%5s: " gnus-tmp-number-of-unread))
2354   (put-text-property
2355    (point)
2356    (progn
2357      (insert gnus-tmp-group "\n")
2358      (1- (point)))
2359    gnus-mouse-face-prop gnus-mouse-face))
2360 (defvar gnus-group-line-format-spec
2361   (gnus-byte-code 'gnus-group-line-format-spec))
2362
2363 (defvar gnus-format-specs
2364   `((version . ,emacs-version)
2365     (group ,gnus-group-line-format ,gnus-group-line-format-spec)
2366     (summary-dummy ,gnus-summary-dummy-line-format
2367                    ,gnus-summary-dummy-line-format-spec)
2368     (summary ,gnus-summary-line-format ,gnus-summary-line-format-spec)))
2369
2370 (defvar gnus-article-mode-line-format-spec nil)
2371 (defvar gnus-summary-mode-line-format-spec nil)
2372 (defvar gnus-group-mode-line-format-spec nil)
2373
2374 ;;; Phew.  All that gruft is over, fortunately.
2375
2376 \f
2377 ;;;
2378 ;;; Gnus Utility Functions
2379 ;;;
2380
2381 (defun gnus-extract-address-components (from)
2382   (let (name address)
2383     ;; First find the address - the thing with the @ in it.  This may
2384     ;; not be accurate in mail addresses, but does the trick most of
2385     ;; the time in news messages.
2386     (if (string-match "\\b[^@ \t<>]+[!@][^@ \t<>]+\\b" from)
2387         (setq address (substring from (match-beginning 0) (match-end 0))))
2388     ;; Then we check whether the "name <address>" format is used.
2389     (and address
2390          ;; Fix by MORIOKA Tomohiko <morioka@jaist.ac.jp>
2391          ;; Linear white space is not required.
2392          (string-match (concat "[ \t]*<" (regexp-quote address) ">") from)
2393          (and (setq name (substring from 0 (match-beginning 0)))
2394               ;; Strip any quotes from the name.
2395               (string-match "\".*\"" name)
2396               (setq name (substring name 1 (1- (match-end 0))))))
2397     ;; If not, then "address (name)" is used.
2398     (or name
2399         (and (string-match "(.+)" from)
2400              (setq name (substring from (1+ (match-beginning 0))
2401                                    (1- (match-end 0)))))
2402         (and (string-match "()" from)
2403              (setq name address))
2404         ;; Fix by MORIOKA Tomohiko <morioka@jaist.ac.jp>.
2405         ;; XOVER might not support folded From headers.
2406         (and (string-match "(.*" from)
2407              (setq name (substring from (1+ (match-beginning 0))
2408                                    (match-end 0)))))
2409     ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
2410     (list (or name from) (or address from))))
2411
2412 (defun gnus-fetch-field (field)
2413   "Return the value of the header FIELD of current article."
2414   (save-excursion
2415     (save-restriction
2416       (let ((case-fold-search t))
2417         (nnheader-narrow-to-headers)
2418         (mail-fetch-field field)))))
2419
2420 (defun gnus-goto-colon ()
2421   (beginning-of-line)
2422   (search-forward ":" (gnus-point-at-eol) t))
2423
2424 ;;;###autoload
2425 (defun gnus-update-format (var)
2426   "Update the format specification near point."
2427   (interactive
2428    (list
2429     (save-excursion
2430       (eval-defun nil)
2431       ;; Find the end of the current word.
2432       (re-search-forward "[ \t\n]" nil t)
2433       ;; Search backward.
2434       (when (re-search-backward "\\(gnus-[-a-z]+-line-format\\)" nil t)
2435         (match-string 1)))))
2436   (let* ((type (intern (progn (string-match "gnus-\\([-a-z]+\\)-line" var)
2437                               (match-string 1 var))))
2438          (entry (assq type gnus-format-specs))
2439          value spec)
2440     (when entry
2441       (setq gnus-format-specs (delq entry gnus-format-specs)))
2442     (set
2443      (intern (format "%s-spec" var))
2444      (gnus-parse-format (setq value (symbol-value (intern var)))
2445                         (symbol-value (intern (format "%s-alist" var)))
2446                         (not (string-match "mode" var))))
2447     (setq spec (symbol-value (intern (format "%s-spec" var))))
2448     (push (list type value spec) gnus-format-specs)
2449
2450     (pop-to-buffer "*Gnus Format*")
2451     (erase-buffer)
2452     (lisp-interaction-mode)
2453     (insert (pp-to-string spec))))
2454
2455 (defun gnus-update-format-specifications (&optional force)
2456   "Update all (necessary) format specifications."
2457   ;; Make the indentation array.
2458   (gnus-make-thread-indent-array)
2459
2460   ;; See whether all the stored info needs to be flushed.
2461   (when (or force
2462             (not (equal emacs-version
2463                         (cdr (assq 'version gnus-format-specs)))))
2464     (setq gnus-format-specs nil))
2465
2466   ;; Go through all the formats and see whether they need updating.
2467   (let ((types '(summary summary-dummy group
2468                          summary-mode group-mode article-mode))
2469         new-format entry type val)
2470     (while (setq type (pop types))
2471       ;; Jump to the proper buffer to find out the value of
2472       ;; the variable, if possible.  (It may be buffer-local.)
2473       (save-excursion
2474         (let ((buffer (intern (format "gnus-%s-buffer" type)))
2475               val)
2476           (when (and (boundp buffer)
2477                      (setq val (symbol-value buffer))
2478                      (get-buffer val)
2479                      (buffer-name (get-buffer val)))
2480             (set-buffer (get-buffer val)))
2481           (setq new-format (symbol-value
2482                             (intern (format "gnus-%s-line-format" type))))))
2483       (setq entry (cdr (assq type gnus-format-specs)))
2484       (if (and entry
2485                (equal (car entry) new-format))
2486           ;; Use the old format.
2487           (set (intern (format "gnus-%s-line-format-spec" type))
2488                (cadr entry))
2489         ;; This is a new format.
2490         (setq val
2491               (if (not (stringp new-format))
2492                   ;; This is a function call or something.
2493                   new-format
2494                 ;; This is a "real" format.
2495                 (gnus-parse-format
2496                  new-format
2497                  (symbol-value
2498                   (intern (format "gnus-%s-line-format-alist"
2499                                   (if (eq type 'article-mode)
2500                                       'summary-mode type))))
2501                  (not (string-match "mode$" (symbol-name type))))))
2502         ;; Enter the new format spec into the list.
2503         (if entry
2504             (progn
2505               (setcar (cdr entry) val)
2506               (setcar entry new-format))
2507           (push (list type new-format val) gnus-format-specs))
2508         (set (intern (format "gnus-%s-line-format-spec" type)) val))))
2509
2510   (unless (assq 'version gnus-format-specs)
2511     (push (cons 'version emacs-version) gnus-format-specs))
2512
2513   (gnus-update-group-mark-positions)
2514   (gnus-update-summary-mark-positions))
2515
2516 (defun gnus-update-summary-mark-positions ()
2517   "Compute where the summary marks are to go."
2518   (save-excursion
2519     (let ((gnus-replied-mark 129)
2520           (gnus-score-below-mark 130)
2521           (gnus-score-over-mark 130)
2522           (thread nil)
2523           (gnus-visual nil)
2524           pos)
2525       (gnus-set-work-buffer)
2526       (gnus-summary-insert-line
2527        [0 "" "" "" "" "" 0 0 ""]  0 nil 128 t nil "" nil 1)
2528       (goto-char (point-min))
2529       (setq pos (list (cons 'unread (and (search-forward "\200" nil t)
2530                                          (- (point) 2)))))
2531       (goto-char (point-min))
2532       (push (cons 'replied (and (search-forward "\201" nil t) (- (point) 2)))
2533             pos)
2534       (goto-char (point-min))
2535       (push (cons 'score (and (search-forward "\202" nil t) (- (point) 2)))
2536             pos)
2537       (setq gnus-summary-mark-positions pos))))
2538
2539 (defun gnus-update-group-mark-positions ()
2540   (save-excursion
2541     (let ((gnus-process-mark 128)
2542           (gnus-group-marked '("dummy.group")))
2543       (gnus-set-active "dummy.group" '(0 . 0))
2544       (gnus-set-work-buffer)
2545       (gnus-group-insert-group-line "dummy.group" 0 nil 0 nil)
2546       (goto-char (point-min))
2547       (setq gnus-group-mark-positions
2548             (list (cons 'process (and (search-forward "\200" nil t)
2549                                       (- (point) 2))))))))
2550
2551 (defvar gnus-mouse-face-0 'highlight)
2552 (defvar gnus-mouse-face-1 'highlight)
2553 (defvar gnus-mouse-face-2 'highlight)
2554 (defvar gnus-mouse-face-3 'highlight)
2555 (defvar gnus-mouse-face-4 'highlight)
2556
2557 (defun gnus-mouse-face-function (form type)
2558   `(put-text-property
2559     (point) (progn ,@form (point))
2560     gnus-mouse-face-prop
2561     ,(if (equal type 0)
2562          'gnus-mouse-face
2563        `(quote ,(symbol-value (intern (format "gnus-mouse-face-%d" type)))))))
2564
2565 (defvar gnus-face-0 'bold)
2566 (defvar gnus-face-1 'italic)
2567 (defvar gnus-face-2 'bold-italic)
2568 (defvar gnus-face-3 'bold)
2569 (defvar gnus-face-4 'bold)
2570
2571 (defun gnus-face-face-function (form type)
2572   `(put-text-property
2573     (point) (progn ,@form (point))
2574     'face ',(symbol-value (intern (format "gnus-face-%d" type)))))
2575
2576 (defun gnus-max-width-function (el max-width)
2577   (or (numberp max-width) (signal 'wrong-type-argument '(numberp max-width)))
2578   (if (symbolp el)
2579       `(if (> (length ,el) ,max-width)
2580            (substring ,el 0 ,max-width)
2581          ,el)
2582     `(let ((val (eval ,el)))
2583        (if (numberp val)
2584            (setq val (int-to-string val)))
2585        (if (> (length val) ,max-width)
2586            (substring val 0 ,max-width)
2587          val))))
2588
2589 (defun gnus-parse-format (format spec-alist &optional insert)
2590   ;; This function parses the FORMAT string with the help of the
2591   ;; SPEC-ALIST and returns a list that can be eval'ed to return the
2592   ;; string.  If the FORMAT string contains the specifiers %( and %)
2593   ;; the text between them will have the mouse-face text property.
2594   (if (string-match
2595        "\\`\\(.*\\)%[0-9]?[{(]\\(.*\\)%[0-9]?[})]\\(.*\n?\\)\\'"
2596        format)
2597       (gnus-parse-complex-format format spec-alist)
2598     ;; This is a simple format.
2599     (gnus-parse-simple-format format spec-alist insert)))
2600
2601 (defun gnus-parse-complex-format (format spec-alist)
2602   (save-excursion
2603     (gnus-set-work-buffer)
2604     (insert format)
2605     (goto-char (point-min))
2606     (while (re-search-forward "\"" nil t)
2607       (replace-match "\\\"" nil t))
2608     (goto-char (point-min))
2609     (insert "(\"")
2610     (while (re-search-forward "%\\([0-9]+\\)?\\([{}()]\\)" nil t)
2611       (let ((number (if (match-beginning 1)
2612                         (match-string 1) "0"))
2613             (delim (aref (match-string 2) 0)))
2614         (if (or (= delim ?\() (= delim ?\{))
2615             (replace-match (concat "\"(" (if (= delim ?\() "mouse" "face")
2616                                    " " number " \""))
2617           (replace-match "\")\""))))
2618     (goto-char (point-max))
2619     (insert "\")")
2620     (goto-char (point-min))
2621     (let ((form (read (current-buffer))))
2622       (cons 'progn (gnus-complex-form-to-spec form spec-alist)))))
2623
2624 (defun gnus-complex-form-to-spec (form spec-alist)
2625   (delq nil
2626         (mapcar
2627          (lambda (sform)
2628            (if (stringp sform)
2629                (gnus-parse-simple-format sform spec-alist t)
2630              (funcall (intern (format "gnus-%s-face-function" (car sform)))
2631                       (gnus-complex-form-to-spec (cddr sform) spec-alist)
2632                       (nth 1 sform))))
2633          form)))
2634
2635 (defun gnus-parse-simple-format (format spec-alist &optional insert)
2636   ;; This function parses the FORMAT string with the help of the
2637   ;; SPEC-ALIST and returns a list that can be eval'ed to return a
2638   ;; string.
2639   (let ((max-width 0)
2640         spec flist fstring newspec elem beg result dontinsert)
2641     (save-excursion
2642       (gnus-set-work-buffer)
2643       (insert format)
2644       (goto-char (point-min))
2645       (while (re-search-forward "%[-0-9]*\\(,[0-9]+\\)?\\([^0-9]\\)\\(.\\)?"
2646                                 nil t)
2647         (if (= (setq spec (string-to-char (match-string 2))) ?%)
2648               (setq newspec "%"
2649                     beg (1+ (match-beginning 0)))
2650           ;; First check if there are any specs that look anything like
2651           ;; "%12,12A", ie. with a "max width specification".  These have
2652           ;; to be treated specially.
2653           (if (setq beg (match-beginning 1))
2654               (setq max-width
2655                     (string-to-int
2656                      (buffer-substring
2657                       (1+ (match-beginning 1)) (match-end 1))))
2658