1 ;;; gnus.el --- a newsreader for GNU Emacs
2 ;; Copyright (C) 1987,88,89,90,93,94,95,96 Free Software Foundation, Inc.
4 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
5 ;; Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
8 ;; This file is part of GNU Emacs.
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)
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.
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.
29 (eval '(run-hooks 'gnus-load-hook))
37 (eval-when-compile (require 'cl))
39 (defvar gnus-directory (or (getenv "SAVEDIR") "~/News/")
40 "*Directory variable from which all other Gnus file variables are derived.")
42 ;; Site dependent variables. These variables should be defined in
45 (defvar gnus-default-nntp-server nil
46 "Specify a default NNTP server.
47 This variable should be defined in paths.el, and should never be set
49 If you want to change servers, you should use `gnus-select-method'.
50 See the documentation to that variable.")
52 (defvar gnus-backup-default-subscribed-newsgroups
53 '("news.announce.newusers" "news.groups.questions" "gnu.emacs.gnus")
54 "Default default new newsgroups the first time Gnus is run.
55 Should be set in paths.el, and shouldn't be touched by the user.")
57 (defvar gnus-local-domain nil
58 "Local domain name without a host name.
59 The DOMAINNAME environment variable is used instead if it is defined.
60 If the `system-name' function returns the full Internet name, there is
61 no need to set this variable.")
63 (defvar gnus-local-organization nil
64 "String with a description of what organization (if any) the user belongs to.
65 The ORGANIZATION environment variable is used instead if it is defined.
66 If this variable contains a function, this function will be called
67 with the current newsgroup name as the argument. The function should
70 In any case, if the string (either in the variable, in the environment
71 variable, or returned by the function) is a file name, the contents of
72 this file will be used as the organization.")
74 ;; Customization variables
76 ;; Don't touch this variable.
77 (defvar gnus-nntp-service "nntp"
78 "*NNTP service name (\"nntp\" or 119).
79 This is an obsolete variable, which is scarcely used. If you use an
80 nntp server for your newsgroup and want to change the port number
81 used to 899, you would say something along these lines:
83 (setq gnus-select-method '(nntp \"my.nntp.server\" (nntp-port-number 899)))")
85 (defvar gnus-nntpserver-file "/etc/nntpserver"
86 "*A file with only the name of the nntp server in it.")
88 ;; This function is used to check both the environment variable
89 ;; NNTPSERVER and the /etc/nntpserver file to see whether one can find
90 ;; an nntp server name default.
91 (defun gnus-getenv-nntpserver ()
92 (or (getenv "NNTPSERVER")
93 (and (file-readable-p gnus-nntpserver-file)
95 (set-buffer (get-buffer-create " *gnus nntp*"))
96 (buffer-disable-undo (current-buffer))
97 (insert-file-contents gnus-nntpserver-file)
98 (let ((name (buffer-string)))
100 (if (string-match "^[ \t\n]*$" name)
103 (kill-buffer (current-buffer))))))))
105 (defvar gnus-select-method
107 (list 'nntp (or (condition-case ()
108 (gnus-getenv-nntpserver)
110 (if (and gnus-default-nntp-server
111 (not (string= gnus-default-nntp-server "")))
112 gnus-default-nntp-server)
114 (if (or (null gnus-nntp-service)
115 (equal gnus-nntp-service "nntp"))
117 (list gnus-nntp-service)))
118 "*Default method for selecting a newsgroup.
119 This variable should be a list, where the first element is how the
120 news is to be fetched, the second is the address.
122 For instance, if you want to get your news via NNTP from
123 \"flab.flab.edu\", you could say:
125 (setq gnus-select-method '(nntp \"flab.flab.edu\"))
127 If you want to use your local spool, say:
129 (setq gnus-select-method (list 'nnspool (system-name)))
131 If you use this variable, you must set `gnus-nntp-server' to nil.
133 There is a lot more to know about select methods and virtual servers -
134 see the manual for details.")
136 (defvar gnus-message-archive-method
139 (nnfolder-directory ,(nnheader-concat message-directory "archive"))
140 (nnfolder-active-file
141 ,(nnheader-concat message-directory "archive/active"))
142 (nnfolder-get-new-mail nil)
143 (nnfolder-inhibit-expiry t))
144 "*Method used for archiving messages you've sent.
145 This should be a mail method.")
147 (defvar gnus-refer-article-method nil
148 "*Preferred method for fetching an article by Message-ID.
149 If you are reading news from the local spool (with nnspool), fetching
150 articles by Message-ID is painfully slow. By setting this method to an
151 nntp method, you might get acceptable results.
153 The value of this variable must be a valid select method as discussed
154 in the documentation of `gnus-select-method'.")
156 (defvar gnus-secondary-select-methods nil
157 "*A list of secondary methods that will be used for reading news.
158 This is a list where each element is a complete select method (see
159 `gnus-select-method').
161 If, for instance, you want to read your mail with the nnml backend,
162 you could set this variable:
164 (setq gnus-secondary-select-methods '((nnml \"\")))")
166 (defvar gnus-secondary-servers nil
167 "*List of NNTP servers that the user can choose between interactively.
168 To make Gnus query you for a server, you have to give `gnus' a
169 non-numeric prefix - `C-u M-x gnus', in short.")
171 (defvar gnus-nntp-server nil
172 "*The name of the host running the NNTP server.
173 This variable is semi-obsolete. Use the `gnus-select-method'
176 (defvar gnus-startup-file "~/.newsrc"
177 "*Your `.newsrc' file.
178 `.newsrc-SERVER' will be used instead if that exists.")
180 (defvar gnus-init-file "~/.gnus"
181 "*Your Gnus elisp startup file.
182 If a file with the .el or .elc suffixes exist, it will be read
185 (defvar gnus-group-faq-directory
186 '("/ftp@mirrors.aol.com:/pub/rtfm/usenet/"
187 "/ftp@sunsite.auc.dk:/pub/usenet/"
188 "/ftp@src.doc.ic.ac.uk:/usenet/news-FAQS/"
189 "/ftp@ftp.seas.gwu.edu:/pub/rtfm/"
190 "/ftp@rtfm.mit.edu:/pub/usenet/"
191 "/ftp@ftp.uni-paderborn.de:/pub/FAQ/"
192 "/ftp@ftp.sunet.se:/pub/usenet/"
193 "/ftp@nctuccca.edu.tw:/USENET/FAQ/"
194 "/ftp@hwarang.postech.ac.kr:/pub/usenet/"
195 "/ftp@ftp.hk.super.net:/mirror/faqs/")
196 "*Directory where the group FAQs are stored.
197 This will most commonly be on a remote machine, and the file will be
200 This variable can also be a list of directories. In that case, the
201 first element in the list will be used by default, and the others will
202 be used as backup sites.
204 Note that Gnus uses an aol machine as the default directory. If this
205 feels fundamentally unclean, just think of it as a way to finally get
206 something of value back from them.
208 If the default site is too slow, try one of these:
210 North America: mirrors.aol.com /pub/rtfm/usenet
211 ftp.seas.gwu.edu /pub/rtfm
212 rtfm.mit.edu /pub/usenet
213 Europe: ftp.uni-paderborn.de /pub/FAQ
214 src.doc.ic.ac.uk /usenet/news-FAQS
215 ftp.sunet.se /pub/usenet
216 sunsite.auc.dk /pub/usenet
217 Asia: nctuccca.edu.tw /USENET/FAQ
218 hwarang.postech.ac.kr /pub/usenet
219 ftp.hk.super.net /mirror/faqs")
221 (defvar gnus-group-archive-directory
222 "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list/"
223 "*The address of the (ding) archives.")
225 (defvar gnus-group-recent-archive-directory
226 "/ftp@ftp.hpc.uh.edu:/pub/emacs/ding-list-recent/"
227 "*The address of the most recent (ding) articles.")
229 (defvar gnus-default-subscribed-newsgroups nil
230 "*This variable lists what newsgroups should be subscribed the first time Gnus is used.
231 It should be a list of strings.
232 If it is `t', Gnus will not do anything special the first time it is
233 started; it'll just use the normal newsgroups subscription methods.")
235 (defvar gnus-use-cross-reference t
236 "*Non-nil means that cross referenced articles will be marked as read.
237 If nil, ignore cross references. If t, mark articles as read in
238 subscribed newsgroups. If neither t nor nil, mark as read in all
241 (defvar gnus-single-article-buffer t
242 "*If non-nil, display all articles in the same buffer.
243 If nil, each group will get its own article buffer.")
245 (defvar gnus-use-dribble-file t
246 "*Non-nil means that Gnus will use a dribble file to store user updates.
247 If Emacs should crash without saving the .newsrc files, complete
248 information can be restored from the dribble file.")
250 (defvar gnus-dribble-directory nil
251 "*The directory where dribble files will be saved.
252 If this variable is nil, the directory where the .newsrc files are
253 saved will be used.")
255 (defvar gnus-asynchronous nil
256 "*If non-nil, Gnus will supply backends with data needed for async article fetching.")
258 (defvar gnus-kill-summary-on-exit t
259 "*If non-nil, kill the summary buffer when you exit from it.
260 If nil, the summary will become a \"*Dead Summary*\" buffer, and
261 it will be killed sometime later.")
263 (defvar gnus-large-newsgroup 200
264 "*The number of articles which indicates a large newsgroup.
265 If the number of articles in a newsgroup is greater than this value,
266 confirmation is required for selecting the newsgroup.")
268 ;; Suggested by Andrew Eskilsson <pi92ae@lelle.pt.hk-r.se>.
269 (defvar gnus-no-groups-message "No news is horrible news"
270 "*Message displayed by Gnus when no groups are available.")
272 (defvar gnus-use-long-file-name (not (memq system-type '(usg-unix-v xenix)))
273 "*Non-nil means that the default name of a file to save articles in is the group name.
274 If it's nil, the directory form of the group name is used instead.
276 If this variable is a list, and the list contains the element
277 `not-score', long file names will not be used for score files; if it
278 contains the element `not-save', long file names will not be used for
279 saving; and if it contains the element `not-kill', long file names
280 will not be used for kill files.")
282 (defvar gnus-article-save-directory gnus-directory
283 "*Name of the directory articles will be saved in (default \"~/News\").")
285 (defvar gnus-kill-files-directory gnus-directory
286 "*Name of the directory where kill files will be stored (default \"~/News\").")
288 (defvar gnus-default-article-saver 'gnus-summary-save-in-rmail
289 "*A function to save articles in your favorite format.
290 The function must be interactively callable (in other words, it must
291 be an Emacs command).
293 Gnus provides the following functions:
295 * gnus-summary-save-in-rmail (Rmail format)
296 * gnus-summary-save-in-mail (Unix mail format)
297 * gnus-summary-save-in-folder (MH folder)
298 * gnus-summary-save-in-file (article format).
299 * gnus-summary-save-in-vm (use VM's folder format).")
301 (defvar gnus-prompt-before-saving 'always
302 "*This variable says how much prompting is to be done when saving articles.
303 If it is nil, no prompting will be done, and the articles will be
304 saved to the default files. If this variable is `always', each and
305 every article that is saved will be preceded by a prompt, even when
306 saving large batches of articles. If this variable is neither nil not
307 `always', there the user will be prompted once for a file name for
308 each invocation of the saving commands.")
310 (defvar gnus-rmail-save-name (function gnus-plain-save-name)
311 "*A function generating a file name to save articles in Rmail format.
312 The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.")
314 (defvar gnus-mail-save-name (function gnus-plain-save-name)
315 "*A function generating a file name to save articles in Unix mail format.
316 The function is called with NEWSGROUP, HEADERS, and optional LAST-FILE.")
318 (defvar gnus-folder-save-name (function gnus-folder-save-name)
319 "*A function generating a file name to save articles in MH folder.
320 The function is called with NEWSGROUP, HEADERS, and optional LAST-FOLDER.")
322 (defvar gnus-file-save-name (function gnus-numeric-save-name)
323 "*A function generating a file name to save articles in article format.
324 The function is called with NEWSGROUP, HEADERS, and optional
327 (defvar gnus-split-methods
328 '((gnus-article-archive-name))
329 "*Variable used to suggest where articles are to be saved.
330 For instance, if you would like to save articles related to Gnus in
331 the file \"gnus-stuff\", and articles related to VM in \"vm-stuff\",
332 you could set this variable to something like:
334 '((\"^Subject:.*gnus\\|^Newsgroups:.*gnus\" \"gnus-stuff\")
335 (\"^Subject:.*vm\\|^Xref:.*vm\" \"vm-stuff\"))
337 This variable is an alist where the where the key is the match and the
338 value is a list of possible files to save in if the match is non-nil.
340 If the match is a string, it is used as a regexp match on the
341 article. If the match is a symbol, that symbol will be funcalled
342 from the buffer of the article to be saved with the newsgroup as the
343 parameter. If it is a list, it will be evaled in the same buffer.
345 If this form or function returns a string, this string will be used as
346 a possible file name; and if it returns a non-nil list, that list will
347 be used as possible file names.")
349 (defvar gnus-move-split-methods nil
350 "*Variable used to suggest where articles are to be moved to.
351 It uses the same syntax as the `gnus-split-methods' variable.")
353 (defvar gnus-save-score nil
354 "*If non-nil, save group scoring info.")
356 (defvar gnus-use-adaptive-scoring nil
357 "*If non-nil, use some adaptive scoring scheme.")
359 (defvar gnus-use-cache 'passive
360 "*If nil, Gnus will ignore the article cache.
361 If `passive', it will allow entering (and reading) articles
362 explicitly entered into the cache. If anything else, use the
363 cache to the full extent of the law.")
365 (defvar gnus-use-trees nil
366 "*If non-nil, display a thread tree buffer.")
368 (defvar gnus-use-grouplens nil
369 "*If non-nil, use GroupLens ratings.")
371 (defvar gnus-keep-backlog nil
372 "*If non-nil, Gnus will keep read articles for later re-retrieval.
373 If it is a number N, then Gnus will only keep the last N articles
374 read. If it is neither nil nor a number, Gnus will keep all read
375 articles. This is not a good idea.")
377 (defvar gnus-use-nocem nil
378 "*If non-nil, Gnus will read NoCeM cancel messages.")
380 (defvar gnus-use-demon nil
381 "If non-nil, Gnus might use some demons.")
383 (defvar gnus-use-scoring t
384 "*If non-nil, enable scoring.")
386 (defvar gnus-use-picons nil
387 "*If non-nil, display picons.")
389 (defvar gnus-fetch-old-headers nil
390 "*Non-nil means that Gnus will try to build threads by grabbing old headers.
391 If an unread article in the group refers to an older, already read (or
392 just marked as read) article, the old article will not normally be
393 displayed in the Summary buffer. If this variable is non-nil, Gnus
394 will attempt to grab the headers to the old articles, and thereby
395 build complete threads. If it has the value `some', only enough
396 headers to connect otherwise loose threads will be displayed.
397 This variable can also be a number. In that case, no more than that
398 number of old headers will be fetched.
400 The server has to support NOV for any of this to work.")
403 ;(defvar gnus-visual t
404 ; "*If non-nil, will do various highlighting.
405 ;If nil, no mouse highlights (or any other highlights) will be
406 ;performed. This might speed up Gnus some when generating large group
407 ;and summary buffers.")
409 (defvar gnus-novice-user t
410 "*Non-nil means that you are a usenet novice.
411 If non-nil, verbose messages may be displayed and confirmations may be
414 (defvar gnus-expert-user nil
415 "*Non-nil means that you will never be asked for confirmation about anything.
416 And that means *anything*.")
418 (defvar gnus-verbose 7
419 "*Integer that says how verbose Gnus should be.
420 The higher the number, the more messages Gnus will flash to say what
421 it's doing. At zero, Gnus will be totally mute; at five, Gnus will
422 display most important messages; and at ten, Gnus will keep on
423 jabbering all the time.")
425 (defvar gnus-keep-same-level nil
426 "*Non-nil means that the next newsgroup after the current will be on the same level.
427 When you type, for instance, `n' after reading the last article in the
428 current newsgroup, you will go to the next newsgroup. If this variable
429 is nil, the next newsgroup will be the next from the group
431 If this variable is non-nil, Gnus will either put you in the
432 next newsgroup with the same level, or, if no such newsgroup is
433 available, the next newsgroup with the lowest possible level higher
434 than the current level.
435 If this variable is `best', Gnus will make the next newsgroup the one
436 with the best level.")
438 (defvar gnus-summary-make-false-root 'adopt
439 "*nil means that Gnus won't gather loose threads.
440 If the root of a thread has expired or been read in a previous
441 session, the information necessary to build a complete thread has been
442 lost. Instead of having many small sub-threads from this original thread
443 scattered all over the summary buffer, Gnus can gather them.
445 If non-nil, Gnus will try to gather all loose sub-threads from an
446 original thread into one large thread.
448 If this variable is non-nil, it should be one of `none', `adopt',
451 If this variable is `none', Gnus will not make a false root, but just
452 present the sub-threads after another.
453 If this variable is `dummy', Gnus will create a dummy root that will
454 have all the sub-threads as children.
455 If this variable is `adopt', Gnus will make one of the \"children\"
456 the parent and mark all the step-children as such.
457 If this variable is `empty', the \"children\" are printed with empty
458 subject fields. (Or rather, they will be printed with a string
459 given by the `gnus-summary-same-subject' variable.)")
461 (defvar gnus-summary-gather-exclude-subject "^ *$\\|^(none)$"
462 "*A regexp to match subjects to be excluded from loose thread gathering.
463 As loose thread gathering is done on subjects only, that means that
464 there can be many false gatherings performed. By rooting out certain
465 common subjects, gathering might become saner.")
467 (defvar gnus-summary-gather-subject-limit nil
468 "*Maximum length of subject comparisons when gathering loose threads.
469 Use nil to compare full subjects. Setting this variable to a low
470 number will help gather threads that have been corrupted by
471 newsreaders chopping off subject lines, but it might also mean that
472 unrelated articles that have subject that happen to begin with the
473 same few characters will be incorrectly gathered.
475 If this variable is `fuzzy', Gnus will use a fuzzy algorithm when
476 comparing subjects.")
478 (defvar gnus-simplify-ignored-prefixes nil
479 "*Regexp, matches for which are removed from subject lines when simplifying.")
481 (defvar gnus-build-sparse-threads nil
482 "*If non-nil, fill in the gaps in threads.
483 If `some', only fill in the gaps that are needed to tie loose threads
484 together. If `more', fill in all leaf nodes that Gnus can find. If
485 non-nil and non-`some', fill in all gaps that Gnus manages to guess.")
487 (defvar gnus-summary-thread-gathering-function 'gnus-gather-threads-by-subject
488 "Function used for gathering loose threads.
489 There are two pre-defined functions: `gnus-gather-threads-by-subject',
490 which only takes Subjects into consideration; and
491 `gnus-gather-threads-by-references', which compared the References
492 headers of the articles to find matches.")
494 ;; Added by Per Abrahamsen <amanda@iesd.auc.dk>.
495 (defvar gnus-summary-same-subject ""
496 "*String indicating that the current article has the same subject as the previous.
497 This variable will only be used if the value of
498 `gnus-summary-make-false-root' is `empty'.")
500 (defvar gnus-summary-goto-unread t
501 "*If non-nil, marking commands will go to the next unread article.
502 If `never', \\<gnus-summary-mode-map>\\[gnus-summary-next-page] will go to the next article,
503 whether it is read or not.")
505 (defvar gnus-group-goto-unread t
506 "*If non-nil, movement commands will go to the next unread and subscribed group.")
508 (defvar gnus-goto-next-group-when-activating t
509 "*If non-nil, the \\<gnus-group-mode-map>\\[gnus-group-get-new-news-this-group] command will advance point to the next group.")
511 (defvar gnus-check-new-newsgroups t
512 "*Non-nil means that Gnus will add new newsgroups at startup.
513 If this variable is `ask-server', Gnus will ask the server for new
514 groups since the last time it checked. This means that the killed list
515 is no longer necessary, so you could set `gnus-save-killed-list' to
518 A variant is to have this variable be a list of select methods. Gnus
519 will then use the `ask-server' method on all these select methods to
520 query for new groups from all those servers.
523 (setq gnus-check-new-newsgroups
524 '((nntp \"some.server\") (nntp \"other.server\")))
526 If this variable is nil, then you have to tell Gnus explicitly to
527 check for new newsgroups with \\<gnus-group-mode-map>\\[gnus-find-new-newsgroups].")
529 (defvar gnus-check-bogus-newsgroups nil
530 "*Non-nil means that Gnus will check and remove bogus newsgroup at startup.
531 If this variable is nil, then you have to tell Gnus explicitly to
532 check for bogus newsgroups with \\<gnus-group-mode-map>\\[gnus-group-check-bogus-groups].")
534 (defvar gnus-read-active-file t
535 "*Non-nil means that Gnus will read the entire active file at startup.
536 If this variable is nil, Gnus will only know about the groups in your
539 If this variable is `some', Gnus will try to only read the relevant
540 parts of the active file from the server. Not all servers support
541 this, and it might be quite slow with other servers, but this should
542 generally be faster than both the t and nil value.
544 If you set this variable to nil or `some', you probably still want to
545 be told about new newsgroups that arrive. To do that, set
546 `gnus-check-new-newsgroups' to `ask-server'. This may not work
547 properly with all servers.")
549 (defvar gnus-level-subscribed 5
550 "*Groups with levels less than or equal to this variable are subscribed.")
552 (defvar gnus-level-unsubscribed 7
553 "*Groups with levels less than or equal to this variable are unsubscribed.
554 Groups with levels less than `gnus-level-subscribed', which should be
555 less than this variable, are subscribed.")
557 (defvar gnus-level-zombie 8
558 "*Groups with this level are zombie groups.")
560 (defvar gnus-level-killed 9
561 "*Groups with this level are killed.")
563 (defvar gnus-level-default-subscribed 3
564 "*New subscribed groups will be subscribed at this level.")
566 (defvar gnus-level-default-unsubscribed 6
567 "*New unsubscribed groups will be unsubscribed at this level.")
569 (defvar gnus-activate-level (1+ gnus-level-subscribed)
570 "*Groups higher than this level won't be activated on startup.
571 Setting this variable to something log might save lots of time when
572 you have many groups that you aren't interested in.")
574 (defvar gnus-activate-foreign-newsgroups 4
575 "*If nil, Gnus will not check foreign newsgroups at startup.
576 If it is non-nil, it should be a number between one and nine. Foreign
577 newsgroups that have a level lower or equal to this number will be
578 activated on startup. For instance, if you want to active all
579 subscribed newsgroups, but not the rest, you'd set this variable to
580 `gnus-level-subscribed'.
582 If you subscribe to lots of newsgroups from different servers, startup
583 might take a while. By setting this variable to nil, you'll save time,
584 but you won't be told how many unread articles there are in the
587 (defvar gnus-save-newsrc-file t
588 "*Non-nil means that Gnus will save the `.newsrc' file.
589 Gnus always saves its own startup file, which is called
590 \".newsrc.eld\". The file called \".newsrc\" is in a format that can
591 be readily understood by other newsreaders. If you don't plan on
592 using other newsreaders, set this variable to nil to save some time on
595 (defvar gnus-save-killed-list t
596 "*If non-nil, save the list of killed groups to the startup file.
597 If you set this variable to nil, you'll save both time (when starting
598 and quitting) and space (both memory and disk), but it will also mean
599 that Gnus has no record of which groups are new and which are old, so
600 the automatic new newsgroups subscription methods become meaningless.
602 You should always set `gnus-check-new-newsgroups' to `ask-server' or
603 nil if you set this variable to nil.")
605 (defvar gnus-interactive-catchup t
606 "*If non-nil, require your confirmation when catching up a group.")
608 (defvar gnus-interactive-exit t
609 "*If non-nil, require your confirmation when exiting Gnus.")
611 (defvar gnus-kill-killed t
612 "*If non-nil, Gnus will apply kill files to already killed articles.
613 If it is nil, Gnus will never apply kill files to articles that have
614 already been through the scoring process, which might very well save lots
617 (defvar gnus-extract-address-components 'gnus-extract-address-components
618 "*Function for extracting address components from a From header.
619 Two pre-defined function exist: `gnus-extract-address-components',
620 which is the default, quite fast, and too simplistic solution, and
621 `mail-extract-address-components', which works much better, but is
624 (defvar gnus-summary-default-score 0
625 "*Default article score level.
626 If this variable is nil, scoring will be disabled.")
628 (defvar gnus-summary-zcore-fuzz 0
629 "*Fuzziness factor for the zcore in the summary buffer.
630 Articles with scores closer than this to `gnus-summary-default-score'
631 will not be marked.")
633 (defvar gnus-simplify-subject-fuzzy-regexp nil
634 "*Strings to be removed when doing fuzzy matches.
635 This can either be a regular expression or list of regular expressions
636 that will be removed from subject strings if fuzzy subject
637 simplification is selected.")
639 (defvar gnus-permanently-visible-groups nil
640 "*Regexp to match groups that should always be listed in the group buffer.
641 This means that they will still be listed when there are no unread
642 articles in the groups.")
644 (defvar gnus-list-groups-with-ticked-articles t
645 "*If non-nil, list groups that have only ticked articles.
646 If nil, only list groups that have unread articles.")
648 (defvar gnus-group-default-list-level gnus-level-subscribed
649 "*Default listing level.
650 Ignored if `gnus-group-use-permanent-levels' is non-nil.")
652 (defvar gnus-group-use-permanent-levels nil
653 "*If non-nil, once you set a level, Gnus will use this level.")
655 (defvar gnus-group-list-inactive-groups t
656 "*If non-nil, inactive groups will be listed.")
658 (defvar gnus-show-mime nil
659 "*If non-nil, do mime processing of articles.
660 The articles will simply be fed to the function given by
661 `gnus-show-mime-method'.")
663 (defvar gnus-strict-mime t
664 "*If nil, MIME-decode even if there is no Mime-Version header in the article.")
666 (defvar gnus-show-mime-method 'metamail-buffer
667 "*Function to process a MIME message.
668 The function is called from the article buffer.")
670 (defvar gnus-decode-encoded-word-method (lambda ())
671 "*Function to decode a MIME encoded-words.
672 The function is called from the article buffer.")
674 (defvar gnus-show-threads t
675 "*If non-nil, display threads in summary mode.")
677 (defvar gnus-thread-hide-subtree nil
678 "*If non-nil, hide all threads initially.
679 If threads are hidden, you have to run the command
680 `gnus-summary-show-thread' by hand or use `gnus-select-article-hook'
681 to expose hidden threads.")
683 (defvar gnus-thread-hide-killed t
684 "*If non-nil, hide killed threads automatically.")
686 (defvar gnus-thread-ignore-subject nil
687 "*If non-nil, ignore subjects and do all threading based on the Reference header.
688 If nil, which is the default, articles that have different subjects
689 from their parents will start separate threads.")
691 (defvar gnus-thread-operation-ignore-subject t
692 "*If non-nil, subjects will be ignored when doing thread commands.
693 This affects commands like `gnus-summary-kill-thread' and
694 `gnus-summary-lower-thread'.
696 If this variable is nil, articles in the same thread with different
697 subjects will not be included in the operation in question. If this
698 variable is `fuzzy', only articles that have subjects that are fuzzily
699 equal will be included.")
701 (defvar gnus-thread-indent-level 4
702 "*Number that says how much each sub-thread should be indented.")
704 (defvar gnus-ignored-newsgroups
705 (purecopy (mapconcat 'identity
706 '("^to\\." ; not "real" groups
707 "^[0-9. \t]+ " ; all digits in name
708 "[][\"#'()]" ; bogus characters
711 "*A regexp to match uninteresting newsgroups in the active file.
712 Any lines in the active file matching this regular expression are
713 removed from the newsgroup list before anything else is done to it,
714 thus making them effectively non-existent.")
716 (defvar gnus-ignored-headers
717 "^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:"
718 "*All headers that match this regexp will be hidden.
719 This variable can also be a list of regexps of headers to be ignored.
720 If `gnus-visible-headers' is non-nil, this variable will be ignored.")
722 (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-"
723 "*All headers that do not match this regexp will be hidden.
724 This variable can also be a list of regexp of headers to remain visible.
725 If this variable is non-nil, `gnus-ignored-headers' will be ignored.")
727 (defvar gnus-sorted-header-list
728 '("^From:" "^Subject:" "^Summary:" "^Keywords:" "^Newsgroups:" "^To:"
729 "^Cc:" "^Date:" "^Organization:")
730 "*This variable is a list of regular expressions.
731 If it is non-nil, headers that match the regular expressions will
732 be placed first in the article buffer in the sequence specified by
735 (defvar gnus-boring-article-headers
736 '(empty followup-to reply-to)
737 "*Headers that are only to be displayed if they have interesting data.
738 Possible values in this list are `empty', `newsgroups', `followup-to',
739 `reply-to', and `date'.")
741 (defvar gnus-show-all-headers nil
742 "*If non-nil, don't hide any headers.")
744 (defvar gnus-save-all-headers t
745 "*If non-nil, don't remove any headers before saving.")
747 (defvar gnus-saved-headers gnus-visible-headers
748 "*Headers to keep if `gnus-save-all-headers' is nil.
749 If `gnus-save-all-headers' is non-nil, this variable will be ignored.
750 If that variable is nil, however, all headers that match this regexp
751 will be kept while the rest will be deleted before saving.")
753 (defvar gnus-inhibit-startup-message nil
754 "*If non-nil, the startup message will not be displayed.")
756 (defvar gnus-signature-separator "^-- *$"
757 "Regexp matching signature separator.")
759 (defvar gnus-signature-limit nil
760 "Provide a limit to what is considered a signature.
761 If it is a number, no signature may not be longer (in characters) than
762 that number. If it is a function, the function will be called without
763 any parameters, and if it returns nil, there is no signature in the
764 buffer. If it is a string, it will be used as a regexp. If it
765 matches, the text in question is not a signature.")
767 (defvar gnus-auto-extend-newsgroup t
768 "*If non-nil, extend newsgroup forward and backward when requested.")
770 (defvar gnus-auto-select-first t
771 "*If nil, don't select the first unread article when entering a group.
772 If this variable is `best', select the highest-scored unread article
773 in the group. If neither nil nor `best', select the first unread
776 If you want to prevent automatic selection of the first unread article
777 in some newsgroups, set the variable to nil in
778 `gnus-select-group-hook'.")
780 (defvar gnus-auto-select-next t
781 "*If non-nil, offer to go to the next group from the end of the previous.
782 If the value is t and the next newsgroup is empty, Gnus will exit
783 summary mode and go back to group mode. If the value is neither nil
784 nor t, Gnus will select the following unread newsgroup. In
785 particular, if the value is the symbol `quietly', the next unread
786 newsgroup will be selected without any confirmation, and if it is
787 `almost-quietly', the next group will be selected without any
788 confirmation if you are located on the last article in the group.
789 Finally, if this variable is `slightly-quietly', the `Z n' command
790 will go to the next group without confirmation.")
792 (defvar gnus-auto-select-same nil
793 "*If non-nil, select the next article with the same subject.")
795 (defvar gnus-summary-check-current nil
796 "*If non-nil, consider the current article when moving.
797 The \"unread\" movement commands will stay on the same line if the
798 current article is unread.")
800 (defvar gnus-auto-center-summary t
801 "*If non-nil, always center the current summary buffer.
802 In particular, if `vertical' do only vertical recentering. If non-nil
803 and non-`vertical', do both horizontal and vertical recentering.")
805 (defvar gnus-break-pages t
806 "*If non-nil, do page breaking on articles.
807 The page delimiter is specified by the `gnus-page-delimiter'
810 (defvar gnus-page-delimiter "^\^L"
811 "*Regexp describing what to use as article page delimiters.
812 The default value is \"^\^L\", which is a form linefeed at the
813 beginning of a line.")
815 (defvar gnus-use-full-window t
816 "*If non-nil, use the entire Emacs screen.")
818 (defvar gnus-window-configuration nil
819 "Obsolete variable. See `gnus-buffer-configuration'.")
821 (defvar gnus-window-min-width 2
822 "*Minimum width of Gnus buffers.")
824 (defvar gnus-window-min-height 1
825 "*Minimum height of Gnus buffers.")
827 (defvar gnus-buffer-configuration
831 (if gnus-carpal '(group-carpal 4))))
835 (if gnus-carpal '(summary-carpal 4))))
842 (if gnus-carpal '(summary-carpal 4))
844 (vertical ((height . 5) (width . 15)
846 (left . -1) (top . 1))
856 (if gnus-carpal '(summary-carpal 4))
857 (if gnus-use-trees '(tree 0.25))
862 (if gnus-carpal '(server-carpal 2))))
866 (if gnus-carpal '(browse-carpal 2))))
869 (message 1.0 point)))
872 (article 1.0 point)))
883 (edit-group 1.0 point)))
887 (edit-server 1.0 point)))
891 (edit-score 1.0 point)))
898 (message 1.0 point)))
901 (message 1.0 point)))
904 (message 1.0 point)))
908 (message 1.0 point)))
915 (if gnus-carpal '(summary-carpal 4))
916 ("*Shell Command Output*" 1.0)))
919 ("*Gnus Help Bug*" 0.5)
920 ("*Gnus Bug*" 1.0 point)))
924 (message 1.0 point))))
925 "Window configuration for all possible Gnus buffers.
926 This variable is a list of lists. Each of these lists has a NAME and
927 a RULE. The NAMEs are commonsense names like `group', which names a
928 rule used when displaying the group buffer; `summary', which names a
929 rule for what happens when you enter a group and do not display an
930 article buffer; and so on. See the value of this variable for a
931 complete list of NAMEs.
933 Each RULE is a list of vectors. The first element in this vector is
934 the name of the buffer to be displayed; the second element is the
935 percentage of the screen this buffer is to occupy (a number in the
936 0.0-0.99 range); the optional third element is `point', which should
937 be present to denote which buffer point is to go to after making this
938 buffer configuration.")
940 (defvar gnus-window-to-buffer
941 '((group . gnus-group-buffer)
942 (summary . gnus-summary-buffer)
943 (article . gnus-article-buffer)
944 (server . gnus-server-buffer)
945 (browse . "*Gnus Browse Server*")
946 (edit-group . gnus-group-edit-buffer)
947 (edit-server . gnus-server-edit-buffer)
948 (group-carpal . gnus-carpal-group-buffer)
949 (summary-carpal . gnus-carpal-summary-buffer)
950 (server-carpal . gnus-carpal-server-buffer)
951 (browse-carpal . gnus-carpal-browse-buffer)
952 (edit-score . gnus-score-edit-buffer)
953 (message . gnus-message-buffer)
954 (mail . gnus-message-buffer)
955 (post-news . gnus-message-buffer)
956 (faq . gnus-faq-buffer)
957 (picons . "*Picons*")
958 (tree . gnus-tree-buffer)
959 (info . gnus-info-buffer)
960 (article-copy . gnus-article-copy)
961 (draft . gnus-draft-buffer))
962 "Mapping from short symbols to buffer names or buffer variables.")
964 (defvar gnus-carpal nil
965 "*If non-nil, display clickable icons.")
967 (defvar gnus-subscribe-newsgroup-method 'gnus-subscribe-zombies
968 "*Function called with a group name when new group is detected.
969 A few pre-made functions are supplied: `gnus-subscribe-randomly'
970 inserts new groups at the beginning of the list of groups;
971 `gnus-subscribe-alphabetically' inserts new groups in strict
972 alphabetic order; `gnus-subscribe-hierarchically' inserts new groups
973 in hierarchical newsgroup order; `gnus-subscribe-interactively' asks
974 for your decision; `gnus-subscribe-killed' kills all new groups;
975 `gnus-subscribe-zombies' will make all new groups into zombies.")
977 ;; Suggested by a bug report by Hallvard B Furuseth.
978 ;; <h.b.furuseth@usit.uio.no>.
979 (defvar gnus-subscribe-options-newsgroup-method
980 (function gnus-subscribe-alphabetically)
981 "*This function is called to subscribe newsgroups mentioned on \"options -n\" lines.
982 If, for instance, you want to subscribe to all newsgroups in the
983 \"no\" and \"alt\" hierarchies, you'd put the following in your
986 options -n no.all alt.all
988 Gnus will the subscribe all new newsgroups in these hierarchies with
989 the subscription method in this variable.")
991 (defvar gnus-subscribe-hierarchical-interactive nil
992 "*If non-nil, Gnus will offer to subscribe hierarchically.
993 When a new hierarchy appears, Gnus will ask the user:
995 'alt.binaries': Do you want to subscribe to this hierarchy? ([d]ys):
997 If the user pressed `d', Gnus will descend the hierarchy, `y' will
998 subscribe to all newsgroups in the hierarchy and `s' will skip this
999 hierarchy in its entirety.")
1001 (defvar gnus-group-sort-function 'gnus-group-sort-by-alphabet
1002 "*Function used for sorting the group buffer.
1003 This function will be called with group info entries as the arguments
1004 for the groups to be sorted. Pre-made functions include
1005 `gnus-group-sort-by-alphabet', `gnus-group-sort-by-unread',
1006 `gnus-group-sort-by-level', `gnus-group-sort-by-score', and
1007 `gnus-group-sort-by-rank'.
1009 This variable can also be a list of sorting functions. In that case,
1010 the most significant sort function should be the last function in the
1013 ;; Mark variables suggested by Thomas Michanek
1014 ;; <Thomas.Michanek@telelogic.se>.
1015 (defvar gnus-unread-mark ?
1016 "*Mark used for unread articles.")
1017 (defvar gnus-ticked-mark ?!
1018 "*Mark used for ticked articles.")
1019 (defvar gnus-dormant-mark ??
1020 "*Mark used for dormant articles.")
1021 (defvar gnus-del-mark ?r
1022 "*Mark used for del'd articles.")
1023 (defvar gnus-read-mark ?R
1024 "*Mark used for read articles.")
1025 (defvar gnus-expirable-mark ?E
1026 "*Mark used for expirable articles.")
1027 (defvar gnus-killed-mark ?K
1028 "*Mark used for killed articles.")
1029 (defvar gnus-souped-mark ?F
1030 "*Mark used for killed articles.")
1031 (defvar gnus-kill-file-mark ?X
1032 "*Mark used for articles killed by kill files.")
1033 (defvar gnus-low-score-mark ?Y
1034 "*Mark used for articles with a low score.")
1035 (defvar gnus-catchup-mark ?C
1036 "*Mark used for articles that are caught up.")
1037 (defvar gnus-replied-mark ?A
1038 "*Mark used for articles that have been replied to.")
1039 (defvar gnus-cached-mark ?*
1040 "*Mark used for articles that are in the cache.")
1041 (defvar gnus-saved-mark ?S
1042 "*Mark used for articles that have been saved to.")
1043 (defvar gnus-process-mark ?#
1045 (defvar gnus-ancient-mark ?O
1046 "*Mark used for ancient articles.")
1047 (defvar gnus-sparse-mark ?Q
1048 "*Mark used for sparsely reffed articles.")
1049 (defvar gnus-canceled-mark ?G
1050 "*Mark used for canceled articles.")
1051 (defvar gnus-score-over-mark ?+
1052 "*Score mark used for articles with high scores.")
1053 (defvar gnus-score-below-mark ?-
1054 "*Score mark used for articles with low scores.")
1055 (defvar gnus-empty-thread-mark ?
1056 "*There is no thread under the article.")
1057 (defvar gnus-not-empty-thread-mark ?=
1058 "*There is a thread under the article.")
1060 (defvar gnus-view-pseudo-asynchronously nil
1061 "*If non-nil, Gnus will view pseudo-articles asynchronously.")
1063 (defvar gnus-view-pseudos nil
1064 "*If `automatic', pseudo-articles will be viewed automatically.
1065 If `not-confirm', pseudos will be viewed automatically, and the user
1066 will not be asked to confirm the command.")
1068 (defvar gnus-view-pseudos-separately t
1069 "*If non-nil, one pseudo-article will be created for each file to be viewed.
1070 If nil, all files that use the same viewing command will be given as a
1071 list of parameters to that command.")
1073 (defvar gnus-insert-pseudo-articles t
1074 "*If non-nil, insert pseudo-articles when decoding articles.")
1076 (defvar gnus-group-line-format "%M%S%p%P%5y: %(%g%)%l\n"
1077 "*Format of group lines.
1078 It works along the same lines as a normal formatting string,
1079 with some simple extensions.
1081 %M Only marked articles (character, \"*\" or \" \")
1082 %S Whether the group is subscribed (character, \"U\", \"K\", \"Z\" or \" \")
1083 %L Level of subscribedness (integer)
1084 %N Number of unread articles (integer)
1085 %I Number of dormant articles (integer)
1086 %i Number of ticked and dormant (integer)
1087 %T Number of ticked articles (integer)
1088 %R Number of read articles (integer)
1089 %t Total number of articles (integer)
1090 %y Number of unread, unticked articles (integer)
1091 %G Group name (string)
1092 %g Qualified group name (string)
1093 %D Group description (string)
1094 %s Select method (string)
1095 %o Moderated group (char, \"m\")
1096 %p Process mark (char)
1097 %O Moderated group (string, \"(m)\" or \"\")
1098 %P Topic indentation (string)
1099 %l Whether there are GroupLens predictions for this group (string)
1100 %n Select from where (string)
1101 %z A string that look like `<%s:%n>' if a foreign select method is used
1102 %u User defined specifier. The next character in the format string should
1103 be a letter. Gnus will call the function gnus-user-format-function-X,
1104 where X is the letter following %u. The function will be passed the
1105 current header as argument. The function should return a string, which
1106 will be inserted into the buffer just like information from any other
1109 Text between %( and %) will be highlighted with `gnus-mouse-face' when
1110 the mouse point move inside the area. There can only be one such area.
1112 Note that this format specification is not always respected. For
1113 reasons of efficiency, when listing killed groups, this specification
1114 is ignored altogether. If the spec is changed considerably, your
1115 output may end up looking strange when listing both alive and killed
1118 If you use %o or %O, reading the active file will be slower and quite
1119 a bit of extra memory will be used. %D will also worsen performance.
1120 Also note that if you change the format specification to include any
1121 of these specs, you must probably re-start Gnus to see them go into
1124 (defvar gnus-summary-line-format "%U%R%z%I%(%[%4L: %-20,20n%]%) %s\n"
1125 "*The format specification of the lines in the summary buffer.
1127 It works along the same lines as a normal formatting string,
1128 with some simple extensions.
1130 %N Article number, left padded with spaces (string)
1132 %s Subject if it is at the root of a thread, and \"\" otherwise (string)
1133 %n Name of the poster (string)
1134 %a Extracted name of the poster (string)
1135 %A Extracted address of the poster (string)
1136 %F Contents of the From: header (string)
1137 %x Contents of the Xref: header (string)
1138 %D Date of the article (string)
1139 %d Date of the article (string) in DD-MMM format
1140 %M Message-id of the article (string)
1141 %r References of the article (string)
1142 %c Number of characters in the article (integer)
1143 %L Number of lines in the article (integer)
1144 %I Indentation based on thread level (a string of spaces)
1145 %T A string with two possible values: 80 spaces if the article
1146 is on thread level two or larger and 0 spaces on level one
1147 %R \"A\" if this article has been replied to, \" \" otherwise (character)
1148 %U Status of this article (character, \"R\", \"K\", \"-\" or \" \")
1149 %[ Opening bracket (character, \"[\" or \"<\")
1150 %] Closing bracket (character, \"]\" or \">\")
1151 %> Spaces of length thread-level (string)
1152 %< Spaces of length (- 20 thread-level) (string)
1153 %i Article score (number)
1154 %z Article zcore (character)
1155 %t Number of articles under the current thread (number).
1156 %e Whether the thread is empty or not (character).
1157 %l GroupLens score (string).
1158 %u User defined specifier. The next character in the format string should
1159 be a letter. Gnus will call the function gnus-user-format-function-X,
1160 where X is the letter following %u. The function will be passed the
1161 current header as argument. The function should return a string, which
1162 will be inserted into the summary just like information from any other
1165 Text between %( and %) will be highlighted with `gnus-mouse-face'
1166 when the mouse point is placed inside the area. There can only be one
1169 The %U (status), %R (replied) and %z (zcore) specs have to be handled
1170 with care. For reasons of efficiency, Gnus will compute what column
1171 these characters will end up in, and \"hard-code\" that. This means that
1172 it is illegal to have these specs after a variable-length spec. Well,
1173 you might not be arrested, but your summary buffer will look strange,
1174 which is bad enough.
1176 The smart choice is to have these specs as for to the left as
1179 This restriction may disappear in later versions of Gnus.")
1181 (defvar gnus-summary-dummy-line-format
1183 "*The format specification for the dummy roots in the summary buffer.
1184 It works along the same lines as a normal formatting string,
1185 with some simple extensions.
1189 (defvar gnus-summary-mode-line-format "Gnus: %%b [%A] %Z"
1190 "*The format specification for the summary mode line.
1191 It works along the same lines as a normal formatting string,
1192 with some simple extensions:
1195 %p Unprefixed group name
1196 %A Current article number
1198 %U Number of unread articles in the group
1199 %e Number of unselected articles in the group
1200 %Z A string with unread/unselected article counts
1201 %g Shortish group name
1202 %S Subject of the current article
1203 %u User-defined spec
1204 %s Current score file name
1205 %d Number of dormant articles
1206 %r Number of articles that have been marked as read in this session
1207 %E Number of articles expunged by the score files")
1209 (defvar gnus-article-mode-line-format "Gnus: %%b %S"
1210 "*The format specification for the article mode line.
1211 See `gnus-summary-mode-line-format' for a closer description.")
1213 (defvar gnus-group-mode-line-format "Gnus: %%b {%M%:%S}"
1214 "*The format specification for the group mode line.
1215 It works along the same lines as a normal formatting string,
1216 with some simple extensions:
1218 %S The native news server.
1219 %M The native select method.
1220 %: \":\" if %S isn't \"\".")
1222 (defvar gnus-valid-select-methods
1223 '(("nntp" post address prompt-address)
1224 ("nnspool" post address)
1225 ("nnvirtual" post-mail virtual prompt-address)
1226 ("nnmbox" mail respool address)
1227 ("nnml" mail respool address)
1228 ("nnmh" mail respool address)
1229 ("nndir" post-mail prompt-address address)
1230 ("nneething" none address prompt-address)
1231 ("nndoc" none address prompt-address)
1232 ("nnbabyl" mail address respool)
1233 ("nnkiboze" post address virtual)
1234 ("nnsoup" post-mail address)
1235 ("nndraft" post-mail)
1236 ("nnfolder" mail respool address))
1237 "An alist of valid select methods.
1238 The first element of each list lists should be a string with the name
1239 of the select method. The other elements may be be the category of
1240 this method (ie. `post', `mail', `none' or whatever) or other
1241 properties that this method has (like being respoolable).
1242 If you implement a new select method, all you should have to change is
1243 this variable. I think.")
1245 (defvar gnus-updated-mode-lines '(group article summary tree)
1246 "*List of buffers that should update their mode lines.
1247 The list may contain the symbols `group', `article' and `summary'. If
1248 the corresponding symbol is present, Gnus will keep that mode line
1249 updated with information that may be pertinent.
1250 If this variable is nil, screen refresh may be quicker.")
1252 ;; Added by Keinonen Kari <kk85613@cs.tut.fi>.
1253 (defvar gnus-mode-non-string-length nil
1254 "*Max length of mode-line non-string contents.
1255 If this is nil, Gnus will take space as is needed, leaving the rest
1256 of the modeline intact.")
1259 ;(defvar gnus-mouse-face 'highlight
1260 ; "*Face used for mouse highlighting in Gnus.
1261 ;No mouse highlights will be done if `gnus-visual' is nil.")
1263 (defvar gnus-summary-mark-below 0
1264 "*Mark all articles with a score below this variable as read.
1265 This variable is local to each summary buffer and usually set by the
1268 (defvar gnus-article-sort-functions '(gnus-article-sort-by-number)
1269 "*List of functions used for sorting articles in the summary buffer.
1270 This variable is only used when not using a threaded display.")
1272 (defvar gnus-thread-sort-functions '(gnus-thread-sort-by-number)
1273 "*List of functions used for sorting threads in the summary buffer.
1274 By default, threads are sorted by article number.
1276 Each function takes two threads and return non-nil if the first thread
1277 should be sorted before the other. If you use more than one function,
1278 the primary sort function should be the last. You should probably
1279 always include `gnus-thread-sort-by-number' in the list of sorting
1280 functions -- preferably first.
1282 Ready-mady functions include `gnus-thread-sort-by-number',
1283 `gnus-thread-sort-by-author', `gnus-thread-sort-by-subject',
1284 `gnus-thread-sort-by-date', `gnus-thread-sort-by-score' and
1285 `gnus-thread-sort-by-total-score' (see `gnus-thread-score-function').")
1287 (defvar gnus-thread-score-function '+
1288 "*Function used for calculating the total score of a thread.
1290 The function is called with the scores of the article and each
1291 subthread and should then return the score of the thread.
1293 Some functions you can use are `+', `max', or `min'.")
1295 (defvar gnus-summary-expunge-below nil
1296 "All articles that have a score less than this variable will be expunged.")
1298 (defvar gnus-thread-expunge-below nil
1299 "All threads that have a total score less than this variable will be expunged.
1300 See `gnus-thread-score-function' for en explanation of what a
1301 \"thread score\" is.")
1303 (defvar gnus-auto-subscribed-groups
1304 "^nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl"
1305 "*All new groups that match this regexp will be subscribed automatically.
1306 Note that this variable only deals with new groups. It has no effect
1307 whatsoever on old groups.")
1309 (defvar gnus-options-subscribe nil
1310 "*All new groups matching this regexp will be subscribed unconditionally.
1311 Note that this variable deals only with new newsgroups. This variable
1312 does not affect old newsgroups.")
1314 (defvar gnus-options-not-subscribe nil
1315 "*All new groups matching this regexp will be ignored.
1316 Note that this variable deals only with new newsgroups. This variable
1317 does not affect old (already subscribed) newsgroups.")
1319 (defvar gnus-auto-expirable-newsgroups nil
1320 "*Groups in which to automatically mark read articles as expirable.
1321 If non-nil, this should be a regexp that should match all groups in
1322 which to perform auto-expiry. This only makes sense for mail groups.")
1324 (defvar gnus-total-expirable-newsgroups nil
1325 "*Groups in which to perform expiry of all read articles.
1326 Use with extreme caution. All groups that match this regexp will be
1327 expiring - which means that all read articles will be deleted after
1328 (say) one week. (This only goes for mail groups and the like, of
1331 (defvar gnus-group-uncollapsed-levels 1
1332 "Number of group name elements to leave alone when making a short group name.")
1334 (defvar gnus-hidden-properties '(invisible t intangible t)
1335 "Property list to use for hiding text.")
1337 (defvar gnus-modtime-botch nil
1338 "*Non-nil means .newsrc should be deleted prior to save.
1339 Its use is due to the bogus appearance that .newsrc was modified on
1344 (defvar gnus-group-mode-hook nil
1345 "*A hook for Gnus group mode.")
1347 (defvar gnus-summary-mode-hook nil
1348 "*A hook for Gnus summary mode.
1349 This hook is run before any variables are set in the summary buffer.")
1351 (defvar gnus-article-mode-hook nil
1352 "*A hook for Gnus article mode.")
1354 (defvar gnus-summary-prepare-exit-hook nil
1355 "*A hook called when preparing to exit from the summary buffer.
1356 It calls `gnus-summary-expire-articles' by default.")
1357 (add-hook 'gnus-summary-prepare-exit-hook 'gnus-summary-expire-articles)
1359 (defvar gnus-summary-exit-hook nil
1360 "*A hook called on exit from the summary buffer.")
1362 (defvar gnus-group-catchup-group-hook nil
1363 "*A hook run when catching up a group from the group buffer.")
1365 (defvar gnus-open-server-hook nil
1366 "*A hook called just before opening connection to the news server.")
1368 (defvar gnus-load-hook nil
1369 "*A hook run while Gnus is loaded.")
1371 (defvar gnus-startup-hook nil
1372 "*A hook called at startup.
1373 This hook is called after Gnus is connected to the NNTP server.")
1375 (defvar gnus-get-new-news-hook nil
1376 "*A hook run just before Gnus checks for new news.")
1378 (defvar gnus-after-getting-new-news-hook nil
1379 "*A hook run after Gnus checks for new news.")
1381 (defvar gnus-group-prepare-function 'gnus-group-prepare-flat
1382 "*A function that is called to generate the group buffer.
1383 The function is called with three arguments: The first is a number;
1384 all group with a level less or equal to that number should be listed,
1385 if the second is non-nil, empty groups should also be displayed. If
1386 the third is non-nil, it is a number. No groups with a level lower
1387 than this number should be displayed.
1389 The only current function implemented is `gnus-group-prepare-flat'.")
1391 (defvar gnus-group-prepare-hook nil
1392 "*A hook called after the group buffer has been generated.
1393 If you want to modify the group buffer, you can use this hook.")
1395 (defvar gnus-summary-prepare-hook nil
1396 "*A hook called after the summary buffer has been generated.
1397 If you want to modify the summary buffer, you can use this hook.")
1399 (defvar gnus-summary-generate-hook nil
1400 "*A hook run just before generating the summary buffer.
1401 This hook is commonly used to customize threading variables and the
1404 (defvar gnus-article-prepare-hook nil
1405 "*A hook called after an article has been prepared in the article buffer.
1406 If you want to run a special decoding program like nkf, use this hook.")
1408 ;(defvar gnus-article-display-hook nil
1409 ; "*A hook called after the article is displayed in the article buffer.
1410 ;The hook is designed to change the contents of the article
1411 ;buffer. Typical functions that this hook may contain are
1412 ;`gnus-article-hide-headers' (hide selected headers),
1413 ;`gnus-article-maybe-highlight' (perform fancy article highlighting),
1414 ;`gnus-article-hide-signature' (hide signature) and
1415 ;`gnus-article-treat-overstrike' (turn \"^H_\" into bold characters).")
1416 ;(add-hook 'gnus-article-display-hook 'gnus-article-hide-headers-if-wanted)
1417 ;(add-hook 'gnus-article-display-hook 'gnus-article-treat-overstrike)
1418 ;(add-hook 'gnus-article-display-hook 'gnus-article-maybe-highlight)
1420 (defvar gnus-article-x-face-command
1421 "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | xv -quit -"
1422 "String or function to be executed to display an X-Face header.
1423 If it is a string, the command will be executed in a sub-shell
1424 asynchronously. The compressed face will be piped to this command.")
1426 (defvar gnus-article-x-face-too-ugly nil
1427 "Regexp matching posters whose face shouldn't be shown automatically.")
1429 (defvar gnus-select-group-hook nil
1430 "*A hook called when a newsgroup is selected.
1432 If you'd like to simplify subjects like the
1433 `gnus-summary-next-same-subject' command does, you can use the
1436 (setq gnus-select-group-hook
1439 (mapcar (lambda (header)
1440 (mail-header-set-subject
1442 (gnus-simplify-subject
1443 (mail-header-subject header) 're-only)))
1444 gnus-newsgroup-headers))))")
1446 (defvar gnus-select-article-hook nil
1447 "*A hook called when an article is selected.")
1449 (defvar gnus-apply-kill-hook '(gnus-apply-kill-file)
1450 "*A hook called to apply kill files to a group.
1451 This hook is intended to apply a kill file to the selected newsgroup.
1452 The function `gnus-apply-kill-file' is called by default.
1454 Since a general kill file is too heavy to use only for a few
1455 newsgroups, I recommend you to use a lighter hook function. For
1456 example, if you'd like to apply a kill file to articles which contains
1457 a string `rmgroup' in subject in newsgroup `control', you can use the
1460 (setq gnus-apply-kill-hook
1463 (cond ((string-match \"control\" gnus-newsgroup-name)
1464 (gnus-kill \"Subject\" \"rmgroup\")
1465 (gnus-expunge \"X\"))))))")
1467 (defvar gnus-visual-mark-article-hook
1468 (list 'gnus-highlight-selected-summary)
1469 "*Hook run after selecting an article in the summary buffer.
1470 It is meant to be used for highlighting the article in some way. It
1471 is not run if `gnus-visual' is nil.")
1473 (defvar gnus-parse-headers-hook nil
1474 "*A hook called before parsing the headers.")
1475 (add-hook 'gnus-parse-headers-hook 'gnus-decode-rfc1522)
1477 (defvar gnus-exit-group-hook nil
1478 "*A hook called when exiting (not quitting) summary mode.")
1480 (defvar gnus-suspend-gnus-hook nil
1481 "*A hook called when suspending (not exiting) Gnus.")
1483 (defvar gnus-exit-gnus-hook nil
1484 "*A hook called when exiting Gnus.")
1486 (defvar gnus-after-exiting-gnus-hook nil
1487 "*A hook called after exiting Gnus.")
1489 (defvar gnus-save-newsrc-hook nil
1490 "*A hook called before saving any of the newsrc files.")
1492 (defvar gnus-save-quick-newsrc-hook nil
1493 "*A hook called just before saving the quick newsrc file.
1494 Can be used to turn version control on or off.")
1496 (defvar gnus-save-standard-newsrc-hook nil
1497 "*A hook called just before saving the standard newsrc file.
1498 Can be used to turn version control on or off.")
1500 (defvar gnus-summary-update-hook
1501 (list 'gnus-summary-highlight-line)
1502 "*A hook called when a summary line is changed.
1503 The hook will not be called if `gnus-visual' is nil.
1505 The default function `gnus-summary-highlight-line' will
1506 highlight the line according to the `gnus-summary-highlight'
1509 (defvar gnus-group-update-hook '(gnus-group-highlight-line)
1510 "*A hook called when a group line is changed.
1511 The hook will not be called if `gnus-visual' is nil.
1513 The default function `gnus-group-highlight-line' will
1514 highlight the line according to the `gnus-group-highlight'
1517 (defvar gnus-mark-article-hook '(gnus-summary-mark-read-and-unread-as-read)
1518 "*A hook called when an article is selected for the first time.
1519 The hook is intended to mark an article as read (or unread)
1520 automatically when it is selected.")
1522 (defvar gnus-group-change-level-function nil
1523 "Function run when a group level is changed.
1524 It is called with three parameters -- GROUP, LEVEL and OLDLEVEL.")
1526 ;; Remove any hilit infestation.
1527 (add-hook 'gnus-startup-hook
1529 (remove-hook 'gnus-summary-prepare-hook
1530 'hilit-rehighlight-buffer-quietly)
1531 (remove-hook 'gnus-summary-prepare-hook 'hilit-install-line-hooks)
1532 (setq gnus-mark-article-hook
1533 '(gnus-summary-mark-read-and-unread-as-read))
1534 (remove-hook 'gnus-article-prepare-hook
1535 'hilit-rehighlight-buffer-quietly)))
1538 ;; Internal variables
1540 (defvar gnus-tree-buffer "*Tree*"
1541 "Buffer where Gnus thread trees are displayed.")
1544 (defvar gnus-use-generic-from nil)
1546 (defvar gnus-thread-indent-array nil)
1547 (defvar gnus-thread-indent-array-level gnus-thread-indent-level)
1549 (defvar gnus-newsrc-file-version nil)
1551 (defvar gnus-method-history nil)
1552 ;; Variable holding the user answers to all method prompts.
1554 (defvar gnus-group-history nil)
1555 ;; Variable holding the user answers to all group prompts.
1557 (defvar gnus-server-alist nil
1558 "List of available servers.")
1560 (defvar gnus-group-indentation-function nil)
1562 (defvar gnus-topic-indentation "") ;; Obsolete variable.
1564 (defvar gnus-goto-missing-group-function nil)
1566 (defvar gnus-override-subscribe-method nil)
1568 (defvar gnus-group-goto-next-group-function nil
1569 "Function to override finding the next group after listing groups.")
1571 (defconst gnus-article-mark-lists
1572 '((marked . tick) (replied . reply)
1573 (expirable . expire) (killed . killed)
1574 (bookmarks . bookmark) (dormant . dormant)
1575 (scored . score) (saved . save)
1579 ;; Avoid highlighting in kill files.
1580 (defvar gnus-summary-inhibit-highlight nil)
1581 (defvar gnus-newsgroup-selected-overlay nil)
1583 (defvar gnus-inhibit-hiding nil)
1584 (defvar gnus-group-indentation "")
1585 (defvar gnus-inhibit-limiting nil)
1586 (defvar gnus-created-frames nil)
1588 (defvar gnus-article-mode-map nil)
1589 (defvar gnus-dribble-buffer nil)
1590 (defvar gnus-headers-retrieved-by nil)
1591 (defvar gnus-article-reply nil)
1592 (defvar gnus-override-method nil)
1593 (defvar gnus-article-check-size nil)
1595 (defvar gnus-current-score-file nil)
1596 (defvar gnus-newsgroup-adaptive-score-file nil)
1597 (defvar gnus-scores-exclude-files nil)
1599 (defvar gnus-opened-servers nil)
1601 (defvar gnus-current-move-group nil)
1602 (defvar gnus-current-copy-group nil)
1603 (defvar gnus-current-crosspost-group nil)
1605 (defvar gnus-newsgroup-dependencies nil)
1606 (defvar gnus-newsgroup-async nil)
1607 (defconst gnus-group-edit-buffer "*Gnus edit newsgroup*")
1609 (defvar gnus-newsgroup-adaptive nil)
1611 (defvar gnus-summary-display-table nil)
1612 (defvar gnus-summary-display-article-function nil)
1614 (defvar gnus-summary-highlight-line-function nil
1615 "Function called after highlighting a summary line.")
1617 (defvar gnus-group-line-format-alist
1618 `((?M gnus-tmp-marked-mark ?c)
1619 (?S gnus-tmp-subscribed ?c)
1620 (?L gnus-tmp-level ?d)
1621 (?N (cond ((eq number t) "*" )
1625 (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked)))
1626 (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))))))
1628 (?R gnus-tmp-number-of-read ?s)
1629 (?t gnus-tmp-number-total ?d)
1630 (?y gnus-tmp-number-of-unread ?s)
1631 (?I (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked))) ?d)
1632 (?T (gnus-range-length (cdr (assq 'tick gnus-tmp-marked))) ?d)
1633 (?i (+ (gnus-range-length (cdr (assq 'dormant gnus-tmp-marked)))
1634 (gnus-range-length (cdr (assq 'tick gnus-tmp-marked)))) ?d)
1635 (?g gnus-tmp-group ?s)
1636 (?G gnus-tmp-qualified-group ?s)
1637 (?c (gnus-short-group-name gnus-tmp-group) ?s)
1638 (?D gnus-tmp-newsgroup-description ?s)
1639 (?o gnus-tmp-moderated ?c)
1640 (?O gnus-tmp-moderated-string ?s)
1641 (?p gnus-tmp-process-marked ?c)
1642 (?s gnus-tmp-news-server ?s)
1643 (?n gnus-tmp-news-method ?s)
1644 (?P gnus-group-indentation ?s)
1645 (?l gnus-tmp-grouplens ?s)
1646 (?z gnus-tmp-news-method-string ?s)
1647 (?u gnus-tmp-user-defined ?s)))
1649 (defvar gnus-summary-line-format-alist
1650 `((?N ,(macroexpand '(mail-header-number gnus-tmp-header)) ?d)
1651 (?S ,(macroexpand '(mail-header-subject gnus-tmp-header)) ?s)
1652 (?s gnus-tmp-subject-or-nil ?s)
1653 (?n gnus-tmp-name ?s)
1654 (?A (car (cdr (funcall gnus-extract-address-components gnus-tmp-from)))
1656 (?a (or (car (funcall gnus-extract-address-components gnus-tmp-from))
1658 (?F gnus-tmp-from ?s)
1659 (?x ,(macroexpand '(mail-header-xref gnus-tmp-header)) ?s)
1660 (?D ,(macroexpand '(mail-header-date gnus-tmp-header)) ?s)
1661 (?d (gnus-dd-mmm (mail-header-date gnus-tmp-header)) ?s)
1662 (?M ,(macroexpand '(mail-header-id gnus-tmp-header)) ?s)
1663 (?r ,(macroexpand '(mail-header-references gnus-tmp-header)) ?s)
1664 (?c (or (mail-header-chars gnus-tmp-header) 0) ?d)
1665 (?L gnus-tmp-lines ?d)
1666 (?I gnus-tmp-indentation ?s)
1667 (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s)
1668 (?R gnus-tmp-replied ?c)
1669 (?\[ gnus-tmp-opening-bracket ?c)
1670 (?\] gnus-tmp-closing-bracket ?c)
1671 (?\> (make-string gnus-tmp-level ? ) ?s)
1672 (?\< (make-string (max 0 (- 20 gnus-tmp-level)) ? ) ?s)
1673 (?i gnus-tmp-score ?d)
1674 (?z gnus-tmp-score-char ?c)
1675 (?l (bbb-grouplens-score gnus-tmp-header) ?s)
1676 (?V (gnus-thread-total-score (and (boundp 'thread) (car thread))) ?d)
1677 (?U gnus-tmp-unread ?c)
1678 (?t (gnus-summary-number-of-articles-in-thread
1679 (and (boundp 'thread) (car thread)) gnus-tmp-level)
1681 (?e (gnus-summary-number-of-articles-in-thread
1682 (and (boundp 'thread) (car thread)) gnus-tmp-level t)
1684 (?u gnus-tmp-user-defined ?s))
1685 "An alist of format specifications that can appear in summary lines,
1686 and what variables they correspond with, along with the type of the
1687 variable (string, integer, character, etc).")
1689 (defvar gnus-summary-dummy-line-format-alist
1690 `((?S gnus-tmp-subject ?s)
1691 (?N gnus-tmp-number ?d)
1692 (?u gnus-tmp-user-defined ?s)))
1694 (defvar gnus-summary-mode-line-format-alist
1695 `((?G gnus-tmp-group-name ?s)
1696 (?g (gnus-short-group-name gnus-tmp-group-name) ?s)
1697 (?p (gnus-group-real-name gnus-tmp-group-name) ?s)
1698 (?A gnus-tmp-article-number ?d)
1699 (?Z gnus-tmp-unread-and-unselected ?s)
1700 (?V gnus-version ?s)
1701 (?U gnus-tmp-unread ?d)
1702 (?S gnus-tmp-subject ?s)
1703 (?e gnus-tmp-unselected ?d)
1704 (?u gnus-tmp-user-defined ?s)
1705 (?d (length gnus-newsgroup-dormant) ?d)
1706 (?t (length gnus-newsgroup-marked) ?d)
1707 (?r (length gnus-newsgroup-reads) ?d)
1708 (?E gnus-newsgroup-expunged-tally ?d)
1709 (?s (gnus-current-score-file-nondirectory) ?s)))
1711 (defvar gnus-article-mode-line-format-alist
1712 gnus-summary-mode-line-format-alist)
1714 (defvar gnus-group-mode-line-format-alist
1715 `((?S gnus-tmp-news-server ?s)
1716 (?M gnus-tmp-news-method ?s)
1717 (?u gnus-tmp-user-defined ?s)
1718 (?: gnus-tmp-colon ?s)))
1720 (defvar gnus-have-read-active-file nil)
1722 (defconst gnus-maintainer
1723 "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)"
1724 "The mail address of the Gnus maintainers.")
1726 (defconst gnus-version-number "5.2.2"
1727 "Version number for this version of Gnus.")
1729 (defconst gnus-version (format "Gnus v%s" gnus-version-number)
1730 "Version string for this version of Gnus.")
1732 (defvar gnus-info-nodes
1733 '((gnus-group-mode "(gnus)The Group Buffer")
1734 (gnus-summary-mode "(gnus)The Summary Buffer")
1735 (gnus-article-mode "(gnus)The Article Buffer"))
1736 "Assoc list of major modes and related Info nodes.")
1738 (defvar gnus-group-buffer "*Group*")
1739 (defvar gnus-summary-buffer "*Summary*")
1740 (defvar gnus-article-buffer "*Article*")
1741 (defvar gnus-server-buffer "*Server*")
1743 (defvar gnus-work-buffer " *gnus work*")
1745 (defvar gnus-original-article-buffer " *Original Article*")
1746 (defvar gnus-original-article nil)
1748 (defvar gnus-buffer-list nil
1749 "Gnus buffers that should be killed on exit.")
1751 (defvar gnus-slave nil
1752 "Whether this Gnus is a slave or not.")
1754 (defvar gnus-variable-list
1755 '(gnus-newsrc-options gnus-newsrc-options-n
1756 gnus-newsrc-last-checked-date
1757 gnus-newsrc-alist gnus-server-alist
1758 gnus-killed-list gnus-zombie-list
1759 gnus-topic-topology gnus-topic-alist
1761 "Gnus variables saved in the quick startup file.")
1763 (defvar gnus-newsrc-options nil
1764 "Options line in the .newsrc file.")
1766 (defvar gnus-newsrc-options-n nil
1767 "List of regexps representing groups to be subscribed/ignored unconditionally.")
1769 (defvar gnus-newsrc-last-checked-date nil
1770 "Date Gnus last asked server for new newsgroups.")
1772 (defvar gnus-topic-topology nil
1773 "The complete topic hierarchy.")
1775 (defvar gnus-topic-alist nil
1776 "The complete topic-group alist.")
1778 (defvar gnus-newsrc-alist nil
1779 "Assoc list of read articles.
1780 gnus-newsrc-hashtb should be kept so that both hold the same information.")
1782 (defvar gnus-newsrc-hashtb nil
1783 "Hashtable of gnus-newsrc-alist.")
1785 (defvar gnus-killed-list nil
1786 "List of killed newsgroups.")
1788 (defvar gnus-killed-hashtb nil
1789 "Hash table equivalent of gnus-killed-list.")
1791 (defvar gnus-zombie-list nil
1792 "List of almost dead newsgroups.")
1794 (defvar gnus-description-hashtb nil
1795 "Descriptions of newsgroups.")
1797 (defvar gnus-list-of-killed-groups nil
1798 "List of newsgroups that have recently been killed by the user.")
1800 (defvar gnus-active-hashtb nil
1801 "Hashtable of active articles.")
1803 (defvar gnus-moderated-list nil
1804 "List of moderated newsgroups.")
1806 (defvar gnus-group-marked nil)
1808 (defvar gnus-current-startup-file nil
1809 "Startup file for the current host.")
1811 (defvar gnus-last-search-regexp nil
1812 "Default regexp for article search command.")
1814 (defvar gnus-last-shell-command nil
1815 "Default shell command on article.")
1817 (defvar gnus-current-select-method nil
1818 "The current method for selecting a newsgroup.")
1820 (defvar gnus-group-list-mode nil)
1822 (defvar gnus-article-internal-prepare-hook nil)
1824 (defvar gnus-newsgroup-name nil)
1825 (defvar gnus-newsgroup-begin nil)
1826 (defvar gnus-newsgroup-end nil)
1827 (defvar gnus-newsgroup-last-rmail nil)
1828 (defvar gnus-newsgroup-last-mail nil)
1829 (defvar gnus-newsgroup-last-folder nil)
1830 (defvar gnus-newsgroup-last-file nil)
1831 (defvar gnus-newsgroup-auto-expire nil)
1832 (defvar gnus-newsgroup-active nil)
1834 (defvar gnus-newsgroup-data nil)
1835 (defvar gnus-newsgroup-data-reverse nil)
1836 (defvar gnus-newsgroup-limit nil)
1837 (defvar gnus-newsgroup-limits nil)
1839 (defvar gnus-newsgroup-unreads nil
1840 "List of unread articles in the current newsgroup.")
1842 (defvar gnus-newsgroup-unselected nil
1843 "List of unselected unread articles in the current newsgroup.")
1845 (defvar gnus-newsgroup-reads nil
1846 "Alist of read articles and article marks in the current newsgroup.")
1848 (defvar gnus-newsgroup-expunged-tally nil)
1850 (defvar gnus-newsgroup-marked nil
1851 "List of ticked articles in the current newsgroup (a subset of unread art).")
1853 (defvar gnus-newsgroup-killed nil
1854 "List of ranges of articles that have been through the scoring process.")
1856 (defvar gnus-newsgroup-cached nil
1857 "List of articles that come from the article cache.")
1859 (defvar gnus-newsgroup-saved nil
1860 "List of articles that have been saved.")
1862 (defvar gnus-newsgroup-kill-headers nil)
1864 (defvar gnus-newsgroup-replied nil
1865 "List of articles that have been replied to in the current newsgroup.")
1867 (defvar gnus-newsgroup-expirable nil
1868 "List of articles in the current newsgroup that can be expired.")
1870 (defvar gnus-newsgroup-processable nil
1871 "List of articles in the current newsgroup that can be processed.")
1873 (defvar gnus-newsgroup-bookmarks nil
1874 "List of articles in the current newsgroup that have bookmarks.")
1876 (defvar gnus-newsgroup-dormant nil
1877 "List of dormant articles in the current newsgroup.")
1879 (defvar gnus-newsgroup-scored nil
1880 "List of scored articles in the current newsgroup.")
1882 (defvar gnus-newsgroup-headers nil
1883 "List of article headers in the current newsgroup.")
1885 (defvar gnus-newsgroup-threads nil)
1887 (defvar gnus-newsgroup-prepared nil
1888 "Whether the current group has been prepared properly.")
1890 (defvar gnus-newsgroup-ancient nil
1891 "List of `gnus-fetch-old-headers' articles in the current newsgroup.")
1893 (defvar gnus-newsgroup-sparse nil)
1895 (defvar gnus-current-article nil)
1896 (defvar gnus-article-current nil)
1897 (defvar gnus-current-headers nil)
1898 (defvar gnus-have-all-headers nil)
1899 (defvar gnus-last-article nil)
1900 (defvar gnus-newsgroup-history nil)
1901 (defvar gnus-current-kill-article nil)
1903 ;; Save window configuration.
1904 (defvar gnus-prev-winconf nil)
1906 (defvar gnus-summary-mark-positions nil)
1907 (defvar gnus-group-mark-positions nil)
1909 (defvar gnus-reffed-article-number nil)
1911 ;;; Let the byte-compiler know that we know about this variable.
1912 (defvar rmail-default-rmail-file)
1914 (defvar gnus-cache-removable-articles nil)
1916 (defvar gnus-dead-summary nil)
1918 (defconst gnus-summary-local-variables
1919 '(gnus-newsgroup-name
1920 gnus-newsgroup-begin gnus-newsgroup-end
1921 gnus-newsgroup-last-rmail gnus-newsgroup-last-mail
1922 gnus-newsgroup-last-folder gnus-newsgroup-last-file
1923 gnus-newsgroup-auto-expire gnus-newsgroup-unreads
1924 gnus-newsgroup-unselected gnus-newsgroup-marked
1925 gnus-newsgroup-reads gnus-newsgroup-saved
1926 gnus-newsgroup-replied gnus-newsgroup-expirable
1927 gnus-newsgroup-processable gnus-newsgroup-killed
1928 gnus-newsgroup-bookmarks gnus-newsgroup-dormant
1929 gnus-newsgroup-headers gnus-newsgroup-threads
1930 gnus-newsgroup-prepared gnus-summary-highlight-line-function
1931 gnus-current-article gnus-current-headers gnus-have-all-headers
1932 gnus-last-article gnus-article-internal-prepare-hook
1933 gnus-newsgroup-dependencies gnus-newsgroup-selected-overlay
1934 gnus-newsgroup-scored gnus-newsgroup-kill-headers
1935 gnus-newsgroup-async gnus-thread-expunge-below
1936 gnus-score-alist gnus-current-score-file gnus-summary-expunge-below
1937 (gnus-summary-mark-below . 0)
1938 gnus-newsgroup-active gnus-scores-exclude-files
1939 gnus-newsgroup-history gnus-newsgroup-ancient
1940 gnus-newsgroup-sparse
1941 (gnus-newsgroup-adaptive . gnus-use-adaptive-scoring)
1942 gnus-newsgroup-adaptive-score-file
1943 (gnus-newsgroup-expunged-tally . 0)
1944 gnus-cache-removable-articles gnus-newsgroup-cached
1945 gnus-newsgroup-data gnus-newsgroup-data-reverse
1946 gnus-newsgroup-limit gnus-newsgroup-limits)
1947 "Variables that are buffer-local to the summary buffers.")
1949 (defconst gnus-bug-message
1950 "Sending a bug report to the Gnus Towers.
1951 ========================================
1953 The buffer below is a mail buffer. When you press `C-c C-c', it will
1954 be sent to the Gnus Bug Exterminators.
1956 At the bottom of the buffer you'll see lots of variable settings.
1957 Please do not delete those. They will tell the Bug People what your
1958 environment is, so that it will be easier to locate the bugs.
1960 If you have found a bug that makes Emacs go \"beep\", set
1961 debug-on-error to t (`M-x set-variable RET debug-on-error RET t RET')
1962 and include the backtrace in your bug report.
1964 Please describe the bug in annoying, painstaking detail.
1966 Thank you for your help in stamping out bugs.
1969 ;;; End of variables.
1971 ;; Define some autoload functions Gnus might use.
1974 ;; This little mapcar goes through the list below and marks the
1975 ;; symbols in question as autoloaded functions.
1978 (let ((interactive (nth 1 (memq ':interactive package))))
1982 (when (consp function)
1983 (setq keymap (car (memq 'keymap function)))
1984 (setq function (car function)))
1985 (autoload function (car package) nil interactive keymap)))
1986 (if (eq (nth 1 package) ':interactive)
1989 '(("metamail" metamail-buffer)
1990 ("info" Info-goto-node)
1991 ("hexl" hexl-hex-string-to-integer)
1992 ("pp" pp pp-to-string pp-eval-expression)
1993 ("mail-extr" mail-extract-address-components)
1994 ("nnmail" nnmail-split-fancy nnmail-article-group)
1995 ("nnvirtual" nnvirtual-catchup-group)
1996 ("timezone" timezone-make-date-arpa-standard timezone-fix-time
1997 timezone-make-sortable-date timezone-make-time-string)
1998 ("sendmail" mail-position-on-field mail-setup)
1999 ("rmailout" rmail-output)
2000 ("rnewspost" news-mail-other-window news-reply-yank-original
2001 news-caesar-buffer-body)
2002 ("rmail" rmail-insert-rmail-file-header rmail-count-new-messages
2004 ("gnus-soup" :interactive t
2005 gnus-group-brew-soup gnus-brew-soup gnus-soup-add-article
2006 gnus-soup-send-replies gnus-soup-save-areas gnus-soup-pack-packet)
2007 ("nnsoup" nnsoup-pack-replies)
2008 ("gnus-scomo" :interactive t gnus-score-mode)
2009 ("gnus-mh" gnus-mh-mail-setup gnus-summary-save-article-folder
2010 gnus-Folder-save-name gnus-folder-save-name)
2011 ("gnus-mh" :interactive t gnus-summary-save-in-folder)
2012 ("gnus-vis" gnus-group-make-menu-bar gnus-summary-make-menu-bar
2013 gnus-server-make-menu-bar gnus-article-make-menu-bar
2014 gnus-browse-make-menu-bar gnus-highlight-selected-summary
2015 gnus-summary-highlight-line gnus-carpal-setup-buffer
2016 gnus-group-highlight-line
2017 gnus-article-add-button gnus-insert-next-page-button
2018 gnus-insert-prev-page-button gnus-visual-turn-off-edit-menu)
2019 ("gnus-vis" :interactive t
2020 gnus-article-push-button gnus-article-press-button
2021 gnus-article-highlight gnus-article-highlight-some
2022 gnus-article-highlight-headers gnus-article-highlight-signature
2023 gnus-article-add-buttons gnus-article-add-buttons-to-head
2024 gnus-article-next-button gnus-article-prev-button)
2025 ("gnus-demon" gnus-demon-add-nocem gnus-demon-add-scanmail
2026 gnus-demon-add-disconnection gnus-demon-add-handler
2027 gnus-demon-remove-handler)
2028 ("gnus-demon" :interactive t
2029 gnus-demon-init gnus-demon-cancel)
2030 ("gnus-salt" gnus-highlight-selected-tree gnus-possibly-generate-tree
2031 gnus-tree-open gnus-tree-close)
2032 ("gnus-nocem" gnus-nocem-scan-groups gnus-nocem-close
2033 gnus-nocem-unwanted-article-p)
2034 ("gnus-srvr" gnus-enter-server-buffer gnus-server-set-info)
2035 ("gnus-srvr" gnus-browse-foreign-server)
2036 ("gnus-cite" :interactive t
2037 gnus-article-highlight-citation gnus-article-hide-citation-maybe
2038 gnus-article-hide-citation gnus-article-fill-cited-article
2039 gnus-article-hide-citation-in-followups)
2040 ("gnus-kill" gnus-kill gnus-apply-kill-file-internal
2041 gnus-kill-file-edit-file gnus-kill-file-raise-followups-to-author
2042 gnus-execute gnus-expunge)
2043 ("gnus-cache" gnus-cache-possibly-enter-article gnus-cache-save-buffers
2044 gnus-cache-possibly-remove-articles gnus-cache-request-article
2045 gnus-cache-retrieve-headers gnus-cache-possibly-alter-active
2046 gnus-cache-enter-remove-article gnus-cached-article-p
2047 gnus-cache-open gnus-cache-close gnus-cache-update-article)
2048 ("gnus-cache" :interactive t gnus-jog-cache gnus-cache-enter-article
2049 gnus-cache-remove-article)
2050 ("gnus-score" :interactive t
2051 gnus-summary-increase-score gnus-summary-lower-score
2052 gnus-score-flush-cache gnus-score-close
2053 gnus-score-raise-same-subject-and-select
2054 gnus-score-raise-same-subject gnus-score-default
2055 gnus-score-raise-thread gnus-score-lower-same-subject-and-select
2056 gnus-score-lower-same-subject gnus-score-lower-thread
2057 gnus-possibly-score-headers gnus-summary-raise-score
2058 gnus-summary-set-score gnus-summary-current-score)
2060 (gnus-summary-score-map keymap) gnus-score-save gnus-score-headers
2061 gnus-current-score-file-nondirectory gnus-score-adaptive
2062 gnus-score-find-trace gnus-score-file-name)
2063 ("gnus-edit" :interactive t gnus-score-customize)
2064 ("gnus-topic" :interactive t gnus-topic-mode)
2065 ("gnus-topic" gnus-topic-remove-group)
2066 ("gnus-salt" :interactive t gnus-pick-mode gnus-binary-mode)
2067 ("gnus-uu" (gnus-uu-extract-map keymap) (gnus-uu-mark-map keymap))
2068 ("gnus-uu" :interactive t
2069 gnus-uu-digest-mail-forward gnus-uu-digest-post-forward
2070 gnus-uu-mark-series gnus-uu-mark-region gnus-uu-mark-buffer
2071 gnus-uu-mark-by-regexp gnus-uu-mark-all
2072 gnus-uu-mark-sparse gnus-uu-mark-thread gnus-uu-decode-uu
2073 gnus-uu-decode-uu-and-save gnus-uu-decode-unshar
2074 gnus-uu-decode-unshar-and-save gnus-uu-decode-save
2075 gnus-uu-decode-binhex gnus-uu-decode-uu-view
2076 gnus-uu-decode-uu-and-save-view gnus-uu-decode-unshar-view
2077 gnus-uu-decode-unshar-and-save-view gnus-uu-decode-save-view
2078 gnus-uu-decode-binhex-view)
2079 ("gnus-msg" (gnus-summary-send-map keymap)
2080 gnus-mail-yank-original gnus-mail-send-and-exit
2081 gnus-sendmail-setup-mail gnus-article-mail
2082 gnus-inews-message-id gnus-new-mail gnus-mail-reply)
2083 ("gnus-msg" :interactive t
2084 gnus-group-post-news gnus-group-mail gnus-summary-post-news
2085 gnus-summary-followup gnus-summary-followup-with-original
2086 gnus-summary-followup-and-reply
2087 gnus-summary-followup-and-reply-with-original
2088 gnus-summary-cancel-article gnus-summary-supersede-article
2089 gnus-post-news gnus-inews-news gnus-cancel-news
2090 gnus-summary-reply gnus-summary-reply-with-original
2091 gnus-summary-mail-forward gnus-summary-mail-other-window
2093 ("gnus-picon" :interactive t gnus-article-display-picons
2094 gnus-group-display-picons gnus-picons-article-display-x-face)
2095 ("gnus-gl" bbb-login bbb-logout bbb-grouplens-group-p
2096 gnus-grouplens-mode)
2097 ("gnus-vm" gnus-vm-mail-setup)
2098 ("gnus-vm" :interactive t gnus-summary-save-in-vm
2099 gnus-summary-save-article-vm gnus-yank-article))))
2103 ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
2104 ;; If you want the cursor to go somewhere else, set these two
2105 ;; functions in some startup hook to whatever you want.
2106 (defalias 'gnus-summary-position-point 'gnus-goto-colon)
2107 (defalias 'gnus-group-position-point 'gnus-goto-colon)
2109 ;;; Various macros and substs.
2111 (defun gnus-header-from (header)
2112 (mail-header-from header))
2114 (defmacro gnus-eval-in-buffer-window (buffer &rest forms)
2115 "Pop to BUFFER, evaluate FORMS, and then return to the original window."
2116 (let ((tempvar (make-symbol "GnusStartBufferWindow"))
2117 (w (make-symbol "w"))
2118 (buf (make-symbol "buf")))
2119 `(let* ((,tempvar (selected-window))
2121 (,w (get-buffer-window ,buf 'visible)))
2126 (pop-to-buffer ,buf))
2128 (select-window ,tempvar)))))
2130 (defmacro gnus-gethash (string hashtable)
2131 "Get hash value of STRING in HASHTABLE."
2132 `(symbol-value (intern-soft ,string ,hashtable)))
2134 (defmacro gnus-sethash (string value hashtable)
2135 "Set hash value. Arguments are STRING, VALUE, and HASHTABLE."
2136 `(set (intern ,string ,hashtable) ,value))
2138 (defmacro gnus-intern-safe (string hashtable)
2139 "Set hash value. Arguments are STRING, VALUE, and HASHTABLE."
2140 `(let ((symbol (intern ,string ,hashtable)))
2145 (defmacro gnus-group-unread (group)
2146 "Get the currently computed number of unread articles in GROUP."
2147 `(car (gnus-gethash ,group gnus-newsrc-hashtb)))
2149 (defmacro gnus-group-entry (group)
2150 "Get the newsrc entry for GROUP."
2151 `(gnus-gethash ,group gnus-newsrc-hashtb))
2153 (defmacro gnus-active (group)
2154 "Get active info on GROUP."
2155 `(gnus-gethash ,group gnus-active-hashtb))
2157 (defmacro gnus-set-active (group active)
2158 "Set GROUP's active info."
2159 `(gnus-sethash ,group ,active gnus-active-hashtb))
2161 ;; modified by MORIOKA Tomohiko <morioka@jaist.ac.jp>
2162 ;; function `substring' might cut on a middle of multi-octet
2164 (defun gnus-truncate-string (str width)
2165 (substring str 0 width))
2167 ;; Added by Geoffrey T. Dairiki <dairiki@u.washington.edu>. A safe way
2168 ;; to limit the length of a string. This function is necessary since
2169 ;; `(substr "abc" 0 30)' pukes with "Args out of range".
2170 (defsubst gnus-limit-string (str width)
2171 (if (> (length str) width)
2172 (substring str 0 width)
2175 (defsubst gnus-simplify-subject-re (subject)
2176 "Remove \"Re:\" from subject lines."
2177 (if (string-match "^[Rr][Ee]: *" subject)
2178 (substring subject (match-end 0))
2181 (defsubst gnus-functionp (form)
2182 "Return non-nil if FORM is funcallable."
2183 (or (and (symbolp form) (fboundp form))
2184 (and (listp form) (eq (car form) 'lambda))))
2186 (defsubst gnus-goto-char (point)
2187 (and point (goto-char point)))
2189 (defmacro gnus-buffer-exists-p (buffer)
2190 `(let ((buffer ,buffer))
2192 (funcall (if (stringp buffer) 'get-buffer 'buffer-name)
2195 (defmacro gnus-kill-buffer (buffer)
2196 `(let ((buf ,buffer))
2197 (if (gnus-buffer-exists-p buf)
2198 (kill-buffer buf))))
2200 (defsubst gnus-point-at-bol ()
2201 "Return point at the beginning of the line."
2208 (defsubst gnus-point-at-eol ()
2209 "Return point at the end of the line."
2216 (defun gnus-alive-p ()
2217 "Say whether Gnus is running or not."
2218 (and gnus-group-buffer
2219 (get-buffer gnus-group-buffer)))
2221 ;; Delete the current line (and the next N lines.);
2222 (defmacro gnus-delete-line (&optional n)
2223 `(delete-region (progn (beginning-of-line) (point))
2224 (progn (forward-line ,(or n 1)) (point))))
2226 ;; Suggested by Brian Edmonds <edmonds@cs.ubc.ca>.
2227 (defvar gnus-init-inhibit nil)
2228 (defun gnus-read-init-file (&optional inhibit-next)
2229 (if gnus-init-inhibit
2230 (setq gnus-init-inhibit nil)
2231 (setq gnus-init-inhibit inhibit-next)
2233 (or (and (file-exists-p gnus-init-file)
2234 ;; Don't try to load a directory.
2235 (not (file-directory-p gnus-init-file)))
2236 (file-exists-p (concat gnus-init-file ".el"))
2237 (file-exists-p (concat gnus-init-file ".elc")))
2239 (load gnus-init-file nil t)
2241 (error "Error in %s: %s" gnus-init-file var))))))
2243 ;; Info access macros.
2245 (defmacro gnus-info-group (info)
2247 (defmacro gnus-info-rank (info)
2249 (defmacro gnus-info-read (info)
2251 (defmacro gnus-info-marks (info)
2253 (defmacro gnus-info-method (info)
2255 (defmacro gnus-info-params (info)
2258 (defmacro gnus-info-level (info)
2259 `(let ((rank (gnus-info-rank ,info)))
2263 (defmacro gnus-info-score (info)
2264 `(let ((rank (gnus-info-rank ,info)))
2265 (or (and (consp rank) (cdr rank)) 0)))
2267 (defmacro gnus-info-set-group (info group)
2268 `(setcar ,info ,group))
2269 (defmacro gnus-info-set-rank (info rank)
2270 `(setcar (nthcdr 1 ,info) ,rank))
2271 (defmacro gnus-info-set-read (info read)
2272 `(setcar (nthcdr 2 ,info) ,read))
2273 (defmacro gnus-info-set-marks (info marks)
2274 `(setcar (nthcdr 3 ,info) ,marks))
2275 (defmacro gnus-info-set-method (info method)
2276 `(setcar (nthcdr 4 ,info) ,method))
2277 (defmacro gnus-info-set-params (info params)
2278 `(setcar (nthcdr 5 ,info) ,params))
2280 (defmacro gnus-info-set-level (info level)
2281 `(let ((rank (cdr ,info)))
2282 (if (consp (car rank))
2283 (setcar (car rank) ,level)
2284 (setcar rank ,level))))
2285 (defmacro gnus-info-set-score (info score)
2286 `(let ((rank (cdr ,info)))
2287 (if (consp (car rank))
2288 (setcdr (car rank) ,score)
2289 (setcar rank (cons (car rank) ,score)))))
2291 (defmacro gnus-get-info (group)
2292 `(nth 2 (gnus-gethash ,group gnus-newsrc-hashtb)))
2294 (defun gnus-byte-code (func)
2295 "Return a form that can be `eval'ed based on FUNC."
2296 (let ((fval (symbol-function func)))
2297 (if (byte-code-function-p fval)
2298 (let ((flist (append fval nil)))
2299 (setcar flist 'byte-code)
2301 (cons 'progn (cddr fval)))))
2303 ;;; Load the compatability functions.
2313 (defvar gnus-shutdown-alist nil)
2315 (defun gnus-add-shutdown (function &rest symbols)
2316 "Run FUNCTION whenever one of SYMBOLS is shut down."
2317 (push (cons function symbols) gnus-shutdown-alist))
2319 (defun gnus-shutdown (symbol)
2320 "Shut down everything that waits for SYMBOL."
2321 (let ((alist gnus-shutdown-alist)
2323 (while (setq entry (pop alist))
2324 (when (memq symbol (cdr entry))
2325 (funcall (car entry))))))
2329 ;; Format specs. The chunks below are the machine-generated forms
2330 ;; that are to be evaled as the result of the default format strings.
2331 ;; We write them in here to get them byte-compiled. That way the
2332 ;; default actions will be quite fast, while still retaining the full
2333 ;; flexibility of the user-defined format specs.
2335 ;; First we have lots of dummy defvars to let the compiler know these
2336 ;; are really dynamic variables.
2338 (defvar gnus-tmp-unread)
2339 (defvar gnus-tmp-replied)
2340 (defvar gnus-tmp-score-char)
2341 (defvar gnus-tmp-indentation)
2342 (defvar gnus-tmp-opening-bracket)
2343 (defvar gnus-tmp-lines)
2344 (defvar gnus-tmp-name)
2345 (defvar gnus-tmp-closing-bracket)
2346 (defvar gnus-tmp-subject-or-nil)
2347 (defvar gnus-tmp-subject)
2348 (defvar gnus-tmp-marked)
2349 (defvar gnus-tmp-marked-mark)
2350 (defvar gnus-tmp-subscribed)
2351 (defvar gnus-tmp-process-marked)
2352 (defvar gnus-tmp-number-of-unread)
2353 (defvar gnus-tmp-group-name)
2354 (defvar gnus-tmp-group)
2355 (defvar gnus-tmp-article-number)
2356 (defvar gnus-tmp-unread-and-unselected)
2357 (defvar gnus-tmp-news-method)
2358 (defvar gnus-tmp-news-server)
2359 (defvar gnus-tmp-article-number)
2360 (defvar gnus-mouse-face)
2361 (defvar gnus-mouse-face-prop)
2363 (defun gnus-summary-line-format-spec ()
2364 (insert gnus-tmp-unread gnus-tmp-replied
2365 gnus-tmp-score-char gnus-tmp-indentation)
2366 (gnus-put-text-property
2370 gnus-tmp-opening-bracket
2371 (format "%4d: %-20s"
2373 (if (> (length gnus-tmp-name) 20)
2374 (substring gnus-tmp-name 0 20)
2376 gnus-tmp-closing-bracket)
2378 gnus-mouse-face-prop gnus-mouse-face)
2379 (insert " " gnus-tmp-subject-or-nil "\n"))
2381 (defvar gnus-summary-line-format-spec
2382 (gnus-byte-code 'gnus-summary-line-format-spec))
2384 (defun gnus-summary-dummy-line-format-spec ()
2386 (gnus-put-text-property
2391 gnus-mouse-face-prop gnus-mouse-face)
2392 (insert " " gnus-tmp-subject "\n"))
2394 (defvar gnus-summary-dummy-line-format-spec
2395 (gnus-byte-code 'gnus-summary-dummy-line-format-spec))
2397 (defun gnus-group-line-format-spec ()
2398 (insert gnus-tmp-marked-mark gnus-tmp-subscribed
2399 gnus-tmp-process-marked
2400 gnus-group-indentation
2401 (format "%5s: " gnus-tmp-number-of-unread))
2402 (gnus-put-text-property
2405 (insert gnus-tmp-group "\n")
2407 gnus-mouse-face-prop gnus-mouse-face))
2408 (defvar gnus-group-line-format-spec
2409 (gnus-byte-code 'gnus-group-line-format-spec))
2411 (defvar gnus-format-specs
2412 `((version . ,emacs-version)
2413 (group ,gnus-group-line-format ,gnus-group-line-format-spec)
2414 (summary-dummy ,gnus-summary-dummy-line-format
2415 ,gnus-summary-dummy-line-format-spec)
2416 (summary ,gnus-summary-line-format ,gnus-summary-line-format-spec)))
2418 (defvar gnus-article-mode-line-format-spec nil)
2419 (defvar gnus-summary-mode-line-format-spec nil)
2420 (defvar gnus-group-mode-line-format-spec nil)
2422 ;;; Phew. All that gruft is over, fortunately.
2426 ;;; Gnus Utility Functions
2429 (defun gnus-extract-address-components (from)
2431 ;; First find the address - the thing with the @ in it. This may
2432 ;; not be accurate in mail addresses, but does the trick most of
2433 ;; the time in news messages.
2434 (if (string-match "\\b[^@ \t<>]+[!@][^@ \t<>]+\\b" from)
2435 (setq address (substring from (match-beginning 0) (match-end 0))))
2436 ;; Then we check whether the "name <address>" format is used.
2438 ;; Fix by MORIOKA Tomohiko <morioka@jaist.ac.jp>
2439 ;; Linear white space is not required.
2440 (string-match (concat "[ \t]*<" (regexp-quote address) ">") from)
2441 (and (setq name (substring from 0 (match-beginning 0)))
2442 ;; Strip any quotes from the name.
2443 (string-match "\".*\"" name)
2444 (setq name (substring name 1 (1- (match-end 0))))))
2445 ;; If not, then "address (name)" is used.
2447 (and (string-match "(.+)" from)
2448 (setq name (substring from (1+ (match-beginning 0))
2449 (1- (match-end 0)))))
2450 (and (string-match "()" from)
2451 (setq name address))
2452 ;; Fix by MORIOKA Tomohiko <morioka@jaist.ac.jp>.
2453 ;; XOVER might not support folded From headers.
2454 (and (string-match "(.*" from)
2455 (setq name (substring from (1+ (match-beginning 0))
2457 ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
2458 (list (or name from) (or address from))))
2460 (defun gnus-fetch-field (field)
2461 "Return the value of the header FIELD of current article."
2464 (let ((case-fold-search t)
2465 (inhibit-point-motion-hooks t))
2466 (nnheader-narrow-to-headers)
2467 (message-fetch-field field)))))
2469 (defun gnus-goto-colon ()
2471 (search-forward ":" (gnus-point-at-eol) t))
2474 (defun gnus-update-format (var)
2475 "Update the format specification near point."
2480 ;; Find the end of the current word.
2481 (re-search-forward "[ \t\n]" nil t)
2483 (when (re-search-backward "\\(gnus-[-a-z]+-line-format\\)" nil t)
2484 (match-string 1)))))
2485 (let* ((type (intern (progn (string-match "gnus-\\([-a-z]+\\)-line" var)
2486 (match-string 1 var))))
2487 (entry (assq type gnus-format-specs))
2490 (setq gnus-format-specs (delq entry gnus-format-specs)))
2492 (intern (format "%s-spec" var))
2493 (gnus-parse-format (setq value (symbol-value (intern var)))
2494 (symbol-value (intern (format "%s-alist" var)))
2495 (not (string-match "mode" var))))
2496 (setq spec (symbol-value (intern (format "%s-spec" var))))
2497 (push (list type value spec) gnus-format-specs)
2499 (pop-to-buffer "*Gnus Format*")
2501 (lisp-interaction-mode)
2502 (insert (pp-to-string spec))))
2504 (defun gnus-update-format-specifications (&optional force)
2505 "Update all (necessary) format specifications."
2506 ;; Make the indentation array.
2507 (gnus-make-thread-indent-array)
2509 ;; See whether all the stored info needs to be flushed.
2511 (not (equal emacs-version
2512 (cdr (assq 'version gnus-format-specs)))))
2513 (setq gnus-format-specs nil))
2515 ;; Go through all the formats and see whether they need updating.
2516 (let ((types '(summary summary-dummy group
2517 summary-mode group-mode article-mode))
2518 new-format entry type val)
2519 (while (setq type (pop types))
2520 ;; Jump to the proper buffer to find out the value of
2521 ;; the variable, if possible. (It may be buffer-local.)
2523 (let ((buffer (intern (format "gnus-%s-buffer" type)))
2525 (when (and (boundp buffer)
2526 (setq val (symbol-value buffer))
2528 (buffer-name (get-buffer val)))
2529 (set-buffer (get-buffer val)))
2530 (setq new-format (symbol-value
2531 (intern (format "gnus-%s-line-format" type))))))
2532 (setq entry (cdr (assq type gnus-format-specs)))
2534 (equal (car entry) new-format))
2535 ;; Use the old format.
2536 (set (intern (format "gnus-%s-line-format-spec" type))
2538 ;; This is a new format.
2540 (if (not (stringp new-format))
2541 ;; This is a function call or something.
2543 ;; This is a "real" format.
2547 (intern (format "gnus-%s-line-format-alist"
2548 (if (eq type 'article-mode)
2549 'summary-mode type))))
2550 (not (string-match "mode$" (symbol-name type))))))
2551 ;; Enter the new format spec into the list.
2554 (setcar (cdr entry) val)
2555 (setcar entry new-format))
2556 (push (list type new-format val) gnus-format-specs))
2557 (set (intern (format "gnus-%s-line-format-spec" type)) val))))
2559 (unless (assq 'version gnus-format-specs)
2560 (push (cons 'version emacs-version) gnus-format-specs))
2562 (gnus-update-group-mark-positions)
2563 (gnus-update-summary-mark-positions))
2565 (defun gnus-update-summary-mark-positions ()
2566 "Compute where the summary marks are to go."
2568 (when (and gnus-summary-buffer
2569 (get-buffer gnus-summary-buffer)
2570 (buffer-name (get-buffer gnus-summary-buffer)))
2571 (set-buffer gnus-summary-buffer))
2572 (let ((gnus-replied-mark 129)
2573 (gnus-score-below-mark 130)
2574 (gnus-score-over-mark 130)
2577 (spec gnus-summary-line-format-spec)
2580 (gnus-set-work-buffer)
2581 (let ((gnus-summary-line-format-spec spec))
2582 (gnus-summary-insert-line
2583 [0 "" "" "" "" "" 0 0 ""] 0 nil 128 t nil "" nil 1)
2584 (goto-char (point-min))
2585 (setq pos (list (cons 'unread (and (search-forward "\200" nil t)
2587 (goto-char (point-min))
2588 (push (cons 'replied (and (search-forward "\201" nil t)
2591 (goto-char (point-min))
2592 (push (cons 'score (and (search-forward "\202" nil t) (- (point) 2)))
2594 (setq gnus-summary-mark-positions pos))))
2596 (defun gnus-update-group-mark-positions ()
2598 (let ((gnus-process-mark 128)
2599 (gnus-group-marked '("dummy.group"))
2600 (gnus-active-hashtb (make-vector 10 0)))
2601 (gnus-set-active "dummy.group" '(0 . 0))
2602 (gnus-set-work-buffer)
2603 (gnus-group-insert-group-line "dummy.group" 0 nil 0 nil)
2604 (goto-char (point-min))
2605 (setq gnus-group-mark-positions
2606 (list (cons 'process (and (search-forward "\200" nil t)
2607 (- (point) 2))))))))
2609 (defvar gnus-mouse-face-0 'highlight)
2610 (defvar gnus-mouse-face-1 'highlight)
2611 (defvar gnus-mouse-face-2 'highlight)
2612 (defvar gnus-mouse-face-3 'highlight)
2613 (defvar gnus-mouse-face-4 'highlight)
2615 (defun gnus-mouse-face-function (form type)
2616 `(gnus-put-text-property
2617 (point) (progn ,@form (point))
2618 gnus-mouse-face-prop
2621 `(quote ,(symbol-value (intern (format "gnus-mouse-face-%d" type)))))))
2623 (defvar gnus-face-0 'bold)
2624 (defvar gnus-face-1 'italic)
2625 (defvar gnus-face-2 'bold-italic)
2626 (defvar gnus-face-3 'bold)
2627 (defvar gnus-face-4 'bold)
2629 (defun gnus-face-face-function (form type)
2630 `(gnus-put-text-property
2631 (point) (progn ,@form (point))
2632 'face ',(symbol-value (intern (format "gnus-face-%d" type)))))
2634 (defun gnus-max-width-function (el max-width)
2635 (or (numberp max-width) (signal 'wrong-type-argument '(numberp max-width)))
2637 `(if (> (length ,el) ,max-width)
2638 (substring ,el 0 ,max-width)
2640 `(let ((val (eval ,el)))
2642 (setq val (int-to-string val)))
2643 (if (> (length val) ,max-width)
2644 (substring val 0 ,max-width)
2647 (defun gnus-parse-format (format spec-alist &optional insert)
2648 ;; This function parses the FORMAT string with the help of the
2649 ;; SPEC-ALIST and returns a list that can be eval'ed to return the
2650 ;; string. If the FORMAT string contains the specifiers %( and %)
2651 ;; the text between them will have the mouse-face text property.
2653 "\\`\\(.*\\)%[0-9]?[{(]\\(.*\\)%[0-9]?[})]\\(.*\n?\\)\\'"
2655 (gnus-parse-complex-format format spec-alist)
2656 ;; This is a simple format.
2657 (gnus-parse-simple-format format spec-alist insert)))
2659 (defun gnus-parse-complex-format (format spec-alist)
2661 (gnus-set-work-buffer)
2663 (goto-char (point-min))
2664 (while (re-search-forward "\"" nil t)
2665 (replace-match "\\\"" nil t))
2666 (goto-char (point-min))
2668 (while (re-search-forward "%\\([0-9]+\\)?\\([{}()]\\)" nil t)
2669 (let ((number (if (match-beginning 1)
2670 (match-string 1) "0"))
2671 (delim (aref (match-string 2) 0)))
2672 (if (or (= delim ?\() (= delim ?\{))
2673 (replace-match (concat "\"(" (if (= delim ?\() "mouse" "face")
2675 (replace-match "\")\""))))
2676 (goto-char (point-max))
2678 (goto-char (point-min))
2679 (let ((form (read (current-buffer))))
2680 (cons 'progn (gnus-complex-form-to-spec form spec-alist)))))
2682 (defun gnus-complex-form-to-spec (form spec-alist)
2687 (gnus-parse-simple-format sform spec-alist t)
2688 (funcall (intern (format "gnus-%s-face-function" (car sform)))
2689 (gnus-complex-form-to-spec (cddr sform) spec-alist)
2693 (defun gnus-parse-simple-format (format spec-alist &optional insert)
2694 ;; This function parses the FORMAT string with the help of the
2695 ;; SPEC-ALIST and returns a list that can be eval'ed to return a
2698 spec flist fstring newspec elem beg result dontinsert)
2700 (gnus-set-work-buffer)
2702 (goto-char (point-min))
2703 (while (re-search-forward "%[-0-9]*\\(,[0-9]+\\)?\\([^0-9]\\)\\(.\\)?"
2705 (if (= (setq spec (string-to-char (match-string 2))) ?%)
2707 beg (1+ (match-beginning 0)))
2708 ;; First check if there are any specs that look anything like
2709 ;; "%12,12A", ie. with a "max width specification". These have
2710 ;; to be treated specially.
2711 (if (setq beg (match-beginning 1))
2715 (1+ (match-beginning 1)) (match-end 1))))
2717 (setq beg (match-beginning 2)))
2718 ;; Find the specification from `spec-alist'.
2719 (unless (setq elem (cdr (assq spec spec-alist)))
2720 (setq elem '("*" ?s)))
2721 ;; Treat user defined format specifiers specially.
2722 (when (eq (car elem) 'gnus-tmp-user-defined)
2725 (list (intern (concat "gnus-user-format-function-"
2727 'gnus-tmp-header) ?s))
2728 (delete-region (match-beginning 3) (match-end 3)))
2729 (if (not (zerop max-width))
2730 (let ((el (car elem)))
2731 (cond ((= (cadr elem) ?c)
2732 (setq el (list 'char-to-string el)))
2734 (setq el (list 'int-to-string el))))
2735 (setq flist (cons (gnus-max-width-function el max-width)
2739 (setq flist (cons (car elem) flist))
2740 (setq newspec (cadr elem)))))
2741 ;; Remove the old specification (and possibly a ",12" string).
2742 (delete-region beg (match-end 2))
2743 ;; Insert the new specification.
2746 (setq fstring (buffer-substring 1 (point-max))))
2747 ;; Do some postprocessing to increase efficiency.
2752 ((string= fstring "")
2754 ;; Not a format string.
2755 ((not (string-match "%" fstring))
2757 ;; A format string with just a single string spec.
2758 ((string= fstring "%s")
2760 ;; A single character.
2761 ((string= fstring "%c")
2764 ((string= fstring "%d")
2767 (list `(princ ,(car flist)))
2768 (list `(int-to-string ,(car flist)))))
2769 ;; Just lots of chars and strings.
2770 ((string-match "\\`\\(%[cs]\\)+\\'" fstring)
2772 ;; A single string spec at the beginning of the spec.
2773 ((string-match "\\`%[sc][^%]+\\'" fstring)
2774 (list (car flist) (substring fstring 2)))
2775 ;; A single string spec in the middle of the spec.
2776 ((string-match "\\`\\([^%]+\\)%[sc]\\([^%]+\\)\\'" fstring)
2777 (list (match-string 1 fstring) (car flist) (match-string 2 fstring)))
2778 ;; A single string spec in the end of the spec.
2779 ((string-match "\\`\\([^%]+\\)%[sc]\\'" fstring)
2780 (list (match-string 1 fstring) (car flist)))
2781 ;; A more complex spec.
2783 (list (cons 'format (cons fstring (nreverse flist)))))))
2789 (cons 'insert result)))
2790 (cond ((stringp result)
2793 (cons 'concat result))
2796 (defun gnus-eval-format (format &optional alist props)
2797 "Eval the format variable FORMAT, using ALIST.
2798 If PROPS, insert the result."
2799 (let ((form (gnus-parse-format format alist props)))
2801 (gnus-add-text-properties (point) (progn (eval form) (point)) props)
2804 (defun gnus-remove-text-with-property (prop)
2805 "Delete all text in the current buffer with text property PROP."
2807 (goto-char (point-min))
2809 (while (get-text-property (point) prop)
2811 (goto-char (next-single-property-change (point) prop nil (point-max))))))
2813 (defun gnus-set-work-buffer ()
2814 (if (get-buffer gnus-work-buffer)
2816 (set-buffer gnus-work-buffer)
2818 (set-buffer (get-buffer-create gnus-work-buffer))
2819 (kill-all-local-variables)
2820 (buffer-disable-undo (current-buffer))
2821 (gnus-add-current-to-buffer-list)))
2823 ;; Article file names when saving.
2825 (defun gnus-Numeric-save-name (newsgroup headers &optional last-file)
2826 "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
2827 If variable `gnus-use-long-file-name' is nil, it is ~/News/News.group/num.
2828 Otherwise, it is like ~/News/news/group/num."
2831 (concat (if (gnus-use-long-file-name 'not-save)
2832 (gnus-capitalize-newsgroup newsgroup)
2833 (gnus-newsgroup-directory-form newsgroup))
2834 "/" (int-to-string (mail-header-number headers)))
2835 gnus-article-save-directory)))
2837 (string-equal (file-name-directory default)
2838 (file-name-directory last-file))
2839 (string-match "^[0-9]+$" (file-name-nondirectory last-file)))
2841 (or last-file default))))
2843 (defun gnus-numeric-save-name (newsgroup headers &optional last-file)
2844 "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
2845 If variable `gnus-use-long-file-name' is non-nil, it is
2846 ~/News/news.group/num. Otherwise, it is like ~/News/news/group/num."
2849 (concat (if (gnus-use-long-file-name 'not-save)
2851 (gnus-newsgroup-directory-form newsgroup))
2852 "/" (int-to-string (mail-header-number headers)))
2853 gnus-article-save-directory)))
2855 (string-equal (file-name-directory default)
2856 (file-name-directory last-file))
2857 (string-match "^[0-9]+$" (file-name-nondirectory last-file)))
2859 (or last-file default))))
2861 (defun gnus-Plain-save-name (newsgroup headers &optional last-file)
2862 "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
2863 If variable `gnus-use-long-file-name' is non-nil, it is
2864 ~/News/News.group. Otherwise, it is like ~/News/news/group/news."
2867 (if (gnus-use-long-file-name 'not-save)
2868 (gnus-capitalize-newsgroup newsgroup)
2869 (concat (gnus-newsgroup-directory-form newsgroup) "/news"))
2870 gnus-article-save-directory)))
2872 (defun gnus-plain-save-name (newsgroup headers &optional last-file)
2873 "Generate file name from NEWSGROUP, HEADERS, and optional LAST-FILE.
2874 If variable `gnus-use-long-file-name' is non-nil, it is
2875 ~/News/news.group. Otherwise, it is like ~/News/news/group/news."
2878 (if (gnus-use-long-file-name 'not-save)
2880 (concat (gnus-newsgroup-directory-form newsgroup) "/news"))
2881 gnus-article-save-directory)))
2883 ;; For subscribing new newsgroup
2885 (defun gnus-subscribe-hierarchical-interactive (groups)
2886 (let ((groups (sort groups 'string<))
2887 prefixes prefix start ans group starts)
2889 (setq prefixes (list "^"))
2890 (while (and groups prefixes)
2891 (while (not (string-match (car prefixes) (car groups)))
2892 (setq prefixes (cdr prefixes)))
2893 (setq prefix (car prefixes))
2894 (setq start (1- (length prefix)))
2895 (if (and (string-match "[^\\.]\\." (car groups) start)
2898 (concat "^" (substring (car groups) 0 (match-end 0))))
2899 (string-match prefix (cadr groups)))
2901 (setq prefixes (cons prefix prefixes))
2902 (message "Descend hierarchy %s? ([y]nsq): "
2903 (substring prefix 1 (1- (length prefix))))
2904 (setq ans (read-char))
2907 (string-match prefix
2908 (setq group (car groups))))
2909 (setq gnus-killed-list
2910 (cons group gnus-killed-list))
2911 (gnus-sethash group group gnus-killed-hashtb)
2912 (setq groups (cdr groups)))
2913 (setq starts (cdr starts)))
2916 (string-match prefix
2917 (setq group (car groups))))
2918 (gnus-sethash group group gnus-killed-hashtb)
2919 (gnus-subscribe-alphabetically (car groups))
2920 (setq groups (cdr groups)))
2921 (setq starts (cdr starts)))
2924 (setq group (car groups))
2925 (setq gnus-killed-list (cons group gnus-killed-list))
2926 (gnus-sethash group group gnus-killed-hashtb)
2927 (setq groups (cdr groups))))
2929 (message "Subscribe %s? ([n]yq)" (car groups))
2930 (setq ans (read-char))
2931 (setq group (car groups))
2933 (gnus-subscribe-alphabetically (car groups))
2934 (gnus-sethash group group gnus-killed-hashtb))
2937 (setq group (car groups))
2938 (setq gnus-killed-list (cons group gnus-killed-list))
2939 (gnus-sethash group group gnus-killed-hashtb)
2940 (setq groups (cdr groups))))
2942 (setq gnus-killed-list (cons group gnus-killed-list))
2943 (gnus-sethash group group gnus-killed-hashtb)))
2944 (setq groups (cdr groups)))))))
2946 (defun gnus-subscribe-randomly (newsgroup)
2947 "Subscribe new NEWSGROUP by making it the first newsgroup."
2948 (gnus-subscribe-newsgroup newsgroup))
2950 (defun gnus-subscribe-alphabetically (newgroup)
2951 "Subscribe new NEWSGROUP and insert it in alphabetical order."
2952 (let ((groups (cdr gnus-newsrc-alist))
2954 (while (and (not before) groups)
2955 (if (string< newgroup (caar groups))
2956 (setq before (caar groups))
2957 (setq groups (cdr groups))))
2958 (gnus-subscribe-newsgroup newgroup before)))
2960 (defun gnus-subscribe-hierarchically (newgroup)
2961 "Subscribe new NEWSGROUP and insert it in hierarchical newsgroup order."
2962 ;; Basic ideas by mike-w@cs.aukuni.ac.nz (Mike Williams)
2964 (set-buffer (find-file-noselect gnus-current-startup-file))
2965 (let ((groupkey newgroup)
2967 (while (and (not before) groupkey)
2968 (goto-char (point-min))
2970 (concat "^\\(" (regexp-quote groupkey) ".*\\)[!:]")))
2971 (while (and (re-search-forward groupkey-re nil t)
2973 (setq before (match-string 1))
2974 (string< before newgroup)))))
2975 ;; Remove tail of newsgroup name (eg. a.b.c -> a.b)
2977 (if (string-match "^\\(.*\\)\\.[^.]+$" groupkey)
2978 (substring groupkey (match-beginning 1) (match-end 1)))))
2979 (gnus-subscribe-newsgroup newgroup before))))
2981 (defun gnus-subscribe-interactively (group)
2982 "Subscribe the new GROUP interactively.
2983 It is inserted in hierarchical newsgroup order if subscribed. If not,
2985 (if (gnus-y-or-n-p (format "Subscribe new newsgroup: %s " group))
2986 (gnus-subscribe-hierarchically group)
2987 (push group gnus-killed-list)))
2989 (defun gnus-subscribe-zombies (group)
2990 "Make the new GROUP into a zombie group."
2991 (push group gnus-zombie-list))
2993 (defun gnus-subscribe-killed (group)
2994 "Make the new GROUP a killed group."
2995 (push group gnus-killed-list))
2997 (defun gnus-subscribe-newsgroup (newsgroup &optional next)
2998 "Subscribe new NEWSGROUP.
2999 If NEXT is non-nil, it is inserted before NEXT. Otherwise it is made
3000 the first newsgroup."
3001 ;; We subscribe the group by changing its level to `subscribed'.
3002 (gnus-group-change-level
3003 newsgroup gnus-level-default-subscribed
3004 gnus-level-killed (gnus-gethash (or next "dummy.group") gnus-newsrc-hashtb))
3005 (gnus-message 5 "Subscribe newsgroup: %s" newsgroup))
3009 (defun gnus-newsgroup-directory-form (newsgroup)
3010 "Make hierarchical directory name from NEWSGROUP name."
3011 (let ((newsgroup (gnus-newsgroup-savable-name newsgroup))
3012 (len (length newsgroup))
3014 ;; If this is a foreign group, we don't want to translate the
3016 (if (setq idx (string-match ":" newsgroup))
3017 (aset newsgroup idx ?/)
3019 ;; Replace all occurrences of `.' with `/'.
3021 (if (= (aref newsgroup idx) ?.)
3022 (aset newsgroup idx ?/))
3023 (setq idx (1+ idx)))
3026 (defun gnus-newsgroup-savable-name (group)
3027 ;; Replace any slashes in a group name (eg. an ange-ftp nndoc group)
3029 (nnheader-replace-chars-in-string group ?/ ?.))
3031 (defun gnus-make-directory (dir)
3032 "Make DIRECTORY recursively."
3033 ;; Why don't we use `(make-directory dir 'parents)'? That's just one
3034 ;; of the many mysteries of the universe.
3035 (let* ((dir (expand-file-name dir default-directory))
3037 (if (string-match "/$" dir)
3038 (setq dir (substring dir 0 (match-beginning 0))))
3039 ;; First go down the path until we find a directory that exists.
3040 (while (not (file-exists-p dir))
3041 (setq dirs (cons dir dirs))
3042 (string-match "/[^/]+$" dir)
3043 (setq dir (substring dir 0 (match-beginning 0))))
3044 ;; Then create all the subdirs.
3045 (while (and dirs (not err))
3047 (make-directory (car dirs))
3048 (error (setq err t)))
3049 (setq dirs (cdr dirs)))
3050 ;; We return whether we were successful or not.
3053 (defun gnus-capitalize-newsgroup (newsgroup)
3054 "Capitalize NEWSGROUP name."
3055 (and (not (zerop (length newsgroup)))
3056 (concat (char-to-string (upcase (aref newsgroup 0)))
3057 (substring newsgroup 1))))
3059 ;; Various... things.
3061 (defun gnus-simplify-subject (subject &optional re-only)
3062 "Remove `Re:' and words in parentheses.
3063 If RE-ONLY is non-nil, strip leading `Re:'s only."
3064 (let ((case-fold-search t)) ;Ignore case.
3065 ;; Remove `Re:', `Re^N:', `Re(n)', and `Re[n]:'.
3066 (when (string-match "\\`\\(re\\([[(^][0-9]+[])]?\\)?:[ \t]*\\)+" subject)
3067 (setq subject (substring subject (match-end 0))))
3068 ;; Remove uninteresting prefixes.
3069 (if (and (not re-only)
3070 gnus-simplify-ignored-prefixes
3071 (string-match gnus-simplify-ignored-prefixes subject))
3072 (setq subject (substring subject (match-end 0))))
3073 ;; Remove words in parentheses from end.
3075 (while (string-match "[ \t\n]*([^()]*)[ \t\n]*\\'" subject)
3076 (setq subject (substring subject 0 (match-beginning 0)))))
3077 ;; Return subject string.
3080 ;; Remove any leading "re:"s, any trailing paren phrases, and simplify
3082 ;; Written by Stainless Steel Rat <ratinox@ccs.neu.edu>.
3083 (defun gnus-simplify-buffer-fuzzy ()
3084 (goto-char (point-min))
3085 (while (search-forward "\t" nil t)
3086 (replace-match " " t t))
3087 (goto-char (point-min))
3088 (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *" nil t)
3089 (goto-char (match-beginning 0))
3091 (looking-at "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *")
3092 (looking-at "^[[].*: .*[]]$"))
3093 (goto-char (point-min))
3094 (while (re-search-forward "^ *\\(re\\|fwd\\)[[{(^0-9]*[])}]?[:;] *"
3096 (replace-match "" t t))
3097 (goto-char (point-min))
3098 (while (re-search-forward "^[[].*: .*[]]$" nil t)
3099 (goto-char (match-end 0))
3102 (progn (goto-char (match-beginning 0)))
3103 (re-search-forward ":"))))
3104 (goto-char (point-min))
3105 (while (re-search-forward " *[[{(][^()\n]*[]})] *$" nil t)
3106 (replace-match "" t t))
3107 (goto-char (point-min))
3108 (while (re-search-forward " +" nil t)
3109 (replace-match " " t t))
3110 (goto-char (point-min))
3111 (while (re-search-forward " $" nil t)
3112 (replace-match "" t t))
3113 (goto-char (point-min))
3114 (while (re-search-forward "^ +" nil t)
3115 (replace-match "" t t))
3116 (goto-char (point-min))
3117 (when gnus-simplify-subject-fuzzy-regexp
3118 (if (listp gnus-simplify-subject-fuzzy-regexp)
3119 (let ((list gnus-simplify-subject-fuzzy-regexp))
3121 (goto-char (point-min))
3122 (while (re-search-forward (car list) nil t)
3123 (replace-match "" t t))
3124 (setq list (cdr list))))
3125 (while (re-search-forward gnus-simplify-subject-fuzzy-regexp nil t)
3126 (replace-match "" t t)))))
3128 (defun gnus-simplify-subject-fuzzy (subject)
3129 "Siplify a subject string fuzzily."
3131 (gnus-set-work-buffer)
3132 (let ((case-fold-search t))
3134 (inline (gnus-simplify-buffer-fuzzy))
3137 ;; Add the current buffer to the list of buffers to be killed on exit.
3138 (defun gnus-add-current-to-buffer-list ()
3139 (or (memq (current-buffer) gnus-buffer-list)
3140 (setq gnus-buffer-list (cons (current-buffer) gnus-buffer-list))))
3142 (defun gnus-string> (s1 s2)
3143 (not (or (string< s1 s2)
3146 (defun gnus-read-active-file-p ()
3147 "Say whether the active file has been read from `gnus-select-method'."
3148 (memq gnus-select-method gnus-have-read-active-file))
3150 ;;; General various misc type functions.
3152 (defun gnus-clear-system ()
3153 "Clear all variables and buffers."
3154 ;; Clear Gnus variables.
3155 (let ((variables gnus-variable-list))
3157 (set (car variables) nil)
3158 (setq variables (cdr variables))))
3159 ;; Clear other internal variables.
3160 (setq gnus-list-of-killed-groups nil
3161 gnus-have-read-active-file nil
3162 gnus-newsrc-alist nil
3163 gnus-newsrc-hashtb nil
3164 gnus-killed-list nil
3165 gnus-zombie-list nil
3166 gnus-killed-hashtb nil
3167 gnus-active-hashtb nil
3168 gnus-moderated-list nil
3169 gnus-description-hashtb nil
3170 gnus-current-headers nil
3171 gnus-thread-indent-array nil
3172 gnus-newsgroup-headers nil
3173 gnus-newsgroup-name nil
3174 gnus-server-alist nil
3175 gnus-group-list-mode nil
3176 gnus-opened-servers nil
3177 gnus-current-select-method nil)
3178 (gnus-shutdown 'gnus)
3179 ;; Kill the startup file.
3180 (and gnus-current-startup-file
3181 (get-file-buffer gnus-current-startup-file)
3182 (kill-buffer (get-file-buffer gnus-current-startup-file)))
3183 ;; Clear the dribble buffer.
3184 (gnus-dribble-clear)
3185 ;; Kill global KILL file buffer.
3186 (when (get-file-buffer (gnus-newsgroup-kill-file nil))
3187 (kill-buffer (get-file-buffer (gnus-newsgroup-kill-file nil))))
3188 (gnus-kill-buffer nntp-server-buffer)
3189 ;; Kill Gnus buffers.
3190 (while gnus-buffer-list
3191 (gnus-kill-buffer (pop gnus-buffer-list)))
3192 ;; Remove Gnus frames.
3193 (while gnus-created-frames
3194 (when (frame-live-p (car gnus-created-frames))
3195 ;; We slap a condition-case around this `delete-frame' to ensure
3196 ;; agains errors if we try do delete the single frame that's left.
3198 (delete-frame (car gnus-created-frames))
3200 (pop gnus-created-frames)))
3202 (defun gnus-windows-old-to-new (setting)
3203 ;; First we take care of the really, really old Gnus 3 actions.
3204 (when (symbolp setting)
3206 ;; Take care of ooold GNUS 3.x values.
3207 (cond ((eq setting 'SelectArticle) 'article)
3208 ((memq setting '(SelectSubject ExpandSubject)) 'summary)
3209 ((memq setting '(SelectNewsgroup ExitNewsgroup)) 'group)
3211 (if (or (listp setting)
3212 (not (and gnus-window-configuration
3213 (memq setting '(group summary article)))))
3215 (let* ((setting (if (eq setting 'group)
3216 (if (assq 'newsgroup gnus-window-configuration)
3218 'newsgroups) setting))
3219 (elem (cadr (assq setting gnus-window-configuration)))
3220 (total (apply '+ elem))
3221 (types '(group summary article))
3222 (pbuf (if (eq setting 'newsgroups) 'group 'summary))
3227 (or (not (numberp (nth i elem)))
3228 (zerop (nth i elem))
3230 (setq perc (/ (float (nth 0 elem)) total))
3231 (setq out (cons (if (eq pbuf (nth i types))
3232 (vector (nth i types) perc 'point)
3233 (vector (nth i types) perc))
3236 (list (nreverse out)))))
3239 (defun gnus-add-configuration (conf)
3240 "Add the window configuration CONF to `gnus-buffer-configuration'."
3241 (setq gnus-buffer-configuration
3242 (cons conf (delq (assq (car conf) gnus-buffer-configuration)
3243 gnus-buffer-configuration))))
3245 (defvar gnus-frame-list nil)
3247 (defun gnus-configure-frame (split &optional window)
3248 "Split WINDOW according to SPLIT."
3250 (setq window (get-buffer-window (current-buffer))))
3251 (select-window window)
3252 ;; This might be an old-stylee buffer config.
3253 (when (vectorp split)
3254 (setq split (append split nil)))
3255 (when (or (consp (car split))
3256 (vectorp (car split)))
3258 (push 'vertical split))
3259 ;; The SPLIT might be something that is to be evaled to
3260 ;; return a new SPLIT.
3261 (while (and (not (assq (car split) gnus-window-to-buffer))
3262 (gnus-functionp (car split)))
3263 (setq split (eval split)))
3264 (let* ((type (car split))
3266 (len (if (eq type 'horizontal) (window-width) (window-height)))
3268 (window-min-width (or gnus-window-min-width window-min-width))
3269 (window-min-height (or gnus-window-min-height window-min-height))
3270 s result new-win rest comp-subs size sub)
3272 ;; Nothing to do here.
3274 ;; Don't switch buffers.
3276 (and (memq 'point split) window))
3277 ;; This is a buffer to be selected.
3278 ((not (memq type '(frame horizontal vertical)))
3279 (let ((buffer (cond ((stringp type) type)
3280 (t (cdr (assq type gnus-window-to-buffer)))))
3283 (error "Illegal buffer type: %s" type))
3284 (unless (setq buf (get-buffer (if (symbolp buffer)
3285 (symbol-value buffer) buffer)))
3286 (setq buf (get-buffer-create (if (symbolp buffer)
3287 (symbol-value buffer) buffer))))
3288 (switch-to-buffer buf)
3289 ;; We return the window if it has the `point' spec.
3290 (and (memq 'point split) window)))
3291 ;; This is a frame split.
3293 (unless gnus-frame-list
3294 (setq gnus-frame-list (list (window-frame
3295 (get-buffer-window (current-buffer))))))
3297 params frame fresult)
3298 (while (< i (length subs))
3299 ;; Frame parameter is gotten from the sub-split.
3300 (setq params (cadr (elt subs i)))
3301 ;; It should be a list.
3302 (unless (listp params)
3304 ;; Create a new frame?
3305 (unless (setq frame (elt gnus-frame-list i))
3306 (nconc gnus-frame-list (list (setq frame (make-frame params))))
3307 (push frame gnus-created-frames))
3308 ;; Is the old frame still alive?
3309 (unless (frame-live-p frame)
3310 (setcar (nthcdr i gnus-frame-list)
3311 (setq frame (make-frame params))))
3312 ;; Select the frame in question and do more splits there.
3313 (select-frame frame)
3314 (setq fresult (or (gnus-configure-frame (elt subs i)) fresult))
3316 ;; Select the frame that has the selected buffer.
3318 (select-frame (window-frame fresult)))))
3319 ;; This is a normal split.
3321 (when (> (length subs) 0)
3322 ;; First we have to compute the sizes of all new windows.
3324 (setq sub (append (pop subs) nil))
3325 (while (and (not (assq (car sub) gnus-window-to-buffer))
3326 (gnus-functionp (car sub)))
3327 (setq sub (eval sub)))
3329 (push sub comp-subs)
3330 (setq size (cadar comp-subs))
3331 (cond ((equal size 1.0)
3332 (setq rest (car comp-subs))
3335 (setq s (floor (* size len))))
3339 (error "Illegal size: %s" size)))
3340 ;; Try to make sure that we are inside the safe limits.
3342 ((eq type 'horizontal)
3343 (setq s (max s window-min-width)))
3344 ((eq type 'vertical)
3345 (setq s (max s window-min-height))))
3346 (setcar (cdar comp-subs) s)
3348 ;; Take care of the "1.0" spec.
3350 (setcar (cdr rest) (- len total))
3351 (error "No 1.0 specs in %s" split))
3352 ;; The we do the actual splitting in a nice recursive
3354 (setq comp-subs (nreverse comp-subs))
3356 (if (null (cdr comp-subs))
3357 (setq new-win window)
3359 (split-window window (cadar comp-subs)
3360 (eq type 'horizontal))))
3361 (setq result (or (gnus-configure-frame
3362 (car comp-subs) window) result))
3363 (select-window new-win)
3364 (setq window new-win)
3365 (setq comp-subs (cdr comp-subs))))
3366 ;; Return the proper window, if any.
3368 (select-window result))))))
3370 (defvar gnus-frame-split-p nil)
3372 (defun gnus-configure-windows (setting &optional force)
3373 (setq setting (gnus-windows-old-to-new setting))
3374 (let ((split (if (symbolp setting)
3375 (cadr (assq setting gnus-buffer-configuration))
3379 (setq gnus-frame-split-p nil)
3382 (error "No such setting: %s" setting))
3384 (if (and (setq all-visible (gnus-all-windows-visible-p split))
3386 ;; All the windows mentioned are already visible, so we just
3387 ;; put point in the assigned buffer, and do not touch the
3389 (select-window all-visible)
3391 ;; Either remove all windows or just remove all Gnus windows.
3392 (let ((frame (selected-frame)))
3394 (if gnus-use-full-window
3395 ;; We want to remove all other windows.
3396 (if (not gnus-frame-split-p)
3397 ;; This is not a `frame' split, so we ignore the
3399 (delete-other-windows)
3400 ;; This is a `frame' split, so we delete all windows
3404 (unless (eq (cdr (assq 'minibuffer
3405 (frame-parameters frame)))
3407 (select-frame frame)
3408 (delete-other-windows)))
3410 ;; Just remove some windows.
3411 (gnus-remove-some-windows)
3412 (switch-to-buffer nntp-server-buffer))
3413 (select-frame frame)))
3415 (switch-to-buffer nntp-server-buffer)
3416 (gnus-configure-frame split (get-buffer-window (current-buffer))))))
3418 (defun gnus-all-windows-visible-p (split)
3419 "Say whether all buffers in SPLIT are currently visible.
3420 In particular, the value returned will be the window that
3422 (let ((stack (list split))
3424 type buffer win buf)
3425 (while (and (setq split (pop stack))
3427 ;; Be backwards compatible.
3428 (when (vectorp split)
3429 (setq split (append split nil)))
3430 (when (or (consp (car split))
3431 (vectorp (car split)))
3433 (push 'vertical split))
3434 ;; The SPLIT might be something that is to be evaled to
3435 ;; return a new SPLIT.
3436 (while (and (not (assq (car split) gnus-window-to-buffer))
3437 (gnus-functionp (car split)))
3438 (setq split (eval split)))
3440 (setq type (elt split 0))
3445 ((not (memq type '(horizontal vertical frame)))
3446 (setq buffer (cond ((stringp type) type)
3447 (t (cdr (assq type gnus-window-to-buffer)))))
3449 (error "Illegal buffer type: %s" type))
3450 (when (setq buf (get-buffer (if (symbolp buffer)
3451 (symbol-value buffer)
3453 (setq win (get-buffer-window buf t)))
3455 (when (memq 'point split)
3456 (setq all-visible win))
3457 (setq all-visible nil)))
3459 (when (eq type 'frame)
3460 (setq gnus-frame-split-p t))
3461 (setq stack (append (cddr split) stack)))))
3462 (unless (eq all-visible t)
3465 (defun gnus-window-top-edge (&optional window)
3466 (nth 1 (window-edges window)))
3468 (defun gnus-remove-some-windows ()
3469 (let ((buffers gnus-window-to-buffer)
3470 buf bufs lowest-buf lowest)
3472 ;; Remove windows on all known Gnus buffers.
3474 (setq buf (cdar buffers))
3476 (setq buf (and (boundp buf) (symbol-value buf))))
3478 (get-buffer-window buf)
3480 (setq bufs (cons buf bufs))
3482 (if (or (not lowest)
3483 (< (gnus-window-top-edge) lowest))
3485 (setq lowest (gnus-window-top-edge))
3486 (setq lowest-buf buf)))))
3487 (setq buffers (cdr buffers)))
3488 ;; Remove windows on *all* summary buffers.
3491 (let ((buf (window-buffer win)))
3492 (if (string-match "^\\*Summary" (buffer-name buf))
3494 (setq bufs (cons buf bufs))
3496 (if (or (not lowest)
3497 (< (gnus-window-top-edge) lowest))
3499 (setq lowest-buf buf)
3500 (setq lowest (gnus-window-top-edge)))))))))
3503 (pop-to-buffer lowest-buf)
3504 (switch-to-buffer nntp-server-buffer)))
3506 (and (not (eq (car bufs) lowest-buf))
3507 (delete-windows-on (car bufs)))
3508 (setq bufs (cdr bufs))))))
3510 (defun gnus-version ()
3511 "Version numbers of this version of Gnus."
3513 (let ((methods gnus-valid-select-methods)
3516 ;; Go through all the legal select methods and add their version
3517 ;; numbers to the total version string. Only the backends that are
3518 ;; currently in use will have their message numbers taken into
3521 (setq meth (intern (concat (caar methods) "-version")))
3523 (stringp (symbol-value meth))
3524 (setq mess (concat mess "; " (symbol-value meth))))
3525 (setq methods (cdr methods)))
3526 (gnus-message 2 mess)))
3528 (defun gnus-info-find-node ()
3529 "Find Info documentation of Gnus."
3531 ;; Enlarge info window if needed.
3532 (let ((mode major-mode)
3534 (Info-goto-node (cadr (assq mode gnus-info-nodes)))
3535 (setq gnus-info-buffer (current-buffer))
3536 (gnus-configure-windows 'info)))
3538 (defun gnus-days-between (date1 date2)
3539 ;; Return the number of days between date1 and date2.
3540 (- (gnus-day-number date1) (gnus-day-number date2)))
3542 (defun gnus-day-number (date)
3543 (let ((dat (mapcar (lambda (s) (and s (string-to-int s)) )
3544 (timezone-parse-date date))))
3545 (timezone-absolute-from-gregorian
3546 (nth 1 dat) (nth 2 dat) (car dat))))
3548 (defun gnus-encode-date (date)
3549 "Convert DATE to internal time."
3550 (let* ((parse (timezone-parse-date date))
3551 (date (mapcar (lambda (d) (and d (string-to-int d))) parse))
3552 (time (mapcar 'string-to-int (timezone-parse-time (aref parse 3)))))
3553 (encode-time (caddr time) (cadr time) (car time)
3554 (caddr date) (cadr date) (car date) (nth 4 date))))
3556 (defun gnus-time-minus (t1 t2)
3557 "Subtract two internal times."
3558 (let ((borrow (< (cadr t1) (cadr t2))))
3559 (list (- (car t1) (car t2) (if borrow 1 0))
3560 (- (+ (if borrow 65536 0) (cadr t1)) (cadr t2)))))
3562 (defun gnus-file-newer-than (file date)
3563 (let ((fdate (nth 5 (file-attributes file))))
3564 (or (> (car fdate) (car date))
3565 (and (= (car fdate) (car date))
3566 (> (nth 1 fdate) (nth 1 date))))))