*** empty log message ***
authorLars Magne Ingebrigtsen <larsi@gnus.org>
Tue, 4 Mar 1997 23:56:43 +0000 (23:56 +0000)
committerLars Magne Ingebrigtsen <larsi@gnus.org>
Tue, 4 Mar 1997 23:56:43 +0000 (23:56 +0000)
42 files changed:
lisp/ChangeLog
lisp/article.el
lisp/custom-edit.el
lisp/custom.el
lisp/gnus-art.el
lisp/gnus-async.el
lisp/gnus-cache.el
lisp/gnus-demon.el
lisp/gnus-ems.el
lisp/gnus-group.el
lisp/gnus-kill.el
lisp/gnus-msg.el
lisp/gnus-nocem.el
lisp/gnus-score.el
lisp/gnus-setup.el
lisp/gnus-soup.el
lisp/gnus-sum.el
lisp/gnus-topic.el
lisp/gnus-undo.el
lisp/gnus-util.el
lisp/gnus-xmas.el
lisp/gnus.el
lisp/message.el
lisp/messcompat.el
lisp/nnbabyl.el
lisp/nnfolder.el
lisp/nnheader.el
lisp/nnmail.el
lisp/nnmbox.el
lisp/nnmh.el
lisp/nnml.el
lisp/nnoo.el
lisp/nnsoup.el
lisp/nntp.el
lisp/nnweb.el
lisp/widget-edit.el
lisp/widget.el
texi/ChangeLog
texi/custom.texi
texi/gnus.texi
texi/message.texi [new file with mode: 0644]
texi/widget.texi

index 3de5681..4cd5359 100644 (file)
@@ -1,3 +1,183 @@
+Tue Oct 29 20:42:07 1996  Lars Magne Ingebrigtsen  <larsi@ylfing.ifi.uio.no>
+
+       * gnus-topic.el (gnus-topic-remove-topic): Fold properly.
+
+Tue Oct 29 19:45:25 1996  Lars Magne Ingebrigtsen  <larsi@ifi.uio.no>
+
+       * message.el (message-generate-new-buffer-clone-locals): Bugged
+       out under XEmacs.
+
+Tue Oct 29 19:21:47 1996  David Moore  <dmoore@ucsd.edu>
+
+       * gnus.el: Fixed autoloads.
+
+Tue Oct 29 17:21:42 1996  Lars Magne Ingebrigtsen  <larsi@ylfing.ifi.uio.no>
+
+       * gnus-art.el (gnus-url-mailto): `message-goto-subject' takes no
+       args. 
+
+Mon Oct 28 15:42:21 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.el: Autoload gnus-score-followup-thread.
+       (gnus-inhibit-startup-message): Doc fix.
+
+Sat Oct 26 15:48:28 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus-xmas.el (gnus-xmas-topic-menu-add): Add menu.
+
+       * gnus-topic.el (gnus-topic-kill-group): Enter into dribble.
+
+       * gnus-sum.el (gnus-summary-universal-argument): Bind
+       `gnus-newsgroup-process-marked' to nil before calling functions. 
+
+Sat Oct 26 15:31:18 1996  David Moore  <dmoore@ucsd.edu>
+
+       * nnmail.el (nnmail-activate): Faster version.
+
+Fri Oct 25 09:02:08 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * nnsoup.el (nnsoup-pack-replies): Error empty dirs.
+
+       * gnus-msg.el (gnus-summary-mail-forward): Allow prefix to forward
+       full headers. 
+
+Thu Oct 24 07:20:30 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus-nocem.el (gnus-nocem-enter-article): Would enter unbound
+       symbols into hashtb.
+
+Thu Oct 24 07:12:23 1996  Michael R. Cook  <mcook@cognex.com>
+
+       * nnmh.el (nnmh-active-number): Misplaced paren.
+
+Thu Oct 24 07:02:54 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus-group.el (gnus-group-list-groups): Clear inboxes.
+
+       * gnus-async.el (gnus-make-async-article-function): Use the
+       success param.
+
+       * nntp.el (nntp-after-change-function-callback): Pass along the
+       right success param.
+
+Wed Oct 23 18:33:15 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus-score.el (gnus-summary-increase-score): Spud.
+
+Wed Oct 23 07:55:42 1996  William Perry  <wmperry@aventail.com>
+
+       * gnus-art.el (gnus-url-mailto): New function.
+
+Wed Oct 23 06:57:10 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * nnbabyl.el (nnbabyl-create-mbox): New function.
+       (nnbabyl-open-server): Create mbox.
+
+       * nnmbox.el (nnmbox-create-mbox): New function.
+
+Tue Oct 22 07:30:12 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * nnml.el (nnml-request-list): Always return t.
+
+Tue Oct 22 03:16:27 1996  Felix Lee  <flee@teleport.com>
+
+       * gnus-score.el (gnus-score-adaptive): Use the right syntax
+       table. 
+
+Tue Oct 22 03:08:30 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * message.el (message-generate-headers): Rename Original-Sender as
+       well.
+       (message-send-news): Typo.
+       (message-send-news): Don't message.
+
+Tue Oct 22 03:06:49 1996  Felix Lee  <flee@teleport.com>
+
+       * gnus-score.el (gnus-score-adaptive): gnus-score-adaptive will do
+       line scoring or word scoring, but not both.
+
+Tue Oct 22 02:48:08 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * message.el (message-send-news): Use it.
+       (message-send-mail): Ditto.
+
+Tue Oct 22 02:40:14 1996  Joev Dubach  <dubach1@husc.harvard.edu>
+
+       * message.el (message-generate-new-buffer-clone-locals): New
+       function. 
+
+Tue Oct 22 01:19:47 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * message.el: Removed `lisp-indent-hook' throughout all files. 
+
+       * gnus.el (gnus-sethash): Fix edebug form spec.
+
+       * gnus-cache.el (gnus-cache-file-name): Translate file chars.
+
+Sun Oct 20 03:41:47 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * nntp.el (nntp-read-server-type): Fold case.
+
+Sat Oct 19 08:03:17 1996  Michael Ernst  <mernst@cs.washington.edu>
+
+       * article.el (article-hide-headers): Do the right thing on
+       articles with no bodies.
+       (article-narrow-to-signature): Doc fix.
+
+Sat Oct 19 07:53:49 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * nnsoup.el (nnsoup-pack-replies): Refuse to pack when there is
+       nothing to pack.
+       (nnsoup-read-areas): Don't bug out on empty packets.
+
+       * gnus-soup.el (gnus-soup-pack-packet): Refuse to pack empty
+       packets. 
+
+Sat Oct 19 07:43:33 1996  Kees de Bruin  <kees_de_bruin@tasking.nl>
+
+       * gnus-sum.el (gnus-auto-center-summary): Fix.
+
+Sat Oct 19 07:32:27 1996  Marc Horowitz  <marc@cygnus.com>
+
+       * gnus-topic.el (gnus-topic-remove-topic): Would clobber
+       duplicates. 
+
+Sat Oct 19 07:01:14 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * message.el (message-send-mail-hook): New hook.
+       (message-send-news-hook): Ditto.
+
+       * gnus-art.el (gnus-summary-write-to-file): New function.
+
+Sat Oct 19 06:56:34 1996  Kees de Bruin  <kees_de_bruin@tasking.nl>
+
+       * gnus-sum.el (gnus-summary-save-article-mail-overwrite): New
+       command and keystroke.
+
+Thu Oct 17 06:25:55 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus-sum.el (gnus-article-sort-by-date): Use faster
+       implementation. 
+
+       * gnus-util.el (gnus-string-get-time): New macro.
+
+       * message.el (message-check-news-syntax): Check more thorougly the
+       From header.
+       (message-check): New macro.
+
+Thu Oct 17 06:03:56 1996  Carsten Leonhardt  <leo@arioch.tng.oche.de>
+
+       * gnus-ems.el (gnus-xemacs): Avoid clobbering functions.
+
+Thu Oct 17 05:34:15 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * message.el (message-cite-function): Initialize from
+       mail-citation-hook. 
+
+Thu Oct 17 02:45:47 1996  Lars Magne Ingebrigtsen  <larsi@hrym.ifi.uio.no>
+
+       * gnus.el: Red Gnus v0.52 is released.
+
 Wed Oct 16 21:01:41 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
 
        * gnus-sum.el (gnus-summary-catchup): Return t.
index 88cd843..0f9079d 100644 (file)
@@ -252,7 +252,9 @@ always hide."
            ;; Then treat the rest of the header lines.
            (narrow-to-region
             (point)
-            (progn (search-forward "\n\n" nil t) (forward-line -1) (point)))
+            (if (search-forward "\n\n" nil t) ; if there's a body
+                (progn (forward-line -1) (point))
+              (point-max)))
            ;; Then we use the two regular expressions
            ;; `gnus-ignored-headers' and `gnus-visible-headers' to
            ;; select which header lines is to remain visible in the
@@ -632,7 +634,7 @@ always hide."
 (defvar mime::preview/content-list)
 (defvar mime::preview-content-info/point-min)
 (defun article-narrow-to-signature ()
-  "Narrow to the signature."
+  "Narrow to the signature; return t if a signature is found, else nil."
   (widen)
   (when (and (boundp 'mime::preview/content-list)
             mime::preview/content-list)
index a357129..047f8e7 100644 (file)
@@ -4,7 +4,7 @@
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: help, faces
-;; Version: 0.993
+;; Version: 0.995
 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
 
 ;;; Commentary:
@@ -15,6 +15,7 @@
 
 (require 'custom)
 (require 'widget-edit)
+(require 'easymenu)
 
 (define-widget-keywords :custom-show :custom-magic
   :custom-state :custom-level :custom-form
@@ -285,10 +286,14 @@ The list should be sorted most significant first."
         (form (widget-get widget :custom-form))
         (state (widget-get widget :custom-state))
         (symbol (widget-get widget :value))
+        (options (get symbol 'custom-options))
         (child-type (or (get symbol 'custom-type) 'sexp))
-        (type (if (listp child-type)
-                  child-type
-                (list child-type)))
+        (type (let ((tmp (if (listp child-type)
+                             child-type
+                           (list child-type))))
+                (when options
+                  (widget-put tmp :options options))
+                tmp))
         (conv (widget-convert type))
         (value (if (boundp symbol)
                    (symbol-value symbol)
@@ -669,6 +674,27 @@ Optional EVENT is the location for the menu."
       (widget-apply widget :notify widget event)
       (widget-setup))))
 
+;;; The `hook' Widget.
+
+(define-widget 'hook 'list
+  "A emacs lisp hook"
+  :convert-widget 'custom-hook-convert-widget
+  :tag "Hook")
+
+(defun custom-hook-convert-widget (widget)
+  ;; Handle `:custom-options'.
+  (let* ((options (widget-get widget :options))
+        (other `(editable-list :inline t (function :format "%v")))
+        (args (if options
+                  (list `(checklist :inline t
+                                    ,@(mapcar (lambda (entry)
+                                                `(function-item ,entry))
+                                              options))
+                        other)
+                (list other))))
+    (widget-put widget :args args)
+    widget))
+
 ;;; The `custom-group' Widget.
 
 (define-widget 'custom-group 'custom
index 4f264c0..415a22f 100644 (file)
@@ -4,7 +4,7 @@
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: help, faces
-;; Version: 0.993
+;; Version: 0.995
 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
 
 ;;; Commentary:
@@ -19,7 +19,7 @@
 
 (require 'widget)
 
-(define-widget-keywords :type :group)
+(define-widget-keywords :options :type :group)
 
 ;; These autoloads should be deleted when the file is added to Emacs
 (autoload 'customize "custom-edit" nil t)
                        (color-instance-name
                         (specifier-instance
                          (face-background 'default))))
-                 (error nil))))
-    (cond (bg-resource (intern (downcase bg-resource)))
-         ((and color
-               (< (apply '+ (custom-x-color-values color))
-                  (/ (apply '+ (custom-x-color-values "white")) 3)))
-          'dark)
-         (t 'light))))
+                 (error nil)))
+        (mode (cond (bg-resource (intern (downcase bg-resource)))
+                    ((and color
+                          (< (apply '+ (custom-x-color-values color))
+                             (/ (apply '+ (custom-x-color-values "white"))
+                                3)))
+                     'dark)
+                    (t 'light))))
+    (if (fboundp 'set-frame-property)
+       ;; `modify-frame-properties' is borken on XEmacs 19.14.
+       (set-frame-property (selected-frame) 'background-mode mode)
+      ;; `set-frame-property' is unimplemented in Emacs 19.34.
+      (modify-frame-parameters (selected-frame)
+                              (cons (cons 'background-mode mode) params)))
+    mode))
 
 ;;; The `defcustom' Macro.
 
@@ -80,6 +88,9 @@
        (setq args (cdr args))
        (cond ((eq keyword :type)
               (put symbol 'custom-type value))
+             ((eq keyword :options)
+              (put symbol 'custom-options 
+                   (append value (get symbol 'custom-options))))
              ((eq keyword :group)
               (custom-add-to-group value symbol 'custom-variable))
              (t
@@ -98,7 +109,8 @@ The remaining arguments should have the form
 
 The following KEYWORD's are defined:
 
-:type  VALUE should be a sexp widget.
+:type  VALUE should be a widget type.
+:options VALUE should be a list of valid members of the widget type.
 :group  VALUE should be a customization group.  
         Add SYMBOL to that group.
 
@@ -113,10 +125,11 @@ information."
 (defun custom-declare-face (face spec doc &rest args)
   "Like `defface', but FACE is evaluated as a normal argument."
   (put face 'factory-face spec)
-  (unless (facep face)
-    ;; If the user has already created the face, respect that.
-    (let ((value (or (get face 'saved-face) spec)))
-      (custom-face-display-set face value)))
+  (when (fboundp 'facep)
+    (unless (facep face)
+      ;; If the user has already created the face, respect that.
+      (let ((value (or (get face 'saved-face) spec)))
+       (custom-face-display-set face value))))
   (when doc
     (put face 'face-documentation doc))
   (while args 
@@ -274,7 +287,7 @@ examine the brightness for you."
 (defun custom-display-match-frame (display frame)
   "Non-nil iff DISPLAY matches FRAME.
 If FRAME is nil, the current FRAME is used."
-  ;; This is a kludge to get started, we realle should use specifiers!
+  ;; This is a kludge to get started, we really should use specifiers!
   (unless frame 
     (setq frame (selected-frame)))
   (if (eq display t)
@@ -287,9 +300,10 @@ If FRAME is nil, the current FRAME is used."
               (options (cdr entry)))
          (setq display (cdr display))
          (cond ((eq req 'type)
-                (setq match (if (fboundp 'device-type)
+                (let ((type (if (fboundp 'device-type)
                                 (device-type frame)
-                              (memq window-system options))))
+                              window-system)))
+                  (setq match (memq type options))))
                ((eq req 'class)
                 (let ((class (if (fboundp 'device-class)
                                  (device-class frame)
index 227bfc1..a6ec484 100644 (file)
@@ -73,14 +73,16 @@ Gnus provides the following functions:
 * gnus-summary-save-in-rmail (Rmail format)
 * gnus-summary-save-in-mail (Unix mail format)
 * gnus-summary-save-in-folder (MH folder)
-* gnus-summary-save-in-file (article format).
-* gnus-summary-save-in-vm (use VM's folder format)."
+* gnus-summary-save-in-file (article format)
+* gnus-summary-save-in-vm (use VM's folder format)
+* gnus-summary-write-to-file (article format -- overwrite)."
   :group 'article
   :type '(radio (function-item gnus-summary-save-in-rmail)
                (function-item gnus-summary-save-in-mail)
                (function-item gnus-summary-save-in-folder)
                (function-item gnus-summary-save-in-file)
-               (function-item gnus-summary-save-in-vm)))
+               (function-item gnus-summary-save-in-vm)
+               (function-item gnus-summary-write-to-file)))
 
 (defcustom gnus-rmail-save-name 'gnus-plain-save-name
   "A function generating a file name to save articles in Rmail format.
@@ -473,7 +475,7 @@ Directory to save to is default to `gnus-article-save-directory'."
     ;; Remember the directory name to save articles.
     (setq gnus-newsgroup-last-mail filename)))
 
-(defun gnus-summary-save-in-file (&optional filename)
+(defun gnus-summary-save-in-file (&optional filename overwrite)
   "Append this article to file.
 Optional argument FILENAME specifies file name.
 Directory to save to is default to `gnus-article-save-directory'."
@@ -489,32 +491,19 @@ Directory to save to is default to `gnus-article-save-directory'."
       (save-excursion
        (save-restriction
          (widen)
+         (when (and overwrite
+                    (file-exists-p filename))
+           (delete-file filename))
          (gnus-output-to-file filename))))
     ;; Remember the directory name to save articles.
     (setq gnus-newsgroup-last-file filename)))
 
-(defun gnus-summary-save-body-in-file (&optional filename)
+(defun gnus-summary-write-to-file (&optional filename)
   "Append this article body to a file.
 Optional argument FILENAME specifies file name.
 The directory to save in defaults to `gnus-article-save-directory'."
   (interactive)
-  (gnus-set-global-variables)
-  (let ((default-name
-         (funcall gnus-file-save-name gnus-newsgroup-name
-                  gnus-current-headers gnus-newsgroup-last-file)))
-    (setq filename (gnus-read-save-file-name
-                   "Save %s body in file:" default-name filename))
-    (gnus-make-directory (file-name-directory filename))
-    (gnus-eval-in-buffer-window gnus-original-article-buffer
-      (save-excursion
-       (save-restriction
-         (widen)
-         (goto-char (point-min))
-         (when (search-forward "\n\n" nil t)
-           (narrow-to-region (point) (point-max)))
-         (gnus-output-to-file filename))))
-    ;; Remember the directory name to save articles.
-    (setq gnus-newsgroup-last-file filename)))
+  (gnus-summary-save-in-file nil t))
 
 (defun gnus-summary-save-in-pipe (&optional command)
   "Pipe this article to subprocess."
@@ -1472,7 +1461,7 @@ groups."
      gnus-button-fetch-group 3)
     ("\\(<?\\(url: ?\\)?news:\\([^>\n\t ]*\\)>?\\)" 1 t
      gnus-button-message-id 3)
-    ("\\(<URL: *\\)?mailto: *\\([^> \n\t]+\\)>?" 0 t gnus-button-reply 2)
+    ("\\(<URL: *\\)?mailto: *\\([^> \n\t]+\\)>?" 0 t gnus-url-mailto 2)
     ;; This is how URLs _should_ be embedded in text...
     ("<URL: *\\([^\n\r>]*\\)>" 0 t gnus-button-url 1)
     ;; Next regexp stolen from highlight-headers.el.
@@ -1832,6 +1821,89 @@ specified by `gnus-button-alist'."
                                   (match-string 3 address)
                                 "nntp"))))))
 
+(defun gnus-split-string (string pattern)
+  "Return a list of substrings of STRING which are separated by PATTERN."
+  (let (parts (start 0))
+    (while (string-match pattern string start)
+      (setq parts (cons (substring string start (match-beginning 0)) parts)
+           start (match-end 0)))
+    (nreverse (cons (substring string start) parts))))
+(defun gnus-url-parse-query-string (query &optional downcase)
+  (let (retval pairs cur key val)
+    (setq pairs (gnus-split-string query "&"))
+    (while pairs
+      (setq cur (car pairs)
+            pairs (cdr pairs))
+      (if (not (string-match "=" cur))
+          nil                           ; Grace
+        (setq key (gnus-url-unhex-string (substring cur 0 (match-beginning 0)))
+              val (gnus-url-unhex-string (substring cur (match-end 0) nil)))
+        (if downcase
+            (setq key (downcase key)))
+        (setq cur (assoc key retval))
+        (if cur
+            (setcdr cur (cons val (cdr cur)))
+          (setq retval (cons (list key val) retval)))))
+    retval))
+(defun gnus-url-unhex (x)
+  (if (> x ?9)
+      (if (>= x ?a)
+          (+ 10 (- x ?a))
+        (+ 10 (- x ?A)))
+    (- x ?0)))
+(defun gnus-url-unhex-string (str &optional allow-newlines)
+  "Remove %XXX embedded spaces, etc in a url.
+If optional second argument ALLOW-NEWLINES is non-nil, then allow the
+decoding of carriage returns and line feeds in the string, which is normally
+forbidden in URL encoding."
+  (setq str (or str ""))
+  (let ((tmp "")
+        (case-fold-search t))
+    (while (string-match "%[0-9a-f][0-9a-f]" str)
+      (let* ((start (match-beginning 0))
+             (ch1 (gnus-url-unhex (elt str (+ start 1))))
+             (code (+ (* 16 ch1)
+                      (gnus-url-unhex (elt str (+ start 2))))))
+        (setq tmp (concat 
+                   tmp (substring str 0 start)
+                   (cond
+                    (allow-newlines
+                     (char-to-string code))
+                    ((or (= code ?\n) (= code ?\r))
+                     " ")
+                    (t (char-to-string code))))
+              str (substring str (match-end 0)))))
+    (setq tmp (concat tmp str))
+    tmp))
+(defun gnus-url-mailto (url)
+  ;; Send mail to someone
+  (if (not (string-match "mailto:/*\\(.*\\)" url))
+      (error "Malformed mailto link: %s" url))
+  (setq url (substring url (match-beginning 1) nil))
+  (let (to args source-url subject func)
+    (if (string-match (regexp-quote "?") url)
+        (setq to (gnus-url-unhex-string (substring url 0 (match-beginning 0)))
+              args (gnus-url-parse-query-string
+                    (substring url (match-end 0) nil) t))
+      (setq to (gnus-url-unhex-string url)))
+    (setq args (cons (list "to" to) args)
+          subject (cdr-safe (assoc "subject" args)))
+    (message-mail)
+    (while args
+      (setq func (intern-soft (concat "message-goto-" (downcase (caar args)))))
+      (if (fboundp func)
+          (funcall func)
+        (message-position-on-field (caar args)))
+      (insert (mapconcat 'identity (cdar args) ", "))
+      (setq args (cdr args)))
+    (if subject
+        (message-goto-body)
+      (message-goto-subject))))
+
 (defun gnus-button-mailto (address)
   ;; Mail to ADDRESS.
   (set-buffer (gnus-copy-article-buffer))
index ee3fb8d..1389ce7 100644 (file)
@@ -104,7 +104,6 @@ It should return non-nil if the article is to be prefetched."
      (gnus-async-release-semaphore 'gnus-async-article-semaphore)))
 
 (put 'gnus-asynch-with-semaphore 'lisp-indent-function 0)
-(put 'gnus-asynch-with-semaphore 'lisp-indent-hook 0)
 (put 'gnus-asynch-with-semaphore 'edebug-form-spec '(body))
        
 ;;;
@@ -199,13 +198,13 @@ It should return non-nil if the article is to be prefetched."
   "Return a callback function."
   `(lambda (arg)
      (save-excursion
-       (gnus-async-set-buffer)
-       (gnus-async-with-semaphore
-       (push (list ',(intern (format "%s-%d" group article))
-                   ,mark (set-marker (make-marker)
-                                     (point-max))
-                   ,group ,article)
-             gnus-async-article-alist))
+       (when arg
+        (gnus-async-set-buffer)
+        (gnus-async-with-semaphore
+         (push (list ',(intern (format "%s-%d" group article))
+                     ,mark (set-marker (make-marker) (point-max))
+                     ,group ,article)
+               gnus-async-article-alist)))
        (if (not (gnus-buffer-live-p ,summary))
           (gnus-async-with-semaphore
            (setq gnus-async-fetch-list nil))
index c9d3a6d..37349a9 100644 (file)
@@ -397,13 +397,14 @@ Returns the list of articles removed."
 (defun gnus-cache-file-name (group article)
   (concat (file-name-as-directory gnus-cache-directory)
          (file-name-as-directory
-          (if (gnus-use-long-file-name 'not-cache)
-              group 
-            (let ((group (nnheader-replace-chars-in-string group ?/ ?_)))
-              ;; Translate the first colon into a slash.
-              (when (string-match ":" group)
-                (aset group (match-beginning 0) ?/))
-              (nnheader-replace-chars-in-string group ?. ?/))))
+          (nnheader-translate-file-chars
+           (if (gnus-use-long-file-name 'not-cache)
+               group
+             (let ((group (nnheader-replace-chars-in-string group ?/ ?_)))
+               ;; Translate the first colon into a slash.
+               (when (string-match ":" group)
+                 (aset group (match-beginning 0) ?/))
+               (nnheader-replace-chars-in-string group ?. ?/)))))
          (if (stringp article) article (int-to-string article))))
 
 (defun gnus-cache-update-article (group article)
index 4255f40..6cb07b6 100644 (file)
@@ -220,37 +220,41 @@ time Emacs has been idle for IDLE `gnus-demon-timestep's."
 
 (defun gnus-demon-scan-nocem ()
   "Scan NoCeM groups for NoCeM messages."
-  (gnus-nocem-scan-groups))
+  (save-window-excursion
+    (gnus-nocem-scan-groups)))
 
 (defun gnus-demon-add-disconnection ()
   "Add daemonic server disconnection to Gnus."
   (gnus-demon-add-handler 'gnus-demon-close-connections nil 30))
 
 (defun gnus-demon-close-connections ()
-  (gnus-close-backends))
+  (save-window-excursion
+    (gnus-close-backends)))
 
 (defun gnus-demon-add-scanmail ()
   "Add daemonic scanning of mail from the mail backends."
   (gnus-demon-add-handler 'gnus-demon-scan-mail 120 60))
 
 (defun gnus-demon-scan-mail ()
-  (let ((servers gnus-opened-servers)
-       server)
-    (while (setq server (car (pop servers)))
-      (and (gnus-check-backend-function 'request-scan (car server))
-          (or (gnus-server-opened server)
-              (gnus-open-server server))
-          (gnus-request-scan nil server)))))
+  (save-window-excursion
+    (let ((servers gnus-opened-servers)
+         server)
+      (while (setq server (car (pop servers)))
+       (and (gnus-check-backend-function 'request-scan (car server))
+            (or (gnus-server-opened server)
+                (gnus-open-server server))
+            (gnus-request-scan nil server))))))
 
 (defun gnus-demon-add-rescan ()
   "Add daemonic scanning of new articles from all backends."
   (gnus-demon-add-handler 'gnus-demon-scan-news 120 60))
 
 (defun gnus-demon-scan-news ()
-  (when (gnus-alive-p)
-    (save-excursion
-      (set-buffer gnus-group-buffer)
-      (gnus-group-get-new-news))))
+  (save-window-excursion
+    (when (gnus-alive-p)
+      (save-excursion
+       (set-buffer gnus-group-buffer)
+       (gnus-group-get-new-news)))))
 
 (provide 'gnus-demon)
 
index dbb4001..87adf4f 100644 (file)
@@ -27,6 +27,8 @@
 
 (eval-when-compile (require 'cl))
 
+;;; Function aliases later to be redefined for XEmacs usage.
+
 (defvar gnus-xemacs (string-match "XEmacs\\|Lucid" emacs-version)
   "Non-nil if running under XEmacs.")
 
@@ -79,8 +81,7 @@
       "{ echo '/* Width=48, Height=48 */'; uncompface; } | icontopbm | xv -quit -"
       "String or function to be executed to display an X-Face header.
 If it is a string, the command will be executed in a sub-shell
-asynchronously.         The compressed face will be piped to this command.")
-)
+asynchronously.         The compressed face will be piped to this command."))
 
   (cond 
    ((string-match "XEmacs\\|Lucid" emacs-version)
index 10fc04f..9867de0 100644 (file)
@@ -872,6 +872,7 @@ ticked: The number of ticked articles."
      gnus-group-misc-menu gnus-group-mode-map ""
      '("Misc"
        ["Send a bug report" gnus-bug t]
+       ["Customize" gnus-group-customize t]
        ["Send a mail" gnus-group-mail t]
        ["Post an article..." gnus-group-post-news t]
        ["Check for new news" gnus-group-get-new-news t]     
@@ -1004,6 +1005,8 @@ listed."
            (gnus-group-default-level nil t)
            gnus-group-default-list-level
            gnus-level-subscribed))))
+  ;; Just do this here, for no particular good reason.
+  (gnus-clear-inboxes-moved)
   (unless level
     (setq level (car gnus-group-list-mode)
          unread (cdr gnus-group-list-mode)))
index f168c68..634e1c1 100644 (file)
@@ -628,11 +628,11 @@ COMMAND must be a lisp expression or a string representing a key sequence."
                (eval form))))))
       did-kill)))
 
-(defun gnus-execute (field regexp form &optional backward ignore-marked)
+(defun gnus-execute (field regexp form &optional backward unread)
   "If FIELD of article header matches REGEXP, execute lisp FORM (or a string).
 If FIELD is an empty string (or nil), entire article body is searched for.
 If optional 1st argument BACKWARD is non-nil, do backward instead.
-If optional 2nd argument IGNORE-MARKED is non-nil, articles which are
+If optional 2nd argument UNREAD is non-nil, articles which are
 marked as read or ticked are ignored."
   (save-excursion
     (let ((killed-no 0)
@@ -658,8 +658,7 @@ marked as read or ticked are ignored."
                   (setq article (gnus-summary-article-number)))
              ;; Find later articles.
              (setq article 
-                   (gnus-summary-search-forward 
-                    ignore-marked nil backward)))
+                   (gnus-summary-search-forward unread nil backward)))
        (and (or (null gnus-newsgroup-kill-headers)
                 (memq article gnus-newsgroup-kill-headers))
             (vectorp (setq header (gnus-summary-article-header article)))
index f7bfc06..d8458e5 100644 (file)
@@ -183,7 +183,6 @@ Thank you for your help in stamping out bugs.
    'send))
 
 (put 'gnus-setup-message 'lisp-indent-function 1)
-(put 'gnus-setup-message 'lisp-indent-hook 1)
 (put 'gnus-setup-message 'edebug-form-spec '(form body))
 
 ;;; Post news commands of Gnus group mode and summary mode
@@ -563,14 +562,17 @@ If prefix argument YANK is non-nil, original article is yanked automatically."
   (interactive "P")
   (gnus-summary-reply (gnus-summary-work-articles n)))
 
-(defun gnus-summary-mail-forward (&optional post)
-  "Forward the current message to another user."
+(defun gnus-summary-mail-forward (&optional full-headers post)
+  "Forward the current message to another user.
+If FULL-HEADERS (the prefix), include full headers when forwarding."
   (interactive "P")
   (gnus-set-global-variables)
   (gnus-setup-message 'forward
     (gnus-summary-select-article)
     (set-buffer gnus-original-article-buffer)
-    (message-forward post)))
+    (let ((message-included-forward-headers
+          (if full-headers "" message-included-forward-headers)))
+      (message-forward post))))
 
 (defun gnus-summary-resend-message (address)
   "Resend the current article to ADDRESS."
@@ -580,10 +582,11 @@ If prefix argument YANK is non-nil, original article is yanked automatically."
     (set-buffer gnus-original-article-buffer)
     (message-resend address)))
 
-(defun gnus-summary-post-forward ()
-  "Forward the current article to a newsgroup."
-  (interactive)
-  (gnus-summary-mail-forward t))
+(defun gnus-summary-post-forward (&optional full-headers)
+  "Forward the current article to a newsgroup.
+If FULL-HEADERS (the prefix), include full headers when forwarding."
+  (interactive "P")
+  (gnus-summary-mail-forward full-headers t))
 
 (defvar gnus-nastygram-message 
   "The following article was inappropriately posted to %s.\n\n"
index e137edd..6510a83 100644 (file)
@@ -185,23 +185,28 @@ isn't bound, the message will be used unconditionally."
   (let ((b (search-forward "\n@@BEGIN NCM BODY\n" nil t))
        (e (search-forward "\n@@END NCM BODY\n" nil t))
        (buf (current-buffer))
-       ncm id)
+       ncm id group)
     (when (and b e)
       (narrow-to-region b (1+ (match-beginning 0)))
       (goto-char (point-min))
       (while (search-forward "\t" nil t)
-       (when (condition-case nil
-                 (boundp (let ((obarray gnus-active-hashtb)) (read buf)))
-               (error nil))
-         (beginning-of-line)
-         (while (= (following-char) ?\t)
-           (forward-line -1))
-         (setq id (buffer-substring (point) (1- (search-forward "\t"))))
-         (push id ncm)
-         (gnus-sethash id t gnus-nocem-hashtb)
-         (forward-line 1)
-         (while (= (following-char) ?\t)
-           (forward-line 1))))
+       (condition-case nil
+           (setq group (let ((obarray gnus-active-hashtb)) (read buf)))
+         (error nil))
+       (if (not (boundp group))
+           ;; Make sure all entries in the hashtb are bound.
+           (set group nil)
+         (when (gnus-gethash (symbol-name group) gnus-newsrc-hashtb)
+           ;; Valid group.
+           (beginning-of-line)
+           (while (= (following-char) ?\t)
+             (forward-line -1))
+           (setq id (buffer-substring (point) (1- (search-forward "\t"))))
+           (push id ncm)
+           (gnus-sethash id t gnus-nocem-hashtb)
+           (forward-line 1)
+           (while (= (following-char) ?\t)
+             (forward-line 1)))))
       (when ncm
        (setq gnus-nocem-touched-alist t)
        (push (cons (let ((time (current-time))) (setcdr (cdr time) nil) time)
index a26fc51..2ceede9 100644 (file)
@@ -323,9 +323,6 @@ of the last successful match.")
     ("followup" 2 gnus-score-followup)
     ("thread" 5 gnus-score-thread)))
 
-(eval-and-compile
-  (autoload 'gnus-uu-ctl-map "gnus-uu" nil nil 'keymap))
-
 ;;; Summary mode score maps.
 
 (gnus-define-keys (gnus-summary-score-map "V" gnus-summary-mode-map)
@@ -469,7 +466,7 @@ used as score."
                               (if (eq (nth 4 entry)
                                       (nth 3 s))
                                   s nil))
-                            char-to-type ))
+                            char-to-type))
               2)))
 
          (gnus-score-kill-help-buffer)
@@ -499,6 +496,12 @@ used as score."
          (if mimic (message "%c %c %c" prefix hchar tchar pchar)
            (message ""))
          (unless (setq temporary (cadr (assq pchar char-to-perm)))
+           ;; Deal with der(r)ided superannuated paradigms.
+           (when (and (eq (1+ prefix) 77)
+                      (eq (+ hchar 12) 109)
+                      (eq tchar 114)
+                      (eq (- pchar 4) 111))
+             (error "You rang?"))
            (if mimic 
                (error "%c %c %c %c" prefix hchar tchar pchar)
              (error ""))))
@@ -524,8 +527,8 @@ used as score."
      (nth 1 entry)                     ; Header
      match                             ; Match
      type                              ; Type
-     (if (eq 's score) nil score)      ; Score
-     (if (eq 'perm temporary)          ; Temp
+     (if (eq score 's) nil score)      ; Score
+     (if (eq temporary 'perm)          ; Temp
         nil
        temporary)
      (not (nth 3 entry)))              ; Prompt
@@ -1962,10 +1965,9 @@ SCORE is the score to add."
        (or gnus-newsgroup-adaptive-score-file
           (gnus-score-file-name 
            gnus-newsgroup-name gnus-adaptive-file-suffix))))
-    (cond
-     ;; Perform ordinary line scoring.
-     ((or (not (listp gnus-use-adaptive-scoring))
-         (memq 'line gnus-use-adaptive-scoring))
+    ;; Perform ordinary line scoring.
+    (when (or (not (listp gnus-use-adaptive-scoring))
+             (memq 'line gnus-use-adaptive-scoring))
       (save-excursion
        (let* ((malist (gnus-copy-sequence gnus-adaptive-score-alist))
               (alist malist)
@@ -2023,8 +2025,9 @@ SCORE is the score to add."
                  (setq elem (cdr elem)))))
            (setq data (cdr data))))))
 
-     ;; Perform adaptive word scoring.
-     ((memq 'word gnus-use-adaptive-scoring)
+    ;; Perform adaptive word scoring.
+    (when (and (listp gnus-use-adaptive-scoring)
+              (memq 'word gnus-use-adaptive-scoring))
       (nnheader-temp-write nil
        (let* ((hashtb (gnus-make-hashtable 1000))
               (date (gnus-day-number (current-time-string)))
@@ -2033,7 +2036,7 @@ SCORE is the score to add."
               word d score val)
          (unwind-protect
              (progn
-               (set-syntax-table syntab)
+               (set-syntax-table gnus-adaptive-word-syntax-table)
                ;; Go through all articles.
                (while (setq d (pop data))
                  (when (and
@@ -2069,7 +2072,7 @@ SCORE is the score to add."
               (gnus-summary-score-entry
                "subject" (symbol-name word) 'w (symbol-value word)
                date nil t)))
-          hashtb)))))))
+          hashtb))))))
 
 (defun gnus-score-edit-done ()
   (let ((bufnam (buffer-file-name (current-buffer)))
index bb240d9..d3ddccf 100644 (file)
   (setq message-cite-function 'sc-cite-original)
   (autoload 'sc-cite-original "supercite"))
 \f
-;;;### (autoloads (gnus-batch-score gnus-fetch-group gnus gnus-slave gnus-no-server gnus-update-format) "gnus" "lisp/gnus.el" (12473 2137))
+;;;### (autoloads (gnus gnus-slave gnus-no-server) "gnus" "lisp/gnus.el" (12473 2137))
 ;;; Generated autoloads from lisp/gnus.el
 
-(autoload 'gnus-update-format "gnus" "\
-Update the format specification near point." t nil)
-
 (autoload 'gnus-slave-no-server "gnus" "\
 Read network news as a slave without connecting to local server." t nil)
 
@@ -184,21 +181,26 @@ If ARG is non-nil and a positive number, Gnus will use that as the
 startup level.  If ARG is non-nil and not a positive number, Gnus will
 prompt the user for the name of an NNTP server to use." t nil)
 
-(autoload 'gnus-fetch-group "gnus" "\
+;;;***
+
+;;; These have moved out of gnus.el into other files.
+;;; FIX FIX FIX: should other things be in gnus-setup? or these not in it?
+(autoload 'gnus-update-format "gnus-spec" "\
+Update the format specification near point." t nil)
+
+(autoload 'gnus-fetch-group "gnus-group" "\
 Start Gnus if necessary and enter GROUP.
 Returns whether the fetching was successful or not." t nil)
 
 (defalias 'gnus-batch-kill 'gnus-batch-score)
 
-(autoload 'gnus-batch-score "gnus" "\
+(autoload 'gnus-batch-score "gnus-kill" "\
 Run batched scoring.
 Usage: emacs -batch -l gnus -f gnus-batch-score <newsgroups> ...
 Newsgroups is a list of strings in Bnews format.  If you want to score
 the comp hierarchy, you'd say \"comp.all\".  If you would not like to
 score the alt hierarchy, you'd say \"!alt.all\"." t nil)
 
-;;;***
-
 (provide 'gnus-setup)
 
 (run-hooks 'gnus-setup-load-hook)
index 28c16d1..f43a946 100644 (file)
@@ -165,6 +165,10 @@ move those articles instead."
   "Make a SOUP packet from the SOUP areas."
   (interactive)
   (gnus-soup-read-areas)
+  (unless (file-exists-p gnus-soup-directory)
+    (message "No such directory: %s" gnus-soup-directory))
+  (when (null (directory-files gnus-soup-directory nil "\\.MSG$"))
+    (message "No files to pack."))
   (gnus-soup-pack gnus-soup-directory gnus-soup-packer))
 
 (defun gnus-group-brew-soup (n)
index 5528d24..8b96b35 100644 (file)
@@ -278,7 +278,7 @@ current article is unread."
 In particular, if `vertical' do only vertical recentering.  If non-nil
 and non-`vertical', do both horizontal and vertical recentering."
   :group 'gnus-summary
-  :type '(choice (const "none" nil)
+  :type '(choice (const :tag "none" nil)
                 (const vertical)
                 (sexp :menu-tag "both" t)))
 
@@ -1494,6 +1494,7 @@ increase the score of each group you read."
   (gnus-define-keys (gnus-summary-save-map "O" gnus-summary-mode-map)
     "o" gnus-summary-save-article
     "m" gnus-summary-save-article-mail
+    "F" gnus-summary-write-article-file
     "r" gnus-summary-save-article-rmail
     "f" gnus-summary-save-article-file
     "b" gnus-summary-save-article-body-file
@@ -1685,6 +1686,7 @@ increase the score of each group you read."
        ["Save in default format" gnus-summary-save-article t]
        ["Save in file" gnus-summary-save-article-file t]
        ["Save in Unix mail format" gnus-summary-save-article-mail t]
+       ["Write to file" gnus-summary-write-article-mail t]
        ["Save in MH folder" gnus-summary-save-article-folder t]
        ["Save in VM folder" gnus-summary-save-article-vm t]
        ["Save in RMAIL mbox" gnus-summary-save-article-rmail t]
@@ -2293,7 +2295,6 @@ This is all marks except unread, ticked, dormant, and expirable."
 ;; Saving hidden threads.
 
 (put 'gnus-save-hidden-threads 'lisp-indent-function 0)
-(put 'gnus-save-hidden-threads 'lisp-indent-hook 0)
 (put 'gnus-save-hidden-threads 'edebug-form-spec '(body))
 
 (defmacro gnus-save-hidden-threads (&rest forms)
@@ -3269,9 +3270,9 @@ If NO-DISPLAY, don't generate a summary buffer."
 
 (defsubst gnus-article-sort-by-date (h1 h2)
   "Sort articles by root article date."
-  (string-lessp
-   (inline (gnus-sortable-date (mail-header-date h1)))
-   (inline (gnus-sortable-date (mail-header-date h2)))))
+  (gnus-time-less
+   (gnus-date-get-time (mail-header-date h1))
+   (gnus-date-get-time (mail-header-date h2))))
 
 (defun gnus-thread-sort-by-date (h1 h2)
   "Sort threads by root article date."
@@ -4713,7 +4714,8 @@ displayed, no centering will be performed."
       (save-excursion
        (while articles
          (gnus-summary-goto-subject (setq article (pop articles)))
-         (command-execute func)
+         (let (gnus-newsgroup-processable)
+           (command-execute func))
          (gnus-summary-remove-process-mark article)))))
   (gnus-summary-position-point))
 
@@ -7983,6 +7985,17 @@ save those articles instead."
   (let ((gnus-default-article-saver 'gnus-summary-save-in-file))
     (gnus-summary-save-article arg)))
 
+(defun gnus-summary-write-article-file (&optional arg)
+  "Write the current article to a file, deleting the previous file.
+If N is a positive number, save the N next articles.
+If N is a negative number, save the N previous articles.
+If N is nil and any articles have been marked with the process mark,
+save those articles instead."
+  (interactive "P")
+  (gnus-set-global-variables)
+  (let ((gnus-default-article-saver 'gnus-summary-write-to-file))
+    (gnus-summary-save-article arg)))
+
 (defun gnus-summary-save-article-body-file (&optional arg)
   "Append the current article body to a file.
 If N is a positive number, save the N next articles.
index 4ae61ae..179fe85 100644 (file)
@@ -437,8 +437,8 @@ articles in the topic and its subtopics."
       (while (and (zerop (forward-line 1))
                  (> (or (gnus-group-topic-level) (1+ level)) level)))
       (delete-region beg (point))
-      (setcar (cdadr (gnus-topic-find-topology topic))
-             (if insert 'visible 'invisible))
+      (setcdr (cadr (gnus-topic-find-topology topic))
+             (if insert (list 'visible) (list 'invisible)))
       (when hide
        (setcdr (cdadr (gnus-topic-find-topology topic))
                (list hide)))
@@ -1033,7 +1033,8 @@ If COPYP, copy the groups instead."
       (let ((topic (gnus-group-topic-name)))
        (gnus-topic-remove-topic nil t)
        (push (gnus-topic-find-topology topic nil nil gnus-topic-topology)
-             gnus-topic-killed-topics))
+             gnus-topic-killed-topics)
+       (gnus-topic-enter-dribble))
     (gnus-group-kill-group n discard)
     (gnus-topic-update-topic)))
   
@@ -1048,6 +1049,7 @@ If COPYP, copy the groups instead."
        (gnus-topic-create-topic
         (caar item) (gnus-topic-parent-topic previous) previous
         item)
+       (gnus-topic-enter-dribble)
        (gnus-topic-goto-topic (caar item)))
     (let* ((prev (gnus-group-group-name))
           (gnus-topic-inhibit-change-level t)
index 35fa60e..1beab7e 100644 (file)
@@ -128,7 +128,6 @@ FORMS may use backtick quote syntax."
        ,@form))))
 
 (put 'gnus-undo-register 'lisp-indent-function 0)
-(put 'gnus-undo-register 'lisp-indent-hook 0)
 (put 'gnus-undo-register 'edebug-form-spec '(body))
 
 (defun gnus-undo-register-1 (function)
index d5cad93..4a89e07 100644 (file)
@@ -52,7 +52,6 @@
         (select-window ,tempvar)))))
 
 (put 'gnus-eval-in-buffer-window 'lisp-indent-function 1)
-(put 'gnus-eval-in-buffer-window 'lisp-indent-hook 1)
 (put 'gnus-eval-in-buffer-window 'edebug-form-spec '(form body))
 
 (defmacro gnus-intern-safe (string hashtable)
   `(gnus-define-keys-1 (quote ,keymap) (quote ,plist) t))
 
 (put 'gnus-define-keys 'lisp-indent-function 1)
-(put 'gnus-define-keys 'lisp-indent-hook 1)
 (put 'gnus-define-keys-safe 'lisp-indent-function 1)
-(put 'gnus-define-keys-safe 'lisp-indent-hook 1)
 (put 'gnus-local-set-keys 'lisp-indent-function 1)
-(put 'gnus-local-set-keys 'lisp-indent-hook 1)
 
 (defmacro gnus-define-keymap (keymap &rest plist)
   "Define all keys in PLIST in KEYMAP."
   `(gnus-define-keys-1 ,keymap (quote ,plist)))
 
 (put 'gnus-define-keymap 'lisp-indent-function 1)
-(put 'gnus-define-keymap 'lisp-indent-hook 1)
 
 (defun gnus-define-keys-1 (keymap plist &optional safe)
   (when (null keymap)
                         timezone-months-assoc))
                   "???"))))))
 
-(defun gnus-time-iso8601 (time)
+(defmacro gnus-date-get-time (date)
+  "Convert DATE string to Emacs time.
+Cache the result as a text property stored in DATE."
+  ;; Either return the cached value...
+  `(let ((d ,date))
+     (or (get-text-property 0 'gnus-time d)
+        ;; or compute the value...
+        (let ((time (nnmail-date-to-time d)))
+          ;; and store it back in the string.
+          (put-text-property 0 1 'gnus-time time d)
+          time))))
+
+(defsubst gnus-time-iso8601 (time)
   "Return a string of TIME in YYMMDDTHHMMSS format."
   (format-time-string "%Y%m%dT%H%M%S" time))
   
 (defun gnus-date-iso8601 (header)
   "Convert the date field in HEADER to YYMMDDTHHMMSS"
   (condition-case ()
-      (gnus-time-iso8601 (nnmail-date-to-time (mail-header-date header)))
+      (gnus-time-iso8601 (gnus-date-get-time (mail-header-date header)))
     (error "")))
 
 (defun gnus-mode-string-quote (string)
-  "Quote all \"%\" in STRING."
+  "Quote all \"%\"'s in STRING."
   (save-excursion
     (gnus-set-work-buffer)
     (insert string)
index 10a26d2..0efa328 100644 (file)
@@ -260,7 +260,6 @@ call it with the value of the `gnus-data' text property."
 (defmacro gnus-xmas-menu-add (type &rest menus)
   `(gnus-xmas-menu-add-1 ',type ',menus))
 (put 'gnus-xmas-menu-add 'lisp-indent-function 1)
-(put 'gnus-xmas-menu-add 'lisp-indent-hook 1)
 
 (defun gnus-xmas-menu-add-1 (type menus)
   (when (and menu-bar-mode
@@ -270,45 +269,49 @@ call it with the value of the `gnus-data' text property."
 
 (defun gnus-xmas-group-menu-add ()
   (gnus-xmas-menu-add group
-                     gnus-group-reading-menu gnus-group-group-menu gnus-group-misc-menu))
+    gnus-group-reading-menu gnus-group-group-menu gnus-group-misc-menu))
 
 (defun gnus-xmas-summary-menu-add ()
   (gnus-xmas-menu-add summary
-                     gnus-summary-misc-menu gnus-summary-kill-menu
-                     gnus-summary-article-menu gnus-summary-thread-menu
-                     gnus-summary-post-menu ))
+    gnus-summary-misc-menu gnus-summary-kill-menu
+    gnus-summary-article-menu gnus-summary-thread-menu
+    gnus-summary-post-menu ))
 
 (defun gnus-xmas-article-menu-add ()
   (gnus-xmas-menu-add article
-                     gnus-article-article-menu gnus-article-treatment-menu))
+    gnus-article-article-menu gnus-article-treatment-menu))
 
 (defun gnus-xmas-score-menu-add ()
   (gnus-xmas-menu-add score
-                     gnus-score-menu))
+    gnus-score-menu))
 
 (defun gnus-xmas-pick-menu-add ()
   (gnus-xmas-menu-add pick
-                     gnus-pick-menu))
+    gnus-pick-menu))
+
+(defun gnus-xmas-topic-menu-add ()
+  (gnus-xmas-menu-add topic
+    gnus-topic-menu))
 
 (defun gnus-xmas-binary-menu-add ()
   (gnus-xmas-menu-add binary
-                     gnus-binary-menu))
+    gnus-binary-menu))
 
 (defun gnus-xmas-tree-menu-add ()
   (gnus-xmas-menu-add tree
-                     gnus-tree-menu))
+    gnus-tree-menu))
 
 (defun gnus-xmas-server-menu-add ()
   (gnus-xmas-menu-add menu
-                     gnus-server-server-menu gnus-server-connections-menu))
+    gnus-server-server-menu gnus-server-connections-menu))
 
 (defun gnus-xmas-browse-menu-add ()
   (gnus-xmas-menu-add browse
-                     gnus-browse-menu))
+    gnus-browse-menu))
 
 (defun gnus-xmas-grouplens-menu-add ()
   (gnus-xmas-menu-add grouplens
-                     gnus-grouplens-menu))
+    gnus-grouplens-menu))
 
 (defun gnus-xmas-read-event-char ()
   "Get the next event."
@@ -440,6 +443,7 @@ call it with the value of the `gnus-data' text property."
   (add-hook 'gnus-score-mode-hook 'gnus-xmas-score-menu-add)
 
   (add-hook 'gnus-pick-mode-hook 'gnus-xmas-pick-menu-add)
+  (add-hook 'gnus-topic-mode-hook 'gnus-xmas-topic-menu-add)
   (add-hook 'gnus-tree-mode-hook 'gnus-xmas-tree-menu-add)
   (add-hook 'gnus-binary-mode-hook 'gnus-xmas-binary-menu-add)
   (add-hook 'gnus-grouplens-mode-hook 'gnus-xmas-grouplens-menu-add)
index 07503b8..b353b77 100644 (file)
   "Score and kill file handling."
   :group 'gnus )
 
-(defconst gnus-version-number "0.52"
+(defconst gnus-version-number "0.53"
   "Version number for this version of Gnus.")
 
 (defconst gnus-version (format "Red Gnus v%s" gnus-version-number)
   "Version string for this version of Gnus.")
 
 (defcustom gnus-inhibit-startup-message nil
-  "*If non-nil, the startup message will not be displayed."
+  "*If non-nil, the startup message will not be displayed.
+This variable is used before `.gnus.el' is loaded, so it should
+be set in `.emacs' instead."
   :group 'gnus-start
   :type 'boolean)
 
        (t
         'ignore)))
 
+(defalias 'gnus-make-overlay 'make-overlay)
+(defalias 'gnus-overlay-put 'overlay-put)
+(defalias 'gnus-move-overlay 'move-overlay)
+(defalias 'gnus-overlay-end 'overlay-end)
+(defalias 'gnus-extent-detached-p '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-make-local-hook 'make-local-hook)
+(defalias 'gnus-add-hook 'add-hook)
+(defalias 'gnus-character-to-event 'identity)
+(defalias 'gnus-add-text-properties 'add-text-properties)
+(defalias 'gnus-put-text-property 'put-text-property)
+(defalias 'gnus-mode-line-buffer-identification 'identity)
+
 ;; 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."
@@ -810,6 +830,8 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
      ("hexl" hexl-hex-string-to-integer)
      ("pp" pp pp-to-string pp-eval-expression)
      ("mail-extr" mail-extract-address-components)
+     ("message" :interactive t
+      message-send-and-exit message-yank-original)
      ("nnmail" nnmail-split-fancy nnmail-article-group nnmail-date-to-time)
      ("nnvirtual" nnvirtual-catchup-group nnvirtual-convert-headers)
      ("timezone" timezone-make-date-arpa-standard timezone-fix-time
@@ -823,7 +845,7 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-soup-send-replies gnus-soup-save-areas gnus-soup-pack-packet)
      ("nnsoup" nnsoup-pack-replies)
      ("score-mode" :interactive t gnus-score-mode)
-     ("gnus-mh" gnus-mh-mail-setup gnus-summary-save-article-folder
+     ("gnus-mh" gnus-summary-save-article-folder
       gnus-Folder-save-name gnus-folder-save-name)
      ("gnus-mh" :interactive t gnus-summary-save-in-folder)
      ("gnus-demon" gnus-demon-add-nocem gnus-demon-add-scanmail
@@ -849,20 +871,20 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-cache-retrieve-headers gnus-cache-possibly-alter-active
       gnus-cache-enter-remove-article gnus-cached-article-p
       gnus-cache-open gnus-cache-close gnus-cache-update-article)
-     ("gnus-cache" :interactive t gnus-jog-cache gnus-cache-enter-article
-      gnus-cache-remove-article gnus-summary-insert-cached-articles)
-     ("gnus-score" :interactive t
-      gnus-summary-increase-score gnus-summary-lower-score
-      gnus-score-flush-cache gnus-score-close
-      gnus-score-raise-same-subject-and-select
-      gnus-score-raise-same-subject gnus-score-default
-      gnus-score-raise-thread gnus-score-lower-same-subject-and-select
-      gnus-score-lower-same-subject gnus-score-lower-thread
-      gnus-possibly-score-headers gnus-summary-raise-score 
-      gnus-summary-set-score gnus-summary-current-score
-      gnus-score-followup-article)
-     ("gnus-score"
-      (gnus-summary-score-map keymap) gnus-score-save gnus-score-headers
+      ("gnus-cache" :interactive t gnus-jog-cache gnus-cache-enter-article
+       gnus-cache-remove-article gnus-summary-insert-cached-articles)
+      ("gnus-score" :interactive t
+       gnus-summary-increase-score gnus-summary-set-score
+       gnus-summary-raise-thread gnus-summary-raise-same-subject
+       gnus-summary-raise-score gnus-summary-raise-same-subject-and-select
+       gnus-summary-lower-thread gnus-summary-lower-same-subject
+       gnus-summary-lower-score gnus-summary-lower-same-subject-and-select
+       gnus-summary-current-score gnus-score-default
+       gnus-score-flush-cache gnus-score-close
+       gnus-possibly-score-headers gnus-score-followup-article
+       gnus-score-followup-thread)
+      ("gnus-score"
+       (gnus-summary-score-map keymap) gnus-score-save gnus-score-headers
       gnus-current-score-file-nondirectory gnus-score-adaptive
       gnus-score-find-trace gnus-score-file-name)
      ("gnus-cus" :interactive t gnus-group-customize gnus-score-customize)
@@ -882,17 +904,14 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-uu-decode-unshar-and-save-view gnus-uu-decode-save-view
       gnus-uu-decode-binhex-view)
      ("gnus-msg" (gnus-summary-send-map keymap)
-      gnus-mail-yank-original gnus-mail-send-and-exit
-      gnus-article-mail gnus-new-mail gnus-mail-reply
-      gnus-copy-article-buffer gnus-extended-version)
+      gnus-article-mail gnus-copy-article-buffer gnus-extended-version)
      ("gnus-msg" :interactive t
       gnus-group-post-news gnus-group-mail gnus-summary-post-news
       gnus-summary-followup gnus-summary-followup-with-original
       gnus-summary-cancel-article gnus-summary-supersede-article
-      gnus-post-news gnus-inews-news 
-      gnus-summary-reply gnus-summary-reply-with-original
+      gnus-post-news gnus-summary-reply gnus-summary-reply-with-original
       gnus-summary-mail-forward gnus-summary-mail-other-window
-      gnus-summary-resend-message gnus-summary-bounced-mail
+      gnus-summary-resend-message gnus-summary-resend-bounced-mail
       gnus-bug)
      ("gnus-picon" :interactive t gnus-article-display-picons
       gnus-group-display-picons gnus-picons-article-display-x-face
@@ -900,7 +919,6 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
      ("gnus-gl" bbb-login bbb-logout bbb-grouplens-group-p 
       gnus-grouplens-mode)
      ("smiley" :interactive t gnus-smiley-display)
-     ("gnus" gnus-add-current-to-buffer-list gnus-add-shutdown)
      ("gnus-win" gnus-configure-windows)
      ("gnus-sum" gnus-summary-insert-line gnus-summary-read-group
       gnus-list-of-unread-articles gnus-list-of-read-articles
@@ -915,9 +933,9 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
       gnus-backlog-remove-article)
      ("gnus-art" gnus-article-read-summary-keys gnus-article-save
       gnus-article-prepare gnus-article-set-window-start
-      gnus-article-show-all-headers gnus-article-next-page
-      gnus-article-prev-page gnus-request-article-this-buffer
-      gnus-article-mode gnus-article-setup-buffer gnus-narrow-to-page)
+      gnus-article-next-page gnus-article-prev-page
+      gnus-request-article-this-buffer gnus-article-mode
+      gnus-article-setup-buffer gnus-narrow-to-page)
      ("gnus-art" :interactive t
       gnus-article-hide-headers gnus-article-hide-boring-headers
       gnus-article-treat-overstrike gnus-article-word-wrap
@@ -933,15 +951,14 @@ gnus-newsrc-hashtb should be kept so that both hold the same information.")
      ("gnus-int" gnus-request-type)
      ("gnus-start" gnus-newsrc-parse-options gnus-1 gnus-no-server-1
       gnus-dribble-enter)
-     ("gnus-dup" gnus-dup-suppress-articles gnus-dup-enter-articles)
+     ("gnus-dup" gnus-dup-suppress-articles gnus-dup-unsuppress-article
+      gnus-dup-enter-articles)
      ("gnus-range" gnus-copy-sequence)
-     ("gnus-vm" gnus-vm-mail-setup)
      ("gnus-eform" gnus-edit-form)
      ("gnus-move" :interactive t
       gnus-group-move-group-to-server gnus-change-server)
      ("gnus-logic" gnus-score-advanced)
-     ("gnus-undo" gnus-undo-mode gnus-undo-register 
-      gnus-dup-unsuppress-article)
+     ("gnus-undo" gnus-undo-mode gnus-undo-register)
      ("gnus-async" gnus-async-request-fetched-article gnus-async-prefetch-next
       gnus-async-prefetch-article gnus-async-prefetch-remove-group)
      ("article" article-decode-rfc1522)
@@ -1026,26 +1043,6 @@ This restriction may disappear in later versions of Gnus.")
 (defvar gnus-group-mode-map (make-keymap))
 (gnus-suppress-keymap gnus-group-mode-map)
 
-;;; Function aliases later to be redefined for XEmacs usage.
-
-(defalias 'gnus-make-overlay 'make-overlay)
-(defalias 'gnus-overlay-put 'overlay-put)
-(defalias 'gnus-move-overlay 'move-overlay)
-(defalias 'gnus-overlay-end 'overlay-end)
-(defalias 'gnus-extent-detached-p '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-make-local-hook 'make-local-hook)
-(defalias 'gnus-add-hook 'add-hook)
-(defalias 'gnus-character-to-event 'identity)
-(defalias 'gnus-add-text-properties 'add-text-properties)
-(defalias 'gnus-put-text-property 'put-text-property)
-(defalias 'gnus-mode-line-buffer-identification 'identity)
-
 \f
 
 ;; Fix by Hallvard B Furuseth <h.b.furuseth@usit.uio.no>.
@@ -1066,7 +1063,7 @@ This restriction may disappear in later versions of Gnus.")
 (defmacro gnus-sethash (string value hashtable)
   "Set hash value.  Arguments are STRING, VALUE, and HASHTABLE."
   `(set (intern ,string ,hashtable) ,value))
-(put 'nnheader-temp-write 'edebug-form-spec '(form form form))
+(put 'gnus-sethash 'edebug-form-spec '(form form form))
 
 (defmacro gnus-group-unread (group)
   "Get the currently computed number of unread articles in GROUP."
@@ -1583,8 +1580,7 @@ just the host name."
                                               ((< colon dot) colon)
                                               ((< dot colon) dot)))
                              ":")
-                    group (substring group (+ 1 colon))
-                    )))
+                    group (substring group (+ 1 colon)))))
            (t
             (let* ((colon (string-match ":" group)))
               (setq foreign (concat (substring group 0 (+ 1 colon)))
@@ -1600,7 +1596,6 @@ just the host name."
              group nil)))
     name))
 
-
 \f
 ;;;
 ;;; Kill file handling.
index 1627213..23cb5fe 100644 (file)
@@ -301,7 +301,11 @@ nil means use indentation.")
 Used by `message-yank-original' via `message-yank-cite'.")
 
 ;;;###autoload
-(defvar message-cite-function 'message-cite-original
+(defvar message-cite-function
+  (if (and (boundp 'mail-citation-hook)
+          mail-citation-hook)
+      mail-citation-hook
+    'message-cite-original)
   "*Function for citing an original message.")
 
 ;;;###autoload
@@ -429,6 +433,12 @@ The cdr of ech entry is a function for applying the face to a region.")
 (defvar message-send-hook nil
   "Hook run before sending messages.")
 
+(defvar message-send-mail-hook nil
+  "Hook run before sending mail messages.")
+
+(defvar message-send-news-hook nil
+  "Hook run before sending news messages.")
+
 (defvar message-sent-hook nil
   "Hook run after sending messages.")
 
@@ -545,34 +555,36 @@ The cdr of ech entry is a function for applying the face to a region.")
 (defun message-tokenize-header (header &optional separator)
   "Split HEADER into a list of header elements.
 \",\" is used as the separator."
-  (let ((regexp (format "[%s]+" (or separator ",")))
-       (beg 1)
-       (first t)
-       quoted elems paren)
-    (save-excursion
-      (message-set-work-buffer)
-      (insert header)
-      (goto-char (point-min))
-      (while (not (eobp))
-       (if first
-           (setq first nil)
-         (forward-char 1))
-       (cond ((and (> (point) beg)
-                   (or (eobp)
-                       (and (looking-at regexp)
-                            (not quoted)
-                            (not paren))))
-              (push (buffer-substring beg (point)) elems)
-              (setq beg (match-end 0)))
-             ((= (following-char) ?\")
-              (setq quoted (not quoted)))
-             ((and (= (following-char) ?\()
-                   (not quoted))
-              (setq paren t))
-             ((and (= (following-char) ?\))
-                   (not quoted))
-              (setq paren nil))))
-      (nreverse elems))))
+  (if (not header)
+      nil
+    (let ((regexp (format "[%s]+" (or separator ",")))
+         (beg 1)
+         (first t)
+         quoted elems paren)
+      (save-excursion
+       (message-set-work-buffer)
+       (insert header)
+       (goto-char (point-min))
+       (while (not (eobp))
+         (if first
+             (setq first nil)
+           (forward-char 1))
+         (cond ((and (> (point) beg)
+                     (or (eobp)
+                         (and (looking-at regexp)
+                              (not quoted)
+                              (not paren))))
+                (push (buffer-substring beg (point)) elems)
+                (setq beg (match-end 0)))
+               ((= (following-char) ?\")
+                (setq quoted (not quoted)))
+               ((and (= (following-char) ?\()
+                     (not quoted))
+                (setq paren t))
+               ((and (= (following-char) ?\))
+                     (not quoted))
+                (setq paren nil))))
+       (nreverse elems)))))
 
 (defun message-fetch-field (header)
   "The same as `mail-fetch-field', only remove all newlines."
@@ -981,20 +993,21 @@ C-c C-r  message-caesar-buffer-body (rot13 the message body)."
   "Insert a signature.  See documentation for the `message-signature' variable."
   (interactive (list 0))
   (let* ((signature 
-         (cond ((and (null message-signature)
-                     (eq force 0))
-                (save-excursion
-                  (goto-char (point-max))
-                  (not (re-search-backward
-                        message-signature-separator nil t))))
-               ((and (null message-signature)
-                     force)
-                t)
-               ((message-functionp message-signature)
-                (funcall message-signature))
-               ((listp message-signature)
-                (eval message-signature))
-               (t message-signature)))
+         (cond
+          ((and (null message-signature)
+                (eq force 0))
+           (save-excursion
+             (goto-char (point-max))
+             (not (re-search-backward
+                   message-signature-separator nil t))))
+          ((and (null message-signature)
+                force)
+           t)
+          ((message-functionp message-signature)
+           (funcall message-signature))
+          ((listp message-signature)
+           (eval message-signature))
+          (t message-signature)))
         (signature
          (cond ((stringp signature)
                 signature)
@@ -1356,7 +1369,7 @@ the user from the mailer."
 
 (defun message-send-mail (&optional arg)
   (require 'mail-utils)
-  (let ((tembuf (generate-new-buffer " message temp"))
+  (let ((tembuf (message-generate-new-buffer-clone-locals " message temp"))
        (case-fold-search nil)
        (news (message-news-p))
        (mailbuf (current-buffer)))
@@ -1412,6 +1425,7 @@ the user from the mailer."
       (replace-match "\n")
       (backward-char 1)
       (setq delimline (point-marker))
+      (run-hooks 'message-send-mail-hook)
       ;; Insert an extra newline if we need it to work around
       ;; Sun's bug that swallows newlines.
       (goto-char (1+ delimline))
@@ -1463,6 +1477,7 @@ to find out how to use this."
   (re-search-forward
    (concat "^" (regexp-quote mail-header-separator) "\n"))
   (replace-match "\n")
+  (run-hooks 'message-send-mail-hook)
   ;; send the message
   (case
       (apply
@@ -1494,7 +1509,6 @@ to find out how to use this."
     ;; should never happen
     (t   (error "qmail-inject reported unknown failure."))))
 
-
 (defun message-send-mail-with-mh ()
   "Send the prepared message buffer with mh."
   (let ((mh-previous-window-config nil)
@@ -1511,11 +1525,12 @@ to find out how to use this."
              (concat "^" (symbol-name (car headers)) ": *") nil t)
             (message-delete-line))
        (pop headers)))
+    (run-hooks 'message-send-mail-hook)
     ;; Pass it on to mh.
     (mh-send-letter)))
 
 (defun message-send-news (&optional arg)
-  (let ((tembuf (generate-new-buffer " *message temp*"))
+  (let ((tembuf (message-generate-new-buffer-clone-locals " *message temp*"))
        (case-fold-search nil)
        (method (if (message-functionp message-post-method)
                    (funcall message-post-method arg)
@@ -1536,7 +1551,7 @@ to find out how to use this."
     (message-cleanup-headers)
     (if (not (message-check-news-syntax))
        (progn
-         (message "Posting nor performed")
+         ;;(message "Posting not performed")
          nil)
       (unwind-protect
          (save-excursion
@@ -1564,6 +1579,7 @@ to find out how to use this."
               (concat "^" (regexp-quote mail-header-separator) "\n"))
              (replace-match "\n")
              (backward-char 1))
+           (run-hooks 'message-send-news-hook)
            (require (car method))
            (funcall (intern (format "%s-open-server" (car method)))
                     (cadr method) (cddr method))
@@ -1581,257 +1597,252 @@ to find out how to use this."
 ;;; Header generation & syntax checking.
 ;;;
 
+(defmacro message-check (type &rest forms)
+  "Eval FORMS if TYPE is to be checked."
+  `(or (message-check-element ,type)
+       (save-excursion
+        ,@forms)))
+
+(put 'message-check 'lisp-indent-function 1)
+(put 'message-check 'edebug-form-spec '(form body))
+
+(defun message-check-element (type)
+  "Returns non-nil if this type is not to be checked."
+  (if (eq message-syntax-checks 'dont-check-for-anything-just-trust-me)
+      t
+    (let ((able (assq type message-syntax-checks)))
+      (and (consp able)
+          (eq (cdr able) 'disabled)))))
+
 (defun message-check-news-syntax ()
   "Check the syntax of the message."
+  (save-excursion
+    (save-restriction
+      (widen)
+      (and 
+       ;; We narrow to the headers and check them first.
+       (save-excursion
+        (save-restriction
+          (message-narrow-to-headers)
+          (message-check-news-header-syntax)))
+       ;; Check the body.
+       (message-check-news-body-syntax)))))
+
+(defun message-check-news-header-syntax ()
   (and 
-   ;; We narrow to the headers and check them first.
-   (save-excursion
-     (save-restriction
-       (message-narrow-to-headers)
-       (and 
-       ;; Check for commands in Subject.
-       (or 
-        (message-check-element 'subject-cmsg)
+   ;; Check for commands in Subject.
+   (message-check 'subject-cmsg
+     (if (string-match "^cmsg " (message-fetch-field "subject"))
+        (y-or-n-p
+         "The control code \"cmsg\" is in the subject.  Really post? ")
+       t))
+   ;; Check for multiple identical headers.
+   (message-check 'multiple-headers
+     (let (found)
+       (while (and (not found) 
+                  (re-search-forward "^[^ \t:]+: " nil t))
         (save-excursion
-          (if (string-match "^cmsg " (message-fetch-field "subject"))
-              (y-or-n-p
-               "The control code \"cmsg \" is in the subject.  Really post? ")
-            t)))
-       ;; Check for multiple identical headers.
-       (or (message-check-element 'multiple-headers)
-           (save-excursion
-             (let (found)
-               (while (and (not found) 
-                           (re-search-forward "^[^ \t:]+: " nil t))
-                 (save-excursion
-                   (or (re-search-forward 
-                        (concat "^" (setq found
-                                          (buffer-substring 
-                                           (match-beginning 0) 
-                                           (- (match-end 0) 2))))
-                        nil t)
-                       (setq found nil))))
-               (if found
-                   (y-or-n-p 
-                    (format "Multiple %s headers.  Really post? " found))
-                 t))))
-       ;; Check for Version and Sendsys.
-       (or (message-check-element 'sendsys)
-           (save-excursion
-             (if (re-search-forward "^Sendsys:\\|^Version:" nil t)
-                 (y-or-n-p
-                  (format "The article contains a %s command.  Really post? "
-                          (buffer-substring (match-beginning 0) 
-                                            (1- (match-end 0)))))
-               t)))
-       ;; See whether we can shorten Followup-To.
-       (or (message-check-element 'shorten-followup-to)
-           (let ((newsgroups (message-fetch-field "newsgroups"))
-                 (followup-to (message-fetch-field "followup-to"))
-                 to)
-             (when (and newsgroups (string-match "," newsgroups)
-                        (not followup-to)
-                        (not
-                         (zerop
-                          (length
-                           (setq to (completing-read 
-                                     "Followups to: (default all groups) " 
-                                     (mapcar (lambda (g) (list g))
-                                             (cons "poster" 
-                                                   (message-tokenize-header 
-                                                    newsgroups)))))))))
-               (goto-char (point-min))
-               (insert "Followup-To: " to "\n"))
-             t))
-       ;; Check "Shoot me".
-       (or (message-check-element 'shoot)
-           (save-excursion
-             (if (re-search-forward
-                  "Message-ID.*.i-have-a-misconfigured-system-so-shoot-me"
-                  nil t)
-                 (y-or-n-p
-                  "You appear to have a misconfigured system.  Really post? ")
-               t)))
-       ;; Check for Approved.
-       (or (message-check-element 'approved)
-           (save-excursion
-             (if (re-search-forward "^Approved:" nil t)
-                 (y-or-n-p
-                  "The article contains an Approved header.  Really post? ")
-               t)))
-       ;; Check the Message-ID header.
-       (or (message-check-element 'message-id)
-           (save-excursion
-             (let* ((case-fold-search t)
-                    (message-id (message-fetch-field "message-id")))
-               (or (not message-id)
-                   (and (string-match "@" message-id)
-                        (string-match "@[^\\.]*\\." message-id))
-                   (y-or-n-p
-                    (format 
-                     "The Message-ID looks strange: \"%s\".  Really post? "
-                     message-id))))))
-       ;; Check the Subject header.
-       (or 
-        (message-check-element 'subject)
-        (save-excursion
-          (let* ((case-fold-search t)
-                 (subject (message-fetch-field "subject")))
-            (or
-             (and subject
-                  (not (string-match "\\`[ \t]*\\'" subject)))
-             (progn
-               (message 
-                "The subject field is empty or missing.  Posting is denied.")
-               nil)))))
-       ;; Check the Newsgroups & Followup-To headers.
-       (or
-        (message-check-element 'existing-newsgroups)
-        (let* ((case-fold-search t)
-               (newsgroups (message-fetch-field "newsgroups"))
-               (followup-to (message-fetch-field "followup-to"))
-               (groups (message-tokenize-header
-                        (if followup-to
-                            (concat newsgroups "," followup-to)
-                          newsgroups)))
-               (hashtb (and (boundp 'gnus-active-hashtb)
-                            gnus-active-hashtb))
-               errors)
-          (if (not hashtb)
-              t
-            (while groups
-              (when (and (not (boundp (intern (car groups) hashtb)))
-                         (not (equal (car groups) "poster")))
-                (push (car groups) errors))
-              (pop groups))
-            (if (not errors)
-                t
-              (y-or-n-p
-               (format
-                "Really post to %s unknown group%s: %s "
-                (if (= (length errors) 1) "this" "these")
-                (if (= (length errors) 1) "" "s")
-                (mapconcat 'identity errors ", ")))))))
-       ;; Check the Newsgroups & Followup-To headers for syntax errors.
-       (or
-        (message-check-element 'valid-newsgroups)
-        (let ((case-fold-search t)
-              (headers '("Newsgroups" "Followup-To"))
-              header error)
-          (while (and headers (not error))
-            (when (setq header (mail-fetch-field (car headers)))
-              (if (or
-                   (not 
-                    (string-match
-                     "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-+_&.a-zA-Z0-9]+\\)*\\'"
-                     header))
-                   (memq 
-                    nil (mapcar 
-                         (lambda (g)
-                           (not (string-match "\\.\\'\\|\\.\\." g)))
-                         (message-tokenize-header header ","))))
-                  (setq error t)))
-            (unless error
-              (pop headers)))
-          (if (not error)
-              t
-            (y-or-n-p
-             (format "The %s header looks odd: \"%s\".  Really post? "
-                     (car headers) header)))))
-       ;; Check the From header.
-       (or 
-        (save-excursion
-          (let* ((case-fold-search t)
-                 (from (message-fetch-field "from")))
-            (cond
-             ((not from)
-              (message "There is no From line.  Posting is denied.")
-              nil)
-             ((not (string-match "@[^\\.]*\\." from))
-              (message
-               "Denied posting -- the From looks strange: \"%s\"." from)
-              nil)
-             ((string-match "@[^@]*@" from)
-              (message 
-               "Denied posting -- two \"@\"'s in the From header: %s." from)
-              nil)
-             ((string-match "(.*).*(.*)" from)
-              (message
-               "Denied posting -- the From header looks strange: \"%s\"." 
-               from)
-              nil)
-             (t t))))))))
-   ;; Check for long lines.
-   (or (message-check-element 'long-lines)
-       (save-excursion
+          (or (re-search-forward 
+               (concat "^" (setq found
+                                 (buffer-substring
+                                  (match-beginning 0) (- (match-end 0) 2))))
+               nil t)
+              (setq found nil))))
+       (if found
+          (y-or-n-p (format "Multiple %s headers.  Really post? " found))
+        t)))
+   ;; Check for Version and Sendsys.
+   (message-check 'sendsys
+     (if (re-search-forward "^Sendsys:\\|^Version:" nil t)
+        (y-or-n-p
+         (format "The article contains a %s command.  Really post? "
+                 (buffer-substring (match-beginning 0) 
+                                   (1- (match-end 0)))))
+       t))
+   ;; See whether we can shorten Followup-To.
+   (message-check 'shorten-followup-to
+     (let ((newsgroups (message-fetch-field "newsgroups"))
+          (followup-to (message-fetch-field "followup-to"))
+          to)
+       (when (and newsgroups
+                 (string-match "," newsgroups)
+                 (not followup-to)
+                 (not
+                  (zerop
+                   (length
+                    (setq to (completing-read 
+                              "Followups to: (default all groups) " 
+                              (mapcar (lambda (g) (list g))
+                                      (cons "poster" 
+                                            (message-tokenize-header 
+                                             newsgroups)))))))))
         (goto-char (point-min))
-        (re-search-forward
-         (concat "^" (regexp-quote mail-header-separator) "$"))
-        (while (and
-                (progn
-                  (end-of-line)
-                  (< (current-column) 80))
-                (zerop (forward-line 1))))
-        (or (bolp)
-            (eobp)
-            (y-or-n-p
-             "You have lines longer than 79 characters.  Really post? "))))
+        (insert "Followup-To: " to "\n"))
+       t))
+   ;; Check "Shoot me".
+   (message-check 'shoot
+     (if (re-search-forward
+         "Message-ID.*.i-have-a-misconfigured-system-so-shoot-me" nil t)
+        (y-or-n-p "You appear to have a misconfigured system.  Really post? ")
+       t))
+   ;; Check for Approved.
+   (message-check 'approved
+     (if (re-search-forward "^Approved:" nil t)
+        (y-or-n-p "The article contains an Approved header.  Really post? ")
+       t))
+   ;; Check the Message-ID header.
+   (message-check 'message-id
+     (let* ((case-fold-search t)
+           (message-id (message-fetch-field "message-id")))
+       (or (not message-id)
+          (and (string-match "@" message-id)
+               (string-match "@[^\\.]*\\." message-id))
+          (y-or-n-p
+           (format "The Message-ID looks strange: \"%s\".  Really post? "
+                   message-id)))))
+   ;; Check the Subject header.
+   (message-check 'subject
+     (let* ((case-fold-search t)
+           (subject (message-fetch-field "subject")))
+       (or
+       (and subject
+            (not (string-match "\\`[ \t]*\\'" subject)))
+       (ignore
+        (message 
+         "The subject field is empty or missing.  Posting is denied.")))))
+   ;; Check the Newsgroups & Followup-To headers.
+   (message-check 'existing-newsgroups
+     (let* ((case-fold-search t)
+           (newsgroups (message-fetch-field "newsgroups"))
+           (followup-to (message-fetch-field "followup-to"))
+           (groups (message-tokenize-header
+                    (if followup-to
+                        (concat newsgroups "," followup-to)
+                      newsgroups)))
+           (hashtb (and (boundp 'gnus-active-hashtb)
+                        gnus-active-hashtb))
+           errors)
+       (if (not hashtb)
+          t
+        (while groups
+          (when (and (not (boundp (intern (car groups) hashtb)))
+                     (not (equal (car groups) "poster")))
+            (push (car groups) errors))
+          (pop groups))
+        (if (not errors)
+            t
+          (y-or-n-p
+           (format
+            "Really post to %s unknown group%s: %s "
+            (if (= (length errors) 1) "this" "these")
+            (if (= (length errors) 1) "" "s")
+            (mapconcat 'identity errors ", ")))))))
+   ;; Check the Newsgroups & Followup-To headers for syntax errors.
+   (message-check 'valid-newsgroups
+     (let ((case-fold-search t)
+          (headers '("Newsgroups" "Followup-To"))
+          header error)
+       (while (and headers (not error))
+        (when (setq header (mail-fetch-field (car headers)))
+          (if (or
+               (not 
+                (string-match
+                 "\\`\\([-+_&.a-zA-Z0-9]+\\)?\\(,[-+_&.a-zA-Z0-9]+\\)*\\'"
+                 header))
+               (memq 
+                nil (mapcar 
+                     (lambda (g)
+                       (not (string-match "\\.\\'\\|\\.\\." g)))
+                     (message-tokenize-header header ","))))
+              (setq error t)))
+        (unless error
+          (pop headers)))
+       (if (not error)
+          t
+        (y-or-n-p
+         (format "The %s header looks odd: \"%s\".  Really post? "
+                 (car headers) header)))))
+   ;; Check the From header.
+   (message-check 'from
+     (let* ((case-fold-search t)
+           (from (message-fetch-field "from"))
+           (ad (nth 1 (mail-extract-address-components from))))
+       (cond
+       ((not from)
+        (message "There is no From line.  Posting is denied.")
+        nil)
+       ((or (not (string-match "@[^\\.]*\\." ad)) ;larsi@ifi
+            (string-match "\\.\\." ad) ;larsi@ifi..uio
+            (string-match "@\\." ad)   ;larsi@.ifi.uio
+            (string-match "\\.$" ad)   ;larsi@ifi.uio.
+            (not (string-match "^[^@]+@[^@]+$" ad)) ;larsi.ifi.uio
+            (string-match "(.*).*(.*)" from)) ;(lars) (lars)
+        (message
+         "Denied posting -- the From looks strange: \"%s\"." from)
+        nil)
+       (t t))))))
+
+(defun message-check-news-body-syntax ()
+  (and
+   ;; Check for long lines.
+   (message-check 'long-lines
+     (goto-char (point-min))
+     (re-search-forward
+      (concat "^" (regexp-quote mail-header-separator) "$"))
+     (while (and
+            (progn
+              (end-of-line)
+              (< (current-column) 80))
+            (zerop (forward-line 1))))
+     (or (bolp)
+        (eobp)
+        (y-or-n-p
+         "You have lines longer than 79 characters.  Really post? ")))
    ;; Check whether the article is empty.
-   (or (message-check-element 'empty)
-       (save-excursion
-        (goto-char (point-min))
-        (re-search-forward
-         (concat "^" (regexp-quote mail-header-separator) "$"))
-        (forward-line 1)
-        (let ((b (point)))
-          (goto-char (point-max))
-          (re-search-backward message-signature-separator nil t)
-          (beginning-of-line)
-          (or (re-search-backward "[^ \n\t]" b t)
-              (y-or-n-p "Empty article.  Really post? ")))))
+   (message-check 'empty
+     (goto-char (point-min))
+     (re-search-forward
+      (concat "^" (regexp-quote mail-header-separator) "$"))
+     (forward-line 1)
+     (let ((b (point)))
+       (goto-char (point-max))
+       (re-search-backward message-signature-separator nil t)
+       (beginning-of-line)
+       (or (re-search-backward "[^ \n\t]" b t)
+          (y-or-n-p "Empty article.  Really post? "))))
    ;; Check for control characters.
-   (or (message-check-element 'control-chars)
-       (save-excursion
-        (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t)
-            (y-or-n-p 
-             "The article contains control characters.  Really post? ")
-          t)))
+   (message-check 'control-chars
+     (if (re-search-forward "[\000-\007\013\015-\037\200-\237]" nil t)
+        (y-or-n-p 
+         "The article contains control characters.  Really post? ")
+       t))
    ;; Check excessive size.
-   (or (message-check-element 'size)
-       (if (> (buffer-size) 60000)
-          (y-or-n-p
-           (format "The article is %d octets long.  Really post? "
-                   (buffer-size)))
-        t))
+   (message-check 'size
+     (if (> (buffer-size) 60000)
+        (y-or-n-p
+         (format "The article is %d octets long.  Really post? "
+                 (buffer-size)))
+       t))
    ;; Check whether any new text has been added.
-   (or (message-check-element 'new-text)
-       (not message-checksum)
-       (not (and (eq (message-checksum) (car message-checksum))
-                (eq (buffer-size) (cdr message-checksum))))
-       (y-or-n-p
-       "It looks like no new text has been added.  Really post? "))
+   (message-check 'new-text
+     (or
+      (not message-checksum)
+      (not (and (eq (message-checksum) (car message-checksum))
+               (eq (buffer-size) (cdr message-checksum))))
+      (y-or-n-p
+       "It looks like no new text has been added.  Really post? ")))
    ;; Check the length of the signature.
-   (or
-    (message-check-element 'signature)
-    (progn
-      (goto-char (point-max))
-      (if (or (not (re-search-backward message-signature-separator nil t))
-             (search-forward message-forward-end-separator nil t))
-         t
-       (if (> (count-lines (point) (point-max)) 5)
-           (y-or-n-p
-            (format
-             "Your .sig is %d lines; it should be max 4.  Really post? "
-             (1- (count-lines (point) (point-max)))))
-         t))))))
-
-(defun message-check-element (type)
-  "Returns non-nil if this type is not to be checked."
-  (if (eq message-syntax-checks 'dont-check-for-anything-just-trust-me)
-      t
-    (let ((able (assq type message-syntax-checks)))
-      (and (consp able)
-          (eq (cdr able) 'disabled)))))
+   (message-check 'signature
+     (goto-char (point-max))
+     (if (or (not (re-search-backward message-signature-separator nil t))
+            (search-forward message-forward-end-separator nil t))
+        t
+       (if (> (count-lines (point) (point-max)) 5)
+          (y-or-n-p
+           (format
+            "Your .sig is %d lines; it should be max 4.  Really post? "
+            (1- (count-lines (point) (point-max)))))
+        t)))))
 
 (defun message-checksum ()
   "Return a \"checksum\" for the current buffer."
@@ -2272,7 +2283,7 @@ Headers already prepared in the buffer are not modified."
                         (downcase secure-sender)))))
          (goto-char (point-min))    
          ;; Rename any old Sender headers to Original-Sender.
-         (when (re-search-forward "^Sender:" nil t)
+         (when (re-search-forward "^\\(Original-\\)*Sender:" nil t)
            (beginning-of-line)
            (insert "Original-")
            (beginning-of-line))
@@ -3118,6 +3129,25 @@ The following arguments may contain lists of values."
        (list
         (list list))))
 
+(defun message-generate-new-buffer-clone-locals (name &optional varstr)
+  "Create and return a buffer with a name based on NAME using generate-new-buffer.
+Then clone the local variables and values from the old buffer to the
+new one, cloning only the locals having a substring matching the
+regexp varstr."
+  (let ((oldlocals (buffer-local-variables)))
+    (save-excursion
+      (set-buffer (generate-new-buffer name))
+      (mapcar (lambda (dude)
+               (when (and (car dude)
+                          (or (not varstr)
+                              (string-match varstr (symbol-name (car dude)))))
+                 (condition-case ()
+                     (set (make-local-variable (car dude))
+                          (cdr dude))
+                   (error))))
+             oldlocals)
+      (current-buffer))))
+
 (run-hooks 'message-load-hook)
 
 (provide 'message)
index c178e20..468742e 100644 (file)
@@ -63,9 +63,6 @@ The function `message-setup' runs this hook.")
   "*Number of spaces to insert at the beginning of each cited line.
 Used by `message-yank-original' via `message-yank-cite'.")
 
-(defvar message-cite-function (car mail-citation-hook)
-  "*Function for citing an original message.")
-
 (defvar message-signature mail-signature
   "*String to be inserted at the end of the message buffer.
 If t, the `message-signature-file' file will be inserted instead.
index 7e701ae..5542804 100644 (file)
 
 (deffoo nnbabyl-open-server (server &optional defs)
   (nnoo-change-server 'nnbabyl server defs)
+  (nnbabyl-create-mbox)
   (cond 
    ((not (file-exists-p nnbabyl-mbox-file))
     (nnbabyl-close-server)
 (deffoo nnbabyl-request-list (&optional server)
   (save-excursion
     (nnmail-find-file nnbabyl-active-file)
-    (setq nnbabyl-group-alist (nnmail-get-active))))
+    (setq nnbabyl-group-alist (nnmail-get-active))
+    t))
 
 (deffoo nnbabyl-request-newgroups (date &optional server)
   (nnbabyl-request-list server))
            nnbabyl-group-alist))
     (cdr active)))
 
-(defun nnbabyl-read-mbox ()
-  (nnmail-activate 'nnbabyl)
+(defun nnbabyl-create-mbox ()
   (unless (file-exists-p nnbabyl-mbox-file)
     ;; Create a new, empty RMAIL mbox file.
     (save-excursion
       (setq buffer-file-name nnbabyl-mbox-file)
       (insert "BABYL OPTIONS:\n\n\^_")
       (nnmail-write-region
-       (point-min) (point-max) nnbabyl-mbox-file t 'nomesg)))
+       (point-min) (point-max) nnbabyl-mbox-file t 'nomesg))))
+
+(defun nnbabyl-read-mbox ()
+  (nnmail-activate 'nnbabyl)
+  (nnbabyl-create-mbox)
 
   (if (and nnbabyl-mbox-buffer
           (buffer-name nnbabyl-mbox-buffer)
index 9c8470e..c95e2d1 100644 (file)
@@ -287,7 +287,8 @@ time saver for large mailboxes.")
   (nnfolder-possibly-change-group nil server)
   (save-excursion
     (nnmail-find-file nnfolder-active-file)
-    (setq nnfolder-group-alist (nnmail-get-active))))
+    (setq nnfolder-group-alist (nnmail-get-active))
+    t))
 
 (deffoo nnfolder-request-newgroups (date &optional server)
   (nnfolder-possibly-change-group nil server)
index 5d9a60e..b44c247 100644 (file)
@@ -518,7 +518,6 @@ If FILE is t, return the buffer contents as a string."
             (kill-buffer ,temp-buffer)))))))
 
 (put 'nnheader-temp-write 'lisp-indent-function 1)
-(put 'nnheader-temp-write 'lisp-indent-hook 1)
 (put 'nnheader-temp-write 'edebug-form-spec '(form body))
 
 (defvar jka-compr-compression-info-list)
index 5f578dd..6eb6442 100644 (file)
@@ -395,7 +395,8 @@ parameter.  It should return nil, `warn' or `delete'.")
       ;; If getting from mail spool directory,
       ;; use movemail to move rather than just renaming,
       ;; so as to interlock with the mailer.
-      (unless (setq popmail (string-match "^po:" (file-name-nondirectory inbox)))
+      (unless (setq popmail (string-match
+                            "^po:" (file-name-nondirectory inbox)))
        (setq movemail t))
       (when popmail 
        (setq inbox (file-name-nondirectory inbox)))
@@ -409,7 +410,8 @@ parameter.  It should return nil, `warn' or `delete'.")
        (if popmail
            (progn
              (setq nnmail-internal-password nnmail-pop-password)
-             (when (and nnmail-pop-password-required (not nnmail-pop-password))
+             (when (and nnmail-pop-password-required
+                        (not nnmail-pop-password))
                (setq nnmail-internal-password
                      (nnmail-read-passwd
                       (format "Password for %s: "
@@ -458,7 +460,8 @@ parameter.  It should return nil, `warn' or `delete'.")
                     'call-process
                     (append
                      (list
-                      (expand-file-name nnmail-movemail-program exec-directory)
+                      (expand-file-name nnmail-movemail-program
+                                        exec-directory)
                       nil errors nil inbox tofile)
                      (when nnmail-internal-password
                        (list nnmail-internal-password))))))
@@ -1051,32 +1054,41 @@ See the documentation for the variable `nnmail-split-fancy' for documentation."
 ;; already activated.
 (defun nnmail-activate (backend &optional force)
   (let (file timestamp file-time)
-    (when (or (not (symbol-value (intern (format "%s-group-alist" backend))))
-             force
-             (and (setq file (condition-case ()
-                                 (symbol-value (intern (format "%s-active-file" 
-                                                               backend)))
-                               (error nil)))
-                  (setq file-time (nth 5 (file-attributes file)))
-                  (or (not
-                       (setq timestamp
-                             (condition-case ()
-                                 (symbol-value (intern
-                                                (format "%s-active-timestamp" 
-                                                        backend)))
-                               (error 'none))))
-                      (not (consp timestamp))
-                      (equal timestamp '(0 0))
-                      (> (nth 0 file-time) (nth 0 timestamp))
-                      (and (= (nth 0 file-time) (nth 0 timestamp))
-                           (> (nth 1 file-time) (nth 1 timestamp))))))
-      (save-excursion
-       (or (eq timestamp 'none)
-           (set (intern (format "%s-active-timestamp" backend))
-                (current-time)))
-       (funcall (intern (format "%s-request-list" backend)))
-       (set (intern (format "%s-group-alist" backend))
-            (nnmail-get-active))))
+    (if (or (not (symbol-value (intern (format "%s-group-alist" backend))))
+           force
+           (and (setq file (condition-case ()
+                               (symbol-value (intern (format "%s-active-file" 
+                                                             backend)))
+                             (error nil)))
+                (setq file-time (nth 5 (file-attributes file)))
+                (or (not
+                     (setq timestamp
+                           (condition-case ()
+                               (symbol-value (intern
+                                              (format "%s-active-timestamp" 
+                                                      backend)))
+                             (error 'none))))
+                    (not (consp timestamp))
+                    (equal timestamp '(0 0))
+                    (> (nth 0 file-time) (nth 0 timestamp))
+                    (and (= (nth 0 file-time) (nth 0 timestamp))
+                         (> (nth 1 file-time) (nth 1 timestamp))))))
+       (save-excursion
+         (or (eq timestamp 'none)
+             (set (intern (format "%s-active-timestamp" backend)) 
+;;; dmoore@ucsd.edu 25.10.96
+;;; it's not always the case that current-time
+;;; does correspond to changes in the file's time.  So just compare
+;;; the file's new time against its own previous time.
+;;;               (current-time)
+                  file-time
+                  ))
+         (funcall (intern (format "%s-request-list" backend)))
+;;; dmoore@ucsd.edu 25.10.96
+;;; BACKEND-request-list already does this itself!
+;;;      (set (intern (format "%s-group-alist" backend)) 
+;;;           (nnmail-get-active))
+         ))
     t))
 
 (defun nnmail-message-id ()
index bb28d0e..2c21879 100644 (file)
 
 (deffoo nnmbox-open-server (server &optional defs)
   (nnoo-change-server 'nnmbox server defs)
+  (nnmbox-create-mbox)
   (cond 
    ((not (file-exists-p nnmbox-mbox-file))
     (nnmbox-close-server)
 (deffoo nnmbox-request-list (&optional server)
   (save-excursion
     (nnmail-find-file nnmbox-active-file)
-    (setq nnmbox-group-alist (nnmail-get-active))))
+    (setq nnmbox-group-alist (nnmail-get-active))
+    t))
 
 (deffoo nnmbox-request-newgroups (date &optional server)
   (nnmbox-request-list server))
            nnmbox-group-alist))
     (cdr active)))
 
+(defun nnmbox-create-mbox ()
+  (when (not (file-exists-p nnmbox-mbox-file))
+    (nnmail-write-region 1 1 nnmbox-mbox-file t 'nomesg)))
+
 (defun nnmbox-read-mbox ()
   (nnmail-activate 'nnmbox)
-  (when (not (file-exists-p nnmbox-mbox-file))
-    (nnmail-write-region 1 1 nnmbox-mbox-file t 'nomesg))
+  (nnmbox-create-mbox)
   (if (and nnmbox-mbox-buffer
           (buffer-name nnmbox-mbox-buffer)
           (save-excursion
index 3de647f..dfe6833 100644 (file)
                       (string-to-int f))
                     (directory-files
                      (nnmail-group-pathname group nnmh-directory)
-                     nil "^[0-9]+$")
-                    '>))))
+                     nil "^[0-9]+$"))
+                    '>)))
        (when files
          (setcdr active (car files)))))
     (setcdr active (1+ (cdr active)))
index 1d7846a..f116fab 100644 (file)
@@ -144,7 +144,7 @@ all.  This may very well take some time.")
   (when (not (file-exists-p nnml-directory))
     (condition-case ()
        (make-directory nnml-directory t)
-      (error t)))
+      (error)))
   (cond 
    ((not (file-exists-p nnml-directory))
     (nnml-close-server)
@@ -235,7 +235,8 @@ all.  This may very well take some time.")
 (deffoo nnml-request-list (&optional server)
   (save-excursion
     (nnmail-find-file nnml-active-file)
-    (setq nnml-group-alist (nnmail-get-active))))
+    (setq nnml-group-alist (nnmail-get-active))
+    t))
 
 (deffoo nnml-request-newgroups (date &optional server)
   (nnml-request-list server))
index 9412ba0..a0f5087 100644 (file)
@@ -39,7 +39,6 @@
          `(defvar ,var ,init))
      (nnoo-define ',var ',map)))
 (put 'defvoo 'lisp-indent-function 2)
-(put 'defvoo 'lisp-indent-hook 2)
 (put 'defvoo 'edebug-form-spec '(var init &optional doc &rest map))
 
 (defmacro deffoo (func args &rest forms)
@@ -48,7 +47,6 @@
        (defun ,func ,args ,@forms)
      (nnoo-register-function ',func)))
 (put 'deffoo 'lisp-indent-function 2)
-(put 'deffoo 'lisp-indent-hook 2)
 (put 'deffoo 'edebug-form-spec '(&define name lambda-list def-body))
 
 (defun nnoo-register-function (func)
@@ -65,7 +63,6 @@
                 nil nil)
           nnoo-definition-alist)))
 (put 'nnoo-declare 'lisp-indent-function 1)
-(put 'nnoo-declare 'lisp-indent-hook 1)
 
 (defun nnoo-parents (backend)
   (nth 1 (assoc backend nnoo-definition-alist)))
@@ -79,7 +76,6 @@
 (defmacro nnoo-import (backend &rest imports)
   `(nnoo-import-1 ',backend ',imports))
 (put 'nnoo-import 'lisp-indent-function 1)
-(put 'nnoo-import 'lisp-indent-hook 1)
 
 (defun nnoo-import-1 (backend imports)
   (let ((call-function
 (defmacro nnoo-map-functions (backend &rest maps)
   `(nnoo-map-functions-1 ',backend ',maps))
 (put 'nnoo-map-functions 'lisp-indent-function 1)
-(put 'nnoo-map-functions 'lisp-indent-hook 1)
 
 (defun nnoo-map-functions-1 (backend maps)
   (let (m margs i)
index f9c935e..83dd12a 100644 (file)
@@ -386,42 +386,43 @@ The SOUP packet file name will be inserted at the %s.")
     prefix))
 
 (defun nnsoup-read-areas ()
-  (save-excursion
-    (set-buffer nntp-server-buffer)
-    (let ((areas (gnus-soup-parse-areas (concat nnsoup-tmp-directory "AREAS")))
-         entry number area lnum cur-prefix file)
-      ;; Go through all areas in the new AREAS file.
-      (while (setq area (pop areas))
-       ;; Change the name to the permanent name and move the files.
-       (setq cur-prefix (nnsoup-next-prefix))
-       (message "Incorporating file %s..." cur-prefix)
-       (when (file-exists-p 
-              (setq file (concat nnsoup-tmp-directory
-                                 (gnus-soup-area-prefix area) ".IDX")))
-         (rename-file file (nnsoup-file cur-prefix)))
-       (when (file-exists-p 
-              (setq file (concat nnsoup-tmp-directory 
-                                 (gnus-soup-area-prefix area) ".MSG")))
-         (rename-file file (nnsoup-file cur-prefix t))
-         (gnus-soup-set-area-prefix area cur-prefix)
-         ;; Find the number of new articles in this area.
-         (setq number (nnsoup-number-of-articles area))
-         (if (not (setq entry (assoc (gnus-soup-area-name area)
-                                     nnsoup-group-alist)))
-             ;; If this is a new area (group), we just add this info to
-             ;; the group alist. 
-             (push (list (gnus-soup-area-name area)
-                         (cons 1 number)
-                         (list (cons 1 number) area))
-                   nnsoup-group-alist)
-           ;; There are already articles in this group, so we add this
-           ;; info to the end of the entry.
-           (nconc entry (list (list (cons (1+ (setq lnum (cdadr entry)))
-                                          (+ lnum number))
-                                    area)))
-           (setcdr (cadr entry) (+ lnum number))))))
-    (nnsoup-write-active-file t)
-    (delete-file (concat nnsoup-tmp-directory "AREAS"))))
+  (when (file-exists-p (concat nnsoup-tmp-directory "AREAS"))
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      (let ((areas (gnus-soup-parse-areas (concat nnsoup-tmp-directory "AREAS")))
+           entry number area lnum cur-prefix file)
+       ;; Go through all areas in the new AREAS file.
+       (while (setq area (pop areas))
+         ;; Change the name to the permanent name and move the files.
+         (setq cur-prefix (nnsoup-next-prefix))
+         (message "Incorporating file %s..." cur-prefix)
+         (when (file-exists-p 
+                (setq file (concat nnsoup-tmp-directory
+                                   (gnus-soup-area-prefix area) ".IDX")))
+           (rename-file file (nnsoup-file cur-prefix)))
+         (when (file-exists-p 
+                (setq file (concat nnsoup-tmp-directory 
+                                   (gnus-soup-area-prefix area) ".MSG")))
+           (rename-file file (nnsoup-file cur-prefix t))
+           (gnus-soup-set-area-prefix area cur-prefix)
+           ;; Find the number of new articles in this area.
+           (setq number (nnsoup-number-of-articles area))
+           (if (not (setq entry (assoc (gnus-soup-area-name area)
+                                       nnsoup-group-alist)))
+               ;; If this is a new area (group), we just add this info to
+               ;; the group alist. 
+               (push (list (gnus-soup-area-name area)
+                           (cons 1 number)
+                           (list (cons 1 number) area))
+                     nnsoup-group-alist)
+             ;; There are already articles in this group, so we add this
+             ;; info to the end of the entry.
+             (nconc entry (list (list (cons (1+ (setq lnum (cdadr entry)))
+                                            (+ lnum number))
+                                      area)))
+             (setcdr (cadr entry) (+ lnum number))))))
+      (nnsoup-write-active-file t)
+      (delete-file (concat nnsoup-tmp-directory "AREAS")))))
 
 (defun nnsoup-number-of-articles (area)
   (save-excursion
@@ -552,12 +553,17 @@ The SOUP packet file name will be inserted at the %s.")
 (defun nnsoup-pack-replies ()
   "Make an outbound package of SOUP replies."
   (interactive)
+  (unless (file-exists-p nnsoup-replies-directory)
+    (message "No such directory: %s" nnsoup-replies-directory))
   ;; Write all data buffers.
   (gnus-soup-save-areas)
   ;; Write the active file.
   (nnsoup-write-active-file)
   ;; Write the REPLIES file.
   (nnsoup-write-replies)
+  ;; Check whether there is anything here.
+  (when (null (directory-files nnsoup-replies-directory nil "\\.MSG$"))
+    (error "No files to pack."))
   ;; Pack all these files into a SOUP packet.
   (gnus-soup-pack nnsoup-replies-directory nnsoup-packer))
 
index 05d6b41..8c99fe8 100644 (file)
@@ -596,6 +596,7 @@ It will prompt for a password."
   ;; Wait for the status string to arrive.
   (setq nntp-server-type (buffer-string))
   (let ((alist nntp-server-action-alist)
+       (case-fold-search t)
        entry)
     ;; Run server-specific commands.
     (while alist
@@ -638,7 +639,8 @@ It will prompt for a password."
                (nntp-inside-change-function t))
            (setq nntp-process-callback nil)
            (save-excursion
-             (funcall callback t))))))))
+             (funcall callback (buffer-name
+                                (get-buffer nntp-process-to-buffer))))))))))
 
 (defun nntp-retrieve-data (command address port buffer
                                   &optional wait-for callback decode)
@@ -741,16 +743,19 @@ It will prompt for a password."
 (defun nntp-decode-text (&optional cr-only)
   "Decode the text in the current buffer."
   (goto-char (point-min))
-  (current-buffer)
+  ;; Remove \R's.
   (while (search-forward "\r" nil t)
     (delete-char -1))
   (unless cr-only
+    ;; Remove trailing ".\n" end-of-transfer marker.
     (goto-char (point-max))
     (forward-line -1)
     (when (looking-at ".\n")
       (delete-char 2))
+    ;; Delete status line.
     (goto-char (point-min))
     (delete-region (point) (progn (forward-line 1) (point)))
+    ;; Remove "." -> ".." encoding.
     (while (search-forward "\n.." nil t)
       (delete-char -1))))
 
index dd1ae72..f779619 100644 (file)
@@ -33,6 +33,9 @@
 (require 'gnus-util)
 (require 'w3)
 (require 'url)
+(condition-case ()
+    (require 'w3-forms)
+  (error))
 
 (nnoo-declare nnweb)
 
index 6d3d344..5f9da01 100644 (file)
@@ -4,7 +4,7 @@
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: extensions
-;; Version: 0.993
+;; Version: 0.995
 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
 
 ;;; Commentary:
     (require 'custom)
   (error nil))
 
-(eval-and-compile
-  (unless (and (featurep 'custom) (fboundp 'custom-declare-variable))
-    ;; We have the old custom-library, hack around it!
-    (defmacro defgroup (&rest args) nil)
-    (defmacro defcustom (&rest args) nil)
-    (defmacro defface (&rest args) nil)
-    (when (fboundp 'copy-face)
-      (copy-face 'default 'widget-documentation-face)
-      (copy-face 'bold 'widget-button-face)
-      (copy-face 'italic 'widget-field-face))
-    (defvar widget-mouse-face 'highlight)
-    (defvar widget-menu-max-size 40)))
+(unless (and (featurep 'custom) (fboundp 'custom-declare-variable))
+  ;; We have the old custom-library, hack around it!
+  (defmacro defgroup (&rest args) nil)
+  (defmacro defcustom (&rest args) nil)
+  (defmacro defface (&rest args) nil)
+  (when (fboundp 'copy-face)
+    (copy-face 'default 'widget-documentation-face)
+    (copy-face 'bold 'widget-button-face)
+    (copy-face 'italic 'widget-field-face))
+  (defvar widget-mouse-face 'highlight)
+  (defvar widget-menu-max-size 40))
 
 ;;; Compatibility.
 
@@ -214,6 +213,8 @@ minibuffer."
   (let ((face (widget-apply widget :button-face-get)))
     (add-text-properties from to (list 'button widget
                                       'mouse-face widget-mouse-face
+                                      'start-open t
+                                      'end-open t
                                       'face face))))
 
 (defun widget-specify-doc (widget from to)
@@ -1774,7 +1775,7 @@ It will read a directory name from the minibuffer when activated."
                           (intern value)
                         value)))
 
-(define-widget 'function 'symbol
+(define-widget 'function 'sexp
   ;; Should complete on functions.
   "A lisp function."
   :tag "Function")
@@ -1864,10 +1865,6 @@ It will read a directory name from the minibuffer when activated."
                         value))
   :match (lambda (widget value) (numberp value)))
 
-(define-widget 'hook 'sexp 
-  "A emacs lisp hook"
-  :tag "Hook")
-
 (define-widget 'list 'group
   "A lisp list."
   :tag "List"
index 71f198d..69237ab 100644 (file)
@@ -4,7 +4,7 @@
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Keywords: help, extensions, faces, hypermedia
-;; Version: 0.993
+;; Version: 0.995
 ;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
 
 ;;; Commentary:
index f392683..7985962 100644 (file)
@@ -1,3 +1,29 @@
+Mon Oct 28 15:50:08 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.texi (Startup Variables): Addition.
+
+Fri Oct 25 09:04:59 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.texi (Summary Mail Commands): Addition.
+
+Wed Oct 23 08:28:29 1996  Hrvoje Niksic  <hniksic@srce.hr>
+
+       * gnus.texi (Fancy Mail Splitting): Removed trailing garbage. 
+
+Tue Oct 22 07:36:02 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.texi (Converting Kill Files): New.
+
+Sat Oct 19 07:17:28 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.texi (Saving Articles): Addition.
+
+       * message.texi (Various Message Variables): Addition.
+
+Thu Oct 17 06:53:04 1996  Lars Magne Ingebrigtsen  <lars@eyesore.no>
+
+       * gnus.texi (Contributors): Added names.
+
 Fri Oct 11 12:38:59 1996  Lars Magne Ingebrigtsen  <larsi@ylfing.ifi.uio.no>
 
        * gnus.texi (Adaptive Scoring): Addition.
index 869e34f..b3d1d9a 100644 (file)
@@ -1,7 +1,7 @@
 \input texinfo.tex
 
 @c %**start of header
-@setfilename custom.info
+@setfilename custom
 @settitle The Customization Library
 @iftex
 @afourpaper
@@ -9,11 +9,22 @@
 @end iftex
 @c %**end of header
 
+@menu
+* Introduction::                
+* User Commands::               
+* The Customization Buffer::    
+* Declaring Groups::            
+* Declaring Variables::         
+* Declaring Faces::             
+* The Init File::               
+* Wishlist::                    
+@end menu
+
 @node Top, Introduction, (dir), (dir)
 @comment  node-name,  next,  previous,  up
 @top The Customization Library
 
-Version: 0.9
+Version: 0.995
 
 @menu
 * Introduction::                
@@ -72,77 +83,332 @@ the @code{emacs} group.
 Create a customization buffer containing a single variable.  
 
 @item customize-face
-Create a customization buffer contaning a single face.
+Create a customization buffer containing a single face.
 
 @item customize-apropos
 Create a customization buffer containing all variables, faces, and
 groups that match a user specified regular expression.
 @end table
 
-@node  The Customization Buffer, Declaring Groups, User Commands, Top
+@node The Customization Buffer, Declaring Groups, User Commands, Top
 @comment  node-name,  next,  previous,  up
 @section The Customization Buffer.
 
-Here should be a description of how to use a customization buffer. 
-For now, try to press @kbd{C-h m} in the buffer, or read @ref{User
-Interface,,widget,The Widget Library}. 
+The customization buffer allows the user to make temporary or permanent
+changes to how specific aspects of emacs works, by setting and editing
+user options.  
 
-The interface will change, as it currently stinks.  Here is some hints
-about how to use it though:
+The customization buffer contains three types of text:
 
-@itemize @bullet
-@item
-Groups and user option start on a new line, and look like this
-@t{@b{name}:}.  If you move point above to the @t{@b{name}} and press
-@kbd{@key{RET}}, or move the mouse pointer above it and press
-@kbd{mouse-2}, you will be presented with a menu.  I call this the
-@dfn{tag menu} below. 
+@table @dfn
+@item informative text
+where the normal editing commands are disabled.
+
+@item editable fields
+where you can edit with the usual emacs commands.  Editable fields are
+usually displayed with a grey background if your terminal supports
+colors, or an italic font otherwise.
+
+@item buttons
+which can be activated by either pressing the @kbd{@key{ret}} while
+point is located on the text, or pushing @kbd{mouse-2} while the mouse
+pointer is above the tex.  Buttons are usually displayed in a bold
+font. 
+@end table
 
-@item
-For groups and faces, you need to activate @samp{Toggle Hide} from the
-tag menu to be able to see the content.
+You can move to the next the next editable field or button by pressing
+@kbd{@key{tab}} or the previous with @kbd{M-@key{tab}}.  Some buttons
+have a small helpful message about their purpose, which will be
+displayed when you move to it with the @key{tab} key.  
 
-@item
-After editing a variable or face, you must activate @samp{Apply} for the
-setting to take effect, and @samp{Set Default} for marking the widget
-value as the new default value.
+The buffer is divided into three part, an introductory text, a list of
+customization options, and a line of customization buttons.  Each part
+will be described in the following. 
 
-@item
-After setting new default values with @samp{Set Default}, you must
-activate the @samp{Save} button in the bottom of the screen to save the
-new defaults.  Otherwise the new defaults will be silently forgotten.
+@menu
+* The Introductory Text::       
+* The Customization Options::   
+* The Variable Options::        
+* The Face Options::            
+* The Group Options::           
+* The State Button::            
+* The Customization Buttons::   
+@end menu
 
-@item
-Pushing @samp{Save} is a no-op unless you have activated @samp{Set Default}
-for some user option.
+@node  The Introductory Text, The Customization Options, The Customization Buffer, The Customization Buffer
+@comment  node-name,  next,  previous,  up
+@subsection  The Introductory Text
 
-@item
-The @code{face} widget never attempts to display the current value of a
-face.  Instead it allows you to specify how the face should be
-initialized.  This is done with a list of @dfn{display} and
-@dfn{attributes} pairs, where the first display that matches a frame
-specify the attributes to use for that frame.
-
-A display can either match all frames, or only frames with a given
-@dfn{type}, @dfn{class}, and @dfn{background}.  The checkbox before each
-of these display parameters determine whether the parameter will be
-checked.  If the checkbox before @samp{Type} is unchecked, the display
-will match all types of frames.  If it is checked, it will match the
-type of frames specified on the rest of the line.
-
-The attributes are specified next.  Each attribute line begins with a
-checkbox, if that checkbox is unchecked the face will not affect that
-particular attribute on the screen, otherwise the face will force the
-the text to have the value for attribute specified after the attrbute
-name.  This means that an attribute like @samp{bold} in effect have
-three states: If the first checkmark is unchecked, the face will not
-affect the boldness of the text.  If the first checkmark is checked, but
-the second is unchecked, the text will be forced to be unbold.  If both
-checkmarks are checked, the text will be forced to be bold.
-
-Think about this, and mail me a suggestion for how to make the face
-widget more intuitive. 
-@end itemize
+The start of the buffer contains a short explanation of what it is, and
+how to get help.  It will typically look like this:
+
+@example
+This is a customization buffer.
+Push RET or click mouse-2 on the word _help_ for more information.
+@end example
+
+Rather boring.  It is mostly just informative text, but the word
+@samp{help} is a button that will bring up this document when
+activated.  
+
+@node  The Customization Options, The Variable Options, The Introductory Text, The Customization Buffer
+@comment  node-name,  next,  previous,  up
+@subsection The Customization Options
+
+Each customization option looks similar to the following text:
+
+@example
+ *** custom-background-mode: default 
+ [ ] [?] The brightness of the background.
+@end example
+
+The option contains the parts described below.
+
+@table @samp
+@item ***
+The Level Button.  The customization options in the buffer are organized
+in a hierarchy, which is indicated by the number of stars in the level
+button.  The top level options will be shown as @samp{*}.  When they are
+expanded, the suboptions will be shown as @samp{**}.  The example option
+is thus a subsuboption.
+
+Activating the level buttons will toggle between hiding and exposing the
+content of that option.  The content can either be the value of the
+option, as in this example, or a list of suboptions.
+
+@item custom-background-mode
+This is the tag of the the option.  The tag is a name of a variable, a
+face, or customization group.  Activating the tag has an effect that
+depends on the exact type of the option.  In this particular case,
+activating the tag will bring up a menu that will allow you to choose
+from the three possible values of the `custom-background-mode'
+variable. 
+
+@item default
+After the tag, the options value is shown.  Depending on its type, you
+may be able to edit the value directly.  If an option should contain a
+file name, it is displayed in an editable field, i.e. you can edit it
+using the standard emacs editing commands.
+
+@item [ ]
+The state button.  This look of this button will indicate the state of
+the option, e.g. whether it is currently hidden, or whether it has been
+modified or not.  Activating the button will allow you to change the
+state, e.g. apply or reset the changes you have made.  This is explained
+in detail in the following sections.
+
+@item [?] 
+The documentation button.  If the documentation is more than one line,
+this button will be present.  Activating the button will toggle whether
+the complete documentation is shown, or only the first line.
+
+@item The brightness of the background.
+This is a documentation string explaining the purpose of this particular
+customization option.
+
+@end table
+
+@node  The Variable Options, The Face Options, The Customization Options, The Customization Buffer
+@comment  node-name,  next,  previous,  up
+@subsection The Variable Options
+
+The most common customization options are emacs lisp variables.  The
+actual editing of these variables depend on what type values the
+variable is expected to contain.  For example, a lisp variable whose
+value should be a string will typically be represented with an editable
+text field in the buffer, where you can change the string directly.  If
+the value is a list, each item in the list will be presented in the
+buffer buffer on a separate line, with buttons to insert new items in
+the list, or delete existing items from the list.  You may want to see 
+@ref{User Interface,,, widget, The Widget Library}, where some examples
+of editing are discussed.  
+
+You can either choose to edit the value directly, or edit the default
+value for that variable.  The default value is a lisp expression that
+will be evaluated when you start emacs.  The result of the evaluation
+will be used as the initial value for that variable.  Editing the
+default value is for experts only, but if the current value of the
+variable is of a wrong type (i.e. a symbol where a string is expected),
+the `edit default' mode will always be selected.
+
+You can see what mode is currently selected by looking at the state
+button.  If it uses parenthesises (like @samp{( )}) it is in `Edit
+default' mode, with square brackets (like @samp{[ ]}) it is normal edit
+mode.   You can switch mode by activating the state button, and select
+either @samp{Edit} or @samp{Edit default} from the menu.
+
+You can change the state of the variable with the other menu items:
+
+@table @samp
+@item Apply
+When you have made your modifications in the buffer, you need to
+activate this item to make the modifications take effect.  The
+modifications will be forgotten next time you run emacs.
+
+@item Set Default
+Unless you activate this item instead!  This will mark the modification
+as permanent, i.e. the changes will be remembered in the next emacs
+session.
+
+@item Reset
+If you have made some modifications and not yet applied them, you can
+undo the modification by activating this item.
+
+@item Reset to Default
+Activating this item will reset the value of the variable to the last
+value you marked as permanent with `Set Default'.
+
+@item Reset to Factory Settings
+Activating this item will undo all modifications you have made, and
+reset the value to the initial value specified by the program itself. 
+@end table
+
+By default, the value of large or complicated variables are hidden.   You
+can show the value by clicking on the level button.
+
+@node  The Face Options, The Group Options, The Variable Options, The Customization Buffer
+@comment  node-name,  next,  previous,  up
+@subsection The Face Options
+
+A face is an object that controls the appearance of some buffer text.
+The face has a number of possible attributes, such as boldness,
+foreground color, and more.  For each attribute you can specify whether
+this attribute is controlled by the face, and if so, what the value is.
+For example, if the attribute bold is not controlled by a face, using
+that face on some buffer text will not affect its boldness.  If the bold
+attribute is controlled by the face, it can be turned either on or of.
+
+It is possible to specify that a face should have different attributes
+on different device types.  For example, a face may make text red on a
+color device, and bold on a monochrome device.
+
+The way this is presented in the customization buffer is to have a list
+of display specifications, and for each display specification a list of
+face attributes.  For each face attribute, there is a checkbox
+specifying whether this attribute has effect and what the value is.
+Here is an example:
+
+@example
+ *** custom-invalid-face: (sample)
+ [ ] Face used when the customize item is invalid.
+ [INS] [DEL] Display: [ ] Type: [ ] X [ ] TTY
+                      [X] Class: [X] Color [ ] Grayscale [ ] Monochrome
+                      [ ] Background: [ ] Light [ ] Dark
+             Attributes: [ ] Bold: off 
+                         [ ] Italic: off 
+                         [ ] Underline: off 
+                         [X] Foreground: yellow (sample)
+                         [X] Background: red (sample)
+                         [ ] Stipple:  
+ [INS] [DEL] Display: all
+             Attributes: [X] Bold: on 
+                         [X] Italic: on 
+                         [X] Underline: on 
+                         [ ] Foreground: default (sample)
+                         [ ] Background: default (sample)
+                         [ ] Stipple:  
+ [INS]
+@end example
+
+This has two display specifications.  The first will match all color
+displays, independently on whether the device is X11 or a tty, and
+whether background color is dark or light.  For devices matching this
+specification, @samp{custom-invalid-face} will force text to be
+displayed in yellow on red, but leave all other attributes alone.
+
+The second display will simply match everything.  Since the list is
+prioritised, this means that it will match all non-color displays.  For
+these, the face will not affect the foreground or background color, but
+force the font to be both bold, italic, and underline.
+
+You can add or delete display specifications by activating the
+@samp{[INS]} and @samp{[DEL]} buttons, and modify them by clicking on
+the check boxes.  The first checkbox in each line in the display
+specification is special.  It specify whether this particular property
+will even be relevant.  By not checking the box in the first display, we
+match all device types, also device types other than X11 and tty, for
+example ms-windows, nextstep, and mac os.
+
+After modifying the face, you can activate the state button to make the
+changes take effect.  The menu items in the state button menu is similar
+to the state menu items for variables described in the previous section.
+
+@node  The Group Options, The State Button, The Face Options, The Customization Buffer
+@comment  node-name,  next,  previous,  up
+@subsection The Group Options
+
+Since Emacs has approximately a zillion configuration options, they have
+been organized in groups.  Each group can contain other groups, thus
+creating a customization hierarchy.  The nesting of the customization
+within the visible part of this hierarchy is indicated by the number of
+stars in the level button.
+
+Since there is really no customization needed for the group itself, the
+menu items in the groups state button will affect all modified group
+members recursively.  Thus, if you activate the @samp{Apply} menu item,
+all variables and faces that have been modified and belong to that group
+will be applied.  For those members that themselves are groups, it will
+work as if you had activated the @samp{Apply} menu item on them as well.
+
+@node  The State Button, The Customization Buttons, The Group Options, The Customization Buffer
+@comment  node-name,  next,  previous,  up
+@subsection The State Button
+
+The state button has two purposes.  The first is to hold the state menu,
+as described in the previous sections.  The second is to indicate the
+state of each customization item.  This is done by the character inside
+the brackets.  The following states have been defined, the first that
+applies to the current item will be used:
+
+@table @samp
+@item -
+The option is currently hidden.  For group options that means the
+members are not shown, for variables and faces that the value is not
+shown.  You cannot perform any of the state change operations on a
+hidden customization option.
+
+@item *
+The value if this option has been modified in the buffer, but not yet
+applied.  
+
+@item +
+The current value of this option is different from the default value.   
+
+@item !
+The default value of this option is different from the factory setting.
+
+@item @@
+The factory setting of this option is not known.  This occurs when you
+try to customize variables or faces that have not been explicitly
+declared as customizable.
+
+@item SPC
+The factory setting is still in effect.
+
+@end table
+
+For non-hidden group options, the state shown is the most severe state
+of its members, where more severe means that it appears earlier in the
+list above (except hidden members, which are ignored).
+
+@node  The Customization Buttons,  , The State Button, The Customization Buffer
+@comment  node-name,  next,  previous,  up
+@subsection The Customization Buttons
+
+The last part of the customization buffer looks like this:
+
+@example
+[Apply] [Set Default] [Reset] [Save]
+@end example
+
+Activating the @samp{[Apply]}, @samp{[Set Default]}, or @samp{[Reset]}
+button will affect all modified customization items that are visible in
+the buffer.
+
+Activating the @samp{[Save]} button will ensure that all customization
+options who are marked as persistent with @samp{Set default} (either
+with the button at the end of the buffer, or with any of the state
+button menus), will actually be saved in your initialization file.
 
 @node  Declaring Groups, Declaring Variables, The Customization Buffer, Top
 @comment  node-name,  next,  previous,  up
@@ -150,18 +416,18 @@ widget more intuitive.
 
 Use @code{defgroup} to declare new customization groups. 
 
-@defun defgroup symbol members [keyword value]... doc
+@defun defgroup symbol members doc [keyword value]...
 Declare @var{symbol} as a customization group containing @var{members}. 
 @var{symbol} does not need to be quoted.
 
+@var{doc} is the group documentation.
+
 @var{members} should be an alist of the form ((@var{name}
 @var{widget})...) where @var{name} is a symbol and @var{widget} is a
 widget for editing that symbol.  Useful widgets are
 @code{custom-variable} for editing variables, @code{custom-face} for
 editing faces, and @code{custom-group} for editing groups.@refill
 
-@var{doc} is the group documentation.
-
 The following @var{keyword}'s are defined:
 
 @table @code
@@ -181,7 +447,7 @@ documentation string.
 
 Use @code{defcustom} to declare user editable variables.
 
-@defun defcustom symbol [keyword value]... doc
+@defun defcustom symbol value doc [keyword value]...
 Declare @var{symbol} as a customizable variable that defaults to @var{value}.
 Neither @var{symbol} nor @var{value} needs to be quoted.
 If @var{symbol} is not already bound, initialize it to @var{value}.
@@ -192,13 +458,16 @@ The following @var{keyword}'s are defined:
 
 @table @code
 @item :type    
-@var{value} should be a sexp widget.
+@var{value} should be a widget type.
+@item :options
+@var{value} should be a list of possible members of the specified type.
+For hooks, this is a list of function names.
 @item :group
 @var{value} should be a customization group. 
 Add @var{symbol} to that group. 
 @end table
 
-@xref{Sexp Types,,widget,The Widget Library}, for information about
+@xref{Sexp Types,,,widget,The Widget Library}, for information about
 widgets to use together with the @code{:type} keyword.
 @end defun
 
@@ -215,7 +484,7 @@ string.
 
 Faces are declared with @code{defface}.
 
-@defun defface FACE SPEC [KEYWORD VALUE]... DOC
+@defun defface face spec doc [keyword value]... 
 
 Declare @var{face} as a customizable face that defaults to @var{spec}.
 @var{face} does not need to be quoted.
@@ -287,12 +556,7 @@ specified.
 
 @itemize @bullet
 @item
-The names of the menu items for the @code{custom-variable},
-@code{custom-face}, and @code{custom-group} tags should be rethought.
-Some of the actions may be better placed as buttons in the buffer.
-
-@item
-The menu items above should be grayed out when the information is
+The menu items should be grayed out when the information is
 missing.  I.e. if a variable doesn't have a factory setting, the user
 should not be allowed to select the @samp{Factory} menu item.
 
@@ -300,17 +564,6 @@ should not be allowed to select the @samp{Factory} menu item.
 We need @strong{much} better support for keyboard operations in the
 customize buffer.
 
-@item
-There should be buttons that will apply, set, reset, etc. all the relevant
-widgets in a customize buffer.
-
-@item
-There should be a menu in the customize buffer.
-
-@item
-The group widget should allow you to apply, set, reset, etc. all the
-relevant members of the group.
-
 @item
 There should be a function to create a customize menu from a group.
 
@@ -326,28 +579,15 @@ menu.
 Support real specifiers under XEmacs.
 
 @item
-@code{customize-apropos} should only match user options that has either
-been declared with this library, or variables whose documentation start
-with @samp{*}.  With an prefix argument, also match all variables that
-has a documentation string.
-
-@item
-If there is only one line of documentation, the @samp{Documentation}
-tag-menu items should go from `first line only' to `none' without going
-over `full'.  I.e. it should have two states instead of three.
-
-@item
-@code{custom-face} should display the @code{face-documentation}
-property.
+Integrate with @file{w3} so you can customization buffers with much
+better formatting.  I'm thinking about adding a <custom>name</custom>
+tag. 
 
 @item
-@code{custom-face}, @code{custom-variable}, and @code{custom-group}
-should be derived from a common @code{custom} widget.
+Try to keep track of whether it is necessary to save or not.
 
 @item
-Integrate with @file{w3} so you can customization buffers with much
-better formatting.  I'm thinking about adding a <custom>name</custom>
-tag. 
+Offer to save if you exit emacs with unsaved customizations.
 
 @end itemize
 
index 584d261..3bd7edb 100644 (file)
@@ -1,7 +1,7 @@
 \input texinfo                  @c -*-texinfo-*-
 
 @setfilename gnus
-@settitle Red Gnus 0.52 Manual
+@settitle Red Gnus 0.53 Manual
 @synindex fn cp
 @synindex vr cp
 @synindex pg cp
@@ -287,7 +287,7 @@ into another language, under the above conditions for modified versions.
 @tex
 
 @titlepage
-@title Red Gnus 0.52 Manual
+@title Red Gnus 0.53 Manual
 
 @author by Lars Magne Ingebrigtsen
 @page
@@ -961,12 +961,23 @@ in a while from the group buffer instead (@pxref{Group Maintenance}).
 @item gnus-inhibit-startup-message
 @vindex gnus-inhibit-startup-message
 If non-@code{nil}, the startup message won't be displayed.  That way,
-your boss might not notice as easily that you are reading news instead of doing
-your job.
+your boss might not notice as easily that you are reading news instead
+of doing your job.  Note that this variable is used before
+@file{.gnus.el} is loaded, so it should be set in @code{.emacs} instead.
 
 @item gnus-no-groups-message
 @vindex gnus-no-groups-message
 Message displayed by Gnus when no groups are available.
+
+@item gnus-play-startup-jingle
+@vindex gnus-play-startup-jingle
+If non-@code{nil}, play the Gnus jingle at startup.
+
+@item gnus-startup-jingle
+@vindex gnus-startup-jingle
+Jingle to be played if the above variable is non-@code{nil}.  The
+default is @samp{Tuxedomoon.Jingle4.au}.
+
 @end table
 
 
@@ -3521,7 +3532,8 @@ command uses the process/prefix convention.
 @kindex S o m (Summary)
 @findex gnus-summary-mail-forward
 Forward the current article to some other person
-(@code{gnus-summary-mail-forward}). 
+(@code{gnus-summary-mail-forward}).  If given a prefix, include the full
+headers of the forwarded article.
 
 @item S m
 @itemx m
@@ -3623,7 +3635,8 @@ process/prefix convention.
 @kindex S o p (Summary)
 @findex gnus-summary-post-forward
 Forward the current article to a newsgroup
-(@code{gnus-summary-post-forward}).
+(@code{gnus-summary-post-forward}).  If given a prefix, include the full
+headers of the forwarded article.
 
 @item S O p
 @kindex S O p (Summary)
@@ -4938,6 +4951,12 @@ Save the current article in rmail format
 Save the current article in plain file format
 (@code{gnus-summary-save-article-file}). 
 
+@item O F
+@kindex O F (Summary)
+@findex gnus-summary-write-article-file
+Write the current article in plain file format, overwriting any previous
+file contents (@code{gnus-summary-write-article-file}). 
+
 @item O b
 @kindex O b (Summary)
 @findex gnus-summary-save-article-body-file
@@ -8577,7 +8596,7 @@ Let's look at an example value of this variable first:
       ;; People...
       (any "larsi@@ifi\\.uio\\.no" "people.Lars Magne Ingebrigtsen"))
    ;; Unmatched mail goes to the catch all group.
-   "misc.misc"))")
+   "misc.misc")
 @end lisp
 
 This variable has the format of a @dfn{split}.  A split is a (possibly)
@@ -10154,6 +10173,7 @@ silently to help keep the sizes of the score files down.
 * Reverse Scoring::          That problem child of old is not problem.
 * Global Score Files::       Earth-spanning, ear-splitting score files.
 * Kill Files::               They are still here, but they can be ignored.
+* Converting Kill Files::    Translating kill files to score files.
 * GroupLens::                Getting predictions on what you like to read.
 * Advanced Scoring::         Using logical expressions to build score rules.
 * Score Decays::             It can be useful to let scores wither away.
@@ -11356,6 +11376,26 @@ A hook called in kill-file mode buffers.
 @end table
 
 
+@node Converting Kill Files
+@section Converting Kill Files
+@cindex kill files
+@cindex converting kill files
+
+If you have loads of old kill files, you may want to convert them into
+score files.  If they are ``regular'', you can use
+the @file{gnus-kill-to-score.el} package; if not, you'll have to do it
+by hand.
+
+The kill to score conversion package isn't included in Gnus by default.
+You can fetch it from
+@file{http://www.ifi.uio.no/~larsi/ding-other/gnus-kill-to-score}.  
+
+If your old kill files are very complex---if they contain more
+non-@code{gnus-kill} forms than not, you'll have to convert them by
+hand.  Or just let them be as they are.  Gnus will still use them as
+before. 
+
+
 @node GroupLens
 @section GroupLens
 @cindex GroupLens
@@ -13166,6 +13206,13 @@ released under the name ``Gnus 5.2''.
 
 On July 28th 1996 work on Red Gnus was begun.
 
+If you happen upon a version of Gnus that has a name that is prefixed --
+``(ding) Gnus'', ``September Gnus'', ``Red Gnus'', ``Mamey Sapote Gnus''
+-- don't panic.  Don't let it know that you're frightened.  Back away.
+Slowly.  Whatever you do, don't run.  Walk away, calmly, until you're
+out of its reach.  Find a proper released version of Gnus and snuggle up
+to that instead.
+
 @menu
 * Why?::                What's the point of Gnus?
 * Compatibility::       Just how compatible is Gnus with @sc{gnus}?
@@ -13406,6 +13453,9 @@ well as numerous other things).
 @item 
 Luis Fernandes---design and graphics.
 
+@item
+Erik Naggum---help, ideas, support, code and stuff.
+
 @item 
 Wes Hardaker---@file{gnus-picon.el} and the manual section on
 @dfn{picons} (@pxref{Picons}).
@@ -13476,16 +13526,19 @@ Peter Arius,
 Marc Auslander,
 Mark Borges,
 Lance A. Brown,
+Kees de Bruin,
 Martin Buchholz,
+Kevin Buhr,
 Alastair Burt,
 Joao Cachopo,
 Massimo Campostrini,
-Michael Cook,
+Michael R. Cook,
 Glenn Coombs, 
 Frank D. Cringle, 
 Geoffrey T. Dairiki,
 Ulrik Dickow,
 Dave Disser,
+Joev Dubach,
 Paul Eggert,
 Michael Ernst,
 Luc Van Eycken,
@@ -13499,20 +13552,28 @@ Marc Horowitz,
 Ishikawa Ichiro, @c Ishikawa
 Francois Felix Ingrand,
 Lee Iverson, 
+Randell Jesup,
 Fred Johansen, 
 Thor Kristoffersen,
 Jens Lautenbacher,
+Carsten Leonhardt,
 Christian Limpach,
+Tonny Madsen,
+Shlomo Mahlab,
 Nat Makarevitch,
 Timo Metzemakers,
 Richard Mlynarik,
+David Moore,
 Lantz Moore,
 Morioka Tomohiko, @c Morioka
 Hrvoje Niksic,
 Andy Norman,
+Alexandre Oliva,
 Ken Olstad,
 Masaharu Onishi, @c Onishi
 Hideki Ono, @c Ono
+William Perry,
+Stephen Peters,
 Ulrich Pfeifer,
 Colin Rafferty,
 Bart Robinson,
@@ -13549,7 +13610,7 @@ actually are people who are using Gnus.  Who'd'a thunk it!
 @menu
 * ding Gnus::          New things in Gnus 5.0/5.1, the first new Gnus.
 * September Gnus::     The Thing Formally Known As Gnus 5.3/5.3.
-* Red Gnus::           The future.
+* Red Gnus::           The future---Gnus 5.4/5.5.
 @end menu
 
 These lists are, of course, just @emph{short} overviews of the
diff --git a/texi/message.texi b/texi/message.texi
new file mode 100644 (file)
index 0000000..efe179c
--- /dev/null
@@ -0,0 +1,1025 @@
+\input texinfo                  @c -*-texinfo-*-
+
+@setfilename message
+@settitle Message Manual
+@synindex fn cp
+@synindex vr cp
+@synindex pg cp
+@iftex
+@finalout
+@end iftex
+@setchapternewpage odd
+
+@ifinfo
+
+This file documents Messa, the Emacs message composition mode.
+
+Copyright (C) 1996 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ifinfo
+
+@tex
+
+@titlepage
+@title Message Manual
+
+@author by Lars Magne Ingebrigtsen
+@page
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1996 Free Software Foundation, Inc. 
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+
+@end titlepage
+@page
+
+@end tex
+
+@node Top
+@top Message
+
+All message composition (both mail and news) takes place in Message mode
+buffers.
+
+@menu
+* Interface::         Setting up message buffers.
+* Commands::          Commands you can execute in message mode buffers.
+* Variables::         Customizing the message buffers.
+* Index::             Variable, function and concept index.
+* Key Index::         List of Message mode keys.
+@end menu
+
+
+@node Interface
+@chapter Interface
+
+When a program (or a person) wants to respond to a message -- reply,
+follow up, forward, cancel -- the program (or person) should just put
+point in the buffer where the message is and call the required command.
+@code{Message} will then pop up a new @code{message} mode buffer with
+appropriate headers filled out, and the user can edit the message before
+sending it.
+
+@menu
+* New Mail Message::     Editing a brand new mail message.
+* New News Message::     Editing a brand new news message.
+* Reply::                Replying via mail.
+* Wide Reply::           Responding to all people via mail.
+* Followup::             Following up via news.
+* Canceling News::       Canceling a news article.
+* Superseding::          Superseding a message.
+* Forwarding::           Forwarding a message via news or mail.
+* Resending::            Resending a mail message.
+* Bouncing::             Bouncing a mail message.
+@end menu
+
+
+@node New Mail Message
+@section New Mail Message
+
+@findex message-mail
+The @code{message-mail} command pops up a new message buffer.  
+
+Two optional parameters are accepted: The first will be used as the
+@code{To} header and the second as the @code{Subject} header.  If these
+aren't present, those two headers will be empty.
+
+
+@node New News Message
+@section New News Message
+
+@findex message-news
+The @code{message-news} command pops up a new message buffer.  
+
+This function accepts two optional parameters.  The first will be used
+as the @code{Newsgroups} header and the second as the @code{Subject}
+header.  If these aren't present, those two headers will be empty.
+
+
+@node Reply
+@section Reply
+
+@findex message-reply
+The @code{message-reply} function pops up a message buffer that's a
+reply to the message in the current buffer.
+
+@vindex message-reply-to-function
+Message uses the normal methods to determine where replies are to go,
+but you can change the behavior to suit your needs by fiddling with the
+@code{message-reply-to-function} variable.
+
+If you want the replies to go to the @code{Sender} instead of the
+@code{From}, you could do something like this:
+
+@lisp
+(setq message-reply-to-function
+      (lambda ()
+       (cond ((equal (mail-fetch-field "from") "somebody")
+               (mail-fetch-field "sender"))     
+             (t 
+              nil))))
+@end lisp
+
+This function will be called narrowed to the head of the article that is
+being replied to.
+
+As you can see, this function should return a string if it has an
+opinion as to what the To header should be.  If it does not, it should
+just return @code{nil}, and the normal methods for determining the To
+header will be used.
+
+This function can also return a list.  In that case, each list element
+should be a cons, where the car should be the name of an header
+(eg. @code{Cc}) and the cdr should be the header value
+(eg. @samp{larsi@@ifi.uio.no}).  All these headers will be inserted into
+the head of the outgoing mail. 
+
+
+@node Wide Reply
+@section Wide Reply
+
+@findex message-wide-reply
+The @code{message-wide-reply} pops up a message buffer that's a wide
+reply to the message in the current buffer.  A @dfn{wide reply} is a
+reply that goes out to all people listed in the @code{To}, @code{From}
+and @code{Cc} headers.
+
+@vindex message-wide-reply-to-function
+Message uses the normal methods to determine where wide replies are to go,
+but you can change the behavior to suit your needs by fiddling with the
+@code{message-wide-reply-to-function}.  It is used in the same way as
+@code{message-reply-to-function} (@pxref{Reply}). 
+
+@findex rmail-dont-reply-to-names
+Addresses that matches the @code{rmail-dont-reply-to-names} regular
+expression will be removed from the @code{Cc} header.
+
+
+@node Followup
+@section Followup
+
+@findex message-followup
+The @code{message-followup} command pops up a message buffer that's a
+followup to the message in the current buffer.
+
+@vindex message-followup-to-function
+Message uses the normal methods to determine where followups are to go,
+but you can change the behavior to suit your needs by fiddling with the
+@code{message-followup-to-function}.  It is used in the same way as
+@code{message-reply-to-function} (@pxref{Reply}).
+
+@vindex message-use-followup-to
+The @code{message-use-followup-to} variable says what to do about
+@code{Followup-To} headers.  If it is @code{use}, always use the value.
+If it is @code{ask} (which is the default), ask whether to use the
+value.  If it is @code{t}, use the value unless it is @samp{poster}.  If
+it is @code{nil}, don't use the value.
+
+
+@node Canceling News
+@section Canceling News
+
+@findex message-cancel-news
+The @code{message-cancel-news} command cancels the article in the
+current buffer.
+
+
+@node Superseding
+@section Superseding
+
+@findex message-supersede
+The @code{message-supersede} command pops up a message buffer that will
+supersede the message in the current buffer.
+
+@vindex message-ignored-supersedes-headers
+Headers matching the @code{message-ignored-supersedes-headers} are
+removed before popping up the new message buffer.  The default is
+@samp{^Path:\\|^Date\\|^NNTP-Posting-Host:\\|^Xref:\\|^Lines:\\|^Received:\\|^X-From-Line:\\|Return-Path:}.
+
+
+
+@node Forwarding
+@section Forwarding
+
+@findex message-forward
+The @code{message-forward} command pops up a message buffer to forward
+the message in the current buffer.  If given a prefix, forward using
+news.
+
+@table @code
+@item message-forward-start-separator
+@vindex message-forward-start-separator
+Delimiter inserted before forwarded messages.  The default is
+@samp{------- Start of forwarded message -------\n}. 
+
+@vindex message-forward-end-separator
+@item message-forward-end-separator
+@vindex message-forward-end-separator
+Delimiter inserted after forwarded messages.  The default is
+@samp{------- End of forwarded message -------\n}. 
+
+@item message-signature-before-forwarded-message
+@vindex message-signature-before-forwarded-message
+If this variable is @code{t}, which it is by default, your personal
+signature will be inserted before the forwarded message.  If not, the
+forwarded message will be inserted first in the new mail.
+
+@item message-included-forward-headers
+@vindex message-included-forward-headers
+Regexp matching header lines to be included in forwarded messages.  
+
+@end table
+
+
+@node Resending
+@section Resending
+
+@findex message-resend
+The @code{message-resend} command will prompt the user for an address
+and resend the message in the current buffer to that address.
+
+@vindex message-ignored-resent-headers
+Headers the match the @code{message-ignored-resent-headers} regexp will
+be removed before sending the message.  The default is
+@samp{^Return-receipt}. 
+
+
+@node Bouncing
+@section Bouncing
+
+@findex message-bounce
+The @code{message-bounce} command will, if the current buffer contains a
+bounced mail message, pop up a message buffer stripped of the bounce
+information.  A @dfn{bounced message} is typically a mail you've sent
+out that has been returned by some @code{mailer-daemon} as
+undeliverable. 
+
+@vindex message-ignored-bounced-headers
+Headers that match the @code{message-ignored-bounced-headers} regexp
+will be removed before popping up the buffer.  The default is
+@samp{^Received:}. 
+
+
+@node Commands
+@chapter Commands
+
+@menu
+* Header Commands::     Commands for moving to headers.
+* Movement::            Moving around in message buffers.
+* Insertion::           Inserting things into message buffers.
+* Various Commands::    Various things.
+* Sending::             Actually sending the message.
+@end menu
+
+
+@node Header Commands
+@section Header Commands
+
+All these commands move to the header in question.  If it doesn't exist,
+it will be inserted.
+
+@table @kbd
+
+@item C-c ?
+@kindex C-c ?
+@findex message-goto-to
+Describe the message mode.
+
+@item C-c C-f C-t
+@kindex C-c C-f C-t 
+@findex message-goto-to
+Go to the @code{To} header (@code{message-goto-to}).
+
+@item C-c C-f C-b
+@kindex C-c C-f C-b 
+@findex message-goto-bcc
+Go to the @code{Bcc} header (@code{message-goto-bcc}).
+
+@item C-c C-f C-f
+@kindex C-c C-f C-f 
+@findex message-goto-fcc
+Go to the @code{Fcc} header (@code{message-goto-fcc}).
+
+@item C-c C-f C-c
+@kindex C-c C-f C-c 
+@findex message-goto-cc
+Go to the @code{Cc} header (@code{message-goto-cc}).
+
+@item C-c C-f C-s
+@kindex C-c C-f C-s 
+@findex message-goto-subject
+Go to the @code{Subject} header (@code{message-goto-subject}).
+
+@item C-c C-f C-r
+@kindex C-c C-f C-r 
+@findex message-goto-reply-to
+Go to the @code{Reply-To} header (@code{message-goto-reply-to}).
+
+@item C-c C-f C-n
+@kindex C-c C-f C-n 
+@findex message-goto-newsgroups
+Go to the @code{Newsgroups} header (@code{message-goto-newsgroups}).
+
+@item C-c C-f C-d
+@kindex C-c C-f C-d 
+@findex message-goto-distribution
+Go to the @code{Distribution} header (@code{message-goto-distribution}).
+
+@item C-c C-f C-o
+@kindex C-c C-f C-o 
+@findex message-goto-followup-to
+Go to the @code{Followup-To} header (@code{message-goto-followup-to}).
+
+@item C-c C-f C-k
+@kindex C-c C-f C-k 
+@findex message-goto-keywords
+Go to the @code{Keywords} header (@code{message-goto-keywords}).
+
+@item C-c C-f C-u
+@kindex C-c C-f C-u 
+@findex message-goto-summary
+Go to the @code{Summary} header (@code{message-goto-summary}).
+
+@end table
+
+
+@node Movement
+@section Movement
+
+@table @kbd
+@item C-c C-b
+@kindex C-c C-b 
+@findex message-goto-body
+Move to the beginning of the body of the message
+(@code{message-goto-body}). 
+
+@item C-c C-i
+@kindex C-c C-i 
+@findex message-goto-signature
+Move to the signature of the message (@code{message-goto-signature}).
+
+@end table
+
+
+@node Insertion
+@section Insertion
+
+@table @kbd
+
+@item C-c C-y
+@kindex C-c C-y 
+@findex message-yank-original
+Yank the message that's being replied to into the message buffer
+(@code{message-yank-original}). 
+
+@item C-c C-q
+@kindex C-c C-q 
+@findex message-fill-yanked-message
+Fill the yanked message (@code{message-fill-yanked-message}). 
+
+@item C-c C-w
+@kindex C-c C-w 
+@findex message-insert-signature
+Insert a signature at the end of the buffer
+(@code{message-insert-signature}).  
+
+@end table
+
+@table @code
+@item message-ignored-cited-headers
+@vindex message-ignored-cited-headers
+All headers that match this regexp will be removed from yanked
+messages.  The default is @samp{.}, which means that all headers will be
+removed.
+
+@item message-citation-line-function
+@vindex message-citation-line-function
+Function called to insert the citation line.  The default is
+@code{message-insert-citation-line}. 
+
+@item message-yank-prefix
+@vindex message-yank-prefix
+@cindex yanking
+@cindex quoting
+When you are replying to or following up an article, you normally want
+to quote the person you are answering.  Inserting quoted text is done by
+@dfn{yanking}, and each quoted line you yank will have
+@code{message-yank-prefix} prepended to it.  The default is @samp{> }.
+If it is @code{nil}, just indent the message.
+
+@item message-indentation-spaces
+@vindex message-indentation-spaces
+Number of spaces to indent yanked messages.
+
+@item message-cite-function
+@vindex message-cite-function
+@findex message-cite-original
+@findex sc-cite-original
+@cindex Supercite
+Function for citing an original message.  The default is
+@code{message-cite-original}.  You can also set it to
+@code{sc-cite-original} to use Supercite.
+
+@item message-indent-citation-function
+@vindex message-indent-citation-function
+Function for modifying a citation just inserted in the mail buffer.
+This can also be a list of functions.  Each function can find the
+citation between @code{(point)} and @code{(mark t)}.  And each function
+should leave point and mark around the citation text as modified.
+
+@item message-signature
+@vindex message-signature
+String to be inserted at the end of the message buffer.  If @code{t}
+(which is the default), the @code{message-signature-file} file will be
+inserted instead.  If a function, the result from the function will be
+used instead.  If a form, the result from the form will be used instead.
+If this variable is @code{nil}, no signature will be inserted at all.
+
+@item message-signature-file
+@vindex message-signature-file
+File containing the signature to be inserted at the end of the buffer.
+The default is @samp{~/.signature}.
+
+@end table
+
+Note that RFC1036 says that a signature should be preceded by the three
+characters @samp{-- } on a line by themselves.  This is to make it
+easier for the recipient to automatically recognize and process the
+signature.  So don't remove those characters, even though you might feel
+that they ruin you beautiful design, like, totally.
+
+Also note that no signature should be more than four lines long.
+Including ASCII graphics is an efficient way to get everybody to believe
+that you are silly and have nothing important to say.
+
+
+
+@node Various Commands
+@section Various Commands
+
+@table @kbd
+
+@item C-c C-r
+@kindex C-c C-r 
+@findex message-caesar-buffer-body
+Caesar rotate (aka. rot13) the current message
+(@code{message-caesar-buffer-body}).  If narrowing is in effect, just
+rotate the visible portion of the buffer.  A numerical prefix says how
+many places to rotate the text.  The default is 13.
+
+@item C-c C-t
+@kindex C-c C-t 
+@findex message-insert-to
+Insert a @code{To} header that contains the @code{Reply-To} or
+@code{From} header of the message you're following up
+(@code{message-insert-to}). 
+
+@item C-c C-n
+@kindex C-c C-n 
+@findex message-insert-newsgroups
+Insert a @code{Newsgroups} header that reflects the @code{Followup-To}
+or @code{Newsgroups} header of the article you're replying to
+(@code{message-insert-newsgroups}).
+
+@item C-c M-r
+@kindex C-c M-r
+@findex message-rename-buffer
+Rename the buffer (@code{message-rename-buffer}).  If given a prefix,
+prompt for a new buffer name.
+
+@end table
+
+
+@node Sending
+@section Sending
+
+@table @kbd
+@item C-c C-c
+@kindex C-c C-c 
+@findex message-send-and-exit
+Send the message and bury the current buffer
+(@code{message-send-and-exit}). 
+
+@item C-c C-s
+@kindex C-c C-s 
+@findex message-send
+Send the message (@code{message-send}). 
+
+@item C-c C-d
+@kindex C-c C-d
+@findex message-dont-send
+Bury the message buffer and exit (@code{message-dont-send}).
+
+@item C-c C-k
+@kindex C-c C-k
+@findex message-kill-buffer
+Kill the message buffer and exit (@code{message-kill-buffer}).
+
+@end table
+
+
+@node Variables
+@chapter Variables
+
+@menu
+* Message Headers::             General message header stuff.
+* Mail Headers::                Customizing mail headers.
+* Mail Variables::              Other mail variables.
+* News Headers::                Customizing news headers.
+* News Variables::              Other news variables.
+* Various Message Variables::   Other message variables.
+* Sending Variables::           Variables for sending.
+* Message Buffers::             How Message names its buffers.
+* Message Actions::             Actions to be performed when exiting.
+@end menu
+
+
+@node Message Headers
+@section Message Headers
+
+Message is quite aggressive on the message generation front.  It has
+to be -- it's a combined news and mail agent.  To be able to send
+combined messages, it has to generate all headers itself to ensure that
+mail and news copies of messages look sufficiently similar.
+
+@table @code
+
+@item message-generate-headers-first
+@vindex message-generate-headers-first
+If non-@code{nil}, generate all headers before starting to compose the
+message.  
+
+@item message-from-style
+@vindex message-from-style
+Specifies how @code{From} headers should look.  There are four legal
+values:
+
+@table @code
+@item nil
+Just the address -- @samp{king@@grassland.com}.
+
+@item parens
+@samp{king@@grassland.com (Elvis Parsley)}.
+
+@item angles
+@samp{Elvis Parsley <king@@grassland.com>}.
+
+@item default
+Look like @code{angles} if that doesn't require quoting, and
+@code{parens} if it does.  If even @code{parens} requires quoting, use
+@code{angles} anyway.
+
+@end table
+
+@item message-deletable-headers
+@vindex message-deletable-headers
+Headers in this list that were previously generated by Message will be
+deleted before posting.  Let's say you post an article.  Then you decide
+to post it again to some other group, you naughty boy, so you jump back
+to the @code{*post-buf*} buffer, edit the @code{Newsgroups} line, and
+ship it off again.  By default, this variable makes sure that the old
+generated @code{Message-ID} is deleted, and a new one generated.  If
+this isn't done, the entire empire would probably crumble, anarchy would
+prevail, and cats would start walking on two legs and rule the world.
+Allegedly.  
+
+@item message-default-headers
+@vindex message-default-headers
+This string is inserted at the end of the headers in all message
+buffers.
+
+@end table
+
+
+@node Mail Headers
+@section Mail Headers
+
+@table @code
+@item message-required-mail-headers
+@vindex message-required-mail-headers
+See @pxref{News Headers} for the syntax of this variable.  It is
+@code{(From Date Subject (optional . In-Reply-To) Message-ID Lines
+(optional . X-Mailer))} by default.
+
+@item message-ignored-mail-headers
+@vindex message-ignored-mail-headers
+Regexp of headers to be removed before mailing.  The default is
+@samp{^Gcc:\\|^Fcc:}. 
+
+@item message-default-mail-headers
+@vindex message-default-mail-headers
+This string is inserted at the end of the headers in all message
+buffers that are initialized as mail.
+
+@end table
+
+
+@node Mail Variables
+@section Mail Variables 
+
+@table @code
+@item message-send-mail-function
+@vindex message-send-mail-function
+Function used to send the current buffer as mail.  The default is
+@code{message-send-mail-with-sendmail}.   If you prefer using MH
+instead, set this variable to @code{message-send-mail-with-mh}.
+
+@end table
+
+
+@node News Headers
+@section News Headers
+
+@vindex message-required-news-headers
+@code{message-required-news-headers} a list of header symbols.  These
+headers will either be automatically generated, or, if that's
+impossible, they will be prompted for.  The following symbols are legal:
+
+@table @code
+
+@item From
+@cindex From
+@findex user-full-name
+@findex user-mail-address
+This required header will be filled out with the result of the
+@code{message-make-from} function, which depends on the
+@code{message-from-style}, @code{user-full-name},
+@code{user-mail-address} variables.
+
+@item Subject
+@cindex Subject
+This required header will be prompted for if not present already. 
+
+@item Newsgroups
+@cindex Newsgroups
+This required header says which newsgroups the article is to be posted
+to.  If it isn't present already, it will be prompted for.
+
+@item Organization
+@cindex organization
+This optional header will be filled out depending on the
+@code{message-user-organization} variable.
+@code{message-user-organization-file} will be used if that variable is
+@code{t}.
+
+@item Lines
+@cindex Lines
+This optional header will be computed by Message.
+
+@item Message-ID
+@cindex Message-ID
+@vindex mail-host-address
+@findex system-name
+@cindex Sun
+This required header will be generated by Message.  A unique ID will be
+created based on date, time, user name and system name.  Message will
+use @code{mail-host-address} as the fully qualified domain name (FQDN)
+of the machine if that variable is define.  If not, it will use
+@code{system-name}, which doesn't report a FQDN on some machines --
+notably Suns.
+
+@item X-Newsreader
+@cindex X-Newsreader
+This optional header will be filled out according to the
+@code{message-newsreader} local variable.
+
+@item X-Mailer
+This optional header will be filled out according to the
+@code{message-mailer} local variable, unless there already is an
+@code{X-Newsreader} header present.
+
+@item In-Reply-To
+This optional header is filled out using the @code{Date} and @code{From}
+header of the article being replied.
+
+@item Expires
+@cindex Expires
+This extremely optional header will be inserted according to the
+@code{message-expires} variable.  It is highly deprecated and shouldn't
+be used unless you know what you're doing.
+
+@item Distribution
+@cindex Distribution
+This optional header is filled out according to the
+@code{message-distribution-function} variable.  It is a deprecated and
+much misunderstood header.
+
+@item Path
+@cindex path
+This extremely optional header should probably not ever be used.
+However, some @emph{very} old servers require that this header is
+present.  @code{message-user-path} further controls how this
+@code{Path} header is to look.  If is is @code{nil}, the the server name
+as the leaf node.  If is is a string, use the string.  If it is neither
+a string nor @code{nil}, use the user name only.  However, it is highly
+unlikely that you should need to fiddle with this variable at all.
+@end table
+
+@findex yow
+@cindex Mime-Version
+In addition, you can enter conses into this list.  The car of this cons
+should be a symbol.  This symbol's name is the name of the header, and
+the cdr can either be a string to be entered verbatim as the value of
+this header, or it can be a function to be called.  This function should
+return a string to be inserted.  For instance, if you want to insert
+@code{Mime-Version: 1.0}, you should enter @code{(Mime-Version . "1.0")}
+into the list.  If you want to insert a funny quote, you could enter
+something like @code{(X-Yow . yow)} into the list.  The function
+@code{yow} will then be called without any arguments.
+
+If the list contains a cons where the car of the cons is
+@code{optional}, the cdr of this cons will only be inserted if it is
+non-@code{nil}.
+
+Other variables for customizing outgoing news articles:
+
+@table @code
+
+@item message-syntax-checks
+@vindex message-syntax-checks
+If non-@code{nil}, message will attempt to check the legality of the
+headers, as well as some other stuff, before posting.  You can control
+the granularity of the check by adding or removing elements from this
+list.  Legal elements are:
+
+@table @code
+@item subject-cmsg 
+Check the subject for commands.
+@item sender
+@cindex Sender
+Insert a new @code{Sender} header if the @code{From} header looks odd. 
+@item multiple-headers 
+Check for the existence of multiple equal headers.
+@item sendsys 
+@cindex sendsys
+Check for the existence of version and sendsys commands.
+@item message-id
+Check whether the @code{Message-ID} looks ok.
+@item from
+Check whether the @code{From} header seems nice.
+@item long-lines 
+@cindex long lines
+Check for too long lines.
+@item control-chars
+Check for illegal characters.
+@item size
+Check for excessive size.
+@item new-text
+Check whether there is any new text in the messages.
+@item signature
+Check the length of the signature.
+@item approved
+@cindex approved
+Check whether the article has an @code{Approved} header, which is
+something only moderators should include.
+@item empty
+Check whether the article is empty.
+@item empty-headers
+Check whether any of the headers are empty.
+@item existing-newsgroups
+Check whether the newsgroups mentioned in the Newsgroups and 
+Followup-To headers exist.
+@item valid-newsgroups
+Check whether the @code{Newsgroups} and @code{Followup-to} headers
+are valid syntactically.
+@item shorten-followup-to
+Check whether to add a @code{Followup-to} header to shorten the number
+of groups to post to.
+@end table
+
+All these conditions are checked by default.
+
+@item message-ignored-news-headers
+@vindex message-ignored-news-headers
+Regexp of headers to be removed before posting.  The default is
+@samp{^NNTP-Posting-Host:\\|^Xref:\\|^Bcc:\\|^Gcc:\\|^Fcc:}. 
+
+@item message-default-news-headers
+@vindex message-default-news-headers
+This string is inserted at the end of the headers in all message
+buffers that are initialized as news.
+
+@end table
+
+
+@node News Variables
+@section News Variables
+
+@table @code
+@item message-send-news-function
+@vindex message-send-news-function
+Function used to send the current buffer as news.  The default is
+@code{message-send-news}. 
+
+@item message-post-method
+@vindex message-post-method
+Method used for posting a prepared news message.
+
+@end table
+
+
+@node Various Message Variables
+@section Various Message Variables
+
+@table @code
+@item message-signature-separator
+@vindex message-signature-separator
+Regexp matching the signature separator.  It is @samp{^-- *$} by
+default. 
+
+@item mail-header-separator
+@vindex mail-header-separator
+String used to separate the headers from the body.  It is @samp{--text
+follows this line--} by default.
+
+@item message-directory
+@vindex message-directory
+Directory used by many mailey things.  The default is @file{~/Mail/}. 
+
+@item message-autosave-directory
+@vindex message-autosave-directory
+Directory where message buffers will be autosaved to.
+
+@item message-signature-setup-hook
+@vindex message-signature-setup-hook
+Hook run when initializing the message buffer.  It is run after the
+headers have been inserted but before the signature has been inserted. 
+
+@item message-setup-hook
+@vindex message-setup-hook
+Hook run as the last thing when the message buffer has been initialized.
+
+@item message-header-setup-hook
+@vindex message-header-setup-hook
+Hook called narrowed to the headers after initializing the headers. 
+
+@item message-send-hook
+@vindex message-send-hook
+Hook run before sending messages.
+
+@item message-send-mail-hook
+@vindex message-send-mail-hook
+Hook run before sending mail messages.
+
+@item message-send-news-hook
+@vindex message-send-news-hook
+Hook run before sending news messages.
+
+@item message-sent-hook
+@vindex message-sent-hook
+Hook run after sending messages.
+
+@item message-mode-syntax-table
+@vindex message-mode-syntax-table
+Syntax table used in message mode buffers.
+
+@end table
+
+
+
+@node Sending Variables
+@section Sending Variables
+
+@table @code
+
+@item message-fcc-handler-function 
+@vindex message-fcc-handler-function 
+A function called to save outgoing articles.  This function will be
+called with the name of the file to store the article in. The default
+function is @code{rmail-output} which saves in Unix mailbox format.
+
+@item message-courtesy-message
+@vindex message-courtesy-message
+When sending combined messages, this string is inserted at the start of
+the mailed copy.  If the string contains the format spec @samp{%s}, the
+newsgroups the article has been posted to will be inserted there.  If
+this variable is @code{nil}, no such courtesy message will be added.
+The default value is @samp{"The following message is a courtesy copy of
+an article\nthat has been posted to %s as well.\n\n"}. 
+
+@end table
+
+
+@node Message Buffers
+@section Message Buffers
+
+Message will generate new buffers with unique buffer names when you
+request a message buffer.  When you send the message, the buffer isn't
+normally killed off.  It's name is changed and a certain number of old
+message buffers are kept alive.
+
+@table @code
+@item message-generate-new-buffers
+@vindex message-generate-new-buffers
+If non-@code{nil}, generate new buffers.  The default is @code{t}.  If
+this is a function, call that function with three parameters: The type,
+the to address and the group name.  (Any of these may be @code{nil}.)
+The function should return the new buffer name.
+
+@item message-max-buffers
+@vindex message-max-buffers
+This variable says how many old message buffers to keep.  If there are
+more message buffers than this, the oldest buffer will be killed.  The
+default is 10.  If this variable is @code{nil}, no old message buffers
+will ever be killed.
+
+@item message-send-rename-function
+@vindex message-send-rename-function
+After sending a message, the buffer is renamed from, for instance,
+@samp{*reply to Lars*} to @samp{*sent reply to Lars*}.  If you don't
+like this, set this variable to a function that renames the buffer in a
+manner you like.  If you don't want to rename the buffer at all, you can
+say:
+
+@lisp
+(setq message-send-rename-function 'ignore)
+@end lisp
+
+@item message-kill-buffer-on-exit
+@findex message-kill-buffer-on-exit
+If non-@code{nil}, kill the buffer immediately on exit.
+
+@end table
+
+
+@node Message Actions
+@section Message Actions
+
+When Message is being used from a news/mail reader, the reader is likely
+to want to perform some task after the message has been sent.  Perhaps
+return to the previous window configuration or mark an article as
+replied.  
+
+@vindex message-kill-actions
+@vindex message-postpone-actions
+@vindex message-exit-actions
+@vindex message-send-actions
+The user may exit from the message buffer in various ways.  The most
+common is @kbd{C-c C-c}, which sends the message and exits.  Other
+possibilities are @kbd{C-c C-s} which just sends the message, @kbd{C-c
+C-d} which postpones the message editing and buries the message buffer,
+and @kbd{C-c C-k} which kills the message buffer.  Each of these actions
+have lists associated with them that contains actions to be executed:
+@code{message-send-actions}, @code{message-exit-actions},
+@code{message-postpone-actions}, and @code{message-kill-actions}.  
+
+Message provides a function to interface with these lists:
+@code{message-add-action}.  The first parameter is the action to be
+added, and the rest of the arguments are which lists to add this action
+to.  Here's an example from Gnus:
+
+@lisp
+  (message-add-action
+   `(set-window-configuration ,(current-window-configuration))
+   'exit 'postpone 'kill)
+@end lisp
+
+This restores the Gnus window configuration when the message buffer is
+killed, postponed or exited.
+
+An @dfn{action} can be either a normal function; or a list where the
+@code{car} is a function and the @code{cdr} is the list of arguments; or
+a form to be @code{eval}ed.
+
+@node Index
+@chapter Index
+@printindex cp
+
+@node Key Index
+@chapter Key Index
+@printindex ky
+
+@summarycontents
+@contents
+@bye
+
+@c End:
index 054a957..66d0272 100644 (file)
@@ -1,9 +1,9 @@
 \input texinfo.tex
 
-@c $Id: widget.texi,v 1.1 1996/09/22 12:07:55 steve Exp $
+@c $Id: widget.texi,v 1.2 1996/10/30 19:27:41 steve Exp $
 
 @c %**start of header
-@setfilename widget.info
+@setfilename widget
 @settitle The Emacs Widget Library
 @iftex
 @afourpaper
@@ -15,7 +15,7 @@
 @comment  node-name,  next,  previous,  up
 @top The Emacs Widget Library
 
-Version: 0.9
+Version: 0.995
 
 @menu
 * Introduction::                
@@ -47,21 +47,21 @@ The basic widgets are:
 @item link
 Areas of text with an associated action.  Intended for hypertext links
 embedded in text.
-@item push 
+@item push-button 
 Like link, but intended for stand-alone buttons.
-@item field
+@item editable-field
 An editable text field.  It can be either variable or fixed length.
-@item choice
+@item menu-choice
 Allows the user to choose one of multiple options from a menu, each
 option is itself a widget.  Only the selected option will be visible in
 the buffer.
-@item radio
+@item radio-button-choice
 Allows the user to choose one of multiple options by pushing radio
 buttons.  The options are implemented as widgets.  All options will be
 visible in the buffer.
 @item item
-A simple constant widget intended to be used in the @code{choice} and
-@code{radio} widgets. 
+A simple constant widget intended to be used in the @code{menu-choice} and
+@code{radio-button-choice} widgets. 
 @item choice-item
 An button item only intended for use in choices.  When pushed, the user
 will be asked to select another option from the choice widget.
@@ -69,7 +69,7 @@ will be asked to select another option from the choice widget.
 A simple @samp{on}/@samp{off} switch.
 @item checkbox
 A checkbox (@samp{[ ]}/@samp{[X]}). 
-@item repeat
+@item editable-list
 Create an editable list.  The user can insert or delete items in the
 list.  Each list item is itself a widget.
 @end table
@@ -178,7 +178,7 @@ change you make must be contained within a single editable text field.
 For example, capitalizing all text from the middle of one field to the
 middle of another field is prohibited.
 
-Editing text fields are created by the @code{field} widget.
+Editing text fields are created by the @code{editable-field} widget.
 
 The editing text fields are highlighted with the
 @code{widget-field-face} face, making them easy to find.
@@ -217,11 +217,11 @@ the example:
 @item The Option Field Tags.
 When you activate one of these buttons, you will be asked to choose
 between a number of different options.  This is how you edit an option
-field.  Option fields are created by the @code{choice} widget.  In
+field.  Option fields are created by the @code{menu-choice} widget.  In
 the example, @samp{@b{Choose}} is an option field tag.
 @item The @samp{@b{[INS]}} and @samp{@b{[DEL]}} buttons.
 Activating these will insert or delete elements from a editable list.
-The list is created by the @code{repeat} widget. 
+The list is created by the @code{editable-list} widget. 
 @item Embedded Buttons.
 The @samp{@b{_other work_}} is an example of an embedded
 button. Embedded buttons are not associated with a fields, but can serve
@@ -231,11 +231,11 @@ usually created by the @code{link} widget.
 Activating one of these will convert it to the other.  This is useful
 for implementing multiple-choice fields.  You can create it wit
 @item The @samp{@b{( )}} and @samp{@b{(*)}} buttons.
-Only one radio button in a @code{radio} widget can be selected at any
+Only one radio button in a @code{radio-button-choice} widget can be selected at any
 time.  When you push one of the unselected radio buttons, it will be
 selected and the previous selected radio button will become unselected. 
 @item The @samp{@b{[Apply Form]}} @samp{@b{[Reset Form]}} buttons.
-These are explicit buttons made with the @code{push} widget.  The main
+These are explicit buttons made with the @code{push-button} widget.  The main
 difference from the @code{link} widget is that the buttons are intended
 to be displayed more like buttons in a GUI, once Emacs grows powerful
 enough. 
@@ -277,6 +277,9 @@ Interface}).
 @lisp
 (require 'widget)
 
+(eval-when-compile
+  (require 'widget-edit))
+
 (defvar widget-example-repeat)
 
 (defun widget-example ()
@@ -288,10 +291,10 @@ Interface}).
   (let ((inhibit-read-only t))
     (erase-buffer))
   (widget-insert "Here is some documentation.\n\nName: ")
-  (widget-create 'field
+  (widget-create 'editable-field
                 :size 13
                 "My Name")
-  (widget-create 'choice
+  (widget-create 'menu-choice
                 :tag "Choose"
                 :value "This"
                 :help-echo "Choose me, please!"
@@ -300,9 +303,9 @@ Interface}).
                                    (widget-value widget)))
                 '(item :tag "This option" :value "This")
                 '(choice-item "That option")
-                '(field :menu-tag "No option" "Thus option"))
+                '(editable-field :menu-tag "No option" "Thus option"))
   (widget-insert "Address: ")
-  (widget-create 'field
+  (widget-create 'editable-field
                 "Some Place\nIn some City\nSome country.")
   (widget-insert "\nSee also ")
   (widget-create 'link
@@ -313,7 +316,7 @@ Interface}).
                 "other work")
   (widget-insert " for more information.\n\nNumbers: count to three below\n")
   (setq widget-example-repeat
-       (widget-create 'repeat
+       (widget-create 'editable-list
                       :entry-format "%i %d %v"
                       :notify (lambda (widget &rest ignore)
                                 (let ((old (widget-get widget
@@ -323,7 +326,7 @@ Interface}).
                                     (widget-put widget ':example-length new)
                                     (message "You can count to %d." new))))
                       :value '("One" "Eh, two?" "Five!")
-                      '(field :value "three")))
+                      '(editable-field :value "three")))
   (widget-insert "\n\nSelect multiple:\n\n")
   (widget-create 'checkbox t)
   (widget-insert " This\n")
@@ -333,13 +336,14 @@ Interface}).
                 :notify (lambda (&rest ignore) (message "Tickle"))
                 t)
   (widget-insert " Thus\n\nSelect one:\n\n")
-  (widget-create 'radio
+  (widget-create 'radio-button-choice
                 :value "One"
                 :notify (lambda (widget &rest ignore)
-                          (message "You selected %s" (widget-value widget)))
+                          (message "You selected %s"
+                                   (widget-value widget)))
                 '(item "One") '(item "Anthor One.") '(item "A Final One."))
   (widget-insert "\n")
-  (widget-create 'push
+  (widget-create 'push-button
                 :notify (lambda (&rest ignore) 
                           (if (= (length (widget-value widget-example-repeat))
                                  3)
@@ -347,7 +351,7 @@ Interface}).
                             (error "Three was the count!")))
                 "Apply Form")
   (widget-insert " ")
-  (widget-create 'push
+  (widget-create 'push-button
                 :notify (lambda (&rest ignore)
                           (widget-example))
                 "Reset Form")
@@ -446,6 +450,15 @@ value.  What this is depends on the widget type.
 @item %d
 Insert the string specified by @code{:doc} here.
 
+@item %h
+Like @samp{%d}, with the following modifications: If the documentation
+string is more than one line, it will add a button which will toggle
+between showing only the first line, and showing the full text.
+Furthermore, if there is no @code{:doc} property in the widget, it will
+instead examine the @code{:documentation-property} property.  If it is a
+lambda expression, it will be called with the widget's value as an
+argument, and the result will be used as the documentation text.
+
 @item %t
 Insert the string specified by @code{:tag} here, or the @code{princ}
 representation of the value if there is no tag.
@@ -469,6 +482,18 @@ string.
 Message displayed whenever you move to the widget with either
 @code{widget-forward} or @code{widget-backward}.
 
+@item :indent
+An integer indicating the absolute number of spaces to indent children
+of this widget.
+
+@item :offset
+An integer indicating how many extra spaces to add to the widget's
+grandchildren compared to this widget.
+
+@item :extra-offset
+An integer indicating how many extra spaces to add to the widget's
+children compared to this widget.
+
 @item :notify
 A function called each time the widget or a nested widget is changed.
 The function is called with two or three arguments.  The first argument
@@ -478,11 +503,11 @@ any.
 
 @item :menu-tag
 Tag used in the menu when the widget is used as an option in a
-@code{choice} widget.
+@code{menu-choice} widget.
 
 @item :menu-tag-get
 Function used for finding the tag when the widget is used as an option
-in a @code{choice} widget.  By default, the tag used will be either the
+in a @code{menu-choice} widget.  By default, the tag used will be either the
 @code{:menu-tag} or @code{:tag} property if present, or the @code{princ}
 representation of the @code{:value} property if not.
 
@@ -497,26 +522,26 @@ return the widget containing the invalid data, and set that widgets
 @code{:error} property to a string explaining the error.
 
 @item :parent
-The parent of a nested widget (e.g. a @code{choice} item or an element of a
-@code{repeat} widget). 
+The parent of a nested widget (e.g. a @code{menu-choice} item or an element of a
+@code{editable-list} widget). 
 @end table
 
 @menu
 * link::                        
-* push::                        
-* field::                       
+* push-button::                        
+* editable-field::                       
 * text::                        
-* choice::                      
-* radio::                       
+* menu-choice::                      
+* radio-button-choice::                       
 * item::                        
 * choice-item::                 
 * toggle::                      
 * checkbox::                    
 * checklist::                   
-* repeat::                      
+* editable-list::                      
 @end menu
 
-@node link, push, Basic Types, Basic Types
+@node link, push-button, Basic Types, Basic Types
 @comment  node-name,  next,  previous,  up
 @subsection The @code{link} Widget
 
@@ -530,28 +555,28 @@ The @var{value}, if present, is used to initialize the @code{:value}
 property.  The value should be a string, which will be inserted in the
 buffer. 
 
-@node  pushfield, link, Basic Types
+@node  push-button, editable-field, link, Basic Types
 @comment  node-name,  next,  previous,  up
-@subsection The @code{push} Widget
+@subsection The @code{push-button} Widget
 
 Syntax:
 
 @example
-TYPE ::= (push [KEYWORD ARGUMENT]...  [ VALUE ])
+TYPE ::= (push-button [KEYWORD ARGUMENT]...  [ VALUE ])
 @end example
 
 The @var{value}, if present, is used to initialize the @code{:value}
 property. The value should be a string, which will be inserted in the
 buffer. 
 
-@node field, text, push, Basic Types
+@node editable-field, text, push-button, Basic Types
 @comment  node-name,  next,  previous,  up
-@subsection The @code{field} Widget
+@subsection The @code{editable-field} Widget
 
 Syntax:
 
 @example
-TYPE ::= (field [KEYWORD ARGUMENT]... [ VALUE ])
+TYPE ::= (editable-field [KEYWORD ARGUMENT]... [ VALUE ])
 @end example
 
 The @var{value}, if present, is used to initialize the @code{:value}
@@ -571,26 +596,47 @@ Face used for highlighting the editable field.  Default is
 
 @item :keymap
 Keymap used in the editable field.  @code{widget-keymap} will allow you
-to use normal editing commands, even if these has been supressed in the
+to use normal editing commands, even if these has been suppressed in the
 current buffer.
 
+@item :hide-front-space
+@itemx :hide-rear-space
+In order to keep track of the editable field, emacs places an invisible
+space character in front of the field, and for fixed sized fields also
+in the rear end of the field.  For fields that extent to the end of the
+line, the terminating linefeed serves that purpose instead.  
+
+Emacs will try to make the spaces intangible when it is safe to do so.
+Intangible means that the cursor motion commands will skip over the
+character as if it didn't exist.  This is safe to do when the text
+preceding or following the widget cannot possible change during the
+lifetime of the @code{editable-field} widget.  The preferred way to tell
+Emacs this, is to add text to the @code{:format} property around the
+value.  For example @code{:format "Tag: %v "}.  
+
+You can overwrite the internal safety check by setting the
+@code{:hide-front-space} or @code{:hide-rear-space} properties to
+non-nil.  This is not recommended.  For example, @emph{all} text that
+belongs to a widget (i.e. is created from its @code{:format} string) will
+change whenever the widget changes its value.
+
 @end table
 
-@node text, choice, field, Basic Types
+@node text, menu-choice, editable-field, Basic Types
 @comment  node-name,  next,  previous,  up
 @subsection The @code{text} Widget
 
-This is just like @code{field}, but intended for multiline text
+This is just like @code{editable-field}, but intended for multiline text
 fields. 
 
-@node choice, radio, text, Basic Types
+@node menu-choice, radio-button-choice, text, Basic Types
 @comment  node-name,  next,  previous,  up
-@subsection The @code{choice} Widget
+@subsection The @code{menu-choice} Widget
 
 Syntax:
 
 @example
-TYPE ::= (choice [KEYWORD ARGUMENT]... TYPE ... )
+TYPE ::= (menu-choice [KEYWORD ARGUMENT]... TYPE ... )
 @end example
 
 The @var{type} arguments represents each possible choice.  The widgets
@@ -603,6 +649,10 @@ widget will match any value that matches at least one of the specified
 Widget type used as a fallback when the value does not match any of the
 specified @var{type} arguments.
 
+@item :case-fold
+Set this to nil if you don't want to ignore case when prompting for a
+choice through the minibuffer.
+
 @item :children
 A list whose car is the widget representing the currently chosen type in
 the buffer. 
@@ -614,14 +664,14 @@ The current chosen type
 The list of types. 
 @end table
 
-@node radio, item, choice, Basic Types
+@node radio-button-choice, item, menu-choice, Basic Types
 @comment  node-name,  next,  previous,  up
-@subsection The @code{radio} Widget
+@subsection The @code{radio-button-choice} Widget
 
 Syntax:
 
 @example
-TYPE ::= (radio [KEYWORD ARGUMENT]...  TYPE ... )
+TYPE ::= (radio-button-choice [KEYWORD ARGUMENT]...  TYPE ... )
 @end example
 
 The @var{type} arguments represents each possible choice.  The widgets
@@ -657,18 +707,20 @@ The current chosen type
 The list of types. 
 @end table
 
-You can add extra radio button items to a radio widget after it has been
-created with the function `widget-radio-add-item'.
+You can add extra radio button items to a @code{radio-button-choice}
+widget after it has been created with the function
+@code{widget-radio-add-item}. 
 
 @defun widget-radio-add-item widget type
-Add to radio widget @var{widget} a new radio button item of type @var{type}.
+Add to @code{radio-button-choice} widget @var{widget} a new radio button item of type
+@var{type}. 
 @end defun
 
-Please note that such items added after the radio widget has been
-created will @strong{not} be properly destructed when you call
-@code{widget-delete}. 
+Please note that such items added after the @code{radio-button-choice}
+widget has been created will @strong{not} be properly destructed when
+you call @code{widget-delete}.
 
-@node item, choice-item, radio, Basic Types
+@node item, choice-item, radio-button-choice, Basic Types
 @comment  node-name,  next,  previous,  up
 @subsection The @code{item} Widget
 
@@ -739,7 +791,7 @@ Syntax:
 TYPE ::= (checkbox [KEYWORD ARGUMENT]...)
 @end example
 
-@node checklist, repeat, checkbox, Basic Types
+@node checklist, editable-list, checkbox, Basic Types
 @comment  node-name,  next,  previous,  up
 @subsection The @code{checklist} Widget
 
@@ -779,14 +831,14 @@ The widgets representing each type.
 The list of types. 
 @end table
 
-@node repeat,  , checklist, Basic Types
+@node editable-list,  , checklist, Basic Types
 @comment  node-name,  next,  previous,  up
-@subsection The @code{repeat} Widget
+@subsection The @code{editable-list} Widget
 
 Syntax:
 
 @example
-TYPE ::= ([KEYWORD ARGUMENT]... TYPE)
+TYPE ::= (editable-list [KEYWORD ARGUMENT]... TYPE)
 @end example
 
 The value is a list, where each member represent one widget of type
@@ -795,10 +847,6 @@ The value is a list, where each member represent one widget of type
 The following extra properties are recognized.
 
 @table @code
-@item :indent
-Number of spaces inserted before each member of the list, except for the
-first. 
-
 @item :entry-format
 This string will be inserted for each entry in the list.
 The following @samp{%} escapes are available:
@@ -867,7 +915,7 @@ This will allow you to edit any valid s-expression in an editable buffer
 field. 
 
 The @code{sexp} widget takes the same keyword arguments as the
-@code{field} widget.
+@code{editable-field} widget.
 @end deffn
 
 @node atoms, composite, generic, Sexp Types
@@ -888,7 +936,7 @@ The @var{value}, if present, is used to initialize the @code{:value}
 property and must be an expression of the same type as the widget.
 I.e. the string widget can only be initialized with a string.
 
-All the atom widgets take the same keyword arguments as the @code{field}
+All the atom widgets take the same keyword arguments as the @code{editable-field}
 widget.
 
 @deffn Widget string
@@ -925,6 +973,12 @@ Allows you to edit an integer in an editable field.
 Allows you to edit a number in an editable field.
 @end deffn
 
+@deffn Widget boolean
+Allows you to edit a boolean.  In lisp this means a variable which is
+either nil meaning false, or non-nil meaning true.
+@end deffn
+
+
 @node composite,  , atoms, Sexp Types
 @comment  node-name,  next,  previous,  up
 @subsection Composite Sexp Widgets.
@@ -941,28 +995,28 @@ will be displayed in the buffer, and be editable to the user.
 @deffn Widget cons
 The value of a @code{cons} widget is a cons-cell where the car is the
 value of the first component and the cdr is the value of the second
-coponent.  There must be exactly two components. 
+component.  There must be exactly two components. 
 @end deffn
 
 @deffn Widget lisp
-The value of a @code{cons} widget is a list containing the value of
+The value of a @code{lisp} widget is a list containing the value of
 each of its component.
 @end deffn
 
 @deffn Widget vector
-The value of a @code{cons} widget is a vector containing the value of
+The value of a @code{vector} widget is a vector containing the value of
 each of its component.
 @end deffn
 
 The above suffice for specifying fixed size lists and vectors.  To get
 variable length lists and vectors, you can use a @code{choice},
-@code{radio}, @code{checklist} or @code{repeat} widget together with the
-@code{:inline} keyword.  If any component of a composite widget has the
-@code{:inline} keyword set, its value must be a list which will then be
-spliced into the composite.  For example, to specify a list whose first
-element must be a file name, and whose remaining arguments should either
-by the symbol @code{t} or two files, you can use the following widget
-specification: 
+@code{set} or @code{repeat} widgets together with the @code{:inline}
+keywords.  If any component of a composite widget has the @code{:inline}
+keyword set, its value must be a list which will then be spliced into
+the composite.  For example, to specify a list whose first element must
+be a file name, and whose remaining arguments should either by the
+symbol @code{t} or two files, you can use the following widget
+specification:
 
 @example
 (list file
@@ -979,6 +1033,25 @@ This concept of inline is probably hard to understand.  It was certainly
 hard to implement so instead of confuse you more by trying to explain it
 here, I'll just suggest you meditate over it for a while.
 
+@deffn Widget choice
+Allows you to edit a sexp which may have one of fixed set of types.  It
+is currently implemented with the @code{choice-menu} basic widget, and
+has a similar syntax.
+@end deffn
+
+@deffn Widget set
+Allows you to specify a type which must be a list whose elements all
+belong to given set.  The elements of the list is not significant.  This
+is implemented on top of the @code{checklist} basic widget, and has a
+similar syntax. 
+@end deffn
+
+@deffn Widget repeat
+Allows you to specify a variable length list whose members are all of
+the same type.  Implemented on top of the `editable-list' basic widget,
+and has a similar syntax.
+@end deffn
+
 @node Widget Properties, Defining New Widgets, Sexp Types, Top
 @comment  node-name,  next,  previous,  up
 @section Properties
@@ -1111,6 +1184,10 @@ if such has been used.
 Function to handle unknown @samp{%} escapes in the format string.  It
 will be called with the widget and the escape character as arguments.
 You can set this to allow your widget to handle non-standard escapes.
+
+You should end up calling @code{widget-default-format-handler} to handle
+unknown escape sequences, which will handle the @samp{%h} and any future
+escape sequences, as well as give an error for unknown escapes.
 @end table
 
 If you want to define a new widget from scratch, use the @code{default}
@@ -1119,7 +1196,7 @@ widget as its base.
 @deffn Widget default [ keyword argument ]
 Widget used as a base for other widgets. 
 
-It provides most of the functionality that is refered to as ``by
+It provides most of the functionality that is referred to as ``by
 default'' in this text. 
 @end deffn
 
@@ -1157,24 +1234,16 @@ Use graphical versions of the widgets for emacsen that can do that.
 I.e. real radio buttons and checkmarks instead of their @sc{ascii}
 equivalents. 
 
-@item
-There should be a way to probe a widget to see if the user has modified
-it. 
-
-@item 
-The support for indentation of component widgets should be finished. 
-
 @item
 There should be support for browsing the widget documentation.
 
 @item
 There should be a way to specify that @key{RET} in a field will call the
 @code{:activate} function.  This should be used by widgets such as
-@code{file} and @code{symbol} prompt with completion.  This way, we
-could also get rid of the default tag for the @code{file} widget.
+@code{file} and @code{symbol} prompt with completion. 
 
 @item
-The @code{choice} tag should be prettier, something like the abbreviated
+The @code{menu-choice} tag should be prettier, something like the abbreviated
 menus in Open Look.
 
 @item
@@ -1183,11 +1252,11 @@ The functions used in many widgets, like
 specific to the first widget where I used them.
 
 @item 
-Unchecked items in a @code{radio} or @code{checklist} should be grayed
-out, and the subwidgets should somehow become inactive.  This could
-perhaps be implemented by binding @code{widget-inactive} to t when inserting
-the grayed out subwidget, and let the widget-specify functions check
-that variable.
+Unchecked items in a @code{radio-button-choice} or @code{checklist}
+should be grayed out, and the subwidgets should somehow become inactive.
+This could perhaps be implemented by binding @code{widget-inactive} to t
+when inserting the grayed out subwidget, and let the widget-specify
+functions check that variable.
 
 @end itemize