*** pub/dgnus/lisp/custom.el Thu Aug 31 12:54:38 1995 --- dgnus/lisp/custom.el Tue Sep 5 21:30:38 1995 *************** *** 32,38 **** ;;; Todo: ;; ;; - Toggle documentation in three states `none', `one-line', `full'. ! ;; - Function to generate a XEmacs menu from a CUSTOM. ;; - Write TeXinfo documentation. ;; - Make it possible to hide sections by clicking at the level. ;; - Declare AUC TeX variables. --- 32,38 ---- ;;; Todo: ;; ;; - Toggle documentation in three states `none', `one-line', `full'. ! ;; - Function to generate an XEmacs menu from a CUSTOM. ;; - Write TeXinfo documentation. ;; - Make it possible to hide sections by clicking at the level. ;; - Declare AUC TeX variables. *************** *** 42,47 **** --- 42,52 ---- ;; - XEmacs port. ;; - Allow `URL', `info', and internal hypertext buttons. ;; - Support meta-variables and goal directed customization. + ;; - Make it easy to declare custom types independently. + ;; - Make it possible to declare default value and type for a single + ;; variable, storing the data in a symbol property. + ;; - Syntactic sugar for CUSTOM declarations. + ;; - Use W3 for variable documenation. ;;; Code: *************** *** 93,107 **** otherwise the new PROP VAL pair is added. The new plist is returned; use `(setq x (plist-put x prop val))' to be sure to use the new value. The PLIST is modified by side effects." ! (while plist ! (cond ((eq (car plist) prop) ! (setcar (cdr plist) val) ! (setq plist nil)) ! ((null (cdr (cdr plist))) ! (setcdr (cdr plist) (list prop val)) ! (setq plist nil)) ! (t ! (setq plist (cdr (cdr plist)))))))) (or (fboundp 'match-string) ;; Introduced in Emacs 19.29. --- 98,116 ---- otherwise the new PROP VAL pair is added. The new plist is returned; use `(setq x (plist-put x prop val))' to be sure to use the new value. The PLIST is modified by side effects." ! (if (null plist) ! (list prop val) ! (let ((current plist)) ! (while current ! (cond ((eq (car current) prop) ! (setcar (cdr current) val) ! (setq current nil)) ! ((null (cdr (cdr current))) ! (setcdr (cdr current) (list prop val)) ! (setq current nil)) ! (t ! (setq current (cdr (cdr current))))))) ! plist))) (or (fboundp 'match-string) ;; Introduced in Emacs 19.29. *************** *** 126,132 **** (assq x (and (boundp 'global-face-data) global-face-data)))) t))) ! (if (facep 'underline) () ;; No underline face in XEmacs 19.12. (and (fboundp 'make-face) --- 135,146 ---- (assq x (and (boundp 'global-face-data) global-face-data)))) t))) ! ;; XEmacs and Emacs 19.29 facep does different things. ! (if (fboundp 'find-face) ! (fset 'custom-facep 'find-face) ! (fset 'custom-facep 'facep)) ! ! (if (custom-facep 'underline) () ;; No underline face in XEmacs 19.12. (and (fboundp 'make-face) *************** *** 249,260 **** ;; Put it in the Help menu, if possible. (if (string-match "XEmacs" emacs-version) ! nil ! ;; This will not work under XEmacs. ! (condition-case nil ! (global-set-key [ menu-bar help-menu customize ] ! '("Customize..." . customize)) ! (error nil))) ;;; Categories: ;; --- 263,304 ---- ;; Put it in the Help menu, if possible. (if (string-match "XEmacs" emacs-version) ! ;; XEmacs (disabled because it doesn't work) ! (add-menu-item '("Help") "Customize..." 'customize nil) ! ;; Emacs 19.28 and earlier ! (global-set-key [ menu-bar help customize ] ! '("Customize..." . customize)) ! ;; Emacs 19.29 and later ! (global-set-key [ menu-bar help-menu customize ] ! '("Customize..." . customize))) ! ! ;; XEmacs popup-menu stolen from w3.el. ! (defun custom-x-really-popup-menu (pos title menudesc) ! "My hacked up function to do a blocking popup menu..." ! (let ((echo-keystrokes 0) ! event menu) ! (while menudesc ! (setq menu (cons (vector (car (car menudesc)) ! (list (car (car menudesc))) t) menu) ! menudesc (cdr menudesc))) ! (setq menu (cons title menu)) ! (popup-menu menu) ! (catch 'popup-done ! (while t ! (setq event (next-command-event event)) ! (cond ((and (misc-user-event-p event) (stringp (car-safe (event-object event)))) ! (throw 'popup-done (event-object event))) ! ((and (misc-user-event-p event) ! (or (eq (event-object event) 'abort) ! (eq (event-object event) 'menu-no-selection-hook))) ! nil) ! ((not (popup-menu-up-p)) ! (throw 'popup-done nil)) ! ((button-release-event-p event);; don't beep twice ! nil) ! (t ! (beep) ! (message "please make a choice from the menu."))))))) ;;; Categories: ;; *************** *** 401,406 **** --- 445,451 ---- (defconst custom-type-properties '((repeat (type . default) + ;; See `custom-match'. (import . custom-repeat-import) (eval . custom-repeat-eval) (quote . custom-repeat-quote) *************** *** 414,419 **** --- 459,465 ---- (del-tag . "[DEL]") (add-tag . "[INS]")) (pair (type . group) + ;; A cons-cell. (accept . custom-pair-accept) (eval . custom-pair-eval) (import . custom-pair-import) *************** *** 421,430 **** (valid . (lambda (c d) (consp d))) (extract . custom-pair-extract)) (list (type . group) (quote . custom-list-quote) ! (valid . (lambda (c d) (listp d))) (extract . custom-list-extract)) (group (type . default) (face-tag . nil) (eval . custom-group-eval) (import . custom-group-import) --- 467,479 ---- (valid . (lambda (c d) (consp d))) (extract . custom-pair-extract)) (list (type . group) + ;; A lisp list. (quote . custom-list-quote) ! (valid . (lambda (c d) ! (and (listp d) (not (eq custom-nil(car d)))))) (extract . custom-list-extract)) (group (type . default) + ;; See `custom-match'. (face-tag . nil) (eval . custom-group-eval) (import . custom-group-import) *************** *** 439,444 **** --- 488,494 ---- (insert . custom-group-insert) (find . custom-group-find)) (toggle (type . choice) + ;; Booleans. (data ((type . const) (tag . "On ") (default . t)) *************** *** 446,451 **** --- 496,502 ---- (tag . "Off") (default . nil)))) (choice (type . default) + ;; See `custom-match'. (query . custom-choice-query) (accept . custom-choice-accept) (extract . custom-choice-extract) *************** *** 455,466 **** --- 506,519 ---- (default . __uninitialized__) (type . const))) (const (type . default) + ;; A `const' only matches a single lisp value. (extract . (lambda (c f) (list (custom-default c)))) (validate . (lambda (c f) nil)) (valid . custom-const-valid) (update . custom-const-update) (insert . custom-const-insert)) (face-doc (type . doc) + ;; A variable containing a face. (doc . "\ You can customize the look of Emacs by deciding which faces should be used when. If you push one of the face buttons below, you will be *************** *** 565,597 **** --- 618,658 ---- (type . list)) ((prompt . "Other") (face . custom-field-value) + (default . __uninitialized__) (type . symbol)))) (file (type . string) + ;; A string containing a file or directory name. (directory . nil) (default-file . nil) (query . custom-file-query)) (sexp (type . default) + ;; Any lisp expression. (width . 40) (default . (__uninitialized__ . "Uninitialized")) (read . custom-sexp-read) (write . custom-sexp-write)) (symbol (type . sexp) + ;; A lisp symbol. (width . 40) (valid . (lambda (c d) (symbolp d)))) (integer (type . sexp) + ;; A lisp integer. (width . 10) (valid . (lambda (c d) (integerp d)))) (string (type . default) + ;; A lisp string. (width . 40) (valid . (lambda (c d) (stringp d))) (read . custom-string-read) (write . custom-string-write)) (button (type . default) + ;; Push me. (accept . ignore) (extract . nil) (validate . ignore) (insert . custom-button-insert)) (doc (type . default) + ;; A documentation only entry with no value. (header . nil) (reset . ignore) (extract . nil) *************** *** 631,637 **** The format is `((SYMBOL (PROPERTY . VALUE)... )... )'.") (defconst custom-local-type-properties nil ! "Local type properties.") (make-variable-buffer-local 'custom-local-type-properties) (defconst custom-nil '__uninitialized__ --- 692,700 ---- The format is `((SYMBOL (PROPERTY . VALUE)... )... )'.") (defconst custom-local-type-properties nil ! "Local type properties. ! Entries in this list take precedence over `custom-type-properties'.") ! (make-variable-buffer-local 'custom-local-type-properties) (defconst custom-nil '__uninitialized__ *************** *** 684,689 **** --- 747,756 ---- "Extract `tag' from CUSTOM." (custom-property custom 'tag)) + (defun custom-face-tag (custom) + "Extract `face-tag' from CUSTOM." + (custom-property custom 'face-tag)) + (defun custom-prompt (custom) "Extract `prompt' from CUSTOM. If none exist, default to `tag' or, failing that, `type'." *************** *** 719,730 **** (custom-property custom 'padding)) (defun custom-valid (custom value) ! "Non-nil if CUSTOM may legally be set to VALUE." (and (not (and (listp value) (eq custom-invalid (car value)))) (funcall (custom-property custom 'valid) custom value))) (defun custom-import (custom value) ! "Import CUSTOM VALUE from external variable." (if (eq custom-nil value) (list custom-nil) (funcall (custom-property custom 'import) custom value))) --- 786,801 ---- (custom-property custom 'padding)) (defun custom-valid (custom value) ! "Non-nil if CUSTOM may validly be set to VALUE." (and (not (and (listp value) (eq custom-invalid (car value)))) (funcall (custom-property custom 'valid) custom value))) (defun custom-import (custom value) ! "Import CUSTOM VALUE from external variable. ! ! This function change VALUE into a form that makes it easier to edit ! internally. What the internal form is exactly depends on CUSTOM. ! The internal form is returned." (if (eq custom-nil value) (list custom-nil) (funcall (custom-property custom 'import) custom value))) *************** *** 747,762 **** (funcall (custom-property custom 'write) custom value)))) (defun custom-read (custom string) ! "Convert CUSTOM field content STRING into external form." (condition-case nil (funcall (custom-property custom 'read) custom string) (error (cons custom-invalid string)))) (defun custom-match (custom values) "Match CUSTOM with a list of VALUES. Return a cons-cell where the car is the sublist of VALUES matching CUSTOM, ! and the cdr is the remaining VALUES." (if (memq values (list custom-nil nil)) (cons custom-nil nil) (funcall (custom-property custom 'match) custom values))) --- 818,844 ---- (funcall (custom-property custom 'write) custom value)))) (defun custom-read (custom string) ! "Convert CUSTOM field content STRING into lisp." (condition-case nil (funcall (custom-property custom 'read) custom string) (error (cons custom-invalid string)))) (defun custom-match (custom values) "Match CUSTOM with a list of VALUES. + Return a cons-cell where the car is the sublist of VALUES matching CUSTOM, ! and the cdr is the remaining VALUES. ! ! A CUSTOM is actually a regular expression over the alphabet of lisp ! types. Most CUSTOM types are just doing a literal match, e.g. the ! `symbol' type matches any lisp symbol. The exceptions are: ! ! group: which corresponds to a `(' and `)' group in a regular expression. ! choice: which corresponds to a group of `|' in a regular expression. ! repeat: which corresponds to a `*' in a regular expression. ! optional: which corresponds to a `?', and isn't implemented yet." (if (memq values (list custom-nil nil)) + ;; Nothing matches the uninitialized or empty list. (cons custom-nil nil) (funcall (custom-property custom 'match) custom values))) *************** *** 853,859 **** (funcall (custom-property (custom-field-custom field) 'query) field)) (defun custom-field-accept (field value &optional original) ! "Accept FIELD VALUE. If optional ORIGINAL is non-nil, concider VALUE for the original value." (let ((inhibit-point-motion-hooks t)) (funcall (custom-property (custom-field-custom field) 'accept) --- 935,941 ---- (funcall (custom-property (custom-field-custom field) 'query) field)) (defun custom-field-accept (field value &optional original) ! "Store a new value into field FIELD, taking it from VALUE. If optional ORIGINAL is non-nil, concider VALUE for the original value." (let ((inhibit-point-motion-hooks t)) (funcall (custom-property (custom-field-custom field) 'accept) *************** *** 864,873 **** (let ((custom (custom-field-custom field))) (if (stringp custom) nil ! (funcall (custom-property custom 'face) field)))) (defun custom-field-update (field) ! "Update content of FIELD." (let ((custom (custom-field-custom field))) (if (stringp custom) nil --- 946,956 ---- (let ((custom (custom-field-custom field))) (if (stringp custom) nil ! (let ((face (funcall (custom-property custom 'face) field))) ! (if (custom-facep face) face nil))))) (defun custom-field-update (field) ! "Update the screen appearance of FIELD to correspond with the field's value." (let ((custom (custom-field-custom field))) (if (stringp custom) nil *************** *** 900,906 **** value)))) (defun custom-repeat-accept (field value &optional original) ! "Enter content of editing FIELD." (let ((values (copy-sequence (custom-field-value field))) (all (custom-field-value field)) (start (custom-field-start field)) --- 983,989 ---- value)))) (defun custom-repeat-accept (field value &optional original) ! "Store a new value into field FIELD, taking it from VALUE." (let ((values (copy-sequence (custom-field-value field))) (all (custom-field-value field)) (start (custom-field-start field)) *************** *** 1040,1046 **** result)) (defun custom-pair-accept (field value &optional original) ! "Enter content of editing FIELD with VALUE." (custom-group-accept field (list (car value) (cdr value)) original)) (defun custom-pair-eval (custom value) --- 1123,1129 ---- result)) (defun custom-pair-accept (field value &optional original) ! "Store a new value into field FIELD, taking it from VALUE." (custom-group-accept field (list (car value) (cdr value)) original)) (defun custom-pair-eval (custom value) *************** *** 1186,1196 **** (setq data (cdr data)))))) (defun custom-group-accept (field value &optional original) ! "Enter content of editing FIELD with VALUE." (let* ((values (custom-field-value field)) (custom (custom-field-custom field)) (from (custom-field-start field)) ! (face-tag (custom-property custom 'face-tag)) current) (if face-tag (put-text-property from (+ from (length (custom-tag custom))) --- 1269,1279 ---- (setq data (cdr data)))))) (defun custom-group-accept (field value &optional original) ! "Store a new value into field FIELD, taking it from VALUE." (let* ((values (custom-field-value field)) (custom (custom-field-custom field)) (from (custom-field-start field)) ! (face-tag (custom-face-tag custom)) current) (if face-tag (put-text-property from (+ from (length (custom-tag custom))) *************** *** 1213,1219 **** (from (point)) (compact (custom-compact custom)) (tag (custom-tag custom)) ! (face-tag (custom-property custom 'face-tag))) (cond (face-tag (custom-text-insert tag)) (tag (custom-tag-insert tag field))) (or compact (custom-documentation-insert custom)) --- 1296,1302 ---- (from (point)) (compact (custom-compact custom)) (tag (custom-tag custom)) ! (face-tag (custom-face-tag custom))) (cond (face-tag (custom-text-insert tag)) (tag (custom-tag-insert tag field))) (or compact (custom-documentation-insert custom)) *************** *** 1244,1250 **** field)) (defun custom-choice-accept (field value &optional original) ! "Reset content of editing FIELD." (let ((custom (custom-field-custom field)) (start (custom-field-start field)) (end (custom-field-end field)) --- 1327,1333 ---- field)) (defun custom-choice-accept (field value &optional original) ! "Store a new value into field FIELD, taking it from VALUE." (let ((custom (custom-field-custom field)) (start (custom-field-start field)) (end (custom-field-end field)) *************** *** 1318,1332 **** (setq current (car data) data (cdr data)) (setq alist (cons (cons (custom-prompt current) current) alist))) ! (let ((answer (if (listp last-input-event) ! (x-popup-menu last-input-event ! (list tag (cons "" (reverse alist)))) ! (let ((choice (completing-read (concat tag " (default " ! default "): ") ! alist nil t))) ! (if (or (null choice) (string-equal choice "")) ! (setq choice default)) ! (cdr (assoc choice alist)))))) (if answer (custom-field-accept field (custom-default answer))))))) --- 1401,1425 ---- (setq current (car data) data (cdr data)) (setq alist (cons (cons (custom-prompt current) current) alist))) ! (let ((answer (cond ((and (fboundp 'button-press-event-p) ! (fboundp 'popup-menu) ! (button-press-event-p last-input-event)) ! (cdr (assoc (car (custom-x-really-popup-menu ! last-input-event tag ! (reverse alist))) ! alist))) ! ((listp last-input-event) ! (x-popup-menu last-input-event ! (list tag (cons "" (reverse alist))))) ! (t ! (let ((choice (completing-read (concat tag ! " (default " ! default ! "): ") ! alist nil t))) ! (if (or (null choice) (string-equal choice "")) ! (setq choice default)) ! (cdr (assoc choice alist))))))) (if answer (custom-field-accept field (custom-default answer))))))) *************** *** 1378,1384 **** (or bg "default") (or stipple "default") bold italic underline)))) ! (if (and (facep name) (fboundp 'make-face)) () (make-face name) --- 1471,1477 ---- (or bg "default") (or stipple "default") bold italic underline)))) ! (if (and (custom-facep name) (fboundp 'make-face)) () (make-face name) *************** *** 1391,1398 **** (defun custom-face-hack (field value) "Face that should be used for highlighting FIELD containing VALUE." ! (let ((custom (custom-field-custom field))) ! (eval (funcall (custom-property custom 'export) custom value)))) (defun custom-const-insert (custom level) "Insert field for CUSTOM at nesting LEVEL in customization buffer." --- 1484,1493 ---- (defun custom-face-hack (field value) "Face that should be used for highlighting FIELD containing VALUE." ! (let* ((custom (custom-field-custom field)) ! (face (eval (funcall (custom-property custom 'export) ! custom value)))) ! (if (custom-facep face) face nil))) (defun custom-const-insert (custom level) "Insert field for CUSTOM at nesting LEVEL in customization buffer." *************** *** 1415,1421 **** 'face (custom-field-face field)))) (defun custom-const-valid (custom value) ! "Non-nil if CUSTOM can legally have the value VALUE." (equal (custom-default custom) value)) (defun custom-const-face (field) --- 1510,1516 ---- 'face (custom-field-face field)))) (defun custom-const-valid (custom value) ! "Non-nil if CUSTOM can validly have the value VALUE." (equal (custom-default custom) value)) (defun custom-const-face (field) *************** *** 1470,1475 **** --- 1565,1571 ---- (defun custom-default-export (custom value) ;; Convert CUSTOM's VALUE to external representation. + ;; See `custom-import'. (if (custom-eval custom value) (eval (car (custom-quote custom value))) value)) *************** *** 1516,1522 **** field)) (defun custom-default-accept (field value &optional original) ! "Enter into FIELD the value VALUE." (if original (custom-field-original-set field value)) (custom-field-value-set field value) --- 1612,1618 ---- field)) (defun custom-default-accept (field value &optional original) ! "Store a new value into field FIELD, taking it from VALUE." (if original (custom-field-original-set field value)) (custom-field-value-set field value) *************** *** 2050,2057 **** from (point) (list 'custom-field field 'custom-tag field ! 'face (let ((face (custom-field-face field))) ! (if (facep face) face nil)) front-sticky t)))) (defun custom-field-read (field) --- 2146,2152 ---- from (point) (list 'custom-field field 'custom-tag field ! 'face (custom-field-face field) front-sticky t)))) (defun custom-field-read (field) *************** *** 2060,2065 **** --- 2155,2164 ---- (buffer-substring-no-properties (custom-field-start field) (custom-field-end field)))) + ;; Fields are shown in a special `active' face when point is inside + ;; it. You activate the field by moving point inside (entering) it + ;; and deactivate the field by moving point outside (leaving) it. + (defun custom-field-leave (field) ;; Deactivate FIELD. (let ((before-change-functions nil) *************** *** 2095,2105 **** (size (- end begin))) (cond ((< size width) (goto-char end) ! (condition-case nil (insert-before-markers-and-inherit (make-string (- width size) padding)) ! (error (insert-before-markers ! (make-string (- width size) padding)))) (goto-char pos)) ((> size width) (let ((start (if (and (< (+ begin width) pos) (<= pos end)) --- 2194,2205 ---- (size (- end begin))) (cond ((< size width) (goto-char end) ! (if (fboundp 'insert-before-markers-and-inherit) ! ;; Emacs 19. (insert-before-markers-and-inherit (make-string (- width size) padding)) ! ;; XEmacs: BUG: Doesn't work! ! (insert-before-markers (make-string (- width size) padding))) (goto-char pos)) ((> size width) (let ((start (if (and (< (+ begin width) pos) (<= pos end)) *************** *** 2111,2117 **** (goto-char pos)))))) (defvar custom-field-changed nil) ! ;; List of fields changed on the screen. (make-variable-buffer-local 'custom-field-changed) (defun custom-field-parse (field) --- 2211,2218 ---- (goto-char pos)))))) (defvar custom-field-changed nil) ! ;; List of fields changed on the screen but whose VALUE attribute has ! ;; not yet been updated to reflect the new screen content. (make-variable-buffer-local 'custom-field-changed) (defun custom-field-parse (field) *** pub/dgnus/lisp/gnus-cite.el Thu Aug 31 12:54:38 1995 --- dgnus/lisp/gnus-cite.el Thu Sep 7 01:00:59 1995 *************** *** 34,39 **** --- 34,43 ---- ;;; Customization: + (defvar gnus-cite-parse-max-size 25000 + "Maximum article size (in bytes) where parsing citations is allowed. + Set it to nil to parse all articles.") + (defvar gnus-cite-prefix-regexp "^[]>|:}+ ]*[]>|:}+]\\(.*>\\)?\\|^.*>" "Regexp matching the longest possible citation prefix on a line.") *************** *** 133,139 **** ;;; Commands: ! (defun gnus-article-highlight-citation () "Highlight cited text. Each citation in the article will be highlighted with a different face. The faces are taken from `gnus-cite-face-list'. --- 137,143 ---- ;;; Commands: ! (defun gnus-article-highlight-citation (&optional force) "Highlight cited text. Each citation in the article will be highlighted with a different face. The faces are taken from `gnus-cite-face-list'. *************** *** 145,151 **** Lines matching `gnus-cite-attribution-postfix' and perhaps `gnus-cite-attribution-prefix' are considered attribution lines." ! (interactive) ;; Create dark or light faces if necessary. (cond ((eq gnus-cite-face-list 'light) (setq gnus-cite-face-list --- 149,155 ---- Lines matching `gnus-cite-attribution-postfix' and perhaps `gnus-cite-attribution-prefix' are considered attribution lines." ! (interactive (list 'force)) ;; Create dark or light faces if necessary. (cond ((eq gnus-cite-face-list 'light) (setq gnus-cite-face-list *************** *** 155,161 **** (mapcar 'gnus-make-face gnus-face-dark-name-list)))) (save-excursion (set-buffer gnus-article-buffer) ! (gnus-cite-parse-maybe) (let ((buffer-read-only nil) (alist gnus-cite-prefix-alist) (faces gnus-cite-face-list) --- 159,165 ---- (mapcar 'gnus-make-face gnus-face-dark-name-list)))) (save-excursion (set-buffer gnus-article-buffer) ! (gnus-cite-parse-maybe force) (let ((buffer-read-only nil) (alist gnus-cite-prefix-alist) (faces gnus-cite-face-list) *************** *** 204,216 **** skip (gnus-cite-find-prefix number)) (gnus-cite-add-face number skip gnus-cite-attribution-face))))) ! (defun gnus-article-hide-citation () "Hide all cited text except attribution lines. See the documentation for `gnus-article-highlight-citation'." ! (interactive) (save-excursion (set-buffer gnus-article-buffer) ! (gnus-cite-parse-maybe) (let ((buffer-read-only nil) (alist gnus-cite-prefix-alist) (inhibit-point-motion-hooks t) --- 208,220 ---- skip (gnus-cite-find-prefix number)) (gnus-cite-add-face number skip gnus-cite-attribution-face))))) ! (defun gnus-article-hide-citation (&optional force) "Hide all cited text except attribution lines. See the documentation for `gnus-article-highlight-citation'." ! (interactive (list 'force)) (save-excursion (set-buffer gnus-article-buffer) ! (gnus-cite-parse-maybe force) (let ((buffer-read-only nil) (alist gnus-cite-prefix-alist) (inhibit-point-motion-hooks t) *************** *** 236,242 **** (interactive (list 'force)) (save-excursion (set-buffer gnus-article-buffer) ! (gnus-cite-parse-maybe) (goto-char (point-min)) (search-forward "\n\n") (let ((start (point)) --- 240,246 ---- (interactive (list 'force)) (save-excursion (set-buffer gnus-article-buffer) ! (gnus-cite-parse-maybe force) (goto-char (point-min)) (search-forward "\n\n") (let ((start (point)) *************** *** 271,289 **** ;;; Internal functions: ! (defun gnus-cite-parse-maybe () ;; Parse if the buffer has changes since last time. (if (eq gnus-article-length (- (point-max) (point-min))) () ! (setq gnus-article-length (- (point-max) (point-min))) ! (gnus-cite-parse))) (defun gnus-cite-parse () ;; Parse and connect citation prefixes and attribution lines. ! (setq gnus-cite-prefix-alist nil ! gnus-cite-attribution-alist nil ! gnus-cite-loose-prefix-alist nil ! gnus-cite-loose-attribution-alist nil) ;; Parse current buffer searching for citation prefixes. (goto-char (point-min)) (or (search-forward "\n\n" nil t) --- 275,300 ---- ;;; Internal functions: ! (defun gnus-cite-parse-maybe (&optional force) ;; Parse if the buffer has changes since last time. (if (eq gnus-article-length (- (point-max) (point-min))) () ! ;;Reset parser information. ! (setq gnus-cite-prefix-alist nil ! gnus-cite-attribution-alist nil ! gnus-cite-loose-prefix-alist nil ! gnus-cite-loose-attribution-alist nil) ! ;; Parse if not too large. ! (if (and (not force) ! gnus-cite-parse-max-size ! (> (buffer-size) gnus-cite-parse-max-size)) ! () ! (setq gnus-article-length (- (point-max) (point-min))) ! (gnus-cite-parse)))) (defun gnus-cite-parse () ;; Parse and connect citation prefixes and attribution lines. ! ;; Parse current buffer searching for citation prefixes. (goto-char (point-min)) (or (search-forward "\n\n" nil t) *************** *** 345,351 **** (setq gnus-cite-prefix-alist (cons entry gnus-cite-prefix-alist))) (t ! (setq gnus-cite-prefix-alist (cons entry gnus-cite-prefix-alist)) ;; Remove articles from other prefixes. (let ((loop alist) current) --- 356,363 ---- (setq gnus-cite-prefix-alist (cons entry gnus-cite-prefix-alist))) (t ! (setq gnus-cite-prefix-alist (cons entry ! gnus-cite-prefix-alist)) ;; Remove articles from other prefixes. (let ((loop alist) current) *************** *** 391,406 **** (gnus-cite-match-attributions 'small nil (lambda (prefix tag) (if tag ! (concat "\\`" (regexp-quote prefix) "[ \t]*" (regexp-quote tag) ">")))) ;; Find loose supercite citations after attributions. (gnus-cite-match-attributions 'small t (lambda (prefix tag) ! (if tag (concat "\\<" (regexp-quote tag) "\\>")))) ;; Find loose supercite citations anywhere. (gnus-cite-match-attributions 'small nil (lambda (prefix tag) ! (if tag (concat "\\<" (regexp-quote tag) "\\>")))) ;; Find nested citations after attributions. (gnus-cite-match-attributions 'small-if-unique t (lambda (prefix tag) --- 403,423 ---- (gnus-cite-match-attributions 'small nil (lambda (prefix tag) (if tag ! (concat "\\`" ! (regexp-quote prefix) "[ \t]*" (regexp-quote tag) ">")))) ;; Find loose supercite citations after attributions. (gnus-cite-match-attributions 'small t (lambda (prefix tag) ! (if tag (concat "\\<" ! (regexp-quote tag) ! "\\>")))) ;; Find loose supercite citations anywhere. (gnus-cite-match-attributions 'small nil (lambda (prefix tag) ! (if tag (concat "\\<" ! (regexp-quote tag) ! "\\>")))) ;; Find nested citations after attributions. (gnus-cite-match-attributions 'small-if-unique t (lambda (prefix tag) *** pub/dgnus/lisp/gnus-cus.el Thu Aug 31 12:54:38 1995 --- dgnus/lisp/gnus-cus.el Fri Sep 8 20:31:06 1995 *************** *** 40,48 **** "turquoise")) (defvar gnus-face-dark-name-list ! '("dark blue" "firebrick" ! "dark green" "dark orange" "dark khaki" "dark violet" ! "dark turquoise")) (custom-declare '() '((tag . "GNUS") --- 40,50 ---- "turquoise")) (defvar gnus-face-dark-name-list ! '("RoyalBlue" "firebrick" ! "dark green" "OrangeRed" "dark khaki" "dark violet" ! "SteelBlue4")) ! ; CornflowerBlue SeaGreen OrangeRed SteelBlue4 DeepPink3 ! ; DarkOlviveGreen4 (custom-declare '() '((tag . "GNUS") *************** *** 67,73 **** You can choose between one of the predefined browsers, or `Other'.") (name . gnus-button-url) - (default . w3-fetch) (calculate . (cond ((boundp 'browse-url-browser-function) browse-url-browser-function) ((fboundp 'w3-fetch) --- 69,74 ---- *** pub/dgnus/lisp/gnus-ems.el Thu Aug 31 12:54:38 1995 --- dgnus/lisp/gnus-ems.el Tue Sep 5 22:11:38 1995 *************** *** 131,137 **** ;; portable! (or (face-differs-from-default-p 'underline) (funcall 'set-face-underline-p 'underline t)) ! (or (fboundp 'set-text-properties) (defun set-text-properties (start end props &optional buffer) (if (or (null buffer) (bufferp buffer)) (if props --- 131,137 ---- ;; portable! (or (face-differs-from-default-p 'underline) (funcall 'set-face-underline-p 'underline t)) ! ; (or (fboundp 'set-text-properties) Fuckit! (defun set-text-properties (start end props &optional buffer) (if (or (null buffer) (bufferp buffer)) (if props *************** *** 139,145 **** (put-text-property start end (car props) (nth 1 props) buffer) (setq props (nthcdr 2 props))) ! (remove-text-properties start end ()))))) (defalias 'gnus-make-overlay 'make-extent) (defalias 'gnus-overlay-put 'set-extent-property) --- 139,145 ---- (put-text-property start end (car props) (nth 1 props) buffer) (setq props (nthcdr 2 props))) ! (remove-text-properties start end ())))) (defalias 'gnus-make-overlay 'make-extent) (defalias 'gnus-overlay-put 'set-extent-property) *** pub/dgnus/lisp/gnus-mh.el Thu Aug 31 12:54:38 1995 --- dgnus/lisp/gnus-mh.el Fri Sep 8 00:10:29 1995 *************** *** 80,85 **** --- 80,86 ---- Optional argument YANK means yank original article. The command \\[mh-yank-cur-msg] yank the original message into current buffer." (let (from cc subject date to reply-to to-userid orig-to + references message-id (config (current-window-configuration)) buffer) (pop-to-buffer gnus-article-buffer) *************** *** 101,107 **** reply-to (gnus-fetch-field "reply-to") cc (gnus-fetch-field "cc") orig-to (or (gnus-fetch-field "to") "") ! date (gnus-fetch-field "date")) (setq to (or reply-to from)) (setq to-userid (mail-strip-quoted-names orig-to)) (if (or (string-match "," orig-to) --- 102,110 ---- reply-to (gnus-fetch-field "reply-to") cc (gnus-fetch-field "cc") orig-to (or (gnus-fetch-field "to") "") ! date (gnus-fetch-field "date") ! references (gnus-fetch-field "references") ! message-id (gnus-fetch-field "message-id")) (setq to (or reply-to from)) (setq to-userid (mail-strip-quoted-names orig-to)) (if (or (string-match "," orig-to) *************** *** 135,141 **** "In-reply-to:" (concat (substring from 0 (string-match " *at \\| *@ \\| *(\\| *<" from)) ! "'s message of " date))) ;; need this for mh-yank-cur-msg (setq mh-sent-from-folder buffer) --- 138,145 ---- "In-reply-to:" (concat (substring from 0 (string-match " *at \\| *@ \\| *(\\| *<" from)) ! "'s message of " date)) ! (nnheader-insert-references references message-id)) ;; need this for mh-yank-cur-msg (setq mh-sent-from-folder buffer) *** pub/dgnus/lisp/gnus-msg.el Thu Aug 31 12:54:38 1995 --- dgnus/lisp/gnus-msg.el Sun Sep 10 01:15:07 1995 *************** *** 45,55 **** If you want to insert the signature, you might put `gnus-inews-insert-signature' in this hook.") ! (defvar gnus-use-followup-to 'use "*Specifies what to do with Followup-To header. If nil, ignore the header. If it is t, use its value, but ignore ! `poster'. If it is neither nil nor t, which is the default, always use ! the value.") (defvar gnus-followup-to-function nil "*A variable that contains a function that returns a followup address. --- 45,55 ---- If you want to insert the signature, you might put `gnus-inews-insert-signature' in this hook.") ! (defvar gnus-use-followup-to t "*Specifies what to do with Followup-To header. If nil, ignore the header. If it is t, use its value, but ignore ! `poster'. If it is the symbol `ask', query the user before posting. ! If it is the symbol `use', always use the value.") (defvar gnus-followup-to-function nil "*A variable that contains a function that returns a followup address. *************** *** 298,304 **** (set-buffer gnus-article-buffer) (if (and gnus-use-followup-to (string-equal "poster" (gnus-fetch-field "followup-to")) ! (or (not (eq gnus-use-followup-to t)) (not (gnus-y-or-n-p "Do you want to ignore `Followup-To: poster'? ")))) ;; Mail to the poster. --- 298,304 ---- (set-buffer gnus-article-buffer) (if (and gnus-use-followup-to (string-equal "poster" (gnus-fetch-field "followup-to")) ! (or (not (memq gnus-use-followup-to '(t ask))) (not (gnus-y-or-n-p "Do you want to ignore `Followup-To: poster'? ")))) ;; Mail to the poster. *************** *** 431,438 **** (not gnus-expert-user) post (not group) (progn ! (setq group ! (completing-read "Group: " gnus-active-hashtb)) (or subject (setq subject (read-string "Subject: "))))) (setq mail-reply-buffer gnus-article-copy) --- 431,439 ---- (not gnus-expert-user) post (not group) (progn ! (setq gnus-newsgroup-name ! (setq group ! (completing-read "Group: " gnus-active-hashtb))) (or subject (setq subject (read-string "Subject: "))))) (setq mail-reply-buffer gnus-article-copy) *************** *** 574,590 **** ;; Correct newsgroups field: change sequence of spaces to comma and ;; eliminate spaces around commas. Eliminate imbedded line breaks. (goto-char (point-min)) ! (if (search-forward-regexp "^Newsgroups: +" nil t) (save-restriction (narrow-to-region (point) ! (if (re-search-forward "^[^ \t]" nil 'end) (match-beginning 0) ! (point-max))) (goto-char (point-min)) ! (replace-regexp "\n[ \t]+" " ") ;No line breaks (too confusing) (goto-char (point-min)) ! (replace-regexp "[ \t\n]*,[ \t\n]*\\|[ \t]+" ","))) ;; Added by Per Abrahamsen . ;; Help save the the world! --- 575,598 ---- ;; Correct newsgroups field: change sequence of spaces to comma and ;; eliminate spaces around commas. Eliminate imbedded line breaks. (goto-char (point-min)) ! (if (re-search-forward "^Newsgroups: +" nil t) (save-restriction (narrow-to-region (point) ! (if (re-search-forward "^[^ \t]" nil t) (match-beginning 0) ! (forward-line 1) ! (point))) (goto-char (point-min)) ! (while (re-search-forward "\n[ \t]+" nil t) ! (replace-match " " t t)) ;No line breaks (too confusing) (goto-char (point-min)) ! (while (re-search-forward "[ \t\n]*,[ \t\n]*\\|[ \t]+" nil t) ! (replace-match "," t t)) ! (goto-char (point-min)) ! ;; Remove a trailing comma. ! (if (re-search-forward ",$" nil t) ! (replace-match "" t t)))) ;; Added by Per Abrahamsen . ;; Help save the the world! *************** *** 593,599 **** (let ((newsgroups (mail-fetch-field "newsgroups")) (followup-to (mail-fetch-field "followup-to")) groups to) ! (if (and (string-match "," newsgroups) (not followup-to)) (progn (while (string-match "," newsgroups) (setq groups --- 601,608 ---- (let ((newsgroups (mail-fetch-field "newsgroups")) (followup-to (mail-fetch-field "followup-to")) groups to) ! (if (and newsgroups ! (string-match "," newsgroups) (not followup-to)) (progn (while (string-match "," newsgroups) (setq groups *************** *** 1539,1555 **** (while follow-to (insert (car (car follow-to)) ": " (cdr (car follow-to)) "\n") (setq follow-to (cdr follow-to))))) ! ;; Fold long references line to follow RFC1036. ! (mail-position-on-field "References") ! (let ((begin (- (point) (length "References: "))) ! (fill-column 78) ! (fill-prefix "\t")) ! (if references (insert references)) ! (if (and references message-id) (insert " ")) ! (if message-id (insert message-id)) ! ;; The region must end with a newline to fill the region ! ;; without inserting extra newline. ! (fill-region-as-paragraph begin (1+ (point)))) (goto-char (point-min)) (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$")) --- 1548,1554 ---- (while follow-to (insert (car (car follow-to)) ": " (cdr (car follow-to)) "\n") (setq follow-to (cdr follow-to))))) ! (nnheader-insert-references references message-id) (goto-char (point-min)) (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$")) *** pub/dgnus/lisp/gnus-score.el Thu Aug 31 12:54:38 1995 --- dgnus/lisp/gnus-score.el Thu Sep 7 23:43:42 1995 *************** *** 360,367 **** ;; Regexp is the default type. (if (eq type t) (setq type 'r)) ;; Simplify matches... ! (if (or (eq type 'r) (eq type 's) (eq type nil)) ! (setq match (gnus-simplify-subject-re match))) (let ((score (gnus-score-default score)) (header (downcase header))) (and prompt (setq match (read-string --- 360,369 ---- ;; Regexp is the default type. (if (eq type t) (setq type 'r)) ;; Simplify matches... ! (cond ((or (eq type 'r) (eq type 's) (eq type nil)) ! (setq match (if match (gnus-simplify-subject-re match) ""))) ! ((eq type 'f) ! (setq match (gnus-simplify-subject-fuzzy match)))) (let ((score (gnus-score-default score)) (header (downcase header))) (and prompt (setq match (read-string *************** *** 390,398 **** (and (= score gnus-score-interactive-default-score) (setq score nil)) (let ((new (cond - ((eq type 'f) - (list (gnus-simplify-subject-fuzzy match) - score (and date (gnus-day-number date)) type)) (type (list match score (and date (gnus-day-number date)) type)) (date --- 392,397 ---- *************** *** 775,781 **** (if (zerop (buffer-size)) (delete-file file) ;; There are scores, so we write the file. ! (write-region (point-min) (point-max) file nil 'silent)))))) (kill-buffer (current-buffer))))) (defun gnus-score-headers (score-files &optional trace) --- 774,782 ---- (if (zerop (buffer-size)) (delete-file file) ;; There are scores, so we write the file. ! (and (file-writable-p file) ! (write-region (point-min) (point-max) ! file nil 'silent))))))) (kill-buffer (current-buffer))))) (defun gnus-score-headers (score-files &optional trace) *** pub/dgnus/lisp/gnus-uu.el Thu Aug 31 12:54:38 1995 --- dgnus/lisp/gnus-uu.el Wed Sep 6 00:55:57 1995 *************** *** 677,682 **** --- 677,686 ---- (save-excursion (save-restriction (set-buffer buffer) + (set-text-properties (point-min) (point-max) nil) + ;; These two are necessary for XEmacs 19.12 fascism. + (put-text-property (point-min) (point-max) 'invisible nil) + (put-text-property (point-min) (point-max) 'intangible nil) (goto-char (point-min)) (re-search-forward "\n\n") (setq body (buffer-substring (1- (point)) (point-max))) *** pub/dgnus/lisp/gnus-vis.el Thu Aug 31 12:54:39 1995 --- dgnus/lisp/gnus-vis.el Sun Sep 10 07:18:00 1995 *************** *** 29,34 **** --- 29,49 ---- (require 'gnus-ems) (require gnus-easymenu) (require 'custom) + + (defvar gnus-group-menu-hook nil + "*Hook run after the creation of the group mode menu.") + + (defvar gnus-summary-menu-hook nil + "*Hook run after the creation of the summary mode menu.") + + (defvar gnus-article-menu-hook nil + "*Hook run after the creation of the article mode menu.") + + (defvar gnus-server-menu-hook nil + "*Hook run after the creation of the server mode menu.") + + (defvar gnus-browse-menu-hook nil + "*Hook run after the creation of the browse mode menu.") ;;; Summary highlights. *************** *** 329,335 **** ["Send a bug report" gnus-bug t] ["Send a mail" gnus-group-mail t] ["Post an article" gnus-group-post-news t] ! ["Customize score file" gnus-score-customize (not (string-match "XEmacs" emacs-version)) ] ["Check for new news" gnus-group-get-new-news t] ["Delete bogus groups" gnus-group-check-bogus-groups t] ["Find new newsgroups" gnus-find-new-newsgroups t] --- 344,351 ---- ["Send a bug report" gnus-bug t] ["Send a mail" gnus-group-mail t] ["Post an article" gnus-group-post-news t] ! ["Customize score file" gnus-score-customize ! (not (string-match "XEmacs" emacs-version)) ] ["Check for new news" gnus-group-get-new-news t] ["Delete bogus groups" gnus-group-check-bogus-groups t] ["Find new newsgroups" gnus-find-new-newsgroups t] *************** *** 348,353 **** --- 364,370 ---- ["Edit global kill file" gnus-group-edit-global-kill t] ["Sort group buffer" gnus-group-sort-groups t] )) + (run-hooks 'gnus-group-menu-hook) ))) ;; Server mode *************** *** 355,396 **** (gnus-visual-turn-off-edit-menu 'server) (or (boundp 'gnus-server-menu) ! (easy-menu-define ! gnus-server-menu ! gnus-server-mode-map ! "" ! '("Server" ! ["Add" gnus-server-add-server t] ! ["Browse" gnus-server-read-server t] ! ["List" gnus-server-list-servers t] ! ["Kill" gnus-server-kill-server t] ! ["Yank" gnus-server-yank-server t] ! ["Copy" gnus-server-copy-server t] ! ["Edit" gnus-server-edit-server t] ! ["Exit" gnus-server-exit t] ! )))) ;; Browse mode (defun gnus-browse-make-menu-bar () (gnus-visual-turn-off-edit-menu 'browse) (or (boundp 'gnus-browse-menu) ! (easy-menu-define ! gnus-browse-menu ! gnus-browse-mode-map ! "" ! '("Browse" ! ["Subscribe" gnus-browse-unsubscribe-current-group t] ! ["Read" gnus-group-read-group t] ! ["Exit" gnus-browse-exit t] ! )))) ;; Summary buffer (defun gnus-summary-make-menu-bar () (gnus-visual-turn-off-edit-menu 'summary) (or ! (boundp 'gnus-summary-mark-menu) (progn (easy-menu-define --- 372,420 ---- (gnus-visual-turn-off-edit-menu 'server) (or (boundp 'gnus-server-menu) ! (progn ! (easy-menu-define ! gnus-server-menu ! gnus-server-mode-map ! "" ! '("Server" ! ["Add" gnus-server-add-server t] ! ["Browse" gnus-server-read-server t] ! ["List" gnus-server-list-servers t] ! ["Kill" gnus-server-kill-server t] ! ["Yank" gnus-server-yank-server t] ! ["Copy" gnus-server-copy-server t] ! ["Edit" gnus-server-edit-server t] ! ["Exit" gnus-server-exit t] ! )) ! (run-hooks 'gnus-server-menu-hook) ! ))) ;; Browse mode (defun gnus-browse-make-menu-bar () (gnus-visual-turn-off-edit-menu 'browse) (or (boundp 'gnus-browse-menu) ! (progn ! (easy-menu-define ! gnus-browse-menu ! gnus-browse-mode-map ! "" ! '("Browse" ! ["Subscribe" gnus-browse-unsubscribe-current-group t] ! ["Read" gnus-group-read-group t] ! ["Exit" gnus-browse-exit t] ! )) ! (run-hooks 'gnus-browse-menu-hook) ! ))) ! ;; Summary buffer (defun gnus-summary-make-menu-bar () (gnus-visual-turn-off-edit-menu 'summary) (or ! (boundp 'gnus-summary-misc-menu) (progn (easy-menu-define *************** *** 657,662 **** --- 681,687 ---- ["Fetch article with id..." gnus-summary-refer-article t] ["Redisplay" gnus-summary-show-article t])) + (easy-menu-define gnus-summary-thread-menu *************** *** 695,701 **** ["Reply & followup and yank" gnus-summary-followup-and-reply-with-original t] ["Uuencode and post" gnus-uu-post-news t] )) ! ))) (defun gnus-score-set-default (var value) --- 720,726 ---- ["Reply & followup and yank" gnus-summary-followup-and-reply-with-original t] ["Uuencode and post" gnus-uu-post-news t] )) ! (run-hooks 'gnus-summary-menu-hook) ))) (defun gnus-score-set-default (var value) *************** *** 871,876 **** --- 896,902 ---- ["Remove carriage return" gnus-article-remove-cr t] ["Remove quoted-unreadable" gnus-article-de-quoted-unreadable t] )) + (run-hooks 'gnus-article-menu-hook) ))) ;;; *************** *** 1153,1188 **** (goto-char pos) (error "No buttons found"))))) ! (defun gnus-article-highlight () "Highlight current article. This function calls `gnus-article-highlight-headers', `gnus-article-highlight-citation', `gnus-article-highlight-signature', and `gnus-article-add-buttons' to do the highlighting. See the documentation for those functions." ! (interactive) (gnus-article-highlight-headers) ! (gnus-article-highlight-citation) (gnus-article-highlight-signature) ! (gnus-article-add-buttons)) ! (defun gnus-article-highlight-some () "Highlight current article. This function calls `gnus-article-highlight-headers', `gnus-article-highlight-signature', and `gnus-article-add-buttons' to do the highlighting. See the documentation for those functions." ! (interactive) (gnus-article-highlight-headers) (gnus-article-highlight-signature) (gnus-article-add-buttons)) ! (defun gnus-article-hide () "Hide current article. This function calls `gnus-article-hide-headers', `gnus-article-hide-citation-maybe', and `gnus-article-hide-signature' to do the hiding. See the documentation for those functions." ! (interactive) (gnus-article-hide-headers) ! (gnus-article-hide-citation-maybe) (gnus-article-hide-signature)) (defun gnus-article-highlight-headers () --- 1179,1214 ---- (goto-char pos) (error "No buttons found"))))) ! (defun gnus-article-highlight (&optional force) "Highlight current article. This function calls `gnus-article-highlight-headers', `gnus-article-highlight-citation', `gnus-article-highlight-signature', and `gnus-article-add-buttons' to do the highlighting. See the documentation for those functions." ! (interactive (list 'force)) (gnus-article-highlight-headers) ! (gnus-article-highlight-citation force) (gnus-article-highlight-signature) ! (gnus-article-add-buttons force)) ! (defun gnus-article-highlight-some (&optional force) "Highlight current article. This function calls `gnus-article-highlight-headers', `gnus-article-highlight-signature', and `gnus-article-add-buttons' to do the highlighting. See the documentation for those functions." ! (interactive (list 'force)) (gnus-article-highlight-headers) (gnus-article-highlight-signature) (gnus-article-add-buttons)) ! (defun gnus-article-hide (&optional force) "Hide current article. This function calls `gnus-article-hide-headers', `gnus-article-hide-citation-maybe', and `gnus-article-hide-signature' to do the hiding. See the documentation for those functions." ! (interactive (list 'force)) (gnus-article-hide-headers) ! (gnus-article-hide-citation-maybe force) (gnus-article-hide-signature)) (defun gnus-article-highlight-headers () *************** *** 1260,1278 **** (add-text-properties (match-end 0) (point-max) gnus-hidden-properties))))) ! (defun gnus-article-add-buttons () "Find external references in article and make them to buttons. External references are things like message-ids and URLs, as specified by `gnus-button-alist'." ! (interactive) (if (eq gnus-button-last gnus-button-alist) () (setq gnus-button-regexp (mapconcat 'car gnus-button-alist "\\|") gnus-button-last gnus-button-alist)) (save-excursion (set-buffer gnus-article-buffer) ! (gnus-cite-parse-maybe) (let ((buffer-read-only nil) (inhibit-point-motion-hooks t) (case-fold-search t)) --- 1286,1304 ---- (add-text-properties (match-end 0) (point-max) gnus-hidden-properties))))) ! (defun gnus-article-add-buttons (&optional force) "Find external references in article and make them to buttons. External references are things like message-ids and URLs, as specified by `gnus-button-alist'." ! (interactive (list 'force)) (if (eq gnus-button-last gnus-button-alist) () (setq gnus-button-regexp (mapconcat 'car gnus-button-alist "\\|") gnus-button-last gnus-button-alist)) (save-excursion (set-buffer gnus-article-buffer) ! (gnus-cite-parse-maybe force) (let ((buffer-read-only nil) (inhibit-point-motion-hooks t) (case-fold-search t)) *** pub/dgnus/lisp/gnus.el Thu Aug 31 12:54:39 1995 --- dgnus/lisp/gnus.el Mon Sep 11 06:06:08 1995 *************** *** 33,38 **** --- 33,40 ---- ;;; Code: + (eval '(run-hooks 'gnus-load-hook)) + (require 'mail-utils) (require 'timezone) (require 'nnheader) *************** *** 82,93 **** ;; Customization variables (defvar gnus-select-method ! (list 'nntp (or (getenv "NNTPSERVER") ! (if (and gnus-default-nntp-server ! (not (string= gnus-default-nntp-server ""))) ! gnus-default-nntp-server) ! (system-name))) "*Default method for selecting a newsgroup. This variable should be a list, where the first element is how the news is to be fetched, the second is the address. --- 84,106 ---- ;; Customization variables + ;; Don't touch this variable. + (defvar gnus-nntp-service "nntp" + "*NNTP service name (\"nntp\" or 119). + This is an obsolete variable, which is scarcely used. If you use an + nntp server for your newsgroup and want to change the port number + used to 899, you would say something along these lines: + + (setq gnus-select-method '(nntp \"my.nntp.server\" (nntp-port-number 899)))") + (defvar gnus-select-method ! (nconc ! (list 'nntp (or (getenv "NNTPSERVER") ! (if (and gnus-default-nntp-server ! (not (string= gnus-default-nntp-server ""))) ! gnus-default-nntp-server) ! (system-name))) ! (if (equal gnus-nntp-service "nntp") nil (list gnus-nntp-service))) "*Default method for selecting a newsgroup. This variable should be a list, where the first element is how the news is to be fetched, the second is the address. *************** *** 146,159 **** This variable is semi-obsolete. Use the `gnus-select-method' variable instead.") - (defvar gnus-nntp-service "nntp" - "*NNTP service name (\"nntp\" or 119). - This is an obsolete variable, which is scarcely used. If you use an - nntp server for your newsgroup and want to change the port number - used to 899, you would say something along these lines: - - (setq gnus-select-method '(nntp \"my.nntp.server\" (nntp-port-number 899)))") - (defvar gnus-startup-file "~/.newsrc" "*Your `.newsrc' file. `.newsrc-SERVER' will be used instead if that exists.") --- 159,164 ---- *************** *** 1086,1091 **** --- 1091,1099 ---- (defvar gnus-open-server-hook nil "*A hook called just before opening connection to the news server.") + (defvar gnus-load-hook nil + "*A hook run while Gnus is loaded.") + (defvar gnus-startup-hook nil "*A hook called at startup. This hook is called after Gnus is connected to the NNTP server.") *************** *** 1343,1349 **** "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)" "The mail address of the Gnus maintainers.") ! (defconst gnus-version "Gnus v5.0" "Version number for this version of Gnus.") (defvar gnus-info-nodes --- 1351,1357 ---- "gnus-bug@ifi.uio.no (The Gnus Bugfixing Girls + Boys)" "The mail address of the Gnus maintainers.") ! (defconst gnus-version "Gnus v5.0.1" "Version number for this version of Gnus.") (defvar gnus-info-nodes *************** *** 3069,3076 **** (define-key gnus-group-mode-map "\177" 'gnus-group-prev-unread-group) (define-key gnus-group-mode-map "N" 'gnus-group-next-group) (define-key gnus-group-mode-map "P" 'gnus-group-prev-group) ! (define-key gnus-group-mode-map "\M-n" 'gnus-group-next-unread-group-same-level) ! (define-key gnus-group-mode-map "\M-p" 'gnus-group-prev-unread-group-same-level) (define-key gnus-group-mode-map "," 'gnus-group-best-unread-group) (define-key gnus-group-mode-map "." 'gnus-group-first-unread-group) (define-key gnus-group-mode-map "u" 'gnus-group-unsubscribe-current-group) --- 3077,3086 ---- (define-key gnus-group-mode-map "\177" 'gnus-group-prev-unread-group) (define-key gnus-group-mode-map "N" 'gnus-group-next-group) (define-key gnus-group-mode-map "P" 'gnus-group-prev-group) ! (define-key gnus-group-mode-map ! "\M-n" 'gnus-group-next-unread-group-same-level) ! (define-key gnus-group-mode-map ! "\M-p" 'gnus-group-prev-unread-group-same-level) (define-key gnus-group-mode-map "," 'gnus-group-best-unread-group) (define-key gnus-group-mode-map "." 'gnus-group-first-unread-group) (define-key gnus-group-mode-map "u" 'gnus-group-unsubscribe-current-group) *************** *** 4221,4227 **** (gnus-group-make-group (gnus-group-real-name name) (list 'nndoc name ! (list 'nndoc-address (concat (file-name-as-directory (car path)) "doc.txt")) (list 'nndoc-article-type 'mbox)))) (gnus-group-position-cursor)) --- 4231,4238 ---- (gnus-group-make-group (gnus-group-real-name name) (list 'nndoc name ! (list 'nndoc-address ! (concat (file-name-as-directory (car path)) "doc.txt")) (list 'nndoc-article-type 'mbox)))) (gnus-group-position-cursor)) *************** *** 4252,4258 **** (defun gnus-group-make-archive-group (&optional all) "Create the (ding) Gnus archive group of the most recent articles. Given a prefix, create a full group." ! (interactive) (let ((group (gnus-group-prefixed-name (if all "ding.archives" "ding.recent") '(nndir "")))) (and (gnus-gethash group gnus-newsrc-hashtb) --- 4263,4269 ---- (defun gnus-group-make-archive-group (&optional all) "Create the (ding) Gnus archive group of the most recent articles. Given a prefix, create a full group." ! (interactive "P") (let ((group (gnus-group-prefixed-name (if all "ding.archives" "ding.recent") '(nndir "")))) (and (gnus-gethash group gnus-newsrc-hashtb) *************** *** 4519,4546 **** "Group: " gnus-active-hashtb nil (memq gnus-select-method gnus-have-read-active-file)))) (let ((newsrc (gnus-gethash group gnus-newsrc-hashtb))) ! (cond (newsrc ! ;; Toggle subscription flag. ! (gnus-group-change-level ! newsrc (if level level (if (<= (nth 1 (nth 2 newsrc)) ! gnus-level-subscribed) ! (1+ gnus-level-subscribed) ! gnus-level-default-subscribed))) ! (gnus-group-update-group group)) ! ((and (stringp group) ! (or (not (memq gnus-select-method gnus-have-read-active-file)) ! (gnus-gethash group gnus-active-hashtb))) ! ;; Add new newsgroup. ! (gnus-group-change-level ! group ! (if level level gnus-level-default-subscribed) ! (or (and (member group gnus-zombie-list) ! gnus-level-zombie) ! gnus-level-killed) ! (and (gnus-group-group-name) ! (gnus-gethash (gnus-group-group-name) gnus-newsrc-hashtb))) ! (gnus-group-update-group group)) ! (t (error "No such newsgroup: %s" group))) (gnus-group-position-cursor))) (defun gnus-group-transpose-groups (n) --- 4530,4560 ---- "Group: " gnus-active-hashtb nil (memq gnus-select-method gnus-have-read-active-file)))) (let ((newsrc (gnus-gethash group gnus-newsrc-hashtb))) ! (cond ! ((string-match "^[ \t]$" group) ! (error "Empty group name")) ! (newsrc ! ;; Toggle subscription flag. ! (gnus-group-change-level ! newsrc (if level level (if (<= (nth 1 (nth 2 newsrc)) ! gnus-level-subscribed) ! (1+ gnus-level-subscribed) ! gnus-level-default-subscribed))) ! (gnus-group-update-group group)) ! ((and (stringp group) ! (or (not (memq gnus-select-method gnus-have-read-active-file)) ! (gnus-gethash group gnus-active-hashtb))) ! ;; Add new newsgroup. ! (gnus-group-change-level ! group ! (if level level gnus-level-default-subscribed) ! (or (and (member group gnus-zombie-list) ! gnus-level-zombie) ! gnus-level-killed) ! (and (gnus-group-group-name) ! (gnus-gethash (gnus-group-group-name) gnus-newsrc-hashtb))) ! (gnus-group-update-group group)) ! (t (error "No such newsgroup: %s" group))) (gnus-group-position-cursor))) (defun gnus-group-transpose-groups (n) *************** *** 4869,4877 **** (interactive "P") (setq gnus-current-kill-article article) (gnus-kill-file-edit-file group) ! (gnus-message 6 ! (substitute-command-keys ! "Editing a global kill file (Type \\[gnus-kill-file-exit] to exit)"))) (defun gnus-group-edit-local-kill (article group) "Edit a local kill file." --- 4883,4892 ---- (interactive "P") (setq gnus-current-kill-article article) (gnus-kill-file-edit-file group) ! (gnus-message ! 6 ! (substitute-command-keys ! "Editing a global kill file (Type \\[gnus-kill-file-exit] to exit)"))) (defun gnus-group-edit-local-kill (article group) "Edit a local kill file." *************** *** 4914,4920 **** The hook `gnus-exit-gnus-hook' is called before actually exiting." (interactive) (if (or noninteractive ;For gnus-batch-kill - (zerop (buffer-size)) ;No news is good news. (not (gnus-server-opened gnus-select-method)) ;NNTP connection closed (not gnus-interactive-exit) ;Without confirmation gnus-expert-user --- 4929,4934 ---- *************** *** 5265,5272 **** (define-key gnus-summary-mode-map "\M-p" 'gnus-summary-prev-unread-subject) (define-key gnus-summary-mode-map "." 'gnus-summary-first-unread-article) (define-key gnus-summary-mode-map "," 'gnus-summary-best-unread-article) ! (define-key gnus-summary-mode-map "\M-s" 'gnus-summary-search-article-forward) ! (define-key gnus-summary-mode-map "\M-r" 'gnus-summary-search-article-backward) (define-key gnus-summary-mode-map "<" 'gnus-summary-beginning-of-article) (define-key gnus-summary-mode-map ">" 'gnus-summary-end-of-article) (define-key gnus-summary-mode-map "j" 'gnus-summary-goto-subject) --- 5279,5288 ---- (define-key gnus-summary-mode-map "\M-p" 'gnus-summary-prev-unread-subject) (define-key gnus-summary-mode-map "." 'gnus-summary-first-unread-article) (define-key gnus-summary-mode-map "," 'gnus-summary-best-unread-article) ! (define-key gnus-summary-mode-map ! "\M-s" 'gnus-summary-search-article-forward) ! (define-key gnus-summary-mode-map ! "\M-r" 'gnus-summary-search-article-backward) (define-key gnus-summary-mode-map "<" 'gnus-summary-beginning-of-article) (define-key gnus-summary-mode-map ">" 'gnus-summary-end-of-article) (define-key gnus-summary-mode-map "j" 'gnus-summary-goto-subject) *************** *** 5280,5286 **** (define-key gnus-summary-mode-map "E" 'gnus-summary-mark-as-expirable) (define-key gnus-summary-mode-map "\M-u" 'gnus-summary-clear-mark-forward) (define-key gnus-summary-mode-map "\M-U" 'gnus-summary-clear-mark-backward) ! (define-key gnus-summary-mode-map "k" 'gnus-summary-kill-same-subject-and-select) (define-key gnus-summary-mode-map "\C-k" 'gnus-summary-kill-same-subject) (define-key gnus-summary-mode-map "\M-\C-k" 'gnus-summary-kill-thread) (define-key gnus-summary-mode-map "\M-\C-l" 'gnus-summary-lower-thread) --- 5296,5303 ---- (define-key gnus-summary-mode-map "E" 'gnus-summary-mark-as-expirable) (define-key gnus-summary-mode-map "\M-u" 'gnus-summary-clear-mark-forward) (define-key gnus-summary-mode-map "\M-U" 'gnus-summary-clear-mark-backward) ! (define-key gnus-summary-mode-map ! "k" 'gnus-summary-kill-same-subject-and-select) (define-key gnus-summary-mode-map "\C-k" 'gnus-summary-kill-same-subject) (define-key gnus-summary-mode-map "\M-\C-k" 'gnus-summary-kill-thread) (define-key gnus-summary-mode-map "\M-\C-l" 'gnus-summary-lower-thread) *************** *** 5299,5312 **** (define-key gnus-summary-mode-map "\C-w" 'gnus-summary-mark-region-as-read) (define-key gnus-summary-mode-map "\C-t" 'gnus-summary-toggle-truncation) (define-key gnus-summary-mode-map "?" 'gnus-summary-mark-as-dormant) ! (define-key gnus-summary-mode-map "\C-c\M-\C-s" 'gnus-summary-show-all-expunged) ! (define-key gnus-summary-mode-map "\C-c\C-s\C-n" 'gnus-summary-sort-by-number) ! (define-key gnus-summary-mode-map "\C-c\C-s\C-a" 'gnus-summary-sort-by-author) ! (define-key gnus-summary-mode-map "\C-c\C-s\C-s" 'gnus-summary-sort-by-subject) (define-key gnus-summary-mode-map "\C-c\C-s\C-d" 'gnus-summary-sort-by-date) (define-key gnus-summary-mode-map "\C-c\C-s\C-i" 'gnus-summary-sort-by-score) (define-key gnus-summary-mode-map "=" 'gnus-summary-expand-window) ! (define-key gnus-summary-mode-map "\C-x\C-s" 'gnus-summary-reselect-current-group) (define-key gnus-summary-mode-map "\M-g" 'gnus-summary-rescan-group) (define-key gnus-summary-mode-map "w" 'gnus-summary-stop-page-breaking) (define-key gnus-summary-mode-map "\C-c\C-r" 'gnus-summary-caesar-message) --- 5316,5334 ---- (define-key gnus-summary-mode-map "\C-w" 'gnus-summary-mark-region-as-read) (define-key gnus-summary-mode-map "\C-t" 'gnus-summary-toggle-truncation) (define-key gnus-summary-mode-map "?" 'gnus-summary-mark-as-dormant) ! (define-key gnus-summary-mode-map ! "\C-c\M-\C-s" 'gnus-summary-show-all-expunged) ! (define-key gnus-summary-mode-map ! "\C-c\C-s\C-n" 'gnus-summary-sort-by-number) ! (define-key gnus-summary-mode-map ! "\C-c\C-s\C-a" 'gnus-summary-sort-by-author) ! (define-key gnus-summary-mode-map ! "\C-c\C-s\C-s" 'gnus-summary-sort-by-subject) (define-key gnus-summary-mode-map "\C-c\C-s\C-d" 'gnus-summary-sort-by-date) (define-key gnus-summary-mode-map "\C-c\C-s\C-i" 'gnus-summary-sort-by-score) (define-key gnus-summary-mode-map "=" 'gnus-summary-expand-window) ! (define-key gnus-summary-mode-map ! "\C-x\C-s" 'gnus-summary-reselect-current-group) (define-key gnus-summary-mode-map "\M-g" 'gnus-summary-rescan-group) (define-key gnus-summary-mode-map "w" 'gnus-summary-stop-page-breaking) (define-key gnus-summary-mode-map "\C-c\C-r" 'gnus-summary-caesar-message) *************** *** 5330,5336 **** (define-key gnus-summary-mode-map gnus-mouse-2 'gnus-mouse-pick-article) (define-key gnus-summary-mode-map "m" 'gnus-summary-mail-other-window) (define-key gnus-summary-mode-map "a" 'gnus-summary-post-news) ! (define-key gnus-summary-mode-map "x" 'gnus-summary-remove-lines-marked-as-read) ; (define-key gnus-summary-mode-map "X" 'gnus-summary-remove-lines-marked-with) (define-key gnus-summary-mode-map "s" 'gnus-summary-isearch-article) (define-key gnus-summary-mode-map "t" 'gnus-summary-toggle-header) --- 5352,5359 ---- (define-key gnus-summary-mode-map gnus-mouse-2 'gnus-mouse-pick-article) (define-key gnus-summary-mode-map "m" 'gnus-summary-mail-other-window) (define-key gnus-summary-mode-map "a" 'gnus-summary-post-news) ! (define-key gnus-summary-mode-map ! "x" 'gnus-summary-remove-lines-marked-as-read) ; (define-key gnus-summary-mode-map "X" 'gnus-summary-remove-lines-marked-with) (define-key gnus-summary-mode-map "s" 'gnus-summary-isearch-article) (define-key gnus-summary-mode-map "t" 'gnus-summary-toggle-header) *************** *** 5359,5373 **** (define-key gnus-summary-mark-map "B" 'gnus-summary-remove-bookmark) (define-key gnus-summary-mark-map "#" 'gnus-summary-mark-as-processable) (define-key gnus-summary-mark-map "\M-#" 'gnus-summary-unmark-as-processable) ! (define-key gnus-summary-mark-map "\M-r" 'gnus-summary-remove-lines-marked-as-read) ! (define-key gnus-summary-mark-map "\M-\C-r" 'gnus-summary-remove-lines-marked-with) (define-key gnus-summary-mark-map "D" 'gnus-summary-show-all-dormant) (define-key gnus-summary-mark-map "\M-D" 'gnus-summary-hide-all-dormant) (define-key gnus-summary-mark-map "S" 'gnus-summary-show-all-expunged) (define-key gnus-summary-mark-map "C" 'gnus-summary-catchup) (define-key gnus-summary-mark-map "H" 'gnus-summary-catchup-to-here) (define-key gnus-summary-mark-map "\C-c" 'gnus-summary-catchup-all) ! (define-key gnus-summary-mark-map "k" 'gnus-summary-kill-same-subject-and-select) (define-key gnus-summary-mark-map "K" 'gnus-summary-kill-same-subject) (define-prefix-command 'gnus-summary-mscore-map) --- 5382,5399 ---- (define-key gnus-summary-mark-map "B" 'gnus-summary-remove-bookmark) (define-key gnus-summary-mark-map "#" 'gnus-summary-mark-as-processable) (define-key gnus-summary-mark-map "\M-#" 'gnus-summary-unmark-as-processable) ! (define-key gnus-summary-mark-map ! "\M-r" 'gnus-summary-remove-lines-marked-as-read) ! (define-key gnus-summary-mark-map ! "\M-\C-r" 'gnus-summary-remove-lines-marked-with) (define-key gnus-summary-mark-map "D" 'gnus-summary-show-all-dormant) (define-key gnus-summary-mark-map "\M-D" 'gnus-summary-hide-all-dormant) (define-key gnus-summary-mark-map "S" 'gnus-summary-show-all-expunged) (define-key gnus-summary-mark-map "C" 'gnus-summary-catchup) (define-key gnus-summary-mark-map "H" 'gnus-summary-catchup-to-here) (define-key gnus-summary-mark-map "\C-c" 'gnus-summary-catchup-all) ! (define-key gnus-summary-mark-map ! "k" 'gnus-summary-kill-same-subject-and-select) (define-key gnus-summary-mark-map "K" 'gnus-summary-kill-same-subject) (define-prefix-command 'gnus-summary-mscore-map) *************** *** 5422,5428 **** (define-key gnus-summary-exit-map "E" 'gnus-summary-exit-no-update) (define-key gnus-summary-exit-map "Q" 'gnus-summary-exit) (define-key gnus-summary-exit-map "Z" 'gnus-summary-exit) ! (define-key gnus-summary-exit-map "n" 'gnus-summary-catchup-and-goto-next-group) (define-key gnus-summary-exit-map "R" 'gnus-summary-reselect-current-group) (define-key gnus-summary-exit-map "G" 'gnus-summary-rescan-group) (define-key gnus-summary-exit-map "N" 'gnus-summary-next-group) --- 5448,5455 ---- (define-key gnus-summary-exit-map "E" 'gnus-summary-exit-no-update) (define-key gnus-summary-exit-map "Q" 'gnus-summary-exit) (define-key gnus-summary-exit-map "Z" 'gnus-summary-exit) ! (define-key gnus-summary-exit-map ! "n" 'gnus-summary-catchup-and-goto-next-group) (define-key gnus-summary-exit-map "R" 'gnus-summary-reselect-current-group) (define-key gnus-summary-exit-map "G" 'gnus-summary-rescan-group) (define-key gnus-summary-exit-map "N" 'gnus-summary-next-group) *************** *** 5456,5469 **** (define-key gnus-summary-wash-hide-map "h" 'gnus-article-hide-headers) (define-key gnus-summary-wash-hide-map "s" 'gnus-article-hide-signature) (define-key gnus-summary-wash-hide-map "c" 'gnus-article-hide-citation) ! (define-key gnus-summary-wash-hide-map "\C-c" 'gnus-article-hide-citation-maybe) (define-prefix-command 'gnus-summary-wash-highlight-map) (define-key gnus-summary-wash-map "H" 'gnus-summary-wash-highlight-map) (define-key gnus-summary-wash-highlight-map "a" 'gnus-article-highlight) ! (define-key gnus-summary-wash-highlight-map "h" 'gnus-article-highlight-headers) ! (define-key gnus-summary-wash-highlight-map "c" 'gnus-article-highlight-citation) ! (define-key gnus-summary-wash-highlight-map "s" 'gnus-article-highlight-signature) (define-prefix-command 'gnus-summary-wash-time-map) (define-key gnus-summary-wash-map "T" 'gnus-summary-wash-time-map) --- 5483,5500 ---- (define-key gnus-summary-wash-hide-map "h" 'gnus-article-hide-headers) (define-key gnus-summary-wash-hide-map "s" 'gnus-article-hide-signature) (define-key gnus-summary-wash-hide-map "c" 'gnus-article-hide-citation) ! (define-key gnus-summary-wash-hide-map ! "\C-c" 'gnus-article-hide-citation-maybe) (define-prefix-command 'gnus-summary-wash-highlight-map) (define-key gnus-summary-wash-map "H" 'gnus-summary-wash-highlight-map) (define-key gnus-summary-wash-highlight-map "a" 'gnus-article-highlight) ! (define-key gnus-summary-wash-highlight-map ! "h" 'gnus-article-highlight-headers) ! (define-key gnus-summary-wash-highlight-map ! "c" 'gnus-article-highlight-citation) ! (define-key gnus-summary-wash-highlight-map ! "s" 'gnus-article-highlight-signature) (define-prefix-command 'gnus-summary-wash-time-map) (define-key gnus-summary-wash-map "T" 'gnus-summary-wash-time-map) *************** *** 6151,6157 **** (gnus-simplify-subject-re (mail-header-subject (car headers))))) (progn ! (if (not (< (or (cdr (assq (mail-header-number (car headers)) gnus-newsgroup-scored)) default) below)) (setq new-roots (cons (car headers) new-roots)) --- 6182,6189 ---- (gnus-simplify-subject-re (mail-header-subject (car headers))))) (progn ! (if (not (< (or (cdr (assq (mail-header-number ! (car headers)) gnus-newsgroup-scored)) default) below)) (setq new-roots (cons (car headers) new-roots)) *************** *** 6480,6486 **** ((eq gnus-summary-make-false-root 'dummy) ;; We output a dummy root. (gnus-summary-insert-dummy-line ! nil header (mail-header-number (car (car (cdr (car thread))))))) (t ;; We do not make a root for the gathered ;; sub-threads at all. --- 6512,6519 ---- ((eq gnus-summary-make-false-root 'dummy) ;; We output a dummy root. (gnus-summary-insert-dummy-line ! nil header (mail-header-number ! (car (car (cdr (car thread))))))) (t ;; We do not make a root for the gathered ;; sub-threads at all. *************** *** 6528,6545 **** gnus-ancient-mark))) (memq number gnus-newsgroup-replied) (memq number gnus-newsgroup-expirable) ! (if (and (eq gnus-summary-make-false-root 'empty) ! (memq number gnus-tmp-gathered)) ! gnus-summary-same-subject ! (if (or (zerop level) ! (and gnus-thread-ignore-subject ! (not (string= ! (gnus-simplify-subject-re ! gnus-tmp-prev-subject) ! (gnus-simplify-subject-re ! subject))))) ! subject ! gnus-summary-same-subject)) (and (eq gnus-summary-make-false-root 'adopt) (memq number gnus-tmp-gathered)) (cdr (assq number gnus-newsgroup-scored))) --- 6561,6578 ---- gnus-ancient-mark))) (memq number gnus-newsgroup-replied) (memq number gnus-newsgroup-expirable) ! (cond ! ((and gnus-thread-ignore-subject ! (not (string= ! (gnus-simplify-subject-re gnus-tmp-prev-subject) ! (gnus-simplify-subject-re subject)))) ! subject) ! ((zerop level) ! (if (and (eq gnus-summary-make-false-root 'empty) ! (memq number gnus-tmp-gathered)) ! gnus-summary-same-subject ! subject)) ! (t gnus-summary-same-subject)) (and (eq gnus-summary-make-false-root 'adopt) (memq number gnus-tmp-gathered)) (cdr (assq number gnus-newsgroup-scored))) *************** *** 6560,6566 **** ;; Do the async thing, if that is required. (if gnus-newsgroup-async (setq gnus-newsgroup-threads ! (mapcar (lambda (h) (cons (mail-header-number h) (mail-header-lines h))) headers))) (while headers --- 6593,6600 ---- ;; Do the async thing, if that is required. (if gnus-newsgroup-async (setq gnus-newsgroup-threads ! (mapcar (lambda (h) ! (cons (mail-header-number h) (mail-header-lines h))) headers))) (while headers *************** *** 6602,6619 **** (let* ((entry (gnus-gethash group gnus-newsrc-hashtb)) (info (nth 2 entry)) articles) - (gnus-check-server - (setq gnus-current-select-method (gnus-find-method-for-group group))) ! (or (gnus-check-server gnus-current-select-method) (error "Couldn't open server")) ! (or (and (null entry) ! (gnus-activate-group group)) ! (and (eq (car entry) t) ! (gnus-activate-group (car info))) ! (gnus-request-group group t) ! (progn (kill-buffer (current-buffer)) (error "Couldn't request group %s: %s" group (gnus-status-message group)))) --- 6636,6649 ---- (let* ((entry (gnus-gethash group gnus-newsrc-hashtb)) (info (nth 2 entry)) articles) ! (or (gnus-check-server ! (setq gnus-current-select-method (gnus-find-method-for-group group))) (error "Couldn't open server")) ! (or (and entry (not (eq (car entry) t))) ; Either it's active... ! (gnus-activate-group group) ; Or we can activate it... ! (progn ; Or we bug out. (kill-buffer (current-buffer)) (error "Couldn't request group %s: %s" group (gnus-status-message group)))) *************** *** 6711,6717 **** (setq gnus-newsgroup-begin (mail-header-number (car gnus-newsgroup-headers))) (setq gnus-newsgroup-end ! (mail-header-number (gnus-last-element gnus-newsgroup-headers)))) (setq gnus-reffed-article-number -1) ;; GROUP is successfully selected. (or gnus-newsgroup-headers t))))) --- 6741,6748 ---- (setq gnus-newsgroup-begin (mail-header-number (car gnus-newsgroup-headers))) (setq gnus-newsgroup-end ! (mail-header-number ! (gnus-last-element gnus-newsgroup-headers)))) (setq gnus-reffed-article-number -1) ;; GROUP is successfully selected. (or gnus-newsgroup-headers t))))) *************** *** 7031,7040 **** (let ((ids articles) (ticked (cdr (assq 'tick (nth 3 info)))) (dormant (cdr (assq 'dormant (nth 3 info)))) ! id) (setq exps nil) (while ids (setq id (car ids)) (if (or (> id (cdr active)) (< id (car active)) (memq id ticked) --- 7062,7083 ---- (let ((ids articles) (ticked (cdr (assq 'tick (nth 3 info)))) (dormant (cdr (assq 'dormant (nth 3 info)))) ! id first) (setq exps nil) (while ids (setq id (car ids)) + (if (and first (> id (cdr active))) + (progn + ;; We'll end up in this situation in one particular + ;; obscure situation. If you re-scan a group and get + ;; a new article that is cross-posted to a different + ;; group that has not been re-scanned, you might get + ;; crossposted article that has a higher number than + ;; Gnus believes possible. So we re-activate this + ;; group as well. This might mean doing the + ;; crossposting thingie will *increase* the number + ;; of articles in some groups. Tsk, tsk. + (setq active (or (gnus-activate-group group) active)))) (if (or (> id (cdr active)) (< id (car active)) (memq id ticked) *************** *** 7195,7201 **** (progn (mail-header-set-xref (car (symbol-value dep)) ! (concat (or (mail-header-xref (car (symbol-value dep))) "") (or (mail-header-xref header) ""))) (setq header nil)) (setcar (symbol-value dep) header)) --- 7238,7245 ---- (progn (mail-header-set-xref (car (symbol-value dep)) ! (concat (or (mail-header-xref ! (car (symbol-value dep))) "") (or (mail-header-xref header) ""))) (setq header nil)) (setcar (symbol-value dep) header)) *************** *** 7725,7731 **** (mode major-mode) (buf (current-buffer))) (run-hooks 'gnus-summary-prepare-exit-hook) ! (gnus-summary-update-info) ; Make all changes in this group permanent. (set-buffer buf) (and gnus-use-cache (gnus-cache-possibly-remove-articles)) ;; Make sure where I was, and go to next newsgroup. --- 7769,7776 ---- (mode major-mode) (buf (current-buffer))) (run-hooks 'gnus-summary-prepare-exit-hook) ! ;; Make all changes in this group permanent. ! (gnus-summary-update-info) (set-buffer buf) (and gnus-use-cache (gnus-cache-possibly-remove-articles)) ;; Make sure where I was, and go to next newsgroup. *************** *** 8352,8358 **** (string-to-int (completing-read "Article number: " ! (mapcar (lambda (headers) (list (int-to-string (mail-header-number headers)))) gnus-newsgroup-headers) nil 'require-match)))) (prog1 --- 8397,8404 ---- (string-to-int (completing-read "Article number: " ! (mapcar (lambda (headers) ! (list (int-to-string (mail-header-number headers)))) gnus-newsgroup-headers) nil 'require-match)))) (prog1 *************** *** 8548,8568 **** (gnus-summary-select-article) (gnus-message 9 "Searching article: %d..." gnus-current-article) (setq last gnus-current-article) ! (gnus-eval-in-buffer-window gnus-article-buffer ! (save-restriction ! (widen) ! ;; Begin search from current point. ! (setq found (funcall re-search regexp nil t)))) ;; Then search next articles. (while (and (not found) (gnus-summary-display-article (gnus-summary-search-subject backward nil nil))) (gnus-message 9 "Searching article: %d..." gnus-current-article) ! (gnus-eval-in-buffer-window gnus-article-buffer ! (save-restriction ! (widen) ! (goto-char (if backward (point-max) (point-min))) ! (setq found (funcall re-search regexp nil t))))) (message "") ;; Adjust article pointer. (or (eq last gnus-current-article) --- 8594,8616 ---- (gnus-summary-select-article) (gnus-message 9 "Searching article: %d..." gnus-current-article) (setq last gnus-current-article) ! (gnus-eval-in-buffer-window ! gnus-article-buffer ! (save-restriction ! (widen) ! ;; Begin search from current point. ! (setq found (funcall re-search regexp nil t)))) ;; Then search next articles. (while (and (not found) (gnus-summary-display-article (gnus-summary-search-subject backward nil nil))) (gnus-message 9 "Searching article: %d..." gnus-current-article) ! (gnus-eval-in-buffer-window ! gnus-article-buffer ! (save-restriction ! (widen) ! (goto-char (if backward (point-max) (point-min))) ! (setq found (funcall re-search regexp nil t))))) (message "") ;; Adjust article pointer. (or (eq last gnus-current-article) *************** *** 8992,8998 **** (or total (setq gnus-newsgroup-expirable es)) ;; We go through the old list of expirable, and mark all ;; really expired articles as non-existant. ! (or (eq es expirable) ; If nothing was expired, we don't mark. (let ((gnus-use-cache nil)) (while expirable (or (memq (car expirable) es) --- 9040,9046 ---- (or total (setq gnus-newsgroup-expirable es)) ;; We go through the old list of expirable, and mark all ;; really expired articles as non-existant. ! (or (eq es expirable) ;If nothing was expired, we don't mark. (let ((gnus-use-cache nil)) (while expirable (or (memq (car expirable) es) *************** *** 9279,9285 **** (while (and (> n 0) (if unmark ! (gnus-summary-remove-process-mark (gnus-summary-article-number)) (gnus-summary-set-process-mark (gnus-summary-article-number))) (zerop (gnus-summary-next-subject (if backward -1 1) nil t))) (setq n (1- n))) --- 9327,9334 ---- (while (and (> n 0) (if unmark ! (gnus-summary-remove-process-mark ! (gnus-summary-article-number)) (gnus-summary-set-process-mark (gnus-summary-article-number))) (zerop (gnus-summary-next-subject (if backward -1 1) nil t))) (setq n (1- n))) *************** *** 9537,9544 **** (insert mark) (and plist (add-text-properties (1- (point)) (point) plist)) (and (eq type 'unread) ! (add-text-properties (1- (point)) (point) (list 'gnus-mark mark))) ! (gnus-summary-update-line (eq mark gnus-unread-mark))))) (defun gnus-mark-article-as-read (article &optional mark) "Enter ARTICLE in the pertinent lists and remove it from others." --- 9586,9594 ---- (insert mark) (and plist (add-text-properties (1- (point)) (point) plist)) (and (eq type 'unread) ! (progn ! (add-text-properties (1- (point)) (point) (list 'gnus-mark mark)) ! (gnus-summary-update-line (eq mark gnus-unread-mark))))))) (defun gnus-mark-article-as-read (article &optional mark) "Enter ARTICLE in the pertinent lists and remove it from others." *************** *** 9970,9976 **** (interactive) (gnus-set-global-variables) (let ((buffer-read-only nil) ! (orig (point)) ;; first goto end then to beg, to have point at beg after let (end (progn (end-of-line) (point))) (beg (progn (beginning-of-line) (point)))) --- 10020,10026 ---- (interactive) (gnus-set-global-variables) (let ((buffer-read-only nil) ! (orig (prog1 (point) (gnus-summary-hide-thread))) ;; first goto end then to beg, to have point at beg after let (end (progn (end-of-line) (point))) (beg (progn (beginning-of-line) (point)))) *************** *** 10013,10019 **** (goto-char end) (search-backward "\n" start t)) (subst-char-in-region start end ?\n ?\^M t) ! (forward-line -1))))) (defun gnus-summary-go-to-next-thread (&optional previous) "Go to the same level (or less) next thread. --- 10063,10070 ---- (goto-char end) (search-backward "\n" start t)) (subst-char-in-region start end ?\n ?\^M t) ! (forward-line -1) ! (gnus-summary-position-cursor))))) (defun gnus-summary-go-to-next-thread (&optional previous) "Go to the same level (or less) next thread. *************** *** 10118,10123 **** --- 10169,10176 ---- (let ((killing t) (level (gnus-summary-thread-level))) (save-excursion + ;; Expand the thread. + (gnus-summary-show-thread) (while killing ;; Mark the article... (cond ((null unmark) (gnus-summary-mark-article-as-read *************** *** 10185,10191 **** gnus-extract-address-components (mail-header-from header)))) (concat ! (downcase (gnus-simplify-subject (gnus-summary-subject-string))) "\r" (or (car extract) (cdr extract))))) 'gnus-thread-sort-by-subject) reverse)) --- 10238,10244 ---- gnus-extract-address-components (mail-header-from header)))) (concat ! (downcase (gnus-simplify-subject (gnus-summary-subject-string) t)) "\r" (or (car extract) (cdr extract))))) 'gnus-thread-sort-by-subject) reverse)) *************** *** 10612,10618 **** (define-key gnus-article-mode-map "h" 'gnus-article-show-summary) (define-key gnus-article-mode-map "s" 'gnus-article-show-summary) (define-key gnus-article-mode-map "\C-c\C-m" 'gnus-article-mail) ! (define-key gnus-article-mode-map "\C-c\C-M" 'gnus-article-mail-with-original) (define-key gnus-article-mode-map "?" 'gnus-article-describe-briefly) (define-key gnus-article-mode-map gnus-mouse-2 'gnus-article-push-button) (define-key gnus-article-mode-map "\r" 'gnus-article-press-button) --- 10665,10672 ---- (define-key gnus-article-mode-map "h" 'gnus-article-show-summary) (define-key gnus-article-mode-map "s" 'gnus-article-show-summary) (define-key gnus-article-mode-map "\C-c\C-m" 'gnus-article-mail) ! (define-key gnus-article-mode-map ! "\C-c\C-M" 'gnus-article-mail-with-original) (define-key gnus-article-mode-map "?" 'gnus-article-describe-briefly) (define-key gnus-article-mode-map gnus-mouse-2 'gnus-article-push-button) (define-key gnus-article-mode-map "\r" 'gnus-article-press-button) *************** *** 11619,11749 **** ;;; Server Communication ;;; - ;; All the Gnus backends have the same interface, and should return - ;; data in a similar format. Below is an overview of what functions - ;; these packages must supply and what results they should return. - ;; - ;; Variables: - ;; - ;; `nntp-server-buffer' - All data should be returned to Gnus in this - ;; buffer. - ;; - ;; Functions for the imaginary backend `choke': - ;; - ;; `choke-retrieve-headers ARTICLES &optional GROUP SERVER' - ;; Should return all headers for all ARTICLES, or return NOV lines for - ;; the same. - ;; - ;; `choke-request-group GROUP &optional SERVER DISCARD' - ;; Switch to GROUP. If DISCARD is nil, active information on the group - ;; must be returned. - ;; - ;; `choke-close-group GROUP &optional SERVER' - ;; Close group. Most backends won't have to do anything with this - ;; call, but it is an opportunity to clean up, if that is needed. It - ;; is called when Gnus exits a group. - ;; - ;; `choke-request-article ARTICLE &optional GROUP SERVER' - ;; Return ARTICLE, which is either an article number or - ;; message-id. Note that not all backends can return articles based on - ;; message-id. - ;; - ;; `choke-request-list SERVER' - ;; Return a list of all newsgroups on SERVER. - ;; - ;; `choke-request-list-newsgroups SERVER' - ;; Return a list of descriptions of all newsgroups on SERVER. - ;; - ;; `choke-request-newgroups DATE &optional SERVER' - ;; Return a list of all groups that have arrived after DATE on - ;; SERVER. Note that the date doesn't have to be respected - Gnus will - ;; always check whether the groups are old or not. Backends that do - ;; not store date information may just return the entire list of - ;; groups, although this might not be a good idea in general. - ;; - ;; `choke-request-post-buffer METHOD HEADER ARTICLE-BUFFER GROUP INFO' - ;; Should return a buffer that is suitable for "posting". nnspool and - ;; nntp return a `*post-buffer*', and nnmail return a `*mail*' - ;; buffer. This function should fill out the appropriate headers. - ;; - ;; `choke-request-post &optional SERVER' - ;; Function that will be called from a buffer to be posted. - ;; - ;; `choke-open-server SERVER &optional ARGUMENT' - ;; Open a connection to SERVER. - ;; - ;; `choke-close-server &optional SERVER' - ;; Close the connection to SERVER. - ;; - ;; `choke-server-opened &optional SERVER' - ;; Whether the conenction to SERVER is opened or not. - ;; - ;; `choke-server-status &optional SERVER' - ;; Should return a status string (not in the nntp buffer, but as the - ;; result of the function). - ;; - ;; `choke-retrieve-groups GROUPS &optional SERVER' - ;; Optional function for retrieving active file info on all groups in - ;; GROUPS. Two return formats are supported: The normal active file - ;; format, and a list of GROUP lines. This function should return (as - ;; a function value) either `active' or `group', depending on what - ;; format it returns. - ;; - ;; The following functions are optional and apply only to backends - ;; that are able to control the contents of their groups totally - ;; (ie. mail backends.) Backends that aren't able to do that - ;; shouldn't define these functions at all. Gnus will check for their - ;; presence before attempting to call them. - ;; - ;; `choke-request-expire-articles ARTICLES &optional NEWSGROUP SERVER' - ;; Should expire (according to some aging scheme) all ARTICLES. Most - ;; backends will not be able to expire articles. Should return a list - ;; of all articles that were not expired. - ;; - ;; `choke-request-move-article ARTICLE GROUP SERVER ACCEPT-FORM &optional LAST' - ;; Should move ARTICLE from GROUP on SERVER by using ACCEPT-FORM. - ;; Removes any information it has added to the article (extra headers, - ;; whatever - make it as clean as possible), and then passes the - ;; article on by evaling ACCEPT-FORM, which is normally a call to the - ;; function described below. If the ACCEPT-FORM returns a non-nil - ;; value, the article should then be deleted. If LAST is nil, that - ;; means that there will be further calls to this function. This might - ;; be taken as an advice not to save buffers/internal variables just - ;; yet, but wait until the last call to speed things up. - ;; - ;; `choke-request-accept-article GROUP &optional LAST' - ;; The contents of the current buffer will be put into GROUP. There - ;; should, of course, be an article in the current buffer. This - ;; function is normally only called by the function described above, - ;; and LAST works the same way as in that function. - ;; - ;; `choke-request-replace-article ARTICLE GROUP BUFFER' - ;; Replace ARTICLE in GROUP with the contents of BUFFER. - ;; This provides an easy interface for allowing editing of - ;; articles. Note that even headers may be edited, so the backend has - ;; to update any tables (nov buffers, etc) that it maintains after - ;; replacing the article. - ;; - ;; `choke-request-create-group GROUP &optional SERVER' - ;; Create GROUP on SERVER. This might be a new, empty group, or it - ;; might be a group that already exists, but hasn't been registered - ;; yet. - ;; - ;; All these functions must return nil if they couldn't service the - ;; request. If the optional arguments are not supplied, some "current" - ;; or "default" values should be used. In short, one should emulate an - ;; NNTP server, in a way. - ;; - ;; If you want to write a new backend, you just have to supply the - ;; functions listed above. In addition, you must enter the new backend - ;; into the list of valid select methods: - ;; (setq gnus-valid-select-methods - ;; (cons '("choke" mail) gnus-valid-select-methods)) - ;; The first element in this list is the name of the backend. Other - ;; elemnets may be `mail' (for mail groups), `post' (for news - ;; groups), `none' (neither), `respool' (for groups that can control - ;; their contents). - (defun gnus-start-news-server (&optional confirm) "Open a method for getting news. If CONFIRM is non-nil, the user will be asked for an NNTP server." --- 11673,11678 ---- *************** *** 11872,11878 **** (defun gnus-request-group (group &optional dont-check) (let ((method (gnus-find-method-for-group group))) - ; (and t (message "%s GROUP %s" (car method) group)) (funcall (gnus-get-function method 'request-group) (gnus-group-real-name group) (nth 1 method) dont-check))) --- 11801,11806 ---- *************** *** 11920,11925 **** --- 11848,11858 ---- (funcall (gnus-get-function method 'request-head) article (gnus-group-real-name group) (nth 1 method)))) + (defun gnus-request-body (article group) + (let ((method (gnus-find-method-for-group group))) + (funcall (gnus-get-function method 'request-body) + article (gnus-group-real-name group) (nth 1 method)))) + ;; Fix by Sudish Joseph . (defun gnus-request-post-buffer (post group subject header artbuf info follow-to respect-poster) *************** *** 12097,12109 **** (gnus-update-format-specifications) - ;; Find the number of unread articles in each non-dead group. - (let ((gnus-read-active-file (and (not level) gnus-read-active-file))) - (gnus-get-unread-articles (or level (1+ gnus-level-subscribed)))) ;; Find new newsgroups and treat them. (if (and init gnus-check-new-newsgroups gnus-read-active-file (not level) (gnus-server-opened gnus-select-method)) (gnus-find-new-newsgroups)) (if (and init gnus-check-bogus-newsgroups gnus-read-active-file (not level) (gnus-server-opened gnus-select-method)) --- 12030,12044 ---- (gnus-update-format-specifications) ;; Find new newsgroups and treat them. (if (and init gnus-check-new-newsgroups gnus-read-active-file (not level) (gnus-server-opened gnus-select-method)) (gnus-find-new-newsgroups)) + + ;; Find the number of unread articles in each non-dead group. + (let ((gnus-read-active-file (and (not level) gnus-read-active-file))) + (gnus-get-unread-articles (or level (1+ gnus-level-subscribed)))) + (if (and init gnus-check-bogus-newsgroups gnus-read-active-file (not level) (gnus-server-opened gnus-select-method)) *************** *** 12120,12126 **** (gnus-ask-server-for-new-groups) (let ((groups 0) group new-newsgroups) ! (gnus-message 5 "Checking for new newsgroups...") (or gnus-have-read-active-file (gnus-read-active-file)) (setq gnus-newsrc-last-checked-date (current-time-string)) (if (not gnus-killed-hashtb) (gnus-make-hashtable-from-killed)) --- 12055,12061 ---- (gnus-ask-server-for-new-groups) (let ((groups 0) group new-newsgroups) ! (gnus-message 5 "Looking for new newsgroups...") (or gnus-have-read-active-file (gnus-read-active-file)) (setq gnus-newsrc-last-checked-date (current-time-string)) (if (not gnus-killed-hashtb) (gnus-make-hashtable-from-killed)) *************** *** 12668,12674 **** (let ((method (gnus-find-method-for-group group)) active) (and (gnus-check-server method) ! ;; We escape all bugs and quits here to make it possible to ;; continue if a group is so out-there that it reports bugs ;; and stuff. (condition-case () --- 12603,12609 ---- (let ((method (gnus-find-method-for-group group)) active) (and (gnus-check-server method) ! ;; We escape all bugs and quit here to make it possible to ;; continue if a group is so out-there that it reports bugs ;; and stuff. (condition-case () *************** *** 12817,12832 **** (setq newsrc (cdr newsrc))) (gnus-check-server method) (setq list-type (gnus-retrieve-groups groups method)) ! (cond ((not list-type) ! (gnus-message ! 1 "Cannot read partial active file from %s server." ! (car method)) ! (ding) ! (sit-for 2)) ! ((eq list-type 'active) ! (gnus-active-to-gnus-format method gnus-active-hashtb)) ! (t ! (gnus-groups-to-gnus-format method gnus-active-hashtb))))) (t (if (not (gnus-request-list method)) (progn --- 12752,12768 ---- (setq newsrc (cdr newsrc))) (gnus-check-server method) (setq list-type (gnus-retrieve-groups groups method)) ! (cond ! ((not list-type) ! (gnus-message ! 1 "Cannot read partial active file from %s server." ! (car method)) ! (ding) ! (sit-for 2)) ! ((eq list-type 'active) ! (gnus-active-to-gnus-format method gnus-active-hashtb)) ! (t ! (gnus-groups-to-gnus-format method gnus-active-hashtb))))) (t (if (not (gnus-request-list method)) (progn *************** *** 13080,13086 **** (cdr (cdr group)))) gnus-newsrc-alist))) (if (setq m (assoc (car group) marked)) ! (setcdr (cdr (cdr info)) (cons (list (cons 'tick (cdr m))) nil)))) (setq newsrc (cdr newsrc))) (setq newsrc killed) (while newsrc --- 13016,13023 ---- (cdr (cdr group)))) gnus-newsrc-alist))) (if (setq m (assoc (car group) marked)) ! (setcdr (cdr (cdr info)) ! (cons (list (cons 'tick (cdr m))) nil)))) (setq newsrc (cdr newsrc))) (setq newsrc killed) (while newsrc *************** *** 13096,13102 **** (and (not (string-match "^ *options" gnus-newsrc-options)) (setq gnus-newsrc-options (concat "options " gnus-newsrc-options))) (and (not (string-match "\n$" gnus-newsrc-options)) ! (setq gnus-newsrc-options (concat gnus-newsrc-options "\n"))))) (setq gnus-newsrc-alist (nreverse gnus-newsrc-alist)) (gnus-make-hashtable-from-newsrc-alist))) --- 13033,13043 ---- (and (not (string-match "^ *options" gnus-newsrc-options)) (setq gnus-newsrc-options (concat "options " gnus-newsrc-options))) (and (not (string-match "\n$" gnus-newsrc-options)) ! (setq gnus-newsrc-options (concat gnus-newsrc-options "\n"))) ! ;; Finally, if we read some options lines, we parse them. ! (or (string= gnus-newsrc-options "") ! (gnus-newsrc-parse-options gnus-newsrc-options)))) ! (setq gnus-newsrc-alist (nreverse gnus-newsrc-alist)) (gnus-make-hashtable-from-newsrc-alist))) *************** *** 13227,13236 **** (setq reads (cons num1 reads)) (setq reads (cons ! (cons num1 (progn ! (narrow-to-region (match-beginning 0) ! (match-end 0)) ! (read buf))) reads)) (widen))) ;; It was just a simple number, so we add it to the --- 13168,13178 ---- (setq reads (cons num1 reads)) (setq reads (cons ! (cons num1 ! (progn ! (narrow-to-region (match-beginning 0) ! (match-end 0)) ! (read buf))) reads)) (widen))) ;; It was just a simple number, so we add it to the *************** *** 13245,13251 **** (t ;; Not numbers and not eol, so this might be a buggy ;; line... ! (or (eobp) ; If it was eob instead of ?\n, we allow it. (progn ;; The line was buggy. (setq group nil) --- 13187,13194 ---- (t ;; Not numbers and not eol, so this might be a buggy ;; line... ! (or (eobp) ! ;; If it was eob instead of ?\n, we allow it. (progn ;; The line was buggy. (setq group nil) *************** *** 14068,14074 **** score-files) ;; if this group has been seen before, return the cached entry (if (setq score-files (assoc group gnus-score-file-alist-cache)) ! (cdr score-files) ; ensures caching of groups with no matches ;; handle the multiple match alist (while alist (and (string-match (car (car alist)) group) --- 14011,14017 ---- score-files) ;; if this group has been seen before, return the cached entry (if (setq score-files (assoc group gnus-score-file-alist-cache)) ! (cdr score-files) ;ensures caching groups with no matches ;; handle the multiple match alist (while alist (and (string-match (car (car alist)) group) *** pub/dgnus/lisp/nnbabyl.el Thu Aug 31 12:54:40 1995 --- dgnus/lisp/nnbabyl.el Sun Sep 10 00:50:45 1995 *************** *** 246,251 **** --- 246,252 ---- (save-excursion (set-buffer nnbabyl-mbox-buffer) + (set-text-properties (point-min) (point-max) nil) (while (and articles is-old) (goto-char (point-min)) (if (search-forward (nnbabyl-article-string (car articles)) nil t) *************** *** 480,485 **** --- 481,489 ---- (nnheader-find-file-noselect nnbabyl-mbox-file nil 'raw))) (buffer-disable-undo (current-buffer)) + (widen) + (setq buffer-read-only nil) + (fundamental-mode) (goto-char (point-min)) (re-search-forward delim nil t) *************** *** 521,548 **** (progn (and gnus-verbose-backends (message "nnbabyl: Reading incoming mail...")) ! (setq incoming ! (nnmail-move-inbox ! (car spools) (concat nnbabyl-mbox-file "-Incoming"))) ! (setq incomings (cons incoming incomings)) ! (save-excursion ! (setq group (nnmail-get-split-group (car spools) group-in)) ! (let* ((nnmail-prepare-incoming-hook ! (cons 'nnbabyl-remove-incoming-delims ! nnmail-prepare-incoming-hook)) ! in-buf) ! (setq in-buf (nnmail-split-incoming ! incoming 'nnbabyl-save-mail t group)) ! (set-buffer in-buf) ! (goto-char (point-min)) ! (while (search-forward "\n\^_\n" nil t) ! (delete-char -1)) ! (set-buffer nnbabyl-mbox-buffer) ! (goto-char (point-max)) ! (search-backward "\n\^_" nil t) ! (goto-char (match-end 0)) ! (insert-buffer-substring in-buf) ! (kill-buffer in-buf))))) (setq spools (cdr spools))) ;; If we did indeed read any incoming spools, we save all info. (and (buffer-modified-p nnbabyl-mbox-buffer) --- 525,554 ---- (progn (and gnus-verbose-backends (message "nnbabyl: Reading incoming mail...")) ! (if (not (setq incoming ! (nnmail-move-inbox ! (car spools) ! (concat nnbabyl-mbox-file "-Incoming")))) ! () ! (setq incomings (cons incoming incomings)) ! (save-excursion ! (setq group (nnmail-get-split-group (car spools) group-in)) ! (let* ((nnmail-prepare-incoming-hook ! (cons 'nnbabyl-remove-incoming-delims ! nnmail-prepare-incoming-hook)) ! in-buf) ! (setq in-buf (nnmail-split-incoming ! incoming 'nnbabyl-save-mail t group)) ! (set-buffer in-buf) ! (goto-char (point-min)) ! (while (search-forward "\n\^_\n" nil t) ! (delete-char -1)) ! (set-buffer nnbabyl-mbox-buffer) ! (goto-char (point-max)) ! (search-backward "\n\^_" nil t) ! (goto-char (match-end 0)) ! (insert-buffer-substring in-buf) ! (kill-buffer in-buf)))))) (setq spools (cdr spools))) ;; If we did indeed read any incoming spools, we save all info. (and (buffer-modified-p nnbabyl-mbox-buffer) *** pub/dgnus/lisp/nnfolder.el Thu Aug 31 12:54:40 1995 --- dgnus/lisp/nnfolder.el Sun Sep 10 00:50:40 1995 *************** *** 612,618 **** (setq activenumber (max activenumber newnum)) (setq activemin (min activemin newnum)))) (setcar active (min activemin activenumber)) ! (setcdr active activenumber) (goto-char (point-min)))) ;; Keep track of the active number on our own, and insert it back into --- 612,618 ---- (setq activenumber (max activenumber newnum)) (setq activemin (min activemin newnum)))) (setcar active (min activemin activenumber)) ! (setcdr active (max activenumber (cdr active))) (goto-char (point-min)))) ;; Keep track of the active number on our own, and insert it back into *************** *** 637,648 **** (progn (narrow-to-region start end) (nnmail-insert-lines) ! (setq activenumber (1+ activenumber)) ! (nnfolder-insert-newsgroup-line (cons nil activenumber)) (widen)))) ;; Make absolutely sure that the active list reflects reality! - (setcdr active activenumber) (nnmail-save-active nnfolder-group-alist nnfolder-active-file) (current-buffer)))) --- 637,647 ---- (progn (narrow-to-region start end) (nnmail-insert-lines) ! (nnfolder-insert-newsgroup-line ! (cons nil (nnfolder-active-number nnfolder-current-group))) (widen)))) ;; Make absolutely sure that the active list reflects reality! (nnmail-save-active nnfolder-group-alist nnfolder-active-file) (current-buffer)))) *************** *** 664,677 **** (progn (and gnus-verbose-backends (message "nnfolder: Reading incoming mail...")) ! (setq incoming ! (nnmail-move-inbox ! (car spools) ! (concat (file-name-as-directory nnfolder-directory) ! "Incoming"))) ! (setq incomings (cons incoming incomings)) ! (setq group (nnmail-get-split-group (car spools) group-in)) ! (nnmail-split-incoming incoming 'nnfolder-save-mail nil group))) (setq spools (cdr spools))) ;; If we did indeed read any incoming spools, we save all info. (if incoming --- 663,677 ---- (progn (and gnus-verbose-backends (message "nnfolder: Reading incoming mail...")) ! (if (not (setq incoming ! (nnmail-move-inbox ! (car spools) ! (concat (file-name-as-directory nnfolder-directory) ! "Incoming")))) ! () ! (setq incomings (cons incoming incomings)) ! (setq group (nnmail-get-split-group (car spools) group-in)) ! (nnmail-split-incoming incoming 'nnfolder-save-mail nil group)))) (setq spools (cdr spools))) ;; If we did indeed read any incoming spools, we save all info. (if incoming *** pub/dgnus/lisp/nnheader.el Thu Aug 31 12:54:40 1995 --- dgnus/lisp/nnheader.el Mon Sep 11 06:05:00 1995 *************** *** 66,91 **** "Set article author of HEADER to FROM." (` (aset (, header) 2 (, from)))) - (defalias 'nntp-header-xref 'mail-header-xref) - (defmacro mail-header-xref (header) - "Return xref string in HEADER." - (` (aref (, header) 8))) - - (defalias 'nntp-set-header-xref 'mail-header-set-xref) - (defmacro mail-header-set-xref (header xref) - "Set article xref of HEADER to xref." - (` (aset (, header) 8 (, xref)))) - - (defalias 'nntp-header-lines 'mail-header-lines) - (defmacro mail-header-lines (header) - "Return lines in HEADER." - (` (aref (, header) 7))) - - (defalias 'nntp-set-header-lines 'mail-header-set-lines) - (defmacro mail-header-set-lines (header lines) - "Set article lines of HEADER to LINES." - (` (aset (, header) 7 (, lines)))) - (defalias 'nntp-header-date 'mail-header-date) (defmacro mail-header-date (header) "Return date in HEADER." --- 66,71 ---- *************** *** 126,131 **** --- 106,132 ---- "Set number of chars in article of HEADER to CHARS." (` (aset (, header) 6 (, chars)))) + (defalias 'nntp-header-lines 'mail-header-lines) + (defmacro mail-header-lines (header) + "Return lines in HEADER." + (` (aref (, header) 7))) + + (defalias 'nntp-set-header-lines 'mail-header-set-lines) + (defmacro mail-header-set-lines (header lines) + "Set article lines of HEADER to LINES." + (` (aset (, header) 7 (, lines)))) + + (defalias 'nntp-header-xref 'mail-header-xref) + (defmacro mail-header-xref (header) + "Return xref string in HEADER." + (` (aref (, header) 8))) + + (defalias 'nntp-set-header-xref 'mail-header-set-xref) + (defmacro mail-header-set-xref (header xref) + "Set article xref of HEADER to xref." + (` (aset (, header) 8 (, xref)))) + + ;; Various cruft the backends and Gnus need to communicate. (defvar nntp-server-buffer nil) *************** *** 337,342 **** --- 338,355 ---- (after-find-file error (not nowarn))))) buf))) + (defun nnheader-insert-references (references message-id) + ;; Fold long references line to follow RFC1036. + (mail-position-on-field "References") + (let ((begin (gnus-point-at-bol)) + (fill-column 78) + (fill-prefix "\t")) + (if references (insert references)) + (if (and references message-id) (insert " ")) + (if message-id (insert message-id)) + ;; The region must end with a newline to fill the region + ;; without inserting extra newline. + (fill-region-as-paragraph begin (1+ (point))))) (provide 'nnheader) *** pub/dgnus/lisp/nnmail.el Thu Aug 31 12:54:40 1995 --- dgnus/lisp/nnmail.el Sun Sep 10 00:08:04 1995 *************** *** 53,59 **** the argument. It should return a non-nil value if it thinks that the mail belongs in that group. ! The last element should always have \"\" as the regexp.") ;; Suggested by Erik Selberg . (defvar nnmail-crosspost t --- 53,61 ---- the argument. It should return a non-nil value if it thinks that the mail belongs in that group. ! The last element should always have \"\" as the regexp. ! ! This variable can also have a function as its value.") ;; Suggested by Erik Selberg . (defvar nnmail-crosspost t *************** *** 222,228 **** info follow-to respect-poster) (let ((method-address (cdr (assq 'to-address (nth 5 info)))) from date to reply-to message-of ! references message-id sender cc sendto elt) (setq method-address (if (and (stringp method-address) (string= method-address "")) --- 224,230 ---- info follow-to respect-poster) (let ((method-address (cdr (assq 'to-address (nth 5 info)))) from date to reply-to message-of ! references message-id cc new-cc sendto elt) (setq method-address (if (and (stringp method-address) (string= method-address "")) *************** *** 255,263 **** (setq message-of (concat (if stop-pos (substring from 0 stop-pos) from) "'s message of " date)))) ! (setq sender (mail-fetch-field "sender")) ! (setq cc (mail-fetch-field "cc")) ! (setq to (mail-fetch-field "to")) (setq subject (mail-header-subject header)) (or (string-match "^[Rr][Ee]:" subject) (setq subject (concat "Re: " subject))) --- 257,267 ---- (setq message-of (concat (if stop-pos (substring from 0 stop-pos) from) "'s message of " date)))) ! (setq cc (mail-strip-quoted-names (mail-fetch-field "cc"))) ! (setq to (mail-strip-quoted-names (mail-fetch-field "to"))) ! (setq new-cc (rmail-dont-reply-to ! (concat (or to "") ! (if cc (concat (if to ", " "") cc) "")))) (setq subject (mail-header-subject header)) (or (string-match "^[Rr][Ee]:" subject) (setq subject (concat "Re: " subject))) *************** *** 274,285 **** (while (setq elt (assoc "To" follow-to)) (setq sendto (concat sendto (and sendto ", ") (cdr elt))) (setq follow-to (delq elt follow-to)))) ! (mail-setup (if (and follow-to (listp follow-to)) sendto ! (or method-address ! (concat (or sender reply-to from "") ! (if to (concat ", " to) "") ! (if cc (concat ", " cc) "")))) ! subject message-of nil article-buffer nil) (auto-save-mode auto-save-default) ;; Note that "To" elements should already be in the message. (if (and follow-to (listp follow-to)) --- 278,289 ---- (while (setq elt (assoc "To" follow-to)) (setq sendto (concat sendto (and sendto ", ") (cdr elt))) (setq follow-to (delq elt follow-to)))) ! (mail-setup (if (and follow-to (listp follow-to)) ! sendto ! (or method-address reply-to from "")) ! subject message-of ! (if (zerop (length new-cc)) nil new-cc) ! article-buffer nil) (auto-save-mode auto-save-default) ;; Note that "To" elements should already be in the message. (if (and follow-to (listp follow-to)) *************** *** 292,308 **** (insert (car (car follow-to)) ": " (cdr (car follow-to)) "\n") (setq follow-to (cdr follow-to))))) ! ;; Fold long references line to follow RFC1036. ! (mail-position-on-field "References") ! (let ((begin (- (point) (length "References: "))) ! (fill-column 78) ! (fill-prefix "\t")) ! (if references (insert references)) ! (if (and references message-id) (insert " ")) ! (if message-id (insert message-id)) ! ;; The region must end with a newline to fill the region ! ;; without inserting extra newline. ! (fill-region-as-paragraph begin (1+ (point)))))) (current-buffer)))) (defun nnmail-find-file (file) --- 296,302 ---- (insert (car (car follow-to)) ": " (cdr (car follow-to)) "\n") (setq follow-to (cdr follow-to))))) ! (nnheader-insert-references references message-id))) (current-buffer)))) (defun nnmail-find-file (file) *** pub/dgnus/lisp/nnmbox.el Thu Aug 31 12:54:40 1995 --- dgnus/lisp/nnmbox.el Sun Sep 10 00:50:38 1995 *************** *** 472,489 **** (progn (and gnus-verbose-backends (message "nnmbox: Reading incoming mail...")) ! (setq incoming ! (nnmail-move-inbox ! (car spools) (concat nnmbox-mbox-file "-Incoming"))) ! (setq incomings (cons incoming incomings)) ! (save-excursion ! (setq group (nnmail-get-split-group (car spools) group-in)) ! (let ((in-buf (nnmail-split-incoming ! incoming 'nnmbox-save-mail t group))) ! (set-buffer nnmbox-mbox-buffer) ! (goto-char (point-max)) ! (insert-buffer-substring in-buf) ! (kill-buffer in-buf))))) (setq spools (cdr spools))) ;; If we did indeed read any incoming spools, we save all info. (and (buffer-modified-p nnmbox-mbox-buffer) --- 472,491 ---- (progn (and gnus-verbose-backends (message "nnmbox: Reading incoming mail...")) ! (if (not (setq incoming ! (nnmail-move-inbox ! (car spools) ! (concat nnmbox-mbox-file "-Incoming")))) ! () ! (setq incomings (cons incoming incomings)) ! (save-excursion ! (setq group (nnmail-get-split-group (car spools) group-in)) ! (let ((in-buf (nnmail-split-incoming ! incoming 'nnmbox-save-mail t group))) ! (set-buffer nnmbox-mbox-buffer) ! (goto-char (point-max)) ! (insert-buffer-substring in-buf) ! (kill-buffer in-buf)))))) (setq spools (cdr spools))) ;; If we did indeed read any incoming spools, we save all info. (and (buffer-modified-p nnmbox-mbox-buffer) *** pub/dgnus/lisp/nnmh.el Thu Aug 31 12:54:40 1995 --- dgnus/lisp/nnmh.el Sun Sep 10 00:50:41 1995 *************** *** 422,434 **** (progn (and gnus-verbose-backends (message "nnmh: Reading incoming mail...")) ! (setq incoming ! (nnmail-move-inbox ! (car spools) (concat (file-name-as-directory nnmh-directory) ! "Incoming"))) ! (setq incomings (cons incoming incomings)) ! (setq group (nnmail-get-split-group (car spools) group-in)) ! (nnmail-split-incoming incoming 'nnmh-save-mail nil group))) (setq spools (cdr spools))) ;; If we did indeed read any incoming spools, we save all info. (if incoming --- 422,436 ---- (progn (and gnus-verbose-backends (message "nnmh: Reading incoming mail...")) ! (if (not (setq incoming ! (nnmail-move-inbox ! (car spools) ! (concat (file-name-as-directory nnmh-directory) ! "Incoming")))) ! () ! (setq incomings (cons incoming incomings)) ! (setq group (nnmail-get-split-group (car spools) group-in)) ! (nnmail-split-incoming incoming 'nnmh-save-mail nil group)))) (setq spools (cdr spools))) ;; If we did indeed read any incoming spools, we save all info. (if incoming *** pub/dgnus/lisp/nnml.el Thu Aug 31 12:54:40 1995 --- dgnus/lisp/nnml.el Sun Sep 10 00:50:44 1995 *************** *** 500,511 **** (progn (and gnus-verbose-backends (message "nnml: Reading incoming mail...")) ! (setq incoming ! (nnmail-move-inbox ! (car spools) (concat nnml-directory "Incoming"))) ! (setq group (nnmail-get-split-group (car spools) group-in)) ! (nnmail-split-incoming incoming 'nnml-save-mail nil group) ! (setq incomings (cons incoming incomings)))) (setq spools (cdr spools))) ;; If we did indeed read any incoming spools, we save all info. (if incoming --- 500,512 ---- (progn (and gnus-verbose-backends (message "nnml: Reading incoming mail...")) ! (if (not (setq incoming ! (nnmail-move-inbox ! (car spools) (concat nnml-directory "Incoming")))) ! () ! (setq group (nnmail-get-split-group (car spools) group-in)) ! (nnmail-split-incoming incoming 'nnml-save-mail nil group) ! (setq incomings (cons incoming incomings))))) (setq spools (cdr spools))) ;; If we did indeed read any incoming spools, we save all info. (if incoming *** pub/dgnus/lisp/nntp.el Thu Aug 31 12:54:40 1995 --- dgnus/lisp/nntp.el Fri Sep 8 00:10:27 1995 *************** *** 639,645 **** (setq followup-to (mail-fetch-field "followup-to")) (if (or (null respect-poster) ;Ignore followup-to: field. (string-equal "" followup-to) ;Bogus header. ! (string-equal "poster" followup-to)) ;Poster (setq followup-to nil)) (setq newsgroups (or follow-to followup-to (mail-fetch-field "newsgroups"))) --- 639,649 ---- (setq followup-to (mail-fetch-field "followup-to")) (if (or (null respect-poster) ;Ignore followup-to: field. (string-equal "" followup-to) ;Bogus header. ! (string-equal "poster" followup-to);Poster ! (and (eq respect-poster 'ask) ! followup-to ! (y-or-n-p (concat "Followup to " ! followup-to "? ")))) (setq followup-to nil)) (setq newsgroups (or follow-to followup-to (mail-fetch-field "newsgroups"))) *************** *** 663,679 **** (insert (car (car newsgroups)) ": " (cdr (car newsgroups)) "\n") (setq newsgroups (cdr newsgroups))))) ! ;; Fold long references line to follow RFC1036. ! (mail-position-on-field "References") ! (let ((begin (- (point) (length "References: "))) ! (fill-column 79) ! (fill-prefix "\t")) ! (if references (insert references)) ! (if (and references message-id) (insert " ")) ! (if message-id (insert message-id)) ! ;; The region must end with a newline to fill the region ! ;; without inserting extra newline. ! (fill-region-as-paragraph begin (1+ (point)))) (if distribution (progn (mail-position-on-field "Distribution") --- 667,673 ---- (insert (car (car newsgroups)) ": " (cdr (car newsgroups)) "\n") (setq newsgroups (cdr newsgroups))))) ! (nnheader-insert-references references message-id) (if distribution (progn (mail-position-on-field "Distribution") *** pub/dgnus/lisp/ChangeLog Thu Aug 31 12:54:42 1995 --- dgnus/lisp/ChangeLog Sun Sep 10 01:15:03 1995 *************** *** 1,4 **** --- 1,166 ---- + Sun Sep 10 00:39:41 1995 Lars Ingebrigtsen + + * gnus-msg.el (gnus-post-news): Set the name of the newsgroup for + later use. + + * gnus.el (gnus-group-unsubscribe-group): Don't accept empty group + names. + + * nnbabyl.el (nnbabyl-get-new-mail): If moving is unsuccessful, + don't pretend it went ok. + * nnmbox.el (nnmbox-get-new-mail): Ditto. + * nnfolder.el (nnfolder-get-new-mail): Ditto. + * nnmh.el (nnmh-get-new-mail): Ditto. + * nnml.el (nnml-get-new-mail): Ditto. + + * gnus-vis.el (gnus-group-menu-hook, gnus-summary-menu-hook, + gnus-article-menu-hook, gnus-server-menu-hook, + gnus-browse-menu-hook): New hooks. + + Fri Sep 8 19:08:29 1995 Per Abrahamsen + + * nnmail.el (nnmail-request-post-buffer): Newer send to `sender', + don't put everything in the `To' header, filter the `CC' header + through `rmail-dont-reply-to'. + + Fri Sep 8 20:42:27 1995 Lars Ingebrigtsen + + * gnus.el (gnus-group-make-archive-group): Wrong interactive spec. + (gnus-select-method): Take `gnus-nntp-service' into account for + backwards compatability. + + Thu Sep 7 22:17:33 1995 Lars Ingebrigtsen + + * gnus.el (gnus-setup-news): Find new groups before finding + numbers of unread articles in the groups. + + * gnus-score.el (gnus-summary-score-entry): Fuzzy wrong match + value. + + * gnus.el ('gnus-load-hook): Run this hook while loading. + + * gnus-vis.el (gnus-summary-make-menu-bar): Would re-generate the + summary buffers on each group entry. + + * gnus-score.el (gnus-score-save): Don't try to write a score file + unless one can. + + Wed Sep 6 20:38:43 1995 Per Abrahamsen + + * gnus-cite.el (gnus-cite-parse-max-size): New variable. + (gnus-cite-parse-maybe): Use it. + (gnus-cite-parse): Move parser initialization to + `gnus-cite-parse-maybe' and reformat. + * gnus-vis.el (gnus-article-add-buttons): Force citation parsing + if called interactively. + * gnus-cite.el (gnus-article-highlight-citation): Ditto. + (gnus-article-hide-citation): Ditto. + (gnus-article-hide-citation-maybe): Ditto. + (gnus-article-highlight): Ditto. + (gnus-article-highlight-some): Ditto. + (gnus-article-hide): Ditto. + + Thu Sep 7 00:52:36 1995 Lars Ingebrigtsen + + * gnus.el (gnus-summary-show-thread): Expand hidden subthreads as + well. + + Wed Sep 6 20:38:43 1995 Per Abrahamsen + + * gnus-msg.el (gnus-use-followup-to): New value `ask' will make + Gnus always ask before obeying the followup-to header. Changed + default to t to confirm with the Seal. + (gnus-summary-followup): Support `ask' value of + `gnus-use-followup-to'. + * nntp.el (nntp-request-post-buffer): Support `ask' value of + `gnus-use-followup-to'. + * gnus.texi (Post): Document `ask' value of + `gnus-use-followup-to'. + + Thu Sep 7 00:20:44 1995 Lars Ingebrigtsen + + * gnus.el (gnus-select-newsgroup): Checked the server twice. + (gnus-select-newsgroup): Wouldn't respond properly to unwell + groups. + + Wed Sep 6 00:11:00 1995 Lars Ingebrigtsen + + * gnus.el (gnus-read-old-newsrc-el-file): Didn't parse options + lines from the .el file. + (gnus-summary-prepare-threads): When using empty make-false-root, + and the subject changed, that wouldn't be reflected in the summary + buffer. + + * nnfolder.el (nnfolder-read-folder): Make absofuckinutely sure + that active numbers never, ever decrease. + + * nnbabyl.el (nnbabyl-request-expire-articles): Remove all text + props. + (nnbabyl-read-mbox): If an rmail buffer is in rmail mode, make it + ordinary. + + * gnus.el (gnus-summary-kill-thread): Did not kill hidden + threads. + + * gnus-uu.el (gnus-uu-save-article): Didn't remove text props. + + * gnus.el (gnus-group-make-articles-read): Would not do + crosspostings in one obscure instance. + (gnus-summary-update-mark): Would compute score-markedness even + when setting the process mark. + + Tue Sep 5 21:50:33 1995 Lars Ingebrigtsen + + * gnus-msg.el (gnus-inews-news): Would choke on trailing + commands. Also used `replace-regexp'. + (gnus-inews-news): Would, for some reason, fold all lines + sometimes. + + * gnus-ems.el: Force our definition of `set-text-properties'. So + there! + + * gnus.el (gnus-summary-sort-by-subject): Sorted oddly for (1/2) + stuff. + (gnus-request-body): Had gone missing for some reason. + (gnus-group-exit): Would quit out of an empty group buffer without + confirmation. + + Mon Sep 4 00:44:38 1995 Per Abrahamsen + + * custom.el (custom-field-face): Check that the face is defined. + (custom-face-tag): New function. + (custom-group-accept): Use it. + (custom-group-insert): Ditto. + (custom-type-properties): Give `face->other' a default value. + (custom-facep): New function. + (custom-face-lookup): Use it. + + Sun Sep 3 19:36:29 1995 Per Abrahamsen + + * custom.el (custom-local-type-properties): Added extra line of + documentation. + (custom-valid, custom-const-valid): Changed legal to valid in doc + string. + (custom-match): More documentation. + (custom-field-update): Doc. clarification. + (custom-field-accept): Ditto. + (custom-type-properties): More documentation. + + Fri Sep 1 15:39:56 1995 Per Abrahamsen + + * custom.el (menu-bar): Added XEmacs and Emacs 19.28 support. + + Fri Sep 1 15:39:56 1995 Per Abrahamsen + + * custom.el (plist-put): Fixed bogus definition. + + Thu Aug 31 15:21:23 1995 Per Abrahamsen + + * gnus-cus.el: Removed dead code. + Thu Aug 31 10:45:26 1995 Lars Magne Ingebrigtsen + + * gnus.el: 5.0 is released. * gnus-cus.el (gnus-face-dark-name-list): Use dark blue instead of sky blue. *** pub/dgnus/texi/Makefile Thu Aug 31 12:54:43 1995 --- dgnus/texi/Makefile Mon Sep 11 05:50:05 1995 *************** *** 1,7 **** TEXI2DVI=texi2dvi EMACS=emacs MAKEINFO=$(EMACS) -batch -q -no-site-file gnus.texi -l texinfmt -f texinfo-every-node-update -f texinfo-format-buffer -f save-buffer ! # MAKEINFO=makeinfo -o gnus gnus.texi LATEX=latex all: gnus.info refcard.dvi --- 1,7 ---- TEXI2DVI=texi2dvi EMACS=emacs MAKEINFO=$(EMACS) -batch -q -no-site-file gnus.texi -l texinfmt -f texinfo-every-node-update -f texinfo-format-buffer -f save-buffer ! # MAKEINFO=makeinfo -o gnus.info gnus.texi LATEX=latex all: gnus.info refcard.dvi *** pub/dgnus/texi/gnus.texi Thu Aug 31 12:54:43 1995 --- dgnus/texi/gnus.texi Mon Sep 11 07:59:44 1995 *************** *** 89,95 **** * Various:: General purpose settings. * Customization:: Tailoring Gnus to your needs. * Troubleshooting:: What you might try if things do not work. ! * The End:: Farewell, and goodbye. * Index:: Variable, function and concept index. * Key Index:: Key Index. @end menu --- 89,96 ---- * Various:: General purpose settings. * Customization:: Tailoring Gnus to your needs. * Troubleshooting:: What you might try if things do not work. ! * The End:: Farewell and goodbye. ! * Appendix:: Technical stuff for technical people. * Index:: Variable, function and concept index. * Key Index:: Key Index. @end menu *************** *** 114,123 **** distribution point for the new and spiffy versions of Gnus, also know as The Site That Destroys Newsrcs And Drives People Mad. ! @dfn{(ding)}, is, of course, short for @dfn{ding is not Gnus}, which is ! a total and utter lie, but who cares? (Besides, the "Gnus" in this ! abbreviation should probably be pronounced "news" as UMEDA intended, ! which makes it a more appropriate name, don't you think?) In any case, after spending all that energy with coming up with a new and spiffy name, we decided that the name was @emph{too} spiffy, so we --- 115,126 ---- distribution point for the new and spiffy versions of Gnus, also know as The Site That Destroys Newsrcs And Drives People Mad. ! During the first extended alpha period of develpment, the new Gnus was ! called "(ding) Gnus". @dfn{(ding)}, is, of course, short for @dfn{ding ! is not Gnus}, which is a total and utter lie, but who cares? (Besides, ! the "Gnus" in this abbreviation should probably be pronounced "news" as ! UMEDA intended, which makes it a more appropriate name, don't you ! think?) In any case, after spending all that energy with coming up with a new and spiffy name, we decided that the name was @emph{too} spiffy, so we *************** *** 130,137 **** @menu * Why?:: What's the point of Gnus? * Compatibility:: Just how compatible is Gnus with @sc{gnus}? * Contributors:: Oodles of people. ! * New Features:: A short description of all the new stuff in Gnus. * Newest Features:: Features so new that they haven't been written yet. @end menu --- 133,141 ---- @menu * Why?:: What's the point of Gnus? * Compatibility:: Just how compatible is Gnus with @sc{gnus}? + * Conformity:: Gnus tries to conform to all standards. * Contributors:: Oodles of people. ! * New Features:: Pointers to some of the new stuff in Gnus. * Newest Features:: Features so new that they haven't been written yet. @end menu *************** *** 228,233 **** --- 232,285 ---- anyway, so you might have to wait longer if you mail XEmacs questions to me. + + @node Conformity + @section Conformity + + No rebels without a clue here, ma'am. We conform to all standards known + to man. Except, of course, where we disagree with the standards and/or + conventions. + + @table @strong + + @item RFC 822 + There are no known breaches to this standard. + + @item RFC 1036 + There are no known breaches to this standard, either. + + @item Usenet Seal of Approval + Gnus hasn't been formally through the Seal process, but I have read + through the Seal text, and I think that Gnus would pass. + + @item Son-of-RFC 1036 + We do have some breaches to this one. + + @table @emph + @item MIME + Gnus does no MIME handling, and this standard-to-be seems to think that + MIME is the bees' knees, so we have major breakage here. + @item X-Newsreader + This is considered to be a "vanity header", while I consider it to be + consumer information. After seeing so many badly formatted articles + coming from @code{tin} and @code{Netscape} I know not to use either of + those for posting articles. I would not have known that if it wasn't + for the @code{X-Newsreader} header. + @item References + Gnus does line breaking on this header. I infer from RFC1036 that being + conservative in what you output is not creating 5000-character lines, so + it seems like a good idea to me. However, this standard-to-be says that + whitespace in the @code{References} header is to be preserved, so... It + doesn't matter one way or the other to Gnus, so if somebody tells me + what The Way is, I'll change it. Or not. + @end table + + @end table + + If you ever see Gnus act noncompliantly to the texts mentioned above, + don't hesitate to drop a note to Gnus Towers and let us know. + + @node Contributors @section Contributors @cindex contributors *************** *** 285,316 **** @section New Features @cindex new features ! The look of all buffers can be changed by setting format-like variables. ! Local spool and several @sc{nntp} servers can be used at once. Virtual ! groups and private mail groups are featured. Gnus can use various strategies for gathering threads that have lost their roots (thereby gathering loose sub-threads in one thread) or it ! can go back and retrieve enough headers to build a complete thread. Killed groups can be displayed in the group buffer, and you can read them as well. Gnus can do partial group updates - you do not have to retrieve the ! entire active file just to check for new articles in a few groups. ! Gnus implements a sliding scale of subscribedness to groups. - The approach to killing has been changed. Instead of simply killing or - not, you can score articles for easier reading. @node Newest Features @section Newest Features @cindex todo Also known as the @dfn{todo list}. Sure to be implemented before the ! next millennium. @itemize @bullet @item --- 337,464 ---- @section New Features @cindex new features ! @itemize @bullet ! ! @item ! The look of all buffers can be changed by setting format-like variables ! (@pxref{Group Buffer Format} and @pxref{Summary Buffer Format}). ! @item ! Local spool and several @sc{nntp} servers can be used at once ! (@pxref{Foreign Groups}). ! ! @item ! You can combine groups into virtual groups (@pxref{nnvirtual}). + @item + You can read a number of different mail formats (@pxref{Reading Mail}). + All the mail backends implement a convenient mail expiry scheme + (@code{Expiring Old Mail Articles}). + + @item Gnus can use various strategies for gathering threads that have lost their roots (thereby gathering loose sub-threads in one thread) or it ! can go back and retrieve enough headers to build a complete thread ! (@pxref{Customizing Threading}). + @item Killed groups can be displayed in the group buffer, and you can read them as well. + @item Gnus can do partial group updates - you do not have to retrieve the ! entire active file just to check for new articles in a few groups ! (@pxref{The Active File}). ! @item ! Gnus implements a sliding scale of subscribedness to groups ! (@pxref{Group Levels}). ! ! @item ! You can score articles according to any number of criteria (@pxref{Score ! Files}). You can even get Gnus to score articles for you ! (@pxref{Adaptive Scoring}). ! ! @item ! Gnus maintains a dribble buffer that is auto-saved the normal Emacs ! manner, so it should be difficult to lose much data on what you have ! read if your machine should go down (@pxref{Auto Save}). ! ! @item ! Gnus now has its own startup file to avoid cluttering up the ! @file{.emacs} file. ! ! @item ! You can set the process mark on both groups and articles and perform ! operations on all the marked items (@pxref{Process/Prefix}). ! ! @item ! You can grep through a subset of groups and create a group from the ! results (@pxref{nnkiboze}). ! ! @item ! You can list subsets of groups according to, well, anything ! (@pxref{Listing Groups}). ! ! @item ! You can browse foreign servers and subscribe to groups from those ! servers (@pxref{Browse Foreign Server}). ! ! @item ! Gnus can fetch articles asynchronously on a second connection to the ! server (@pxref{Asynchronous Fetching}). ! ! @item ! You can cache articles locally (@pxref{Article Caching}). ! ! @item ! The uudecode functions have been expanded and generalized ! (@pxref{Decoding Articles}). ! ! @item ! You can still post uuencoded articles, which was a little-known feature ! of @sc{gnus} past (@pxref{Uuencoding & Posting}). ! ! @item ! Fetching parents (and other articles) now actually works without ! glitches (@pxref{Finding the Parent}). ! ! @item ! Gnus can fetch FAQs to and descriptions of groups (@pxref{Group ! Information}). ! ! @item ! Digests (and other files) can be used as the basis for groups ! (@pxref{nndoc}). ! ! @item ! Articles can be highlighted and customized (@pxref{Customizing ! Articles}). ! ! @item ! All Gnus buffers can be customized in a difficult fashion ! (@pxref{Windows Configuration}). ! ! @item ! You can click on buttons instead of using the keyboard ! (@pxref{Buttons}). ! ! @end itemize ! ! This is, of course, just a @emph{short} overview of the @emph{most} ! important new features. No, really. There are tons more. Yes, we have ! feeping creaturism in full effect, but nothing too gratuitous, I would ! hope. @node Newest Features @section Newest Features @cindex todo Also known as the @dfn{todo list}. Sure to be implemented before the ! next millennium. ! ! Be afraid. Be very afraid. @itemize @bullet @item *************** *** 318,331 **** I could steal code from @code{Mew}, the @sc{mime} mail reader for Emacs, but I'm not quite sure what the status of that project is. Gnus might support @sc{mime} quite soon, and it might not. @item ! When the user references the parent of an article, some sort of ! re-threading should be done to build a proper tree. The same goes for ! article expunging. However, as it stands, it's not a trivial issue to ! re-generate parts of the summary buffer. Generating the entire buffer ! is very easy, but slow. @end itemize @node Terminology @chapter Terminology --- 466,542 ---- I could steal code from @code{Mew}, the @sc{mime} mail reader for Emacs, but I'm not quite sure what the status of that project is. Gnus might support @sc{mime} quite soon, and it might not. + + @item + @code{trn}-like trees. + @item + @code{nn}-like pick-and-read summary interface. + @item + NoCeM support. + @item + Frame configuration. + @item + Re-sending bounced mail and rejected articles. + @item + Floating point group levels and group bubbling. + @item + @file{/etc/nntpserver} usage. + @item + Automatic re-scan of incoming mail. + @item + Buttonize more stuff in the article buffer. + @item + A better and simpler method for specifying mail composing methods. + @item + Marks for saved, forwarded, etc articles. + @item + Speed up caching and adaptive scoring. + @item + Gather thread by filling in missing Message-IDs. + @item + Slave Gnusii to enable several Gnusii to run at once. + @item + PGP support. + @item + Allow posting through mail-to-news gateways. @item ! Allow renaming mail groups in a simple fashion. ! @item ! Speed up massive group massacres. ! @item ! @code{jka-compr} isn't fully supported. ! @item ! Create better digests. ! @item ! Do better word-wrap on cited text. ! @item ! Better X-Face support with X-Face databases and stuff. ! @item ! Support SELF-DISCIPLINE pins. ! @item ! Really do unbinhexing. ! @item ! Fetching by Message-ID should work in mail groups. ! @item ! Listing of all active groups. ! @item ! XEmacs toolbar. ! @item ! Do the X-Receipt-To thing. ! @item ! Hierarchal group buffers. ! @item ! Don't kill summary buffers upon exit from the groups. ! @item ! Allow adaption on secondary marks. @end itemize + And much, much, much more. There is more to come than has already been + implemented. (But that's always true, isn't it?) + + You can probably sneak a look at the actual up-to-the-second todo list + by snooping @code{}. + @node Terminology @chapter Terminology *************** *** 750,755 **** --- 961,976 ---- @section Startup Variables @table @code + @item gnus-load-hook + @vindex gnus-load-hook + A hook that is run while Gnus is being loaded. Note that this hook will + normally be run just once in a single Emacs session, no matter how many + times you start Gnus. + + @item gnus-startup-hook + @vindex gnus-startup-hook + A hook that is run after starting up Gnus successfully. + @item gnus-check-bogus-newsgroups @vindex gnus-check-bogus-newsgroups If non-@code{nil}, Gnus will check for and delete all bogus groups at *************** *** 758,768 **** --- 979,991 ---- bogus groups isn't very quick, so to save time and resources, it's best to leave this option off, and instead do the checking for bogus groups once in a while from the group buffer (@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 that you are reading news instead of doing your job. + @item gnus-no-groups-message @vindex gnus-no-groups-message Message displayed by Gnus when no groups are available. *************** *** 1742,1765 **** Reading mail with a newsreader - isn't that just plain WeIrD? But of course. @menu * Creating Mail Groups:: How to create mail groups. * Fancy Mail Splitting:: Gnus can do hairy splitting of incoming mail. * Mail & Procmail:: Reading mail groups that procmail create. * Expiring Old Mail Articles:: Getting rid of unwanted mail. * Not Reading Mail:: Using mail backends for reading other files. ! @end menu ! ! Gnus will read the mail spool when you activate a mail group. The mail ! file is first copied to your home directory. What happens after that ! depends on what format you want to store your mail in. ! ! @menu ! * nnmbox:: Using the (quite) standard Un*x mbox. ! * nnbabyl:: Many Emacs programs use the rmail babyl format. ! * nnml:: Store your mail in a private spool? ! * nnmh:: An mhspool-like backend useful for procmail people. ! * nnfolder:: Having one file for each group. @end menu @vindex nnmail-read-incoming-hook --- 1965,1985 ---- Reading mail with a newsreader - isn't that just plain WeIrD? But of course. + Gnus will read the mail spool when you activate a mail group. The mail + file is first copied to your home directory. What happens after that + depends on what format you want to store your mail in. + @menu * Creating Mail Groups:: How to create mail groups. * Fancy Mail Splitting:: Gnus can do hairy splitting of incoming mail. * Mail & Procmail:: Reading mail groups that procmail create. * Expiring Old Mail Articles:: Getting rid of unwanted mail. * Not Reading Mail:: Using mail backends for reading other files. ! * nnmbox:: Using the (quite) standard Un*x mbox. ! * nnbabyl:: Emacs programs use the rmail babyl format. ! * nnml:: Store your mail in a private spool? ! * nnmh:: An mhspool-like backend. ! * nnfolder:: Having one file for each group. @end menu @vindex nnmail-read-incoming-hook *************** *** 2599,2604 **** --- 2819,2825 ---- @item r @kindex r (Group) @findex gnus-group-read-init-file + @vindex gnus-init-file Read the init file (@code{gnus-init-file}, which defaults to @file{~/.gnus}) (@code{gnus-group-read-init-file}). @item s *************** *** 3348,3355 **** If @code{nil}, always ignore the Followup-To header. If it is @code{t}, use its value, but ignore the special value @samp{poster}, which will send the followup as a reply mail to the person you are responding to. ! If it is neither @code{nil} nor @code{t}, always use the Followup-To ! value. @item gnus-followup-to-function @vindex gnus-followup-to-function --- 3569,3576 ---- If @code{nil}, always ignore the Followup-To header. If it is @code{t}, use its value, but ignore the special value @samp{poster}, which will send the followup as a reply mail to the person you are responding to. ! If it is the symbol @code{ask}, query the user before posting. ! If it is the symbol @code{use}, always use the value. @item gnus-followup-to-function @vindex gnus-followup-to-function *************** *** 4572,4577 **** --- 4793,4800 ---- * Uuencoded Articles:: Uudecode articles. * Shared Articles:: Unshar articles. * PostScript Files:: Split PostScript. + * Decoding Variables:: Variables for a happy decoding. + * Viewing Files:: You want to look at the result of the decoding? @end menu All these functions use the process/prefix convention *************** *** 4592,4602 **** series}, will not be properly recognized by any of the automatic viewing commands, and you have to mark the articles manually with @key{#}. - @menu - * Decoding Variables:: Variables for a happy decoding. - * Viewing Files:: You want to look at the result of the decoding? - @end menu - @node Uuencoded Articles @subsection Uuencoded Articles @cindex uudecode --- 4815,4820 ---- *************** *** 5376,5383 **** alists should probably be placed before the "real" score file functions, to ensure that the last score file returned is the local score file. Phu. ! @item gnus-kill-expiry-days ! @vindex gnus-kill-expiry-days This variable says how many days should pass before an unused score file entry is expired. The default is 7. @end table --- 5594,5601 ---- alists should probably be placed before the "real" score file functions, to ensure that the last score file returned is the local score file. Phu. ! @item gnus-score-expiry-days ! @vindex gnus-score-expiry-days This variable says how many days should pass before an unused score file entry is expired. The default is 7. @end table *************** *** 6143,6153 **** @node Article Keymap @section Article Keymap ! Most of the keystrokes in the summary buffer can also be used in the ! article buffer. They should behave as if you typed them in the summary ! buffer, which means that you don't actually have to have a summary ! buffer displayed while reading. You can do it all from the article ! buffer. A few additional keystrokes are available: --- 6361,6371 ---- @node Article Keymap @section Article Keymap ! @c Most of the keystrokes in the summary buffer can also be used in the ! @c article buffer. They should behave as if you typed them in the summary ! @c buffer, which means that you don't actually have to have a summary ! @c buffer displayed while reading. You can do it all from the article ! @c buffer. A few additional keystrokes are available: *************** *** 6346,6351 **** --- 6564,6574 ---- @node Servers & Methods @section Servers & Methods + Wherever you would normally use a select method + (eg. @code{gnus-secondary-select-method}, in the group select method, + when browsing a foreign server) you can use a virtual server name + instead. This could potentially save lots of typing. And it's nice all + over. @node Various *************** *** 6784,6789 **** --- 7007,7687 ---- not for a seat upon the dais@* but at the common table.@* @end quotation + + @node Appendix + @chapter A Programmer's Guide to Gnus + + It is my hope that other people will figure out smart stuff that Gnus + can do, and that other people will write those smart things as well. To + facilitate that I thought it would be a good idea to describe the inner + workings of Gnus. And some of the not-so-inner workings, while I'm at + it. + + You can never expect the internals of a program not to change, but I + will be defining (in some details) the interface between Gnus and its + backends (this is written in stone), the format of the score files + (ditto), data structures (some are less likely to change than others) + and general method of operations. + + @menu + * Backend Interface:: How Gnus communicates with the servers. + * Score File Syntax:: A BNF definition of the score file standard. + * Headers:: How Gnus stores headers internally. + * Ranges:: A handy format for storing mucho numbers. + * Group Info:: The group info format. + @end menu + + + @node Backend Interface + @section Backend Interface + + Gnus doesn't know anything about nntp, spools, mail or virtual groups. + It only knows how to talk to @dfn{virtual servers}. A virtual server is + a @dfn{backend} and some @dfn{backend variables}. As examples of the + first, we have @code{nntp}, @code{nnspool} and @code{nnmbox}. As + examples of the latter we have @code{nntp-port-number} and + @code{nnmbox-directory}. + + When Gnus asks for information from a backend -- say @code{nntp} -- on + something, it will normally include a virtual server name in the + function parameters. (If not, the backend should use the "current" + virtual server.) For instance, @code{nntp-request-list} takes a virtual + server as its only (optional) parameter. If this virtual server hasn't + been opened, the function should fail. + + Note that a virtual server name has no relation to some physical server + name. Take this example: + + @lisp + (nntp "odd-one" + (nntp-address "ifi.uio.no") + (nntp-port-number 4324)) + @end lisp + + Here the virtual server name is @samp{"odd-one"} while the name of + the physical server is @samp{"ifi.uio.no"}. + + The backends should be able to switch between several virtual servers. + The standard backends implement this by keeping an alist of virtual + server environments that it pulls down/pushes up when needed. + + There are two groups of interface functions: @dfn{required functions}, + which must be present, and @dfn{optional functions}, which Gnus will + always check whether are present before attempting to call. + + All these functions are expected to return data in the buffer + @code{nntp-server-buffer} (@samp{" *nntpd*"}), which is somewhat + unfortunately named, but we'll have to live with it. When I talk about + "resulting data", I always refer to the data in that buffer. When I + talk about "return value", I talk about the function value returned by + the function call. + + Some backends could be said to be @dfn{server-forming} backends, and + some might be said to not be. The latter are backends that generally + only operate on one group at a time, and have no concept of "server" -- + they have a group, and they deliver info on that group and nothing more. + + In the examples and definitions I will refer to the imaginary backend + @code{nnchoke}. + + @menu + * Required Backend Functions:: Functions that must be implemented. + * Optional Backend Functions:: Functions that need not be implemented. + @end menu + + + @node Required Backend Functions + @subsection Required Backend Functions + + @table @code + + @item (nnchoke-retrieve-headers ARTICLES &optional GROUP SERVER) + + @var{articles} is either a range of article numbers or a list of + @code{Message-ID}s. Current backends do not fully support either - only + sequences (lists) of article numbers, and most backends do not support + retrieval of @code{Message-ID}s. But they should try for both. + + The result data should either be HEADs or NOV lines, and the result + value should either be @code{headers} or @code{nov} to reflect this. + This might later be expanded to @code{various}, which will be a mixture + of HEADs and NOV lines, but this is currently not supported by Gnus. + + Here's an example HEAD: + + @example + 221 1056 Article retrieved. + Path: ifi.uio.no!sturles + From: sturles@@ifi.uio.no (Sturle Sunde) + Newsgroups: ifi.discussion + Subject: Re: Something very droll + Date: 27 Oct 1994 14:02:57 +0100 + Organization: Dept. of Informatics, University of Oslo, Norway + Lines: 26 + Message-ID: <38o8e1$a0o@@holmenkollen.ifi.uio.no> + References: <38jdmq$4qu@@visbur.ifi.uio.no> + NNTP-Posting-Host: holmenkollen.ifi.uio.no + . + @end example + + So a @code{headers} return value would imply that there's a number of + these in the data buffer. + + Here's a BNF definition of such a buffer: + + @example + headers = *head + head = error / valid-head + error-message = [ "4" / "5" ] 2number " " eol + valid-head = valid-message *header "." eol + valid-message = "221 " " Article retrieved." eol + header = eol + @end example + + If the return value is @code{nov}, the data buffer should contain + @dfn{network overview database} lines. These are basically fields + separated by tabs. + + @example + nov-buffer = *nov-line + nov-line = 8*9 [ field ] eol + field = + @end example + + For a closer explanation what should be in those fields, + @xref{Headers}. + + + @item (nnchoke-open-server SERVER &optional DEFINITIONS) + + @var{server} is here the virtual server name. @var{definitions} is a + list of @code{(VARIABLE VALUE)} pairs that defines this virtual server. + + If the server can't be opened, no error should be signaled. The backend + may then choose to refuse further attempts at connecting to this + server. In fact, it should do so. + + If the server is opened already, this function should return a + non-@code{nil} value. There should be no data returned. + + + @item (nnchoke-close-server &optional SERVER) + + Close connection to @var{server} and free all resources connected + to it. + + There should be no data returned. + + + @item (nnchoke-request-close) + + Close connection to all servers and free all resources that the backend + have reserved. All buffers that have been created by that backend + should be killed. (Not the @code{nntp-server-buffer}, though.) + + There should be no data returned. + + + @item (nnchoke-server-opened &optional SERVER) + + This function should return whether @var{server} is opened, and that the + connection to it is still alive. This function should under no + circumstances attempt to reconnect to a server that is has lost + connection to. + + There should be no data returned. + + + @item (nnchoke-status-message &optional SERVER) + + This function should return the last error message from @var{server}. + + There should be no data returned. + + + @item (nnchoke-request-article ARTICLE &optional GROUP SERVER TO-BUFFER) + + The result data from this function should be the article specified by + @var{article}. This might either be a @code{Message-ID} or a number. + It is optional whether to implement retrieval by @code{Message-ID}, but + it would be nice if that were possible. + + If @var{to-buffer} is non-@code{nil}, the result data should be returned + in this buffer instead of the normal data buffer. This is to make it + possible to avoid copying large amounts of data from one buffer to + another, and Gnus mainly request articles to be inserted directly into + its article buffer. + + + @item (nnchoke-open-group GROUP &optional SERVER) + + Make @var{group} the current group. + + There should be no data returned by this function. + + + @item (nnchoke-request-group GROUP &optional SERVER) + + Get data on @var{group}. This function also has the side effect of + making @var{group} the current group. + + Here's an example of some result data and a definition of the same: + + @example + 211 56 1000 1059 ifi.discussion + @end example + + The first number is the status, which should be @samp{211}. Next is the + total number of articles in the group, the lowest article number, the + highest article number, and finally the group name. Note that the total + number of articles may be less than one might think while just + considering the highest and lowest article numbers, but some articles + may have been cancelled. Gnus just discards the total-number, so + whether one should take the bother to generate it properly (if that is a + problem) is left as an excercise to the reader. + + @example + group-status = [ error / info ] eol + error = [ "4" / "5" ] 2 " " + info = "211 " 3* [ " " ] + @end example + + + @item (nnchoke-close-group GROUP &optional SERVER) + + Close @var{group} and free any resources connected to it. This will be + a no-op on most backends. + + There should be no data returned. + + + @item (nnchoke-request-list &optional SERVER) + + Return a list of all groups available on @var{server}. And that means + @emph{all}. + + Here's an example from a server that only carries two groups: + + @example + ifi.test 0000002200 0000002000 y + ifi.discussion 3324 3300 n + @end example + + On each line we have a group name, then the highest article number in + that group, the lowest article number, and finally a flag. + + @example + active-file = *active-line + active-line = name " " " " " " flags eol + name = + flags = "n" / "y" / "m" / "x" / "j" / "=" name + @end example + + The flag says whether the group is read-only (@samp{n}), is moderated + (@samp{m}), is dead (@samp{x}), is aliased to some other group + (@samp{=other-group} or none of the above (@samp{y}). + + + @item (nnchoke-request-post &optional SERVER) + + This function should post the current buffer. It might return whether + the posting was successful or not, but that's not required. If, for + instance, the posting is done asynchronously, it has generally not been + completed by the time this function concludes. In that case, this + function should set up some kind of sentinel to beep the user loud and + clear if the posting could not be completed. + + There should be no result data from this function. + + + @item (nnchoke-request-post-buffer POST GROUP SUBJECT HEADER ARTICLE-BUFFER INFO FOLLOW-TO RESPECT-POSTER) + + This function should return a buffer suitable for composing an article + to be posted by @code{nnchoke-request-post}. If @var{post} is + non-@code{nil}, this is not a followup, but a totally new article. + @var{group} is the name of the group to be posted to. @var{subject} is + the subject of the message. @var{article-buffer} is the buffer being + followed up, if that is the case. @var{info} is the group info. + @var{follow-to} is the group that one is supposed to re-direct the + article to. If @var{respect-poster} is non-@code{nil}, the special + @samp{"poster"} value of a @code{Followup-To} header is to be respected. + + There should be no result data returned. + + @end table + + @node Optional Backend Functions + @subsection Optional Backend Functions + + @table @code + + @item (nnchoke-retrieve-groups GROUPS &optional SERVER) + + @var{groups} is a list of groups, and this function should request data + on all those groups. How it does it is of no concern to Gnus, but it + should attempt to do this in a speedy fashion. + + The return value of this function can be either @code{active} or + @code{group}, which says what the format of the result data is. The + former is in the same format as the data from + @code{nnchoke-request-list}, while the latter is a buffer full of lines + in the same format as @code{nnchoke-request-group} gives. + + @example + group-buffer = *active-line / *group-status + @end example + + + @item (nnchoke-request-update-info GROUP INFO &optional SERVER) + + A Gnus group info (@pxref{Group Info}) is handed to the backend for + alterations. This comes in handy if the backend really carries all the + information (as is the case with virtual an imap groups). This function + may alter the info in any manner it sees fit, and should return the + (altered) group info. This function may alter the group info + destructively, so no copying is needed before boogying. + + There should be no result data from this function. + + + @item (nnchoke-request-scan &optional GROUP SERVER) + + This function may be called at any time (by Gnus or anything else) to + request that the backend check for incoming articles, in one way or + another. A mail backend will typically read the spool file or query the + POP server when this function is invoked. The @var{group} doesn't have + to be heeded -- if the backend decides that it is too much work just + scanning for a single group, it may do a total scan of all groups. It + would be nice, however, to keep things local if that's practical. + + There should be no result data from this function. + + + @item (nnchoke-request-asynchronous GROUP &optional SERVER ARTICLES) + + This is a request to fetch articles asynchronously later. + @var{articles} is an alist of @var{(article-number line-number)}. One + would generally expect that if one later fetches article number 4, for + instance, some sort of asynchronous fetching of the articles after 4 + (which might be 5, 6, 7 or 11, 3, 909 depending on the order in that + alist) would be fetched asynchronouly, but that is left up to the + backend. Gnus doesn't care. + + There should be no result data from this function. + + + @item (nnchoke-request-group-description GROUP &optional SERVER) + + The result data from this function should be a description of + @var{group}. + + @example + description-line = name description eol + name = + description = + @end example + + @item (nnchoke-request-list-newsgroups &optional SERVER) + + The result data from this function should be the description of all + groups available on the server. + + @example + description-buffer = *description-line + @end example + + + @item (nnchoke-request-newgroups DATE &optional SERVER) + + The result data from this function should be all groups that were + created after @samp{date}, which is in normal human-readable date + format. The data should be in the active buffer format. + + + @item (nnchoke-request-create-groups GROUP &optional SERVER) + + This function should create an empty group with name @var{group}. + + There should be no return data. + + + @item (nnchoke-request-expire-articles ARTICLES &optional GROUP SERVER FORCE) + + This function should run the expiry process on all articles in the + @var{articles} range (which is currently a simple list of article + numbers.) It is left up to the backend to decide how old articles + should be before they are removed by this function. If @var{force} is + non-@code{nil}, all @var{articles} should be deleted, no matter how new + they are. + + This function should return a list of articles that it did not/was not + able to delete. + + There should be no result data returned. + + + @item (nnchoke-request-move-article ARTICLE GROUP SERVER ACCEPT-FORM + &optional LAST) + + This function should move @var{article} (which is a number) from + @var{group} by calling @var{accept-form}. + + This function should ready the article in question for moving by + removing any header lines it has added to the article, and generally + should "tidy up" the article. Then it should @code{eval} + @var{accept-form} in the buffer where the "tidy" article is. This will + do the actual copying. If this @code{eval} returns a non-@code{nil} + value, the article should be removed. + + If @var{last} is @code{nil}, that means that there is a high likelihood + that there will be more requests issued shortly, so that allows some + optimizations. + + There should be no data returned. + + + @item (nnchoke-request-accept-article GROUP &optional LAST) + + This function takes the current buffer and inserts it into @var{group}. + If @var{last} in @code{nil}, that means that there will be more calls to + this function in short order. + + There should be no data returned. + + + @item (nnchoke-request-replace-article ARTICLE GROUP BUFFER) + + This function should remove @var{article} (which is a number) from + @var{group} and insert @var{buffer} there instead. + + There should be no data returned. + + @end table + + + @node Score File Syntax + @section Score File Syntax + + Score files are meant to be easily parsable, but yet extremely + mallable. It was decided that something that had the same read syntax + as an Emacs Lisp list would fit that spec. + + Here's a typical score file: + + @lisp + (("summary" + ("win95" -10000 nil s) + ("Gnus")) + ("from" + ("Lars" -1000)) + (mark -100)) + @end lisp + + BNF definition of a score file: + + @example + score-file = "" / "(" *element ")" + element = rule / atom + rule = string-rule / number-rule / date-rule + string-rule = "(" quote string-header quote space *string-match ")" + number-rule = "(" quote number-header quote space *number-match ")" + date-rule = "(" quote date-header quote space *date-match ")" + quote = + string-header = "subject" / "from" / "references" / "message-id" / + "xref" / "body" / "head" / "all" / "followup" + number-header = "lines" / "chars" + date-header = "date" + string-match = "(" quote quote [ "" / [ space score [ "" / + space date [ "" / [ space string-match-t ] ] ] ] ] ")" + score = "nil" / + date = "nil" / + string-match-t = "nil" / "s" / "substring" / "S" / "Substring" / + "r" / "regex" / "R" / "Regex" / + "e" / "exact" / "E" / "Exact" / + "f" / "fuzzy" / "F" / "Fuzzy" + number-match = "(" [ "" / [ space score [ "" / + space date [ "" / [ space number-match-t ] ] ] ] ] ")" + number-match-t = "nil" / "=" / "<" / ">" / ">=" / "<=" + date-match = "(" quote quote [ "" / [ space score [ "" / + space date [ "" / [ space date-match-t ] ] ] ] ")" + date-match-t = "nil" / "at" / "before" / "after" + atom = "(" [ required-atom / optional-atom ] ")" + required-atom = mark / expunge / mark-and-expunge / files / + exclude-files / read-only / touched + optional-atom = adapt / local / eval + mark = "mark" space nil-or-number + nil-or-t = "nil" / + expunge = "expunge" space nil-or-number + mark-and-expunge = "mark-and-expunge" space nil-or-number + files = "files" *[ space ] + exclude-files = "exclude-files" *[ space ] + read-only = "read-only" [ space "nil" / space "t" ] + adapt = "adapt" [ space "nil" / space "t" / space adapt-rule ] + adapt-rule = "(" *[ *[ "(" ")" ] ")" + local = "local" *[ space "(" space
")" ] + eval = "eval" space + space = *[ " " / / ] + @end example + + Any unrecognized elements in a score file should be ignored, but not + discarded. + + As you can see, white space is needed, but the type and amount of white + space is irrelevant. This means that formatting of the score file is + left up to the programmer -- if it's simpler to just spew it all out on + one looong line, then that's ok. + + The meaning of the various atoms are explained elsewhere in this + manual. + + @node Headers + @section Headers + + Gnus uses internally a format for storing article headers that + corresponds to the @sc{nov} format in a mysterious fashion. One could + almost suspect that the author looked at the @sc{nov} specification and + just shamelessly @emph{stole} the entire thing, and one would be right. + + @dfn{Header} is a severly overloaded term. "Header" is used in RFC1036 + to talk about lines in the head of an article (eg., @code{From}). It is + used by many people as a synonym for "head" -- "the header and the + body". (That should be avoided, in my opinion.) And Gnus uses a format + interanally that it calls "header", which is what I'm talking about + here. This is a 9-element vector, basically, with each header (ouch) + having one slot. + + These slots are, in order: @code{number}, @code{subject}, @code{from}, + @code{date}, @code{id}, @code{references}, @code{chars}, @code{lines}, + @code{xref}. There are macros for accessing and setting these slots -- + they all have predicatable names beginning with @code{mail-header-} and + @code{mail-header-set-}, respectively. + + The @code{xref} slot is really a @code{misc} slot. Any extra info will + be put in there. + + @node Ranges + @section Ranges + + @sc{gnus} introduced a concept that I found so useful that I've started + using it a lot and have elaborated on it greatly. + + The question is simple: If you have a large amount of objects that are + identified by numbers (say, articles, to take a @emph{wild} example) + that you want to callify as being "included", a normal sequence isn't + very useful. (A 200,000 length sequence is a bit long-winded.) + + The solution is as simple as the question: You just collapse the + sequence. + + @example + (1 2 3 4 5 6 10 11 12) + @end example + + is transformed into + + @example + ((1 . 6) (10 . 12)) + @end example + + To avoid having those nasty @samp{(13 . 13)} elements to denote a + lonesome object, a @samp{13} is a valid element: + + @example + ((1 . 6) 7 (10 . 12)) + @end example + + This means that comparing two ranges to find out whether they are equal + is slightly tricky: + + @example + ((1 . 6) 7 8 (10 . 12)) + @end example + + and + + @example + ((1 . 5) (7 . 8) (10 . 12)) + @end example + + are equal. In fact, any non-descending list is a range: + + @example + (1 2 3 4 5) + @end example + + is a perfectly valid range, although a pretty longwinded one. This is + also legal: + + @example + (1 . 5) + @end example + + and is equal to the previous range. + + Here's a BNF definition of ranges. Of course, one must remember the + semantic requirement that the numbers are non-descending. (Any number + of repetition of the same number is allowed, but apt to disappear in + range handling.) + + @example + range = simple-range / normal-range + simple-range = "(" number " . " number ")" + normal-range = "(" start-contents ")" + contents = "" / simple-range *[ " " contents ] / + number *[ " " contents ] + @end example + + Gnus currently uses ranges to keep track of read articles and article + marks. I plan on implementing a number of range operators in C if The + Powers That Be are willing to let me. (I haven't asked yet, because I + need to do some more thinking on what operators I need to make life + totally range-based without ever having to convert back to normal + sequences.) + + + @node Group Info + @section Group Info + + Gnus stores all permanent info on groups in a @dfn{group info} list. + This list is from three to six elements (or more) long and exhaustively + describes the group. + + Here are two example group infos; one is a very simple group while the + second is a more complex one: + + @example + ("no.group" 5 (1 . 54324)) + + ("nnml:my.mail" 3 ((1 . 5) 9 (20 . 55)) + ((tick (15 . 19)) (replied 3 6 (19 . 23))) + (nnml "") + (auto-expire (to-address "ding@@ifi.uio.no"))) + @end example + + The first element is the group name as Gnus knows the group; the second + is the group level; the third is the read articles in range format; the + fourth is a list of article marks lists; the fifth is the select method; + and the sixth contains the group parameters. + + Here's a BNF definition of the group info format: + + @example + info = "(" group space level space read + [ "" / [ space marks-list [ "" / [ space method [ "" / + space parameters ] ] ] ] ] ")" + group = quote quote + level = + read = range + marks-lists = nil / "(" *marks ")" + marks = "(" range ")" + method = "(" *elisp-forms ")" + parameters = "(" *elisp-forms ")" + @end example + + Actually that @samp{marks} rule is a fib. A @samp{marks} is a + @samp{} consed on to a @samp{range}, but that's a bitch to say + in pseudo-BNF. + @node Index @chapter Index