(gnus-version-number): Bumped version.
[gnus] / lisp / gnus.el
index 710c94b..5dfc04c 100644 (file)
@@ -33,6 +33,7 @@
 (eval-when-compile (require 'cl))
 (require 'wid-edit)
 (require 'mm-util)
+(require 'nnheader)
 
 ;; Make sure it was the right mm-util.
 (unless (fboundp 'mm-guess-mime-charset)
@@ -281,7 +282,7 @@ is restarted, and sometimes reloaded."
   :link '(custom-manual "(gnus)Exiting Gnus")
   :group 'gnus)
 
-(defconst gnus-version-number "0.08"
+(defconst gnus-version-number "0.13"
   "Version number for this version of Gnus.")
 
 (defconst gnus-version (format "Oort Gnus v%s" gnus-version-number)
@@ -671,6 +672,33 @@ be set in `.emacs' instead."
      ()))
   "Face used for normal interest ancient articles.")
 
+(defface gnus-summary-high-undownloaded-face
+   '((((class color)
+       (background light))
+      (:bold t :foreground "cyan4" :bold nil))
+     (((class color) (background dark))
+      (:bold t :foreground "LightGray" :bold nil))
+     (t (:inverse-video t :bold t)))
+  "Face used for high interest uncached articles.")
+
+(defface gnus-summary-low-undownloaded-face
+   '((((class color)
+       (background light))
+      (:italic t :foreground "cyan4" :bold nil))
+     (((class color) (background dark))
+      (:italic t :foreground "LightGray" :bold nil))
+     (t (:inverse-video t :italic t)))
+  "Face used for low interest uncached articles.")
+
+(defface gnus-summary-normal-undownloaded-face
+   '((((class color)
+       (background light))
+      (:foreground "cyan4" :bold nil))
+     (((class color) (background dark))
+      (:foreground "LightGray" :bold nil))
+     (t (:inverse-video t)))
+  "Face used for normal interest uncached articles.")
+
 (defface gnus-summary-high-unread-face
   '((t
      (:bold t)))
@@ -835,20 +863,22 @@ be set in `.emacs' instead."
    ((and
      (fboundp 'find-image)
      (display-graphic-p)
-     (let ((image (find-image
-                  `((:type xpm :file "gnus.xpm"
-                           :color-symbols
-                           (("thing" . ,(car gnus-logo-colors))
-                            ("shadow" . ,(cadr gnus-logo-colors))
-                            ("background" . ,(face-background 'default))))
-                    (:type pbm :file "gnus.pbm"
-                           ;; Account for the pbm's blackground.
-                           :background ,(face-foreground 'gnus-splash-face)
-                           :foreground ,(face-background 'default))
-                    (:type xbm :file "gnus.xbm"
-                           ;; Account for the xbm's blackground.
-                           :background ,(face-foreground 'gnus-splash-face)
-                           :foreground ,(face-background 'default))))))
+     (let* ((data-directory (nnheader-find-etc-directory "gnus"))
+           (image (find-image
+                   `((:type xpm :file "gnus.xpm"
+                            :color-symbols
+                            (("thing" . ,(car gnus-logo-colors))
+                             ("shadow" . ,(cadr gnus-logo-colors))
+                             ("oort" . "#eeeeee")
+                             ("background" . ,(face-background 'default))))
+                     (:type pbm :file "gnus.pbm"
+                            ;; Account for the pbm's blackground.
+                            :background ,(face-foreground 'gnus-splash-face)
+                            :foreground ,(face-background 'default))
+                     (:type xbm :file "gnus.xbm"
+                            ;; Account for the xbm's blackground.
+                            :background ,(face-foreground 'gnus-splash-face)
+                            :foreground ,(face-background 'default))))))
        (when image
         (let ((size (image-size image)))
           (insert-char ?\n (max 0 (round (- (window-height)
@@ -1374,7 +1404,7 @@ cache to the full extent of the law."
   :group 'gnus-meta
   :type 'boolean)
 
-(defcustom gnus-keep-backlog nil
+(defcustom gnus-keep-backlog 20
   "*If non-nil, Gnus will keep read articles for later re-retrieval.
 If it is a number N, then Gnus will only keep the last N articles
 read.  If it is neither nil nor a number, Gnus will keep all read
@@ -1714,6 +1744,183 @@ articles to list when the group is a large newsgroup (see
 `gnus-large-newsgroup').  If it is `nil', the default value is the
 total number of articles in the group.")
 
+;; group parameters for spam processing added by Ted Zlatanov <tzz@lifelogs.com>
+(defvar gnus-group-spam-classification-spam t
+  "Spam group classification (requires spam.el).
+This group contains spam messages.  On summary entry, unread messages
+will be marked as spam.  On summary exit, the specified spam
+processors will be invoked on spam-marked messages, then those
+messages will be expired, so the spam processor will only see a
+spam-marked message once.")
+
+(defvar gnus-group-spam-classification-ham 'ask
+  "The ham value for the spam group parameter (requires spam.el).
+On summary exit, the specified ham processors will be invoked on
+ham-marked messages.  Exercise caution, since the ham processor will
+see the same message more than once because there is no ham message
+registry.")
+
+(gnus-define-group-parameter
+ spam-contents
+ :type list
+ :function-document
+ "The spam type (spam, ham, or neither) of the group."
+ :variable gnus-spam-newsgroup-contents
+ :variable-default nil
+ :variable-document
+ "*Groups in which to automatically mark new articles as spam on
+summary entry.  If non-nil, this should be a list of group name
+regexps that should match all groups in which to do automatic spam
+tagging, associated with a classification (spam, ham, or neither).
+This only makes sense for mail groups."
+ :variable-group spam
+ :variable-type '(repeat 
+                        (list :tag "Group contents spam/ham classification"
+                         (regexp :tag "Group")
+                         (choice
+                          (variable-item gnus-group-spam-classification-spam)
+                          (variable-item gnus-group-spam-classification-ham)
+                          (other :tag "Unclassified" nil))))
+
+ :parameter-type '(list :tag "Group contents spam/ham classification"
+                  (choice :tag "Group contents classification for spam sorting"
+                          (variable-item gnus-group-spam-classification-spam)
+                          (variable-item gnus-group-spam-classification-ham)
+                          (other :tag "Unclassified" nil)))
+ :parameter-document
+ "The spam classification (spam, ham, or neither) of this group.
+When a spam group is entered, all unread articles are marked as spam.")
+
+(defvar gnus-group-spam-exit-processor-ifile "ifile"
+  "The ifile summary exit spam processor.
+Only applicable to spam groups.")
+
+(defvar gnus-group-spam-exit-processor-stat "stat"
+  "The spam-stat summary exit spam processor.
+Only applicable to spam groups.")
+
+(defvar gnus-group-spam-exit-processor-bogofilter "bogofilter"
+  "The Bogofilter summary exit spam processor.
+Only applicable to spam groups.")
+
+(defvar gnus-group-spam-exit-processor-blacklist "blacklist"
+  "The Blacklist summary exit spam processor.
+Only applicable to spam groups.")
+
+(defvar gnus-group-ham-exit-processor-ifile "ifile-ham"
+  "The ifile summary exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+(defvar gnus-group-ham-exit-processor-stat "stat-ham"
+  "The spam-stat summary exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+(defvar gnus-group-ham-exit-processor-whitelist "whitelist"
+  "The whitelist summary exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+(defvar gnus-group-ham-exit-processor-BBDB "bbdb"
+  "The BBDB summary exit ham processor.
+Only applicable to non-spam (unclassified and ham) groups.")
+
+(gnus-define-group-parameter
+ spam-process
+ :type list
+ :parameter-type '(choice :tag "Spam Summary Exit Processor"
+                          :value nil
+                         (list :tag "Spam Summary Exit Processor Choices"
+                          (set 
+                           (variable-item gnus-group-spam-exit-processor-ifile)
+                           (variable-item gnus-group-spam-exit-processor-stat)
+                           (variable-item gnus-group-spam-exit-processor-bogofilter)
+                           (variable-item gnus-group-spam-exit-processor-blacklist)
+                           (variable-item gnus-group-ham-exit-processor-ifile)
+                           (variable-item gnus-group-ham-exit-processor-stat)
+                           (variable-item gnus-group-ham-exit-processor-whitelist)
+                           (variable-item gnus-group-ham-exit-processor-BBDB))))
+ :function-document
+ "Which spam or ham processors will be applied to the GROUP articles at summary exit."
+ :variable gnus-spam-process-newsgroups
+ :variable-default nil
+ :variable-document
+ "*Groups in which to automatically process spam or ham articles with
+a backend on summary exit.  If non-nil, this should be a list of group
+name regexps that should match all groups in which to do automatic
+spam processing, associated with the appropriate processor.  This only makes sense
+for mail groups."
+ :variable-group spam
+ :variable-type '(repeat :tag "Spam/Ham Processors" 
+                        (list :tag "Spam Summary Exit Processor Choices"
+                         (regexp :tag "Group Regexp") 
+                         (set :tag "Spam/Ham Summary Exit Processor"
+                              (variable-item gnus-group-spam-exit-processor-ifile)
+                              (variable-item gnus-group-spam-exit-processor-stat)
+                              (variable-item gnus-group-spam-exit-processor-bogofilter)
+                              (variable-item gnus-group-spam-exit-processor-blacklist)
+                              (variable-item gnus-group-ham-exit-processor-ifile)
+                              (variable-item gnus-group-ham-exit-processor-stat)
+                              (variable-item gnus-group-ham-exit-processor-whitelist)
+                              (variable-item gnus-group-ham-exit-processor-BBDB))))
+ :parameter-document
+ "Which spam processors will be applied to the spam or ham GROUP articles at summary exit.")
+
+(gnus-define-group-parameter
+ spam-process-destination
+ :parameter-type '(choice :tag "Destination for spam-processed articles at summary exit"
+                         (string :tag "Move to a group")
+                         (other :tag "Expire" nil))
+ :function-document
+ "Where spam-processed articles will go at summary exit."
+ :variable gnus-spam-process-destinations
+ :variable-default nil
+ :variable-document
+ "*Groups in which to explicitly send spam-processed articles to
+another group, or expire them (the default).  If non-nil, this should
+be a list of group name regexps that should match all groups in which
+to do spam-processed article moving, associated with the destination
+group or `nil' for explicit expiration.  This only makes sense for
+mail groups."
+ :variable-group spam
+ :variable-type '(repeat 
+                 :tag "Spam-processed articles destination" 
+                 (list
+                  (regexp :tag "Group Regexp") 
+                  (choice 
+                   :tag "Destination for spam-processed articles at summary exit"
+                   (string :tag "Move to a group")
+                   (other :tag "Expire" nil))))
+ :parameter-document
+ "Where spam-processed articles will go at summary exit.")
+
+(gnus-define-group-parameter
+ ham-process-destination
+ :parameter-type '(choice 
+                  :tag "Destination for ham articles at summary exit from a spam group"
+                         (string :tag "Move to a group")
+                         (other :tag "Do nothing" nil))
+ :function-document
+ "Where ham articles will go at summary exit from a spam group."
+ :variable gnus-ham-process-destinations
+ :variable-default nil
+ :variable-document
+ "*Groups in which to explicitly send ham articles to
+another group, or do nothing (the default).  If non-nil, this should
+be a list of group name regexps that should match all groups in which
+to do ham article moving, associated with the destination
+group or `nil' for explicit ignoring.  This only makes sense for
+mail groups, and only works in spam groups."
+ :variable-group spam
+ :variable-type '(repeat 
+                 :tag "Ham articles destination" 
+                 (list
+                  (regexp :tag "Group Regexp") 
+                  (choice 
+                   :tag "Destination for ham articles at summary exit from spam group"
+                   (string :tag "Move to a group")
+                   (other :tag "Expire" nil))))
+ :parameter-document
+ "Where ham articles will go at summary exit from a spam group.")
+
 (defcustom gnus-group-uncollapsed-levels 1
   "Number of group name elements to leave alone when making a short group name."
   :group 'gnus-group-visual
@@ -2006,7 +2213,7 @@ such as a mark that says whether an article is stored in the cache
                        gnus-newsrc-alist gnus-server-alist
                        gnus-killed-list gnus-zombie-list
                        gnus-topic-topology gnus-topic-alist
-                       gnus-format-specs)
+                       gnus-agent-covered-methods gnus-format-specs)
   "Gnus variables saved in the quick startup file.")
 
 (defvar gnus-newsrc-alist nil
@@ -2104,7 +2311,8 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
      ("gnus-demon" :interactive t
       gnus-demon-init gnus-demon-cancel)
      ("gnus-fun" gnus-convert-gray-x-face-to-xpm gnus-display-x-face-in-from
-      gnus-convert-image-to-gray-x-face)
+      gnus-convert-image-to-gray-x-face gnus-convert-face-to-png
+      gnus-face-from-file)
      ("gnus-salt" gnus-highlight-selected-tree gnus-possibly-generate-tree
       gnus-tree-open gnus-tree-close gnus-carpal-setup-buffer)
      ("gnus-nocem" gnus-nocem-scan-groups gnus-nocem-close
@@ -3017,9 +3225,13 @@ You should probably use `gnus-find-method-for-group' instead."
 You should call this in the `gnus-group-buffer' buffer.
 The function `gnus-group-find-parameter' will do that for you."
   ;; The speed trick:  No cons'ing and quit early.
-  (or (let ((params (funcall gnus-group-get-parameter-function group)))
-       ;; Start easy, check the "real" group parameters.
-       (gnus-group-parameter-value params symbol allow-list))
+  (let* ((params (funcall gnus-group-get-parameter-function group))
+        ;; Start easy, check the "real" group parameters.
+        (simple-results
+         (gnus-group-parameter-value params symbol allow-list t)))
+    (if simple-results
+       ;; Found results; return them.
+       (car simple-results)
       ;; We didn't found it there, try `gnus-parameters'.
       (let ((result nil)
            (head nil)
@@ -3041,7 +3253,7 @@ The function `gnus-group-find-parameter' will do that for you."
              ;; Exit the loop early.
              (setq tail nil))))
        ;; Done.
-       result)))
+       result))))
 
 (defun gnus-group-find-parameter (group &optional symbol allow-list)
   "Return the group parameters for GROUP.
@@ -3068,7 +3280,8 @@ also examines the topic parameters."
        (gnus-group-parameter-value params symbol allow-list)
       params)))
 
-(defun gnus-group-parameter-value (params symbol &optional allow-list)
+(defun gnus-group-parameter-value (params symbol &optional
+                                         allow-list present-p)
   "Return the value of SYMBOL in group PARAMS."
   ;; We only wish to return group parameters (dotted lists) and
   ;; not local variables, which may have the same names.
@@ -3082,7 +3295,8 @@ also examines the topic parameters."
                       (eq (car elem) symbol)
                       (or allow-list
                           (atom (cdr elem))))
-             (throw 'found (cdr elem))))))))
+             (throw 'found (if present-p (list (cdr elem))
+                             (cdr elem)))))))))
 
 (defun gnus-group-add-parameter (group param)
   "Add parameter PARAM to GROUP."