*** empty log message ***
[gnus] / lisp / gnus.el
index 467b99a..33c1fdf 100644 (file)
 
 (eval '(run-hooks 'gnus-load-hook))
 
 
 (eval '(run-hooks 'gnus-load-hook))
 
+(eval-when-compile (require 'cl))
+
 (require 'custom)
 (require 'custom)
-(require 'gnus-load)
+(eval-and-compile
+  (if (< emacs-major-version 20)
+      (require 'gnus-load)))
 (require 'message)
 
 (defgroup gnus nil
 (require 'message)
 
 (defgroup gnus nil
   :group 'gnus
   :group 'faces)
 
   :group 'gnus
   :group 'faces)
 
+(defgroup gnus-agent nil
+  "Offline support for Gnus."
+  :group 'gnus)
+
 (defgroup gnus-files nil
   "Files used by Gnus."
   :group 'gnus)
 (defgroup gnus-files nil
   "Files used by Gnus."
   :group 'gnus)
@@ -238,10 +246,10 @@ is restarted, and sometimes reloaded."
   :link '(custom-manual "(gnus)Exiting Gnus")
   :group 'gnus)
 
   :link '(custom-manual "(gnus)Exiting Gnus")
   :group 'gnus)
 
-(defconst gnus-version-number "5.4.60"
+(defconst gnus-version-number "0.18"
   "Version number for this version of Gnus.")
 
   "Version number for this version of Gnus.")
 
-(defconst gnus-version (format "Gnus v%s" gnus-version-number)
+(defconst gnus-version (format "Quassia Gnus v%s" gnus-version-number)
   "Version string for this version of Gnus.")
 
 (defcustom gnus-inhibit-startup-message nil
   "Version string for this version of Gnus.")
 
 (defcustom gnus-inhibit-startup-message nil
@@ -260,6 +268,7 @@ be set in `.emacs' instead."
 
 (unless (featurep 'gnus-xmas)
   (defalias 'gnus-make-overlay 'make-overlay)
 
 (unless (featurep 'gnus-xmas)
   (defalias 'gnus-make-overlay 'make-overlay)
+  (defalias 'gnus-delete-overlay 'delete-overlay)
   (defalias 'gnus-overlay-put 'overlay-put)
   (defalias 'gnus-move-overlay 'move-overlay)
   (defalias 'gnus-overlay-end 'overlay-end)
   (defalias 'gnus-overlay-put 'overlay-put)
   (defalias 'gnus-move-overlay 'move-overlay)
   (defalias 'gnus-overlay-end 'overlay-end)
@@ -267,7 +276,6 @@ be set in `.emacs' instead."
   (defalias 'gnus-extent-start-open 'ignore)
   (defalias 'gnus-set-text-properties 'set-text-properties)
   (defalias 'gnus-group-remove-excess-properties 'ignore)
   (defalias 'gnus-extent-start-open 'ignore)
   (defalias 'gnus-set-text-properties 'set-text-properties)
   (defalias 'gnus-group-remove-excess-properties 'ignore)
-  (defalias 'gnus-topic-remove-excess-properties 'ignore)
   (defalias 'gnus-appt-select-lowest-window 'appt-select-lowest-window)
   (defalias 'gnus-mail-strip-quoted-names 'mail-strip-quoted-names)
   (defalias 'gnus-character-to-event 'identity)
   (defalias 'gnus-appt-select-lowest-window 'appt-select-lowest-window)
   (defalias 'gnus-mail-strip-quoted-names 'mail-strip-quoted-names)
   (defalias 'gnus-character-to-event 'identity)
@@ -275,47 +283,10 @@ be set in `.emacs' instead."
   (defalias 'gnus-put-text-property 'put-text-property)
   (defalias 'gnus-mode-line-buffer-identification 'identity)
   (defalias 'gnus-characterp 'numberp)
   (defalias 'gnus-put-text-property 'put-text-property)
   (defalias 'gnus-mode-line-buffer-identification 'identity)
   (defalias 'gnus-characterp 'numberp)
+  (defalias 'gnus-deactivate-mark 'deactivate-mark)
+  (defalias 'gnus-window-edges 'window-edges)
   (defalias 'gnus-key-press-event-p 'numberp))
 
   (defalias 'gnus-key-press-event-p 'numberp))
 
-;; The XEmacs people think this is evil, so it must go.
-(defun custom-face-lookup (&optional fg bg stipple bold italic underline)
-  "Lookup or create a face with specified attributes."
-  (let ((name (intern (format "custom-face-%s-%s-%s-%S-%S-%S"
-                             (or fg "default")
-                             (or bg "default")
-                             (or stipple "default")
-                             bold italic underline))))
-    (if (and (custom-facep name)
-            (fboundp 'make-face))
-       ()
-      (copy-face 'default name)
-      (when (and fg
-                (not (string-equal fg "default")))
-       (ignore-errors
-         (set-face-foreground name fg)))
-      (when (and bg
-                (not (string-equal bg "default")))
-       (ignore-errors
-         (set-face-background name bg)))
-      (when (and stipple
-                (not (string-equal stipple "default"))
-                (not (eq stipple 'custom:asis))
-                (fboundp 'set-face-stipple))
-       (set-face-stipple name stipple))
-      (when (and bold
-                (not (eq bold 'custom:asis)))
-       (ignore-errors
-         (make-face-bold name)))
-      (when (and italic
-                (not (eq italic 'custom:asis)))
-       (ignore-errors
-         (make-face-italic name)))
-      (when (and underline
-                (not (eq underline 'custom:asis)))
-       (ignore-errors
-         (set-face-underline-p name t))))
-    name))
-
 ;; We define these group faces here to avoid the display
 ;; update forced when creating new faces.
 
 ;; We define these group faces here to avoid the display
 ;; update forced when creating new faces.
 
@@ -635,17 +606,17 @@ be set in `.emacs' instead."
 (defface gnus-splash-face
   '((((class color)
       (background dark))
 (defface gnus-splash-face
   '((((class color)
       (background dark))
-     (:foreground "red"))
+     (:foreground "ForestGreen"))
     (((class color)
       (background light))
     (((class color)
       (background light))
-     (:foreground "red"))
+     (:foreground "ForestGreen"))
     (t
      ()))
   "Level 1 newsgroup face.")
 
 (defun gnus-splash ()
   (save-excursion
     (t
      ()))
   "Level 1 newsgroup face.")
 
 (defun gnus-splash ()
   (save-excursion
-    (switch-to-buffer gnus-group-buffer)
+    (switch-to-buffer (get-buffer-create gnus-group-buffer))
     (let ((buffer-read-only nil))
       (erase-buffer)
       (unless gnus-inhibit-startup-message
     (let ((buffer-read-only nil))
       (erase-buffer)
       (unless gnus-inhibit-startup-message
@@ -784,18 +755,20 @@ used to 899, you would say something along these lines:
                 (kill-buffer (current-buffer))))))))
 
 (defcustom gnus-select-method
                 (kill-buffer (current-buffer))))))))
 
 (defcustom gnus-select-method
-  (ignore-errors
+  (condition-case nil
     (nconc
     (nconc
-     (list 'nntp (or (ignore-errors
-                      (gnus-getenv-nntpserver))
+     (list 'nntp (or (condition-case nil
+                        (gnus-getenv-nntpserver)
+                      (error nil))
                     (when (and gnus-default-nntp-server
                                (not (string= gnus-default-nntp-server "")))
                       gnus-default-nntp-server)
                     (when (and gnus-default-nntp-server
                                (not (string= gnus-default-nntp-server "")))
                       gnus-default-nntp-server)
-                    (system-name)))
+                    "news"))
      (if (or (null gnus-nntp-service)
             (equal gnus-nntp-service "nntp"))
         nil
      (if (or (null gnus-nntp-service)
             (equal gnus-nntp-service "nntp"))
         nil
-       (list gnus-nntp-service))))
+       (list gnus-nntp-service)))
+    (error nil))
   "Default method for selecting a newsgroup.
 This variable should be a list, where the first element is how the
 news is to be fetched, the second is the address.
   "Default method for selecting a newsgroup.
 This variable should be a list, where the first element is how the
 news is to be fetched, the second is the address.
@@ -1152,7 +1125,8 @@ slower."
     ("nndraft" post-mail)
     ("nnfolder" mail respool address)
     ("nngateway" none address prompt-address physical-address)
     ("nndraft" post-mail)
     ("nnfolder" mail respool address)
     ("nngateway" none address prompt-address physical-address)
-    ("nnweb" none))
+    ("nnweb" none)
+    ("nnagent" post-mail))
   "An alist of valid select methods.
 The first element of each list lists should be a string with the name
 of the select method.  The other elements may be the category of
   "An alist of valid select methods.
 The first element of each list lists should be a string with the name
 of the select method.  The other elements may be the category of
@@ -1169,6 +1143,7 @@ this variable.    I think."
                        (checklist :inline t
                                   (const :format "%v " address)
                                   (const :format "%v " prompt-address)
                        (checklist :inline t
                                   (const :format "%v " address)
                                   (const :format "%v " prompt-address)
+                                  (const :format "%v " physical-address)
                                   (const :format "%v " virtual)
                                   (const respool)))))
 
                                   (const :format "%v " virtual)
                                   (const respool)))))
 
@@ -1387,6 +1362,9 @@ want."
   :group 'gnus-article-saving
   :type 'directory)
 
   :group 'gnus-article-saving
   :type 'directory)
 
+(defvar gnus-plugged t
+  "Whether Gnus is plugged or not.")
+
 \f
 ;;; Internal variables
 
 \f
 ;;; Internal variables
 
@@ -1394,6 +1372,12 @@ want."
 (defvar gnus-original-article-buffer " *Original Article*")
 (defvar gnus-newsgroup-name nil)
 
 (defvar gnus-original-article-buffer " *Original Article*")
 (defvar gnus-newsgroup-name nil)
 
+(defvar gnus-agent nil
+  "Whether we want to use the Gnus agent or not.")
+
+(defvar gnus-command-method nil
+  "Dynamically bound variable that says what the current backend is.")
+
 (defvar gnus-current-select-method nil
   "The current method for selecting a newsgroup.")
 
 (defvar gnus-current-select-method nil
   "The current method for selecting a newsgroup.")
 
@@ -1431,7 +1415,8 @@ want."
     (expirable . expire) (killed . killed)
     (bookmarks . bookmark) (dormant . dormant)
     (scored . score) (saved . save)
     (expirable . expire) (killed . killed)
     (bookmarks . bookmark) (dormant . dormant)
     (scored . score) (saved . save)
-    (cached . cache)))
+    (cached . cache) (downloadable . download)
+    (unsendable . unsend)))
 
 (defvar gnus-headers-retrieved-by nil)
 (defvar gnus-article-reply nil)
 
 (defvar gnus-headers-retrieved-by nil)
 (defvar gnus-article-reply nil)
@@ -1573,7 +1558,8 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-tree-open gnus-tree-close gnus-carpal-setup-buffer)
      ("gnus-nocem" gnus-nocem-scan-groups gnus-nocem-close
       gnus-nocem-unwanted-article-p)
       gnus-tree-open gnus-tree-close gnus-carpal-setup-buffer)
      ("gnus-nocem" gnus-nocem-scan-groups gnus-nocem-close
       gnus-nocem-unwanted-article-p)
-     ("gnus-srvr" gnus-enter-server-buffer gnus-server-set-info)
+     ("gnus-srvr" gnus-enter-server-buffer gnus-server-set-info
+      gnus-server-server-name)
      ("gnus-srvr" gnus-browse-foreign-server)
      ("gnus-cite" :interactive t
       gnus-article-highlight-citation gnus-article-hide-citation-maybe
      ("gnus-srvr" gnus-browse-foreign-server)
      ("gnus-cite" :interactive t
       gnus-article-highlight-citation gnus-article-hide-citation-maybe
@@ -1665,7 +1651,8 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-article-date-original gnus-article-date-lapsed
       gnus-article-show-all-headers
       gnus-article-edit-mode gnus-article-edit-article
       gnus-article-date-original gnus-article-date-lapsed
       gnus-article-show-all-headers
       gnus-article-edit-mode gnus-article-edit-article
-      gnus-article-edit-done gnus-decode-rfc1522 article-decode-rfc1522)
+      gnus-article-edit-done gnus-decode-rfc1522 article-decode-rfc1522
+      gnus-start-date-timer gnus-stop-date-timer)
      ("gnus-int" gnus-request-type)
      ("gnus-start" gnus-newsrc-parse-options gnus-1 gnus-no-server-1
       gnus-dribble-enter)
      ("gnus-int" gnus-request-type)
      ("gnus-start" gnus-newsrc-parse-options gnus-1 gnus-no-server-1
       gnus-dribble-enter)
@@ -1680,8 +1667,14 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
      ("gnus-async" gnus-async-request-fetched-article gnus-async-prefetch-next
       gnus-async-prefetch-article gnus-async-prefetch-remove-group
       gnus-async-halt-prefetch)
      ("gnus-async" gnus-async-request-fetched-article gnus-async-prefetch-next
       gnus-async-prefetch-article gnus-async-prefetch-remove-group
       gnus-async-halt-prefetch)
+     ("gnus-agent" gnus-open-agent gnus-agent-get-function
+      gnus-agent-save-groups gnus-agent-save-active gnus-agent-method-p
+      gnus-agent-get-undownloaded-list)
+     ("gnus-agent" :interactive t
+      gnus-unplugged gnus-agentize)
      ("gnus-vm" :interactive t gnus-summary-save-in-vm
      ("gnus-vm" :interactive t gnus-summary-save-in-vm
-      gnus-summary-save-article-vm))))
+      gnus-summary-save-article-vm)
+     ("gnus-draft" :interactive t gnus-draft-mode gnus-group-send-drafts))))
 
 ;;; gnus-sum.el thingies
 
 
 ;;; gnus-sum.el thingies
 
@@ -1722,6 +1715,7 @@ with some simple extensions.
 %l   GroupLens score (string).
 %V   Total thread score (number).
 %P   The line number (number).
 %l   GroupLens score (string).
 %V   Total thread score (number).
 %P   The line number (number).
+%O   Download mark (character).
 %u   User defined specifier.  The next character in the format string should
      be a letter.  Gnus will call the function gnus-user-format-function-X,
      where X is the letter following %u.  The function will be passed the
 %u   User defined specifier.  The next character in the format string should
      be a letter.  Gnus will call the function gnus-user-format-function-X,
      where X is the letter following %u.  The function will be passed the
@@ -1753,7 +1747,7 @@ This restriction may disappear in later versions of Gnus."
 
 (defun gnus-suppress-keymap (keymap)
   (suppress-keymap keymap)
 
 (defun gnus-suppress-keymap (keymap)
   (suppress-keymap keymap)
-  (let ((keys `([delete] "\177" "\M-u"))) ;gnus-mouse-2
+  (let ((keys `([backspace] [delete] "\177" "\M-u"))) ;gnus-mouse-2
     (while keys
       (define-key keymap (pop keys) 'undefined))))
 
     (while keys
       (define-key keymap (pop keys) 'undefined))))
 
@@ -1992,8 +1986,135 @@ If ARG, insert string at point."
     (setq gnus-info-buffer (current-buffer))
     (gnus-configure-windows 'info)))
 
     (setq gnus-info-buffer (current-buffer))
     (gnus-configure-windows 'info)))
 
+;;;
+;;; gnus-interactive
+;;;
+
+(defvar gnus-current-prefix-symbol nil
+  "Current prefix symbol.")
+
+(defvar gnus-current-prefix-symbols nil
+  "List of current prefix symbols.")
+
+(defun gnus-interactive (string &optional params)
+  "Return a list that can be fed to `interactive'.
+See `interactive' for full documentation.
+
+Adds the following specs:
+
+y -- The current symbolic prefix.
+Y -- A list of the current symbolic prefix(es).
+A -- Article number.
+H -- Article header.
+g -- Group name."
+  (let ((i 0)
+       out c prompt)
+    (while (< i (length string))
+      (string-match ".\\([^\n]*\\)\n?" string i)
+      (setq c (aref string i))
+      (when (match-end 1)
+       (setq prompt (match-string 1 string)))
+      (setq i (match-end 0))
+      ;; We basically emulate just about everything that
+      ;; `interactive' does, but adds the "g" and "G" specs.
+      (push
+       (cond
+       ((= c ?a)
+        (completing-read prompt obarray 'fboundp t))
+       ((= c ?b)
+        (read-buffer prompt (current-buffer) t))
+       ((= c ?B)
+        (read-buffer prompt (other-buffer (current-buffer))))
+       ((= c ?c)
+        (read-char))
+       ((= c ?C)
+        (completing-read prompt obarray 'commandp t))
+       ((= c ?d)
+        (point))
+       ((= c ?D)
+        (read-file-name prompt nil default-directory 'lambda))
+       ((= c ?f)
+        (read-file-name prompt nil nil 'lambda))
+       ((= c ?F)
+        (read-file-name prompt))
+       ((= c ?k)
+        (read-key-sequence prompt))
+       ((= c ?K)
+        (error "Not implemented spec"))
+       ((= c ?e)
+        (error "Not implemented spec"))
+       ((= c ?m)
+        (mark))
+       ((= c ?N)
+        (error "Not implemented spec"))
+       ((= c ?n)
+        (string-to-number (read-from-minibuffer prompt)))
+       ((= c ?p)
+        (prefix-numeric-value current-prefix-arg))
+       ((= c ?P)
+        current-prefix-arg)
+       ((= c ?r)
+        'gnus-prefix-nil)
+       ((= c ?s)
+        (read-string prompt))
+       ((= c ?S)
+        (intern (read-string prompt)))
+       ((= c ?v)
+        (read-variable prompt))
+       ((= c ?x)
+        (read-minibuffer prompt))
+       ((= c ?x)
+        (eval-minibuffer prompt))
+       ;; And here the new specs come.
+       ((= c ?y)
+        gnus-current-prefix-symbol)
+       ((= c ?Y)
+        gnus-current-prefix-symbols)
+       ((= c ?g)
+        (gnus-group-group-name))
+       ((= c ?A)
+        (gnus-summary-article-number))
+       ((= c ?H)
+        (gnus-summary-article-header))
+       (t
+        (error "Not implemented spec")))
+       out)
+      (cond
+       ((= c ?r)
+       (push (if (< (point) (mark) (point) (mark))) out)
+       (push (if (> (point) (mark) (point) (mark))) out))))
+    (setq out (delq 'gnus-prefix-nil out))
+    (nreverse out)))
+
+(defun gnus-symbolic-argument (&optional arg)
+  "Read a symbolic argument and a command, and then execute command."
+  (interactive "P")
+  (let* ((in-command (this-command-keys))
+        (command in-command)
+        gnus-current-prefix-symbols
+        gnus-current-prefix-symbol
+        syms)
+    (while (equal in-command command)
+      (message "%s-" (key-description (this-command-keys)))
+      (push (intern (char-to-string (read-char))) syms)
+      (setq command (read-key-sequence nil t)))
+    (setq gnus-current-prefix-symbols (nreverse syms)
+         gnus-current-prefix-symbol (car gnus-current-prefix-symbols))
+    (call-interactively (key-binding command t))))
+
 ;;; More various functions.
 
 ;;; More various functions.
 
+(defsubst gnus-check-backend-function (func group)
+  "Check whether GROUP supports function FUNC.
+GROUP can either be a string (a group name) or a select method."
+  (ignore-errors
+    (let ((method (if (stringp group)
+                     (car (gnus-find-method-for-group group))
+                   group)))
+      (unless (featurep method)
+       (require method))
+      (fboundp (intern (format "%s-%s" method func))))))
+
 (defun gnus-group-read-only-p (&optional group)
   "Check whether GROUP supports editing or not.
 If GROUP is nil, `gnus-newsgroup-name' will be checked instead.         Note
 (defun gnus-group-read-only-p (&optional group)
   "Check whether GROUP supports editing or not.
 If GROUP is nil, `gnus-newsgroup-name' will be checked instead.         Note
@@ -2014,7 +2135,7 @@ that that variable is buffer-local to the summary buffers."
       (string-match gnus-total-expirable-newsgroups group)))))
 
 (defun gnus-group-auto-expirable-p (group)
       (string-match gnus-total-expirable-newsgroups group)))))
 
 (defun gnus-group-auto-expirable-p (group)
-  "Check whether GROUP is total-expirable or not."
+  "Check whether GROUP is auto-expirable or not."
   (let ((params (gnus-group-find-parameter group))
        val)
     (cond
   (let ((params (gnus-group-find-parameter group))
        val)
     (cond
@@ -2077,7 +2198,7 @@ that that variable is buffer-local to the summary buffers."
 
 (defun gnus-simplify-mode-line ()
   "Make mode lines a bit simpler."
 
 (defun gnus-simplify-mode-line ()
   "Make mode lines a bit simpler."
-  (setq mode-line-modified "-- ")
+  (setq mode-line-modified (cdr gnus-mode-line-modified))
   (when (listp mode-line-format)
     (make-local-variable 'mode-line-format)
     (setq mode-line-format (copy-sequence mode-line-format))
   (when (listp mode-line-format)
     (make-local-variable 'mode-line-format)
     (setq mode-line-format (copy-sequence mode-line-format))
@@ -2179,7 +2300,8 @@ that that variable is buffer-local to the summary buffers."
 (defun gnus-group-prefixed-name (group method)
   "Return the whole name from GROUP and METHOD."
   (and (stringp method) (setq method (gnus-server-to-method method)))
 (defun gnus-group-prefixed-name (group method)
   "Return the whole name from GROUP and METHOD."
   (and (stringp method) (setq method (gnus-server-to-method method)))
-  (if (not method)
+  (if (or (not method)
+         (gnus-server-equal method "native"))
       group
     (concat (format "%s" (car method))
            (when (and
       group
     (concat (format "%s" (car method))
            (when (and
@@ -2232,6 +2354,15 @@ You should probably use `gnus-find-method-for-group' instead."
       (setq methods (cdr methods)))
     methods))
 
       (setq methods (cdr methods)))
     methods))
 
+(defun gnus-groups-from-server (server)
+  "Return a list of all groups that are fetched from SERVER."
+  (let ((alist (cdr gnus-newsrc-alist))
+       info groups)
+    (while (setq info (pop alist))
+      (when (gnus-server-equal (gnus-info-method info) server)
+       (push (gnus-info-group info) groups)))
+    (sort groups 'string<)))
+
 (defun gnus-group-foreign-p (group)
   "Say whether a group is foreign or not."
   (and (not (gnus-group-native-p group))
 (defun gnus-group-foreign-p (group)
   "Say whether a group is foreign or not."
   (and (not (gnus-group-native-p group))
@@ -2483,17 +2614,6 @@ If NEWSGROUP is nil, return the global kill file name instead."
                (t
                 (gnus-server-add-address method)))))))
 
                (t
                 (gnus-server-add-address method)))))))
 
-(defsubst gnus-check-backend-function (func group)
-  "Check whether GROUP supports function FUNC.
-GROUP can either be a string (a group name) or a select method."
-  (ignore-errors
-    (let ((method (if (stringp group)
-                     (car (gnus-find-method-for-group group))
-                   group)))
-      (unless (featurep method)
-       (require method))
-      (fboundp (intern (format "%s-%s" method func))))))
-
 (defun gnus-methods-using (feature)
   "Find all methods that have FEATURE."
   (let ((valids gnus-valid-select-methods)
 (defun gnus-methods-using (feature)
   "Find all methods that have FEATURE."
   (let ((valids gnus-valid-select-methods)