[comp.emacs] Supercite 2.0 part 02 of 02

warsaw@cme.nist.gov (Barry A. Warsaw) (10/14/89)

--cut here-------------------------------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 2)."
# Contents:  supercite.el
# Wrapped by warsaw@rtg on Fri Oct 13 18:46:09 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'supercite.el' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'supercite.el'\"
else
echo shar: Extracting \"'supercite.el'\" \(83103 characters\)
sed "s/^X//" >'supercite.el' <<'END_OF_FILE'
X;; ======================================================================
X;; supercite.el -- Version 2.0
X
X;; Citation and attribution package for various GNU emacs news and
X;; electronic mail readers.  It has been tested with these commonly
X;; available news and mail readers: VM 4.40, GNUS 3.12 and RMAIL
X;; 18.55. It will interface to VM 4.40+ with no modifications, but
X;; with GNUS 3.12 and RMAIL 18.55 modifications to distribution files
X;; emacs/lisp/{sendmail, rnewspost}.el of GNU emacs version 18.55 are
X;; required.  These modifications are supplied as diff files and as
X;; overload functions.  See the file sup-misc.el for more information.
X
X;; This package does not do any yanking of messages, but is run under
X;; normal conditions via a hook by a reply function in the news/mail
X;; reader package.  "M-x sc-describe" or "C-c ?" for more information
X;; on how to meet the interface if you are writing a reader package,
X;; or want to link supercite with a reader.
X
X;; This package was derived from superyank.el, written by the same
X;; author.
X
X;; This file is distributed in the hope that it will be useful, but
X;; WITHOUT ANY WARRANTY.  No author or distributor accepts
X;; responsibility to anyone for the consequences of using it or for
X;; whether it serves any particular purpose or works at all, unless he
X;; says so in writing.
X
X;; This software was written as part of the author's official duty as
X;; an employee of the United States Government and is thus in the
X;; public domain.  You are free to use this software as you wish, but
X;; WITHOUT ANY WARRANTY WHATSOEVER.  It would be nice, though if when
X;; you use this code, you give due credit to the author.
X
X;; ======================================================================
X;; Author:
X;;
X;; NAME: Barry A. Warsaw             USMAIL: National Institute of Standards
X;; TELE: (301) 975-3460                      and Technology (formerly NBS)
X;; UUCP: {...}!uunet!cme-durer!warsaw        Rm. B-124, Bldg. 220
X;; ARPA: warsaw@cme.nist.gov                 Gaithersburg, MD 20899
X
X;; Want to be on the Supercite mailing list?
X;;
X;; Send articles to supercite@cme.nist.gov or uunet!cme-durer!supercite
X;; Send administrative queries/requests to supercite-request@cme.nist.gov
X;;	or uunet!cme-durer!supercite-request
X
X;; ======================================================================
X;; Credits:
X;;
X;; This package was derived from the SUPERYANK 1.11 package as posted
X;; to the net.  SUPERYANK 1.11 was inspired by code and ideas from
X;; Martin Neitzel and Ashwin Ram.  It has been migrated to SUPERCITE
X;; 2.0 through the comments and suggestions of the superyank (now the
X;; supercite) mailing list which consists of many authors and users of
X;; the various mail and news reading packages.
X
X;; ======================================================================
X;; Thanks:
X;;
X;; Many folks on the supercite mailing list have contributed their help in
X;; debugging, making suggestions and supplying support code or bug fixes
X;; for the pre-release versions of supercite 2.0.  I want to thank every-
X;; one who helped, especially:
X;;
X;; Mark Baushke, Khalid Sattar, David Lawrence, Chris Davis, Kyle
X;; Jones and Kayvan Sylvan
X;;
X;; I don't mean to leave anyone out. All who have help have been
X;; appreciated.
X
X;; ======================================================================
X;; Wish list for version 2.1:
X;;
X;; 1) make assoc lists and other global internal variables buffer-local?
X;;
X;; 2) handle multiple yanking into a single reply buffer. perhaps have a
X;;    stack for sc-gal-information?
X;;
X;; 3) write my own mail-yank-clear-headers which will allow selective
X;;    clearing or leaving of mail headers. Also allow me to not
X;;    (require 'sendmail).
X;;
X;; 4) add a selectable indentation *before* the attribution string.
X
X;; ======================================================================
X;; require and provide features and autoload
X;;
X(require 'sendmail)
X(require 'mail-utils)
X(require 'baw-alist)
X(provide 'supercite)
X
X
X;; **********************************************************************
X;;  
X;; start of user defined variables
X;; 
X;; **********************************************************************
X
X
X;; ----------------------------------------------------------------------
X;; this variable holds the default author's name for citations
X;;
X(defvar sc-default-author-name "Anonymous"
X  "*String used when an author's name cannot be found.")
X
X
X;; ----------------------------------------------------------------------
X;; this variable holds the default attribution string for citations
X;;
X(defvar sc-default-attribution "Anon"
X  "*String that is used when the author's real attribution string
Xcannot be found.  This string should not contain either of the strings
X`sc-citation-delimiter' or `sc-citation-separator'.")
X
X
X;; ----------------------------------------------------------------------
X;; string used as an end delimiter for both nested and non-nested citations
X;;
X(defvar sc-citation-delimiter ">"
X  "*String to use as an end-delimiter for citations.  This string is
Xused in both nested and non-nested citations.  For best results, use a
Xsingle character with no trailing space.  Most commonly used string
Xis: \">\.")
X
X
X;; ----------------------------------------------------------------------
X;; separator string between the sc-citation-delimiter and the text
X;;
X(defvar sc-citation-separator " "
X  "*String to use as a separator between the `sc-citation-delimiter' and
Xthe original text.  Normally this character is a single space
Xcharacter though often a single tab character is used.")
X
X
X;; ----------------------------------------------------------------------
X;; regular expression that matches existing citations
X;;
X(defvar sc-cite-regexp "\\s *[a-zA-Z0-9]*\\s *>+"
X  "*Regular expression that describes how an already cited line in an
Xarticle begins.  The regexp is only used at the beginning of a line,
Xso it doesn't need to begin with a '^'.")
X
X
X;; ----------------------------------------------------------------------
X;; regular expression that delimits names from titles
X;;
X(defvar sc-titlecue-regexp "\\s +-+\\s +"
X  "*Regular expression that delineates names from titles in the
Xauthor's name field.  Often, people will set up their name field to
Xlook like this:
X
X     (John Xavier Doe -- Computer Hacker Extraordinaire)
X
XSet to nil to treat entire field as a name.")
X
X
X;; ----------------------------------------------------------------------
X;; variable that holds preferred attribution
X;;
X(defvar sc-preferred-attribution 'firstname
X
X  "*Symbol that specified which portion of the author's name should be
Xused as the attribution string. The value of this variable should be a
Xquoted symbol, based on the following key:
X
X     emailname   -- email address name
X     initials    -- initials of author
X     firstname   -- first name of author
X     lastname    -- last name of author
X     middlename1 -- first middle name of author
X     middlename2 -- second middle name of author
X     ...
X
XMiddlename indexes can be any positive integer greater than 0, though
Xit is unlikely that many authors will supply more than one middle
Xname, if that many.
X
XType \\<sc-leached-keymap>\\[sc-describe] for information.")
X
X
X;; ----------------------------------------------------------------------
X;; mail fields list
X;;
X(defvar sc-mail-fields-list
X  '("date" "message-id"  "subject" "newsgroup" "references"
X    "from" "return-path" "path"    "reply"     "organization")
X
X  "*List of mail fields that you may want to use to build your
Xreference header. Each field should be a string which will be passed
Xto `mail-fetch-field'.  
X
XSee `sc-field' for information on how to use these fields in your
Xreference header, or type \\<sc-leached-keymap>\\[sc-describe].")
X
X
X;; ----------------------------------------------------------------------
X;; mumble string
X;;
X(defvar sc-mumble-string "mumble"
X  "*Value returned by `sc-field' if chosen field cannot be found. You
Xmay want to set this to nil.")
X
X
X;; ----------------------------------------------------------------------
X;; reference header tag string
X;;
X(defvar sc-reference-tag-string ">>>>> "
X  "*String that delineates reference header lines from the rest of the
Xcited text. This is annoying to some people. If you're one of them,
Xset this variable to the empty string, or whatever you choose.")
X
X
X;; ----------------------------------------------------------------------
X;; preferred header
X;;
X(defvar sc-preferred-header-style 1
X  "*Integer specifying which header rewrite function the user prefers
Xto use in citation references.  This variable is used as an index into
X`sc-rewrite-header-list' when writing a reference.  The first function
Xin this list is zero indexed.")
X
X
X;; ----------------------------------------------------------------------
X;; header list
X;;
X(defvar sc-rewrite-header-list
X  '((sc-no-header)
X    (sc-header-on-said)
X    (sc-header-inarticle-writes)
X    (sc-header-regarding-writes)
X    (sc-header-verbose)
X    (sc-header-attributed-writes)
X    )
X  "*Contains a list of functions.  Each function in this list is a
Xreference header rewrite function that is used when inserting a
Xcitation reference header at the top of a cited body of text.  The
Xvariable `sc-preferred-header-style' controls which function is chosen
Xfor automatic reference inserting.  Electric reference mode will cycle
Xthrough this list rewrite functions.  Here's a list of predefined
Xheader styles which you can use as a model for writing your own:
X
X     sc-no-header:
X          {nothing is written}
X
X     sc-header-on-said [default]:
X          On <date>
X          <from> said:
X
X     sc-header-inarticle-writes:
X          In article <message-id> <from> writes:
X
X     sc-header-regarding-writes:
X          Regarding <subject>; <from> adds:
X
X     sc-header-verbose:
X          On <date>, <from>
X          from the organization <organization>
X          has this to say about article <message-id>
X          in newsgroups <newsgroups>
X          concerning <subject>
X          referring to previous articles <reference>
X          whose comments are cited by \"<citation>\"
X
X     sc-header-attributed-writes:
X          \"<attribution>\" == <author> <from> writes:
X
XEach line of the reference will be prefixed by the
X`sc-reference-tag-string'. If you write your own reference header
Xfunctions, be sure to use this variable.
X
XThe variables that you can use to create your headers are those that
Xare included in `sc-mail-fields-list'.  Some additional fields are
Xalways made available by SUPERCITE.  These are:
X
X     \"sc-author\"       - author of the original article
X     \"sc-firstname\"    - author's firstname
X     \"sc-lastname\"     - author's lastname
X     \"sc-middlename-N\" - author's Nth middlename
X     \"sc-attribution\"  - user chosen attribution string
X     \"sc-citation\"     - user chosen citation string
X     \"from\"            - the value of the \"From:\" field
X
XAny of these field names can be used (as strings) as arguments to
X`sc-field'.")
X
X
X;; ----------------------------------------------------------------------
X;; variable controlling citation type, nested or non-nested
X;;
X(defvar sc-nested-citation-p nil
X  "*Non-nil uses nested citations, nil uses non-nested citations.
XNested citations are of the style:
X
X     I wrote this
X     > He wrote this
X     >> She replied to something he wrote
X
XNon-nested citations are of the style:
X
X     I wrote this
X     John> He wrote this
X     Jane> She originally wrote this")
X
X
X;; ----------------------------------------------------------------------
X;; confirmation control flag
X;;
X(defvar sc-confirm-always-p t
X  "*If t, always confirm attribution string before citing text body.")
X
X
X;; ----------------------------------------------------------------------
X;; non-nil means downcase the author's name string
X;;
X(defvar sc-downcase-p nil
X  "*Non-nil means downcase the attribution and citation strings.")
X
X
X;; ----------------------------------------------------------------------
X;; controls removal of leading white spaces
X;;
X(defvar sc-left-justify-p nil
X  "*If non-nil, delete all leading white space before citing.")
X
X
X;; ----------------------------------------------------------------------
X;; controls auto filling of region
X;;
X(defvar sc-auto-fill-region-p nil
X  "*If non-nil, automatically fill each paragraph after it has been cited.")
X
X
X;; ----------------------------------------------------------------------
X;; use electric references
X;;
X(defvar sc-electric-references-p t
X  "*Use electric references if non-nil.")
X
X
X;; ----------------------------------------------------------------------
X;; use only the preferred attribution?
X;;
X(defvar sc-use-only-preference-p nil
X  "*This variable controls what happens when the preferred attribution
Xstring cannot be found.  If non-nil, then `sc-default-attribution'
Xwill be used. If nil, then some secondary scheme will be employed to
Xfind a suitable attribution string.")
X
X
X;; ----------------------------------------------------------------------
X;; user customization load hook
X;;
X(defvar sc-load-hook nil
X  "*User definable hook which runs after supercite is loaded.")
X
X
X;; ----------------------------------------------------------------------
X;; run hook
X;;
X(defvar sc-run-hook nil
X  "*User definable hook which runs after `sc-cite-original' is
Xexecuted.")
X
X
X;; ----------------------------------------------------------------------
X;; fill function hook
X;;
X(defvar sc-fill-paragraph-hook 'sc-fill-paragraph
X  "*Hook for filling a paragraph.  This hook gets executed when you
Xfill a paragraph either manually or automagically. It expects point to
Xbe within the extent of the paragraph that is going to be filled.")
X
X
X;; ----------------------------------------------------------------------
X;; default keymap
X;;
X(defvar sc-default-keymap
X  '(lambda ()
X     (local-set-key "\C-c\C-r" 'sc-insert-reference)
X     (local-set-key "\C-c\C-t" 'sc-cite)
X     (local-set-key "\C-c\C-a" 'sc-recite)
X     (local-set-key "\C-c\C-u" 'sc-uncite)
X     (local-set-key "\C-c\C-i" 'sc-insert-citation)
X     (local-set-key "\C-c\C-o" 'sc-open-line)
X     (local-set-key "\C-c\C-q" 'sc-fill-paragraph-manually)
X     (local-set-key "\C-c\q"   'sc-fill-paragraph-manually)
X     (local-set-key "\C-c\C-m" 'sc-modify-information)
X     (local-set-key "\C-c?"    'sc-describe)
X     )
X  "*Default keymap if major-mode can't be found in `sc-local-keymaps'.")
X
X
X;; ----------------------------------------------------------------------
X;; keymap per-interface list
X;;
X(defvar sc-local-keymaps
X  '((mail-mode
X     (lambda ()
X       (local-set-key "\C-c\C-r" 'sc-insert-reference)
X       (local-set-key "\C-c\C-t" 'sc-cite)
X       (local-set-key "\C-c\C-a" 'sc-recite)
X       (local-set-key "\C-c\C-u" 'sc-uncite)
X       (local-set-key "\C-c\C-i" 'sc-insert-citation)
X       (local-set-key "\C-c\C-o" 'sc-open-line)
X       (local-set-key "\C-c\C-q" 'sc-fill-paragraph-manually)
X       (local-set-key "\C-c\q"   'sc-fill-paragraph-manually)
X       (local-set-key "\C-c\C-m" 'sc-modify-information)
X       (local-set-key "\C-c?"    'sc-describe)
X       ))
X    (mh-letter-mode
X     (lambda ()
X       (local-set-key "\C-c\C-r" 'sc-insert-reference)
X       (local-set-key "\C-c\C-t" 'sc-cite)
X       (local-set-key "\C-c\C-a" 'sc-recite)
X       (local-set-key "\C-c\C-u" 'sc-uncite)
X       (local-set-key "\C-ci"    'sc-insert-citation)
X       (local-set-key "\C-c\C-o" 'sc-open-line)
X       (local-set-key "\C-c\q"   'sc-fill-paragraph-manually)
X       (local-set-key "\C-c\C-m" 'sc-modify-information)
X       (local-set-key "\C-c?"    'sc-describe)
X       ))
X    (news-reply-mode mail-mode)
X    (vm-mail-mode mail-mode)
X    (e-reply-mode mail-mode)
X    (n-reply-mode mail-mode)
X    )
X  "*List of keymaps to use with the associated major-mode.")
X
X
X;; **********************************************************************
X;; 
X;; end of user defined variables
X;; 
X;; **********************************************************************
X
X
X;; ======================================================================
X;; global variables, not user accessable
X;;
X
X;; ----------------------------------------------------------------------
X;; the new citation style means we can clean out other headers in
X;; addition to those previously cleaned out.  anyway, we create our
X;; own headers.  cleans out mail, gnus, vm and other headers. add to
X;; this for other mail or news readers you may be using.
X;;
X(setq mail-yank-ignored-headers
X      (concat
X       "^via:\\|^origin:\\|^status:\\|^received:\\|^remailed\\|"
X       "^[a-z-]*message-id:\\|^\\(summary-\\)?line[s]?:\\|^cc:\\|"
X       "^subject:\\|^\\(\\(in-\\)?reply-\\)?to:\\|^sender:\\|^replied:\\|"
X       "^\\(\\(return\\|reply\\)-\\)?path:\\|^\\(posted-\\)?date:\\|"
X       "^\\(mail-\\)?from:\\|^newsgroup[s]?:\\|^organization:\\|^keywords:\\|"
X       "^distribution:\\|^xref:\\|^references:\\|^x-mailer:\\|"
X       "^\\(x-\\)?followup-to:\\|^x-vm-attributes:\\|^expires:\\|"
X       "^approved:\\|^apparently-to:\\|^summary:\\|"
X       "^x-vm-attributes:\\|^x-vm-v[0-9]+-data:"))
X
X
X;; ----------------------------------------------------------------------
X;; global alists
X;;
X(setq sc-gal-attributions nil)
X(setq sc-gal-information  nil)
X
X
X;; ----------------------------------------------------------------------
X;; misc variables
X;;
X(setq sc-force-confirmation-p nil)
X(setq sc-fill-arg nil)
X(setq sc-electric-bufname "*Supercite Electric Reference*")
X(setq sc-leached-keymap (current-local-map))
X
X
X;; ======================================================================
X;; update global alists
X
X;; ----------------------------------------------------------------------
X;; update the global var alist
X;;
X(defun sc-update-gal (attribution)
X  "Update the `sc-gal-information' alist to include the ATTRIBUTION
Xand the nested and non-nested citations derived from ATTRIBUTION.
XAssociate with keys \"sc-attribution\", \"sc-nested-citation\", and
X\"sc-citation\" respectively."
X  (let ((attrib (if sc-downcase-p (downcase attribution) attribution)))
X    (aput 'sc-gal-information "sc-attribution" attrib)
X    (aput 'sc-gal-information "sc-nested-citation"
X	  (concat attrib sc-citation-delimiter))
X    (aput 'sc-gal-information "sc-citation"
X	  (concat attrib sc-citation-delimiter sc-citation-separator))))
X
X
X;; ======================================================================
X;; this section snarfs mail fields and places them in the info alist
X
X;; ----------------------------------------------------------------------
X;; fetch all the fields
X;;
X(defun sc-fetch-fields (start end)
X  "Fetch the mail fields in the region from START to END, and add them
Xto the global alist, `sc-gal-information'.  These fields can be
Xaccessed in reference headers with `sc-field'."
X  (save-excursion
X    (save-restriction
X      (narrow-to-region start end)
X      (goto-char start)
X      (mapcar
X       (function
X	(lambda (field)
X	  (let ((value (mail-fetch-field field)))
X	    (and value
X		 (aput 'sc-gal-information field value)))))
X       sc-mail-fields-list)
X      (aput 'sc-gal-information "from" (mail-fetch-field "from")))))
X
X
X;; ----------------------------------------------------------------------
X;; return the field's value
X;;
X(defun sc-field (field)
X  "Return the value associated with the FIELD.  If FIELD was not
Xfound, return `sc-mumble-string'."
X  (or (aget sc-gal-information field)
X      sc-mumble-string))
X
X
X;; ======================================================================
X;; contains supplied header reference rewrite functions
X
X
X;; ----------------------------------------------------------------------
X;; no header is written
X;;
X(defun sc-no-header ()
X  "Does nothing. Use this instead of nil to get a blank header."
X  ())
X
X
X;; ----------------------------------------------------------------------
X;; On <date>, <so-and-so> said:
X;;
X(defun sc-header-on-said ()
X  "\"On <date>, <from> said:\""
X  (insert-string sc-reference-tag-string
X		 "On " (sc-field "date") ", " (sc-field "from") " said:\n"))
X
X
X;; ----------------------------------------------------------------------
X;; In article <blah>, <so-and-so> writes:
X;;
X(defun sc-header-inarticle-writes ()
X  "\"In article <message-id>, <from> writes:\""
X  (insert-string sc-reference-tag-string
X		 "In article " (sc-field "message-id")
X		 ", " (sc-field "from") " writes:\n"))
X
X
X;; ----------------------------------------------------------------------
X;; Regarding <subject>, <so-and-so> adds:
X;;
X(defun sc-header-regarding-writes ()
X  "\"Regarding <subject>; <from> adds:\""
X  (insert-string sc-reference-tag-string
X		 "Regarding " (sc-field "subject")
X		 "; " (sc-field "from") " adds:\n"))
X
X
X;; ----------------------------------------------------------------------
X;; too verbose to comment
X;;
X(defun sc-header-verbose ()
X  "Very verbose."
X  (let ((cr (concat "\n" sc-reference-tag-string)))
X    (insert-string sc-reference-tag-string
X		   "On " (sc-field "date") "," (sc-field "from")
X		   cr "from the organization " (sc-field "organization")
X		   cr "had this to say about article " (sc-field "message-id")
X		   cr "in newsgroups " (sc-field "newsgroups")
X		   cr "concerning " (sc-field "subject")
X		   cr "referring to previous articles " (sc-field "references")
X		   cr "whose comments are cited by \""
X		   (sc-field "sc-citation")
X		   " \".\n" )))
X
X
X;; ----------------------------------------------------------------------
X;; yet another style
X;;
X(defun sc-header-attributed-writes ()
X  "\"<sc-attribution>\" == <sc-author> <sc-from> writes:"
X  (insert-string sc-reference-tag-string
X		 "\"" (sc-field "sc-attribution")
X		 "\" == " (sc-field "sc-author") " "
X		 (sc-field "sc-from") "writes:\n"))
X
X
X;; ======================================================================
X;; this section queries the user for necessary information
X;;
X
X;; ----------------------------------------------------------------------
X;; query the user for the attribution string
X;;
X(defun sc-query (default)
X  "Query for an attribution string with the DEFAULT choice.  Returns
Xthe string entered by the user, if non-empty and non-nil, or DEFAULT
Xotherwise."
X  (let* ((prompt (concat "Enter attribution string: (default "
X			 default
X			 ") "))
X	 (query (read-input prompt)))
X    (if (or (null query)
X	    (string= query ""))
X	default
X      query)))
X
X
X;; ----------------------------------------------------------------------
X;; confirm the attribution string from the user
X;;
X(defun sc-confirm ()
X  "Confirm the preferred attribution with the user. When this function
Xis called, `sc-gal-attributions' is set and the `aheadsym' of this
Xalist is used as the default selection.  Also, C-g [quit] selects the
Xdefault."
X  (if (or sc-confirm-always-p
X	  sc-force-confirmation-p)
X      (aput 'sc-gal-attributions
X	     (let* ((default (aheadsym sc-gal-attributions))
X		    chosen
X		    (prompt (concat "Complete attribution string: (default "
X				    default
X				    ") "))
X		    (minibuffer-local-completion-map
X		     (copy-keymap minibuffer-local-completion-map)))
X	       (define-key minibuffer-local-completion-map "\C-g"
X		 '(lambda () (interactive) (beep) (exit-minibuffer)))
X	       (setq chosen (completing-read prompt sc-gal-attributions))
X	       (if (or (not chosen)
X		       (string= chosen ""))
X		   default
X		 chosen))))
X  (setq sc-force-confirmation-p nil))
X
X
X;; ======================================================================
X;; this section contains primitive functions used in the email address
X;; parsing schemes.  they extract name fields from various parts of
X;; the "from:" field.
X
X
X;; ----------------------------------------------------------------------
X;; address form: name%[stuff]
X;;
X(defun sc-%-style-address (from-string)
X  "Try to extract \"name\" from an email address string FROM-STRING
Xof the style \"name%machine@machine.\""
X  (and (string-match "[a-zA-Z0-9]+%" from-string 0)
X       (substring from-string (match-beginning 0) (1- (match-end 0)))))
X
X
X;; ----------------------------------------------------------------------
X;; address form: [stuff]name@[stuff]
X;;
X(defun sc-@-style-address (from-string)
X  "Try to extract \"name\" from an email address string FROM-STRING
Xof the style \"name@machine.domain\""
X  (and (string-match "[a-zA-Z0-9]+@" from-string 0)
X       (substring from-string (match-beginning 0) (1- (match-end 0)))))
X
X
X;; ----------------------------------------------------------------------
X;; address form: [stuff]![stuff]...!name[stuff]
X;;
X(defun sc-!-style-address (from-string)
X  "Try to extract \"name\" from an email address string FROM-STRING
Xof the style \"machine!machine!...!name\""
X  (let ((eostring (string-match "$" from-string 0))
X	(mstart (string-match "![a-zA-Z0-9]+\\([^!a-zA-Z0-9]\\|$\\)"
X			      from-string 0))
X	(mend (match-end 0)))
X    (if mstart
X	(substring from-string (1+ mstart) (if (= mend eostring)
X					       mend
X					     (1- mend)))
X      nil)))
X
X
X;; ----------------------------------------------------------------------
X;; no style addresses, like local names: "name"
X;;
X(defun sc-no-style-address (from-string)
X  "Try to extract \"name\" from an email address string FROM-STRING
Xof the style \"name\""
X  (and (string-match "[a-zA-Z0-9]+" from-string 0)
X       (substring from-string (match-beginning 0) (match-end 0))))
X
X
X;; ----------------------------------------------------------------------
X;; get one of the email style names
X;;
X(defun sc-get-emailname (from-string)
X  "Using various email address string parsing schemes, try each one
Xuntil you get a non nil, non-empty string. FROM-STRING is the mail
Xaddress string to parse."
X  (cond
X   ((sc-%-style-address from-string))
X   ((sc-@-style-address from-string))
X   ((sc-!-style-address from-string))
X   ((sc-no-style-address from-string))
X   (t (substring from-string 0 10))))
X
X
X;; ======================================================================
X;; this section contains functions that will extract a list of names
X;; from the name field string.
X
X
X;; ----------------------------------------------------------------------
X;; returns the "car" of the namestring, really the first namefield
X;;
X(defun sc-string-car (namestring)
X  "Return the string-equivalent \"car\" of NAMESTRING, really the
Xfirst name field.
X
X     example: (sc-string-car \"John Xavier Doe\")
X              => \"John\""
X  (substring namestring
X	     (progn (string-match "\\s *" namestring) (match-end 0))
X	     (progn (string-match "\\s *\\S +" namestring) (match-end 0))))
X
X
X;; ----------------------------------------------------------------------
X;; returns the "cdr" of the namestring, really the whole string from
X;; after the first name field to the end of the string.
X;;
X(defun sc-string-cdr (namestring)
X  "Return the string-equivalent \"cdr\" of NAMESTRING, really the name
Xstring from after the first name field to the end of the string.
X
X     example: (sc-string-cdr \"John Xavier Doe\")
X              => \"Xavier Doe\""
X  (substring namestring
X	     (progn (string-match "\\s *\\S +\\s *" namestring) (match-end 0))))
X
X
X;; ----------------------------------------------------------------------
X;; extract the namestring from the "from:" string
X;;
X(defun sc-extract-namestring (from-string)
X  "Parse FROM-STRING which contains the string on the \"From: \" line,
Xfrom just after the \"From: \" string to the end of the line.  It
Xreturns the string which should be the full name of the user, minus
Xthe title."
X  (let ((pstart (string-match "(.*)" from-string 0))
X	(pend (match-end 0))
X	(qstart (string-match "\".*\"" from-string 0))
X	(qend (match-end 0))
X	(bstart (string-match "\\([.a-zA-Z0-9---]+\\s *\\)+" from-string 0))
X	(bend (match-end 0)))
X    (cond
X     (pstart (substring from-string
X			(1+ pstart)
X			(or (string-match sc-titlecue-regexp
X					  from-string
X					  (1+ pstart))
X			    (1- pend))))
X     (qstart (substring from-string
X			(1+ qstart)
X			(or (string-match sc-titlecue-regexp
X					  from-string
X					  (1+ qstart))
X			    (1- qend))))
X     (bstart (substring from-string
X			bstart
X			(or (string-match sc-titlecue-regexp
X					  from-string
X					  bstart)
X			    bend))))))
X
X
X;; ----------------------------------------------------------------------
X;; convert a namestring to a list of namefields
X;;
X(defun sc-namestring-to-list (namestring)
X  "Convert NAMESTRING to a list of names.
X
XExample: (sc-namestring-to-list \"John Xavier Doe\")
X=> (\"John\" \"Xavier\" \"Doe\")"
X  (if (not (string-match namestring ""))
X      (append (list (sc-string-car namestring))
X	      (sc-namestring-to-list (sc-string-cdr namestring)))))
X
X
X;; ----------------------------------------------------------------------
X;; given the from-string, return the name list
X;;
X(defun sc-get-namelist (from-string)
X  "Parse the FROM-STRING and return a list of author names in the
Xorder in which they appear in the name field."
X  (sc-namestring-to-list (sc-extract-namestring from-string)))
X
X
X;; ----------------------------------------------------------------------
X;; strip the initials from each item in the list and return a string
X;; that is the concatenation of the initials
X;;
X(defun sc-strip-initials (namelist)
X  "Snag the first character from each name in the list NAMELIST and
Xconcat them into initials."
X  (if (not namelist)
X      nil
X    (concat (substring (car namelist) 0 1)
X	    (sc-strip-initials (cdr namelist)))))
X
X
X;; ======================================================================
X;; this section handles selection of the attribution and citation strings
X;;
X
X;; ----------------------------------------------------------------------
X;; populate alists
X;;
X(defun sc-populate-alists (from-string)
X  "Using the FROM-STRING, populate the association lists
X`sc-gal-attributions' and `sc-gal-information' with important and
Xuseful information. Return the list of name symbols."
X  (let* ((namelist (sc-get-namelist from-string))
X	 (revnames (reverse (cdr namelist)))
X	 (midnames (reverse (cdr revnames)))
X	 (firstname (car namelist))
X	 (midnames (reverse (cdr revnames)))
X	 (lastname (car revnames))
X	 (initials (sc-strip-initials namelist))
X	 (emailname (sc-get-emailname from-string))
X	 (n 1)
X	 (symlist '(emailname initials firstname lastname)))
X
X    ;; put basic information
X    (aput 'sc-gal-attributions 'firstname firstname)
X    (aput 'sc-gal-attributions 'lastname lastname)
X    (aput 'sc-gal-attributions 'emailname emailname)
X    (aput 'sc-gal-attributions 'initials initials)
X
X    (aput 'sc-gal-information "sc-firstname" firstname)
X    (aput 'sc-gal-information "sc-lastname" lastname)
X    (aput 'sc-gal-information "sc-emailname" emailname)
X    (aput 'sc-gal-information "sc-initials" initials)
X
X    ;; put middle names
X    (mapcar
X     (function
X      (lambda (name)
X	(let ((symbol (intern (format "middlename%d" n)))
X	      (string (format "sc-middlename-%d" n)))
X	  (aput 'sc-gal-attributions symbol name)
X	  (aput 'sc-gal-information string name)
X	  (setq n (1+ n))
X	  (nconc symlist (list symbol)))))
X     midnames)
X
X    ;; build the sc-author entry
X    (aput 'sc-gal-information "sc-author"
X	  (concat firstname " " (mapconcat
X				 (function
X				  (lambda (name) name))
X				 midnames " ")
X		  (if midnames " ") lastname))
X    symlist))
X
X
X;; ----------------------------------------------------------------------
X;; sort the attribution alist so that preference is at head
X;;
X(defun sc-sort-attribution-alist ()
X  "Sort the `sc-gal-attributions' alist so that the preferred
Xattribution is at the head of the list. Use secondary methods if
Xnecessary."
X  (asort 'sc-gal-attributions sc-preferred-attribution)
X
X  ;; use backup scheme if preference is not legal
X  (if (or (null sc-preferred-attribution)
X	  (anot-head-p sc-gal-attributions sc-preferred-attribution)
X	  (let ((prefval (aget sc-gal-attributions
X			       sc-preferred-attribution)))
X	    (or (null prefval)
X		(string= prefval ""))))
X      ;; no legal attribution
X      (if sc-use-only-preference-p
X	  (aput 'sc-gal-attributions 'sc-user-query
X		(sc-query sc-default-attribution))
X	;; else use secondary scheme
X	(asort 'sc-gal-attributions 'firstname))))
X
X
X;; ----------------------------------------------------------------------
X;; build the attribution alist for the first time
X;;
X(defun sc-build-attribution-alist (from-string)
X  "Using the FROM-STRING, set up `sc-gal-attributions' to be the list
Xof possible attributions, with preference applied."
X  (let ((symlist (sc-populate-alists from-string))
X	(headval (progn (sc-sort-attribution-alist)
X			(aget sc-gal-attributions
X			      (aheadsym sc-gal-attributions)))))
X
X    ;; foreach element in the symlist, remove the corresponding key-value
X    ;; pair in the alist, then insert just the value.
X    (mapcar
X     (function
X      (lambda (symbol)
X	(let ((value (aget sc-gal-attributions symbol)))
X	  (if (not (or (null value)
X		       (string= value "")))
X	      (aput 'sc-gal-attributions value))
X	  (adelete 'sc-gal-attributions symbol))))
X     symlist)
X
X    ;; now reinsert the head (preferred) attribution, this effectively
X    ;; just moves the head value to the front of the list.
X    (aput 'sc-gal-attributions headval)
X
X    ;; check to be sure alist is not nil
X    (if (null sc-gal-attributions)
X	(aput 'sc-gal-attributions sc-default-attribution))))
X
X
X;; ----------------------------------------------------------------------
X;; using the global attribution alist, confirm that that's the one wanted
X;; by the user.
X;;
X(defun sc-select ()
X  "Select an attribution and create a citation from that, using the
Xglobal alist `sc-gal-attributions'. If a previous global attribution
Xalist has been built, do not rebuild, but confirm again if
Xconfirmation is desired."
X  (cond
X   (sc-nested-citation-p
X    (sc-update-gal ""))
X   ((null (aget sc-gal-information "from" t))
X    (aput 'sc-gal-information "sc-author" sc-default-author-name)
X    (sc-update-gal (sc-query sc-default-attribution)))
X   ((null sc-gal-attributions)
X    (sc-build-attribution-alist (aget sc-gal-information "from" t))
X    (sc-confirm)
X    (sc-update-gal (aheadsym sc-gal-attributions)))
X   (t
X    (sc-confirm)
X    (sc-update-gal (aheadsym sc-gal-attributions)))))
X
X
X;; ======================================================================
X;; region citing and unciting
X
X;; ----------------------------------------------------------------------
X;; cite a region
X;;
X(defun sc-cite-region (start end)
X  "Cite a region delineated by START and END, by inserting the
Xcitation string at the beginning of every non-blank line in the
Xregion, if nested citations are used. Insert the citation string at
Xthe beginning of every non-blank, not-already-cited line if non-nested
Xcitations are used."
X  (save-excursion
X    (set-mark end)
X    (goto-char start)
X    (beginning-of-line)
X    (let ((fstart (point))
X	  (fend   (point)))
X      
X      (while (< (point) (mark))
X	
X	;; remove leading whitespace if desired 
X	(and sc-left-justify-p
X	     (fixup-whitespace))
X	
X	;; if end of line then perhaps autofill
X	(cond ((eolp)
X	       (or (= fstart fend)
X		   (not sc-auto-fill-region-p)
X		   (save-excursion (set-mark fend)
X				   (goto-char (/ (+ fstart fend 1) 2))
X				   (run-hooks 'sc-fill-paragraph-hook)))
X	       (setq fstart (point)
X		     fend (point)))
X	      
X	      ;; not end of line so perhap cite it
X	      ((not (looking-at sc-cite-regexp))
X	       (insert (aget sc-gal-information "sc-citation")))
X	      (sc-nested-citation-p
X	       (insert (aget sc-gal-information "sc-nested-citation"))))
X	
X	(setq fend (point))
X	(forward-line)))))
X
X
X;; ----------------------------------------------------------------------
X;; uncite a region
X;;
X(defun sc-uncite-region (start end cite-regexp)
X  "Remove citations from region delineated by START and END by
Xremoving CITE-REGEXP at the beginning of each line that starts with
XCITE-REGEXP. Unciting also auto-fills if flag is set."
X  (save-excursion
X    (set-mark end)
X    (goto-char start)
X    (beginning-of-line)
X    (let ((fstart (point))
X	  (fend (point)))
X
X      (while (< (point) (mark))
X
X	;; if end of line, then perhaps autofill
X	(cond ((eolp)
X	       (or (= fstart fend)
X		   (not sc-auto-fill-region-p)
X		   (save-excursion (set-mark fend)
X				   (goto-char (/ (+ fstart fend 1) 2))
X				   (run-hooks 'sc-fill-paragraph-hook)))
X	       (setq fstart (point)
X		     fend (point)))
X
X	      ;; not end of line so perhaps uncite it
X	      ((looking-at cite-regexp)
X	       (save-excursion
X		 (save-restriction
X		   (narrow-to-region (progn (beginning-of-line)
X					    (point))
X				     (progn (end-of-line)
X					    (point)))
X		   (beginning-of-line)
X		   (delete-region (point-min)
X				  (progn (re-search-forward cite-regexp
X							    (point-max)
X							    t)
X					 (match-end 0)))))))
X	(setq fend (point))
X	(forward-line)))))
X
X
X;; ======================================================================
X;; this section contains paragraph filling support
X
X;; ----------------------------------------------------------------------
X;; try to figure out the fill-prefix on the current line
X;;
X(defun sc-guess-fill-prefix ()
X
X  "Examine the current line, and try to figure out the prefix being
Xused on that line, using a couple of heuristics.  Search begins on
Xfirst non-blank line in the region of interest.
X
X     1) If `fill-prefix' is already bound to the empty string, return
X        nil.
X
X     2) If `fill-prefix' is already bound, but not to the empty
X        string, return the value of `fill-prefix'.
X
X     3) If the current line starts with the last chosen citation
X        string, then that string is returned.
X
X     4) If the current line starts with a string matching the regular
X        expression, `sc-cite-regexp', then that string is returned.
X
X     5) Nil is returned."
X  (save-excursion
X
X    ;; scan for first non-blank line in the region
X    (beginning-of-line)
X    (while (and (< (point) (mark))
X		(eolp))
X      (forward-line))
X
X    (let ((citation (aget sc-gal-information "sc-citation")))
X      (cond
X       ((string= fill-prefix "") nil)
X       (fill-prefix)
X       ((looking-at (regexp-quote citation)) citation)
X       ((looking-at sc-cite-regexp)
X	(buffer-substring
X	 (point) (progn
X		   (re-search-forward (concat sc-cite-regexp "\\s *")
X				      (point-max) nil)
X		   (point))))
X       ((looking-at (concat ".*" sc-citation-delimiter "\\s *"))
X	(buffer-substring
X	 (point) (progn (re-search-forward (concat ".*" sc-citation-delimiter
X						   "\\s *"))
X			(point))))
X       (t nil)))))
X
X
X;; ----------------------------------------------------------------------
X;; check all lines in real paragraph for beginning with fill-prefix
X;;
X(defun sc-consistant-cite-p (prefix)
X  "Check current *real* paragraph (i.e. paragraph delineated by
X`(forward|backward)-paragraph') to see if all lines start with prefix.
XReturns t if the entire paragraph is consistantly cited, nil
Xotherwise."
X  (save-excursion
X    (let ((end   (progn (forward-paragraph)
X			(beginning-of-line)
X			(or (not (eolp))
X			    (forward-char -1))
X			(point)))
X	  (start (progn (backward-paragraph)
X			(beginning-of-line)
X			(or (not (eolp))
X			    (forward-char 1))
X			(point)))
X	  (badline t))
X      
X      (goto-char start)
X      (beginning-of-line)
X      (while (and (< (point) end)
X		  badline)
X	(setq badline (looking-at prefix))
X	(forward-line))
X      badline)))
X
X
X;; ----------------------------------------------------------------------
X;; look for the beginning of consistant citation
X;;
X(defun sc-fill-start (fill-prefix)
X  "Return the position of the beginning of the region around point that
Xstarts with the FILL-PREFIX. Restrict scan to current paragraph."
X  (save-excursion
X    (let ((badline nil)
X	  (top (save-excursion
X		 (backward-paragraph)
X		 (beginning-of-line)
X		 (or (not (eolp))
X		     (forward-char 1))
X		 (point))))
X      (while (and (not badline)
X		  (> (point) top))
X	(forward-line -1)
X	(setq badline (not (looking-at fill-prefix)))))
X    (forward-line)
X    (point)))
X
X
X;; ----------------------------------------------------------------------
X;; look for the end of consistant citation
X;;
X(defun sc-fill-end (fill-prefix)
X  "Return the position of the end of the region around point that
Xstarts with the FILL-PREFIX. Restrict scan to current paragraph."
X  (save-excursion
X    (let ((badline nil)
X	  (bot (save-excursion
X		 (forward-paragraph)
X		 (beginning-of-line)
X		 (or (not (eolp))
X		     (forward-char -1))
X		 (point))))
X      (while (and (not badline)
X		  (< (point) bot))
X	(beginning-of-line)
X	(setq badline (not (looking-at fill-prefix)))
X	(forward-line 1)))
X    (forward-line -1)
X    (point)))
X
X
X;; ----------------------------------------------------------------------
X;; fill paragraph automagically
X;;
X(defun sc-fill-paragraph ()
X  "Fill the paragraph containing or following point, automagically
Xfinding the paragraph's fill-prefix using heuristics in
X`sc-guess-fill-prefix'.
X
XIf every line in the entire paragraph that encompasses point starts
Xwith the same fill-prefix, then the entire paragraph is automagically
Xfilled. However, if there is inconsistant citing among the lines, then
Xthe user will be queried to restrict the fill to only those lines
Xaround point that begin with the fill-prefix.
X
XThe variable `sc-fill-arg' is passed to `fill-paragraph' and
X`fill-region-as-paragraph' to justify both sides of the paragraph if
Xan argument was given to `sc-fill-paragraph-manually'."
X  (save-excursion
X    (let ((pnt (point))
X	  (fill-prefix (sc-guess-fill-prefix)))
X      (cond
X       ((not fill-prefix)
X	(fill-paragraph sc-fill-arg))
X       ((sc-consistant-cite-p fill-prefix)
X	(fill-paragraph sc-fill-arg))
X       ((y-or-n-p "Inconsistent citation found. Restrict? ")
X	(fill-region-as-paragraph (progn (goto-char pnt)
X					 (sc-fill-start fill-prefix))
X				  (progn (goto-char pnt)
X					 (sc-fill-end fill-prefix))
X				  sc-fill-arg))
X       (t
X	(progn
X	  (setq fill-prefix (aget sc-gal-information "sc-citation"))
X	  (fill-paragraph sc-fill-arg)))))))
X
X
X;; ======================================================================
X;; electric insert reference
X
X;; ----------------------------------------------------------------------
X;; next reference
X;;
X(defun sc-eref-next ()
X  "Display next reference in minibuffer."
X  (interactive)
X  (sc-other-reference 1))
X
X
X;; ----------------------------------------------------------------------
X;; prev reference
X;;
X(defun sc-eref-prev ()
X  "Display previous reference in minibuffer."
X  (interactive)
X  (sc-other-reference -1))
X
X
X;; ----------------------------------------------------------------------
X;; update show buffer
X;;
X(defun sc-eref-show ()
X  "Show the reference buffer."
X  (interactive)
X  (if (get-buffer-window sc-electric-bufname)
X      (delete-windows-on (get-buffer sc-electric-bufname))
X    (let ((curbuffer (buffer-name)))
X      (set-buffer sc-electric-bufname)
X      (setq buffer-read-only nil)
X      (erase-buffer)
X      (goto-char (point-min))
X      (insert-buffer curbuffer)
X      (setq buffer-read-only t)
X      (set-buffer curbuffer)
X      (display-buffer sc-electric-bufname))))
X
X
X;; ----------------------------------------------------------------------
X;; set reference
X;;
X(defun sc-eref-setn ()
X  "Set reference header selected as preferred."
X  (interactive)
X  (setq sc-preferred-header-style
X	(aget sc-gal-information "sc-reference-number"))
X  (message "Preferred reference style set."))
X
X
X;; ----------------------------------------------------------------------
X;; jump to preferred reference header
X;;
X(defun sc-eref-jump ()
X  "Set reference header to preferred header."
X  (interactive)
X  (erase-buffer)
X  (insert (sc-reference-into-buffer sc-preferred-header-style)))
X
X
X;; ----------------------------------------------------------------------
X;; exit from minibuffer
X;;
X(defun sc-eref-exit ()
X  "Exit cleanly from electric reference insert minibuffer."
X  (interactive)
X  (erase-buffer)
X  (beep)
X  (exit-minibuffer))
X
X
X;; ----------------------------------------------------------------------
X;; return a reference and insert into buffer
X;;
X(defun sc-reference-into-buffer (refnum)
X  "Make the electric buffer current and scribble the reference header
Xindexed by REFNUM into that buffer.  Then return the buffer contents
Xas a string."
X  (let ((ref-func  (nth refnum sc-rewrite-header-list))
X	(curbuffer (buffer-name))
X	reference)
X    (get-buffer-create sc-electric-bufname)
X    (set-buffer sc-electric-bufname)
X    (setq buffer-read-only nil)
X    (erase-buffer)
X    (eval ref-func)
X    (setq reference (buffer-substring (point-min) (point-max)))
X    (setq buffer-read-only t)
X    (set-buffer curbuffer)
X    reference))
X
X
X;; ----------------------------------------------------------------------
X;; move to next or previous reference
X;;
X(defun sc-other-reference (delta)
X  "Scribble into the minibuffer the reference header indexed by
Xapplying DELTA to the currently viewed reference. DELTA is normalized
Xto the range of possible values."
X  (let* ((oldrefnum (aget sc-gal-information "sc-reference-number"))
X	 (newrefnum (min (max 0 (+ oldrefnum delta))
X			 (1- (length sc-rewrite-header-list)))))
X    (if (= oldrefnum newrefnum)
X	(error (if (= oldrefnum 0)
X		   "No preceding reference headers in list."
X		 "No following reference headers in list."))
X      (erase-buffer)
X      (aput 'sc-gal-information "sc-reference-number" newrefnum)
X      (insert (sc-reference-into-buffer newrefnum))
X      (goto-char (point-min)))))	       
X
X
X;; ----------------------------------------------------------------------
X;; enter electric insert reference
X;;
X(defun sc-insert-reference-electric ()
X  "Put the current reference header into the minibuffer and allow
Xelectric choosing of the inserted reference header.  While editing
Xthe reference, the following commands are available:
X\\{sc-electric-map}."
X  (let* ((refnum (aget sc-gal-information "sc-reference-number"))
X	 (prompt "Use: ")
X	 (reference (sc-reference-into-buffer refnum))
X	 chosen
X	 (sc-electric-map (copy-keymap minibuffer-local-map)))
X    ;; set up keymap
X    (define-key sc-electric-map "\ep"  'sc-eref-prev)
X    (define-key sc-electric-map "\en"  'sc-eref-next)
X    (define-key sc-electric-map "\ev"  'sc-eref-show)
X    (define-key sc-electric-map "\e."  'sc-eref-setn)
X    (define-key sc-electric-map "\e,"  'sc-eref-jump)
X    (define-key sc-electric-map "\C-g" 'sc-eref-exit)
X
X    ;; read from the minibuffer
X    (setq chosen (read-from-minibuffer prompt reference sc-electric-map))
X    (kill-buffer sc-electric-bufname)
X    chosen))
X
X
X;; ======================================================================
X;; the following functions are the top level, interactive functions that
X;; can be bound to key strokes
X
X;; ----------------------------------------------------------------------
X;; rewrite the header to be more conversational
X;;
X(defun sc-insert-reference (arg)
X  "Rewrite the reference header into a more conversational style and
Xinsert it into the reply buffer.  Two different ways of chosing the
Xreference header style are available to the user.  In both cases, no
Xsupplied numeric ARG means just insert the header indexed by
X`sc-preferred-header-style'.  Numeric ARG supplied is treated
Xdifferently based on the electricity of reference insertion.
X
XIf `sc-electric-references-p' is non-nil, then use electric reference
Xselection.  In this case ARG indicates electric references should be
Xused for the current selection.  See `sc-insert-reference-electric'
Xfor more information.
X
XIf `sc-electric-references-p' is nil, then treat ARG as an index into
Xthe list of reference headers and just directly insert into the
Xmessage buffer."
X  (interactive "P")
X  (let (func)
X    (cond
X     ((or (not arg)
X	  (not (setq func (nth (prefix-numeric-value arg)
X			       sc-rewrite-header-list))))
X      (eval (nth sc-preferred-header-style sc-rewrite-header-list)))
X     (sc-electric-references-p
X      (aput 'sc-gal-information "sc-reference-number" sc-preferred-header-style)
X      (insert (sc-insert-reference-electric)))
X     (t
X      (eval func)))))
X
X
X;; ----------------------------------------------------------------------
X;; attribute and cite the entire region
X;;
X(defun sc-cite (arg)
X  "This is the main function to cite and attribute a region of text in
Xthe reply buffer created by some email reader package.  When this
Xfunction is called, it is assumed that point and mark are set to the
Xregion which is going to be cited and attributed.  It is also assumed
Xthat point points to the beginning of the yanked mail header lines,
Xwhich will first be parsed for useful information, then deleted from
Xthe buffer.  Once this useful information has been glommed from the
Xheaders, an attribution string is found (and confirmed if desired) and
Xthe region of text body is cited.
X
XNumeric ARG is passed to reference insertion function
X`sc-insert-reference'."
X  (interactive "P")
X
X  (and (interactive-p)
X       (setq sc-force-confirmation-p t))
X
X  (sc-select)
X  (undo-boundary)
X  (sc-insert-reference (if (consp arg) arg nil))
X  (let ((xchange (if (> (mark) (point)) nil
X		   (exchange-point-and-mark)
X		   t)))
X    (sc-cite-region (point) (mark))
X
X    ;; leave point on first cited line
X    (while (and (< (point) (mark))
X		(not (looking-at (aget sc-gal-information
X				       (if sc-nested-citation-p
X					   "sc-nested-citation"
X					 "sc-citation")))))
X      (forward-line))
X
X    (and xchange
X	 (exchange-point-and-mark))))
X
X
X;; ----------------------------------------------------------------------
X;; uncite the region
X;;
X(defun sc-uncite ()
X  "Uncite the region."
X  (interactive)
X  (undo-boundary)
X  (let ((xchange (if (> (mark) (point)) nil
X		   (exchange-point-and-mark)
X		   t))
X	(fp (cond ((sc-guess-fill-prefix))
X		  (t ""))))
X
X    (sc-uncite-region (point) (mark) (regexp-quote fp))
X    (and xchange
X	 (exchange-point-and-mark))))
X
X
X;; ----------------------------------------------------------------------
X;; recite the region
X;;
X(defun sc-recite ()
X  "Recite the region by first unciting then citing the text."
X  (interactive)
X  (setq sc-force-confirmation-p t)
X  (sc-select)
X  (undo-boundary)
X  (let ((xchange (if (> (mark) (point)) nil
X		   (exchange-point-and-mark)
X		   t)))
X
X    (sc-uncite-region (point) (mark) (regexp-quote (sc-guess-fill-prefix)))
X    (sc-cite-region (point) (mark))
X    (and xchange
X	 (exchange-point-and-mark))))
X
X
X;; ----------------------------------------------------------------------
X;; insert the citation string at beginning of line
X;;
X(defun sc-insert-citation ()
X  "Insert the citation string at the beginning of the line that point
Xis on."
X  (interactive)
X  (save-excursion
X    (beginning-of-line)
X    (insert-string (aget sc-gal-information "sc-citation"))))
X
X
X;; ----------------------------------------------------------------------
X;; open a line putting the attribution at the beginning
X
X(defun sc-open-line (arg)
X  "Insert a newline and leave point before it.  Also inserts the
Xcitation string at the beginning of the line.  With ARG, inserts that
Xmany newlines."
X  (interactive "p")
X  (save-excursion
X    (let ((start (point)))
X      (open-line arg)
X      (goto-char start)
X      (forward-line)
X      (while (< 0 arg)
X	(sc-insert-citation)
X	(forward-line 1)
X	(setq arg (- arg 1))))))
X
X
X;; ----------------------------------------------------------------------
X;; fill the paragraph manually
X;;
X(defun sc-fill-paragraph-manually (arg)
X  "Interactive program to fill the paragraph containing or following
Xpoint automagically.  All this function really does is run the fill
Xhook, `sc-fill-paragraph-hook'. Global variable `sc-fill-arg' is set
Xto numeric ARG and is used by `sc-fill-paragraph', default program for
X`sc-fill-paragraph-hook'."
X  (interactive "P")
X  (setq sc-fill-arg arg)
X  (run-hooks 'sc-fill-paragraph-hook))
X
X
X;; ----------------------------------------------------------------------
X;; modify sc-gal-information entries
X;;
X(defun sc-modify-information (arg)
X  "Interactively modify information held in the alist
X`sc-gal-information'. Numeric ARG, if supplied, deletes an entry from
Xthe alist. You can easily add an entry to the alist by overriding the
Xcompletion."
X  (interactive "P")
X  (let* ((defaultkey (aheadsym sc-gal-information))
X	 (prompt (concat "Select information key to "
X			 (if (consp arg)
X			     "delete"
X			   "modify")
X			 ": (default "
X			 defaultkey
X			 ") "))
X	 (key (completing-read prompt sc-gal-information)))
X
X    (if (or (string= key "")
X	    (null key))
X	(setq key defaultkey))
X
X    (if (consp arg)
X	(adelete 'sc-gal-information key)
X      (let* ((oldval (aget sc-gal-information key t))
X	     (prompt (concat "Enter new value for key \""
X			     key
X			     "\" (default \""
X			     oldval
X			     "\") "))
X	     (newval (read-input prompt)))
X	(if (or (string= newval "")
X		(null newval))
X	    nil
X	  (aput 'sc-gal-information key newval))))))
X
X
X;; ======================================================================
X;; leach onto current mode
X
X;; ----------------------------------------------------------------------
X;; load local keymap via the hook
X;;
X(defun sc-append-current-keymap ()
X  "In the buffer that is using supercite (usually some type of reply
Xbuffer), append some useful keystrokes to the local key map. Evaluates
X`sc-local-keymaps' for hook to run."
X  (let ((hook (car (cdr (assq major-mode sc-local-keymaps)))))
X    (cond
X     ((not hook)
X      (run-hooks 'sc-default-keymap))
X     ((not (listp hook))
X      (setq hook (car (cdr (assq hook sc-local-keymaps))))
X      (run-hooks 'hook))
X     (t
X      (run-hooks 'hook))))
X  (setq sc-leached-keymap (current-local-map)))
X
X
X;; ----------------------------------------------------------------------
X;; snag all supercite keybindings
X;;
X(defun sc-snag-all-keybindings ()
X  "Snag all keybindings in major-modes current keymap."
X  (let* ((curkeymap (current-local-map))
X	 (symregexp ".*sc-.*\n")
X	 (docstring (substitute-command-keys "\\{curkeymap}"))
X	 (start 0)
X	 (maxend (length docstring))
X	 (spooge ""))
X    (while (and (< start maxend)
X		(string-match symregexp docstring start))
X      (setq spooge (concat spooge (substring docstring
X					     (match-beginning 0)
X					     (match-end 0))))
X      (setq start (match-end 0)))
X    spooge))
X
X
X;; ----------------------------------------------------------------------
X;; spoogify doc string of current major mode
X;;
X(defun sc-spoogify-docstring ()
X  "This function modifies [makes into spooge] the docstring for the
Xcurrent major mode. It uses a cute hack to grab the docstring, add
Xsome text to it, then place it back into the lambda expression for the
Xfunction. NOTE: May bomb out if the major-mode is preloaded"
X  ;; check to be sure it hasn't already been added
X  (let* ((symfunc (symbol-function major-mode))
X	 (doc-cdr (nthcdr 2 symfunc))
X	 (doc-str (documentation major-mode)))
X    (cond
X     ((not (stringp doc-str)))
X     ((string-match "supercite" doc-str))
X     (t
X      (setcar doc-cdr (concat doc-str "
X
XThe major mode for this buffer has been modified to include the
XSUPERCITE 2.0 package for handling attributions and citations of
Xoriginal messages in email replies.  For more information on this
Xpackage, execute the command \"sc-describe\" (see below).  The
Xfollowing keys are bound to SUPERCITE commands:
X
X"
X			      (sc-snag-all-keybindings)))))))
X
X
X;; ======================================================================
X;; this section contains default hooks and hook support for execution
X
X;; ----------------------------------------------------------------------
X;; run citations via hook
X;;
X(defun sc-cite-original ()
X  "Hook version of sc-cite.  This is callable from the various mail and
Xnews readers' reply function to cite the yanked region.  It does not do
Xany yanking of the original message but it does require a few things:
X
X1) The reply buffer is the current buffer
X2) The original message has been yanked and inserted into the reply buffer
X3) Verbose headers from the original message have been inserted into the
X   reply buffer directly before the text of the original message.
X4) Point points to the beginning of the verbose headers
X5) Mark points to the end of the body of text to be cited."
X  
X  (setq sc-gal-attributions nil)
X  (setq sc-gal-information nil)
X  (let ((start (region-beginning))
X	(end   (region-end)))
X    (sc-fetch-fields start end)
X    (mail-yank-clear-headers start end)
X    (sc-cite sc-preferred-header-style)
X    (sc-append-current-keymap)
X    (sc-spoogify-docstring)
X    (run-hooks 'sc-run-hook)
X    ))
X
X
X;; ----------------------------------------------------------------------
X;; rnewspost.el shouldn't rewrite the header.  This only works with
X;; diffs to rnewspost.el that I posted with the original superyank
X;; code.
X;;
X(setq news-reply-header-hook nil)
X
X
X;; ----------------------------------------------------------------------
X;; run the load hook
X;;
X(run-hooks 'sc-load-hook)
X
X
X
X;; ======================================================================
X;; describe this package
X;;
X
X;; ----------------------------------------------------------------------
X;; describe verbosely
X;;
X(defun sc-describe ()
X
X  "This package provides mechanisms for doing sophisticated citing of
Xyanked text in the reply buffers of the major news and email reading
Xmodes. Supercite 2.0 is based on the work done for Superyank 1.11,
Xthough the actual code of the present package bears little resemblance
Xto its predecesor.
X
XSupercite 2.0 has been tested and *seems* to work with GNUS 3.12,
XRMAIL 18.55 and VM 4.37. It is also supposed to work with MH-E mode
Xand perhaps even GNEWS.  Some modifications may be necessary to run
XSupercite with these packages and this is covered in sections below.
X
XAuthor:
X
XNAME: Barry A. Warsaw                USMAIL: National Institute of Standards
XTELE: (301) 975-3460                         and Technology (formerly NBS)
XUUCP: {...}!uunet!cme-durer!warsaw           Rm. B-124, Bldg. 220
XARPA: warsaw@cme.nist.gov                    Gaithersburg, MD 20899
X
XGet on the Supercite mailing list:
X
XSend articles to supercite@cme.nist.gov or uunet!cme-durer!supercite
XSend administrative queries/requests to supercite-request@cme.nist.gov
X	or uunet!cme-durer!supercite-request
X
X-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
X
XWhat is a citation?  A \"citation\" is the acknowledgement of the
Xoriginal author of a mail message, in the body of the reply. The
X\"attribution string\" is the part of the author's name that will be
Xused to cite the body of the text (e.g. \"John\", the author's first
Xname). The \"citation string\" is built from the attribution string,
Xthe \"citation delimiter\", and the \"citation separator\".  It is the
Xstring that is inserted in front of every line to be cited in the
Xreply body (e.g. \"John> \").
X
XThere are two general forms of citation.  In \"nested citations\",
Xindication is made that the cited line was written by someone *other*
Xthan the current message author, but no reference is made as to the
Xidentity of the original author.  Here's an example of what a message
Xbuffer would look like using nested citations after multiple replies:
X
X     >>John originally wrote this
X     >>and this as well
X     > Jane said that John didn't know
X     > what he was talking about
X     And that's what I think too.
X
XIn \"non-nested citations\" each cited line begins with an informative
Xstring referencing the original author.  Only the first level of
Xreferencing will be shown; subsequent cites don't nest the references.
XThe same message described above might look like this if non-nested
Xcitations were used:
X
X     John> John originally wrote this
X     John> and this as well
X     Jane> Jane said that John didn't know
X     Jane> what he was talking about
X     And that's what I think too.
X
XNotice that my inclusion of Jane's inclusion of John's original
Xmessage did not result in a cited line beginning with: \"Jane>John>\".
XThus no nested citations.
X
XFor non-nested citations, a fair amount of intellegence is used to
Xdecipher the author's name from mail header information. This name,
Xalong with email mailbox terminus and the author's initials, are
Xavailable to the Supercite user for use as the attribution string.
XOnce the attribution string is chosen, the citation string is built
Xand is inserted at the front of every line in the region to be cited.
XFinally, a \"reference header\" is inserted at the top of the cited
Xregion, which is usually used to show which citation is linked to
Xwhich author.
X
XThe citing of the text body is undoable, so the user could yank and
Xcite the text, undo, then continually re-cite the text until the
Xdesired citation string is inserted. Often people would like a
Xnickname to be used as the citation string, but this nickname cannot
Xbe picked up by Supercite.  It is a simple matter to undo the original
Xcitation, and then perform a citation with the nickname as the
Xattribution string.
X
X-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
X
XThere are a number of variables which control some of the features
Xdescribed thus far. First there is the variable which controls whether
Xnested or non-nested citations will be used:
X
X          Variable: sc-nested-citation-p
X               controls citation style.  If nil, non-nested citations
X               are used.  If non-nil, old-style nested citations are
X               used.  Default: nil.
X
XWhenever a citation is used, whether nested or non-nested, there is a
Xdistinguishing character or string used to set the cited text apart
Xfrom the rest of the message body. This character or string is set in
Xthe following variable:
X
X          Variable: sc-citation-delimiter
X               string that end-delineates a citation reference.  For
X               nested citations this is the string to insert in front
X               of cited lines.  For non-nested citations, this is the
X               string to insert between the attribution string and the
X               citation separator.  For best results this should be a
X               single character, typically \">\", with no trailing
X               space.  Default: \">\".
X
XA string is inserted between `sc-citation-delimiter' and the original
Xline of text in both nested and non-nested citations.  For nested
Xcitations, this string is only inserted on first level citations.  For
Xnon-nested citations, this string is always inserted (since all
Xcitations are first level).  This string is defined in the following
Xvariable: 
X
X          Variable: sc-citation-separator
X               string that separates between the
X               `sc-citation-delimiter' and the cited line in
X               non-nested citations.  Default: \" \".  (a single
X               space).
X
XOccasionally, for whatever reason, the author's name cannot be found
Xand so a default author name may be used:
X
X          Variable: sc-default-author-name
X               string used when author's name cannot be found.
X               Default: \"Anonymous\".
X
XAlso if the author's name cannot be found, a default attribution
Xstring may be used, from which a legal citation string will be built:
X
X          Variable: sc-default-attribution
X               string used when author's attribution string cannot be
X               found. Default: \"Anon\".
X
XHow does the package determine if a line has already been cited, so
Xthat for non-nested citations, the line won't be recited?  This is
Xaccomplished through the use of a regular expression.
X
X          Variable: sc-cite-regexp
X               regular expression that describes how an already cited
X               line begins.  Default: \"\\\\s *[a-zA-Z0-9]*\\\\s *>+\".
X
X-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
X
XSupercite employs a number of heuristics to decipher the author's name
Xbased on the \"From:\" field which is usually present in all mail and
Xnews reading buffers.  If possible, it will pick out the author's
Xfirst, last and middle names, the author's initials and the author's
Xemail terminus.  Supercite can recognize \"From:\" lines with the
Xfollowing forms:
X
X     From: John Xavier Doe <doe@speedy.computer.com>
X     From: \"John Xavier Doe\" <doe@speedy.computer.com>
X     From: doe@speedy.computer.com (John Xavier Doe)
X     From: computer!speedy!doe (John Xavier Doe)
X     From: doe%speedy@computer.com (John Xavier Doe)
X     From: computer!speedy!doe (John Xavier-Doe)
X     From: computer!speedy!doe (John Xavier-Doe -- Decent Hacker)
X
XOnce Supercite has parsed this field, it puts together a list of these
Xnames and may present them to the user for attribution string
Xselection.
X
XNote that some author fields (as in the last example above) will
Xcontain a descriptive title.  The user can choose to ignore the title,
Xwhile still recognizing hyphenated names, through the use of a regular
Xexpression:
X
X          Variable: sc-titlecue-regexp
X               regular expression that delineates names from titles in
X               the author's name fields.  Default: \"\\\\s +-+\\\\s +\".
X
XSelection of the attribution string is done automatically, however,
Xthe user is able to confirm the selection of attribution string before
Xit is used to cite the region.  The behavior of confirmation is
Xcontrolled by a variable:
X
X          Variable: sc-confirm-always-p
X               if non-nil, always confirm attribution string with user
X               before using to cite text.  If nil, use automatic
X               selection to choose attribution string. Default: t.
X
XIf confirmation is chosen, then the list of possible attribution
Xstrings (the \"alist\") is presented to the user.  A carriage return
Xwill select the \"preferred\" attribution string (see below), and
Xcompletion *is* case sensitive.  The user can override all choices by
Xtyping any string in the minibuffer; this string is taken as the
Xliteral attribution string.
X
XIn the case of the \"From:\" fields above, the alist might look like:
X
X     ((\"doe\") (\"JXD\") (\"John\") (\"Xavier\") (\"Doe\"))
X
Xwith \"doe\" as the preferred attribution string. Say at this point, a
Xconfirmed citation is performed and the user chooses \"John\", then
Xundoes the citation and redoes a confirmed citation.  The alist would
Xlook like:
X
X     ((\"John\") (\"doe\") (\"JXD\") (\"Xavier\") (\"Doe\"))
X
Xwith \"John\" as the preferred attribution string.  Now, the user
Xtypes in the string \"Boss\" as the attribution string, undoes this,
Xthen redoes a confirmed citation.  The alist would look like:
X
X     ((\"Boss\") (\"John\") (\"doe\") (\"JXD\") (\"Xavier\") (\"Doe\"))
X
XIn this way, the user can selectively cite parts of a single message
Xbody, tailoring the citation string to each region being cited.
X
X-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
X
XThe \"preferred\" attribution is settable by the user and is used to
Xindicate which part of the author's name is used for automatic
Xselection of the attribution string, or the preferred default for
Xthe first confirmed selection.
X
X          Variable: sc-preferred-attribution
X               quoted symbol specifying which portion of an author's
X               name should be used when building the attribution
X               string using the following key:
X
X               emailname   -- email terminus
X               initials    -- author's initials
X               firstname   -- first name
X               lastname    -- last name
X               middlename1 -- first middle name
X               middlename2 -- second middle name
X               ...
X
X               Middlename indexes can be any positive integer greater
X               than 0, though it is unlikely that many authors will
X               supply more than one middle name, if that many.
X               Default: 'firstname.
X
XIf automatic selection is used, and the preferred attribution can't be
Xfound, then either the `sc-default-attribution' will be used or some
Xsecondary scheme will be employed to find a non-nil, non-empty
Xattribution string. You can tell Supercite to only use your preferred
Xattribution by setting the variable:
X
X          Variable: sc-use-only-preference-p
X               controls what happens when the preferred attribution
X               string cannot be found.  If non-nil, then
X               `sc-default-attribution' is used, otherwise a secondary
X               scheme is employed.  Default: nil.
X
XThe secondary scheme will first try to use the author's first name. If
Xthat is nil or empty, then the alist is searched for the first
Xnon-nil, non-empty string.  If still no attribution string can be
Xfound, then the user is either queried, or `sc-default-attribution' is
Xused, depending on the value of `sc-confirm-always-p'.
X
XOnce a legal attribution string is found, you can force the string to
Xlower case characters.
X
X          Variable: sc-downcase-p
X               non-nil means downcase the attribution string.
X               Default: nil.
X
X-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
X
XTypically, citation is performed on a body of text that has been
Xyanked from a mail or news reading buffer.  This yanked text should
Xhave the verbose headers at the top of the region to be cited.  As
Xmentioned above, Supercite will parse these headers, picking out
Xuseful information (most notably the \"From:\" line), then delete
Xthose mail headers, and replace them with user customizable reference
Xheaders.  You can have multiple references header styles at your
Xdisposal and can customize your own headers, adding them to the list
Xof those available. This list is kept in the variable:
X
X          Variable: sc-rewrite-header-list
X               list of user customizable reference header rewrite
X               functions.
X               Default: '((sc-no-header)
X                           (sc-header-on-said)
X                           (sc-header-inarticle-writes)
X                           (sc-header-regarding-writes)
X                           (sc-header-verbose)
X                           (sc-header-attributed-writes)).
X
XAdd your own functions to this list or re-order the list to utilize
Xyour own custom reference headers.  A reference header is rewritten
Xautomatically when the text is originally yanked, and a command is
Xprovided that allows the user to call any of the reference header
Xrewrite functions (see below). The header written by default is user
Xcustomizable.
X
X          Variable: sc-preferred-header-style
X               integer specifying which header rewrite function is
X               used when automatically inserting the rewritten header.
X               This is an index into `sc-rewrite-header-list', with
X               the first element indexed as zero.  Default: 1.
X
XAlternatively, you can use electric reference inserting which will pop
Xup the references in the minibuffer for your selection.  You can
Xminimally edit this reference or scan through the list.  Electric
Xreferencing is also available when you use the `sc-insert-reference'
Xcommand (see below).
X
X          Variable: sc-electric-references-p
X               Non-nil specifies use electric references.
X               Default: t.
X
XWhile in the electric reference minibuffer, certain keys are bound to
Xcertain functions.
X
X     (M-p) show previous reference header
X     (M-n) show next reference header
X     (M-v) toggle reference header buffer visible/non-visible. This is
X           especially useful if your reference is multilined, which wouldn't
X           show up nicely in the minibuffer.
X     (M-.) set current visible reference header to be your new preferred
X           reference header by setting `sc-preferred-header-style'
X     (M-,) show preferred reference header
X     (C-g) abort electric references
X     (RET) exit electric references and insert reference into buffer
X
XYou can do some minimal amounts of editing of the references while in
Xelectric reference mode, but edit the minibuffer instead of *Supercite
XElectric Reference* buffer.
X
XYou may want to include some information about the author in your
Xcustom reference headers.  This information can come from the mail
Xheaders or some internal supercite variables.  There is a variable
Xthat describes which mail headers should be fetched and remembered for
Xuse in the reference headers:
X
X          Variable: sc-mail-fields-list
X	       List of mail fields that you may want to use to build
X	       your custom reference header.  Each field should be a
X	       string which will be passed to `mail-fetch-field'.  See
X	       the function `sc-field' for information on how to
X	       access these fields in your reference header.
X	       Default: '(\"date\" \"from\" \"message-id\" \"subject\"
X			  \"newsgroup\" \"references\" \"organization\"
X			  \"return-path\" \"path\" \"reply\")
X
XIn addition to those fields described in `sc-mail-fields-list',
Xsupercite always provides these fields for use: \"sc-attribution\",
X\"sc-nested-citation\", \"sc-citation\", \"from\", \"sc-author\",
X\"sc-firstname\", \"sc-lastname\", \"sc-middlename-1\"....  The middle
Xnames may or may not be present, based on the author's name field.
XThe \"from\" field is always provided just in case you forget to add
Xit to `sc-mail-fields-list'.
X
X-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
X
XSupercite provides some paragraph filling functions, and the user has
Xthe choice of automatically filling each paragraph as it is cited or
Xleaving cited paragraphs unfilled by default, controlled by this
Xvariable: 
X
X          Variable: sc-auto-fill-region-p
X               if non-nil, automatically fill each paragraph after it
X               has been cited.  Default: nil.
X
XWith either automatic or manual filling of paragraphs, the actual
Xfunction used to fill the paragraph is hook-able:
X
X          Variable: sc-fill-paragraph-hook
X               hook for filling a paragraph. run when you fill a
X               paragraph either automatically or manually.
X               Default: 'sc-fill-paragraph.
X
X-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
X
XHere are a couple of other user definable variables.  For more
Xinformation on these or any supercite variable, type:
X\\[describe-variable] <variable-name>.
X
X          Variable: sc-mumble-string
X               String returned by `sc-field' if chosen field can't be
X               found.  Default: \"mumble\".
X
X          Variable: sc-reference-tag-string
X               String that is inserted before reference header lines
X               on those reference rewrite functions which are
X               predefined.  Default: \">>>>> \"
X
X          Variable: sc-left-justify-p
X               if non-nil, delete all leading white space before citing.
X               Default: nil.
X
X          Variable: sc-load-hook
X               user definable hook which runs after supercite is loaded.
X               Default: nil.
X
X          Variable: sc-run-hook
X               user definable hook which runs after `sc-cite-original'
X               executes.
X               Default: nil.
X
X-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
X
XSince every email/news reader uses a different buffer name or
Xmajor-mode to reply in, Supercite can't know ahead of time what the
Xbuffer or major-mode name is. So Supercite needs to leaches onto
Xwhatever buffer the reply is being made in, modifying the keymap and
Xthe documentation string for that buffer. Many of the Supercite 2.0
Xbeta testers used many different readers, so a mechanism was developed
Xto provide a per-interface keymap, which installs itself into the
Xbuffer's current-local-map based on the major-mode of the buffer.
XThere are two variables which control the keymap that gets installed:
X
X          Variable: sc-default-keymap
X               Default keymap to use if major-mode keybinding cannot
X               be found in `sc-local-keymaps'.
X               Keybindings:
X                    (C-c C-r) sc-insert-reference
X                    (C-c C-t) sc-cite
X                    (C-c C-a) sc-recite
X                    (C-c C-u) sc-uncite
X                    (C-c C-i) sc-insert-citation
X                    (C-c C-o) sc-open-line
X                    (C-c C-q) sc-fill-paragraph-manually
X                    (C-c q)   sc-fill-paragraph-manually
X                    (C-c C-m) sc-modify-information
X                    (C-c ?)   sc-supercite
X
X          Variable: sc-local-keymaps
X               Variable which contains a list of interfaces and their
X               keybindings.
X
XSc-local-keymaps is an association list of the form:
X
X     ((MAJOR-MODE [FUNCTION | MAJOR-MODE])*)
X
XWhen it is time to modify the keymap of the current buffer, Supercite
Xlooks up the `major-mode' of that buffer in this association list. If
Xit matches the major mode with a MAJOR-MODE key, the value is
Xreturned, otherwise, the default keymap is installed (see above).
X
XIf the MAJOR-MODE is found and the value is returned, this value is
Xchecked to see if it is a list.  If so, it is assumed that this value
Xis a lambda expression which will set the current local keymap as
Xdesired.  If the value is not a list, it is assumed to be a previously
Xdefined MAJOR-MODE.  This new major mode is looked up and the lambda
Xexpression is evaluated.  Only one level of indirection is possible,
Xbut this does allow you to save space when defining key bindings.
X
X-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
X
XThere are a number of interactive commands that are provided as part
Xof the supercite package. The bindings shown as default are those for
Xmail-mode buffers. Your keybindings may be different so check them
Xwith \\[describe-bindings], *after* supercite has been loaded and the
Xfirst message has been yanked and cited.
X
X          Command: sc-insert-reference
X               insert a reference header. If numeric ARG is not supplied,
X               insert the header indexed by `sc-preferred-header-style'.
X               If ARG is supplied and electric referencing is set, then
X               enter electric referencing.  If electric referencing is
X               not set, then insert the reference indexed by ARG.
X               Default binding: \"\\C-c \\C-r\".
X
X          Command: sc-cite
X               cite a region of text designated by point and mark.
X               Numeric ARG is passed to `sc-insert-reference'.  When
X               run interactively, confirmation is always requested.
X               Default binding: \"\\C-c \\C-t\".
X
X          Command: sc-uncite
X               uncite the region of text designated by point and mark by
X               guessing the fill prefix and removing that from every line
X               beginning with fill prefix in the region.
X               Default binding: \"\\C-c \\C-u\".
X
X          Command: sc-recite
X               recite the region of text designated by point and mark.
X               Reference header is not re-inserted and confirmation is
X               always requested.  Reciting is done by unciting, then
X               citing the region.
X               Default binding: \"\\C-c \\C-a\".
X
X          Command: sc-insert-citation
X               insert the citation string at the beginning of the
X               current line.
X               Default binding: \"\\C-c \\C-i\".
X
X          Command: sc-open-line
X               insert a newline and leave point before it. also insert
X               the citation string at the beginning of the new line.
X               Numeric ARG inserts that many new lines.
X               Default binding: \"\\C-c \\C-o\".
X
X          Command: sc-fill-paragraph-manually
X               fill paragraph containing or following point by running
X               the hook, `sc-fill-paragraph-hook'.  Global variable
X               `sc-fill-arg' is set to numeric ARG (used by
X               `sc-fill-paragraph').
X               Default binding: \"\\C-c \\C-q\" and \"\\C-c q\".
X
X          Command: sc-modify-information
X               interactively add, delete or modify a key value in the
X               attribution list `sc-gal-information'.
X               Default binding: \"\\C-c \\C-m\".
X
X-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
X
XFinally, some discussion on how to interface supercite with the
Xvarious mail/news readers you might be using is in order.  This
Xdiscussion is also useful for those who might be writing a mail/news
Xreader and want to let your users take advantage of Supercite.
X
XThe author runs a Supercite mailing list on which a number of
Xmail/news reader authors and other Supercite users participate.  A
Xwhile back some discussion was held and an interface between these
Xreaders and Supercite was agreed upon.  The ancestor to this package,
XSUPERYANK 1.11 was designed along an old inteface and this package,
XSUPERCITE 2.0 conforms to this new standard.  As of the date of this
Xwriting (12-Oct-1989) only VM 4.37 conforms to this standard as
Xdistributed. GNUS 3.12, RMAIL and MH-E all use functions distributed
Xwith EMACS 18.55 and patches are available to the appropriate files,
Xdistributed along with Supercite as: 
X
X     {rnewspost,sendmail,mh-e}.el.diff
X
XIf you do not want to install the diffs, or are not able to install
Xthem, check the file sup-misc.el.  This file contains overload
Xfunctions which can be selectively loaded to provide the necessary
Xfunctionality.  If you decide to go the overload route, be sure to set
X`sc-load-hook' to something like:
X
X     (setq sc-load-hook '(lambda () (load \"sup-misc\")))
X
XThe variables controlling overloading should be rather self
Xexplanatory in the sup-misc.el file.  This file also contains some
Xmiscellaneous extension to RMAIL. Also, in superyank version 1.11, the
Xfunction `mail-yank-original' was overloaded and bound to \"\\C-c
X\\C-y\". This functionality is provided in this release, but will no
Xlonger be supported.
X
XNow, with Supercite version 2.0, a hook is provided called
X`mail-yank-hooks' which is run *after* the text is yanked.  This way,
Xthe particular mail/news reader handles setting up the reply buffer
Xand yanking the appropriate text into the buffer, but leaves citing
Xthe lines up to external functions. Most readers will provide a simple
Xcitation function hooked in by default, for those who haven't yet
Xdiscovered this superior citation package.  Mh-e users should use
X`mh-yank-hooks' instead of `mail-yank-hooks'.  For these to work you
Xmust have installed diffs to {rnewspost,sendmail,mh-e}.el or used the
Xoverloaded functions supplied in sup-misc.el.
X
XThe mail/news reader should put the verbose mail headers at the top of
Xthe yanked text and leave POINT at the beginning of the headers.  MARK
Xshould point to the end of the yanked text.  Then it should run
X`mail-yank-hooks'.
X
XAdd some of this code to your .emacs file to use supercite 2.0:
X
X     (autoload 'sc-cite-original \"supercite\" \"Hookified Supercite 2.0\" t)
X     (autoload 'sc-cite          \"supercite\" \"Interactive Supercite 2.0\" t)
X     (autoload 'sc-describe      \"supercite\" \"Describe Supercite 2.0\" t)
X     (setq mail-yank-hooks 'sc-cite-original)
X     (setq mh-yank-hooks 'sc-cite-original)
X
XEnjoy, and please send the author your compliments, questions,
Xsuggestions and bug reports.  Don't forget, if you're interested in
Xdiscussing supercite, join the mailing list by sending mail to the
Xrequest line mentioned above."
X
X  (interactive)
X  (describe-function 'sc-describe))
END_OF_FILE
if test 83103 -ne `wc -c <'supercite.el'`; then
    echo shar: \"'supercite.el'\" unpacked with wrong size!
fi
# end of 'supercite.el'
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    echo "Check the README for installation info."
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0