|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T a
Length: 27379 (0x6af3)
Types: TextFile
Names: »art.el«
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89
└─⟦32c6b6024⟧ »./gnews-2.0-tar.Z«
└─⟦5d06bd818⟧
└─⟦this⟧ »gnews-2.0/art.el«
;;; art.el: pager-mode commands for Gnews
;;; Copyright (C) 1987, 1988 by Matthew P Wiener; all rights reserved.
;;; Send bugs, complaints, suggestions etc to weemba@garnet.berkeley.edu
;; Gnews is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY. No author or distributor accepts responsibility to
;; anyone for the consequences of using it or for whether it serves any
;; particular purpose or works at all, unless he says so in writing.
;; Refer to the Gnews General License for full details.
;; Everyone is granted permission to copy, modify and redistribute Gnews,
;; but only under the conditions described in the Gnews General License.
;; A copy of this license is supposed to have been given to you along with
;; Gnews so you can know your rights and responsibilities. It should be
;; accessible with the key sequence "ESC l l" while in News mode. Among
;; other things, the copyright notice and this notice must be preserved on
;; all copies.
\f
(defun article-scroll-up (arg &optional ff digest)
"Scroll window forward upward ARG lines, or nearly a full screen if no
ARG. Catch end of buffer errors.\n
Optional second argument FF, if non-nil, blocks an incorrect second call
to article-forward-intern."
(condition-case ()
(progn
(scroll-up arg)
(if (and article-grab-point
(not (if ff (save-excursion (goto-char article-grab-point)
(beginning-of-line)
(looking-at article-formfeed))))
(pos-visible-in-window-p article-grab-point))
(article-forward-intern nil ff digest)))
(end-of-buffer (if (or gnews-edit-p
(= (read (article-field "Lines"))
(1+ (count-lines (article-min) (point-max)))))
(setq article-count-off-but-ok t)
(error "Truncated article")))))
(defun article-forward (&optional arg)
"Scroll the current article forward one page.\n
In Lisp code (only), optional argument ARG means scroll forward that
many lines. Interactively, use article-line, which see."
(interactive (list nil))
(let ((agp article-grab-point)
(ff article-formfeed)
(top article-formfeed-top)
(digest article-formfeed-post))
(if (and agp (pos-visible-in-window-p agp))
(progn (article-forward-intern nil ff digest)
(if (pos-visible-in-window-p ; Check for
(save-excursion ; non-null
(goto-char agp) ; reading
(re-search-forward "[^ \n\t\f]" nil t) ; material:
(point))) ; if so, then
nil ; leave alone
(article-scroll-up arg ff digest)) ; else scroll.
(if article-formfeed-top ; And then
(progn (goto-char agp) ; adjust the
(beginning-of-line) ; top of the
(if (looking-at ff) (recenter top))))) ; if needed
(article-scroll-up arg ff digest))
(article-%-compute)
(if (article-done) (article-quit))
(gnews-flush)))
(defun article-down ()
"Scroll the current article down half a page."
(interactive)
(article-forward (/ (window-height) 2)))
(defun article-line (arg)
"Scroll the current article up one line--with numeric argument ARG,
scroll that many lines."
(interactive "p")
(if (article-done)
(ding)
(article-forward arg)))
(defun article-quit ()
"Quit the current article."
(interactive)
(article-forward-intern t)
(if article-junkable (article-junk))
(gnews-message (concat "End of article " article-current
"--what next " group-prompt-default
(if (eq article-current article-final) " $ " " ? ")))
(group-mode)
(gnews-flush)
t)
(defun article-junk (&optional pfx art-no super)
"Mark current article as junked.\n
In Lisp code, non-nil optional argument PFX (the prefix argument) means
do a local junk, and non-nil argument ART-NO is the article number to
junk. Non-nil argument SUPER means due a superjunk: add this message-ID
to this newsgroup's hook-kills: temporary if SUPER is numeric, temporary
and permanent if t."
(interactive "P")
(setq hook-kill-continue) ; terminate hook processing
(if (and (eq article-junkable 'mark) (not (interactive-p))) nil
(if (and (not pfx) art-no)
(let ((b (current-buffer)))
(save-excursion
(set-buffer nntp-buffer)
(nntp-exec t t "head" art-no)
(article-header-clean t))
(set-buffer b)))
(setcdr (cdr (assoc group-current group-roster)) amark)
(let ((xgp (list nil))
(xref (list nil))
(str (if (or pfx (string-match "<0>" nntp-info))
"" (if article-field-list
(article-field "Xref") ; from a read article
(save-excursion ; from a per-hook junk
(set-buffer nntp-buffer)
(goto-char (point-max))
(if (re-search-backward "^Xref: \\(.*\\)" nil t)
(gnews-match 1) ; cross-posted
""))))) ; not cross-posted
(mid (if super
(if article-field-list
(article-field "Message-ID")
(save-excursion
(set-buffer nntp-buffer)
(goto-char 1)
(re-search-forward "^Message-ID: \\(.*\\)" nil t)
(gnews-match 1)))))
ss)
(if (string= str "")
(setq xref (list nil (or art-no article-current))
xgp (list nil group-current))
(while (string-match "\\([^ :]+\\):\\([0-9]+\\)" str ss)
(nconc xgp (list (substring
str (match-beginning 1) (match-end 1))))
(nconc xref (list (string-to-int
(substring
str (match-beginning 2) (match-end 2)))))
(setq ss (match-end 0))))
(gnews-map (function
(lambda (x y)
(let* ((ngl (assoc x group-roster))
(ngam (gnddr ngl)))
(if (and ngl (or article-junk-unsub (gnadr ngl)))
(if ngam (amark-list-insert y ngam)
(nconc ngl (list y)))))))
(cdr xgp)
(cdr xref)))
(setq group-checkpoint t
amark (gnddr (assoc group-current group-roster)))
(if (and (boundp 'index-pop) ; index-mode is around
(not nntp-index-p) ; and we're not killing
(null art-no)) ; but this was direct
(let ((b (current-buffer)))
(save-excursion
(set-buffer index-buffer)
(goto-char 1)
(if (re-search-forward
(concat "^\\(^ *" article-current "\\).") nil t)
(index-junk-line nil)))
(set-buffer b)))
(if (interactive-p) (message "%d: junked" (or art-no article-current))))
(gnews-flush))
(defun article-junk-local ()
"Mark current article as junked in current newsgroup only."
(interactive)
(article-junk t)
(if (interactive-p) (message "%d: junked" article-current))
(gnews-flush))
(defun article-ignore () "Ignore this article" t)
(defun article-yes ()
"For use within hook-kill processing: break out and set to the article."
(setq hook-kill-continue))
(put 'article-junk 'hook-kill-junk t)
(put 'article-junk-local 'hook-kill-junk t)
(put 'article-ignore 'hook-kill-junk t)
(defun article-restart ()
"Restart the current article."
(interactive)
(if (< article-final article-current)
(ding)
(setq buffer-read-only)
(article-header-clean nil)
(setq buffer-read-only t)
(article-mode)
(goto-char 1)
(article-%-compute))
(gnews-hilite)
(gnews-flush))
(defun article-restart-verbose ()
"Restart the current article with full headers."
(interactive)
(if (< article-final article-current)
(ding)
(article-forward-intern nil)
(goto-char 1)
(setq buffer-read-only)
(gnews-delete-paragraph)
(mapcar '(lambda (h) (insert (car h) ": " (cdr h) ?\n))
(cdr article-field-list))
(goto-char 1)
(run-hooks 'article-header-hook)
(goto-char 1)
(setq buffer-read-only t)
(article-%-compute)
(if (article-done) (article-quit) (article-mode))
(goto-char 1))
(gnews-flush))
(defun article-restart-reset ()
"Completely restart the current article."
(interactive)
(cond ((< article-final article-current)
(ding))
((and (< 0 article-current)
(catch 'article-nil (article-get article-current)))
(article-junk-local)
(message "whoops--this article was cancelled"))
((= 0 article-current)
(article-get-msg-id (article-field "Message-ID"))))
(gnews-flush))
(defun article-rot13 ()
"Rot13 the current article."
(interactive)
(if (< article-final article-current)
(ding)
(setq buffer-read-only)
(save-excursion
(goto-char (article-min))
(gnews-rot13 (article-min) (article-max)))
(setq buffer-read-only t
gnews-rot13-p (not gnews-rot13-p))
(article-%-compute)
;; note: for a-r13-r, we must return !nil if a-q
(if (article-done) (article-quit))))
(defun article-rot13-restart ()
"Restart and rot13 the current article."
(interactive)
(let (gnews-rot13-p) (article-restart)) ; shield for sake of a-r13
(article-rot13))
(defun article-rot13-forward ()
"Scroll forward and rot13 the current article."
(interactive)
(or (article-rot13) (article-forward)))
(defun article-downcase ()
"Lowercase the current article."
(interactive)
(if (< article-final article-current)
(ding)
(article-forward-intern t)
(setq buffer-read-only)
(save-excursion
(downcase-region (article-min) (article-max)))
(setq buffer-read-only t gnews-edit-p t)
(if (article-done) (article-quit)))
(gnews-flush))
(defun article-ununderline ()
"Remove underlining from the current article."
(interactive)
(if (< article-final article-current)
(ding)
(article-forward-intern t)
(setq buffer-read-only)
(save-excursion
(ununderline-region (article-min) (article-max)))
(setq buffer-read-only t gnews-edit-p t)
(if (article-done) (article-quit)))) ; must return !nil if quit
(defun article-back ()
"Scroll back a page in the current article."
(interactive)
(if (< article-final article-current)
(ding)
(scroll-down nil)
(article-%-compute))
(move-to-window-line 0)
(gnews-hilite)
(gnews-flush))
(defun article-back-half ()
"Scroll back half a page in the current article."
(interactive)
(if (< article-final article-current)
(ding)
(scroll-down (/ (window-height) 2))
(article-%-compute)
(if (article-done) (article-quit)))
(move-to-window-line 0)
(gnews-hilite)
(gnews-flush))
(defun article-end ()
"Go to the end of the current article."
(interactive)
(article-forward-intern nil)
(end-of-buffer)
(recenter (- (window-height) 1))
(move-to-window-line -1)
(sit-for 0)
(article-%-compute)
(if (article-done) (article-quit))
(gnews-flush))
(defun article-grep (pfx)
"Search for a regexp in the article--non-nil prefix argument PFX
means search backwards."
(interactive "P")
(article-forward-intern nil)
(setq article-grep-directions '(re-search-forward . re-search-backward))
(if pfx (setq article-grep-directions (nreverse article-grep-directions)))
(funcall (car article-grep-directions)
(setq article-grep-string (or (read-string "grep for: ")
article-grep-string))
nil t)
(recenter article-grep-height)
(article-%-compute)
(if (article-done) (article-quit))
(gnews-flush))
(defun article-grep-repeat (pfx)
"Repeat previous regexp search--non-nil prefix argument PFX means
reverse search direction."
(interactive "P")
(if (null article-grep-string) (article-grep pfx)
(article-forward-intern nil)
(if pfx (setq article-grep-directions (nreverse article-grep-directions)))
(funcall (car article-grep-directions)
article-grep-string nil t)
(recenter article-grep-height)
(article-%-compute)
(if (article-done) (article-quit))
(gnews-flush)))
(defun article-grep-digest (pfx)
"Search for a digest separator--non-nil prefix argument PFX means
search backwards."
(interactive "P")
(article-forward-intern nil)
(if pfx nil (forward-line 1))
(funcall (if pfx 're-search-backward 're-search-forward)
article-digest-separator nil t)
(recenter 0)
(beginning-of-line)
(article-%-compute)
(if (article-done) (article-quit))
(gnews-flush))
(defun article-skip-indent ()
"Skip past indentation, ie, the first character on the bottom line"
(interactive)
(move-to-window-line -1)
(beginning-of-line)
(re-search-forward
(concat "^[^" (regexp-quote
(char-to-string
(following-char))) "]") nil t)
(beginning-of-line)
(article-forward-intern nil)
(recenter article-grep-height)
(article-%-compute)
(if (article-done) (article-quit))
(gnews-flush))
(defun article-recenter (&optional pfx arg)
"Recenter the current article, as in recenter.\n
In Lisp code, if optional PFX is non-nil, then ARG is passed to recenter."
(interactive "P\np")
(if (< article-final article-current)
(ding)
(recenter (cond (pfx arg)
((interactive-p) nil)
(t 0)))
(article-%-compute)
(if (article-done) (article-quit)))
(gnews-hilite)
(gnews-flush))
(defun article-isearch-forward ()
(interactive)
(article-forward-intern nil)
(isearch t)
(article-%-compute))
(defun article-isearch-backward ()
(interactive)
(article-forward-intern nil)
(isearch nil)
(article-%-compute))
(defun article-isearch-forward-regexp ()
(interactive)
(article-forward-intern nil)
(isearch t t)
(article-%-compute))
(defun article-isearch-backward-regexp ()
(interactive)
(article-forward-intern nil)
(isearch nil t)
(article-%-compute))
\f
;;; the basic article getting primitives
;;; article-get's complexity comes from its attempt to be quick and clever.
;;; First, only the head is gotten, permitting quick checks for hook-kill
;;; purposes. If the article passes, then the body is gotten too. But we
;;; do a little buffering along the way, only grabbing enough of the body
;;; to get a quick display up. If the length of the article is greater
;;; than article-big lines, then we do a full display, even if the user
;;; by default asks for just a partial display--ie, just give him something
;;; to read while waiting. Also, the *first* character hit by a user while
;;; waiting is processed--normally all typeahead is flushed.
;;; article-get-slow is not actually that slow (except for large articles)
;;; it just has none of the above sophistication. Being simpler, it should
;;; be less error prone, but this is counterbalanced by the fact that I work
;;; primarily with/on article-get. At the moment, I still must use it in
;;; forward/backward pattern searches and with the spool code. Both needs
;;; are a mystery to me.
(defun article-get (number &optional hooklist interact)
"Display article NUMBER of the current newsgroup.\n
In Lisp code, optional argument HOOKLIST is a list of per-hooks to
apply, and a non-nil INTERACT means pretend this function was called
interactively."
(interactive "narticle #: ")
(setq gnews-edit-p nil
gnews-rot13-p nil
interact (or (interactive-p) interact))
(if (< article-final number)
(group-last)
(if (nntp-exec t t "head" number)
(let ((b (current-buffer))
(hook-kill-continue t)
lines)
(set-buffer nntp-buffer)
(if interact (article-current-set number))
(setq article-field-list)
(while (and hooklist hook-kill-continue)
(if (hook-kill-do (car hooklist) nil)
(progn ; hook-kill-junk property
(hook-kill-junk-message number (car hooklist))
(set-buffer b) ; I have to doooo this?
(throw 'article-nil t))) ; article KILLed; try again
(setq hooklist (cdr hooklist)))
(article-header-clean t)
(if interact
(article-history-append number group-current
(article-field "Message-ID")))
(setq lines (article-effective-init-display))
(nntp-exec nil nil "body" number)
(while (and (nntp-run-p) ; catch a broken connection
(not nntp-eot)
(< (count-lines 1 (point-max))
(or lines
(window-height
(get-buffer-window news-buffer)))))
(gnews-accept-process-output nntp))
(if (not (nntp-run-p))
(news-quit
(y-or-n-p "Connection died: save the current roster? ")))
(save-excursion ; get rid of NNTP info
(goto-char 1)
(re-search-forward "^222.*$") ; the NNTP info message
(setq nntp-info-true (gnews-match 0))
(replace-match ""))
(if lines (forward-line lines))
(setq article-grab-point (if lines (point)))
(article-display-init)
(nntp-finish)
(set-buffer nntp-buffer)
(goto-char 1)
(insert nntp-info ?\n) ; put back first field
(setq nntp-info nntp-info-true)
(set-buffer news-buffer)
(gnews-exec-1-pending) ; get one out before flushing
(if (setq article-junkable (article-done)) (article-quit)))
(or (article-run-hooks number hooklist interact 'article-not-found-hooks)
(throw 'article-nil t)))) ; article not found--give up
(gnews-flush))
(defun article-get-msg-id (msg-id)
"Display the article with message-ID MSG-ID. Interactively, the
first message-ID that ends at point or after, if it exists, is offered
as a default choice.\n
The enclosing angle brackets are optional."
(interactive
(list (read-string "Message-ID: " (article-msg-id-after-point))))
(setq gnews-edit-p)
(if (string= (substring msg-id 0 1) "<") nil
(setq msg-id (concat "<" msg-id)))
(if (string= (substring msg-id -1) ">") nil
(setq msg-id (concat msg-id ">")))
(setq article-field-list-previous article-field-list)
(if (nntp-exec t t "article" msg-id)
(let (lines)
(set-buffer nntp-buffer)
(article-header-clean t)
(setq lines (article-effective-init-display))
(if lines (forward-line lines))
(setq article-grab-point (if lines (point)))
(if (cdr article-field-list)
(progn
(if (< 0 article-current)
(setq article-message-id msg-id
article-trace article-current
article-current 0)) ; NNTP can't return #/gp
(article-display-init t))
(message "Message-ID %s: no such article" msg-id (ding))
(setq article-field-list article-field-list-previous)))
(or (article-run-hooks msg-id 0 t 'article-not-found-hooks)
(message "Message-ID %s: no such article" msg-id (ding))
(setq article-field-list article-field-list-previous)))
(gnews-flush))
(defun article-get-slow (number &optional hook interact)
"Display article NUMBER of the current newsgroup.\n
In Lisp code, optional argument HOOK is a list of per-hooks to apply, and
non-nil INTERACT means to pretend this function was called interactively.\n"
(interactive "narticle #: ")
(setq gnews-edit-p nil
gnews-rot13-p nil
interact (or (interactive-p) interact))
(if (< article-final number)
(group-last)
(if (nntp-exec t t "article" number)
(let ((b (current-buffer))
lines)
(set-buffer nntp-buffer)
(if interact (article-current-set number))
(article-header-clean t)
(if interact
(article-history-append number group-current
(article-field "Message-ID")))
(setq lines (article-effective-init-display))
(let ((article-current number)
(hook-kill-continue t))
(while (and hook hook-kill-continue)
(if (hook-kill-do (car hook) t)
(progn
(hook-kill-junk-message number hook)
(set-buffer b) ; I have to doooo this?
(throw 'article-nil t))) ; article KILLed; try again
(setq hook (cdr hook))))
(if lines (forward-line lines))
(setq article-grab-point (if lines (point)))
(article-display-init t)
(if (setq article-junkable (article-done)) (article-quit)))
(or (article-run-hooks number hooklist interact 'article-not-found-hooks)
(throw 'article-nil t)))) ; article not found--give it up
(gnews-flush))
(defun article-run-hooks (art-no kills interact hooks)
"Run an article-fetching hook or through a list of article-fetchings
hooks until one of them returns non-nil.\n
This is used by the article-get-* commands to permit non-standard news
article fetching to intermix with the NNTP. If a hook returns non-nil,
it means that Gnews is now set to the indicated article, and is ready
for the user to read the article.\n
Arguments are ART-NO, the article number or message-id of interest,
KILLS, the hook-kills that are applicable, INTERACT, non-nil if the call
is to be treated as if it were interactive, and HOOKS, the hook or list
of hooks to run through.\n
The article Message-ID's case uses 0 for KILLS, since there are no kills
associated with article-get-msg-id.\n
Each hook function should take three arguments: ART-NO, KILLS, INTERACT."
(setq hooks (cond ((fboundp hooks) (list hooks))
((boundp hooks) (eval hooks))))
(let ((hook (car hooks)) found)
(while (and hooks (not found))
(if (fboundp hook)
(setq found (funcall hook art-no kills interact)))
(setq hooks (cdr hooks) hook (car hooks)))
found))
\f
;;; Gnews Edit mode
;;; Edit the display of the current article. The article itself is
;;; of course unaffected, and any changes will be lost upon exiting
;;; the current article. Useful for fixing things that don't quite
;;; match the expectations of your own article filters and the like.
;;; Does not change any internals, like article-field-list.
(if gnews-edit-mode-map nil
(setq gnews-edit-mode-map (gnews-copy-keymap text-mode-map))
(gnews-key-bind gnews-edit-mode-map
'(("\^c\^c".gnews-edit-exit)
("\^c\^]".gnews-edit-abort)
("\^c\^r".gnews-edit-rot13)
("\^c?".describe-mode)
("\^c\^h".gnews-describe-mode))))
(defun gnews-edit-mode ()
"Mode to edit the current article with. It is Text mode with a few
extra commands:\n\\<gnews-edit-mode-map>
\t\\[gnews-edit-exit] to implement the changes and return, and
\t\\[gnews-edit-abort] to ignore the changes and return.\n
\t\\[gnews-edit-rot13] to rot13 regions of text.\n
Also, there is help via:\n
\t\\[describe-mode] to summarize this mode's commands, and
\t\\[gnews-describe-mode] to describe this mode's commands.\n"
(interactive)
(text-mode)
(use-local-map gnews-edit-mode-map)
(make-local-variable 'gnews-edit-p)
(setq major-mode 'gnews-edit-mode
mode-name "Gnews Edit"
gnews-edit-p nil
gnews-read-p nil
gnews-hook-p t)
(run-hooks 'text-mode-hook 'gnews-edit-hook))
(defun article-edit ()
"Edit the contents of the current article."
(interactive)
(article-forward-intern nil)
(setq gnews-pre-edit-text (buffer-substring (point-min) (point-max))
gnews-pre-edit-point (point)
buffer-read-only nil)
(gnews-edit-mode)
(gnews-set-mode-line)
(message "Use %s to implement changes, %s to abort"
(if (eq (key-binding "\C-c\C-c") 'gnews-edit-exit) "C-c C-c"
(substitute-command-keys "\\[gnews-edit-exit]"))
(if (eq (key-binding "\C-c\C-]") 'gnews-edit-abort) "C-c C-]"
(substitute-command-keys "\\[gnews-edit-abort]"))))
(defun gnews-edit-rot13 (beg end)
"Rot13 the region."
(interactive "*r")
(gnews-rot13 beg end))
(defun gnews-edit-exit (edp)
"Return to group/pager mode, with changes in effect."
(interactive (list t))
(setq buffer-read-only t
gnews-edit-p (or gnews-edit-p ; once edited, always edited
(and edp (not (eq last-command 'article-edit)))))
(article-mode)
(article-%-compute)
(if (article-done) (article-quit)))
(defun gnews-edit-abort ()
"Return to group/pager mode, with changes ignored."
(interactive)
(delete-region (point-min) (point-max))
(insert gnews-pre-edit-text)
(goto-char gnews-pre-edit-point)
(gnews-edit-exit nil))
\f
;;; Mail box saving
;;; If there are any other styles worth emulating, write your own, and
;;; let me know about it. A saver is invoked only if gnews-save-style
;;; is set to the name of the saver function.
(defun gnews-output-to-rmail-file (file-name)
"Append the current article to an Rmail file named FILE-NAME.
If the file does not exist, ask if it should be created.
If file is being visited, the message is appended to the Emacs
buffer visiting that file."
;; full header handling added by unido!pbinfo!michael (Michael Schmidt)
(interactive (list (read-file-name
(concat "Rmail save: (default "
(file-name-nondirectory group-last-save)
") ")
(file-name-directory group-last-save)
(if (file-directory-p group-last-save)
(concat group-last-save article-current)
group-last-save))))
(require 'rmail)
(if article-grab-point (article-forward-intern group-save-junk))
(setq file-name (expand-file-name file-name)
group-last-save file-name)
(or (get-file-buffer file-name)
(file-exists-p file-name)
(if (y-or-n-p
(concat "\"" file-name "\" does not exist, create it? "))
(let ((file-buffer (create-file-buffer file-name)))
(save-excursion
(set-buffer file-buffer)
(rmail-insert-rmail-file-header)
(let ((require-final-newline nil))
(write-region (point-min) (point-max) file-name t 1)))
(kill-buffer file-buffer))
(error "Output file does not exist")))
(save-restriction
(widen)
;; Decide whether to append to a file or to an Emacs buffer.
(save-excursion
(let ((buf (get-file-buffer file-name))
(cur (current-buffer))
(from (reply-domain (article-field "From")))
(time (current-time-string))
(beg 1)
(end 1)
(buffer-read-only nil))
;; now fake some Babyl
(goto-char 1)
(insert "\f\n1,,\n")
(insert (format "Summary-line: %2d-%3s %25s #%s\n"
(string-to-int (substring time 11 13))
(substring time 4 7)
(if (< (length from) 26) from (substring from 0 25))
(article-field "Subject")))
(mapcar '(lambda (h) (insert (car h) ": " (cdr h) ?\n))
(cdr article-field-list))
(insert "\n*** EOOH ***\n")
(goto-char (point-max))
(insert ?\^_)
(setq end (point-max))
(if (not buf)
(append-to-file beg end file-name)
;; File has been visited, in buffer BUF.
(set-buffer buf)
(let ((buffer-read-only nil)
(msg (and (boundp 'rmail-current-message)
rmail-current-message)))
;; If MSG is non-nil, buffer is in RMAIL mode.
(if msg
(progn (widen)
(narrow-to-region (point-max) (point-max))))
(insert-buffer-substring cur beg end)
(if msg
(progn
(goto-char (point-min))
(widen)
(search-backward "\^_")
(narrow-to-region (point) (point-max))
(goto-char (1+ (point-min)))
(rmail-count-new-messages t)
(rmail-show-message msg)))))
;; and now unfake the Babyl
(set-buffer cur)
(goto-char 1)
(let ((beg (point)))
(search-forward "*** EOOH ***\n")
(delete-region beg (point)))
(goto-char (point-max))
(delete-char -1)))))
(defun gnews-output-to-mbox-file (file-name)
"Append the current article to a Unix mail file named FILE-NAME."
(interactive (list (read-file-name
(concat "Mbox save: (default "
(file-name-nondirectory group-last-save)
") ")
(file-name-directory group-last-save)
(if (file-directory-p group-last-save)
(concat group-last-save article-current)
group-last-save))))
(require 'rmail)
(if article-grab-point (article-forward-intern group-save-junk))
(setq file-name (expand-file-name file-name)
group-last-save file-name)
(let ((b (current-buffer))
(mb (get-buffer-create "*gnews*mbox*"))
(case-fold-search t))
(save-excursion
(set-buffer mb)
(erase-buffer)
(insert-buffer-substring b)
(insert "\n")
(goto-char (point-min))
(insert "From "
(reply-domain (article-field "From")) " " ; MJS
(current-time-string) "\n")
(while (search-forward "\nFrom " nil t)
(forward-char -5)
(insert ?>))
(append-to-file (point-min) (point-max) file-name))
(kill-buffer mb)))