gnus-start.el 115 KB
Newer Older
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
1
;;; gnus-start.el --- startup functions for Gnus
2

Paul Eggert's avatar
Paul Eggert committed
3
;; Copyright (C) 1996-2019 Free Software Foundation, Inc.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
4

5
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
6 7 8 9
;; Keywords: news

;; This file is part of GNU Emacs.

10
;; GNU Emacs is free software: you can redistribute it and/or modify
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
11
;; it under the terms of the GNU General Public License as published by
12 13
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
14 15 16

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
18 19 20
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
21
;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
22 23 24 25 26 27 28 29 30 31 32

;;; Commentary:

;;; Code:

(require 'gnus)
(require 'gnus-win)
(require 'gnus-int)
(require 'gnus-spec)
(require 'gnus-range)
(require 'gnus-util)
Gnus developers's avatar
Gnus developers committed
33
(require 'gnus-cloud)
34 35
(autoload 'message-make-date "message")
(autoload 'gnus-agent-read-servers-validate "gnus-agent")
36
(autoload 'gnus-agent-save-local "gnus-agent")
37
(autoload 'gnus-agent-possibly-alter-active "gnus-agent")
38

Glenn Morris's avatar
Glenn Morris committed
39
(eval-when-compile (require 'cl-lib))
40

Dan Nicolaescu's avatar
Dan Nicolaescu committed
41 42 43
(defvar gnus-agent-covered-methods)
(defvar gnus-agent-file-loading-local)
(defvar gnus-agent-file-loading-cache)
44
(defvar gnus-topic-alist)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
45 46 47 48 49 50 51

(defcustom gnus-startup-file (nnheader-concat gnus-home-directory ".newsrc")
  "Your `.newsrc' file.
`.newsrc-SERVER' will be used instead if that exists."
  :group 'gnus-start
  :type 'file)

52
(defcustom gnus-backup-startup-file 'never
Miles Bader's avatar
Miles Bader committed
53
  "Control use of version numbers for backups of `gnus-startup-file'.
54 55
This variable takes the same values as the `version-control'
variable."
56
  :version "22.1"
57 58 59 60 61 62 63 64 65 66
  :group 'gnus-start
  :type '(choice (const :tag "Never" never)
		 (const :tag "If existing" nil)
		 (other :tag "Always" t)))

(defcustom gnus-save-startup-file-via-temp-buffer t
  "Whether to write the startup file contents to a buffer then save
the buffer or write directly to the file.  The buffer is faster
because all of the contents are written at once.  The direct write
uses considerably less memory."
67
  :version "22.1"
68 69 70 71
  :group 'gnus-start
  :type '(choice (const :tag "Write via buffer" t)
                 (const :tag "Write directly to file" nil)))

Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
72
(defcustom gnus-init-file (nnheader-concat gnus-home-directory ".gnus")
73 74
  "Your Gnus Emacs-Lisp startup file name.
If a file with the `.el' or `.elc' suffixes exists, it will be read instead."
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
75 76 77 78
  :group 'gnus-start
  :type 'file)

(defcustom gnus-site-init-file
79
  (condition-case nil
80 81 82
      (concat (file-name-directory
	       (directory-file-name installation-directory))
	      "site-lisp/gnus-init")
83
    (error nil))
84
  "The site-wide Gnus Emacs-Lisp startup file name, or nil if none.
85
If a file with the `.el' or `.elc' suffixes exists, it will be read instead."
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
86
  :group 'gnus-start
87
  :type '(choice file (const nil)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
88 89

(defcustom gnus-use-dribble-file t
90
  "Non-nil means that Gnus will use a dribble file to store user updates.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
91 92 93 94 95 96
If Emacs should crash without saving the .newsrc files, complete
information can be restored from the dribble file."
  :group 'gnus-dribble-file
  :type 'boolean)

(defcustom gnus-dribble-directory nil
97
  "The directory where dribble files will be saved.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
98 99 100 101 102
If this variable is nil, the directory where the .newsrc files are
saved will be used."
  :group 'gnus-dribble-file
  :type '(choice directory (const nil)))

103
(defcustom gnus-check-new-newsgroups 'ask-server
104
  "Non-nil means that Gnus will run `gnus-find-new-newsgroups' at startup.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
105 106 107 108
This normally finds new newsgroups by comparing the active groups the
servers have already reported with those Gnus already knows, either alive
or killed.

109
When any of the following are true, `gnus-find-new-newsgroups' will instead
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
110 111 112 113
ask the servers (primary, secondary, and archive servers) to list new
groups since the last time it checked:
  1. This variable is `ask-server'.
  2. This variable is a list of select methods (see below).
114
  3. Option `gnus-read-active-file' is nil or `some'.
115
  4. A prefix argument is given to `gnus-find-new-newsgroups' interactively.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
116 117 118 119 120 121 122 123 124

Thus, if this variable is `ask-server' or a list of select methods or
`gnus-read-active-file' is nil or `some', then the killed list is no
longer necessary, so you could safely set `gnus-save-killed-list' to nil.

This variable can be a list of select methods which Gnus will query with
the `ask-server' method in addition to the primary, secondary, and archive
servers.

125
E.g.:
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
126
  (setq gnus-check-new-newsgroups
127
	\\='((nntp \"some.server\") (nntp \"other.server\")))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
128 129 130 131 132 133 134 135 136 137 138 139 140

If this variable is nil, then you have to tell Gnus explicitly to
check for new newsgroups with \\<gnus-group-mode-map>\\[gnus-find-new-newsgroups]."
  :group 'gnus-start
  :type '(choice (const :tag "no" nil)
		 (const :tag "by brute force" t)
		 (const :tag "ask servers" ask-server)
		 (repeat :menu-tag "ask additional servers"
			 :tag "ask additional servers"
			 :value ((nntp ""))
			 (sexp :format "%v"))))

(defcustom gnus-check-bogus-newsgroups nil
141
  "Non-nil means that Gnus will check and remove bogus newsgroup at startup.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
142 143 144 145 146
If this variable is nil, then you have to tell Gnus explicitly to
check for bogus newsgroups with \\<gnus-group-mode-map>\\[gnus-group-check-bogus-groups]."
  :group 'gnus-start-server
  :type 'boolean)

147
(defcustom gnus-read-active-file 'some
148
  "Non-nil means that Gnus will read the entire active file at startup.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
If this variable is nil, Gnus will only know about the groups in your
`.newsrc' file.

If this variable is `some', Gnus will try to only read the relevant
parts of the active file from the server.  Not all servers support
this, and it might be quite slow with other servers, but this should
generally be faster than both the t and nil value.

If you set this variable to nil or `some', you probably still want to
be told about new newsgroups that arrive.  To do that, set
`gnus-check-new-newsgroups' to `ask-server'.  This may not work
properly with all servers."
  :group 'gnus-start-server
  :type '(choice (const nil)
		 (const some)
		 (const t)))

166 167
(defconst gnus-level-subscribed 5
  "Groups with levels less than or equal to this variable are subscribed.")
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
168

169 170
(defconst gnus-level-unsubscribed 7
  "Groups with levels less than or equal to this variable are unsubscribed.
Miles Bader's avatar
Miles Bader committed
171 172 173 174 175

Groups with levels less than `gnus-level-subscribed', which
should be less than this variable, are subscribed.  Groups with
levels from `gnus-level-subscribed' (exclusive) upto this
variable (inclusive) are unsubscribed.  See also
176
`gnus-level-zombie', `gnus-level-killed' and the Info node `(gnus)Group
Miles Bader's avatar
Miles Bader committed
177
Levels' for details.")
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
178

179 180
(defconst gnus-level-zombie 8
  "Groups with this level are zombie groups.")
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
181

182 183
(defconst gnus-level-killed 9
  "Groups with this level are killed.")
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
184 185

(defcustom gnus-level-default-subscribed 3
186
  "New subscribed groups will be subscribed at this level."
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
187 188 189 190
  :group 'gnus-group-levels
  :type 'integer)

(defcustom gnus-level-default-unsubscribed 6
191
  "New unsubscribed groups will be unsubscribed at this level."
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
192 193 194 195
  :group 'gnus-group-levels
  :type 'integer)

(defcustom gnus-activate-level (1+ gnus-level-subscribed)
196
  "Groups higher than this level won't be activated on startup.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
197 198 199 200 201 202
Setting this variable to something low might save lots of time when
you have many groups that you aren't interested in."
  :group 'gnus-group-levels
  :type 'integer)

(defcustom gnus-activate-foreign-newsgroups 4
203
  "If nil, Gnus will not check foreign newsgroups at startup.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
204 205 206 207 208 209 210 211 212 213 214
If it is non-nil, it should be a number between one and nine.  Foreign
newsgroups that have a level lower or equal to this number will be
activated on startup.  For instance, if you want to active all
subscribed newsgroups, but not the rest, you'd set this variable to
`gnus-level-subscribed'.

If you subscribe to lots of newsgroups from different servers, startup
might take a while.  By setting this variable to nil, you'll save time,
but you won't be told how many unread articles there are in the
groups."
  :group 'gnus-group-levels
215 216
  :type '(choice integer
		 (const :tag "none" nil)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
217

218
(defcustom gnus-read-newsrc-file t
219
  "Non-nil means that Gnus will read the `.newsrc' file.
220 221 222 223 224
Gnus always reads its own startup file, which is called
\".newsrc.eld\".  The file called \".newsrc\" is in a format that can
be readily understood by other newsreaders.  If you don't plan on
using other newsreaders, set this variable to nil to save some time on
entry."
225
  :version "21.1"
226 227 228
  :group 'gnus-newsrc
  :type 'boolean)

Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
229
(defcustom gnus-save-newsrc-file t
230
  "Non-nil means that Gnus will save the `.newsrc' file.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
231 232 233 234 235 236 237 238 239
Gnus always saves its own startup file, which is called
\".newsrc.eld\".  The file called \".newsrc\" is in a format that can
be readily understood by other newsreaders.  If you don't plan on
using other newsreaders, set this variable to nil to save some time on
exit."
  :group 'gnus-newsrc
  :type 'boolean)

(defcustom gnus-save-killed-list t
240
  "If non-nil, save the list of killed groups to the startup file.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
241 242 243 244 245 246 247 248 249 250 251
If you set this variable to nil, you'll save both time (when starting
and quitting) and space (both memory and disk), but it will also mean
that Gnus has no record of which groups are new and which are old, so
the automatic new newsgroups subscription methods become meaningless.

You should always set `gnus-check-new-newsgroups' to `ask-server' or
nil if you set this variable to nil.

This variable can also be a regexp.  In that case, all groups that do
not match this regexp will be removed before saving the list."
  :group 'gnus-newsrc
252 253 254 255 256
  :type '(radio (sexp :format "Non-nil\n"
		      :match (lambda (widget value)
			       (and value (not (stringp value))))
		      :value t)
		(const nil)
257
		regexp))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
258 259

(defcustom gnus-ignored-newsgroups
260 261
  (mapconcat 'identity
	     '("^to\\."			; not "real" groups
262
	       "^[0-9. \t]+\\( \\|$\\)"	; all digits in name
263
	       "^[\"][\"#'()]"	; bogus characters
264 265
	       )
	     "\\|")
266
  "A regexp to match uninteresting newsgroups in the active file.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
267 268 269 270 271 272 273
Any lines in the active file matching this regular expression are
removed from the newsgroup list before anything else is done to it,
thus making them effectively non-existent."
  :group 'gnus-group-new
  :type 'regexp)

(defcustom gnus-subscribe-newsgroup-method 'gnus-subscribe-zombies
274
  "Function(s) called with a group name when new group is detected.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
275 276 277 278 279 280
A few pre-made functions are supplied: `gnus-subscribe-randomly'
inserts new groups at the beginning of the list of groups;
`gnus-subscribe-alphabetically' inserts new groups in strict
alphabetic order; `gnus-subscribe-hierarchically' inserts new groups
in hierarchical newsgroup order; `gnus-subscribe-interactively' asks
for your decision; `gnus-subscribe-killed' kills all new groups;
281 282 283
`gnus-subscribe-zombies' will make all new groups into zombies;
`gnus-subscribe-topics' will enter groups into the topics that
claim them."
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
284 285 286 287 288 289 290
  :group 'gnus-group-new
  :type '(radio (function-item gnus-subscribe-randomly)
		(function-item gnus-subscribe-alphabetically)
		(function-item gnus-subscribe-hierarchically)
		(function-item gnus-subscribe-interactively)
		(function-item gnus-subscribe-killed)
		(function-item gnus-subscribe-zombies)
291
		(function-item gnus-subscribe-topics)
292 293 294
		function
		(repeat function)))

Stefan Monnier's avatar
Stefan Monnier committed
295 296 297
(define-obsolete-variable-alias 'gnus-subscribe-newsgroup-hooks
  'gnus-subscribe-newsgroup-functions "24.3")
(defcustom gnus-subscribe-newsgroup-functions nil
298
  "Hooks run after you subscribe to a new group.
299
The hooks will be called with new group's name as argument."
300
  :version "22.1"
301 302
  :group 'gnus-group-new
  :type 'hook)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
303 304 305

(defcustom gnus-subscribe-options-newsgroup-method
  'gnus-subscribe-alphabetically
306
  "Function(s) called to subscribe newsgroups mentioned on \"options -n\" lines.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
307 308 309 310 311 312
If, for instance, you want to subscribe to all newsgroups in the
\"no\" and \"alt\" hierarchies, you'd put the following in your
.newsrc file:

options -n no.all alt.all

Miles Bader's avatar
Miles Bader committed
313 314
Gnus will then subscribe all new newsgroups in these hierarchies
with the subscription method in this variable."
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
315 316 317 318 319 320 321
  :group 'gnus-group-new
  :type '(radio (function-item gnus-subscribe-randomly)
		(function-item gnus-subscribe-alphabetically)
		(function-item gnus-subscribe-hierarchically)
		(function-item gnus-subscribe-interactively)
		(function-item gnus-subscribe-killed)
		(function-item gnus-subscribe-zombies)
322 323 324
		(function-item gnus-subscribe-topics)
		function
		(repeat function)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
325 326

(defcustom gnus-subscribe-hierarchical-interactive nil
327
  "If non-nil, Gnus will offer to subscribe hierarchically.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
328 329 330 331 332 333 334 335 336 337
When a new hierarchy appears, Gnus will ask the user:

'alt.binaries': Do you want to subscribe to this hierarchy? ([d]ys):

If the user pressed `d', Gnus will descend the hierarchy, `y' will
subscribe to all newsgroups in the hierarchy and `s' will skip this
hierarchy in its entirety."
  :group 'gnus-group-new
  :type 'boolean)

338
(defcustom gnus-auto-subscribed-categories '(mail post-mail)
339
  "New groups from methods of these categories will be subscribed automatically.
340 341 342 343 344 345 346
Note that this variable only deals with new groups.  It has no
effect whatsoever on old groups.  The default is to automatically
subscribe all groups from mail-like backends."
  :version "24.1"
  :group 'gnus-group-new
  :type '(repeat symbol))

Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
347
(defcustom gnus-auto-subscribed-groups
348
  "^nnml\\|^nnfolder\\|^nnmbox\\|^nnmh\\|^nnbabyl\\|^nnmaildir\\|^nnimap"
349
  "All new groups that match this regexp will be subscribed automatically.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
350 351 352 353 354 355 356 357 358 359
Note that this variable only deals with new groups.  It has no effect
whatsoever on old groups.

New groups that match this regexp will not be handled by
`gnus-subscribe-newsgroup-method'.  Instead, they will
be subscribed using `gnus-subscribe-options-newsgroup-method'."
  :group 'gnus-group-new
  :type 'regexp)

(defcustom gnus-options-subscribe nil
360
  "All new groups matching this regexp will be subscribed unconditionally.
361
Note that this variable deals only with new newsgroups.  This variable
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
362 363 364 365 366 367 368 369 370 371
does not affect old newsgroups.

New groups that match this regexp will not be handled by
`gnus-subscribe-newsgroup-method'.  Instead, they will
be subscribed using `gnus-subscribe-options-newsgroup-method'."
  :group 'gnus-group-new
  :type '(choice regexp
		 (const :tag "none" nil)))

(defcustom gnus-options-not-subscribe nil
372
  "All new groups matching this regexp will be ignored.
373
Note that this variable deals only with new newsgroups.  This variable
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
374 375 376 377 378 379
does not affect old (already subscribed) newsgroups."
  :group 'gnus-group-new
  :type '(choice regexp
		 (const :tag "none" nil)))

(defcustom gnus-modtime-botch nil
380
  "Non-nil means .newsrc should be deleted prior to save.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
Its use is due to the bogus appearance that .newsrc was modified on
disc."
  :group 'gnus-newsrc
  :type 'boolean)

(defcustom gnus-check-bogus-groups-hook nil
  "A hook run after removing bogus groups."
  :group 'gnus-start-server
  :type 'hook)

(defcustom gnus-startup-hook nil
  "A hook called at startup.
This hook is called after Gnus is connected to the NNTP server."
  :group 'gnus-start
  :type 'hook)

397
(defcustom gnus-before-startup-hook nil
Miles Bader's avatar
Miles Bader committed
398
  "A hook called before startup.
399 400 401 402 403 404 405 406 407
This hook is called as the first thing when Gnus is started.
See also `gnus-before-resume-hook'."
  :group 'gnus-start
  :type 'hook)

(defcustom gnus-before-resume-hook nil
  "A hook called before resuming Gnus after suspend.
This hook is called as the first thing when Gnus is resumed after a suspend.
See also `gnus-before-startup-hook'."
408
  :version "24.4"
409 410 411
  :group 'gnus-start
  :type 'hook)

Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
412 413 414 415 416
(defcustom gnus-started-hook nil
  "A hook called as the last thing after startup."
  :group 'gnus-start
  :type 'hook)

417
(defcustom gnus-setup-news-hook nil
418 419 420 421
  "A hook after reading the .newsrc file, but before generating the buffer."
  :group 'gnus-start
  :type 'hook)

422 423
(defcustom gnus-get-top-new-news-hook nil
  "A hook run just before Gnus checks for new news globally."
424
  :version "22.1"
425 426 427
  :group 'gnus-group-new
  :type 'hook)

Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
428 429 430 431 432 433
(defcustom gnus-get-new-news-hook nil
  "A hook run just before Gnus checks for new news."
  :group 'gnus-group-new
  :type 'hook)

(defcustom gnus-after-getting-new-news-hook
434
  '(gnus-display-time-event-handler)
435
  "A hook run after Gnus checks for new news when Gnus is already running."
436
  :version "24.1"
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
437 438 439
  :group 'gnus-group-new
  :type 'hook)

440 441 442 443 444
(defcustom gnus-read-newsrc-el-hook nil
  "A hook called after reading the newsrc.eld? file."
  :group 'gnus-newsrc
  :type 'hook)

Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
(defcustom gnus-save-newsrc-hook nil
  "A hook called before saving any of the newsrc files."
  :group 'gnus-newsrc
  :type 'hook)

(defcustom gnus-save-quick-newsrc-hook nil
  "A hook called just before saving the quick newsrc file.
Can be used to turn version control on or off."
  :group 'gnus-newsrc
  :type 'hook)

(defcustom gnus-save-standard-newsrc-hook nil
  "A hook called just before saving the standard newsrc file.
Can be used to turn version control on or off."
  :group 'gnus-newsrc
  :type 'hook)

462 463 464 465 466 467
(defcustom gnus-group-mode-hook nil
  "Hook for Gnus group mode."
  :group 'gnus-group-various
  :options '(gnus-topic-mode)
  :type 'hook)

468
(defcustom gnus-always-read-dribble-file nil
469
  "Unconditionally read the dribble file."
470 471 472
  :group 'gnus-newsrc
  :type 'boolean)

473 474
;;; Internal variables

475 476
;; Fixme: deal with old emacs-mule when mm-universal-coding-system is
;; utf-8-emacs.
477 478
(defvar gnus-ding-file-coding-system mm-universal-coding-system
  "Coding system for ding file.")
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505

(defvar gnus-newsrc-file-version nil)
(defvar gnus-override-subscribe-method nil)
(defvar gnus-dribble-buffer nil)
(defvar gnus-newsrc-options nil
  "Options line in the .newsrc file.")

(defvar gnus-newsrc-options-n nil
  "List of regexps representing groups to be subscribed/ignored unconditionally.")

(defvar gnus-newsrc-last-checked-date nil
  "Date Gnus last asked server for new newsgroups.")

(defvar gnus-current-startup-file nil
  "Startup file for the current host.")

;; Byte-compiler warning.
(defvar gnus-group-line-format)

;; Suggested by Brian Edmonds <edmonds@cs.ubc.ca>.
(defvar gnus-init-inhibit nil)
(defun gnus-read-init-file (&optional inhibit-next)
  ;; Don't load .gnus if the -q option was used.
  (when init-file-user
    (if gnus-init-inhibit
	(setq gnus-init-inhibit nil)
      (setq gnus-init-inhibit inhibit-next)
506 507 508 509 510 511 512 513
      (dolist (file (list gnus-site-init-file gnus-init-file))
	(when (and file
		   (locate-library file))
	  (if (or debug-on-error debug-on-quit)
	      (load file nil t)
	    (condition-case var
		(load file nil t)
	      (error
514
	       (error "Error in %s: %s" file (cadr var))))))))))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
515 516 517 518 519

;; For subscribing new newsgroup

(defun gnus-subscribe-hierarchical-interactive (groups)
  (let ((groups (sort groups 'string<))
520
	prefixes prefix start ans group starts real-group)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
521 522 523
    (while groups
      (setq prefixes (list "^"))
      (while (and groups prefixes)
524 525
	(while (not (string-match (car prefixes)
				  (gnus-group-real-name (car groups))))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
526 527 528
	  (setq prefixes (cdr prefixes)))
	(setq prefix (car prefixes))
	(setq start (1- (length prefix)))
529 530
	(if (and (string-match "[^\\.]\\." (gnus-group-real-name (car groups))
			       start)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
531 532
		 (cdr groups)
		 (setq prefix
533 534 535 536
		       (concat "^" (substring
				    (gnus-group-real-name (car groups))
				    0 (match-end 0))))
		 (string-match prefix (gnus-group-real-name (cadr groups))))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
537 538 539 540
	    (progn
	      (push prefix prefixes)
	      (message "Descend hierarchy %s? ([y]nsq): "
		       (substring prefix 1 (1- (length prefix))))
541 542
	      (while (not (memq (setq ans (read-char-exclusive))
				'(?y ?\n ?\r ?n ?s ?q)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
543 544 545 546
		(ding)
		(message "Descend hierarchy %s? ([y]nsq): "
			 (substring prefix 1 (1- (length prefix)))))
	      (cond ((= ans ?n)
547 548 549 550
		     (dolist (g groups)
		       (when (string-match prefix (gnus-group-real-name g))
			 (push g gnus-killed-list)
			 (puthash g t gnus-killed-hashtb)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
551 552
		     (setq starts (cdr starts)))
		    ((= ans ?s)
553 554 555 556
		     (dolist (g groups)
		       (when (string-match prefix (gnus-group-real-name g))
			 (puthash g t gnus-killed-hashtb)
			 (gnus-subscribe-alphabetically g)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
557 558
		     (setq starts (cdr starts)))
		    ((= ans ?q)
559 560 561
		     (dolist (g groups)
		       (push g gnus-killed-list)
		       (puthash g t gnus-killed-hashtb)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
562 563
		    (t nil)))
	  (message "Subscribe %s? ([n]yq)" (car groups))
564 565
	  (while (not (memq (setq ans (read-char-exclusive))
			    '(?y ?\n ?\r ?q ?n)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
566 567 568 569 570
	    (ding)
	    (message "Subscribe %s? ([n]yq)" (car groups)))
	  (setq group (car groups))
	  (cond ((= ans ?y)
		 (gnus-subscribe-alphabetically (car groups))
571
		 (puthash group t gnus-killed-hashtb))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
572
		((= ans ?q)
573 574 575
		 (dolist (g groups)
		   (push g gnus-killed-list)
		   (puthash g t gnus-killed-hashtb)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
576 577
		(t
		 (push group gnus-killed-list)
578
		 (puthash group t gnus-killed-hashtb)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
579 580 581 582 583 584 585
	  (setq groups (cdr groups)))))))

(defun gnus-subscribe-randomly (newsgroup)
  "Subscribe new NEWSGROUP by making it the first newsgroup."
  (gnus-subscribe-newsgroup newsgroup))

(defun gnus-subscribe-alphabetically (newgroup)
586
  "Subscribe new NEWGROUP and insert it in alphabetical order."
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
587 588 589 590 591 592 593 594 595
  (let ((groups (cdr gnus-newsrc-alist))
	before)
    (while (and (not before) groups)
      (if (string< newgroup (caar groups))
	  (setq before (caar groups))
	(setq groups (cdr groups))))
    (gnus-subscribe-newsgroup newgroup before)))

(defun gnus-subscribe-hierarchically (newgroup)
596
  "Subscribe new NEWGROUP and insert it in hierarchical newsgroup order."
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
597
  ;; Basic ideas by mike-w@cs.aukuni.ac.nz (Mike Williams)
598
  (with-current-buffer (nnheader-find-file-noselect gnus-current-startup-file)
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
    (prog1
	(let ((groupkey newgroup) before)
	  (while (and (not before) groupkey)
	    (goto-char (point-min))
	    (let ((groupkey-re
		   (concat "^\\(" (regexp-quote groupkey) ".*\\)[!:]")))
	      (while (and (re-search-forward groupkey-re nil t)
			  (progn
			    (setq before (match-string 1))
			    (string< before newgroup)))))
	    ;; Remove tail of newsgroup name (eg. a.b.c -> a.b)
	    (setq groupkey
		  (when (string-match "^\\(.*\\)\\.[^.]+$" groupkey)
		    (substring groupkey (match-beginning 1) (match-end 1)))))
	  (gnus-subscribe-newsgroup newgroup before))
      (kill-buffer (current-buffer)))))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
615 616 617 618 619

(defun gnus-subscribe-interactively (group)
  "Subscribe the new GROUP interactively.
It is inserted in hierarchical newsgroup order if subscribed.  If not,
it is killed."
620
  (if (gnus-y-or-n-p (format "Subscribe new newsgroup %s? " group))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
621 622 623 624 625 626 627 628 629 630 631 632 633
      (gnus-subscribe-hierarchically group)
    (push group gnus-killed-list)))

(defun gnus-subscribe-zombies (group)
  "Make the new GROUP into a zombie group."
  (push group gnus-zombie-list))

(defun gnus-subscribe-killed (group)
  "Make the new GROUP a killed group."
  (push group gnus-killed-list))

(defun gnus-subscribe-newsgroup (newsgroup &optional next)
  "Subscribe new NEWSGROUP.
634
If NEXT is non-nil, it is inserted before NEXT.  Otherwise it is made
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
635 636 637 638 639 640
the first newsgroup."
  (save-excursion
    (goto-char (point-min))
    ;; We subscribe the group by changing its level to `subscribed'.
    (gnus-group-change-level
     newsgroup gnus-level-default-subscribed
641
     gnus-level-killed (or next "dummy.group"))
642
    (gnus-request-update-group-status newsgroup 'subscribe)
643
    (gnus-message 5 "Subscribe newsgroup: %s" newsgroup)
Stefan Monnier's avatar
Stefan Monnier committed
644
    (run-hook-with-args 'gnus-subscribe-newsgroup-functions newsgroup)
645
    t))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
646 647 648 649 650 651 652 653

(defun gnus-read-active-file-p ()
  "Say whether the active file has been read from `gnus-select-method'."
  (memq gnus-select-method gnus-have-read-active-file))

;;; General various misc type functions.

;; Silence byte-compiler.
Dan Nicolaescu's avatar
Dan Nicolaescu committed
654 655 656 657 658 659 660 661 662 663 664 665 666 667
(defvar gnus-current-headers)
(defvar gnus-thread-indent-array)
(defvar gnus-newsgroup-name)
(defvar gnus-newsgroup-headers)
(defvar gnus-group-list-mode)
(defvar gnus-group-mark-positions)
(defvar gnus-newsgroup-data)
(defvar gnus-newsgroup-unreads)
(defvar nnoo-state-alist)
(defvar gnus-current-select-method)
(defvar mail-sources)
(defvar nnmail-scan-directory-mail-source-once)
(defvar nnmail-split-history)
(defvar nnmail-spool-file)
668 669 670 671 672 673

(defun gnus-close-all-servers ()
  "Close all servers."
  (interactive)
  (dolist (server gnus-opened-servers)
    (gnus-close-server (car server))))
674

Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
675 676 677
(defun gnus-clear-system ()
  "Clear all variables and buffers."
  ;; Clear Gnus variables.
678
  (let ((variables (remove 'gnus-format-specs gnus-variable-list)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
679 680 681 682 683 684
    (while variables
      (set (car variables) nil)
      (setq variables (cdr variables))))
  ;; Clear other internal variables.
  (setq gnus-list-of-killed-groups nil
	gnus-have-read-active-file nil
685
        gnus-agent-covered-methods nil
686 687
        gnus-agent-file-loading-local nil
        gnus-agent-file-loading-cache nil
688
        gnus-server-method-cache nil
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
689
	gnus-newsrc-alist nil
690
	gnus-group-list nil
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
	gnus-newsrc-hashtb nil
	gnus-killed-list nil
	gnus-zombie-list nil
	gnus-killed-hashtb nil
	gnus-active-hashtb nil
	gnus-moderated-hashtb nil
	gnus-description-hashtb nil
	gnus-current-headers nil
	gnus-thread-indent-array nil
	gnus-newsgroup-headers nil
	gnus-newsgroup-name nil
	gnus-server-alist nil
	gnus-group-list-mode nil
	gnus-opened-servers nil
	gnus-group-mark-positions nil
	gnus-newsgroup-data nil
	gnus-newsgroup-unreads nil
	nnoo-state-alist nil
709
	gnus-current-select-method nil
710
	nnmail-split-history nil
711
	gnus-extended-servers nil
712
	gnus-ephemeral-servers nil)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
713 714 715 716 717 718 719 720 721 722 723 724
  (gnus-shutdown 'gnus)
  ;; Kill the startup file.
  (and gnus-current-startup-file
       (get-file-buffer gnus-current-startup-file)
       (kill-buffer (get-file-buffer gnus-current-startup-file)))
  ;; Clear the dribble buffer.
  (gnus-dribble-clear)
  ;; Kill global KILL file buffer.
  (when (get-file-buffer (gnus-newsgroup-kill-file nil))
    (kill-buffer (get-file-buffer (gnus-newsgroup-kill-file nil))))
  (gnus-kill-buffer nntp-server-buffer)
  ;; Kill Gnus buffers.
725
  (do-auto-save t)
726
  (dolist (buffer (gnus-buffers))
727 728 729 730 731
    (when (gnus-buffer-exists-p buffer)
      (with-current-buffer buffer
	(set-buffer-modified-p nil)
	(when (local-variable-p 'kill-buffer-hook)
	  (setq kill-buffer-hook nil))))
732
    (gnus-kill-buffer buffer))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
733 734 735 736 737
  ;; Remove Gnus frames.
  (gnus-kill-gnus-frames))

(defun gnus-no-server-1 (&optional arg slave)
  "Read network news.
738 739 740 741 742 743
If ARG is a positive number, Gnus will use that as the startup
level.  If ARG is nil, Gnus will be started at level 2
\(`gnus-level-default-subscribed' minus one).  If ARG is non-nil
and not a positive number, Gnus will prompt the user for the name
of an NNTP server to use.  As opposed to \\[gnus], this command
will not connect to the local server."
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
744 745 746 747 748 749 750 751 752
  (interactive "P")
  (let ((val (or arg (1- gnus-level-default-subscribed))))
    (gnus val t slave)
    (make-local-variable 'gnus-group-use-permanent-levels)
    (setq gnus-group-use-permanent-levels val)))

(defun gnus-1 (&optional arg dont-connect slave)
  "Read network news.
If ARG is non-nil and a positive number, Gnus will use that as the
753
startup level.  If ARG is non-nil and not a positive number, Gnus will
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
754 755 756
prompt the user for the name of an NNTP server to use."
  (interactive "P")

757
  (if (gnus-alive-p)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
758
      (progn
759
	(gnus-run-hooks 'gnus-before-resume-hook)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
760 761 762 763 764 765 766
	(switch-to-buffer gnus-group-buffer)
	(gnus-group-get-new-news
	 (and (numberp arg)
	      (> arg 0)
	      (max (car gnus-group-list-mode) arg))))

    (gnus-clear-system)
767 768
    (gnus-splash)
    (gnus-run-hooks 'gnus-before-startup-hook)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
769 770
    (nnheader-init-server-buffer)
    (setq gnus-slave slave)
771
    (gnus-read-init-file)
772 773 774 775

    ;; Add "native" to gnus-predefined-server-alist just to have a
    ;; name for the native select method.
    (when gnus-select-method
776 777
      (add-to-list 'gnus-predefined-server-alist
		   (cons "native" gnus-select-method)))
778

779 780
    (if gnus-agent
	(gnus-agentize))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
781 782 783 784 785 786 787 788 789 790

    (let ((level (and (numberp arg) (> arg 0) arg))
	  did-connect)
      (unwind-protect
	  (progn
	    (unless dont-connect
	      (setq did-connect
		    (gnus-start-news-server (and arg (not level))))))
	(if (and (not dont-connect)
		 (not did-connect))
791
	    ;; Couldn't connect to the server, so bail out.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
792
	    (gnus-group-quit)
793
	  (gnus-run-hooks 'gnus-startup-hook)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
794 795 796 797 798 799 800 801 802 803
	  ;; Find the current startup file name.
	  (setq gnus-current-startup-file
		(gnus-make-newsrc-file gnus-startup-file))

	  ;; Read the dribble file.
	  (when (or gnus-slave gnus-use-dribble-file)
	    (gnus-dribble-read-file))

	  ;; Do the actual startup.
	  (gnus-setup-news nil level dont-connect)
804
	  (gnus-run-hooks 'gnus-setup-news-hook)
805 806
	  (when gnus-agent
	    (gnus-request-create-group "queue" '(nndraft "")))
807
	  (gnus-start-draft-setup)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
808 809 810 811 812
	  ;; Generate the group buffer.
	  (gnus-group-list-groups level)
	  (gnus-group-first-unread-group)
	  (gnus-configure-windows 'group)
	  (gnus-group-set-mode-line)
813 814 815 816
	  (gnus-run-hooks 'gnus-started-hook))))))

(defun gnus-start-draft-setup ()
  "Make sure the draft group exists."
817
  (interactive)
818
  (gnus-request-create-group "drafts" '(nndraft ""))
819
  (unless (gnus-group-entry "nndraft:drafts")
820
    (let ((gnus-level-default-subscribed 1))
821 822
      (gnus-subscribe-group "nndraft:drafts" nil '(nndraft "")))
    (setcar (gnus-group-entry "nndraft:drafts") 0))
823 824
  (unless (equal (gnus-group-get-parameter "nndraft:drafts" 'gnus-dummy t)
		 '((gnus-draft-mode)))
825 826
    (gnus-group-set-parameter
     "nndraft:drafts" 'gnus-dummy '((gnus-draft-mode)))))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844


;;;
;;; Dribble file
;;;

(defvar gnus-dribble-ignore nil)
(defvar gnus-dribble-eval-file nil)

(defun gnus-dribble-file-name ()
  "Return the dribble file for the current .newsrc."
  (concat
   (if gnus-dribble-directory
       (concat (file-name-as-directory gnus-dribble-directory)
	       (file-name-nondirectory gnus-current-startup-file))
     gnus-current-startup-file)
   "-dribble"))

845 846 847
(defun gnus-dribble-enter (string &optional regexp)
  "Enter STRING into the dribble buffer.
If REGEXP is given, lines that match it will be deleted."
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
848 849 850 851 852
  (when (and (not gnus-dribble-ignore)
	     gnus-dribble-buffer
	     (buffer-name gnus-dribble-buffer))
    (let ((obuf (current-buffer)))
      (set-buffer gnus-dribble-buffer)
853 854 855 856 857 858 859 860
      (when regexp
	(goto-char (point-min))
	(let (end)
	  (while (re-search-forward regexp nil t)
	    (unless (bolp) (forward-line 1))
	    (setq end (point))
	    (goto-char (match-beginning 0))
	    (delete-region (point-at-bol) end))))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
861
      (goto-char (point-max))
862 863 864
      ;; Make sure that each dribble entry is a single line, so that
      ;; the "remove" code above works.
      (insert (replace-regexp-in-string "\n" "\\\\n" string) "\n")
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
865
      (bury-buffer gnus-dribble-buffer)
866
      (with-current-buffer gnus-group-buffer
867
	(gnus-group-set-mode-line))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
868 869 870 871 872 873 874 875 876
      (set-buffer obuf))))

(defun gnus-dribble-touch ()
  "Touch the dribble buffer."
  (gnus-dribble-enter ""))

(defun gnus-dribble-read-file ()
  "Read the dribble file from disk."
  (let ((dribble-file (gnus-dribble-file-name)))
877 878
    (unless (file-exists-p (file-name-directory dribble-file))
      (make-directory (file-name-directory dribble-file) t))
879 880 881
    (with-current-buffer (setq gnus-dribble-buffer
			       (gnus-get-buffer-create
				(file-name-nondirectory dribble-file)))
882
      (set (make-local-variable 'file-precious-flag) t)
883
      (setq buffer-save-without-query t)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
884 885
      (erase-buffer)
      (setq buffer-file-name dribble-file)
886 887
      ;; The buffer may be shrunk a lot when deleting old entries.
      ;; It caused the auto-saving to stop.
888
      (set (make-local-variable 'auto-save-include-big-deletions) t)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
889
      (auto-save-mode t)
890
      (buffer-disable-undo)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
891 892 893 894
      (bury-buffer (current-buffer))
      (set-buffer-modified-p nil)
      (let ((auto (make-auto-save-file-name))
	    (gnus-dribble-ignore t)
895
	    (purpose nil)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
896 897 898 899 900 901 902 903 904 905 906 907
	    modes)
	(when (or (file-exists-p auto) (file-exists-p dribble-file))
	  ;; Load whichever file is newest -- the auto save file
	  ;; or the "real" file.
	  (if (file-newer-than-file-p auto dribble-file)
	      (nnheader-insert-file-contents auto)
	    (nnheader-insert-file-contents dribble-file))
	  (unless (zerop (buffer-size))
	    (set-buffer-modified-p t))
	  ;; Set the file modes to reflect the .newsrc file modes.
	  (save-buffer)
	  (when (and (file-exists-p gnus-current-startup-file)
908
		     (file-exists-p dribble-file)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
909
		     (setq modes (file-modes gnus-current-startup-file)))
910
	    (gnus-set-file-modes dribble-file modes))
911 912 913
	  (goto-char (point-min))
	  (when (search-forward "Gnus was exited on purpose" nil t)
	    (setq purpose t))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
914
	  ;; Possibly eval the file later.
915 916
	  (when (or gnus-always-read-dribble-file
		    (gnus-y-or-n-p
917 918 919
		     (if purpose
			 "Gnus exited on purpose without saving; read auto-save file anyway? "
		     "Gnus auto-save file exists.  Do you want to read it? ")))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
920 921 922 923 924 925 926 927 928 929 930 931 932 933
	    (setq gnus-dribble-eval-file t)))))))

(defun gnus-dribble-eval-file ()
  (when gnus-dribble-eval-file
    (setq gnus-dribble-eval-file nil)
    (save-excursion
      (let ((gnus-dribble-ignore t))
	(set-buffer gnus-dribble-buffer)
	(eval-buffer (current-buffer))))))

(defun gnus-dribble-delete-file ()
  (when (file-exists-p (gnus-dribble-file-name))
    (delete-file (gnus-dribble-file-name)))
  (when gnus-dribble-buffer
934
    (with-current-buffer gnus-dribble-buffer
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
935 936 937 938 939 940 941 942 943
      (let ((auto (make-auto-save-file-name)))
	(when (file-exists-p auto)
	  (delete-file auto))
	(erase-buffer)
	(set-buffer-modified-p nil)))))

(defun gnus-dribble-save ()
  (when (and gnus-dribble-buffer
	     (buffer-name gnus-dribble-buffer))
944
    (with-current-buffer gnus-dribble-buffer
945 946
      (when (> (buffer-size) 0)
	(save-buffer)))))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
947 948 949

(defun gnus-dribble-clear ()
  (when (gnus-buffer-exists-p gnus-dribble-buffer)
950
    (with-current-buffer gnus-dribble-buffer
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
951 952 953 954 955 956 957 958 959 960 961 962 963
      (erase-buffer)
      (set-buffer-modified-p nil)
      (setq buffer-saved-size (buffer-size)))))


;;;
;;; Active & Newsrc File Handling
;;;

(defun gnus-setup-news (&optional rawfile level dont-connect)
  "Setup news information.
If RAWFILE is non-nil, the .newsrc file will also be read.
If LEVEL is non-nil, the news will be set up at level LEVEL."
964 965 966 967 968
  (require 'nnmail)
  (let ((init (not (and gnus-newsrc-alist gnus-active-hashtb (not rawfile))))
	;; Binding this variable will inhibit multiple fetchings
	;; of the same mail source.
	(nnmail-fetched-sources (list t)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
969 970 971 972 973 974 975 976

    (when init
      ;; Clear some variables to re-initialize news information.
      (setq gnus-newsrc-alist nil
	    gnus-active-hashtb nil)
      ;; Read the newsrc file and create `gnus-newsrc-hashtb'.
      (gnus-read-newsrc-file rawfile))

977
    ;; Make sure the archive server is available to all and sundry.
978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005
    (let ((method (or (and (stringp gnus-message-archive-method)
			   (gnus-server-to-method
			    gnus-message-archive-method))
		      gnus-message-archive-method)))
      ;; Check whether the archive method is writable.
      (unless (or (not method)
		  (stringp method)
		  (memq 'respool (assoc (format "%s" (car method))
					gnus-valid-select-methods)))
	(setq method "archive")) ;; The default.
      (when (stringp method)
	(setq method `(nnfolder
		       ,method
		       (nnfolder-directory
			,(nnheader-concat message-directory method))
		       (nnfolder-active-file
			,(nnheader-concat message-directory
					  (concat method "/active")))
		       (nnfolder-get-new-mail nil)
		       (nnfolder-inhibit-expiry t))))
      (if (assoc "archive" gnus-server-alist)
	  (when gnus-update-message-archive-method
	    (if method
		(setcdr (assoc "archive" gnus-server-alist) method)
	      (setq gnus-server-alist (delq (assoc "archive" gnus-server-alist)
					    gnus-server-alist))))
	(when method
	  (push (cons "archive" method) gnus-server-alist))))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
1006 1007 1008 1009 1010 1011 1012

    ;; If we don't read the complete active file, we fill in the
    ;; hashtb here.
    (when (or (null gnus-read-active-file)
	      (eq gnus-read-active-file 'some))
      (gnus-update-active-hashtb-from-killed))
    (unless gnus-active-hashtb
1013
      (setq gnus-active-hashtb (gnus-make-hashtable 4000)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
    ;; Initialize the cache.
    (when gnus-use-cache
      (gnus-cache-open))

    ;; Possibly eval the dribble file.
    (and init
	 (or gnus-use-dribble-file gnus-slave)
	 (gnus-dribble-eval-file))

    ;; Slave Gnusii should then clear the dribble buffer.
    (when (and init gnus-slave)
      (gnus-dribble-clear))

    (gnus-update-format-specifications)

    ;; See whether we need to read the description file.
    (when (and (boundp 'gnus-group-line-format)
1031
	       (stringp gnus-group-line-format)
1032 1033
	       (let ((case-fold-search nil))
		 (string-match "%[-,0-9]*D" gnus-group-line-format))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
1034 1035 1036 1037 1038 1039 1040 1041
	       (not gnus-description-hashtb)
	       (not dont-connect)
	       gnus-read-active-file)
      (gnus-read-all-descriptions-files))

    ;; Find new newsgroups and treat them.
    (when (and init gnus-check-new-newsgroups (not level)
	       (gnus-check-server gnus-select-method)
1042 1043
	       (not gnus-slave)
	       gnus-plugged)
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
1044 1045
      (gnus-find-new-newsgroups))

1046 1047 1048 1049 1050 1051
    ;; Check and remove bogus newsgroups.
    (when (and init gnus-check-bogus-newsgroups
	       gnus-read-active-file (not level)
	       (gnus-server-opened gnus-select-method))
      (gnus-check-bogus-newsgroups))

Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
1052 1053 1054 1055 1056
    ;; Read any slave files.
    (gnus-master-read-slave-newsrc)

    ;; Find the number of unread articles in each non-dead group.
    (let ((gnus-read-active-file (and (not level) gnus-read-active-file)))
1057
      (gnus-get-unread-articles level dont-connect))))
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072

(defun gnus-call-subscribe-functions (method group)
  "Call METHOD to subscribe GROUP.
If no function returns `non-nil', call `gnus-subscribe-zombies'."
  (unless (cond
	   ((functionp method)
	    (funcall method group))
	   ((listp method)
	    (catch 'found
	      (dolist (func method)
		(if (funcall func group)
		    (throw 'found t)))
	      nil))
	   (t nil))
    (gnus-subscribe-zombies group)))
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
1073 1074 1075

(defun gnus-find-new-newsgroups (&optional arg)
  "Search for new newsgroups and add them.
1076
Each new newsgroup will be treated with `gnus-subscribe-newsgroup-method'.
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
1077
The `-n' option line from .newsrc is respected.
1078 1079 1080 1081 1082 1083 1084 1085 1086

With 1 C-u, use the `ask-server' method to query the server for new
groups.
With 2 C-u's, use most complete method possible to query the server
for new groups, and subscribe the new groups as zombies."
  (interactive "p")
  (let* ((gnus-subscribe-newsgroup-method
	  gnus-subscribe-newsgroup-method)
	 (check (cond
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
		 ((or (and (= (or arg 1) 4)
			   (not (listp gnus-check-new-newsgroups)))
		      (null gnus-read-active-file)
		      (eq gnus-read-active-file 'some))
		  'ask-server)
		 ((= (or arg 1) 16)
		  (setq gnus-subscribe-newsgroup-method
			'gnus-subscribe-zombies)
		  t)
		 (t gnus-check-new-newsgroups))))
1097 1098 1099 1100 1101 1102
    (if (or (consp check)
            (eq check 'ask-server))
        ;; Ask the server for new groups.
        (gnus-ask-server-for-new-groups)
      ;; Go through the active hashtb and look for new groups.
      (let ((groups 0)
1103
            new-newsgroups)
1104 1105 1106 1107 1108 1109 1110 1111
        (gnus-message 5 "Looking for new newsgroups...")
        (unless gnus-have-read-active-file
          (gnus-read-active-file))
        (setq gnus-newsrc-last-checked-date (message-make-date))
        (unless gnus-killed-hashtb
          (gnus-make-hashtable-from-killed))
        ;; Go though every newsgroup in `gnus-active-hashtb' and compare
        ;; with `gnus-newsrc-hashtb' and `gnus-killed-hashtb'.
1112 1113 1114 1115 1116
        (maphash
         (lambda (g-name active)
           (unless (or (gethash g-name gnus-killed-hashtb)
                       (gethash g-name gnus-newsrc-hashtb))
             (let ((do-sub (gnus-matches-options-n g-name)))