*** empty log message ***
[bpt/emacs.git] / lisp / textmodes / tex-mode.el
index 3da099f..ffb0606 100644 (file)
@@ -1,7 +1,7 @@
 ;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- coding: utf-8 -*-
 
 ;; Copyright (C) 1985, 1986, 1989, 1992, 1994, 1995, 1996, 1997, 1998
-;;   1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;;   1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
 ;;   Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
@@ -247,15 +247,20 @@ Normally set to either `plain-tex-mode' or `latex-mode'."
 (defcustom tex-fontify-script t
   "If non-nil, fontify subscript and superscript strings."
   :type 'boolean
-  :group 'tex)
+  :group 'tex
+  :version "23.1")
 (put 'tex-fontify-script 'safe-local-variable 'booleanp)
 
 (defcustom tex-font-script-display '(-0.2 0.2)
-  "Display specification for subscript and superscript content.
-The first is used for subscript, the second is used for superscripts."
+  "How much to lower and raise subscript and superscript content.
+This is a list of two floats.  The first is negative and
+specifies how much subscript is lowered, the second is positive
+and specifies how much superscript is raised.  Heights are
+measured relative to that of the normal text."
   :group 'tex
   :type '(list (float :tag "Subscript")
-               (float :tag "Superscript")))
+               (float :tag "Superscript"))
+  :version "23.1")
 
 (defvar tex-last-temp-file nil
   "Latest temporary file generated by \\[tex-region] and \\[tex-buffer].
@@ -673,12 +678,42 @@ An alternative value is \" . \", if you use a font with a narrow period."
          (put-text-property beg next 'display nil))
       (setq beg next))))
 
+(defcustom tex-suscript-height-ratio 0.8
+  "Ratio of subscript/superscript height to that of the preceding text.
+In nested subscript/superscript, this factor is applied repeatedly,
+subject to the limit set by `tex-suscript-height-minimum'."
+  :type 'float
+  :group 'tex
+  :version "23.1")
+
+(defcustom tex-suscript-height-minimum 0.0
+  "Integer or float limiting the minimum size of subscript/superscript text.
+An integer is an absolute height in units of 1/10 point, a float
+is a height relative to that of the default font.  Zero means no minimum."
+  :type '(choice (integer :tag "Integer height in 1/10 point units")
+                (float :tag "Fraction of default font height"))
+  :group 'tex
+  :version "23.1")
+
+(defun tex-suscript-height (height)
+  "Return the integer height of subscript/superscript font in 1/10 points.
+Not smaller than the value set by `tex-suscript-height-minimum'."
+  (ceiling (max (if (integerp tex-suscript-height-minimum)
+                   tex-suscript-height-minimum
+                 ;; For bootstrapping.
+                 (condition-case nil
+                     (* tex-suscript-height-minimum
+                        (face-attribute 'default :height))
+                   (error 0)))
+               ;; NB assumes height is integer.
+               (* height tex-suscript-height-ratio))))
+
 (defface superscript
-  '((t :height 0.8)) ;; :raise 0.2
+  '((t :height tex-suscript-height)) ;; :raise 0.2
   "Face used for superscripts."
   :group 'tex)
 (defface subscript
-  '((t :height 0.8)) ;; :raise -0.2
+  '((t :height tex-suscript-height)) ;; :raise -0.2
   "Face used for subscripts."
   :group 'tex)
 
@@ -1403,7 +1438,7 @@ Return the value returned by the last execution of BODY."
 
 (defun tex-next-unmatched-eparen (otype)
   "Leave point after the next unmatched escaped closing parenthesis.
-The string OPAREN is an opening parenthesis type: `(', `{', or `['."
+The string OTYPE is an opening parenthesis type: `(', `{', or `['."
   (condition-case nil
       (let ((ctype (char-to-string (cdr (aref (syntax-table)
                                              (string-to-char otype))))))
@@ -1416,6 +1451,19 @@ The string OPAREN is an opening parenthesis type: `(', `{', or `['."
     (wrong-type-argument (error "Unknown opening parenthesis type: %s" otype))
     (search-failed (error "Couldn't find closing escaped paren"))))
 
+(defun tex-last-unended-eparen (ctype)
+  "Leave point at the start of the last unended escaped opening parenthesis.
+The string CTYPE is a closing parenthesis type:  `)', `}', or `]'."
+  (condition-case nil
+      (let ((otype (char-to-string (cdr (aref (syntax-table)
+                                             (string-to-char ctype))))))
+       (while (and (tex-search-noncomment
+                    (re-search-backward (format "\\\\[%s%s]" ctype otype)))
+                   (looking-at (format "\\\\%s" (regexp-quote ctype))))
+         (tex-last-unended-eparen ctype)))
+    (wrong-type-argument (error "Unknown opening parenthesis type: %s" ctype))
+    (search-failed (error "Couldn't find unended escaped paren"))))
+
 (defun tex-goto-last-unclosed-latex-block ()
   "Move point to the last unclosed \\begin{...}.
 Mark is left at original location."
@@ -1427,26 +1475,32 @@ Mark is left at original location."
     (push-mark)
     (goto-char spot)))
 
+;; Don't think this one actually _needs_ (for the purposes of
+;; tex-mode) to handle escaped parens.
 (defun latex-backward-sexp-1 ()
-  "Like (backward-sexp 1) but aware of multi-char elements."
+  "Like (backward-sexp 1) but aware of multi-char elements and escaped parens."
   (let ((pos (point))
        (forward-sexp-function))
     (backward-sexp 1)
-    (if (looking-at "\\\\begin\\>")
-       (signal 'scan-error
-               (list "Containing expression ends prematurely"
-                     (point) (prog1 (point) (goto-char pos))))
-      (when (eq (char-after) ?{)
-       (let ((newpos (point)))
-         (when (ignore-errors (backward-sexp 1) t)
-           (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))))))))
+    (cond ((looking-at "\\\\\\(begin\\>\\|[[({]\\)")
+          (signal 'scan-error
+                  (list "Containing expression ends prematurely"
+                        (point) (prog1 (point) (goto-char pos)))))
+         ((looking-at "\\\\\\([])}]\\)")
+          (tex-last-unended-eparen (match-string 1)))
+         ((eq (char-after) ?{)
+          (let ((newpos (point)))
+            (when (ignore-errors (backward-sexp 1) t)
+              (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))))))))
 
 ;; Note this does not handle things like mismatched brackets inside
 ;; begin/end blocks.
+;; Needs to handle escaped parens for tex-validate-*.
+;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2007-09/msg00038.html
 (defun latex-forward-sexp-1 ()
   "Like (forward-sexp 1) but aware of multi-char elements and escaped parens."
   (let ((pos (point))
@@ -1465,6 +1519,8 @@ Mark is left at original location."
        ((looking-at "\\\\begin\\>")
        (goto-char (match-end 0))
        (tex-next-unmatched-end))
+       ;; A better way to handle this, \( .. \) etc, is probably to
+       ;; temporarily change the syntax of the \ in \( to punctuation.
        ((looking-back "\\\\[])}]")
        (signal 'scan-error
                (list "Containing expression ends prematurely"
@@ -1876,7 +1932,8 @@ FILE is typically the output DVI or PDF file."
                  (not (file-symlink-p f)))
             (unless (string-match ignored-dirs-re f)
               (setq files (nconc
-                           (directory-files f t tex-input-files-re)
+                            (ignore-errors ;Not readable or something.
+                              (directory-files f t tex-input-files-re))
                            files)))
           (when (file-newer-than-file-p f file)
             (setq uptodate nil)))))