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