;;; latex.el --- Support for LaTeX documents.
;; 
;; Maintainer: Per Abrahamsen <auc-tex@sunsite.auc.dk>
;; Version: 9.7l
;; Keywords: wp
;; X-URL: http://sunsite.auc.dk/auctex

;; Copyright 1991 Kresten Krab Thorup
;; Copyright 1993, 1994, 1995, 1996, 1997 Per Abrahamsen
;; 
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 1, or (at your option)
;; any later version.
;; 
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;; 
;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

;;; Code:

(require 'tex)

;;; Syntax

(defvar LaTeX-optop "["
  "The LaTeX optional argument opening character.")
(make-variable-buffer-local 'LaTeX-optop)

(defvar LaTeX-optcl "]"
  "The LaTeX optional argument closeing character.")
(make-variable-buffer-local 'LaTeX-optcl)

;;; Style

(defvar LaTeX-default-style "article"
  "*Default when creating new documents.")

  (make-variable-buffer-local 'LaTeX-default-style)

(defvar LaTeX-default-options nil
  "*Default options to documentstyle.
A list of strings.")

 (make-variable-buffer-local 'LaTeX-default-options)

;;; Syntax Table

(defvar LaTeX-mode-syntax-table (copy-syntax-table TeX-mode-syntax-table)
  "Syntax table used in LaTeX mode.")

(progn ; set [] to match for LaTeX.
  (modify-syntax-entry (string-to-char LaTeX-optop)
		       (concat "(" LaTeX-optcl) 
		       LaTeX-mode-syntax-table)  
  (modify-syntax-entry (string-to-char LaTeX-optcl)
		       (concat ")" LaTeX-optop)
		       LaTeX-mode-syntax-table))

;;; Sections

(defun LaTeX-section (arg)
  "Insert a template for a LaTeX section.
Determinate the type of section to be inserted, by the argument ARG.

If ARG is nil or missing, use the current level.
If ARG is a list (selected by C-u), go downward one level.
If ARG is negative, go up that many levels.
If ARG is positive or zero, use absolute level:

  0 : part
  1 : chapter
  2 : section
  3 : subsection
  4 : subsubsection
  5 : paragraph
  6 : subparagraph

The following variables can be set to customize:

LaTeX-section-hook	Hooks to run when inserting a section.
LaTeX-section-label	Prefix to all section labels."
  
  (interactive "*P")
  (let* ((val (prefix-numeric-value arg))
	 (level (cond ((null arg)
		       (LaTeX-current-section))
		      ((listp arg)
		       (LaTeX-down-section))
		      ((< val 0)
		       (LaTeX-up-section (- val)))
		      (t val)))
	 (name (LaTeX-section-name level))
	 (toc nil)
	 (title "")
	 (done-mark (make-marker)))
    (newline)
    (run-hooks 'LaTeX-section-hook)
    (newline)
    (if (marker-position done-mark)
	(goto-char (marker-position done-mark)))
    (set-marker done-mark nil)))

(defun LaTeX-current-section ()
  "Return the level of the section that contain point.
See also LaTeX-section for description of levels."
  (save-excursion
    (max (LaTeX-largest-level)
	 (if (re-search-backward (LaTeX-outline-regexp) nil t)
	     (- (LaTeX-outline-level) (LaTeX-outline-offset))
	   (LaTeX-largest-level)))))

(defun LaTeX-down-section ()
  "Return the value of a section one level under the current. Tries to
find what kind of section that have been used earlier in the text, If
this fail, it will just return one less than the current section."
  (save-excursion 
    (let ((current (LaTeX-current-section))
	  (next nil)
	  (regexp (LaTeX-outline-regexp)))
      (if (not (re-search-backward regexp nil t))
	  (1+ current)
	(while (not next)
	  (cond
	   ((eq (LaTeX-current-section) current)
	    (if (re-search-forward regexp nil t)
		(if (<= (setq next (LaTeX-current-section)) current) ;Wow!
		    (setq next (1+ current)))
	      (setq next (1+ current))))
	   ((not (re-search-backward regexp nil t))
	    (setq next (1+ current)))))
	next))))

(defun LaTeX-up-section (arg)
  "Return the value of the section ARG levels above this one."
  (save-excursion
    (if (zerop arg)
	(LaTeX-current-section)
      (let ((current (LaTeX-current-section)))
	(while (and (>= (LaTeX-current-section) current)
		    (re-search-backward (LaTeX-outline-regexp)
					nil t)))
	(LaTeX-up-section (1- arg))))))

(defvar LaTeX-section-list '(("part" 0)
			     ("chapter" 1)
			     ("section" 2)
			     ("subsection" 3)
			     ("subsubsection" 4)
			     ("paragraph" 5)
			     ("subparagraph" 6))
  "List which elements is the names of the sections used by LaTeX.")

(defun LaTeX-section-name (level)
  "Return the name of the section corresponding to LEVEL."
  (let ((entry (TeX-member level LaTeX-section-list
			   (function (lambda (a b) (equal a (nth 1 b)))))))
    (if entry
	(nth 0 entry)
      nil)))

(defun LaTeX-section-level (name)
  "Return the level of the section NAME."
  (let ((entry (TeX-member name LaTeX-section-list
			   (function (lambda (a b) (equal a (nth 0 b)))))))

    (if entry
	(nth 1 entry)
      nil)))

(defvar TeX-outline-extra nil
  "*List of extra TeX outline levels.

Each element is a list with two entries.  The first entry is the
regular expression matching a header, and the second is the level of
the header.  See LaTeX-section-list for existing header levels.")

(defun LaTeX-outline-regexp (&optional anywhere)
  "Return regexp for LaTeX sections.  

If optional argument ANYWHERE is not nil, do not require that the
header is at the start of a line."
  (concat (if anywhere "" "^")
	  "[ \t]*"
	  (regexp-quote TeX-esc)
	  "\\(appendix\\|documentstyle\\|documentclass\\|"
	  (mapconcat 'car LaTeX-section-list "\\|")
	  "\\)\\b"
	  (if TeX-outline-extra
	      "\\|"
	    "")
	  (mapconcat 'car TeX-outline-extra "\\|")
	  "\\|" TeX-header-end
	  "\\|" TeX-trailer-start))

(defvar LaTeX-largest-level nil
  "Largest sectioning level with current document style")

(make-variable-buffer-local 'LaTeX-largest-level)

(defun LaTeX-largest-level ()
  (TeX-update-style)
  LaTeX-largest-level)

(defun LaTeX-outline-offset ()
  "Offset to add to LaTeX-section-list levels to get outline level."
  (- 2 (LaTeX-largest-level)))

(defun TeX-look-at (list)
  "Check if we are looking at the first element of a member of LIST.
If so, return the second element, otherwise return nil."
  (while (and list
	      (not (looking-at (nth 0 (car list)))))
    (setq list (cdr list)))
  (if list
      (nth 1 (car list))
    nil))

(defun LaTeX-outline-level ()
  "Find the level of current outline heading in an LaTeX document."
  (cond ((looking-at LaTeX-header-end) 1)
	((looking-at LaTeX-trailer-start) 1)
	((TeX-look-at TeX-outline-extra)
	 (max 1 (+ (TeX-look-at TeX-outline-extra)
		   (LaTeX-outline-offset))))
	(t
	 (save-excursion
	  (skip-chars-forward " \t")
	  (forward-char 1)
	  (cond ((looking-at "appendix") 1)
		((looking-at "documentstyle") 1)
		((looking-at "documentclass") 1)
		((TeX-look-at LaTeX-section-list)
		 (max 1 (+ (TeX-look-at LaTeX-section-list)
			   (LaTeX-outline-offset))))
		(t
		 (error "Unrecognized header")))))))

(add-hook 'TeX-remove-style-hook
	  (function (lambda () (setq LaTeX-largest-level nil))))

(defvar LaTeX-section-hook
  '(LaTeX-section-heading
    LaTeX-section-title
;; LaTeX-section-toc		; Most people won't want this
    LaTeX-section-section
    LaTeX-section-label)
  "*List of hooks to run when a new section is inserted.

The following variables are set before the hooks are run

level - numeric section level, see the documentation of `LaTeX-section'.
name - name of the sectioning command, derived from `level'.
title - The title of the section, default to an empty string.
toc - Entry for the table of contents list, default nil.
done-mark - Position of point afterwards, default nil (meaning end).

The following standard hook exist -

LaTeX-section-heading: Query the user about the name of the
sectioning command.  Modifies `level' and `name'.

LaTeX-section-title: Query the user about the title of the
section. Modifies `title'.

LaTeX-section-toc: Query the user for the toc entry.  Modifies
`toc'. 

LaTeX-section-section: Insert LaTeX section command according to
`name', `title', and `toc'.  If `toc' is nil, no toc entry is
enserted.  If `toc' or `title' are empty strings, `done-mark' will be
placed at the point they should be inserted.

LaTeX-section-label: Insert a label after the section command.
Controled by the variable `LaTeX-section-label'.

To get a full featured LaTeX-section command, insert 

 (setq LaTeX-section-hook
       '(LaTeX-section-heading
	 LaTeX-section-title
	 LaTeX-section-toc
	 LaTeX-section-section
	 LaTeX-section-label))

in your .emacs file.")

(defvar LaTeX-section-label
  '(("chapter" . "cha:")
    ("section" . "sec:")
    ("subsection" . "sec:"))
  "*Default prefix when asking for a label.

If it is a string, it it used unchanged for all kinds of sections. 
If it is nil, no label is inserted.
If it is a list, the list is searched for a member whose car is equal
to the name of the sectioning command being inserted.  The cdr is then
used as the prefix.  If the name is not found, or if the cdr is nil,
no label is inserted.")

;;; Section Hooks.

(defun LaTeX-section-heading ()
  "Hook to prompt for LaTeX section name.
Insert this hook into LaTeX-section-hook to allow the user to change
the name of the sectioning command inserted with M-x LaTeX-section."
  (let ((string (completing-read
		 (concat "Select level: (default " name ") ")
		 LaTeX-section-list
		 nil nil nil)))
    ; Update name
    (if (not (zerop (length string)))
	(setq name string))
    ; Update level
    (setq level (LaTeX-section-level name))))

(defun LaTeX-section-title ()
  "Hook to prompt for LaTeX section title.
Insert this hook into LaTeX-section-hook to allow the user to change
the title of the section inserted with M-x LaTeX-section."
  (setq title (read-string "What title: ")))

(defun LaTeX-section-toc ()
  "Hook to prompt for the LaTeX section entry in the table of content .
Insert this hook into LaTeX-section-hook to allow the user to insert
a different entry for the section in the table of content."
  (setq toc (read-string "Toc Entry: "))
  (if (zerop (length toc))
      (setq toc nil)))

(defun LaTeX-section-section ()
  "Hook to insert LaTeX section command into the file.
Insert this hook into LaTeX-section-hook after those hooks which sets
the `name', `title', and `toc' variables, but before those hooks which
assumes the section already is inserted."
    (insert TeX-esc name)
    (cond ((null toc))
	  ((zerop (length toc))
	   (insert LaTeX-optop)
	   (set-marker done-mark (point))
	   (insert LaTeX-optcl))
	  (t
	   (insert LaTeX-optop toc LaTeX-optcl)))
    (insert TeX-grop)
    (if (zerop (length title))
	(set-marker done-mark (point)))
    (insert title TeX-grcl)
    (newline))

(defun LaTeX-section-label ()
  "Hook to insert a label after the sectioning command.
Insert this hook into LaTeX-section-hook to prompt for a label to be
inserted after the sectioning command.

The beaviour of this hook is controled by LaTeX-section-label."
  (and (LaTeX-label name)
       (newline)))

;;; Environments

(defvar LaTeX-default-environment "itemize"
  "*The default environment when creating new ones with LaTeX-environment.")
 (make-variable-buffer-local 'LaTeX-default-environment)

(defun LaTeX-environment (arg)
  "Make LaTeX environment (\\begin{...}-\\end{...} pair).
With optional ARG, modify current environment.
 
It may be customized with the following variables:
 
LaTeX-default-environment       Your favorite environment.
LaTeX-default-style             Your favorite document style.
LaTeX-default-options           Your favorite document style options.
LaTeX-float                     Where you want figures and tables to float.
LaTeX-table-label               Your prefix to labels in tables.
LaTeX-figure-label              Your prefix to labels in figures.
LaTeX-default-format            Format for array and tabular.
LaTeX-default-position          Position for array and tabular."
 
  (interactive "*P")
  (let ((environment (completing-read (concat "Environment type: (default "
                                               (if (TeX-near-bobp)
                                                   "document"
                                                 LaTeX-default-environment)
                                               ") ")
                                       (LaTeX-environment-list))))
    ;; Get default
    (cond ((and (zerop (length environment))
                (TeX-near-bobp))
           (setq environment "document"))
          ((zerop (length environment))
           (setq environment LaTeX-default-environment))
          (t
           (setq LaTeX-default-environment environment)))
 
    (let ((entry (assoc environment (LaTeX-environment-list))))
      (if (null entry)
          (LaTeX-add-environments (list environment)))
 
      (if arg
	  (LaTeX-modify-environment environment)
	(LaTeX-environment-menu environment)))))

(defun LaTeX-environment-menu (environment)
  ;; Insert ENVIRONMENT around point or region. 
  (let ((entry (assoc environment (LaTeX-environment-list))))
    (cond ((not (and entry (nth 1 entry)))
	   (LaTeX-insert-environment environment))
	  ((numberp (nth 1 entry))
	   (let ((count (nth 1 entry))
		 (args ""))
	     (while (> count 0)
	       (setq args (concat args TeX-grop TeX-grcl))
	       (setq count (- count 1)))
	     (LaTeX-insert-environment environment args)))
	  ((stringp (nth 1 entry))
	   (let ((prompts (cdr entry))
		 (args ""))
	     (while prompts
	       (setq args (concat args
				  TeX-grop
				  (read-from-minibuffer (concat (car prompts)
								": "))
				  TeX-grcl))
	       (setq prompts (cdr prompts)))
	     (LaTeX-insert-environment environment args)))
	  (t
	   (apply (nth 1 entry) environment (nthcdr 2 entry))))))

(defun LaTeX-close-environment ()
  "Creates an \\end{...} to match the current environment."
  (interactive "*")
  (if (> (point)
	 (save-excursion
	   (beginning-of-line)
	   (skip-chars-forward " \t")
	   (point)))
      (insert "\n"))
  (insert "\\end{" (LaTeX-current-environment 1) "}")
  (LaTeX-indent-line)
  (if (not (looking-at "[ \t]*$"))
      (insert "\n")
    (let ((next-line-add-newlines t))
      (next-line 1)
      (beginning-of-line)))
  (LaTeX-indent-line))

(autoload 'outline-flag-region "outline")

(defun LaTeX-hide-environment ()
  "Hide current LaTeX environment using selective display."
  (interactive)
  (outline-flag-region (save-excursion (LaTeX-find-matching-begin) (point))
		       (save-excursion (LaTeX-find-matching-end) (point))
		       ?\r))

(defun LaTeX-show-environment ()
  "Show current LaTeX environment."
  (interactive)
  (outline-flag-region (save-excursion (LaTeX-find-matching-begin) (point))
		       (save-excursion (LaTeX-find-matching-end) (point))
		       ?\n))

(defun LaTeX-insert-environment (environment &optional extra)
  "Insert environment of type ENV, with optional argument EXTRA."
  (if (and (TeX-active-mark)
	   (not (eq (mark) (point))))
      (progn 
	(if (< (mark) (point))
	    (exchange-point-and-mark))
	(or (TeX-looking-at-backward "^[ \t]*")
	    (newline))
	(insert TeX-esc "begin" TeX-grop environment TeX-grcl)
	(LaTeX-indent-line)
	(if extra (insert extra))
	(newline)
	(goto-char (mark))
	(or (TeX-looking-at-backward "^[ \t]*")
	    (newline))
	(insert TeX-esc "end" TeX-grop environment TeX-grcl)
	(or (looking-at "[ \t]*$")
	    (save-excursion (newline-and-indent)))
	(LaTeX-indent-line)
	(end-of-line 0)
	(or (assoc environment LaTeX-indent-environment-list)
	    (LaTeX-fill-environment nil)))
    (or (TeX-looking-at-backward "^[ \t]*")
	(newline))
    (insert TeX-esc "begin" TeX-grop environment TeX-grcl)
    (LaTeX-indent-line)
    (if extra (insert extra))
    (newline-and-indent)
    (newline)
    (insert TeX-esc "end" TeX-grop environment TeX-grcl)
    (or (looking-at "[ \t]*$")
	(save-excursion (newline-and-indent)))
    (LaTeX-indent-line)
    (end-of-line 0)))

(defun LaTeX-modify-environment (environment)
  ;; Modify current environment.
  (save-excursion
    (LaTeX-find-matching-end)
    (re-search-backward (concat (regexp-quote TeX-esc)
				"end"
				(regexp-quote TeX-grop)
				" *\\([a-zA-Z*]*\\)"
				(regexp-quote TeX-grcl))
			(save-excursion (beginning-of-line 1) (point)))
    (replace-match (concat TeX-esc "end" TeX-grop environment TeX-grcl) t t)
    (beginning-of-line 1)
    (LaTeX-find-matching-begin)
    (re-search-forward (concat (regexp-quote TeX-esc)
			       "begin"
			       (regexp-quote TeX-grop)
			       " *\\([a-zA-Z*]*\\)"
			       (regexp-quote TeX-grcl))
		       (save-excursion (end-of-line 1) (point)))
    (replace-match (concat TeX-esc "begin" TeX-grop environment TeX-grcl) t t)))

(defun LaTeX-current-environment (&optional arg)
  "Return the name (a string) of the enclosing LaTeX environment.
With optional ARG>=1, find that outer level."
  (setq arg (if arg (if (< arg 1) 1 arg) 1))
  (save-excursion
    (while (and
	    (/= arg 0)
	    (re-search-backward
	     (concat (regexp-quote TeX-esc) "begin" (regexp-quote TeX-grop)
		     "\\|"
		     (regexp-quote TeX-esc) "end" (regexp-quote TeX-grop)) 
	     nil t 1))
      (cond ((TeX-in-comment)
	     (beginning-of-line 1))
	    ((looking-at (concat (regexp-quote TeX-esc)
				 "end" (regexp-quote TeX-grop)))
	     (setq arg (1+ arg)))
	    (t
	    (setq arg (1- arg)))))
    (if (/= arg 0)
	"document"
      (search-forward TeX-grop)
      (let ((beg (point)))
	(search-forward TeX-grcl)
	(backward-char 1)
	(buffer-substring beg (point))))))

(defun TeX-near-bobp ()
  ;; Return t iff there's nothing but whitespace between (bob) and (point).
  (save-excursion
    (skip-chars-backward " \t\n")
    (bobp)))

;;; Environment Hooks

(defvar LaTeX-document-style-hook nil
  "List of hooks to run when inserting a document style environment.

To insert a hook here, you must insert it in the appropiate style file.")

(defun LaTeX-env-document (&optional ignore)
  "Create new LaTeX document."

  (TeX-insert-macro (if (string-equal LaTeX-version "2")
			"documentstyle"
		      "documentclass"))

  (newline 3)
  (end-of-line 0)
  (LaTeX-insert-environment "document")
  (run-hooks 'LaTeX-document-style-hook)
  (setq LaTeX-document-style-hook nil))

(defvar LaTeX-float "htbp"
  "*Default float when creating figure and table environments.
Set to nil if you don't want any float.")
 (make-variable-buffer-local 'LaTeX-float)

(defvar LaTeX-label-function nil
  "*A function inserting a label at point.
Sole argument of the function is the environment. The function has to return
the label inserted, or nil if no label was inserted.")

(defvar LaTeX-figure-label "fig:"
  "*Default prefix to figure labels.")
 (make-variable-buffer-local 'LaTeX-figure-label)

(defvar LaTeX-table-label "tab:"
  "*Default prefix to table labels.")
 (make-variable-buffer-local 'LaTeX-table-label)

(defvar LaTeX-default-format ""
  "Specifies the default format string for array and tabular environments.")
 (make-variable-buffer-local 'LaTeX-default-format)

(defvar LaTeX-default-position ""
  "Specifies the default position string for array and tabular environments.")
 (make-variable-buffer-local 'LaTeX-default-position)

(defun LaTeX-env-item (environment)
  "Insert ENVIRONMENT and the first item."
  (LaTeX-insert-environment environment)
  (if (TeX-active-mark)
      (progn
	(LaTeX-find-matching-begin)
	(end-of-line 1))
    (end-of-line 0))
  (delete-char 1)
  (delete-horizontal-space)
  (LaTeX-insert-item))

(defun LaTeX-label (environment)
  "Insert a label for ENVIRONMENT at point.
If LaTeX-label-function is a valid function, LaTeX label will transfer the
job to this function."
  (let (label)
    (if (and (boundp 'LaTeX-label-function)
	     LaTeX-label-function
	     (fboundp LaTeX-label-function))

	(setq label (funcall LaTeX-label-function environment))
      (let ((prefix
	     (cond
	      ((string= "figure" environment) LaTeX-figure-label)
	      ((string= "table"  environment) LaTeX-table-label)
	      ((assoc environment LaTeX-section-list)
	       (cond
		((stringp LaTeX-section-label) LaTeX-section-label)
		((and (listp LaTeX-section-label)
		      (assoc environment LaTeX-section-label))
		 (cdr (assoc environment LaTeX-section-label)))
		(t nil)))
	      (t ""))))
	(if prefix
	    (progn
	      (setq label (read-string "What label: " prefix))
	      (if (string= prefix label)
		  (setq label nil)     ; No label eneterd
		(insert TeX-esc "label" TeX-grop label TeX-grcl)))))
      (if label
	  (progn
	    (LaTeX-add-labels label)
	    label)
	nil))))


(defun LaTeX-env-figure (environment)
  "Create ENVIRONMENT with \\label and \\caption commands."
  (let ((float (read-string "Float to: " LaTeX-float))
	(caption (read-string "Caption: "))
        (center (y-or-n-p "Center: ")))

    (setq LaTeX-float (if (zerop (length float))
			  LaTeX-float
			float))
	  
    (LaTeX-insert-environment environment
			      (and LaTeX-float
				   (concat LaTeX-optop
					   LaTeX-float
					   LaTeX-optcl)))
    
    (if center
	(progn
	  (LaTeX-insert-environment "center")))
    
    (newline-and-indent)
    (LaTeX-label environment)
    (end-of-line 0)
    (LaTeX-indent-line)

    (if (zerop (length caption))
	()
      ;; NOTE: Caption is _inside_ center because that looks best typeset.
      (newline-and-indent)
      (insert TeX-esc "caption" TeX-grop caption TeX-grcl)
      (end-of-line 0)
      (LaTeX-indent-line))
    
    (if (string= environment "table") (LaTeX-env-array "tabular"))))

(defun LaTeX-env-array (environment)
  "Insert ENVIRONMENT with position and column specifications 
like array and tabular."
  (let ((pos (read-string "Position: "))
	(fmt (read-string "Format: " LaTeX-default-format)))
    (setq LaTeX-default-position pos)
      (setq LaTeX-default-format fmt)
    (LaTeX-insert-environment environment
			      (concat
			        (if (not (zerop (length pos)))
				    (format "[%s]" pos))
				(format "{%s}" fmt)))
    (end-of-line 0)
    (next-line 1)
    (delete-horizontal-space)))

(defun LaTeX-env-label (environment)
  "Insert ENVIRONMENT and prompt for label."
  (LaTeX-insert-environment environment)
  (and (LaTeX-label environment)
       (newline-and-indent)))

(defun LaTeX-env-list (environment)
  "Insert ENVIRONMENT and the first item."
  (let ((label (read-string "Default Label: ")))
    (LaTeX-insert-environment environment
			      (format "{%s}{}" label))
    (end-of-line 0)
    (delete-char 1)
    (delete-horizontal-space))
  (LaTeX-insert-item))

(defun LaTeX-env-minipage (environment)
  "Create new LaTeX minipage."
  (let ((pos (read-string "Position: " LaTeX-default-position))
	(width (read-string "Width: ")))
    (setq LaTeX-default-position pos)
    (if (zerop (length width))
	(setq width "4cm"))
    (LaTeX-insert-environment environment
			      (concat (if (not (zerop (length pos)))
					  (format "[%s]" pos))
				      (format "{%s}" width)))
    (end-of-line 0)
    (next-line 1)
    (delete-horizontal-space)))

(defun LaTeX-env-tabular* (environment)
  "Insert ENVIRONMENT with width, position and column specifications."
  (let ((width (read-string "Width: "))
	(pos (read-string "Position: " LaTeX-default-position))
	(fmt (read-string "Format: " LaTeX-default-format)))
    (setq LaTeX-default-position pos)
    (setq LaTeX-default-format fmt)
    (LaTeX-insert-environment environment
			      (concat
			        (if (not (zerop (length width)))
				    (format "{%s}" width))
			        (if (not (zerop (length pos)))
					  (format "[%s]" pos))
				(format "{%s}" fmt)))
    (end-of-line 0)
    (next-line 1)
    (delete-horizontal-space)))

(defun LaTeX-env-picture (environment)
  "Insert ENVIRONMENT with width, height specifications."
  (let ((width (read-string "Width: "))
	(height (read-string "Height: "))
	(x-offset (read-string "X Offset: "))
	(y-offset (read-string "Y Offset: ")))
    (if (zerop (length x-offset))
	(setq x-offset "0"))
    (if (zerop (length y-offset))
	(setq y-offset "0"))
    (LaTeX-insert-environment environment
			      (concat (format "(%s,%s)" width height)
				      (if (not (and (string= x-offset "0")
						    (string= y-offset "0")))
					  (format "(%s,%s)" x-offset y-offset))))
				      
    (end-of-line 0)
    (next-line 1)
    (delete-horizontal-space)))

(defun LaTeX-env-bib (environment)
  "Insert ENVIRONMENT with label for bibitem."
  (LaTeX-insert-environment environment
			    (concat TeX-grop
				    (read-string "Label for BibItem: " "99")
				    TeX-grcl))
  (end-of-line 0)
  (delete-char 1)
  (delete-horizontal-space)
  (LaTeX-insert-item))

;;; Item hooks

(defvar LaTeX-item-list nil
  "An list of environments where items have a special syntax. 
The cdr is the name of the function, used to insert this kind of items.")

(defun LaTeX-insert-item ()
  "Insert a new item in an environment.
You may use LaTeX-item-list to change the routines used to insert the item."
  (interactive "*")
  (let ((environment (LaTeX-current-environment)))
    (newline)
    (if (assoc environment LaTeX-item-list)
	(funcall (cdr (assoc environment LaTeX-item-list)))
      (TeX-insert-macro "item"))
    (LaTeX-indent-line)))

(defun LaTeX-item-argument ()
  "Insert a new item with an optional argument."
  (let ((TeX-arg-item-label-p t))
    (TeX-insert-macro "item")))

(defun LaTeX-item-bib ()
  "Insert a new bibitem."
  (TeX-insert-macro "bibitem"))

;;; Parser

(defvar LaTeX-auto-minimal-regexp-list
  '(("\\\\document\\(style\\|class\\)\
\\(\\[\\(\\([^#\\\\\\.%]\\|%[^\n\r]*[\n\r]\\)+\\)\\]\\)?\
{\\([^#\\\\\\.\n\r]+\\)}"
     (3 5 1) LaTeX-auto-style))
  "Minimal list of regular expressions matching LaTeX macro definitions.")

(defvar LaTeX-auto-label-regexp-list
  '(("\\\\label{\\([^\n\r%\\{}]+\\)}" 1 LaTeX-auto-label))
  "List of regular expression matching LaTeX labels only.")

(defvar LaTeX-auto-regexp-list 
  (append
   '(("\\\\newcommand{?\\\\\\([a-zA-Z]+\\)}?\\[\\([0-9]+\\)\\]\
\\[\\([^\]\\\\\n\r]+\\)\\]"
      (1 2 3) LaTeX-auto-optional)
     ("\\\\newcommand{?\\\\\\([a-zA-Z]+\\)}?\\[\\([0-9]+\\)\\]"
      (1 2) LaTeX-auto-arguments)
     ("\\\\newcommand{?\\\\\\([a-zA-Z]+\\)}?" 1 TeX-auto-symbol)
     ("\\\\newenvironment{?\\([a-zA-Z]+\\)}?\\[\\([0-9]+\\)\\]\\["
      1 LaTeX-auto-environment)
     ("\\\\newenvironment{?\\([a-zA-Z]+\\)}?\\[\\([0-9]+\\)\\]"
      (1 2) LaTeX-auto-env-args)
     ("\\\\newenvironment{?\\([a-zA-Z]+\\)}?" 1 LaTeX-auto-environment)
     ("\\\\newtheorem{\\([a-zA-Z]+\\)}" 1 LaTeX-auto-environment)
     ("\\\\input{\\(\\.*[^#}%\\\\\\.\n\r]+\\)\\(\\.[^#}%\\\\\\.\n\r]+\\)?}"
      1 TeX-auto-file)
     ("\\\\include{\\(\\.*[^#}%\\\\\\.\n\r]+\\)\\(\\.[^#}%\\\\\\.\n\r]+\\)?}"
      1 TeX-auto-file)
     ("\\\\usepackage\\(\\[[^\]\\\\]*\\]\\)?\
{\\(\\([^#}\\\\\\.%]\\|%[^\n\r]*[\n\r]\\)+\\)}"
      (2) LaTeX-auto-style)
     ("\\\\bibitem{\\([a-zA-Z][^, \n\r\t%\"#'()={}]*\\)}" 1 LaTeX-auto-bibitem)
     ("\\\\bibitem\\[[^][\n\r]+\\]{\\([a-zA-Z][^, \n\r\t%\"#'()={}]*\\)}"
      1 LaTeX-auto-bibitem)
     ("\\\\bibliography{\\([^#}\\\\\n\r]+\\)}" 1 LaTeX-auto-bibliography))
   LaTeX-auto-label-regexp-list
   LaTeX-auto-minimal-regexp-list)
  "List of regular expression matching common LaTeX macro definitions.")

(defun LaTeX-auto-prepare ()
  ;; Prepare for LaTeX parsing.
  (setq LaTeX-auto-arguments nil
	LaTeX-auto-optional nil
	LaTeX-auto-env-args nil
	LaTeX-auto-style nil
	LaTeX-auto-end-symbol nil))

(add-hook 'TeX-auto-prepare-hook 'LaTeX-auto-prepare)
  
(defun LaTeX-auto-cleanup ()
  ;; Cleanup after LaTeX parsing.

  ;; Cleanup BibTeX files
  (setq LaTeX-auto-bibliography
	(apply 'append (mapcar (function (lambda (arg)
					   (TeX-split-string "," arg)))
			       LaTeX-auto-bibliography)))
    
  ;; Cleanup document styles and packages
  (if (null LaTeX-auto-style)
      ()
    (while LaTeX-auto-style
      (let* ((entry (car LaTeX-auto-style))
	     (options (nth 0 entry))
	     (style (nth 1 entry))
	     (class (nth 2 entry)))

	;; Next document style.
	(setq LaTeX-auto-style (cdr LaTeX-auto-style))

	;; Get the options.
	(setq options (TeX-split-string 
		       "\\([ \t\r\n]\\|%[^\n\r]*[\n\r]\\|,\\)+"
		       options))

	;; Strip empty options.
	(if (string-equal (car options) "")
	    (setq options (cdr options)))
	(let ((index options))
	  (while (cdr-safe index)
	    (if (string-equal (car (cdr index)) "")
		(setcdr index (cdr (cdr index)))
	      (setq index (cdr index)))))

	;; Add them, to the style list.
	(setq TeX-auto-file (append options TeX-auto-file))

	;; The second argument if present is a normal style file.
	(if (null style)
	    ()
	  (setq TeX-auto-file (cons style TeX-auto-file))

	  ;; And a special "art10" style file combining style and size.
	  (setq TeX-auto-file
		(cons (concat 
		       (cond ((string-equal "article" style)
			      "art")
			     ((string-equal "book" style)
			      "bk")
			     ((string-equal "report" style)
			      "rep")
			     ((string-equal "jarticle" style)
			      "jart")
			     ((string-equal "jbook" style)
			      "jbk")
			     ((string-equal "jreport" style)
			      "jrep")
			     ((string-equal "j-article" style)
			      "j-art")
			     ((string-equal "j-book" style)
			      "j-bk")
			     ((string-equal "j-report" style )
			      "j-rep")
			     (t style))
		       (cond ((member "11pt" options)
			      "11")
			     ((member "12pt" options)
			      "12")
			     (t
			      "10")))
		      TeX-auto-file)))

	;; The third argument if "class" indicates LaTeX2e features.
	(cond ((equal class "class")
	       (setq TeX-auto-file (cons "latex2e" TeX-auto-file)))
	      ((equal class "style")
	       (setq TeX-auto-file (cons "latex2" TeX-auto-file)))))))
    
  ;; Cleanup optional arguments
  (mapcar (function (lambda (entry)
		      (setq TeX-auto-symbol
			    (cons (list (nth 0 entry)
					(string-to-int (nth 1 entry)))
				  TeX-auto-symbol))))
	  LaTeX-auto-arguments)

  ;; Cleanup default optional arguments
  (mapcar (function (lambda (entry)
		      (setq TeX-auto-symbol
			    (cons (list (nth 0 entry)
					(vector "argument")
					(1- (string-to-int (nth 1 entry))))
				  TeX-auto-symbol))))
	  LaTeX-auto-optional)

  ;; Cleanup environments arguments
  (mapcar (function (lambda (entry)
		      (setq LaTeX-auto-environment
			    (cons (list (nth 0 entry)
					(string-to-int (nth 1 entry)))
				  LaTeX-auto-environment))))
	  LaTeX-auto-env-args)
    
  ;; Cleanup use of def to add environments
  ;; NOTE: This uses an O(N^2) algorithm, while an O(N log N)
  ;; algorithm is possible.
  (mapcar (function (lambda (symbol)
		      (if (not (TeX-member symbol TeX-auto-symbol 'equal))
			  ;; No matching symbol, insert in list
			  (setq TeX-auto-symbol
				(cons (concat "end" symbol) TeX-auto-symbol))
			;; Matching symbol found, remove from list
			(if (equal (car TeX-auto-symbol) symbol)
			    ;; Is it the first symbol?
			    (setq TeX-auto-symbol (cdr TeX-auto-symbol))
			  ;; Nope!  Travel the list
			  (let ((list TeX-auto-symbol))
			    (while (consp (cdr list))
			      ;; Until we find it.
			      (if (equal (car (cdr list)) symbol)
				  ;; Then remove it.
				  (setcdr list (cdr (cdr list))))
			      (setq list (cdr list)))))
			;; and add the symbol as an environment.
			(setq LaTeX-auto-environment
			      (cons symbol LaTeX-auto-environment)))))
	  LaTeX-auto-end-symbol))

(add-hook 'TeX-auto-cleanup-hook 'LaTeX-auto-cleanup)

(TeX-auto-add-type "label" "LaTeX")
(TeX-auto-add-type "bibitem" "LaTeX")
(TeX-auto-add-type "environment" "LaTeX")
(TeX-auto-add-type "bibliography" "LaTeX" "bibliographies")

(fset 'LaTeX-add-bibliographies-auto
      (symbol-function 'LaTeX-add-bibliographies))
(defun LaTeX-add-bibliographies (&rest bibliographies)
  "Add BIBLIOGRAPHIES to the list of known bibliographies and style files."
  (apply 'LaTeX-add-bibliographies-auto bibliographies)
  (apply 'TeX-run-style-hooks bibliographies))

(fset 'LaTeX-add-environments-auto
      (symbol-function 'LaTeX-add-environments))
(defun LaTeX-add-environments (&rest environments)
  "Add ENVIRONMENTS to the list of known environments."
  (apply 'LaTeX-add-environments-auto environments)
  (setq LaTeX-menu-changed t))

;;; BibTeX

;;;###autoload
(defun BibTeX-auto-store ()
  "This function should be called from bibtex-mode-hook.
It will setup BibTeX to store keys in an auto file."
  ;; We want this to be early in the list, so we do not
  ;; add it before we enter BibTeX mode the first time. 
  (if (boundp 'local-write-file-hooks)
      (add-hook 'local-write-file-hooks 'TeX-safe-auto-write)
    (add-hook 'write-file-hooks 'TeX-safe-auto-write))
  (make-local-variable 'TeX-auto-update)
  (setq TeX-auto-update 'BibTeX)
  (make-local-variable 'TeX-auto-untabify)
  (setq TeX-auto-untabify nil)
  (make-local-variable 'TeX-auto-parse-length)
  (setq TeX-auto-parse-length 999999)
  (make-local-variable 'TeX-auto-regexp-list)
  (setq TeX-auto-regexp-list BibTeX-auto-regexp-list))

(defvar BibTeX-auto-regexp-list
  '(("@[Ss][Tt][Rr][Ii][Nn][Gg]" 1 ignore)
    ("@[a-zA-Z]+[{(][ \t]*\\([a-zA-Z][^, \n\r\t%\"#'()={}]*\\)"
     1 LaTeX-auto-bibitem))
  "List of regexp-list expressions matching BibTeX items.")

;;; Macro Argument Hooks

(defun TeX-arg-conditional (optional expr then else)
  "Implement if EXPR THEN ELSE.

If EXPR evaluate to true, parse THEN as an argument list, else parse
ELSE as an argument list."
  (TeX-parse-arguments (if (eval expr) then else)))

(defun TeX-arg-free (optional &optional &rest args)
  "Parse its arguments but use no braces when they are inserted."
  (let ((< "")
	(> ""))
    (if (equal (length args) 1)
	(TeX-parse-argument optional (car args))
      (TeX-parse-argument optional args))))

(defun TeX-arg-literal (optional &optional &rest args)
  "Insert its arguments into the buffer.  
Used for specifying extra syntax for a macro."
  (apply 'insert args))

(defun TeX-arg-eval (optional &rest args)
  "Evaluate args and insert value in buffer."
  (TeX-argument-insert (eval args) optional))

(defun TeX-arg-label (optional &optional prompt definition)
  "Prompt for a label completing with known labels."
  (let ((label (completing-read (TeX-argument-prompt optional prompt "Key")
				(LaTeX-label-list))))
    (if (and definition (not (string-equal "" label)))
	(LaTeX-add-labels label))
    (TeX-argument-insert label optional optional)))

(defun TeX-arg-macro (optional &optional prompt definition)
  "Prompt for a TeX macro with completion."
  (let ((macro (completing-read (TeX-argument-prompt optional prompt
						     (concat "Macro: "
							     TeX-esc)
						     t)
				(TeX-symbol-list))))
    (if (and definition (not (string-equal "" macro)))
	(TeX-add-symbols macro))
    (TeX-argument-insert macro optional TeX-esc)))

(defun TeX-arg-environment (optional &optional prompt definition)
  "Prompt for a LaTeX environment with completion."
  (let ((environment (completing-read (TeX-argument-prompt optional prompt
							   "Environment")
				      (TeX-symbol-list))))
    (if (and definition (not (string-equal "" environment)))
	(LaTeX-add-environments environment))

    (TeX-argument-insert environment optional)))

(defun TeX-arg-cite (optional &optional prompt definition)
  "Prompt for a BibTeX citation with completion."
  (setq prompt (concat (if optional "(Optional) " "")
		       (if prompt prompt "Add key")
		       ": (default none) "))
  (let ((items (multi-prompt "," t prompt (LaTeX-bibitem-list))))
    (apply 'LaTeX-add-bibitems items)
    (TeX-argument-insert (mapconcat 'identity items ",") optional optional)))

(defun TeX-arg-counter (optional &optional prompt definition)
  "Prompt for a LaTeX counter."
  ;; Completion not implemented yet.
  (TeX-argument-insert
   (read-string (TeX-argument-prompt optional prompt "Counter"))
   optional))

(defun TeX-arg-savebox (optional &optional prompt definition)
  "Prompt for a LaTeX savebox."
  ;; Completion not implemented yet.
  (TeX-argument-insert
   (read-string (TeX-argument-prompt optional prompt
				     (concat "Savebox: " TeX-esc)
				     t))
   optional TeX-esc))

(defun TeX-arg-file (optional &optional prompt)
  "Prompt for a filename in the current directory."
  (TeX-argument-insert (read-file-name (TeX-argument-prompt optional
							    prompt "File")
				       "" "" nil)
		       optional))

(defun TeX-arg-define-label (optional &optional prompt)
  "Prompt for a label completing with known labels."
  (TeX-arg-label optional prompt t))

(defun TeX-arg-define-macro (optional &optional prompt)
  "Prompt for a TeX macro with completion."
  (TeX-arg-macro optional prompt t))

(defun TeX-arg-define-environment (optional &optional prompt)
  "Prompt for a LaTeX environment with completion."
  (TeX-arg-environment optional prompt t))

(defun TeX-arg-define-cite (optional &optional prompt)
  "Prompt for a BibTeX citation."
  (TeX-arg-cite optional prompt t))

(defun TeX-arg-define-counter (optional &optional prompt)
  "Prompt for a LaTeX counter."
  (TeX-arg-counter optional prompt t))

(defun TeX-arg-define-savebox (optional &optional prompt)
  "Prompt for a LaTeX savebox."
  (TeX-arg-savebox optional prompt t))

(defvar LaTeX-style-list '(("book")
			   ("article")
			   ("letter")
			   ("slides")
			   ("report"))
  "*List of document styles.")

  (make-variable-buffer-local 'LaTeX-style-list)

(defun TeX-arg-document (optional &optional ignore)
  "Insert arguments to documentstyle and documentclass."
  (let ((style (completing-read 
		(concat "Document style: (default " LaTeX-default-style ") ")
		LaTeX-style-list))
	(options (read-string "Options: "
			      (if (stringp LaTeX-default-options)
				  LaTeX-default-options
				(mapconcat 'identity
					   LaTeX-default-options
					   ",")))))
    (if (zerop (length style))
	(setq style LaTeX-default-style))
    (if (not (zerop (length options)))
	(insert LaTeX-optop options LaTeX-optcl))
    (insert TeX-grop style TeX-grcl))

  ;; remove old information
  (TeX-remove-style)

  ;; defined in individual style hooks
  (TeX-update-style))

(defvar TeX-global-input-files nil
  "*List of the non-local TeX input files. 

Initialized once at the first time you prompt for an input file.
May be reset with `C-u \\[TeX-normal-mode]'.")

(defun TeX-arg-input-file (optionel &optional prompt local)
  "Prompt for a tex or sty file.

First optional argument is the promt, the second is a flag.  
If the flag is set, only complete with local files."
  (if (or TeX-global-input-files local)
      ()
    (message "Searching for files...")
    (setq TeX-global-input-files
	  (mapcar 'list (TeX-search-files (append TeX-macro-private
						  TeX-macro-global)
					  TeX-file-extensions t t))))
  (let ((file (if TeX-check-path
		  (completing-read
		   (TeX-argument-prompt optionel prompt "File")
		   (append (mapcar 'list
				   (TeX-search-files '(".")
						     TeX-file-extensions
						     t t))
			   (if local
			       nil
			     TeX-global-input-files)))
		(read-file-name
		 (TeX-argument-prompt optionel prompt "File")))))
    (if (null file)
	(setq file ""))
    (if (not (string-equal "" file))
	(TeX-run-style-hooks file))
    (TeX-argument-insert file optionel)))

(defvar BibTeX-global-style-files nil
  "*Association list of BibTeX style files.

Initialized once at the first time you prompt for an input file.
May be reset with `C-u \\[TeX-normal-mode]'.")

(defun TeX-arg-bibstyle (optional &optional prompt)
  "Prompt for a BibTeX style file."
  (message "Searching for BibTeX styles...")
  (or BibTeX-global-style-files
      (setq BibTeX-global-style-files
	    (mapcar 'list
		    (TeX-search-files (append TeX-macro-private
					      TeX-macro-global)
				      BibTeX-style-extensions t t))))

  (TeX-argument-insert
   (completing-read (TeX-argument-prompt optional prompt "BibTeX style")
		    (append (mapcar 'list
				    (TeX-search-files '(".")
						      BibTeX-style-extensions
						      t t))
			    BibTeX-global-style-files))
   optional))

(defvar BibTeX-global-files nil
  "*Association list of BibTeX files.

Initialized once at the first time you prompt for an BibTeX file.
May be reset with `C-u \\[TeX-normal-mode]'.")

(defun TeX-arg-bibliography (optional &optional prompt)
  "Prompt for a BibTeX database file."
  (message "Searching for BibTeX files...")
  (or BibTeX-global-files
      (setq BibTeX-global-files
	    (mapcar 'list (TeX-search-files nil BibTeX-file-extensions t t))))
  
  (let ((styles (multi-prompt 
		 "," t
		 (TeX-argument-prompt optional prompt "BibTeX files")
		 (append (mapcar 'list
				 (TeX-search-files '(".")
						   BibTeX-file-extensions
						   t t))
			 BibTeX-global-files))))
    (apply 'LaTeX-add-bibliographies styles)
    (TeX-argument-insert (mapconcat 'identity styles ",") optional)))

(defun TeX-arg-corner (optional &optional prompt)
  "Prompt for a LaTeX side or corner position with completion."
  (TeX-argument-insert
   (completing-read (TeX-argument-prompt optional prompt "Position")
		    '(("") ("l") ("r") ("t") ("b") ("tl") ("tr") ("bl") ("br"))
		    nil t)
   optional))

(defun TeX-arg-lr (optional &optional prompt)
  "Prompt for a LaTeX side with completion."
  (TeX-argument-insert
   (completing-read (TeX-argument-prompt optional prompt "Position")
		    '(("") ("l") ("r"))
		    nil t)
   optional))

(defun TeX-arg-tb (optional &optional prompt)
  "Prompt for a LaTeX side with completion."
  (TeX-argument-insert
   (completing-read (TeX-argument-prompt optional prompt "Position")
		    '(("") ("t") ("b"))
		    nil t)
   optional))

(defun TeX-arg-pagestyle (optional &optional prompt)
  "Prompt for a LaTeX pagestyle with completion."
  (TeX-argument-insert
   (completing-read (TeX-argument-prompt optional prompt "Pagestyle")
		    '(("plain") ("empty") ("headings") ("myheadings")))
   optional))

(defun TeX-arg-verb (optional &optional ignore)
  "Prompt for delimiter and text."
  (let ((del (read-quoted-char "Delimiter: "))
	(text (read-from-minibuffer "Text: ")))
    (insert del text del)))

(defun TeX-arg-pair (optional first second)
  "Insert a pair of number, prompted by FIRST and SECOND.

The numbers are surounded by parenthesizes and separated with a
comma."
  (insert "(" (read-string (concat first  ": ")) ","
	      (read-string (concat second ": ")) ")"))

(defun TeX-arg-size (optional)
  "Insert width and height as a pair."
  (TeX-arg-pair optional "Width" "Height"))

(defun TeX-arg-coordinate (optional)
  "Insert x and y coordinate as a pair."
 (TeX-arg-pair optional "X position" "Y position"))

(defconst TeX-braces-default-association
  '(("[" . "]")
    ("\\{" . "\\}")
    ("(" . ")")
    ("|" . "|")
    ("\\|" . "\\|")
    ("/" . "/")
    ("\\backslash" . "\\backslash")
    ("\\lfloor" . "\\rfloor")
    ("\\lceil" . "\\rceil")
    ("\\langle" . "\\rangle")))

(defvar TeX-braces-user-association nil
  "A list of your personal association of brace symbols for \\left and \\right

The car of each entry is the brace used with \\left,
the cdr is the brace used with \\right.")

(defvar TeX-braces-association
  (append TeX-braces-user-association
          TeX-braces-default-association)
    "A list of association of brace symbols for \\left and \\right.
The car of each entry is the brace used with \\left,
the cdr is the brace used with \\right.")

(defvar TeX-left-right-braces
  '(("[") ("]") ("\\{") ("\\}") ("(") (")") ("|") ("\\|")
    ("/") ("\\backslash") ("\\lfloor") ("\\rfloor")
    ("\\lceil") ("\\rceil") ("\\langle") ("\\rangle")
    ("\\uparrow") ("\\Uparrow") ("\\downarrow") ("\\Downarrow")
    ("\\updownarrow") ("\\Updownarrow") ("."))
  "List of symbols which can follow the \\left or \\right command")

(defun TeX-arg-insert-braces (optional &optional prompt)
  (save-excursion
    (backward-word 1)
    (backward-char)
    (newline-and-indent)
    (beginning-of-line 0)
    (if (looking-at "^[ \t]*$")
	(progn (delete-horizontal-space)
	       (delete-char 1))))
  (let ((left-brace (completing-read
                     (TeX-argument-prompt optional prompt "Which brace")
                     TeX-left-right-braces)))
    (insert left-brace)
    (newline-and-indent)
    (save-excursion
      (let ((right-brace (cdr (assoc left-brace
                                     TeX-braces-association))))
	(newline)
        (insert TeX-esc "right")
        (if (and TeX-arg-right-insert-p
                 right-brace)
            (insert right-brace)
          (insert (completing-read
                   (TeX-argument-prompt optional prompt "Which brace")
                   TeX-left-right-braces)))
	(LaTeX-indent-line)))))

;;; Indentation

(defvar LaTeX-indent-level 2
  "*Indentation of begin-end blocks in LaTeX.")

(defvar LaTeX-item-indent (- LaTeX-indent-level)
  "*Extra indentation for lines beginning with an item.")

(defvar LaTeX-item-regexp "\\(bib\\)?item\\b"
  "*Regular expression matching macros considered items.")

(defun LaTeX-indent-line ()
  "Indent the line containing point, as LaTeX source.
Add LaTeX-indent-level indentation in each \\begin{ - \\end{ block.
Lines starting with an item is given an extra indentation of
LaTeX-item-indent."
  (interactive)
  (let ((indent (LaTeX-indent-calculate)))
    (save-excursion
      (if (/= (current-indentation) indent)
	  (let ((beg (progn
		       (beginning-of-line)
		       (point))))
	    (back-to-indentation)
	    (delete-region beg (point))
	    (indent-to indent))))
    (if (< (current-column) indent)
	(back-to-indentation))))

(defun LaTeX-fill-region-as-paragraph (from to &optional justify-flag)
  "Fill region as one paragraph: break lines to fit fill-column,
but leave all lines ending with \\\\ (plus its optional argument) alone.
Prefix arg means justify too.
From program, pass args FROM, TO and JUSTIFY-FLAG."
  (interactive "*r\nP")
  (or (assoc (LaTeX-current-environment) LaTeX-indent-environment-list)
      (save-restriction
	(narrow-to-region from to)
	(goto-char from)
	(while (not (eobp))
	  (LaTeX-indent-line)
	  (forward-line))
	(goto-char from)
	(while (not (eobp))
	  (if 
	      (re-search-forward (concat "^.*"
					 (regexp-quote TeX-esc)
					 (regexp-quote TeX-esc)
					 "\\(\\s-*\\*\\)?"
					 "\\(\\s-*\\[[^]]*\\]\\)?\\s-*$") 
				 nil t)
	      (progn
		(goto-char (match-end 0))
		(delete-horizontal-space)
		;; I doubt very much if we want justify -
		;; this is a line with \\
		;; if you think otherwise - uncomment the next line
		;; (and justify-flag (justify-current-line))
		(forward-char)
		;; keep our position in a buffer
		(save-excursion
		  (LaTeX-fill-region-as-para-do
		   from (match-beginning 0) justify-flag))
		(setq from (point)))
	    ;; ELSE part follows - loop termination relies on a fact
	    ;; that (LaTeX-fill-region-as-para-do) moves point past
	    ;; the filled region
	    (LaTeX-fill-region-as-para-do from to justify-flag)))
	;; the following four lines are clearly optional, but I like my
	;; LaTeX code that way 
	(goto-char (point-min))
	(while (search-forward "$$ " nil t)
	  (replace-match "$$\n" t t)
	  (LaTeX-indent-line)))))

(defun LaTeX-fill-region-as-para-do (from to justify-flag)
  "Fill region as one paragraph: break lines to fit fill-column."
  (if (< from to)
      (progn
	;; (save-restriction) here is likely not needed because
	;; it was done by a caller, but I am not sure - mj
	(save-restriction
	  (goto-char from)
	  (skip-chars-forward " \n")
	  (LaTeX-indent-line)
	  (beginning-of-line)
	  (narrow-to-region (point) to)
	  (setq from (point))

	  ;; from is now before the text to fill,
	  ;; but after any fill prefix on the first line.

	  ;; Make sure sentences ending at end of line get an extra space.
	  (if (or (not (boundp 'sentence-end-double-space))
		  sentence-end-double-space)
	      (progn
		(goto-char from)
		(while (re-search-forward "[.?!][]})\"']*$" nil t)
		  (insert ? ))))
	  ;; The change all newlines to spaces.
    (subst-char-in-region from (point-max) ?\n ?\ )
    ;; Flush excess spaces, except in the paragraph indentation.
    (goto-char from)
    (skip-chars-forward " \t")
    (while (re-search-forward "   *" nil t)
      (delete-region
       (+ (match-beginning 0)
	  (if (save-excursion
		(skip-chars-backward " ]})\"'")
		(memq (preceding-char) '(?. ?? ?!)))
	      2 1))
       (match-end 0)))
    (goto-char (point-max))
    (delete-horizontal-space)
    (insert "  ")
    (goto-char (point-min))
    (let ((prefixcol 0))
      (while (not (eobp))
	(move-to-column (1+ fill-column))
	(if (eobp)
	    nil
	  (skip-chars-backward "^ \n")
	  (if (if (zerop prefixcol)
		  (bolp)
		(>= prefixcol (current-column)))
	      (skip-chars-forward "^ \n")
	    (forward-char -1)))
	(delete-horizontal-space)
	(if (equal (preceding-char) ?\\)
	    (insert ? ))
	(insert ?\n)
	(LaTeX-indent-line)
	(setq prefixcol (current-column))
	(and justify-flag (not (eobp))
	     (progn
	       (forward-line -1)
	       (justify-current-line)
	       (forward-line 1)))
	)
      (goto-char (point-max))
      (delete-horizontal-space))))))

(defun LaTeX-fill-paragraph (prefix)
  "Fill and indent paragraph at or after point.
Prefix arg means justify as well."
  (interactive "*P")
  (save-excursion
    (beginning-of-line)
    (if (looking-at "[ \t]*%]")
	(re-search-forward "^[ \t]*[^% \t\n]"))
    (forward-paragraph)
    (or (bolp) (newline 1))
    (and (eobp) (open-line 1))
    (let ((end (point-marker))
	  (start (progn
		   (backward-paragraph)
		   (point))))
      (LaTeX-fill-region-as-paragraph start end prefix))))

(defun LaTeX-fill-region (from to &optional justify what)
  "Fill and indent each of the paragraphs in the region as LaTeX text.
Prefix arg (non-nil third arg, if called from program)
means justify as well. Fourth arg WHAT is a word to be displayed when
formatting."
  (interactive "*r\nP")
  (save-restriction
    (save-excursion
      (let ((length (- to from))
	    (to (set-marker (make-marker) to)))
	(goto-char from)
	(beginning-of-line)
	(while (< (point) to)
	  (message "Formatting%s ... %d%%"
		   (if (not what)
		       ""
		     what)
		   (/ (* 100 (- (point) from)) length))
	  (save-excursion (LaTeX-fill-paragraph justify))
	  (forward-paragraph 2)
	  (if (not (eobp))
	      (backward-paragraph)))
	(set-marker to nil)))
    (message "Finished")))

(defun LaTeX-find-matching-end ()
  "Move point to the \\end of the current environment"
  (interactive)
  (let ((regexp (concat (regexp-quote TeX-esc) "\\(begin\\|end\\)\\b"))
	(level 1))
    (beginning-of-line 1)
    (if (looking-at (concat " *" (regexp-quote TeX-esc) "begin\\b"))
	(end-of-line 1))
    (while (and (> level 0) (re-search-forward regexp nil t))
      (if (= (char-after (1+ (match-beginning 0))) ?b);;begin
	  (setq level (1+ level))
	(setq level (1- level))))
    (if (= level 0)
	(search-forward "}")
      (error "Can't locate end of current environment"))))

(defun LaTeX-find-matching-begin ()
  "Move point to the \\begin of the current environment"
  (interactive)
  (let ((regexp (concat (regexp-quote TeX-esc) "\\(begin\\|end\\)\\b"))
	(level 1))
    (beginning-of-line 1)
    (if (looking-at (concat " *" (regexp-quote TeX-esc) "begin\\b"))
	(end-of-line 1))
    (while (and (> level 0) (re-search-backward regexp nil t))
      (if (= (char-after (1+ (match-beginning 0))) ?e);;end
	  (setq level (1+ level))
	(setq level (1- level))))
    (or (= level 0)
	(error "Can't locate beginning of current environment"))))

(defun LaTeX-mark-environment ()
  "Set mark to end of current environment and point to the matching begin
will not work properly if there are unbalanced begin-end pairs in
comments and verbatim environments"
  (interactive)
  (let ((cur (point)))
    (LaTeX-find-matching-end)
    (beginning-of-line 2)
    (set-mark (point))
    (goto-char cur)
    (LaTeX-find-matching-begin)
    (TeX-activate-region)))

(defun LaTeX-fill-environment (justify)
  "Fill and indent current environment as LaTeX text."
  (interactive "*P")
  (save-excursion
    (LaTeX-mark-environment)
    (re-search-forward "{\\([^}]+\\)}")
    (LaTeX-fill-region
     (region-beginning)
     (region-end)
     justify
     (concat " environment " (TeX-match-buffer 1)))))

(defun LaTeX-fill-section (justify)
  "Fill and indent current logical section as LaTeX text."
  (interactive "*P")
  (save-excursion
    (LaTeX-mark-section)
    (re-search-forward "{\\([^}]+\\)}")
    (LaTeX-fill-region
     (region-beginning)
     (region-end)
     justify
     (concat " section " (TeX-match-buffer 1)))))

(defun LaTeX-mark-section ()
  "Set mark at end of current logical section, and point at top."
  (interactive)
  (re-search-forward (concat  "\\(" (LaTeX-outline-regexp)
			      "\\|\\'\\)"))
  (re-search-backward "^")
  (set-mark (point))
  (re-search-backward (concat "\\(" (LaTeX-outline-regexp)
			      "\\|\\`\\)"))
  (TeX-activate-region))

(defun LaTeX-fill-buffer (justify)
  "Fill and indent current buffer as LaTeX text."
  (interactive "*P")
  (save-excursion
    (LaTeX-fill-region
     (point-min)
     (point-max)
     justify
     (concat " buffer " (buffer-name)))))

(defvar LaTeX-indent-environment-list
  '(("verbatim" current-indentation)
    ("verbatim*" current-indentation)
    ;; The following should have there own, smart indentation function.
    ;; Some other day.
    ("alltt")
    ("array")
    ("displaymath")
    ("eqnarray")
    ("eqnarray*")
    ("equation")
    ("equation*")
    ("picture")
    ("tabbing")
    ("table")
    ("table*")
    ("tabular")
    ("tabular*"))
    "Alist of environments with special indentation.
The second element in each entry is the function to calculate the
indentation level in columns.")

(defvar LaTeX-indent-environment-check t
  "*If non-nil, check for any special environments.")

(defvar LaTeX-left-comment-regexp "%%%"
  "*Regexp matching comments that should be placed on the left margin.")

(defvar LaTeX-right-comment-regexp "%[^%]"
  "*Regexp matching comments that should be placed to the right margin.")

(defvar LaTeX-ignore-comment-regexp nil
  "*Regexp matching comments that whose indentation should not be touched.")

(defun LaTeX-indent-calculate ()
  ;; Return the correct indentation of line of LaTeX source. (I hope...)
  (save-excursion
    (back-to-indentation)
    (cond ((looking-at (concat (regexp-quote TeX-esc)
			       "\\(begin\\|end\\){verbatim\\*?}"))
	   ;; \end{verbatim} must be flush left, otherwise an unwanted
	   ;; empty line appears in LaTeX's output.
	   0)
	  ((and LaTeX-left-comment-regexp
		(looking-at LaTeX-left-comment-regexp))
	   ;; Comments to the left margin.
	   0)
	  ((and LaTeX-right-comment-regexp
                (looking-at LaTeX-right-comment-regexp))
           ;; Comments to the right margin.
	   comment-column)
	  ((and LaTeX-ignore-comment-regexp
                (looking-at LaTeX-ignore-comment-regexp))
           ;; Comments best left alone.
	   (current-indentation))
	  ((and LaTeX-indent-environment-check
		;; Special environments.
		(let ((entry (assoc (LaTeX-current-environment)
				    LaTeX-indent-environment-list)))
		  (and entry
		       (nth 1 entry)
		       (funcall (nth 1 entry))))))
	  ((looking-at (concat (regexp-quote TeX-esc) "end\\b"))
	   ;; Backindent at \end.
	   (- (LaTeX-indent-calculate-last) LaTeX-indent-level))
	  ((looking-at (concat (regexp-quote TeX-esc) "right\\b"))
	   ;; Backindent at \right.
	   (- (LaTeX-indent-calculate-last) LaTeX-left-right-indent-level))
	  ((looking-at (concat (regexp-quote TeX-esc) LaTeX-item-regexp))
	   ;; Items.
	   (+ (LaTeX-indent-calculate-last) LaTeX-item-indent))
	  (t (LaTeX-indent-calculate-last)))))

(defvar LaTeX-left-right-indent-level LaTeX-indent-level
  "*The level of indentation produced by a \\left macro.")

(defun LaTeX-indent-level-count ()
  ;; Count indentation change caused by all \left, \right, \begin, and
  ;; \end commands in the current line.
  (save-excursion
    (save-restriction
      (let ((count 0))
	(narrow-to-region (point)
			  (save-excursion
			    (re-search-forward (concat "[^"
						       (regexp-quote TeX-esc)
						       "]%\\|\n\\|\\'"))
			    (backward-char)
			    (point)))
	(while (search-forward TeX-esc nil t)
	  (cond
	   ((looking-at "left\\b")
	    (setq count (+ count LaTeX-left-right-indent-level)))
	   ((looking-at "right\\b")
	    (setq count (- count LaTeX-left-right-indent-level)))
	   ((looking-at "begin\\b")
	    (setq count (+ count LaTeX-indent-level)))
	   ((looking-at "end\\b")
	    (setq count (- count LaTeX-indent-level)))
	   ((looking-at (regexp-quote TeX-esc))
	    (forward-char 1))))
	count))))

(defun LaTeX-indent-calculate-last ()
  "Return the correct indentation of a normal line of text.
The point is supposed to be at the beginning of the current line."
  (save-restriction
    (widen)
    (skip-chars-backward "\n\t ")
    (move-to-column (current-indentation))

    ;; Ignore comments.
    (while (and (looking-at (regexp-quote comment-start)) (not (bobp)))
      (skip-chars-backward "\n\t ")
      (if (not (bobp))
	  (move-to-column (current-indentation))))

    (cond ((bobp) 0)
	  ((looking-at (concat (regexp-quote TeX-esc) "begin{document}"))
	   ;; I dislike having all of the document indented...
	   (current-indentation))
	  ((looking-at (concat (regexp-quote TeX-esc) "begin *"
			       (regexp-quote TeX-grop)
			       "verbatim\\*?"
			       (regexp-quote TeX-grcl)))
	   0)
	  ((looking-at (concat (regexp-quote TeX-esc) "end"
			       (regexp-quote TeX-grop)
			       "verbatim\\*?"
			       (regexp-quote TeX-grcl)))
	   ;; If I see an \end{verbatim} in the previous line I skip
	   ;; back to the preceding \begin{verbatim}.
	   (save-excursion
	     (if (re-search-backward (concat (regexp-quote TeX-esc)
					     "begin *"
					     (regexp-quote TeX-grop)
					     "verbatim\\*?"
					     (regexp-quote TeX-grcl)) 0 t)
		 (LaTeX-indent-calculate-last)
	       0)))
	  (t (+ (current-indentation)
		(TeX-brace-count-line)
		(LaTeX-indent-level-count)
		(cond ((looking-at (concat (regexp-quote TeX-esc) "end\\b"))
		       LaTeX-indent-level)
		      ((looking-at (concat (regexp-quote TeX-esc) "right\\b"))
		       LaTeX-left-right-indent-level)
		      ((looking-at (concat (regexp-quote TeX-esc)
					   LaTeX-item-regexp))
		       (- LaTeX-item-indent))
		      (t 0)))))))

;;; Math Minor Mode

(defvar LaTeX-math-list nil
  "AList of your personal LaTeX math symbols.  

Each entry should be a list with three elements, KEY, VALUE, and MENU.
KEY is the key to be redefined (under `LaTeX-math-abbrev-prefix' in
math minor mode, VALUE can be a string with the name of the macro to
be inserted, or a function to be called.  The optional third element is
the name of the submenu where the command should be added.

See also `LaTeX-math-menu'.")

(defconst LaTeX-math-default
  '((?a "alpha" "greek")
    (?b "beta" "greek")
    (?c LaTeX-math-cal "Cal-whatever")
    (?d "delta" "greek")
    (?e "epsilon" "greek")
    (?f "phi" "greek")
    (?g "gamma" "greek")
    (?h  "eta" "greek")
    (?k "kappa" "greek")
    (?l "lambda" "greek")
    (?m "mu" "greek")
    (?N "nabla" "greek")
    (?n "nu" "greek")
    (?o "omega" "greek")
    (?p "pi" "greek")
    (?q "theta" "greek")
    (?r "rho" "greek")
    (?s "sigma" "greek")
    (?t "tau" "greek")
    (?u "upsilon" "greek")
    (?x "chi" "greek")
    (?y "psi" "greek")
    (?z "zeta" "greek")
    (?D "Delta" "Greek")
    (?F "Phi" "Greek")
    (?G "Gamma" "Greek")
    (?Q "Theta" "Greek")
    (?L "Lambda" "Greek")
    (?Y "Psi" "Greek")
    (?P "Pi" "Greek")
    (?S "Sigma" "Greek")
    (?U "Upsilon" "Greek")
    (?O "Omega" "Greek")
    (nil "pm" "Binary Op")
    (nil "mp" "Binary Op")
    (?* "times" "Binary Op")
    (nil "div" "Binary Op")
    (nil "ast" "Binary Op")
    (nil "star" "Binary Op")
    (nil "circ" "Binary Op")
    (nil "bullet" "Binary Op")
    (?. "cdot" "Binary Op")
    (?- "cap" "Binary Op")
    (?+ "cup" "Binary Op")
    (nil "uplus" "Binary Op")
    (nil "sqcap" "Binary Op")
    (?| "vee" "Binary Op")
    (?& "wedge" "Binary Op")
    (?\\ "setminus" "Binary Op")
    (nil "wr" "Binary Op")
    (nil "diamond" "Binary Op")
    (nil "bigtriangleup" "Binary Op")
    (nil "bigtriangledown" "Binary Op")
    (nil "triangleleft" "Binary Op")
    (nil "triangleright" "Binary Op")
    (nil "lhd" "Binary Op")
    (nil "rhd" "Binary Op")
    (nil "unlhd" "Binary Op")
    (nil "unrhd" "Binary Op")
    (nil "oplus" "Binary Op")
    (nil "ominus" "Binary Op")
    (nil "otimes" "Binary Op")
    (nil "oslash" "Binary Op")
    (nil "odot" "Binary Op")
    (nil "bigcirc" "Binary Op")
    (nil "dagger" "Binary Op")
    (nil "ddagger" "Binary Op")
    (nil "amalg" "Binary Op")
    (?< "leq" "Relational")
    (?> "geq" "Relational")
    (nil "qed" "Relational")
    (nil "equiv" "Relational")
    (nil "models" "Relational")
    (nil "prec" "Relational")
    (nil "succ" "Relational")
    (nil "sim" "Relational")
    (nil "perp" "Relational")
    (nil "preceq" "Relational")
    (nil "succeq" "Relational")
    (nil "simeq" "Relational")
    (nil "mid" "Relational")
    (nil "ll" "Relational")
    (nil "gg" "Relational")
    (nil "asymp" "Relational")
    (nil "parallel" "Relational")
    (?{ "subset" "Relational")
    (?} "supset" "Relational")
    (nil "approx" "Relational")
    (nil "bowtie" "Relational")
    (?\[ "subseteq" "Relational")
    (?\] "supseteq" "Relational")
    (nil "cong" "Relational")
    (nil "Join" "Relational")
    (nil "sqsubset" "Relational")
    (nil "sqsupset" "Relational")
    (nil "neq" "Relational")
    (nil "smile" "Relational")
    (nil "sqsubseteq" "Relational")
    (nil "sqsupseteq" "Relational")
    (nil "doteq" "Relational")
    (nil "frown" "Relational")
    (?i "in" "Relational")
    (nil "ni" "Relational")
    (nil "propto" "Relational")
    (nil "vdash" "Relational")
    (nil "dashv" "Relational")
    (?\C-b "leftarrow" "Arrows")
    (nil "Leftarrow" "Arrows")
    (?\C-f "rightarrow" "Arrows")
    (nil "Rightarrow" "Arrows")
    (nil "leftrightarrow" "Arrows")
    (nil "Leftrightarrow" "Arrows")
    (nil "mapsto" "Arrows")
    (nil "hookleftarrow" "Arrows")
    (nil "leftharpoonup" "Arrows")
    (nil "leftharpoondown" "Arrows")
    (nil "longleftarrow" "Arrows")
    (nil "Longleftarrow" "Arrows")
    (nil "longrightarrow" "Arrows")
    (nil "Longrightarrow" "Arrows")
    (nil "longleftrightarrow" "Arrows")
    (nil "Longleftrightarrow" "Arrows")
    (nil "longmapsto" "Arrows")
    (nil "hookrightarrow" "Arrows")
    (nil "rightharpoonup" "Arrows")
    (nil "rightharpoondown" "Arrows")
    (?\C-p "uparrow" "Arrows")
    (nil "Uparrow" "Arrows")
    (?\C-n "downarrow" "Arrows")
    (nil "Downarrow" "Arrows")
    (nil "updownarrow" "Arrows")
    (nil "Updownarrow" "Arrows")
    (nil "nearrow" "Arrows")
    (nil "searrow" "Arrows")
    (nil "swarrow" "Arrows")
    (nil "nwarrow" "Arrows")
    (nil "ldots" "Misc Symbol") 
    (nil "cdots" "Misc Symbol") 
    (nil "vdots" "Misc Symbol") 
    (nil "ddots" "Misc Symbol") 
    (nil "aleph" "Misc Symbol") 
    (nil "prime" "Misc Symbol") 
    (?A "forall" "Misc Symbol") 
    (?I "infty" "Misc Symbol") 
    (nil "hbar" "Misc Symbol") 
    (?0 "emptyset" "Misc Symbol") 
    (?E "exists" "Misc Symbol") 
    (nil "nabla" "Misc Symbol") 
    (nil "surd" "Misc Symbol") 
    (nil "Box" "Misc Symbol") 
    (nil "triangle" "Misc Symbol") 
    (nil "Diamond" "Misc Symbol") 
    (nil "imath" "Misc Symbol") 
    (nil "jmath" "Misc Symbol") 
    (nil "ell" "Misc Symbol") 
    (nil "neg" "Misc Symbol") 
    (?/ "not" "Misc Symbol")
    (nil "top" "Misc Symbol") 
    (nil "flat" "Misc Symbol") 
    (nil "natural" "Misc Symbol") 
    (nil "sharp" "Misc Symbol") 
    (nil "wp" "Misc Symbol") 
    (nil "bot" "Misc Symbol") 
    (nil "clubsuit" "Misc Symbol") 
    (nil "diamondsuit" "Misc Symbol") 
    (nil "heartsuit" "Misc Symbol") 
    (nil "spadesuit" "Misc Symbol") 
    (nil "mho" "Misc Symbol") 
    (nil "Re" "Misc Symbol") 
    (nil "Im" "Misc Symbol") 
    (nil "angle" "Misc Symbol") 
    (nil "partial" "Misc Symbol") 
    (nil "sum" "Var Symbol")
    (nil "prod" "Var Symbol")
    (nil "coprod" "Var Symbol")
    (nil "int" "Var Symbol")
    (nil "oint" "Var Symbol")
    (nil "bigcap" "Var Symbol")
    (nil "bigcup" "Var Symbol")
    (nil "bigsqcup" "Var Symbol")
    (nil "bigvee" "Var Symbol")
    (nil "bigwedge" "Var Symbol")
    (nil "bigodot" "Var Symbol")
    (nil "bigotimes" "Var Symbol")
    (nil "bigoplus" "Var Symbol")
    (nil "biguplus" "Var Symbol")
    (nil "arccos" "Log-like")
    (nil "arcsin" "Log-like")
    (nil "arctan" "Log-like")
    (nil "arg" "Log-like")
    (?\C-c "cos" "Log-like")
    (nil "cosh" "Log-like")
    (nil "cot" "Log-like")
    (nil "coth" "Log-like")
    (nil "csc" "Log-like")
    (nil "deg" "Log-like")
    (?\C-d "det" "Log-like")
    (nil "dim" "Log-like")
    (?\C-e "exp" "Log-like")
    (nil "gcd" "Log-like")
    (nil "hom" "Log-like")
    (?\C-_ "inf" "Log-like")
    (nil "ker" "Log-like")
    (nil "lg" "Log-like")
    (?\C-l "lim" "Log-like")
    (nil "liminf" "Log-like")
    (nil "limsup" "Log-like")
    (nil "ln" "Log-like")
    (nil "log" "Log-like")
    (nil "max" "Log-like")
    (nil "min" "Log-like")
    (nil "Pr" "Log-like")
    (nil "sec" "Log-like")
    (?\C-s "sin" "Log-like")
    (nil "sinh" "Log-like")
    (?\C-^ "sup" "Log-like")
    (?\C-t "tan" "Log-like")
    (nil "tanh" "Log-like")
    (nil "uparrow" "delimiters")
    (nil "Uparrow" "delimiters")
    (nil "downarrow" "delimiters")
    (nil "Downarrow" "delimiters")
    (nil "{" "delimiters")
    (nil "}" "delimiters")
    (nil "updownarrow" "delimiters")
    (nil "Updownarrow" "delimiters")
    (nil "lfloor" "delimiters")
    (nil "rfloor" "delimiters")
    (nil "lceil" "delimiters")
    (nil "rceil" "delimiters")
    (?\( "langle" "delimiters")
    (?\) "rangle" "delimiters")
    (nil "backslash" "delimiters")
    (nil "|" "delimiters")
    (nil "rmoustache" "Delimiters")
    (nil "lmoustache" "Delimiters")
    (nil "rgroup" "Delimiters")
    (nil "lgroup" "Delimiters")    
    (nil "arrowvert" "Delimiters")
    (nil "Arrowvert" "Delimiters")
    (nil "bracevert" "Delimiters")
    (nil "widetilde" "Constructs")
    (nil "widehat" "Constructs")
    (nil "overleftarrow" "Constructs")
    (nil "overrightarrow" "Constructs")
    (nil "overline" "Constructs")
    (nil "underline" "Constructs")
    (nil "overbrace" "Constructs")
    (nil "underbrace" "Constructs")
    (nil "sqrt" "Constructs")
    (nil "frac" "Constructs")
    (?^ "hat" "Accents")
    (nil "acute" "Accents")
    (nil "bar" "Accents")
    (nil "dot" "Accents")
    (nil "breve" "Accents")
    (nil "check" "Accents")
    (nil "grave" "Accents")
    (nil "vec" "Accents")
    (nil "ddot" "Accents")
    (?~ "tilde" "Accents")
    (nil "ulcorner" ("AMS" "Hebrew"))
    (nil "urcorner" ("AMS" "Hebrew"))
    (nil "llcorner" ("AMS" "Hebrew"))
    (nil "lrcorner" ("AMS" "Hebrew"))
    (nil "dashrightarrow" ("AMS" "Arrows"))
    (nil "dashleftarrow" ("AMS" "Arrows"))
    (nil "leftleftarrows" ("AMS" "Arrows"))
    (nil "leftrightarrows" ("AMS" "Arrows"))
    (nil "Lleftarrow" ("AMS" "Arrows"))
    (nil "twoheadleftarrow" ("AMS" "Arrows"))
    (nil "leftarrowtail" ("AMS" "Arrows"))
    (nil "looparrowleft" ("AMS" "Arrows"))
    (nil "leftrightharpoons" ("AMS" "Arrows"))
    (nil "curvearrowleft" ("AMS" "Arrows"))
    (nil "circlearrowleft" ("AMS" "Arrows"))
    (nil "Lsh" ("AMS" "Arrows"))
    (nil "upuparrows" ("AMS" "Arrows"))
    (nil "upharpoonleft" ("AMS" "Arrows"))
    (nil "downharpoonleft" ("AMS" "Arrows"))
    (nil "multimap" ("AMS" "Arrows"))
    (nil "leftrightsquigarrow" ("AMS" "Arrows"))
    (nil "looparrowright" ("AMS" "Arrows"))
    (nil "rightleftharpoons" ("AMS" "Arrows"))
    (nil "curvearrowright" ("AMS" "Arrows"))
    (nil "circlearrowright" ("AMS" "Arrows"))
    (nil "Rsh" ("AMS" "Arrows"))
    (nil "downdownarrows" ("AMS" "Arrows"))
    (nil "upharpoonright" ("AMS" "Arrows"))
    (nil "downharpoonright" ("AMS" "Arrows"))
    (nil "rightsquigarrow" ("AMS" "Arrows"))
    (nil "nleftarrow" ("AMS" "Neg Arrows"))
    (nil "nrightarrow" ("AMS" "Neg Arrows"))
    (nil "nLeftarrow" ("AMS" "Neg Arrows"))
    (nil "nRightarrow" ("AMS" "Neg Arrows"))
    (nil "nleftrightarrow" ("AMS" "Neg Arrows"))
    (nil "nLeftrightarrow" ("AMS" "Neg Arrows"))
    (nil "leqq" ("AMS" "Relational I"))
    (nil "leqslant" ("AMS" "Relational I"))
    (nil "eqslantless" ("AMS" "Relational I"))
    (nil "lesssim" ("AMS" "Relational I"))
    (nil "lessapprox" ("AMS" "Relational I"))
    (nil "approxeq" ("AMS" "Relational I"))
    (nil "lessdot" ("AMS" "Relational I"))
    (nil "lll" ("AMS" "Relational I"))
    (nil "lessgtr" ("AMS" "Relational I"))
    (nil "lesseqgtr" ("AMS" "Relational I"))
    (nil "lesseqqgtr" ("AMS" "Relational I"))
    (nil "doteqdot" ("AMS" "Relational I"))
    (nil "risingdotseq" ("AMS" "Relational I"))
    (nil "fallingdotseq" ("AMS" "Relational I"))
    (nil "backsim" ("AMS" "Relational I"))
    (nil "backsimeq" ("AMS" "Relational I"))
    (nil "subseteqq" ("AMS" "Relational I"))
    (nil "Subset" ("AMS" "Relational I"))
    (nil "sqsubset" ("AMS" "Relational I"))
    (nil "preccurlyeq" ("AMS" "Relational I"))
    (nil "curlyeqprec" ("AMS" "Relational I"))
    (nil "precsim" ("AMS" "Relational I"))
    (nil "precapprox" ("AMS" "Relational I"))
    (nil "vartriangleleft" ("AMS" "Relational I"))
    (nil "trianglelefteq" ("AMS" "Relational I"))
    (nil "vDash" ("AMS" "Relational I"))
    (nil "Vvdash" ("AMS" "Relational I"))
    (nil "smallsmile" ("AMS" "Relational I"))
    (nil "smallfrown" ("AMS" "Relational I"))
    (nil "bumpeq" ("AMS" "Relational I"))
    (nil "Bumpeq" ("AMS" "Relational I"))
    (nil "geqq" ("AMS" "Relational II"))
    (nil "geqslant" ("AMS" "Relational II"))
    (nil "eqslantgtr" ("AMS" "Relational II"))
    (nil "gtrsim" ("AMS" "Relational II"))
    (nil "gtrapprox" ("AMS" "Relational II"))
    (nil "gtrdot" ("AMS" "Relational II"))
    (nil "ggg" ("AMS" "Relational II"))
    (nil "gtrless" ("AMS" "Relational II"))
    (nil "gtreqless" ("AMS" "Relational II"))
    (nil "gtreqqless" ("AMS" "Relational II"))
    (nil "eqcirc" ("AMS" "Relational II"))
    (nil "circeq" ("AMS" "Relational II"))
    (nil "triangleq" ("AMS" "Relational II"))
    (nil "thicksim" ("AMS" "Relational II"))
    (nil "thickapprox" ("AMS" "Relational II"))
    (nil "supseteqq" ("AMS" "Relational II"))
    (nil "Supset" ("AMS" "Relational II"))
    (nil "sqsupset" ("AMS" "Relational II"))
    (nil "succcurlyeq" ("AMS" "Relational II"))
    (nil "curlyeqsucc" ("AMS" "Relational II"))
    (nil "succsim" ("AMS" "Relational II"))
    (nil "succapprox" ("AMS" "Relational II"))
    (nil "vartriangleright" ("AMS" "Relational II"))
    (nil "trianglerighteq" ("AMS" "Relational II"))
    (nil "Vdash" ("AMS" "Relational II"))
    (nil "shortmid" ("AMS" "Relational II"))
    (nil "shortparallel" ("AMS" "Relational II"))
    (nil "between" ("AMS" "Relational II"))
    (nil "pitchfork" ("AMS" "Relational II"))
    (nil "varpropto" ("AMS" "Relational II"))
    (nil "blacktriangleleft" ("AMS" "Relational II"))
    (nil "therefore" ("AMS" "Relational II"))
    (nil "backepsilon" ("AMS" "Relational II"))
    (nil "blacktriangleright" ("AMS" "Relational II"))
    (nil "because" ("AMS" "Relational II"))
    (nil "nless" ("AMS" "Neg Rel I"))
    (nil "nleq" ("AMS" "Neg Rel I"))
    (nil "nleqslant" ("AMS" "Neg Rel I"))
    (nil "nleqq" ("AMS" "Neg Rel I"))
    (nil "lneq" ("AMS" "Neg Rel I"))
    (nil "lneqq" ("AMS" "Neg Rel I"))
    (nil "lvertneqq" ("AMS" "Neg Rel I"))
    (nil "lnsim" ("AMS" "Neg Rel I"))
    (nil "lnapprox" ("AMS" "Neg Rel I"))
    (nil "nprec" ("AMS" "Neg Rel I"))
    (nil "npreceq" ("AMS" "Neg Rel I"))
    (nil "precnsim" ("AMS" "Neg Rel I"))
    (nil "precnapprox" ("AMS" "Neg Rel I"))
    (nil "nsim" ("AMS" "Neg Rel I"))
    (nil "nshortmid" ("AMS" "Neg Rel I"))
    (nil "nmid" ("AMS" "Neg Rel I"))
    (nil "nvdash" ("AMS" "Neg Rel I"))
    (nil "nvDash" ("AMS" "Neg Rel I"))
    (nil "ntriangleleft" ("AMS" "Neg Rel I"))
    (nil "ntrianglelefteq" ("AMS" "Neg Rel I"))
    (nil "nsubseteq" ("AMS" "Neg Rel I"))
    (nil "subsetneq" ("AMS" "Neg Rel I"))
    (nil "varsubsetneq" ("AMS" "Neg Rel I"))
    (nil "subsetneqq" ("AMS" "Neg Rel I"))
    (nil "varsubsetneqq" ("AMS" "Neg Rel I"))
    (nil "ngtr" ("AMS" "Neg Rel II"))
    (nil "ngeq" ("AMS" "Neg Rel II"))
    (nil "ngeqslant" ("AMS" "Neg Rel II"))
    (nil "ngeqq" ("AMS" "Neg Rel II"))
    (nil "gneq" ("AMS" "Neg Rel II"))
    (nil "gneqq" ("AMS" "Neg Rel II"))
    (nil "gvertneqq" ("AMS" "Neg Rel II"))
    (nil "gnsim" ("AMS" "Neg Rel II"))
    (nil "gnapprox" ("AMS" "Neg Rel II"))
    (nil "nsucc" ("AMS" "Neg Rel II"))
    (nil "nsucceq" ("AMS" "Neg Rel II"))
    (nil "succnsim" ("AMS" "Neg Rel II"))
    (nil "succnapprox" ("AMS" "Neg Rel II"))
    (nil "ncong" ("AMS" "Neg Rel II"))
    (nil "nshortparallel" ("AMS" "Neg Rel II"))
    (nil "nparallel" ("AMS" "Neg Rel II"))
    (nil "nvDash" ("AMS" "Neg Rel II"))
    (nil "nVDash" ("AMS" "Neg Rel II"))
    (nil "ntriangleright" ("AMS" "Neg Rel II"))
    (nil "ntrianglerighteq" ("AMS" "Neg Rel II"))
    (nil "nsupseteq" ("AMS" "Neg Rel II"))
    (nil "nsupseteqq" ("AMS" "Neg Rel II"))
    (nil "supsetneq" ("AMS" "Neg Rel II"))
    (nil "varsupsetneq" ("AMS" "Neg Rel II"))
    (nil "supsetneqq" ("AMS" "Neg Rel II"))
    (nil "varsupsetneqq" ("AMS" "Neg Rel II"))
    (nil "dotplus" ("AMS" "Binary Op"))
    (nil "smallsetminus" ("AMS" "Binary Op"))
    (nil "Cap" ("AMS" "Binary Op"))
    (nil "Cup" ("AMS" "Binary Op"))
    (nil "barwedge" ("AMS" "Binary Op"))
    (nil "veebar" ("AMS" "Binary Op"))
    (nil "doublebarwedge" ("AMS" "Binary Op"))
    (nil "boxminus" ("AMS" "Binary Op"))
    (nil "boxtimes" ("AMS" "Binary Op"))
    (nil "boxdot" ("AMS" "Binary Op"))
    (nil "boxplus" ("AMS" "Binary Op"))
    (nil "divideontimes" ("AMS" "Binary Op"))
    (nil "ltimes" ("AMS" "Binary Op"))
    (nil "rtimes" ("AMS" "Binary Op"))
    (nil "leftthreetimes" ("AMS" "Binary Op"))
    (nil "rightthreetimes" ("AMS" "Binary Op"))
    (nil "curlywedge" ("AMS" "Binary Op"))
    (nil "curlyvee" ("AMS" "Binary Op"))
    (nil "circleddash" ("AMS" "Binary Op"))
    (nil "circledast" ("AMS" "Binary Op"))
    (nil "circledcirc" ("AMS" "Binary Op"))
    (nil "centerdot" ("AMS" "Binary Op"))
    (nil "intercal" ("AMS" "Binary Op"))
    (nil "hbar" ("AMS" "Misc"))
    (nil "hslash" ("AMS" "Misc"))
    (nil "vartriangle" ("AMS" "Misc"))
    (nil "triangledown" ("AMS" "Misc"))
    (nil "square" ("AMS" "Misc"))
    (nil "lozenge" ("AMS" "Misc"))
    (nil "circledS" ("AMS" "Misc"))
    (nil "angle" ("AMS" "Misc"))
    (nil "measuredangle" ("AMS" "Misc"))
    (nil "nexists" ("AMS" "Misc"))
    (nil "mho" ("AMS" "Misc"))
    (nil "Finv" ("AMS" "Misc"))
    (nil "Game" ("AMS" "Misc"))
    (nil "Bbbk" ("AMS" "Misc"))
    (nil "backprime" ("AMS" "Misc"))
    (nil "varnothing" ("AMS" "Misc"))
    (nil "blacktriangle" ("AMS" "Misc"))
    (nil "blacktriangledown" ("AMS" "Misc"))
    (nil "blacksquare" ("AMS" "Misc"))
    (nil "blacklozenge" ("AMS" "Misc"))
    (nil "bigstar" ("AMS" "Misc"))
    (nil "sphericalangle" ("AMS" "Misc"))
    (nil "complement" ("AMS" "Misc"))
    (nil "eth" ("AMS" "Misc"))
    (nil "diagup" ("AMS" "Misc"))
    (nil "diagdown" ("AMS" "Misc"))
    (nil "Hat" ("AMS" "Accents"))
    (nil "Check" ("AMS" "Accents"))
    (nil "Tilde" ("AMS" "Accents"))
    (nil "Acute" ("AMS" "Accents"))
    (nil "Grave" ("AMS" "Accents"))
    (nil "Dot" ("AMS" "Accents"))
    (nil "Ddot" ("AMS" "Accents"))
    (nil "Breve" ("AMS" "Accents"))
    (nil "Bar" ("AMS" "Accents"))
    (nil "Vec" ("AMS" "Accents"))
    (nil "dddot" ("AMS" "Accents"))
    (nil "ddddot" ("AMS" "Accents"))
    (nil "bigl" ("AMS" "Delimiters"))
    (nil "bigr" ("AMS" "Delimiters"))
    (nil "Bigl" ("AMS" "Delimiters"))
    (nil "Bigr" ("AMS" "Delimiters"))
    (nil "biggl" ("AMS" "Delimiters"))
    (nil "biggr" ("AMS" "Delimiters"))
    (nil "Biggl" ("AMS" "Delimiters"))
    (nil "Biggr" ("AMS" "Delimiters"))
    (nil "lvert" ("AMS" "Delimiters"))
    (nil "rvert" ("AMS" "Delimiters"))
    (nil "lVert" ("AMS" "Delimiters"))
    (nil "rVert" ("AMS" "Delimiters"))
    (nil "nobreakdash" ("AMS" "Special"))
    (nil "leftroot" ("AMS" "Special"))
    (nil "uproot" ("AMS" "Special"))
    (nil "accentedsymbol" ("AMS" "Special"))
    (nil "xleftarrow" ("AMS" "Special"))
    (nil "xrightarrow" ("AMS" "Special"))
    (nil "overset" ("AMS" "Special"))
    (nil "underset" ("AMS" "Special"))
    (nil "dfrac" ("AMS" "Special"))
    (nil "genfrac" ("AMS" "Special"))
    (nil "tfrac" ("AMS" "Special"))
    (nil "binom" ("AMS" "Special"))
    (nil "dbinom" ("AMS" "Special"))
    (nil "tbinom" ("AMS" "Special"))
    (nil "smash" ("AMS" "Special"))
    (nil "eucal" ("AMS" "Special"))
    (nil "boldsymbol" ("AMS" "Special"))
    (nil "text" ("AMS" "Special"))
    (nil "intertext" ("AMS" "Special"))
    (nil "substack" ("AMS" "Special"))
    (nil "subarray" ("AMS" "Special"))
    (nil "sideset" ("AMS" "Special"))))

(defvar LaTeX-math-abbrev-prefix "`"
  "Prefix key for use in LaTeX-math-mode.")

(defvar LaTeX-math-keymap (make-sparse-keymap)
  "Keymap used for LaTeX-math-mode commands.")

(defvar LaTeX-math-menu
  '("Math"
    ("Greek") ("greek") ("Binary Op") ("Relational") ("Arrows")
    ("Misc Symbol") ("Var Symbol") ("Log-like") ("delimiters")
    ("Delimiters") ("Constructs") ("Accents") ("AMS"))
  "Menu containing LaTeX math commands.
The menu entries will be generated dynamically, but you can specify
the sequence by initializing this variable.")

(define-key LaTeX-math-keymap
  (concat LaTeX-math-abbrev-prefix LaTeX-math-abbrev-prefix)
  'LaTeX-math-insert-prefix)

(let ((math (reverse (append LaTeX-math-list LaTeX-math-default)))
      (map (lookup-key LaTeX-math-keymap LaTeX-math-abbrev-prefix)))
  (while math
    (let* ((entry (car math))
	   (key (nth 0 entry))
	   value menu name)
      (setq math (cdr math))
      (if (listp (cdr entry))
	  (setq value (nth 1 entry)
		menu (nth 2 entry))
	(setq value (cdr entry)
	      menu nil))
      (if (stringp value)
	  (progn
	   (setq name (intern (concat "LaTeX-math-" value)))
	   (fset name (list 'lambda (list 'arg) (list 'interactive "*P")
			    (list 'LaTeX-math-insert value 'arg))))
	(setq name value))
      (if key
	  (progn 
	    (setq key (if (numberp key) (char-to-string key) (vector key)))
	    (define-key map key name)))
      (if menu
	  (let ((parent LaTeX-math-menu))
	    (if (listp menu)
		(progn 
		  (while (cdr menu)
		    (let ((sub (assoc (car menu) LaTeX-math-menu)))
		      (if sub
			  (setq parent sub)
			(setcdr parent (cons (list (car menu)) (cdr parent))))
		      (setq menu (cdr menu))))
		  (setq menu (car menu))))
	    (let ((sub (assoc menu parent)))
	      (if sub 
		  (if (stringp value)
		      (setcdr sub (cons (vector value name t) (cdr sub)))
		    (error "Cannot have multiple special math menu items"))
		(setcdr parent
			(cons (if (stringp value)
				  (list menu (vector value name t))
				(vector menu name t))
			      (cdr parent))))))))))

(easy-menu-define LaTeX-math-mode-menu
    LaTeX-math-keymap
    "Menu used in math minor mode."
  LaTeX-math-menu)

(defvar LaTeX-math-mode nil
  "Is LaTeX-math-mode on or off? non nil means on.")

 (make-variable-buffer-local 'LaTeX-math-mode)

(or (assoc 'LaTeX-math-mode minor-mode-alist)
    (setq minor-mode-alist (cons '(LaTeX-math-mode " Math") minor-mode-alist)))

(or (assoc 'LaTeX-math-mode minor-mode-map-alist)
    (setq minor-mode-map-alist
	  (cons (cons 'LaTeX-math-mode LaTeX-math-keymap)
		minor-mode-map-alist)))

(defun LaTeX-math-mode (&optional arg)
  "A minor mode with easy acces to TeX math macros. 

Easy insertion of LaTeX math symbols.  If you give a prefix argument,
the symbols will be surrounded by dollar signs.  The following
commands are defined:

\\{LaTeX-math-keymap}"
  (interactive "P")
  (setq LaTeX-math-mode
	(not (or (and (null arg) LaTeX-math-mode)
		 (<= (prefix-numeric-value arg) 0))))
  (if LaTeX-math-mode
      (easy-menu-add LaTeX-math-mode-menu LaTeX-math-keymap)
    (easy-menu-remove LaTeX-math-mode-menu))
  (set-buffer-modified-p (buffer-modified-p)))

(fset 'latex-math-mode 'LaTeX-math-mode)

(defun LaTeX-math-insert-prefix ()
  "Insert the value of `LaTeX-math-abbrev-prefix'."
  (interactive "*")
  (let (LaTeX-math-mode)
    (call-interactively (key-binding LaTeX-math-abbrev-prefix))))

(defun LaTeX-math-insert (string dollar)
  ;; Inserts \STRING{}. If DOLLAR is non-nil, put $'s around it.
  (if dollar (insert "$"))
  (TeX-insert-macro string)
  (if dollar (insert "$")))

(defun LaTeX-math-cal (char dollar)
  "Inserts a {\\cal CHAR}.  If DOLLAR is non-nil, put $'s around it."
  (interactive "*c\nP")
  (if dollar (insert "$"))
  (if (member "latex2e" (TeX-style-list))
      (insert "\\mathcal{" (char-to-string char) "}")
    (insert "{\\cal " (char-to-string char) "}"))
  (if dollar (insert "$")))

(provide 'latex)

;;; Keymap

(defvar LaTeX-mode-map
  (let ((map (copy-keymap TeX-mode-map)))
    
    ;; Standard
    (define-key map "\n"      'reindent-then-newline-and-indent)
    
    ;; From latex.el
    (define-key map "\t"      'LaTeX-indent-line)
    (define-key map "\eq"     'LaTeX-fill-paragraph) ;*** Alias
    ;; This key is now used by Emacs for face settings.
    ;; (define-key map "\eg"     'LaTeX-fill-region) ;*** Alias
    (define-key map "\e\C-e"  'LaTeX-find-matching-end)
    (define-key map "\e\C-a"  'LaTeX-find-matching-begin)
    
    (define-key map "\C-c\C-q\C-p" 'LaTeX-fill-paragraph)
    (define-key map "\C-c\C-q\C-r" 'LaTeX-fill-region)
    (define-key map "\C-c\C-q\C-s" 'LaTeX-fill-section)
    (define-key map "\C-c\C-q\C-e" 'LaTeX-fill-environment)
    
    (define-key map "\C-c."    'LaTeX-mark-environment) ;*** Dubious
    (define-key map "\C-c*"    'LaTeX-mark-section) ;*** Dubious

    (define-key map "\C-c\C-e" 'LaTeX-environment)
    (define-key map "\C-c\n"   'LaTeX-insert-item)
    (or (key-binding "\e\r")
	(define-key map "\e\r"    'LaTeX-insert-item)) ;*** Alias
    (define-key map "\C-c]" 'LaTeX-close-environment)
    (define-key map "\C-c\C-s" 'LaTeX-section)

    ;; Outline commands...
    ;; We want to use the right prefix, if possible.
    (let ((outline (cond ((not (boundp 'outline-minor-mode-prefix))
			  (lookup-key map "\C-c"))
			 ((keymapp (lookup-key map outline-minor-mode-prefix))
			  (lookup-key map outline-minor-mode-prefix))
			 (t
			  (define-key map
			    outline-minor-mode-prefix (make-sparse-keymap))
			  (lookup-key map outline-minor-mode-prefix)))))
      (define-key outline "\C-z" 'LaTeX-hide-environment)
      (define-key outline "\C-x" 'LaTeX-show-environment))

    (define-key map "\C-c~"    'LaTeX-math-mode) ;*** Dubious
    
    map)
  "Keymap used in LaTeX-mode.")

(defvar LaTeX-environment-menu-name "Insert Environment  (C-c C-e)")

(defun LaTeX-environment-menu-entry (entry)
  ;; Create an entry for the environment menu.
  (vector (car entry) (list 'LaTeX-environment-menu (car entry)) t))

(defvar LaTeX-environment-modify-menu-name "Change Environment  (C-u C-c C-e)")

(defun LaTeX-environment-modify-menu-entry (entry)
  ;; Create an entry for the change environment menu.
  (vector (car entry) (list 'LaTeX-modify-environment (car entry)) t))

(defun LaTeX-section-enable-symbol (LEVEL)
  ;; Symbol used to enable section LEVEL in the menu bar.
  (intern (concat "LaTeX-section-" (int-to-string (nth 1 entry)) "-enable")))

(defun LaTeX-section-enable (entry)
  ;; Enable or disable section ENTRY from LaTeX-section-list.
  (let ((level (nth 1 entry)))
    (set (LaTeX-section-enable-symbol level)
	 (>= level LaTeX-largest-level))))

(defun LaTeX-section-menu (level)
  ;; Insert section from menu.
  (let ((LaTeX-section-hook (delq 'LaTeX-section-heading
				  (copy-sequence LaTeX-section-hook))))
    (LaTeX-section level)))

(defun LaTeX-section-menu-entry (entry)
  ;; Create an entry for the section menu.
  (let ((enable (LaTeX-section-enable-symbol (nth 1 entry))))
    (set enable t)
    (vector (car entry) (list 'LaTeX-section-menu (nth 1 entry)) enable)))

(defun LaTeX-section-menu-create ()
  ;; Create a menu over LaTeX sections.
  (append '("Section  (C-c C-s)")
	  (mapcar 'LaTeX-section-menu-entry LaTeX-section-list)))

(defvar LaTeX-menu-changed nil)
;; Need to update LaTeX menu.
(make-variable-buffer-local 'LaTeX-menu-changed)

(defun LaTeX-menu-update ()
  ;; Update entries on AUC TeX menu.
  (or (not (eq major-mode 'latex-mode))
      (null LaTeX-menu-changed)
      (not (fboundp 'easy-menu-change))
      (progn
	(TeX-update-style)
	(setq LaTeX-menu-changed nil)
	(message "Updating section menu...")
	(mapcar 'LaTeX-section-enable LaTeX-section-list)
	(message "Updating environment menu...")
	(easy-menu-change '("LaTeX") LaTeX-environment-menu-name
			  (mapcar 'LaTeX-environment-menu-entry
				  (LaTeX-environment-list)))
	(message "Updating modify environment menu...")
	(easy-menu-change '("LaTeX") LaTeX-environment-modify-menu-name
			  (mapcar 'LaTeX-environment-modify-menu-entry
				  (LaTeX-environment-list)))
	(message "Updating...done"))))

(add-hook 'activate-menubar-hook 'LaTeX-menu-update)

(easy-menu-define LaTeX-mode-menu
    LaTeX-mode-map
    "Menu used in LaTeX mode."
  (list "LaTeX"
	(list LaTeX-environment-menu-name "Bug.")
	(list LaTeX-environment-modify-menu-name "Bug.")
	(LaTeX-section-menu-create)
	["Macro..." TeX-insert-macro t]
	["Complete" TeX-complete-symbol t]
	["Item" LaTeX-insert-item t]
	(list "Insert Font"
	      ["Emphasize"  (TeX-font nil ?\C-e) :keys "C-c C-f C-e"]
	      ["Bold"       (TeX-font nil ?\C-b) :keys "C-c C-f C-b"]
	      ["Typewriter" (TeX-font nil ?\C-t) :keys "C-c C-f C-t"]
	      ["Small Caps" (TeX-font nil ?\C-c) :keys "C-c C-f C-c"]
	      ["Sans Serif" (TeX-font nil ?\C-f) :keys "C-c C-f C-f"]
	      ["Italic"     (TeX-font nil ?\C-i) :keys "C-c C-f C-i"]
	      ["Slanted"    (TeX-font nil ?\C-s) :keys "C-c C-f C-s"]
	      ["Roman"      (TeX-font nil ?\C-r) :keys "C-c C-f C-r"])
	(list "Change Font"
	      ["Emphasize"  (TeX-font t ?\C-e) :keys "C-u C-c C-f C-e"]
	      ["Bold"       (TeX-font t ?\C-b) :keys "C-u C-c C-f C-b"]
	      ["Typewriter" (TeX-font t ?\C-t) :keys "C-u C-c C-f C-t"]
	      ["Small Caps" (TeX-font t ?\C-c) :keys "C-u C-c C-f C-c"]
	      ["Sans Serif" (TeX-font t ?\C-f) :keys "C-u C-c C-f C-f"]
	      ["Italic"     (TeX-font t ?\C-i) :keys "C-u C-c C-f C-i"]
	      ["Slanted"    (TeX-font t ?\C-s) :keys "C-u C-c C-f C-s"]
	      ["Roman"      (TeX-font t ?\C-r) :keys "C-u C-c C-f C-r"])
	["Delete Font" (TeX-font t ?\C-d) :keys "C-c C-f C-d"]
	"-"
	["Next Error" TeX-next-error t]
	(list "TeX Output"
	      ["Kill Job" TeX-kill-job t]
	      ["Debug Bad Boxes" TeX-toggle-debug-boxes
	       :style toggle :selected TeX-debug-bad-boxes ]
	      ["Switch to Original File" TeX-home-buffer t]
	      ["Recenter Output Buffer" TeX-recenter-output-buffer t])
	(list "Formatting and Marking"
	      ["Format Environment" LaTeX-fill-environment t]
	      ["Format Paragraph" LaTeX-fill-paragraph t]
	      ["Format Region" LaTeX-fill-region t]
	      ["Format Section" LaTeX-fill-section t]
	      ["Mark Environment" LaTeX-mark-environment t]
	      ["Mark Section" LaTeX-mark-section t]
	      ["Beginning of Environment" LaTeX-find-matching-begin t]
	      ["End of Environment" LaTeX-find-matching-end t]
	      ["Hide Environment" LaTeX-hide-environment t]
	      ["Show Environment" LaTeX-show-environment t])
	(list "Miscellaneous"
	      ["Uncomment Region" TeX-un-comment-region t]
	      ["Comment Region" TeX-comment-region t]
	      ["Switch to Master file" TeX-home-buffer t]
	      ["Save Document" TeX-save-document t]
	      ["Math Mode" LaTeX-math-mode 
	       :style toggle :selected LaTeX-math-mode ]
	      ["Documentation" TeX-goto-info-page t]
	      ["Submit bug report" TeX-submit-bug-report t]
	      [ "Convert 209 to 2e" LaTeX-209-to-2e
		:active (member "latex2" (TeX-style-list)) ]
	      ["Reset Buffer" TeX-normal-mode t]
	      ["Reset AUC TeX" (TeX-normal-mode t) :keys "C-u C-c C-n"])))

(defvar LaTeX-font-list
  '((?\C-b "\\textbf{" "}")
    (?\C-c "\\textsc{" "}")
    (?\C-e "\\emph{" "}")
    (?\C-f "\\textsf{" "}")
    (?\C-i "\\textit{" "}")
    (?\C-m "\\textmd{" "}")
    (?\C-n "\\textnormal{" "}")
    (?\C-r "\\textrm{" "}")
    (?\C-s "\\textsl{" "}")
    (?\C-t "\\texttt{" "}")
    (?\C-u "\\textup{" "}")
    (?\C-d "" "" t))
  "Font commands used with LaTeX2e.  See `TeX-font-list'.")

;;; Mode

(defvar TeX-arg-cite-note-p nil
  "*If non-nil, ask for optional note in citations.")

(defvar TeX-arg-footnote-number-p nil
  "*If non-nil, ask for optional number in footnotes.")

(defvar TeX-arg-item-label-p nil
  "*If non-nil, always ask for optional label in items.
Otherwise, only ask in description environments.")

(defvar TeX-arg-right-insert-p t
  "*If non-nil, always insert automatically the corresponding
\\right if \\left is inserted.")

(defvar LaTeX-paragraph-commands
  (concat "\\[\\|\\]\\|"  ; display math delimitors
	  "begin\\b\\|end\\b\\|part\\b\\|chapter\\b\\|label\\b\\|"
	  "caption\\b\\|section\\b\\|subsection\\b\\|subsubsection\\b\\|"
	  "par\\b\\|noindent\\b\\|paragraph\\b\\|include\\b\\|"
	  "includeonly\\b\\|tableofcontents\\b\\|appendix\\b")
  "Regexp matching names of LaTeX macros that should have their own line.")

;;; Do not ;;;###autoload because of conflict with standard tex-mode.el.
(defun latex-mode ()
  "Major mode for editing files of input for LaTeX.
See info under AUC TeX for full documentation.

Special commands:
\\{LaTeX-mode-map}

Entering LaTeX mode calls the value of text-mode-hook,
then the value of TeX-mode-hook, and then the value
of LaTeX-mode-hook."
  (interactive)
  (LaTeX-common-initialization)
  (setq mode-name "LaTeX")
  (setq major-mode 'latex-mode)  
  (setq TeX-command-default "LaTeX")
  (run-hooks 'text-mode-hook 'TeX-mode-hook 'LaTeX-mode-hook)

  ;; Defeat filladapt if auto-fill-mode is set in text-mode-hook.
  (and (boundp 'filladapt-function-table)
       (boundp 'auto-fill-function)
       (eq auto-fill-function 'do-auto-fill)
       (setq auto-fill-function
	     (cdr (assoc 'do-auto-fill filladapt-function-table)))))

(defvar LaTeX-header-end
  (concat (regexp-quote TeX-esc) "begin *" TeX-grop "document" TeX-grcl)
  "Default end of header marker for LaTeX documents.")

(defvar LaTeX-trailer-start
  (concat (regexp-quote TeX-esc) "end *" TeX-grop "document" TeX-grcl)
  "Default start of trailer marker for LaTeX documents.")

(defun LaTeX2e-font-replace (start end)
  "Replace LaTeX2e font specification around point with START and END."
  (save-excursion
    (catch 'done
      (while t
	(if (/= ?\\ (following-char))
	    (skip-chars-backward "a-zA-Z "))
	(skip-chars-backward "\\\\")
	(if (looking-at "\\\\\\(emph\\|text[a-z]+\\){")
	    (throw 'done t)
	  (up-list -1))))
    (forward-sexp 2)
    (save-excursion
      (replace-match start t t))
    (delete-backward-char 1)
    (insert end)))

(defun LaTeX-common-initialization ()
  ;; Common initialization for LaTeX derived modes.
  (VirTeX-common-initialization)
  (set-syntax-table LaTeX-mode-syntax-table)
  (make-local-variable 'indent-line-function)
  (setq indent-line-function 'LaTeX-indent-line)
  (use-local-map LaTeX-mode-map)
  (easy-menu-add TeX-mode-menu LaTeX-mode-map)
  (easy-menu-add LaTeX-mode-menu LaTeX-mode-map)

  (or LaTeX-largest-level 
      (setq LaTeX-largest-level (LaTeX-section-level "section")))
  
  (setq TeX-header-end LaTeX-header-end
	TeX-trailer-start LaTeX-trailer-start)

  (require 'outline)
  (make-local-variable 'outline-level)
  (setq outline-level 'LaTeX-outline-level)
  (make-local-variable 'outline-regexp)
  (setq outline-regexp (LaTeX-outline-regexp t))
  
  (make-local-variable 'TeX-auto-full-regexp-list)
  (setq TeX-auto-full-regexp-list 
	(append LaTeX-auto-regexp-list plain-TeX-auto-regexp-list))

  (setq paragraph-start
	(concat
	 "\\("
	 "^.*[^" TeX-esc "\n]%.*$\\|"
	 "^%.*$\\|"
	 "^[ \t]*$\\|"
	 "^[ \t]*"
	 (regexp-quote TeX-esc)
	 "\\("
	 LaTeX-paragraph-commands
	 "\\|item\\b"
	 "\\)"
	 "\\|"
	 "^[ \t]*\\$\\$" ; display math delimitor
	 "\\)" ))
  (setq paragraph-separate
	(concat
	 "\\("
	 "^.*[^" TeX-esc "\n]%.*$\\|"
	 "^%.*$\\|"
	 "^[ \t]*$\\|"
	 "^[ \t]*"
	 (regexp-quote TeX-esc)
	 "\\("
	 LaTeX-paragraph-commands
	 "\\)"
	 "\\)"))
  (setq selective-display t)

  (make-local-variable 'LaTeX-item-list)
  (setq LaTeX-item-list '(("description" . LaTeX-item-argument)
			  ("thebibliography" . LaTeX-item-bib)))

  (setq TeX-complete-list
	(append '(("\\\\cite\\[[^]\n\r\\%]*\\]{\\([^{}\n\r\\%,]*\\)"
		   1 LaTeX-bibitem-list "}")
		  ("\\\\cite{\\([^{}\n\r\\%,]*\\)" 1 LaTeX-bibitem-list "}")
		  ("\\\\cite{\\([^{}\n\r\\%]*,\\)\\([^{}\n\r\\%,]*\\)"
		   2 LaTeX-bibitem-list)
		  ("\\\\nocite{\\([^{}\n\r\\%,]*\\)" 1 LaTeX-bibitem-list "}")
		  ("\\\\nocite{\\([^{}\n\r\\%]*,\\)\\([^{}\n\r\\%,]*\\)"
		   2 LaTeX-bibitem-list)
		  ("\\\\ref{\\([^{}\n\r\\%,]*\\)" 1 LaTeX-label-list "}")
		  ("\\\\eqref{\\([^{}\n\r\\%,]*\\)" 1 LaTeX-label-list "}")
		  ("\\\\pageref{\\([^{}\n\r\\%,]*\\)" 1 LaTeX-label-list "}")
		  ("\\\\begin{\\([A-Za-z]*\\)" 1 LaTeX-environment-list "}")
		  ("\\\\end{\\([A-Za-z]*\\)" 1 LaTeX-environment-list "}")
		  ("\\\\renewcommand{\\\\\\([A-Za-z]*\\)"
		   1 LaTeX-symbol-list "}")
		  ("\\\\renewenvironment{\\([A-Za-z]*\\)"
		   1 LaTeX-environment-list "}"))
		TeX-complete-list))

  (LaTeX-add-environments
   '("document" LaTeX-env-document)
   '("enumerate" LaTeX-env-item)
   '("itemize" LaTeX-env-item)
   '("list" LaTeX-env-list)
   '("trivlist" LaTeX-env-item)
   '("picture" LaTeX-env-picture)
   '("tabular" LaTeX-env-array)
   '("tabular*" LaTeX-env-array)
   '("array" LaTeX-env-array)
   '("eqnarray" LaTeX-env-label)
   '("equation" LaTeX-env-label)
   '("minipage" LaTeX-env-minipage)

   ;; The following have no special support, but are included in
   ;; case the auto files are missing. 

   "sloppypar" "picture" "tabbing" "verbatim" "verbatim*"
   "flushright" "flushleft" "displaymath" "math" "quote" "quotation"
   "abstract" "center" "titlepage" "verse" "eqnarray*"

   ;; The following are not defined in latex.el, but in a number of
   ;; other style files.  I'm to lazy to copy them to all the
   ;; corresponding .el files right now.

   ;; This means that AUC TeX will complete e.g.
   ;; ``thebibliography'' in a letter, but I guess we can live with
   ;; that.  

   '("description" LaTeX-env-item)
   '("figure" LaTeX-env-figure)
   '("figure*" LaTeX-env-figure)
   '("table" LaTeX-env-figure)
   '("table*" LaTeX-env-figure)
   '("thebibliography" LaTeX-env-bib)
   '("theindex" LaTeX-env-item))

  (TeX-add-symbols
   '("addtocounter" TeX-arg-counter "Value")
   '("alph" TeX-arg-counter)
   '("arabic" TeX-arg-counter)
   '("fnsymbol" TeX-arg-define-counter)
   '("newcounter" TeX-arg-define-counter
     [ TeX-arg-counter "Within counter" ])
   '("roman" TeX-arg-counter)
   '("setcounter" TeX-arg-counter "Value")
   '("usecounter" TeX-arg-counter)
   '("value" TeX-arg-counter)
   '("stepcounter" TeX-arg-counter)
   '("refstepcounter" TeX-arg-counter)
   '("label" TeX-arg-define-label)
   '("pageref" TeX-arg-label)
   '("ref" TeX-arg-label)
   '("newcommand" TeX-arg-define-macro [ "Number of arguments" ] t)
   '("renewcommand" TeX-arg-macro [ "Number of arguments" ] t)
   '("newenvironment" TeX-arg-define-environment
     [ "Number of arguments"] t t)
   '("renewenvironment" TeX-arg-environment
     [ "Number of arguments"] t t)
   '("newtheorem" TeX-arg-define-environment
     [ TeX-arg-environment "Numbered like" ]
     t [ (TeX-arg-eval progn (if (eq (save-excursion
				       (backward-char 2)
				       (preceding-char)) ?\])
				 ()
			       (TeX-arg-counter t "Within counter"))
		       "") ])
   '("newfont" TeX-arg-define-macro t)
   '("circle" "Diameter")
   '("circle*" "Diameter")
   '("dashbox" "Dash Length" TeX-arg-size
     [ TeX-arg-corner ] t)
   '("frame" t)
   '("framebox" (TeX-arg-conditional 
		 (string-equal (LaTeX-current-environment) "picture")
		 (TeX-arg-size [ TeX-arg-corner ] t)
		 ([ "Length" ] [ TeX-arg-lr ] t)))
   '("line" (TeX-arg-pair "X slope" "Y slope") "Length")
   '("linethickness" "Dimension")
   '("makebox" (TeX-arg-conditional 
		(string-equal (LaTeX-current-environment) "picture")
		(TeX-arg-size [ TeX-arg-corner ] t)
		([ "Length" ] [ TeX-arg-lr ] t)))
   '("multiput"
     TeX-arg-coordinate
     (TeX-arg-pair "X delta" "Y delta")
     "Number of copies"
     t)
   '("oval" TeX-arg-size [ TeX-arg-corner "Portion" ])
   '("put" TeX-arg-coordinate t)
   '("savebox" TeX-arg-define-savebox
     (TeX-arg-conditional
      (string-equal (LaTeX-current-environment) "picture")
      (TeX-arg-size [ TeX-arg-corner ] t)
      ([ "Length" ] [ TeX-arg-lr ] t)))
   '("shortstack" [ TeX-arg-lr ] t)
   '("vector" (TeX-arg-pair "X slope" "Y slope") "Length")
   '("cline" "Span `i-j'")
   '("multicolumn" "Columns" "Position" t)
   '("item"
     (TeX-arg-conditional (or TeX-arg-item-label-p
			      (string-equal (LaTeX-current-environment)
					    "description"))
			  ([ "Item label" ])
			  ())
     (TeX-arg-literal " "))
   '("bibitem" [ "Bibitem label" ] TeX-arg-define-cite)
   '("cite"
     (TeX-arg-conditional TeX-arg-cite-note-p ([ "Note" ]) ())
     TeX-arg-cite)
   '("nocite" TeX-arg-cite)
   '("bibliographystyle" TeX-arg-bibstyle)
   '("bibliography" TeX-arg-bibliography)
   '("footnote"
     (TeX-arg-conditional TeX-arg-footnote-number-p ([ "Number" ]) nil)
     t)
   '("footnotetext" 
     (TeX-arg-conditional TeX-arg-footnote-number-p ([ "Number" ]) nil)
     t)
   '("footnotemark" 
     (TeX-arg-conditional TeX-arg-footnote-number-p ([ "Number" ]) nil))
   '("newlength" TeX-arg-define-macro)
   '("setlength" TeX-arg-macro "Length")
   '("addtolength" TeX-arg-macro "Length")
   '("settowidth" TeX-arg-macro t)
   '("\\" [ "Space" ])
   '("\\*" [ "Space" ])
   '("hyphenation" t)
   '("linebreak" [ "How much [0 - 4]" ])
   '("nolinebreak" [ "How much [0 - 4]" ])
   '("nopagebreak" [ "How much [0 - 4]" ])
   '("pagebreak" [ "How much [0 - 4]" ])
   '("stackrel" t nil)
   '("frac" t nil)
   '("lefteqn" t)
   '("overbrace" t)
   '("overline" t)
   '("sqrt" [ "Root" ] t)
   '("underbrace" t)
   '("underline" t)
   '("author" t)
   '("date" t)
   '("thanks" t)
   '("title" t)
   '("pagenumbering" (TeX-arg-eval
		      completing-read "Numbering style: "
		      '(("arabic") ("roman") ("Roman") ("alph") ("Alph"))))
   '("pagestyle" TeX-arg-pagestyle)
   '("markboth" t nil)
   '("markright" t)
   '("thispagestyle" TeX-arg-pagestyle)
   '("addvspace" "Length")
   '("fbox" t)
   '("hspace*" "Length")
   '("hspace" "Length")
   '("mbox" t)
   '("newsavebox" TeX-arg-define-savebox)
   '("parbox" [ TeX-arg-tb] "Width" t)
   '("raisebox" "Raise" [ "Height above" ] [ "Depth below" ] t)
   '("rule" [ "Raise" ] "Width" "Thickness")
   '("sbox" TeX-arg-define-savebox t)
   '("usebox" TeX-arg-savebox)
   '("vspace*" "Length")
   '("vspace" "Length")
   '("documentstyle" TeX-arg-document)
   '("include" (TeX-arg-input-file "File" t))
   '("includeonly" t)
   '("input" TeX-arg-input-file)
   '("addcontentsline" TeX-arg-file
     (TeX-arg-eval
      completing-read "Numbering style: " LaTeX-section-list)
     t)
   '("addtocontents" TeX-arg-file t)
   '("typeout" t)
   '("typein" [ TeX-arg-define-macro ] t)
   '("verb" TeX-arg-verb)
   '("verb*" TeX-arg-verb)
   '("extracolsep" t)
   '("index" t)
   '("glossary" t)
   '("numberline" "Section number" "Heading")
   '("caption" t)
   '("marginpar" [ "Left margin text" ] "Text")
   '("left" TeX-arg-insert-braces)

   ;; These have no special support, but are included in case the
   ;; auto files are missing. 

   "LaTeX" "SLiTeX" "samepage" "newline" "smallskip" "medskip"
   "bigskip" "stretch" "nonumber" "centering" "raggedright"
   "raggedleft" "kill" "pushtabs" "poptabs" "protect" "arraystretch"
   "hline" "vline" "cline" "thinlines" "thicklines" "and" "makeindex"
   "makeglossary" "reversemarginpar" "normalmarginpar"
   "raggedbottom" "flushbottom" "sloppy" "fussy" "newpage"
   "clearpage" "cleardoublepage" "twocolumn" "onecolumn")

  (TeX-run-style-hooks "LATEX")

  (make-local-variable 'TeX-font-list)
  (make-local-variable 'TeX-font-replace-function)
  (if (string-equal LaTeX-version "2")
      ()
    (setq TeX-font-list LaTeX-font-list)
    (setq TeX-font-replace-function 'LaTeX2e-font-replace)
    (TeX-add-symbols
     '("newcommand" TeX-arg-define-macro
       [ "Number of arguments" ] [ "Default value for first argument" ] t)
     '("renewcommand" TeX-arg-macro
       [ "Number of arguments" ] [ "Default value for first argument" ] t)
     '("usepackage" [ "Options" ] (TeX-arg-input-file "Package"))
     '("documentclass" TeX-arg-document)))

  (TeX-add-style-hook "latex2e"
   ;; Use new fonts for `\documentclass' documents.
   (function (lambda ()
     (setq TeX-font-list LaTeX-font-list)
     (setq TeX-font-replace-function 'LaTeX2e-font-replace)
     (if (equal LaTeX-version "2")
	 (setq TeX-command-default "LaTeX2e"))
     (run-hooks 'LaTeX2e-hook))))
  
  (TeX-add-style-hook "latex2"
   ;; Use old fonts for `\documentstyle' documents.
   (function (lambda ()
     (setq TeX-font-list (default-value 'TeX-font-list))
     (setq TeX-font-replace-function
	   (default-value 'TeX-font-replace-function))
     (run-hooks 'LaTeX2-hook)))))

(defvar LaTeX-builtin-opts 
  '("12pt" "11pt" "10pt" "twocolumn" "twoside" "draft")
  "Built in options for LaTeX standard styles")

(defun LaTeX-209-to-2e ()
  "Make a stab at changing 2.09 doc header to 2e style."
  (interactive)
  (TeX-home-buffer)
  (let (optstr optlist 2eoptlist 2epackages docline docstyle)
    (goto-char (point-min))
    (if 
	(search-forward-regexp
	 "\\documentstyle\\[\\([^]]*\\)\\]{\\([^}]*\\)}"
	 (point-max) t)
	(setq optstr (buffer-substring (match-beginning 1) (match-end 1))
	      docstyle (buffer-substring (match-beginning 2)
	      (match-end 2))
	      optlist (TeX-split-string "," optstr))
      (if (search-forward-regexp
	   "\\documentstyle{\\([^}]*\\)}"
	   (point-max) t)
	  (setq docstyle (buffer-substring (match-beginning 1)
	  (match-end 1)))
	(error "No documentstyle defined")))
    (beginning-of-line 1)
    (setq docline (point))
    (insert "%%%")
    (while optlist
      (if (member (car optlist) LaTeX-builtin-opts)
	  (setq 2eoptlist (cons (car optlist) 2eoptlist))
	(setq 2epackages (cons (car optlist) 2epackages)))
      (setq optlist (cdr optlist)))
    ;;(message (format "%S %S" 2eoptlist 2epackages))
    (goto-char docline)
    (next-line 1)
    (insert "\\documentclass")
    (if 2eoptlist
	(insert "[" 
		(mapconcat (function (lambda (x) x)) 
			   (nreverse 2eoptlist) ",") "]"))
    (insert "{" docstyle "}\n")
    (if 2epackages
	(insert "\\usepackage{" 
		(mapconcat (function (lambda (x) x)) 
			   (nreverse 2epackages) "}\n\\usepackage{") "}\n"))
    (if (equal docstyle "slides")
      (progn
	(goto-char (point-min))
	(while (re-search-forward "\\\\blackandwhite{" nil t)
      (replace-match "\\\\input{" nil nil)))))
  (TeX-normal-mode nil))

;;; latex.el ends here
