(org-special-keyword): New face.
[bpt/emacs.git] / lisp / textmodes / tex-mode.el
index 87dc8fc..b4ec3fe 100644 (file)
@@ -1,7 +1,7 @@
 ;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- coding: utf-8 -*-
 
-;; Copyright (C) 1985,86,89,92,94,95,96,97,98,1999,2002,2003
-;;       Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1986, 1989, 1992, 1994, 1995, 1996, 1997, 1998, 1999,
+;;   2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: tex
@@ -23,8 +23,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 (require 'compile)
 
 (defgroup tex-file nil
-  "TeX files and directories"
+  "TeX files and directories."
   :prefix "tex-"
   :group 'tex)
 
 (defgroup tex-run nil
-  "Running external commands from TeX mode"
+  "Running external commands from TeX mode."
   :prefix "tex-"
   :group 'tex)
 
 (defgroup tex-view nil
-  "Viewing and printing TeX files"
+  "Viewing and printing TeX files."
   :prefix "tex-"
   :group 'tex)
 
@@ -127,7 +127,7 @@ and the input file name, with no separating space and are not shell-quoted.
 If nil, TeX runs with no options.  See the documentation of `tex-command'."
   :type 'string
   :group 'tex-run
-  :version "21.4")
+  :version "22.1")
 
 ;;;###autoload
 (defcustom tex-start-commands "\\nonstopmode\\input"
@@ -139,7 +139,7 @@ If nil, no commands are used.  See the documentation of `tex-command'."
                       "\\nonstopmode\\input")
                (string :tag "String at your choice"))
   :group 'tex-run
-  :version "21.4")
+  :version "22.1")
 
 (defvar latex-standard-block-names
   '("abstract"         "array"         "center"        "description"
@@ -196,7 +196,11 @@ use."
   :group 'tex-view)
 
 ;;;###autoload
-(defcustom tex-dvi-view-command '(if (eq window-system 'x) "xdvi" "dvi2tty * | cat -s")
+(defcustom tex-dvi-view-command
+  '(cond
+    ((eq window-system 'x) "xdvi")
+    ((eq window-system 'w32) "yap")
+    (t "dvi2tty * | cat -s"))
   "*Command used by \\[tex-view] to display a `.dvi' file.
 If it is a string, that specifies the command directly.
 If this string contains an asterisk (`*'), that is replaced by the file name;
@@ -453,7 +457,8 @@ An alternative value is \" . \", if you use a font with a narrow period."
                      '("input" "include" "includeonly" "bibliography"
                        "epsfig" "psfig" "epsf" "nofiles" "usepackage"
                        "documentstyle" "documentclass" "verbatiminput"
-                       "includegraphics" "includegraphics*")
+                       "includegraphics" "includegraphics*"
+                       "url" "nolinkurl")
                      t))
           ;; Miscellany.
           (slash "\\\\")
@@ -463,6 +468,10 @@ An alternative value is \" . \", if you use a font with a narrow period."
           ;; (arg "\\(?:{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)\\|\\\\[a-z*]+\\)"))
           (arg "{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)"))
       (list
+       ;; font-lock-syntactic-keywords causes the \ of \end{verbatim} to be
+       ;; highlighted as tex-verbatim-face.  Let's undo that.
+       ;; This is ugly and brittle :-(  --Stef
+       '("^\\(\\\\\\)end" (1 (get-text-property (match-end 1) 'face) t))
        ;; display $$ math $$
        ;; We only mark the match between $$ and $$ because the $$ delimiters
        ;; themselves have already been marked (along with $..$) by syntactic
@@ -495,6 +504,11 @@ An alternative value is \" . \", if you use a font with a narrow period."
         1 font-lock-function-name-face))))
   "Subdued expressions to highlight in TeX modes.")
 
+(defun tex-font-lock-append-prop (prop)
+  (unless (memq (get-text-property (match-end 1) 'face)
+               '(font-lock-comment-face tex-verbatim-face))
+    prop))
+
 (defconst tex-font-lock-keywords-2
   (append tex-font-lock-keywords-1
    (eval-when-compile
@@ -548,16 +562,19 @@ An alternative value is \" . \", if you use a font with a narrow period."
        ;;
        ;; Font environments.  It seems a bit dubious to use `bold' etc. faces
        ;; since we might not be able to display those fonts.
-       (list (concat slash bold " *" arg) 2 '(quote bold) 'append)
-       (list (concat slash italic " *" arg) 2 '(quote italic) 'append)
+       (list (concat slash bold " *" arg) 2
+             '(tex-font-lock-append-prop 'bold) 'append)
+       (list (concat slash italic " *" arg) 2
+             '(tex-font-lock-append-prop 'italic) 'append)
        ;; (list (concat slash type arg) 2 '(quote bold-italic) 'append)
        ;;
        ;; Old-style bf/em/it/sl.  Stop at `\\' and un-escaped `&', for tables.
        (list (concat "\\\\\\(em\\|it\\|sl\\)\\>" args)
-             2 '(quote italic) 'append)
+             2 '(tex-font-lock-append-prop 'italic) 'append)
        ;; This is separate from the previous one because of cases like
        ;; {\em foo {\bf bar} bla} where both match.
-       (list (concat "\\\\bf\\>" args) 1 '(quote bold) 'append)))))
+       (list (concat "\\\\\\(bf\\(series\\)?\\)\\>" args)
+             2 '(tex-font-lock-append-prop 'bold) 'append)))))
    "Gaudy expressions to highlight in TeX modes.")
 
 (defun tex-font-lock-suscript (pos)
@@ -585,7 +602,7 @@ An alternative value is \" . \", if you use a font with a narrow period."
           ;; degenerate to nasty complexity (because we try to match the
           ;; closing brace, which forces trying all matching combinations).
           (arg "{\\(?:[^{}\\]\\|\\\\.\\|{[^}]*}\\)*"))
-       `((,(concat "[_^] *\\([^\n\\{}]\\|" slash general "\\|" arg "}\\)")
+       `((,(concat "[_^] *\\([^\n\\{}#]\\|" slash general "\\|#[0-9]\\|" arg "}\\)")
          (1 (tex-font-lock-suscript (match-beginning 0))
             append))))))
   "Experimental expressions to highlight in TeX modes.")
@@ -599,11 +616,16 @@ An alternative value is \" . \", if you use a font with a narrow period."
 (defvar tex-font-lock-syntactic-keywords
   (let ((verbs (regexp-opt tex-verbatim-environments t)))
     `((,(concat "^\\\\begin *{" verbs "}.*\\(\n\\)") 2 "|")
-      (,(concat "^\\\\end *{" verbs "}\\(.?\\)") 2
-       (unless (<= (match-beginning 0) (point-min))
-        (put-text-property (1- (match-beginning 0)) (match-beginning 0)
-                           'syntax-table (string-to-syntax "|"))
-        "<"))
+      ;; Technically, we'd like to put the "|" property on the \n preceding
+      ;; the \end, but this would have 2 disadvantages:
+      ;; 1 - it's wrong if the verbatim env is empty (the same \n is used to
+      ;;     start and end the fenced-string).
+      ;; 2 - font-lock considers the preceding \n as being part of the
+      ;;     preceding line, so things gets screwed every time the previous
+      ;;     line is re-font-locked on its own.
+      ;; There's a hack in tex-font-lock-keywords-1 to remove the verbatim
+      ;; face from the \ but C-M-f still jumps to the wrong spot :-(  --Stef
+      (,(concat "^\\(\\\\\\)end *{" verbs "}\\(.?\\)") (1 "|") (3 "<"))
       ;; ("^\\(\\\\\\)begin *{comment}" 1 "< b")
       ;; ("^\\\\end *{comment}.*\\(\n\\)" 1 "> b")
       ("\\\\verb\\**\\([^a-z@*]\\)" 1 "\""))))
@@ -621,20 +643,29 @@ An alternative value is \" . \", if you use a font with a narrow period."
 
 (defface superscript
   '((t :height 0.8)) ;; :raise 0.3
-  "Face used for superscripts.")
+  "Face used for superscripts."
+  :group 'tex)
 (defface subscript
   '((t :height 0.8)) ;; :raise -0.3
-  "Face used for subscripts.")
+  "Face used for subscripts."
+  :group 'tex)
 
-(defface tex-math-face
+(defface tex-math
   '((t :inherit font-lock-string-face))
-  "Face used to highlight TeX math expressions.")
-(defvar tex-math-face 'tex-math-face)
-(defface tex-verbatim-face
+  "Face used to highlight TeX math expressions."
+  :group 'tex)
+;; backward-compatibility alias
+(put 'tex-math-face 'face-alias 'tex-math)
+(defvar tex-math-face 'tex-math)
+
+(defface tex-verbatim
   ;; '((t :inherit font-lock-string-face))
   '((t :family "courier"))
-  "Face used to highlight TeX verbatim environments.")
-(defvar tex-verbatim-face 'tex-verbatim-face)
+  "Face used to highlight TeX verbatim environments."
+  :group 'tex)
+;; backward-compatibility alias
+(put 'tex-verbatim-face 'face-alias 'tex-verbatim)
+(defvar tex-verbatim-face 'tex-verbatim)
 
 ;; Use string syntax but math face for $...$.
 (defun tex-font-lock-syntactic-face-function (state)
@@ -769,10 +800,12 @@ Inherits `shell-mode-map' with a few additions.")
                      (regexp-opt '("documentstyle" "documentclass"
                                    "begin" "subsection" "section"
                                    "part" "chapter" "newcommand"
-                                   "renewcommand") 'words)
+                                   "renewcommand" "RequirePackage") 'words)
                      "\\|NeedsTeXFormat{LaTeX")))
-                 (if (looking-at
-                      "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")
+                 (if (and (looking-at
+                           "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")
+                          ;; SliTeX is almost never used any more nowadays.
+                          (tex-executable-exists-p slitex-run-command))
                      'slitex-mode
                    'latex-mode)
                'plain-tex-mode))))
@@ -804,6 +837,14 @@ says which mode to use."
       (tex-mode-internal)
     (tex-guess-mode)))
 
+;; The following three autoloaded aliases appear to conflict with
+;; AUCTeX.  However, even though AUCTeX uses the mixed case variants
+;; for all mode relevant variables and hooks, the invocation function
+;; and setting of `major-mode' themselves need to be lowercase for
+;; AUCTeX to provide a fully functional user-level replacement.  So
+;; these aliases should remain as they are, in particular since AUCTeX
+;; users are likely to use them.
+
 ;;;###autoload
 (defalias 'TeX-mode 'tex-mode)
 ;;;###autoload
@@ -1003,10 +1044,8 @@ Entering SliTeX mode runs the hook `text-mode-hook', then the hook
        'tex-categorize-whitespace)
   (set (make-local-variable 'facemenu-add-face-function)
        (lambda (face end)
-        (let ((face-text (cdr (assq face tex-face-alist))))
-          (if face-text
-              face-text
-            (error "Face %s not configured for %s mode" face mode-name)))))
+        (or (cdr (assq face tex-face-alist))
+            (error "Face %s not configured for %s mode" face mode-name))))
   (set (make-local-variable 'facemenu-end-add-face) "}")
   (set (make-local-variable 'facemenu-remove-face-function) t)
   (set (make-local-variable 'font-lock-defaults)
@@ -1067,7 +1106,7 @@ Inserts the value of `tex-open-quote' (normally ``) or `tex-close-quote'
 inserts \" characters."
   (interactive "*P")
   (if (or arg (memq (char-syntax (preceding-char)) '(?/ ?\\))
-         (eq (get-text-property (point) 'face) 'tex-verbatim-face)
+         (eq (get-text-property (point) 'face) tex-verbatim-face)
          (save-excursion
            (backward-char (length tex-open-quote))
            (when (or (looking-at (regexp-quote tex-open-quote))
@@ -1075,7 +1114,7 @@ inserts \" characters."
              (delete-char (length tex-open-quote))
              t)))
       (self-insert-command (prefix-numeric-value arg))
-    (insert (if (memq (char-syntax (preceding-char)) '(?\( ?> ?\ ))
+    (insert (if (memq (char-syntax (preceding-char)) '(?\( ?> ?\s))
                tex-open-quote tex-close-quote))))
 
 (defun tex-validate-buffer ()
@@ -1141,10 +1180,14 @@ on the line for the invalidity you want to see."
                                         'occur-target tem)))))
            (goto-char prev-end))))
       (with-current-buffer standard-output
-       (if (eq num-matches 0)
-           (insert "None!\n"))
-       (if (interactive-p)
-           (message "%d mismatches found" num-matches))))))
+       (let ((no-matches (zerop num-matches)))
+         (if no-matches
+             (insert "None!\n"))
+         (if (interactive-p)
+             (message (cond (no-matches "No mismatches found")
+                            ((= num-matches 1) "1 mismatch found")
+                            (t "%d mismatches found"))
+                      num-matches)))))))
 
 (defun tex-validate-region (start end)
   "Check for mismatched braces or $'s in region.
@@ -1162,14 +1205,14 @@ area if a mismatch is found."
              (forward-sexp 1))
            ;; Now check that like matches like.
            (goto-char start)
-           (while (progn (skip-syntax-forward "^(")
-                         (not (eobp)))
-             (let ((match (matching-paren (following-char))))
-               (save-excursion
+           (while (re-search-forward "\\s(" nil t)
+             (save-excursion
+               (let ((pos (match-beginning 0)))
+                 (goto-char pos)
                  (forward-sexp 1)
-                 (or (= (preceding-char) match)
-                     (error "Mismatched parentheses"))))
-             (forward-char 1)))
+                 (or (eq (preceding-char) (cdr (syntax-after pos)))
+                     (eq (char-after pos) (cdr (syntax-after (1- (point)))))
+                     (error "Mismatched parentheses"))))))
        (error
         (skip-syntax-forward " .>")
         (setq failure-point (point)))))
@@ -1215,8 +1258,13 @@ A prefix arg inhibits the checking."
 (defvar latex-block-default "enumerate")
 
 (defvar latex-block-args-alist
-  '(("array" nil ?\{ (skeleton-read "[options]: ") ?\})
-    ("tabular" nil ?\{ (skeleton-read "[options]: ") ?\}))
+  '(("array" nil ?\{ (skeleton-read "Format: ") ?\})
+    ("tabular" nil ?\{ (skeleton-read "Format: ") ?\})
+    ("minipage" nil ?\{ (skeleton-read "Size: ") ?\})
+    ("picture" nil ?\( (skeleton-read "SizeX,SizeY: ") ?\))
+    ;; FIXME: This is right for Prosper, but not for seminar.
+    ;; ("slide" nil ?\{ (skeleton-read "Title: ") ?\})
+    )
   "Skeleton element to use for arguments to particular environments.
 Every element of the list has the form (NAME . SKEL-ELEM) where NAME is
 the name of the environment and SKEL-ELEM is an element to use in
@@ -1225,8 +1273,11 @@ a skeleton (see `skeleton-insert').")
 (defvar latex-block-body-alist
   '(("enumerate" nil '(latex-insert-item) > _)
     ("itemize" nil '(latex-insert-item) > _)
-    ("table" nil "\\caption{" > - "}" > \n _)
-    ("figure" nil  > _ \n "\\caption{" > _ "}" >))
+    ("table" nil "\\caption{" > (skeleton-read "Caption: ") "}" > \n
+     '(if (and (boundp 'reftex-mode) reftex-mode) (reftex-label "table"))
+     \n _)
+    ("figure" nil  > _ \n "\\caption{" > (skeleton-read "Caption: ") "}" > \n
+     '(if (and (boundp 'reftex-mode) reftex-mode) (reftex-label "table"))))
   "Skeleton element to use for the body of particular environments.
 Every element of the list has the form (NAME . SKEL-ELEM) where NAME is
 the name of the environment and SKEL-ELEM is an element to use in
@@ -1250,7 +1301,8 @@ Puts point on a blank line between them."
     choice)
   \n "\\begin{" str "}"
   (cdr (assoc str latex-block-args-alist))
-  > \n (or (cdr (assoc str latex-block-body-alist)) '(nil > _)) \n
+  > \n (or (cdr (assoc str latex-block-body-alist)) '(nil > _))
+  (unless (bolp) '\n)
   "\\end{" str "}" > \n)
 
 (define-skeleton latex-insert-item
@@ -1314,7 +1366,9 @@ Mark is left at original location."
       (when (eq (char-after) ?{)
        (let ((newpos (point)))
          (when (ignore-errors (backward-sexp 1) t)
-           (if (looking-at "\\\\end\\>")
+           (if (or (looking-at "\\\\end\\>")
+                   ;; In case the \\ ends a verbatim section.
+                   (and (looking-at "end\\>") (eq (char-before) ?\\)))
                (tex-last-unended-begin)
              (goto-char newpos))))))))
 
@@ -1446,6 +1500,8 @@ Mark is left at original location."
 ;; The utility functions:
 
 (define-derived-mode tex-shell shell-mode "TeX-Shell"
+  (set (make-local-variable 'compilation-parse-errors-function)
+       'tex-compilation-parse-errors)
   (compilation-shell-minor-mode t))
 
 ;;;###autoload
@@ -1454,10 +1510,12 @@ Mark is left at original location."
       (make-comint
        "tex-shell"
        (or tex-shell-file-name (getenv "ESHELL") shell-file-name)
-       nil)
+       nil
+       ;; Specify an interactive shell, to make sure it prompts.
+       "-i")
     (let ((proc (get-process "tex-shell")))
       (set-process-sentinel proc 'tex-shell-sentinel)
-      (process-kill-without-query proc)
+      (set-process-query-on-exit-flag proc nil)
       (tex-shell)
       (while (zerop (buffer-size))
        (sleep-for 1)))))
@@ -1521,8 +1579,9 @@ Return the process in which TeX is running."
            (concat
             (if file
                 (if star (concat (substring cmd 0 star)
-                                 file (substring cmd (1+ star)))
-                  (concat cmd " " file))
+                                 (shell-quote-argument file)
+                                 (substring cmd (1+ star)))
+                  (concat cmd " " (shell-quote-argument file)))
               cmd)
             (if background "&" ""))))
       ;; Switch to buffer before checking for subproc output in it.
@@ -1573,7 +1632,8 @@ If NOT-ALL is non-nil, save the `.dvi' file."
 
 (defcustom tex-use-reftex t
   "If non-nil, use RefTeX's list of files to determine what command to use."
-  :type 'boolean)
+  :type 'boolean
+  :group 'tex)
 
 (defvar tex-compile-commands
   '(((concat "pdf" tex-command
@@ -1584,19 +1644,19 @@ If NOT-ALL is non-nil, save the `.dvi' file."
             " " (if (< 0 (length tex-start-commands))
                     (shell-quote-argument tex-start-commands)) " %f")
      t "%r.dvi")
-    ("yap %r &" "%r.dvi")
     ("xdvi %r &" "%r.dvi")
+    ("xpdf %r.pdf &" "%r.pdf")
+    ("gv %r.ps &" "%r.ps")
+    ("yap %r &" "%r.dvi")
     ("advi %r &" "%r.dvi")
+    ("gv %r.pdf &" "%r.pdf")
     ("bibtex %r" "%r.aux" "%r.bbl")
     ("makeindex %r" "%r.idx" "%r.ind")
     ("texindex %r.??")
     ("dvipdfm %r" "%r.dvi" "%r.pdf")
     ("dvipdf %r" "%r.dvi" "%r.pdf")
-    ("dvips %r" "%r.dvi" "%r.ps")
+    ("dvips -o %r.ps %r" "%r.dvi" "%r.ps")
     ("ps2pdf %r.ps" "%r.ps" "%r.pdf")
-    ("gv %r.ps &" "%r.ps")
-    ("gv %r.pdf &" "%r.pdf")
-    ("xpdf %r.pdf &" "%r.pdf")
     ("lpr %r.ps" "%r.ps"))
   "List of commands for `tex-compile'.
 Each element should be of the form (FORMAT IN OUT) where
@@ -1654,9 +1714,12 @@ of the current buffer."
   (let* ((file (or tex-main-file
                   ;; Compatibility with AUCTeX.
                   (with-no-warnings
-                   (when (and (boundp 'TeX-master) (stringp TeX-master))
-                     (make-local-variable 'tex-main-file)
-                     (setq tex-main-file TeX-master)))
+                   (when (boundp 'TeX-master)
+                     (cond ((stringp TeX-master)
+                            (make-local-variable 'tex-main-file)
+                            (setq tex-main-file TeX-master))
+                           ((and (eq TeX-master t) buffer-file-name)
+                            (file-relative-name buffer-file-name)))))
                   ;; Try to guess the main file.
                   (if (not buffer-file-name)
                       (error "Buffer is not associated with any file")
@@ -1730,7 +1793,7 @@ FILE is typically the output DVI or PDF file."
           (when (file-newer-than-file-p f file)
             (setq uptodate nil)))))
      uptodate)))
-    
+
 
 (autoload 'format-spec "format-spec")
 
@@ -1761,7 +1824,7 @@ FILE is typically the output DVI or PDF file."
        (not (tex-uptodate-p (format-spec out fspec)))))))
 
 (defun tex-compile-default (fspec)
-  "Guess a default command given the format-spec FSPEC."
+  "Guess a default command given the `format-spec' FSPEC."
   ;; TODO: Learn to do latex+dvips!
   (let ((cmds nil)
        (unchanged-in nil))
@@ -1771,6 +1834,8 @@ FILE is typically the output DVI or PDF file."
        (if (tex-command-active-p cmd fspec)
            (push cmd cmds)
          (push (nth 1 cmd) unchanged-in))))
+    ;; If no command seems to be applicable, arbitrarily pick the first one.
+    (setq cmds (if cmds (nreverse cmds) (list (car tex-compile-commands))))
     ;; Remove those commands whose input was considered stable for
     ;; some other command (typically if (t . "%.pdf") is inactive
     ;; then we're using pdflatex and the fact that the dvi file
@@ -1780,7 +1845,7 @@ FILE is typically the output DVI or PDF file."
        (unless (member (nth 1 cmd) unchanged-in)
          (push cmd tmp)))
       ;; Only remove if there's something left.
-      (if tmp (setq cmds tmp)))
+      (if tmp (setq cmds (nreverse tmp))))
     ;; Remove commands whose input is not uptodate either.
     (let ((outs (delq nil (mapcar (lambda (x) (nth 2 x)) cmds)))
          (tmp nil))
@@ -1788,7 +1853,7 @@ FILE is typically the output DVI or PDF file."
        (unless (member (nth 1 cmd) outs)
          (push cmd tmp)))
       ;; Only remove if there's something left.
-      (if tmp (setq cmds tmp)))
+      (if tmp (setq cmds (nreverse tmp))))
     ;; Select which file we're going to operate on (the latest).
     (let ((latest (nth 1 (car cmds))))
       (dolist (cmd (prog1 (cdr cmds) (setq cmds (list (car cmds)))))
@@ -1839,8 +1904,8 @@ FILE is typically the output DVI or PDF file."
            (prog1 (file-name-directory (expand-file-name file))
              (setq file (file-name-nondirectory file))))
          (root (file-name-sans-extension file))
-         (fspec (list (cons ?r (comint-quote-filename root))
-                      (cons ?f (comint-quote-filename file))))
+         (fspec (list (cons ?r (shell-quote-argument root))
+                      (cons ?f (shell-quote-argument file))))
          (default (tex-compile-default fspec)))
      (list default-directory
           (completing-read
@@ -1861,14 +1926,14 @@ FILE is typically the output DVI or PDF file."
          (compile-command
           (if star
              (concat (substring command 0 star)
-                     (comint-quote-filename file)
+                     (shell-quote-argument file)
                      (substring command (1+ star)))
             (concat command " "
                    tex-start-options
                    (if (< 0 (length tex-start-commands))
                        (concat
                         (shell-quote-argument tex-start-commands) " "))
-                   (comint-quote-filename file)))))
+                   (shell-quote-argument file)))))
     (tex-send-tex-command compile-command dir)))
 
 (defun tex-send-tex-command (cmd &optional dir)
@@ -1877,10 +1942,9 @@ FILE is typically the output DVI or PDF file."
                                       default-directory))))
              (not dir))
     (let (shell-dirtrack-verbose)
-      (tex-send-command tex-shell-cd-command dir)))
+      (tex-send-command tex-shell-cd-command
+                       (concat "\"" (convert-standard-filename dir) "\""))))
   (with-current-buffer (process-buffer (tex-send-command cmd))
-    (make-local-variable 'compilation-parse-errors-function)
-    (setq compilation-parse-errors-function 'tex-compilation-parse-errors)
     (setq compilation-last-buffer (current-buffer))
     (compilation-forget-errors)
     ;; Don't parse previous compilations.
@@ -1912,7 +1976,6 @@ since TeX does not put file names and line numbers on the same line as
 for the error messages."
   (require 'thingatpt)
   (setq compilation-error-list nil)
-  (message "Parsing error messages...")
   (let ((default-directory             ; Perhaps dir has changed meanwhile.
          (file-name-directory (buffer-file-name tex-last-buffer-texed)))
        found-desired (num-errors-found 0)
@@ -1927,8 +1990,8 @@ for the error messages."
                        end-of-error (match-end 0)))
                (re-search-forward
                 "^l\\.\\([0-9]+\\) \\(\\.\\.\\.\\)?\\(.*\\)$" nil 'move))
-      (let* ((this-error (set-marker (make-marker) begin-of-error))
-            (linenum (string-to-int (match-string 1)))
+      (let* ((this-error (copy-marker begin-of-error))
+            (linenum (string-to-number (match-string 1)))
             (error-text (regexp-quote (match-string 3)))
             (filename
              (save-excursion
@@ -1944,21 +2007,22 @@ for the error messages."
              (or (null last-filename)
                  (not (string-equal last-filename filename))))
             (error-location
-             (save-excursion
-               (if (equal filename (concat tex-zap-file ".tex"))
-                   (set-buffer tex-last-buffer-texed)
-                 (set-buffer (find-file-noselect filename)))
-               (if new-file
-                   (progn (goto-line linenum) (setq last-position nil))
-                 (goto-char last-position)
-                 (forward-line (- linenum last-linenum)))
-               ;; first try a forward search for the error text,
-               ;; then a backward search limited by the last error.
-               (let ((starting-point (point)))
-                 (or (re-search-forward error-text nil t)
-                     (re-search-backward error-text last-position t)
-                     (goto-char starting-point)))
-               (point-marker))))
+             (with-current-buffer
+                 (if (equal filename (concat tex-zap-file ".tex"))
+                     tex-last-buffer-texed
+                   (find-file-noselect filename))
+               (save-excursion
+                 (if new-file
+                     (progn (goto-line linenum) (setq last-position nil))
+                   (goto-char last-position)
+                   (forward-line (- linenum last-linenum)))
+                 ;; first try a forward search for the error text,
+                 ;; then a backward search limited by the last error.
+                 (let ((starting-point (point)))
+                   (or (re-search-forward error-text nil t)
+                       (re-search-backward error-text last-position t)
+                       (goto-char starting-point)))
+                 (point-marker)))))
        (goto-char this-error)
        (if (and compilation-error-list
                 (or (and find-at-least
@@ -1977,8 +2041,7 @@ for the error messages."
                      compilation-error-list))
          (goto-char end-of-error)))))
   (set-marker compilation-parsing-end (point))
-  (setq compilation-error-list (nreverse compilation-error-list))
-  (message "Parsing error messages...done"))
+  (setq compilation-error-list (nreverse compilation-error-list)))
 \f
 ;;; The commands:
 
@@ -2174,8 +2237,7 @@ is provided, use the alternative command, `tex-alt-dvi-print-command'."
         (tex-start-shell))
       (tex-send-command
        (if alt tex-alt-dvi-print-command tex-dvi-print-command)
-       (shell-quote-argument
-       print-file-name-dvi)
+       print-file-name-dvi
        t))))
 
 (defun tex-alt-print ()
@@ -2193,6 +2255,9 @@ because there is no standard value that would generally work."
   (interactive)
   (or tex-dvi-view-command
       (error "You must set `tex-dvi-view-command'"))
+  ;; Restart the TeX shell if necessary.
+  (or (tex-shell-running)
+      (tex-start-shell))
   (let ((tex-dvi-print-command (eval tex-dvi-view-command)))
     (tex-print)))
 
@@ -2243,7 +2308,8 @@ Runs the shell command defined by `tex-show-queue-command'."
        (tex-out-file
          (tex-append (file-name-nondirectory (buffer-file-name)) ""))
        (file-dir (file-name-directory (buffer-file-name))))
-    (tex-send-command tex-shell-cd-command file-dir)
+    (tex-send-command tex-shell-cd-command
+                     (concat "\"" (convert-standard-filename file-dir) "\""))
     (tex-send-command tex-bibtex-command tex-out-file))
   (tex-display-shell))
 \f
@@ -2256,6 +2322,7 @@ Runs the shell command defined by `tex-show-queue-command'."
 (defvar tex-indent-basic 2)
 (defvar tex-indent-item tex-indent-basic)
 (defvar tex-indent-item-re "\\\\\\(bib\\)?item\\>")
+(defvar latex-noindent-environments '("document"))
 
 (defvar tex-latex-indent-syntax-table
   (let ((st (make-syntax-table tex-mode-syntax-table)))
@@ -2306,7 +2373,6 @@ There might be text before point."
              (latex-find-indent 'virtual))))
      ;; Default (maybe an argument)
      (let ((pos (point))
-          (char (char-after))
           ;; Outdent \item if necessary.
           (indent (if (looking-at tex-indent-item-re) (- tex-indent-item) 0))
           up-list-pos)
@@ -2324,6 +2390,17 @@ There might be text before point."
         ;; Have to indent relative to the open-paren.
         (goto-char up-list-pos)
         (if (and (not tex-indent-allhanging)
+                 (save-excursion
+                   ;; Make sure we're an argument to a macro and
+                   ;; that the macro is at the beginning of a line.
+                   (condition-case nil
+                       (progn
+                         (while (eq (char-syntax (char-after)) ?\()
+                           (forward-sexp -1))
+                         (and (eq (char-syntax (char-after)) ?/)
+                              (progn (skip-chars-backward " \t&")
+                                     (bolp))))
+                     (scan-error nil)))
                  (> pos (progn (latex-down-list)
                                (forward-comment (point-max))
                                (point))))
@@ -2331,26 +2408,32 @@ There might be text before point."
             (current-column)
           ;; We're the first element after a hanging brace.
           (goto-char up-list-pos)
-          (+ indent tex-indent-basic (latex-find-indent 'virtual))))
+          (+ (if (and (looking-at "\\\\begin *{\\([^\n}]+\\)")
+                      (member (match-string 1)
+                              latex-noindent-environments))
+                 0 tex-indent-basic)
+             indent (latex-find-indent 'virtual))))
        ;; We're now at the "beginning" of a line.
        ((not (and (not virtual) (eq (char-after) ?\\)))
         ;; Nothing particular here: just keep the same indentation.
         (+ indent (current-column)))
        ;; We're now looking at a macro call.
-         ((looking-at tex-indent-item-re)
-          ;; Indenting relative to an item, have to re-add the outdenting.
+       ((looking-at tex-indent-item-re)
+        ;; Indenting relative to an item, have to re-add the outdenting.
         (+ indent (current-column) tex-indent-item))
        (t
         (let ((col (current-column)))
-          (if (not (eq (char-syntax char) ?\())
+          (if (or (not (eq (char-syntax (or (char-after pos) ?\s)) ?\())
+                  ;; Can't be an arg if there's an empty line inbetween.
+                  (save-excursion (re-search-forward "^[ \t]*$" pos t)))
               ;; If the first char was not an open-paren, there's
               ;; a risk that this is really not an argument to the
               ;; macro at all.
-                (+ indent col)
-              (forward-sexp 1)
-              (if (< (line-end-position)
-                     (save-excursion (forward-comment (point-max))
-                                     (point)))
+              (+ indent col)
+            (forward-sexp 1)
+            (if (< (line-end-position)
+                   (save-excursion (forward-comment (point-max))
+                                   (point)))
                 ;; we're indenting the first argument.
                 (min (current-column) (+ tex-indent-arg col))
               (skip-syntax-forward " ")
@@ -2417,5 +2500,5 @@ There might be text before point."
 
 (provide 'tex-mode)
 
-;;; arch-tag: c0a680b1-63aa-4547-84b9-4193c29c0080
+;; arch-tag: c0a680b1-63aa-4547-84b9-4193c29c0080
 ;;; tex-mode.el ends here