1;;; font-latex.el --- LaTeX fontification for Font Lock mode.
2
3;; Copyright (C) 1996-2019  Free Software Foundation, Inc.
4
5;; Authors:    Peter S. Galbraith <psg@debian.org>
6;;             Simon Marshall <Simon.Marshall@esrin.esa.it>
7;; Maintainer: auctex-devel@gnu.org
8;; Created:    06 July 1996
9;; Keywords:   tex, wp, faces
10
11;;; This file is not part of GNU Emacs.
12
13;; This package is free software; you can redistribute it and/or modify
14;; it under the terms of the GNU General Public License as published by
15;; the Free Software Foundation; either version 3, or (at your option)
16;; any later version.
17
18;; This package is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
24;; along with GNU Emacs; see the file COPYING.  If not, write to the
25;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
26;; Boston, MA 02110-1301, USA.
27
28;;; Commentary:
29;;
30;; This package enhances font-lock fontification patterns for LaTeX.
31;; font-lock mode is a minor mode that causes your comments to be
32;; displayed in one face, strings in another, reserved words in
33;; another, and so on.
34;;
35;; ** Infinite loops !? **
36;; If you get an infinite loop, send a bug report!
37;; Then set the following in your ~/.emacs file to keep on working:
38;;   (setq font-latex-do-multi-line nil)
39
40;;; Code:
41
42(require 'font-lock)
43(require 'tex)
44
45(eval-when-compile
46  (require 'cl-lib))
47
48(defgroup font-latex nil
49  "Font-latex text highlighting package."
50  :prefix "font-latex-"
51  :group 'faces
52  :group 'tex
53  :group 'AUCTeX)
54
55(defgroup font-latex-keywords nil
56  "Keywords for highlighting text in font-latex."
57  :prefix "font-latex-"
58  :group 'font-latex)
59
60(defgroup font-latex-highlighting-faces nil
61  "Faces for highlighting text in font-latex."
62  :prefix "font-latex-"
63  :group 'font-latex)
64
65(defvar font-latex-multiline-boundary 5000
66  "Size of region to search for the start or end of a multiline construct.")
67
68(defvar font-latex-quote-regexp-beg nil
69  "Regexp used to find quotes.")
70(make-variable-buffer-local 'font-latex-quote-regexp-beg)
71
72(defvar font-latex-quote-list '(("``" "''") ("<<" ">>" french) ("«" "»" french))
73  "List of quote specifiers for quotation fontification.
74
75Each element of the list is either a list consisting of two
76strings to be used as opening and closing quotation marks
77independently of the value of `font-latex-quotes' or a list with
78three elements where the first and second element are strings for
79opening and closing quotation marks and the third element being
80either the symbol 'german or 'french describing the order of
81quotes.
82
83If `font-latex-quotes' specifies a different state, order of the
84added quotes will be reversed for fontification.  For example if
85'(\"\\\"<\" \"\\\">\" french) is given but `font-latex-quotes'
86specifies 'german, quotes will be used like \">foo\"< for
87fontification.")
88
89(defvar font-latex-quotes-control nil
90  "Internal variable for keeping track if `font-latex-quotes' changed.")
91(make-variable-buffer-local 'font-latex-quotes-control)
92
93(defvar font-latex-quotes-internal nil
94  "Internal variable for tracking outcome of automatic detection.
95If automatic detection is not enabled, it is assigned the value
96of `font-latex-quotes'.")
97(make-variable-buffer-local 'font-latex-quotes-internal)
98
99(defvar font-latex-quotes-fallback 'french
100  "Fallback value for `font-latex-quotes' if automatic detection fails.")
101
102(defvar font-latex-quote-style-list-french
103  '("french" "frenchb" "frenchle" "frenchpro" "francais" "canadien"
104    "acadian" "italian")
105  "List of styles for which French-style quote matching should be activated.")
106
107(defvar font-latex-quote-style-list-german
108  '("austrian" "german" "germanb" "naustrian" "ngerman")
109  "List of styles for which German-style quote matching should be activated.")
110
111(defcustom font-latex-quotes 'auto
112  "Whether to fontify << French quotes >> or >>German quotes<<.
113Also selects \"<quote\"> versus \">quote\"<.
114
115If value `auto' is chosen, an attempt is being made in deriving
116the type of quotation mark matching from document settings like
117the language option supplied to the babel package.
118
119If nil, quoted content will not be fontified."
120  :type '(choice (const auto) (const french) (const german) (const nil))
121  :group 'font-latex)
122(put 'font-latex-quotes 'safe-local-variable
123     '(lambda (x) (memq x '(auto french german nil))))
124
125(defun font-latex-add-quotes (quotes)
126  "Add QUOTES to `font-latex-quote-list'.
127QUOTES has to be a list adhering to the format of an element of
128`font-latex-quote-list'."
129  (setq font-latex-quotes-control nil)
130  (add-to-list (make-local-variable 'font-latex-quote-list) quotes))
131
132(defun font-latex-quotes-set-internal ()
133  "Set `font-latex-quotes-internal' according to `font-latex-quotes'.
134If `font-latex-quotes' is set to `auto', try to derive the
135correct value from document properties."
136  (setq font-latex-quotes-internal
137	(if (eq font-latex-quotes 'auto)
138	    (or (when (TeX-elt-of-list-member
139		       font-latex-quote-style-list-french TeX-active-styles)
140		  'french)
141		(when (TeX-elt-of-list-member
142		       font-latex-quote-style-list-german TeX-active-styles)
143		  'german)
144		font-latex-quotes-fallback)
145	  font-latex-quotes)))
146;; Update the value of `font-latex-quotes-internal' when the list of
147;; styles changes.
148(add-hook 'TeX-update-style-hook 'font-latex-quotes-set-internal)
149
150;; The definitions of the title faces were originally taken from
151;; info.el (Copyright (C) 1985, 86, 92, 93, 94, 95, 96, 97, 98, 99,
152;; 2000, 2001 Free Software Foundation, Inc.) and adapted to the needs
153;; of font-latex.el.
154
155(defconst font-latex-sectioning-max 5
156  "Highest number for font-latex-sectioning-N-face")
157(defface font-latex-sectioning-5-face
158  '((((type tty pc) (class color) (background light))
159     (:foreground "blue4" :weight bold))
160    (((type tty pc) (class color) (background dark))
161     (:foreground "yellow" :weight bold))
162    (((class color) (background light))
163     (:weight bold :inherit variable-pitch :foreground "blue4"))
164    (((class color) (background dark))
165     (:weight bold :inherit variable-pitch :foreground "yellow"))
166    (t (:weight bold :inherit variable-pitch)))
167  "Face for sectioning commands at level 5."
168  :group 'font-latex-highlighting-faces)
169
170(defun font-latex-update-sectioning-faces (&optional max height-scale)
171  "Update sectioning commands faces."
172  (unless height-scale
173    (setq height-scale (if (numberp font-latex-fontify-sectioning)
174			   ;; Make sure `height-scale' is a floating point
175			   ;; number because `set-face-attribute' treats
176			   ;; integers differently from floating points.
177			   (float font-latex-fontify-sectioning)
178			 1.1)))
179  (unless max
180    (setq max font-latex-sectioning-max))
181  (dotimes (num max)
182    (let* (;; reverse for XEmacs:
183	   (num (- max (1+ num)))
184	   (face-name (intern (format "font-latex-sectioning-%s-face" num))))
185      (unless (get face-name 'saved-face) ; Do not touch customized faces.
186	(set-face-attribute face-name nil :height  height-scale)))))
187
188(defcustom font-latex-fontify-sectioning 1.1
189  "Whether to fontify sectioning macros with varying height or a color face.
190
191If it is a number, use varying height faces.  The number is used
192for scaling starting from `font-latex-sectioning-5-face'.  Typically
193values from 1.05 to 1.3 give best results, depending on your font
194setup.  If it is the symbol `color', use `font-lock-type-face'.
195
196Caveats: Customizing the scaling factor applies to all sectioning
197faces unless those face have been saved by customize.  Setting
198this variable directly does not take effect unless you call
199`font-latex-update-sectioning-faces' or restart Emacs.
200
201Switching from `color' to a number or vice versa does not take
202effect unless you call \\[font-lock-fontify-buffer] or restart
203Emacs."
204  :type '(choice (number :tag "Scale factor")
205		 (const color))
206  :initialize 'custom-initialize-default
207  :set (lambda (symbol value)
208	 (set-default symbol value)
209	 (unless (eq value 'color)
210	   (font-latex-update-sectioning-faces font-latex-sectioning-max value)))
211  :group 'font-latex)
212
213(defun font-latex-make-sectioning-faces (max &optional height-scale)
214  "Build the faces used to fontify sectioning commands."
215  (unless max (setq max font-latex-sectioning-max))
216  (unless height-scale
217    (setq height-scale (if (numberp font-latex-fontify-sectioning)
218			   ;; Make sure `height-scale' is a floating point
219			   ;; number because the integer type is treated
220			   ;; differently.
221			   (float font-latex-fontify-sectioning)
222			 1.1)))
223  (dotimes (num max)
224    (let* ((num (- max (1+ num)))
225	   (face-name (intern (format "font-latex-sectioning-%s-face" num)))
226	   (f-inherit (intern (format "font-latex-sectioning-%s-face" (1+ num)))))
227      (eval
228       `(defface ,face-name
229	  '((t (:height ,height-scale :inherit ,f-inherit)))
230	  (format "Face for sectioning commands at level %s.
231
232Probably you don't want to customize this face directly.  Better
233change the base face `font-latex-sectioning-5-face' or customize the
234variable `font-latex-fontify-sectioning'." ',num)
235	  :group 'font-latex-highlighting-faces)))))
236
237(font-latex-make-sectioning-faces font-latex-sectioning-max)
238
239
240;;; Keywords
241
242(defvar font-latex-keywords-1 nil
243  "Subdued level highlighting for LaTeX modes.")
244
245(defvar font-latex-keywords-2 nil
246  "High level highlighting for LaTeX modes.")
247
248(defvar font-latex-built-in-keyword-classes
249  '(("warning"
250     ("nopagebreak" "pagebreak" "newpage" "clearpage" "cleardoublepage"
251      "enlargethispage" "nolinebreak" "linebreak" "newline" "-" "\\" "\\*"
252      "appendix" "displaybreak" "allowdisplaybreaks" "include")
253     font-latex-warning-face 1 noarg)
254    ("variable"
255     (("setlength" "|{\\{") ("settowidth" "|{\\{") ("settoheight" "{{")
256      ("settodepth" "{{") ("setcounter" "{|{\\")
257      ("addtolength" "|{\\{") ("addtocounter" "{|{\\")
258      ("stepcounter" "{") ("refstepcounter" "{")
259      ("arabic" "{") ("roman" "{") ("Roman" "{") ("alph" "{") ("Alph" "{")
260      ("fnsymbol" "{"))
261     font-lock-variable-name-face 2 command)
262    ("biblatexnoarg"
263     ("newrefsegment" "mancite" "pno" "ppno" "nopp" "psq" "psqq")
264     font-lock-variable-name-face 2 noarg)
265    ("biblatex"
266     (;; 3.2.2 Setting Package Options
267      ("ExecuteBibliographyOptions" "[{")
268      ;; 3.7.1 Resources
269      ("addbibresource" "[{") ("addglobalbib" "[{") ("addsectionbib" "[{")
270      ;; 3.7.2 The Bibliography
271      ("printbibliography" "[") ("bibbysection"    "[") ("bibbysegment" "[")
272      ("bibbycategory"     "[") ("printbibheading" "[")
273      ;; 3.7.3 Bibliography Lists
274      ("printbiblist" "[{") ("printshorthands" "[")
275      ;; 3.7.4 Bibliography Sections
276      ("newrefsection" "[")
277      ;; 3.7.6 Bibliography Categories
278      ("DeclareBibliographyCategory" "{") ("addtocategory" "{{")
279      ;; 3.7.7 Bibliography Headings and Environments
280      ("defbibenvironment" "{{{{") ("defbibheading" "{[{")
281      ;; 3.7.8 Bibliography Notes
282      ("defbibnote" "{{")
283      ;; 3.7.9 Bibliography Filters and Checks
284      ("defbibfilter" "{{") ("defbibcheck" "{{")
285      ;; 3.7.10 Reference Contexts
286      ("DeclareRefcontext"       "{{")  ("newrefcontext"        "[{")
287      ("assignrefcontextkeyws"   "*[{") ("assignrefcontextcats" "*[{")
288      ("assignrefcontextentries" "*[{")
289      ;; 3.7.11 Dynamic Entry Sets
290      ("defbibentryset" "{{")
291      ;; 3.8.1 Standard Commands
292      ("Cite" "[[{")
293      ("parencite" "*[[{") ("Parencite"    "[[{")
294      ("footcite"  "[[{")  ("footcitetext" "[[{")
295      ;; 3.8.2 Style-specific Commands
296      ("textcite"  "[[{") ("Textcite"  "[[{")
297      ("smartcite" "[[{") ("Smartcite" "[[{")
298      ("supercite" "{")
299      ;; 3.8.3 Qualified Citation Lists
300      ;; For qualified lists, fontify at least 2 mandatory arguments
301      ("cites"      "(([[{[[{") ("Cites"         "(([[{[[{")
302      ("parencites" "(([[{[[{") ("Parencites"    "(([[{[[{")
303      ("footcites"  "(([[{[[{") ("footcitetexts" "(([[{[[{")
304      ("smartcites" "(([[{[[{") ("Smartcites"    "(([[{[[{")
305      ("textcites"  "(([[{[[{") ("Textcites"     "(([[{[[{")
306      ("supercites" "(([[{[[{")
307      ;; 3.8.4 Style-independent Commands
308      ("autocite" "*[[{")      ("Autocite" "*[[{")
309      ("autocites" "(([[{[[{") ("Autocites" "(([[{[[{")
310      ;; 3.8.5 Text Commands
311      ("citeauthor" "*[[{") ("Citeauthor" "*[[{") ("citetitle" "*[[{")
312      ("citeyear"   "*[[{") ("citedate" "*[[{")
313      ("citeurl"    "[[{")  ("parentext" "{")
314      ("brackettext" "{")
315      ;; 3.8.6 Special Commands
316      ("fullcite"  "[[{")         ("footfullcite" "[[{")
317      ("volcite"   "[{[{")        ("Volcite"      "[{[{")
318      ("volcites"  "(([{[{[{[{")  ("Volcites"     "(([{[{[{[{")
319      ("pvolcite"  "[{[{")        ("Pvolcite"     "[{[{")
320      ("pvolcites" "(([{[{[{[{")  ("Pvolcites"    "(([{[{[{[{")
321      ("fvolcite"  "[{[{")        ("ftvolcite"    "[{[{")
322      ("fvolcites" "(([{[{[{[{")  ("Fvolcites"    "(([{[{[{[{")
323      ("svolcite"  "[{[{")        ("Svolcite"     "[{[{")
324      ("svolcites" "(([{[{[{[{")  ("Svolcites"    "(([{[{[{[{")
325      ("tvolcite"  "[{[{")        ("Tvolcite"     "[{[{")
326      ("tvolcites" "(([{[{[{[{")  ("Tvolcites"    "(([{[{[{[{")
327      ("avolcite"  "[{[{")        ("Avolcite"     "[{[{")
328      ("avolcites" "(([{[{[{[{")  ("Avolcites"    "(([{[{[{[{")
329      ("notecite"  "[[{")         ("Notecite"     "[[{")
330      ("pnotecite" "[[{")         ("Pnotecite"    "[[{")
331      ("fnotecite" "[[{")
332      ;; 3.8.7 Low-level Commands
333      ("citename" "[[{[{") ("citelist" "[[{[{") ("citefield" "[[{[{")
334      ;; 3.8.8 Miscellaneous Commands
335      ("citereset" "*") ("RN" "{") ("Rn" "{")
336      ;; 3.9 Localization Commands
337      ("DefineBibliographyStrings" "{{")  ("DefineBibliographyExtras" "{{")
338      ("UndefineBibliographyExtras" "{{") ("DefineHyphenationExceptions" "{{")
339      ("NewBibliographyString" "{"))
340     font-lock-constant-face 2 command)
341    ("reference"
342     (("nocite" "*{") ("cite" "*[[{") ("label" "{") ("pageref" "{")
343      ("vref" "*{") ("eqref" "{") ("ref" "{") ("Ref" "{") ("include" "{")
344      ("input" "{") ("bibliography" "{") ("index" "{") ("glossary" "{")
345      ("footnote" "[{") ("footnotemark" "[") ("footnotetext" "[{")
346      ("marginpar" "[{"))
347     font-lock-constant-face 2 command)
348    ("function"
349     (("begin" "{") ("end" "{") ("pagenumbering" "{")
350      ("thispagestyle" "{") ("pagestyle" "{") ("nofiles" "")
351      ("includeonly" "{") ("bibliographystyle" "{") ("documentstyle" "[{")
352      ("documentclass" "[{[") ("newenvironment" "*{[[{{")
353      ("newcommand" "*|{\\[[{") ("newlength" "|{\\")
354      ("newtheorem" "{[{[")
355      ("providecommand" "*|{\\[[{")
356      ("newcounter" "{[") ("renewenvironment" "*{[[{{")
357      ("renewcommand" "*|{\\[[{") ("renewtheorem" "{[{[")
358      ("usepackage" "[{[") ("fbox" "{") ("mbox" "{") ("rule" "[{{")
359      ("addvspace" "{") ("vspace" "*{") ("hspace" "*{")
360      ("thinspace" "")  ("negthinspace" "")
361      ("labelformat" "{{")
362      ;; XXX: Should macros without arguments rather be listed in a
363      ;; separate category with 'noarg instead of 'command handling?
364      ("enspace" "") ("enskip" "") ("quad" "") ("qquad" "") ("nonumber" "")
365      ("centering" "") ("raggedright" "") ("raggedleft" "")
366      ("TeX" "") ("LaTeX" "") ("LaTeXe" ""))
367     font-lock-function-name-face 2 command)
368    ("sectioning-0"
369     (("part" "*[{"))
370     (if (eq font-latex-fontify-sectioning 'color)
371	 'font-lock-type-face
372       'font-latex-sectioning-0-face)
373     2 command)
374    ("sectioning-1"
375     (("chapter" "*[{"))
376     (if (eq font-latex-fontify-sectioning 'color)
377	 'font-lock-type-face
378       'font-latex-sectioning-1-face)
379     2 command)
380    ("sectioning-2"
381     (("section" "*[{"))
382     (if (eq font-latex-fontify-sectioning 'color)
383	 'font-lock-type-face
384       'font-latex-sectioning-2-face)
385     2 command)
386    ("sectioning-3"
387     (("subsection" "*[{"))
388     (if (eq font-latex-fontify-sectioning 'color)
389	 'font-lock-type-face
390       'font-latex-sectioning-3-face)
391     2 command)
392    ("sectioning-4"
393     (("subsubsection" "*[{"))
394     (if (eq font-latex-fontify-sectioning 'color)
395	 'font-lock-type-face
396       'font-latex-sectioning-4-face)
397     2 command)
398    ("sectioning-5"
399     (("paragraph" "*[{") ("subparagraph" "*[{")
400      ("subsubparagraph" "*[{"))
401     (if (eq font-latex-fontify-sectioning 'color)
402	 'font-lock-type-face
403       'font-latex-sectioning-5-face)
404     2 command)
405    ("slide-title" () font-latex-slide-title-face 2 command)
406    ("textual"
407     (("item" "[") ("bibitem" "[{") ("title" "{") ("author" "{") ("date" "{")
408      ("thanks" "{") ("address" "{") ("caption" "[{")
409      ("textsuperscript" "{") ("textsubscript" "{") ("verb" "*"))
410     font-lock-type-face 2 command)
411    ("bold-command"
412     (("textbf" "{") ("textsc" "{") ("textup" "{") ("boldsymbol" "{")
413      ("pmb" "{"))
414     font-latex-bold-face 1 command)
415    ("italic-command"
416     (("emph" "{") ("textit" "{") ("textsl" "{"))
417     font-latex-italic-face 1 command)
418    ("math-command"
419     (("ensuremath" "|{\\"))
420     font-latex-math-face 1 command)
421    ("type-command"
422     (("texttt" "{") ("textsf" "{") ("textrm" "{") ("textmd" "{") ("oldstylenums" "{"))
423     font-lock-type-face 1 command)
424    ("bold-declaration"
425     ("bf" "bfseries" "sc" "scshape" "upshape")
426     font-latex-bold-face 1 declaration)
427    ("italic-declaration"
428     ("em" "it" "itshape" "sl" "slshape")
429     font-latex-italic-face 1 declaration)
430    ("type-declaration"
431     ("tt" "ttfamily" "sf" "sffamily" "rm" "rmfamily" "mdseries"
432      "tiny" "scriptsize" "footnotesize" "small" "normalsize"
433      "large" "Large" "LARGE" "huge" "Huge")
434     font-lock-type-face 1 declaration))
435  "Built-in keywords and specifications for font locking.
436
437The first element of each item is the name of the keyword class.
438
439The second element is a list of keywords (macros without an
440escape character) to highlight or, if the fifth element is the
441symbol 'command, a list of lists where the first element of each
442item is a keyword and the second a string specifying the macro
443syntax.  It can contain \"*\" if the macro has a starred variant,
444\"[\" for an optional argument, \"{\" for a mandatory argument,
445and \"\\\" for a macro.  A \"|\" means the following two tokens
446should be regarded as alternatives.
447
448The third element is the symbol of a face to be used or a Lisp
449form returning a face symbol.
450
451The fourth element is the fontification level.
452
453The fifth element is the type of construct to be matched.  It can
454be one of 'noarg which will match simple macros without
455arguments (like \"\\foo\"), 'declaration which will match macros
456inside a TeX group (like \"{\\bfseries foo}\"), or 'command which
457will match macros of the form \"\\foo[bar]{baz}\".")
458
459(defcustom font-latex-deactivated-keyword-classes nil
460  "List of strings for built-in keyword classes to be deactivated.
461
462Valid entries are \"warning\", \"variable\", \"biblatexnoarg\",
463\"biblatex\", \"reference\", \"function\" , \"sectioning-0\",
464\"sectioning-1\", \"sectioning-2\", \"sectioning-3\",
465\"sectioning-4\", \"sectioning-5\", \"slide-title\", \"textual\",
466\"bold-command\", \"italic-command\", \"math-command\",
467\"type-command\", \"bold-declaration\", \"italic-declaration\",
468\"type-declaration\".
469
470You have to restart Emacs for a change of this variable to take effect."
471  :group 'font-latex-keywords
472  :type `(set ,@(mapcar
473		 (lambda (spec)
474		   `(const :tag ,(concat
475				  ;; Name of the keyword class
476				  (let ((name (split-string (car spec) "-")))
477				    (setcar name (capitalize (car name)))
478				    (mapconcat 'identity name " "))
479				  " keywords in `"
480				  ;; Name of the face
481				  (symbol-name
482				   (let ((face (nth 2 spec)))
483				     (if (symbolp face) face (eval face))))
484				  "'.\n"
485				  ;; List of keywords
486				  (with-temp-buffer
487				    (insert "  Keywords: "
488					    (mapconcat (lambda (x)
489							 (if (listp x)
490							     (car x)
491							   x))
492						       (nth 1 spec) ", "))
493				    (fill-paragraph nil)
494				    (buffer-string)))
495			   ,(car spec)))
496		 font-latex-built-in-keyword-classes)))
497
498(defun font-latex-make-match-defun (prefix name face type)
499  "Return a function definition for keyword matching.
500The variable holding the keywords to match are determined by the
501strings PREFIX and NAME.  The type of matcher is determined by
502the symbol TYPE.
503
504This is a helper function for `font-latex-make-built-in-keywords'
505and `font-latex-make-user-keywords' and not intended for general
506use."
507  ;; Note: The functions are byte-compiled at the end of font-latex.el.
508  ;; FIXME: Is the cond-clause possible inside of the defun?
509
510  ;; In an earlier version of font-latex the type could be a list like
511  ;; (command 1).  This indicated a macro with one argument.  Provide
512  ;; a match function in this case but don't actually support it.
513  (cond ((or (eq type 'command) (listp type))
514	 (eval `(defun ,(intern (concat prefix name)) (limit)
515		  ,(concat "Fontify `" prefix name "' up to LIMIT.
516
517Generated by `font-latex-make-match-defun'.")
518		  (when ,(intern (concat prefix name))
519		    (font-latex-match-command-with-arguments
520		     ,(intern (concat prefix name))
521		     (append
522		      (when (boundp ',(intern (concat prefix name
523						      "-keywords-local")))
524			,(intern (concat prefix name "-keywords-local")))
525		      ,(intern (concat prefix name "-keywords")))
526		     ;; `face' can be a face symbol, a form returning
527		     ;; a face symbol, or a list of face attributes.
528		     ,(if (and (listp face) (fboundp (car face)))
529			 face
530			`',face)
531		     limit)))))
532	((eq type 'declaration)
533	 (eval `(defun ,(intern (concat prefix name)) (limit)
534		  ,(concat "Fontify `" prefix name "' up to LIMIT.
535
536Generated by `font-latex-make-match-defun'.")
537		  (when ,(intern (concat prefix name))
538		    (font-latex-match-command-in-braces
539		     ,(intern (concat prefix name)) limit)))))
540	((eq type 'noarg)
541	 (eval `(defun ,(intern (concat prefix name)) (limit)
542		  ,(concat "Fontify `" prefix name "' up to LIMIT.
543
544Generated by `font-latex-make-match-defun'.")
545		  (when ,(intern (concat prefix name))
546		    (re-search-forward
547		     ,(intern (concat prefix name)) limit t)))))))
548
549(defun font-latex-keyword-matcher (prefix name face type)
550  "Return a matcher and highlighter as required by `font-lock-keywords'.
551PREFIX and NAME are strings which are concatenated to form the
552respective match function.  FACE is a face name or a list of face
553attributes that will be applied to the respective part of the
554match returned by the match function.  A lisp form returning a
555face name or a list of face attributes is also valid for FACE.
556TYPE is the type of construct to be highlighted.  Currently the
557symbols 'command, 'declaration and 'noarg are valid.
558
559This is a helper function for `font-latex-make-built-in-keywords'
560and `font-latex-make-user-keywords' and not intended for general
561use."
562  ;; Quote a list of face attributes and a face symbol
563  ;; but do not quote a form returning such value.
564  (unless (and (listp face) (fboundp (car face)))
565    (setq face `',face))
566
567  ;; In an earlier version of font-latex the type could be a list like
568  ;; (command 1).  This indicated a macro with one argument.  Provide
569  ;; a matcher in this case but don't actually support it.
570  (cond ((or (eq type 'command) (listp type))
571	 `(,(intern (concat prefix name))
572	   (0 (font-latex-matched-face 0) append t)
573	   (1 (font-latex-matched-face 1) append t)
574	   (2 (font-latex-matched-face 2) append t)
575	   (3 (font-latex-matched-face 3) append t)
576	   (4 (font-latex-matched-face 4) append t)
577	   (5 (font-latex-matched-face 5) append t)
578	   (6 (font-latex-matched-face 6) append t)
579	   (7 (font-latex-matched-face 7) append t)
580	   (8 (font-latex-matched-face 8) append t)
581	   (9 (font-latex-matched-face 9) append t)
582	   (10 (font-latex-matched-face 10) append t)
583	   (11 (font-latex-matched-face 11) append t)))
584	((eq type 'noarg)
585	 `(,(intern (concat prefix name))
586	   (0 ,face)))
587	((eq type 'declaration)
588	 `(,(intern (concat prefix name))
589	   (0 'font-latex-warning-face t t)
590	   (1 'font-lock-keyword-face append t)
591	   (2 ,face append t)))))
592
593(defun font-latex-make-built-in-keywords ()
594  "Build defuns, defvars and defcustoms for built-in keyword fontification."
595  (dolist (item font-latex-built-in-keyword-classes)
596    (let ((prefix "font-latex-match-")
597	  (name (nth 0 item))
598	  (keywords (nth 1 item))
599	  (face (nth 2 item))
600	  (level (nth 3 item))
601	  (type (nth 4 item)))
602
603      ;; defvar font-latex-match-*-keywords-local
604      (eval `(defvar ,(intern (concat prefix name "-keywords-local"))
605	       ',keywords
606	       ,(concat "Buffer-local keywords to add to `"
607			prefix name "-keywords'.\n\n"
608			(if (eq type 'command)
609			    "\
610This must be a list where each element is a list consisting of a
611keyword string \(not a regular expression\) omitting the leading
612backslash and a format specifier as described in the doc string of
613`font-latex-user-keyword-classes'."
614			  "\
615This must be a list where each element is a keyword string \(not a
616regular expression\) omitting the leading backslash.")
617
618			"\n\n\
619This is an internal variable which should not be set directly.
620Use `font-latex-add-keywords' instead.
621
622Generated by `font-latex-make-built-in-keywords'.")))
623      (make-variable-buffer-local
624       (intern (concat prefix name "-keywords-local")))
625
626      ;; defun font-latex-match-*-make
627      ;; Note: The functions are byte-compiled at the end of font-latex.el.
628      (eval `(defun ,(intern (concat prefix name "-make")) ()
629	       ,(concat "Make or remake the variable `" prefix name "'.
630
631Generated by `font-latex-make-built-in-keywords'.")
632	       (let ((keywords
633		      (append
634		       (unless (member ,name
635				       font-latex-deactivated-keyword-classes)
636			 ,(intern (concat prefix name "-keywords-local")))
637		       ,(intern (concat prefix name "-keywords"))))
638		     multi-char-macros single-char-macros)
639		 (dolist (elt keywords)
640		   (let ((keyword (if (listp elt) (car elt) elt)))
641		     (if (string-match "^[A-Za-z]" keyword)
642			 (push keyword multi-char-macros)
643		       (push keyword single-char-macros))))
644		 (when (or multi-char-macros single-char-macros)
645		   (setq ,(intern (concat prefix name))
646			 (concat
647			  "\\\\\\("
648			  (when multi-char-macros
649			    (concat
650			     "\\(?:" (regexp-opt multi-char-macros) "\\)\\>"))
651			  (when single-char-macros
652			    (concat
653			     (when multi-char-macros "\\|")
654			     "\\(?:" (regexp-opt single-char-macros) "\\)"))
655			  "\\)"))))))
656
657      ;; defcustom font-latex-match-*-keywords
658      (eval `(defcustom ,(intern (concat prefix name "-keywords")) nil
659	       ,(concat "List of keywords "
660			(when (eq type 'command) "and formats ")
661			"for " name " face.\n"
662			(if (eq type 'command)
663			    "\
664Each element has to be a list consisting of the name of a macro
665omitting the leading backslash and a format specifier as
666described in the doc string of `font-latex-user-keyword-classes'."
667			  "\
668Each element has to be the name of a macro as a string, omitting
669the leading backslash.")
670			"\n\n\
671Setting this variable directly does not take effect; restart
672Emacs.
673
674Generated by `font-latex-make-built-in-keywords'.")
675	       :type '(repeat ,(if (eq type 'command)
676				   '(list (string :tag "Keyword")
677					  (string :tag "Format"))
678				 '(string :tag "Keyword")))
679	       :set (lambda (symbol value)
680		      (set-default symbol value)
681		      (funcall ',(intern (concat prefix name "-make"))))
682	       :group 'font-latex-keywords))
683
684      ;; defvar font-latex-match-*
685      (eval `(defvar ,(intern (concat prefix name)) nil
686	       ,(concat "Regular expression to match " name
687			" keywords.
688
689Generated by `font-latex-make-built-in-keywords'")))
690      (make-variable-buffer-local (intern (concat prefix name)))
691
692      ;; defun font-latex-match-*
693      (font-latex-make-match-defun prefix name face type)
694
695      ;; Add matchers and highlighters to `font-latex-keywords-{1,2}'.
696      (let ((keywords-entry (font-latex-keyword-matcher
697			     prefix name face type)))
698	(add-to-list (intern (concat "font-latex-keywords-"
699				     (number-to-string level)))
700		     keywords-entry t)
701	(when (= level 1)
702	  (add-to-list 'font-latex-keywords-2
703		       keywords-entry t))))))
704(font-latex-make-built-in-keywords)
705
706(defcustom font-latex-user-keyword-classes nil
707  "List of user-defined keyword classes for font locking.
708
709Every keyword class consists of four parts, a name, a list of
710keywords, a face and a specifier for the type of macro to be
711highlighted.
712
713When adding new entries, you have to use unique values for the
714class names, i.e. they must not clash with names of the built-in
715keyword classes or other names given by you.  Additionally the
716names must not contain spaces.
717
718The list of keywords defines which commands and declarations
719should be covered by the keyword class.  A keyword can either be
720a simple command name omitting the leading backslash or a list
721consisting of the command name and a string specifying the syntax
722of the command.  The latter is useful if you want to match LaTeX
723macros with arguments (see below).  You can specify the occurence
724and order of optional (\"[\") and mandatory (\"{\") arguments for
725each keyword.  For example for \"documentclass\" you'd use \"[{\"
726because the macro has one optional followed by one mandatory
727argument.  Optionally starred macros can be indicated with \"*\".
728In case an argument is an unbraced macro, use \"\\\".  You can
729also specify two alternative arguments by prefixing them with
730\"|\".  As an example, the specifier for \\newcommand is
731\"*|{\\=\\[[{\".
732
733The face argument can either be an existing face or a face
734attribute.
735
736There are three alternatives for the class type:
737
738A value of `command' indicates commands with arguments
739\(\"\\foo[bar]{baz}\").  The mandatory arguments in curly braces
740will get the face you specified.
741
742A value of `declaration' indicates declarations inside of TeX
743groups (\"{\\foo bar}\").  The content inside the braces,
744excluding the command, will get the face you specified.  In case
745the braces are missing, the face will be applied to the command
746itself.
747
748A value of `noarg' indicates commands without arguments
749\(\"\\foo\").  The command itself will get the face you
750specified.
751
752Setting this variable directly does not take effect;
753restart Emacs."
754  :group 'font-latex-keywords
755  :type `(repeat (list (string :tag "Name")
756		       (choice (repeat :tag "Keywords" (string :tag "Keyword"))
757			       (repeat
758				:tag "Keywords with specs"
759				(group (string :tag "Keyword")
760				       (string :tag "Format specifier"))))
761		       ,'(choice (face :tag "Face name")
762				 (custom-face-edit :tag "Face attributes"))
763		       (choice :tag "Type"
764			       ;; Maps to
765			       ;;`font-latex-match-command-with-arguments'
766			       (const :tag "Command with arguments"
767				      command)
768			       ;; Maps to
769			       ;;`font-latex-match-command-in-braces'
770			       (const :tag "Declaration inside TeX group"
771				      declaration)
772			       ;; Maps to `re-search-forward'
773			       (const :tag "Command without arguments"
774				      noarg))))
775  :set (lambda (symbol value)
776	 (dolist (item value)
777	   (when (string-match " " (car item))
778	     (error "No spaces allowed in name")))
779	 (let (names names-uniq)
780	   (dolist (item (append font-latex-built-in-keyword-classes value))
781	     (setq names (append names (list (car item)))))
782	   (setq names (TeX-sort-strings names))
783	   (setq names-uniq (TeX-delete-duplicate-strings names))
784	   (dotimes (i (safe-length names-uniq))
785	     (unless (string= (nth i names) (nth i names-uniq))
786	       (error "Name %S already exists" (nth i names)))))
787	 (set-default symbol value)
788	 (let ((prefix "font-latex-match-"))
789	   (dolist (elt value)
790	     (unless (boundp (intern (concat prefix (car elt))))
791	       ;; defvar font-latex-match-*
792	       (eval `(defvar ,(intern (concat prefix (car elt))) nil
793			,(concat "Regular expression to match " (car elt)
794				 " keywords.
795
796Generated by `font-latex-user-keyword-classes'"))))
797	     (let ((keywords (nth 1 elt))
798		   single-char-macro-flag)
799	       (setq keywords (if (listp (car keywords))
800				  (mapcar 'car keywords)
801				keywords))
802	       (catch 'single-char
803		 (dolist (keyword keywords)
804		   (unless (string-match "^[A-Za-z]" keyword)
805		     (setq single-char-macro-flag t)
806		     (throw 'single-char nil))))
807	       (set (intern (concat prefix (car elt)))
808		    (when (> (safe-length keywords) 0)
809		    (concat "\\\\" (let ((max-specpdl-size 1000))
810				     (regexp-opt keywords t))
811			    (unless single-char-macro-flag "\\>")))))))))
812
813(defun font-latex-make-user-keywords ()
814  "Build defuns and defvars for user keyword fontification."
815  (let ((keyword-specs font-latex-user-keyword-classes))
816    (dolist (item keyword-specs)
817      (let ((prefix "font-latex-match-")
818	    (name (nth 0 item))
819	    (keywords (nth 1 item))
820	    (face (nth 2 item))
821	    (type (nth 3 item)))
822
823	;; defvar font-latex-match-*-keywords
824	(eval `(defvar ,(intern (concat prefix name "-keywords")) ',keywords
825		 ,(concat "Font-latex keywords for " name " face.
826
827Generated by `font-latex-make-user-keywords'.")))
828
829	;; defun font-latex-match-*
830	(font-latex-make-match-defun prefix name face type)
831
832	;; Add the matcher to `font-latex-keywords-2'.
833	(add-to-list 'font-latex-keywords-2
834		     (font-latex-keyword-matcher prefix name face type) t))))
835
836  ;; Add the "fixed" matchers and highlighters.
837  (dolist (item
838	   '(("\\(^\\|[^\\]\\)\\(&+\\)" 2 'font-latex-warning-face)
839	     ("\\$\\$\\([^$]+\\)\\$\\$" 1 'font-latex-math-face)
840	     (font-latex-match-quotation
841	      (0 'font-latex-string-face append)
842	      (1 'font-latex-warning-face))
843	     ;; Hack to remove the verbatim face from the \ in
844	     ;; \end{verbatim} and similar.  The same hack is used in
845	     ;; tex-mode.el.
846	     ("\\(\\\\\\)end"
847	      (1 (get-text-property (match-end 1) 'face) t))))
848    (add-to-list 'font-latex-keywords-1 item)
849    (add-to-list 'font-latex-keywords-2 item))
850  (dolist (item
851	   '((font-latex-match-math-env
852	      (0 'font-latex-warning-face t t)
853	      (1 'font-latex-math-face append t))
854	     (font-latex-match-math-envII
855	      (0 'font-latex-math-face append t))
856	     (font-latex-match-simple-command
857	      (0 'font-latex-sedate-face append))
858	     (font-latex-match-script
859	      (1 (font-latex-script (match-beginning 0)) append))
860	     (font-latex-match-script-chars
861	      (1 (font-latex-script-char (match-beginning 1)) prepend))))
862    (add-to-list 'font-latex-keywords-2 item t)))
863(font-latex-make-user-keywords)
864
865(defun font-latex-add-keywords (keywords class)
866  "Add KEYWORDS to CLASS.
867KEYWORDS is a list of keywords or keywords with syntax specs.
868CLASS corresponds to a keyword class and can be one of the
869symbols 'warning, 'variable, 'reference, 'biblatexnoarg,
870'biblatex, 'function, 'sectioning-0, 'sectioning-1,
871'sectioning-2, 'sectioning-3, 'sectioning-4, 'sectioning-5,
872'slide-title, 'textual, 'bold-command, 'italic-command,
873'math-command, 'type-command, 'bold-declaration,
874'italic-declaration or 'type-declaration.
875
876The keywords will be added to the buffer-local list of keywords
877of the respective keyword class and necessary updates of the font
878locking machinery will be triggered."
879  (let* ((class (symbol-name class))
880	 (list (intern (format "font-latex-match-%s-keywords-local" class))))
881    (dolist (elt keywords)
882      (add-to-list list elt))
883    (funcall (intern (format "font-latex-match-%s-make" class)))
884    (font-latex-update-font-lock)))
885
886(defvar font-latex-keywords font-latex-keywords-1
887  "Default expressions to highlight in TeX mode.")
888
889
890;;; Subscript and superscript
891
892(defcustom font-latex-fontify-script t
893  "If non-nil, fontify subscript and superscript strings.
894
895By default, super/subscripts are raised/lowered if this variable
896is non-nil.  This fontification only affects one level of
897scripts, e.g., in x^{y^z}, the y and the z have the same size and
898are equally raised over x.
899
900If this variable is set to the symbol `multi-level', then y is
901raised above x, and z is raised above y.  With many script
902levels, the text might become too small to be readable, thus
903there is the option `font-latex-fontify-script-max-level'.  (The
904factors for text shrinking are defined in the faces
905`font-latex-superscript-face' and `font-latex-subscript-face' and
906the raise/lower factor in `font-latex-script-display'.)
907
908If this variable is set to the symbol `invisible', then the
909effect is essentially like `multi-level' but additionally the
910script operators ^ and _ are not displayed."
911  :type '(choice (boolean :tag "Enabled")
912		 (const :tag "Multiple levels" multi-level)
913		 (const :tag "Hide ^ and _" invisible))
914  :group 'font-latex)
915(put 'font-latex-fontify-script 'safe-local-variable
916     (lambda (val)
917       (or (booleanp val)
918	   (memq val '(multi-level invisible)))))
919
920(defcustom font-latex-fontify-script-max-level 3
921  "Maximum scriptification level for which script faces are applied.
922The faces `font-latex-superscript-face' and
923`font-latex-subscript-face' define custom :height values < 1.0.
924Therefore, scripts are displayed with a slightly smaller font
925than normal math text.  If `font-latex-fontify-script' is
926`multi-level' or `invisible', the font size becomes too small to
927be readable after a few levels.  This option allows to specify
928the maximum level after which the size of the script text won't
929be shrunken anymore.
930
931For example, see this expression:
932
933  \\( x^{y^{z^a_b}} \\)
934
935x has scriptification level 0, y has level 1, z has level 2, and
936both a and b have scriptification level 3.
937
938If `font-latex-fontify-script-max-level' was 2, then z, a, and b
939would have the same font size.  If it was 3 or more, then a and b
940were smaller than z just in the same way as z is smaller than y
941and y is smaller than x."
942  :group 'font-latex
943  :type 'integer)
944
945(defcustom font-latex-script-display '((raise -0.5) . (raise 0.5))
946  "Display specification for subscript and superscript content.
947The car is used for subscript, the cdr is used for superscripts."
948  :group 'font-latex
949  :type '(cons (choice (sexp :tag "Subscript form")
950		       (const :tag "No lowering" nil))
951	       (choice (sexp :tag "Superscript form")
952		       (const :tag "No raising" nil))))
953
954
955;;; Syntactic keywords
956
957(defvar font-latex-syntactic-keywords nil
958  "Syntactic keywords used by `font-latex'.")
959(make-variable-buffer-local 'font-latex-syntactic-keywords)
960
961(defvar font-latex-syntactic-keywords-extra nil
962  "List of syntactic keywords to add to `font-latex-syntactic-keywords'.
963The form should be the same as in `font-lock-syntactic-keywords'.")
964(make-variable-buffer-local 'font-latex-syntactic-keywords-extra)
965
966;; Set and updated in `font-latex-set-syntactic-keywords'.
967(defvar font-latex-doctex-syntactic-keywords nil)
968
969(defun font-latex-set-syntactic-keywords ()
970  "Set the variable `font-latex-syntactic-keywords'.
971This function can be used to refresh the variable in case other
972variables influencing its value, like `LaTeX-verbatim-environments',
973have changed."
974  ;; Checks for non-emptiness of lists added in order to cater for
975  ;; installations where `(regexp-opt-group nil)' would enter a loop.
976  (let ((verb-envs (and (fboundp 'LaTeX-verbatim-environments)
977			(LaTeX-verbatim-environments)))
978	(verb-macros-with-delims
979	 (and (fboundp 'LaTeX-verbatim-macros-with-delims)
980	      (LaTeX-verbatim-macros-with-delims)))
981	(verb-macros-with-braces
982	 (and (fboundp 'LaTeX-verbatim-macros-with-braces)
983	      (LaTeX-verbatim-macros-with-braces))))
984    (setq verb-envs (and verb-envs (regexp-opt verb-envs))
985	  verb-macros-with-delims (and verb-macros-with-delims
986				       (regexp-opt verb-macros-with-delims))
987	  verb-macros-with-braces (and verb-macros-with-braces
988				       (regexp-opt verb-macros-with-braces))
989	  font-latex-syntactic-keywords nil)
990    (unless (= (length verb-envs) 0)
991      (add-to-list 'font-latex-syntactic-keywords
992		   `(,(concat
993		       "^[ \t]*\\\\begin *{\\(?:" verb-envs "\\)}"
994		       ;; Some environments accept an optional and/or mandatory
995		       ;; argument that can span over more lines.  Between
996		       ;; "\begin{<envname>}" and the optional argument there
997		       ;; can be whitespaces and the newline can be commented
998		       ;; by a "%" character.
999		       "[ \t]*\\(?:%.*\n[ \t]*\\)?"
1000		       ;; The following line of the regexp matches the optional
1001		       ;; argument and allows for up to one level of brackets
1002		       ;; inside the argument (e.g., the dialect of a language
1003		       ;; in the `lstlisting' environment by the `listings'
1004		       ;; package).
1005		       "\\(?:\\[[^\]\[]*\\(?:\\[[^\]\[]*\\][^\]\[]*\\)*\\]\\)?"
1006		       ;; After the optional argument, there may also be
1007		       ;; another mandatory argument(s) (e.g. with VerbatimOut or
1008		       ;; the minted envs or defined with `lstnewenvironment').
1009		       "\\(?:{[^}]*}\\)*"
1010		       ;; Now match the final newline.  The "." alternative
1011		       ;; catches the case where verbatim content is written
1012		       ;; immediately after the \begin{verbatim}.
1013		       "\\(\n\\|.\\)")
1014		     (1 "|" t)))
1015      (add-to-list 'font-latex-syntactic-keywords
1016		   ;; Using the newline character for the syntax
1017		   ;; property often resulted in fontification
1018		   ;; problems when text was inserted at the end of
1019		   ;; the verbatim environment.  That's why we now use
1020		   ;; the starting backslash of \end.  There is a hack
1021		   ;; in `font-latex-make-user-keywords' to remove the
1022		   ;; spurious fontification of the backslash.
1023		   `(,(concat "\\(\\\\\\)end *{\\(?:" verb-envs "\\)}")
1024		     (1 "|" t))))
1025    (unless (= (length verb-macros-with-delims) 0)
1026      (add-to-list 'font-latex-syntactic-keywords
1027		   `(,(concat "\\\\\\(?:" verb-macros-with-delims "\\)"
1028			      ;; Some macros take an optional
1029			      ;; argument.  This is the same line as
1030			      ;; above for environments.
1031			      "\\(?:\\[[^][]*\\(?:\\[[^][]*\\][^][]*\\)*\\]\\)?"
1032			      ;; An opening curly brace as delimiter
1033			      ;; is valid, but allowing it might screw
1034			      ;; up fontification of stuff like
1035			      ;; "\url{...} foo \textbf{<--!...}".
1036			      "\\([^a-z@*\n\f{]\\).*?"
1037			      ;; Give an escape char at the end of the
1038			      ;; verbatim construct punctuation syntax.
1039			      ;; Prevents wrong fontification of stuff
1040			      ;; like "\verb|foo\|".
1041			      "\\(" (regexp-quote TeX-esc) "*\\)\\(\\1\\)")
1042		     (1 "\"") (2 ".") (3 "\""))))
1043    (unless (= (length verb-macros-with-braces) 0)
1044      (add-to-list 'font-latex-syntactic-keywords
1045		   `(,(concat "\\\\\\(?:" verb-macros-with-braces "\\)"
1046			      ;; Some macros take an optional
1047			      ;; argument.  This is the same line as
1048			      ;; above for environments.
1049			      "\\(?:\\[[^][]*\\(?:\\[[^][]*\\][^][]*\\)*\\]\\)?"
1050			      "\\({\\).*?[^\\]\\(?:\\\\\\\\\\)*\\(}\\)")
1051		     (1 "|") (2 "|")))))
1052  (when font-latex-syntactic-keywords-extra
1053    (nconc font-latex-syntactic-keywords font-latex-syntactic-keywords-extra))
1054  ;; Cater for docTeX mode.
1055  (setq font-latex-doctex-syntactic-keywords
1056	(append font-latex-syntactic-keywords
1057		;; For docTeX comment-in-doc.
1058		`(("\\(\\^\\)\\^A" (1 (font-latex-doctex-^^A)))))))
1059
1060
1061;;; Syntactic fontification
1062
1063;; Copy and adaptation of `tex-font-lock-syntactic-face-function' in
1064;; `tex-mode.el' of CVS Emacs (March 2004)
1065(defun font-latex-syntactic-face-function (state)
1066  (let ((char (nth 3 state)))
1067    (cond
1068     ((not char) 'font-lock-comment-face)
1069     ((eq char ?$) 'font-latex-math-face)
1070     (t
1071      (when (characterp char)
1072	;; This is a \verb?...? construct.  Let's find the end and mark it.
1073	(save-excursion
1074	  (skip-chars-forward (string ?^ char)) ;; Use `end' ?
1075	  (when (eq (char-syntax (preceding-char)) ?/)
1076	    (put-text-property (1- (point)) (point) 'syntax-table '(1)))
1077	  (unless (eobp)
1078	    (put-text-property (point) (1+ (point)) 'syntax-table '(7)))))
1079      'font-latex-verbatim-face))))
1080
1081
1082;;; Faces
1083
1084(defface font-latex-bold-face
1085  (let ((font (cond ((assq :inherit custom-face-attributes) '(:inherit bold))
1086		    ((assq :weight custom-face-attributes) '(:weight bold))
1087		    (t '(:bold t)))))
1088    `((((class grayscale) (background light))
1089       (:foreground "DimGray" ,@font))
1090      (((class grayscale) (background dark))
1091       (:foreground "LightGray" ,@font))
1092      (((class color) (background light))
1093       (:foreground "DarkOliveGreen" ,@font))
1094      (((class color) (background dark))
1095       (:foreground "OliveDrab" ,@font))
1096      (t (,@font))))
1097  "Face used to highlight text to be typeset in bold."
1098  :group 'font-latex-highlighting-faces)
1099
1100(defface font-latex-italic-face
1101  (let ((font (cond ((assq :inherit custom-face-attributes) '(:inherit italic))
1102		    ((assq :slant custom-face-attributes) '(:slant italic))
1103		    (t '(:italic t)))))
1104    `((((class grayscale) (background light))
1105       (:foreground "DimGray" ,@font))
1106      (((class grayscale) (background dark))
1107       (:foreground "LightGray" ,@font))
1108      (((class color) (background light))
1109       (:foreground "DarkOliveGreen" ,@font))
1110      (((class color) (background dark))
1111       (:foreground "OliveDrab" ,@font))
1112      (t (,@font))))
1113  "Face used to highlight text to be typeset in italic."
1114  :group 'font-latex-highlighting-faces)
1115
1116(defface font-latex-math-face
1117  (let ((font (cond ((assq :inherit custom-face-attributes)
1118		     '(:inherit underline))
1119		    (t '(:underline t)))))
1120    `((((class grayscale) (background light))
1121       (:foreground "DimGray" ,@font))
1122      (((class grayscale) (background dark))
1123       (:foreground "LightGray" ,@font))
1124      (((class color) (background light))
1125       (:foreground "SaddleBrown"))
1126      (((class color) (background dark))
1127       (:foreground "burlywood"))
1128      (t (,@font))))
1129  "Face used to highlight math."
1130  :group 'font-latex-highlighting-faces)
1131
1132(defface font-latex-sedate-face
1133  '((((class grayscale) (background light)) (:foreground "DimGray"))
1134    (((class grayscale) (background dark))  (:foreground "LightGray"))
1135    (((class color) (background light)) (:foreground "DimGray"))
1136    (((class color) (background dark))  (:foreground "LightGray"))
1137   ;;;(t (:underline t))
1138    )
1139  "Face used to highlight sedate stuff."
1140  :group 'font-latex-highlighting-faces)
1141
1142(defface font-latex-string-face
1143  (let ((font (cond ((assq :inherit custom-face-attributes) '(:inherit italic))
1144		    ((assq :slant custom-face-attributes) '(:slant italic))
1145		    (t '(:italic t)))))
1146    `((((type tty) (class color))
1147       (:foreground "green"))
1148      (((class grayscale) (background light))
1149       (:foreground "DimGray" ,@font))
1150      (((class grayscale) (background dark))
1151       (:foreground "LightGray" ,@font))
1152      (((class color) (background light))
1153       (:foreground "RosyBrown"))
1154      (((class color) (background dark))
1155       (:foreground "LightSalmon"))
1156      (t (,@font))))
1157  "Face used to highlight strings."
1158  :group 'font-latex-highlighting-faces)
1159
1160(defface font-latex-warning-face
1161  (let ((font (cond ((assq :inherit custom-face-attributes) '(:inherit bold))
1162		    ((assq :weight custom-face-attributes) '(:weight bold))
1163		    (t '(:bold t)))))
1164    `((((class grayscale)(background light))
1165       (:foreground "DimGray" ,@font))
1166      (((class grayscale)(background dark))
1167       (:foreground "LightGray" ,@font))
1168      (((class color)(background light))
1169       (:foreground "red" ,@font))
1170      (((class color)(background dark))
1171       (:foreground "red" ,@font))
1172      (t (,@font))))
1173  "Face for important keywords."
1174  :group 'font-latex-highlighting-faces)
1175
1176(defface font-latex-verbatim-face
1177  (let ((font (if (and (assq :inherit custom-face-attributes)
1178		       (facep 'fixed-pitch))
1179		  '(:inherit fixed-pitch)
1180		'(:family "courier"))))
1181    `((((class grayscale) (background light))
1182       (:foreground "DimGray" ,@font))
1183      (((class grayscale) (background dark))
1184       (:foreground "LightGray" ,@font))
1185      (((class color) (background light))
1186       (:foreground "SaddleBrown" ,@font))
1187      (((class color) (background dark))
1188       (:foreground "burlywood" ,@font))
1189      (t (,@font))))
1190  "Face used to highlight TeX verbatim environments."
1191  :group 'font-latex-highlighting-faces)
1192
1193(defface font-latex-superscript-face
1194  '((t (:height 0.85)))
1195  "Face used for superscripts."
1196  :group 'font-latex-highlighting-faces)
1197
1198(defface font-latex-subscript-face
1199  '((t (:height 0.85)))
1200  "Face used for subscripts."
1201  :group 'font-latex-highlighting-faces)
1202
1203(defface font-latex-script-char-face
1204  (let ((font (cond ((assq :inherit custom-face-attributes)
1205		     '(:inherit underline))
1206		    (t '(:underline t)))))
1207    `((((class grayscale) (background light))
1208       (:foreground "DarkGray" ,@font))
1209      (((class grayscale) (background dark))
1210       (:foreground "gray" ,@font))
1211      (((class color) (background light))
1212       (:foreground "salmon"))
1213      (((class color) (background dark))
1214       (:foreground "DarkRed"))
1215      (t (,@font))))
1216  "Face used for the script chars ^ and _."
1217  :group 'font-latex-highlighting-faces)
1218
1219(defface font-latex-slide-title-face
1220  (let* ((scale 1.2))
1221    `((t (:inherit (variable-pitch font-lock-type-face)
1222		   :weight bold :height ,scale))))
1223  "Face for slide titles."
1224  :group 'font-latex-highlighting-faces)
1225
1226;;; Setup
1227
1228(defvar font-lock-comment-start-regexp nil
1229  "Regexp to match the start of a comment.")
1230
1231(defvar font-latex-extend-region-functions nil
1232  "List of functions extending the region for multiline constructs.
1233
1234Each function should accept two arguments, the begin and end of
1235the region to be fontified, and return the new region start.  If
1236no extension is necessary, the original region start should be
1237returned.
1238
1239All specified functions will be called and the region extended
1240backwards to the minimum over their return values.")
1241
1242(defvar font-latex-syntax-alist
1243  ;; Use word syntax for @ because we use \> for matching macros and
1244  ;; we don't want \foo@bar to be found if we search for \foo.
1245  '((?\( . ".") (?\) . ".") (?$ . "\"") (?@ . "w"))
1246  "List of specifiers for the syntax alist of `font-lock-defaults'.")
1247
1248(defun font-latex-add-to-syntax-alist (list)
1249  "Activate syntactic font locking for the entries in LIST.
1250The entries are added to `font-latex-syntax-alist' and eventually
1251end up in `font-lock-defaults'.  Each entry in LIST should be a
1252cons pair as expected by `font-lock-defaults'.  The function also
1253triggers Font Lock to recognize the change."
1254  (set (make-local-variable 'font-latex-syntax-alist)
1255       (append font-latex-syntax-alist list))
1256  ;; Tell font-lock about the update.
1257  (setq font-lock-set-defaults nil)
1258  (font-latex-setup))
1259
1260;;;###autoload
1261(defun font-latex-setup ()
1262  "Setup this buffer for LaTeX font-lock.  Usually called from a hook."
1263  (font-latex-set-syntactic-keywords)
1264  ;; Trickery to make $$ fontification be in `font-latex-math-face' while
1265  ;; strings get whatever `font-lock-string-face' has been set to.
1266  (when (fboundp 'built-in-face-specifiers)
1267    ;; Cool patch from Christoph Wedler...
1268    (let (instance)
1269      (mapc (lambda (property)
1270	      (setq instance
1271		    (face-property-instance 'font-latex-math-face property
1272					    nil 0 t))
1273	      (if (numberp instance)
1274		  (setq instance
1275			(face-property-instance 'default property nil 0)))
1276	      (or (numberp instance)
1277		  (set-face-property 'font-lock-string-face property
1278				     instance (current-buffer))))
1279	    (built-in-face-specifiers))))
1280
1281  ;; Activate multi-line fontification facilities if available.
1282  (when (boundp 'font-lock-multiline)
1283    (set (make-local-variable 'font-lock-multiline) t))
1284
1285  ;; Functions for extending the region.
1286  (dolist (elt '(font-latex-extend-region-backwards-command-with-args
1287		 font-latex-extend-region-backwards-command-in-braces
1288		 font-latex-extend-region-backwards-quotation
1289		 font-latex-extend-region-backwards-math-env
1290		 font-latex-extend-region-backwards-math-envII))
1291    (add-to-list 'font-latex-extend-region-functions elt))
1292
1293  ;; Tell Font Lock about the support.
1294  (make-local-variable 'font-lock-defaults)
1295  ;; The test for `major-mode' currently only works with docTeX mode
1296  ;; because `TeX-install-font-lock' is called explicitely in
1297  ;; `doctex-mode'.  In case other modes have to be distinguished as
1298  ;; well, remove the call to `TeX-install-font-lock' from
1299  ;; `VirTeX-common-initialization' and place it in the different
1300  ;; `xxx-mode' calls instead, but _after_ `major-mode' is set.
1301  (let ((defaults
1302	  `((font-latex-keywords font-latex-keywords-1 font-latex-keywords-2)
1303	    nil nil ,font-latex-syntax-alist nil))
1304	(variables
1305	 '((font-lock-comment-start-regexp . "%")
1306	   (font-lock-mark-block-function . mark-paragraph)
1307	   (font-lock-fontify-region-function
1308	    . font-latex-fontify-region)
1309	   (font-lock-unfontify-region-function
1310	    . font-latex-unfontify-region))))
1311    ;; Add the mode-dependent stuff to the basic variables defined above.
1312    (if (eq major-mode 'doctex-mode)
1313	(progn
1314	  (setcar defaults (append (car defaults)
1315				   '(font-latex-doctex-keywords)))
1316	  (setq variables
1317		(append variables
1318			'((font-lock-syntactic-face-function
1319			   . font-latex-doctex-syntactic-face-function)
1320			  (font-lock-syntactic-keywords
1321			   . font-latex-doctex-syntactic-keywords)))))
1322      (setq variables
1323	    (append variables
1324		    '((font-lock-syntactic-face-function
1325		       . font-latex-syntactic-face-function)
1326		      (font-lock-syntactic-keywords
1327		       . font-latex-syntactic-keywords)))))
1328    ;; Set the defaults.
1329    (setq font-lock-defaults (append defaults variables)))
1330
1331  ;; Make sure fontification will be refreshed if a user sets variables
1332  ;; influencing fontification in her file-local variables section.
1333  (add-hook 'hack-local-variables-hook #'font-latex-after-hacking-local-variables t t))
1334
1335(defun font-latex-update-font-lock (&optional syntactic-kws)
1336  "Tell font-lock about updates of fontification rules.
1337If SYNTACTIC-KWS is non-nil, also update
1338`font-latex-syntactic-keywords'."
1339  ;; Update syntactic keywords.
1340  (when syntactic-kws
1341    (font-latex-set-syntactic-keywords))
1342
1343  ;; Let font-lock recompute its fontification rules.
1344  (setq font-lock-set-defaults nil)
1345  (font-lock-set-defaults)
1346
1347  ;; Re-initialize prettification if needed.
1348  (when (and (boundp 'prettify-symbols-mode)
1349	     (boundp 'prettify-symbols--keywords)
1350	     prettify-symbols-mode
1351	     prettify-symbols--keywords)
1352    (font-lock-add-keywords nil prettify-symbols--keywords)))
1353
1354(defun font-latex-jit-lock-force-redisplay (buf start end)
1355  "Compatibility for Emacsen not offering `jit-lock-force-redisplay'."
1356  ;; The following block is an expansion of `jit-lock-force-redisplay'
1357  ;; and involved macros taken from CVS Emacs on 2007-04-28.
1358  (with-current-buffer buf
1359    (let ((modified (buffer-modified-p)))
1360      (unwind-protect
1361	  (let ((buffer-undo-list t)
1362		(inhibit-read-only t)
1363		(inhibit-point-motion-hooks t)
1364		(inhibit-modification-hooks t)
1365		deactivate-mark
1366		buffer-file-name
1367		buffer-file-truename)
1368	    (put-text-property start end 'fontified t))
1369	(unless modified
1370	  (restore-buffer-modified-p nil))))))
1371
1372(defun font-latex-fontify-region (beg end &optional loudly)
1373  "Fontify region from BEG to END.
1374If optional argument is non-nil, print status messages."
1375  (let ((extend-list (delq nil (mapcar (lambda (fun) (funcall fun beg end))
1376				       font-latex-extend-region-functions))))
1377    (when extend-list
1378      (let ((orig-beg beg))
1379	(setq beg (apply 'min extend-list))
1380	(when (featurep 'jit-lock)
1381	  ;; Stolen from `jit-lock-fontify-now' (2007-04-27) and
1382	  ;; adapted.  Without this stanza only the line in which a
1383	  ;; change happened will refontified.  The rest will only be
1384	  ;; refontified upon redisplay.
1385	  (run-with-timer 0 nil 'font-latex-jit-lock-force-redisplay
1386			  (current-buffer) beg orig-beg))))
1387    (font-lock-default-fontify-region beg end loudly)))
1388
1389;; Copy and adaption of `tex-font-lock-unfontify-region' from
1390;; tex-mode.el in GNU Emacs on 2004-08-04.
1391;; (XEmacs passes a third argument to the function.)
1392(defun font-latex-unfontify-region (beg end &rest ignored)
1393  "Unfontify region from BEG to END."
1394  (font-lock-default-unfontify-region beg end)
1395  ;; XEmacs does not provide `font-lock-extra-managed-props', so
1396  ;; remove the `font-latex-multiline' property manually.  (The
1397  ;; property is only added if `font-lock-multiline' is bound.)
1398  (unless (boundp 'font-lock-multiline)
1399    (remove-text-properties beg end '(font-latex-multiline)))
1400  (remove-text-properties beg end '(script-level))
1401  (let ((start beg))
1402    (while (< beg end)
1403      (let ((next (next-single-property-change beg 'display nil end))
1404	    (prop (get-text-property beg 'display)))
1405	(if (and (eq (car-safe prop) 'raise)
1406		 (null (cddr prop)))
1407	    (put-text-property beg next 'display nil))
1408	(setq beg next)))
1409    (remove-text-properties start end '(invisible))))
1410
1411(defadvice font-lock-after-change-function (before font-latex-after-change
1412						   activate)
1413  "Extend region for fontification of multiline constructs.
1414This is only necessary if the editor does not provide multiline
1415fontification facilities like `font-lock-multiline' itself."
1416  (unless (boundp 'font-lock-multiline)
1417    (let ((ad-beg (ad-get-arg 0))
1418	  (ad-end (ad-get-arg 1)))
1419      (save-excursion
1420	(goto-char ad-beg)
1421	(beginning-of-line)
1422	(when (get-text-property (point) 'font-latex-multiline)
1423	  (setq ad-beg (previous-single-property-change (point)
1424							'font-latex-multiline))
1425	  (when (numberp ad-beg)
1426	    (ad-set-arg 0 ad-beg)))
1427	(goto-char ad-end)
1428	(end-of-line)
1429	(when (get-text-property (point) 'font-latex-multiline)
1430	  (setq ad-end (next-single-property-change (point)
1431						    'font-latex-multiline))
1432	  (when (numberp ad-end)
1433	    (ad-set-arg 1 ad-end)))))))
1434
1435(defun font-latex-after-hacking-local-variables ()
1436  "Refresh fontification if required by updates of file-local variables.
1437This function is added to `hack-local-variables-hook' and
1438recomputes fontification if variables affecting fontification are
1439modified.  Such variables include
1440`LaTeX-verbatim-environments-local',
1441`LaTeX-verbatim-macros-with-braces-local',
1442`LaTeX-verbatim-macros-with-delims-local'."
1443  (when
1444      ;; In Emacs we know if the value came from file or directory
1445      ;; locals.  Note to self: directory-local variables are also added
1446      ;; to file-local-variables-alist.
1447      (let ((hacked-local-vars (mapcar #'car file-local-variables-alist)))
1448	(or (memq 'LaTeX-verbatim-environments-local hacked-local-vars)
1449	    (memq 'LaTeX-verbatim-macros-with-braces-local hacked-local-vars)
1450	    (memq 'LaTeX-verbatim-macros-with-delims-local hacked-local-vars)))
1451    ;; Ok, we need to refresh fontification.
1452    (font-latex-update-font-lock t)))
1453
1454;;; Utility functions
1455
1456(defun font-latex-find-matching-close (openchar closechar)
1457  "Skip over matching pairs of OPENCHAR and CLOSECHAR.
1458OPENCHAR is the opening character and CLOSECHAR is the closing
1459character.  Character pairs are usually { } or [ ].  Comments are
1460ignored during the search."
1461  (let ((parse-sexp-ignore-comments
1462	 (not (eq major-mode 'doctex-mode))) ; scan-sexps ignores comments
1463	(init-point (point))
1464	(mycount 1)
1465	(esc-char (or (and (boundp 'TeX-esc) TeX-esc) "\\"))
1466	;; XXX: Do not look up syntax-table properties since they may
1467	;; be misleading, e.g. in the case of "{foo}^^A" where the
1468	;; closing brace gets a comment end syntax.
1469	(parse-sexp-lookup-properties nil))
1470    (or
1471     (condition-case nil
1472	 (progn
1473	   (goto-char (with-syntax-table
1474			  (TeX-search-syntax-table openchar closechar)
1475			(scan-sexps (point) 1)))
1476	   ;; No error code.  See if closechar is unquoted
1477	   (save-excursion
1478	     (backward-char 1)
1479	     (zerop (mod (skip-chars-backward (regexp-quote esc-char)) 2))))
1480       (error nil))
1481     (save-match-data
1482       (goto-char (1+ init-point))
1483       (while (and (> mycount 0)
1484		   (re-search-forward
1485		    (string ?\[
1486			    ;; closechar might be ]
1487			    ;; and therefor must be first in regexp
1488			    closechar openchar
1489			    ?\])
1490		    nil t))
1491	 (cond
1492	  ((font-latex-commented-outp)
1493	   (forward-line 1))
1494	  ((save-excursion
1495	     (backward-char 1)
1496	     (zerop (mod (skip-chars-backward (regexp-quote esc-char))
1497			 2)))
1498	   (setq mycount (+ mycount
1499			    (if (= (preceding-char) openchar) 1 -1)))))))
1500     (if (= mycount 0)
1501	 t
1502       (goto-char init-point)
1503       nil))))
1504
1505(defun font-latex-commented-outp ()
1506  "Return t if comment character is found between bol and point."
1507  (save-excursion
1508    (let ((limit (point))
1509	  (esc-char (if (and (boundp 'TeX-esc) TeX-esc) TeX-esc "\\")))
1510      (forward-line 0)
1511      (if (and (eq (char-after) ?\%)
1512	       (not (font-latex-faces-present-p 'font-latex-verbatim-face)))
1513	  (not (eq major-mode 'doctex-mode))
1514	(catch 'found
1515	  (while (progn (skip-chars-forward "^%" limit)
1516			(< (point) limit))
1517	    (when (and (save-excursion
1518			 (zerop (mod (skip-chars-backward
1519				      (regexp-quote esc-char)) 2)))
1520		       (not (font-latex-faces-present-p
1521			     'font-latex-verbatim-face)))
1522	      (throw 'found t))
1523	    (forward-char)))))))
1524
1525(defun font-latex-faces-present-p (faces &optional pos)
1526  "Return t if FACES are present at position POS.
1527FACES may be a single face or a list of faces.
1528If POS is omitted, the current position of point is used."
1529  (let* ((faces (if (listp faces) faces (list faces)))
1530	 (pos (or pos (point)))
1531	 (prop (get-text-property pos 'face))
1532	 (prop-list (if (listp prop) prop (list prop))))
1533    (catch 'member
1534      (dolist (item prop-list)
1535	(when (memq item faces)
1536	  (throw 'member t))))))
1537
1538(defun font-latex-forward-comment ()
1539  "Like `forward-comment' but with special provisions for docTeX mode.
1540In docTeX mode \"%\" at the start of a line will be treated as whitespace."
1541  (if (eq major-mode 'doctex-mode)
1542      ;; XXX: We should probably cater for ^^A as well.
1543      (progn
1544	(while (progn (if (bolp) (skip-chars-forward "%"))
1545		      (> (skip-chars-forward " \t\n") 0)))
1546	(when (eq (char-after) ?%)
1547	  (beginning-of-line 2)
1548	  t))
1549    (forward-comment 1)))
1550
1551(defun font-latex-put-multiline-property-maybe (beg end)
1552  "Add a multiline property if no equivalent is provided by the editor.
1553The text property is used to find the start or end of a multiline
1554construct when unfontifying a region.  Emacs adds such a text
1555property automatically if `font-lock-multiline' is set to t and
1556extends the region to be unfontified automatically as well."
1557  (unless (boundp 'font-lock-multiline)
1558    (put-text-property beg end 'font-latex-multiline t)))
1559
1560
1561;;; Match functions
1562
1563(defvar font-latex-matched-faces nil
1564  "List of faces corresponding to matches in match data.")
1565
1566(defun font-latex-matched-face (pos)
1567  "Return face at position POS in `font-latex-matched-faces'."
1568  (nth pos font-latex-matched-faces))
1569
1570(defvar font-latex-command-with-args-default-spec nil ; "*[{"
1571  "Default specifier for keywords without syntax description.
1572Set this to nil if verification of command syntax is unwanted.")
1573
1574(defvar font-latex-command-with-args-opt-arg-delims
1575  '((?\[ . ?\]) (?< . ?>) (?\( . ?\)))
1576  "List character pairs used as delimiters for optional arguments.")
1577
1578(defvar font-latex-syntax-error-modes '(latex-mode)
1579  "List of modes where syntax errors in macros should be indicated.")
1580
1581(defun font-latex-match-command-with-arguments (regexp keywords face limit)
1582  "Search for regexp command KEYWORDS[opt]{arg} before LIMIT.
1583Returns nil if none of KEYWORDS is found."
1584  (setq font-latex-matched-faces nil)
1585  (catch 'match
1586    (while (re-search-forward regexp limit t)
1587      (unless (font-latex-faces-present-p '(font-lock-comment-face
1588					    font-latex-verbatim-face)
1589					  (match-beginning 0))
1590	(let* ((beg (match-beginning 0))
1591	       end		   ; Used for multiline text property.
1592	       (match-data (list beg))
1593	       match-beg syntax-error alternative spec
1594	       error-indicator-pos
1595	       (spec-list (string-to-list
1596			   (or (cadr (assoc (match-string 1) keywords))
1597			       font-latex-command-with-args-default-spec)))
1598	       (parse-sexp-ignore-comments t)) ; scan-sexps ignores comments
1599	  (goto-char (match-end 0))
1600	  ;; Check for starred macro if first spec is an asterisk or a
1601	  ;; plus sign in case of \defaultfontfeatures+ provided by
1602	  ;; fontspec.sty
1603	  (when (or (eq (car spec-list) ?*)
1604		    (eq (car spec-list) ?+))
1605	    (setq spec-list (cdr spec-list))
1606	    (skip-chars-forward "*+" (1+ (point))))
1607	  ;; Add current point to match data and use keyword face for
1608	  ;; region from start to point.
1609	  (nconc match-data (list (point)))
1610	  (add-to-list 'font-latex-matched-faces 'font-lock-keyword-face)
1611	  (setq end (point))
1612	  (catch 'break
1613	    ;; Walk the list of specs.
1614	    (while spec-list
1615	      (setq spec (pop spec-list)
1616		    error-indicator-pos beg)
1617	      (while (and (not (eobp)) (font-latex-forward-comment)))
1618	      ;; Alternative
1619	      (when (eq spec ?|)
1620		(setq alternative t)
1621		(setq spec (pop spec-list)))
1622	      (cond
1623	       ;; Macros: \foo
1624	       ((eq spec ?\\)
1625		(if (eq (char-after) spec)
1626		    (progn
1627		      (nconc match-data
1628			     (list (point)
1629				   (progn
1630				     (forward-char)
1631				     (if (zerop (skip-syntax-forward "_w"))
1632					 (forward-char) ; Single-char macro.
1633				       (skip-chars-forward "*+"))
1634				     (point))))
1635		      (nconc font-latex-matched-faces (list face))
1636		      (setq end (max end (point)))
1637		      (when alternative (pop spec-list)))
1638		  (setq syntax-error t)
1639		  (throw 'break nil)))
1640	       ;; Mandatory arguments: {...}
1641	       ((eq spec ?{)
1642		(if (and (eq (char-after) spec)
1643			 (setq match-beg (point))
1644			 (font-latex-find-matching-close ?{ ?}))
1645		    (progn
1646		      (nconc match-data (list (1+ match-beg) (1- (point))))
1647		      (nconc font-latex-matched-faces (list face))
1648		      (setq end (max end (1- (point))))
1649		      (when alternative (pop spec-list)))
1650		  (unless alternative
1651		    (setq syntax-error t)
1652		    (when (and match-beg (= match-beg (point)))
1653		      (setq error-indicator-pos match-beg))
1654		    (throw 'break nil))))
1655	       ;; Optional arguments: [...] and others
1656	       ((eq (char-after) spec)
1657		(setq match-beg (point))
1658		(if (font-latex-find-matching-close
1659		     spec (cdr (assq
1660				spec
1661				font-latex-command-with-args-opt-arg-delims)))
1662		    (progn
1663		      (nconc match-data (list (1+ match-beg) (1- (point))))
1664		      (nconc font-latex-matched-faces
1665			     (list 'font-lock-variable-name-face))
1666		      (setq end (max end (1- (point)))))
1667		  (setq syntax-error t
1668			error-indicator-pos match-beg)
1669		  (throw 'break nil))))
1670	      (setq alternative nil)))
1671	  (when (and syntax-error (memq major-mode
1672					font-latex-syntax-error-modes))
1673	    ;; Add the warning face at the front of the list because
1674	    ;; the matcher uses 'append and the face would otherwise
1675	    ;; be overridden by the keyword face.
1676	    (setq match-data (append (list error-indicator-pos
1677					   (1+ error-indicator-pos))
1678				     match-data))
1679	    (push 'font-latex-warning-face font-latex-matched-faces))
1680	  (font-latex-put-multiline-property-maybe beg end)
1681	  (store-match-data match-data)
1682	  (throw 'match t))))))
1683
1684(defun font-latex-extend-region-backwards-command-with-args (beg end)
1685  "Return position to extend region backwards for commands with args.
1686Return nil if region does not have to be extended for a multiline
1687macro to fit in.  The region between the positions BEG and END
1688marks boundaries for searching for macro ends."
1689  (save-excursion
1690    (goto-char end)
1691    (catch 'extend
1692      (while (TeX-search-backward-unescaped "}" beg t)
1693	(let ((macro-start (TeX-find-macro-start
1694			    (max (point-min)
1695				 (- beg font-latex-multiline-boundary)))))
1696	  (when (and macro-start
1697		     (< macro-start beg))
1698	    (throw 'extend macro-start))))
1699      nil)))
1700
1701(defun font-latex-match-command-in-braces (keywords limit)
1702  "Search for command like {\\bfseries fubar} before LIMIT.
1703Sets `match-data' so that:
1704 subexpression 0 is a warning indicator,
1705 subexpression 1 is the keyword, and
1706 subexpression 2 is the rest in the TeX group.
1707Returns nil if no command is found."
1708  (catch 'match
1709    (while (re-search-forward keywords limit t)
1710      (unless (font-latex-faces-present-p '(font-lock-comment-face
1711					    font-latex-verbatim-face)
1712					  (match-beginning 0))
1713	(let ((kbeg (match-beginning 0)) (kend (match-end 1))
1714	      (beg  (match-end 0))
1715	      cbeg cend
1716	      (parse-sexp-ignore-comments t)) ; scan-sexps ignores comments
1717	  (goto-char kbeg)
1718	  (if (not (eq (preceding-char) ?\{))
1719	      ;; Fontify only the keyword (no argument found).
1720	      (progn
1721		(setq cbeg kbeg cend kend)
1722		(goto-char (match-end 0))
1723		(store-match-data (list (point) (point)
1724					(point) (point)
1725					cbeg cend))
1726		(throw 'match t))
1727	    ;; There's an opening bracket
1728	    (save-restriction
1729	      ;; Restrict to LIMIT.
1730	      (narrow-to-region (point-min) limit)
1731	      (forward-char -1)		; Move on the opening bracket
1732	      (if (font-latex-find-matching-close ?\{ ?\})
1733		  (progn
1734		    (font-latex-put-multiline-property-maybe beg (1- (point)))
1735		    (store-match-data (list kbeg kbeg
1736					    kbeg kend
1737					    beg (1- (point)))))
1738		(goto-char kend)
1739		(store-match-data (list (1- kbeg) kbeg
1740					kbeg kend
1741					kend kend)))
1742	      (throw 'match t))))))))
1743
1744(defun font-latex-extend-region-backwards-command-in-braces (beg end)
1745  "Return position to extend region backwards for commands in braces.
1746Return nil if region does not have to be extended for a multiline
1747group to fit in.  The region between the positions BEG and END
1748marks boundaries for searching for group ends."
1749  (save-excursion
1750    (goto-char end)
1751    (catch 'extend
1752      (while (TeX-search-backward-unescaped "}" beg t)
1753	(let ((group-start (TeX-find-opening-brace
1754			    nil (max (point-min)
1755				     (- beg font-latex-multiline-boundary)))))
1756	  (when group-start
1757	    ;; XXX: Actually we'd have to check if any of the
1758	    ;; declaration-type macros can be found right after the
1759	    ;; brace.  If we don't do this (like now) large regions
1760	    ;; may be refontified for no good reason.  For checking
1761	    ;; the built-in `font-latex-match-*' variables for
1762	    ;; declaration-type macros as well as the respective
1763	    ;; user-defined variables could be concatenated.
1764	    (goto-char group-start)
1765	    (when (< group-start beg)
1766	      (throw 'extend group-start)))))
1767      nil)))
1768
1769(defvar font-latex-match-simple-exclude-list
1770  '("-" "," "/" "&" "#" "_" "`" "'" "^" "~" "=" "." "\"")
1771  "List of characters directly after \"\\\" excluded from fontification.
1772Each character is a string.")
1773
1774(defvar font-latex-match-simple-include-list '("@")
1775  "List of characters allowed in a macro for fontification.
1776Each character is a string.  This variable is initialized to
1777\"@\" since internal LaTeX commands are very often redefined in a
1778.tex file and the fontification should work correctly in those
1779cases.")
1780(make-variable-buffer-local 'font-latex-match-simple-include-list)
1781
1782(defun font-latex-match-simple-command (limit)
1783  "Search for command like \\foo before LIMIT."
1784  ;; \s_ matches chars with symbol syntax, \sw chars with word syntax,
1785  ;; \s. chars with punctuation syntax.  We must exclude matches where
1786  ;; the first character after the \ is a reserved character and
1787  ;; should not be fontified (e.g. \, in foo\,bar or \- in foo\-bar).
1788  ;; These characters are stored in
1789  ;; `font-latex-match-simple-exclude-list'.  In docTeX mode, we
1790  ;; remove "_" from this list to get correct fontification for macros
1791  ;; like `\__module_foo:nnn'
1792  (let* ((search (lambda ()
1793		   (TeX-re-search-forward-unescaped
1794		    (concat
1795                     ;; Chars directly after backslash
1796                     "\\\\\\(\\s_\\|\\sw\\|\\s.\\)"
1797                     ;; Start group of the following chars
1798                     "\\(?:["
1799                     ;; a-zA-Z are always allowed:
1800                     "a-zA-Z"
1801                     ;; Additional characters added by AUCTeX styles
1802                     (mapconcat #'identity
1803                                  font-latex-match-simple-include-list
1804                                  "")
1805                     ;; End group
1806                     "]\\)*")
1807		    limit t)))
1808	 (pos (funcall search)))
1809    (while (and pos
1810		(member (match-string 1)
1811			(if (eq major-mode 'doctex-mode)
1812			    (remove "_" font-latex-match-simple-exclude-list)
1813			  font-latex-match-simple-exclude-list)))
1814      (setq pos (funcall search)))
1815    pos))
1816
1817(defun font-latex-match-math-env (limit)
1818  "Match math pattern up to LIMIT.
1819Used for patterns like:
1820\\( F = ma \\)
1821\\=\\[ F = ma \\] but not \\\\=\\[len]"
1822  (catch 'match
1823    (while (re-search-forward "\\(\\\\(\\)\\|\\(\\\\\\[\\)" limit t)
1824      (unless (save-excursion
1825		(goto-char (match-beginning 0))
1826		;; \\[ does not start a math environment
1827		(/= (mod (skip-chars-backward "\\\\") 2) 0))
1828	(let ((beg (match-beginning 0))
1829	      (open-tag (if (match-beginning 1) "\\(" "\\["))
1830	      (close-tag (if (match-beginning 1) "\\)" "\\]")))
1831	  ;; Search for both opening and closing tags in order to be
1832	  ;; able to avoid erroneously matching stuff like "\(foo \(bar\)".
1833	  (if (and (re-search-forward (concat "[^\\]\\(?:\\\\\\\\\\)*\\("
1834					      (regexp-quote open-tag) "\\|"
1835					      (regexp-quote close-tag) "\\)")
1836				      limit 'move)
1837		   (string= (match-string 1) close-tag))
1838	      ;; Found closing tag.
1839	      (progn
1840		(font-latex-put-multiline-property-maybe beg (point))
1841		(store-match-data (list beg beg beg (point))))
1842	    ;; Did not find closing tag.
1843	    (goto-char (+ beg 2))
1844	    (store-match-data (list beg (point) (point) (point))))
1845	  (throw 'match t))))))
1846
1847(defun font-latex-extend-region-backwards-math-env (beg end)
1848  "Return position to extend region backwards for math environments.
1849Return nil if region does not have to be extended for a multiline
1850environment to fit in.  The region between the positions BEG and
1851END marks boundaries for searching for environment ends."
1852  (save-excursion
1853    (goto-char end)
1854    (catch 'extend
1855      (while (re-search-backward "\\(\\\\)\\)\\|\\(\\\\]\\)" beg t)
1856	(when (and (zerop (mod (skip-chars-backward "\\\\") 2))
1857		   (re-search-backward
1858		    (concat "[^\\]\\(?:\\\\\\\\\\)*\\("
1859			    (regexp-quote (if (match-beginning 1) "\\(" "\\["))
1860			    "\\)")
1861		    (- beg font-latex-multiline-boundary) t)
1862		   (goto-char (match-beginning 1))
1863		   (< (point) beg))
1864	  (throw 'extend (point))))
1865      nil)))
1866
1867(defcustom font-latex-math-environments
1868  '("display" "displaymath" "equation" "eqnarray" "gather" "math" "multline"
1869    "align" "alignat" "xalignat" "xxalignat" "flalign")
1870  "List of math environment names for font locking."
1871  :type '(repeat string)
1872  :group 'font-latex)
1873
1874(defun font-latex-match-math-envII (limit)
1875  "Match math patterns up to LIMIT.
1876Used for patterns like:
1877\\begin{equation}
1878 fontified stuff
1879\\end{equation} or
1880\\begin{empheq}[X=Y\\Rightarrow]{alignat=3}
1881 fontified stuff
1882\\end{empheq}
1883The \\begin{equation} incl. arguments in the same line and
1884\\end{equation} are not fontified here."
1885  (when (re-search-forward (concat "\\\\begin[ \t]*{"
1886				   (regexp-opt font-latex-math-environments t)
1887				   ;; Subexpression 2 is used to build
1888				   ;; the \end{<env>} construct below
1889				   "\\(\\*?}\\)"
1890				   ;; Match an optional and possible
1891				   ;; mandatory argument(s) as long as
1892				   ;; they are on the same line with
1893				   ;; no spaces in-between
1894				   "\\(?:\\[[^][]*\\(?:\\[[^][]*\\][^][]*\\)*\\]\\)?"
1895				   "\\(?:{[^}]*}\\)*")
1896			   limit t)
1897    (let ((beg (match-end 0)) end)
1898      (if (re-search-forward (concat "\\\\end[ \t]*{"
1899				     (regexp-quote
1900				      (buffer-substring-no-properties
1901				       (match-beginning 1)
1902				       (match-end 2))))
1903			     ;; XXX: Should this rather be done by
1904			     ;; extending the region to be fontified?
1905			     (+ limit font-latex-multiline-boundary) 'move)
1906	  (setq end (match-beginning 0))
1907	(goto-char beg)
1908	(setq end beg))
1909      (font-latex-put-multiline-property-maybe beg end)
1910      (store-match-data (list beg end))
1911      t)))
1912
1913(defun font-latex-extend-region-backwards-math-envII (beg end)
1914  "Return position to extend region backwards for math environments.
1915Return nil if region does not have to be extended for a multiline
1916environment to fit in.  The region between the positions BEG and
1917END marks boundaries for searching for environment ends."
1918  (save-excursion
1919    (goto-char end)
1920    (catch 'extend
1921      (while (re-search-backward
1922	      (concat "\\\\end[ \t]*{"
1923		      (regexp-opt font-latex-math-environments t)
1924		      "\\*?}") beg t)
1925	(when (and (re-search-backward
1926		    (concat  "\\\\begin[ \t]*{"
1927			     (buffer-substring-no-properties
1928			      (match-beginning 1)
1929			      (match-end 0))
1930			     ;; Match an optional and possible
1931			     ;; mandatory argument(s)
1932			     "\\(?:\\[[^][]*\\(?:\\[[^][]*\\][^][]*\\)*\\]\\)?"
1933			     "\\(?:{[^}]*}\\)*")
1934		    (- beg font-latex-multiline-boundary) t)
1935		   (< (point) beg))
1936	  (throw 'extend (point))))
1937      nil)))
1938
1939(defun font-latex-update-quote-list ()
1940  "Update quote list and regexp if value of `font-latex-quotes' changed."
1941  (unless (eq font-latex-quotes-control font-latex-quotes)
1942    (setq font-latex-quotes-control font-latex-quotes)
1943    (font-latex-quotes-set-internal)
1944    ;; Set order of each entry in `font-latex-quote-list' according to
1945    ;; setting of `font-latex-quotes-internal'.
1946    (let ((tail font-latex-quote-list)
1947	  elt)
1948      (while tail
1949	(setq elt (car tail))
1950	(when (and (> (safe-length elt) 2)
1951		   (not (eq (nth 2 elt) font-latex-quotes-internal)))
1952	  (setcar tail (list (nth 1 elt) (nth 0 elt)
1953			     font-latex-quotes-internal)))
1954	(setq tail (cdr tail))))
1955    (setq font-latex-quote-regexp-beg
1956	  (regexp-opt (mapcar 'car font-latex-quote-list) t))))
1957
1958(defun font-latex-match-quotation (limit)
1959  "Match quote patterns up to LIMIT.
1960Used for patterns like:
1961``this is a normal quote'' and these are multilingual quoted strings:
1962\"< french \"> and \"`german\"' quotes.
1963The quotes << french >> and 8-bit french are used if `font-latex-quotes' is
1964set to french, and >>german<< (and 8-bit) are used if set to german."
1965  (when font-latex-quotes
1966    (font-latex-update-quote-list)
1967    ;; Search for matches.
1968    (catch 'match
1969      (while (TeX-re-search-forward-unescaped
1970	      font-latex-quote-regexp-beg limit t)
1971	(unless (font-latex-faces-present-p '(font-lock-comment-face
1972					      font-latex-verbatim-face
1973					      font-latex-math-face)
1974					    (match-beginning 0))
1975	  (let* ((beg (match-beginning 0))
1976		 (after-beg (match-end 0))
1977		 (opening-quote (match-string 0))
1978		 (closing-quote
1979		  (nth 1 (assoc (if (fboundp 'string-make-multibyte)
1980				    (string-make-multibyte (match-string 0))
1981				  (match-string 0))
1982				font-latex-quote-list)))
1983		 (nest-count 0)
1984		 (point-of-surrender (+ beg font-latex-multiline-boundary)))
1985	    ;; Find closing quote taking nested quotes into account.
1986	    (while (progn
1987		     (re-search-forward
1988		      (concat opening-quote "\\|" closing-quote)
1989		      point-of-surrender 'move)
1990		     (when (and (< (point) point-of-surrender) (not (eobp)))
1991		       (if (string= (match-string 0) opening-quote)
1992			   (setq nest-count (1+ nest-count))
1993			 (when (/= nest-count 0)
1994			   (setq nest-count (1- nest-count)))))))
1995	    ;; If no closing quote was found, set the second match which
1996	    ;; will be marked with warning color, if one was found, set
1997	    ;; the first match which will be marked with string color.
1998	    (if (or (= (point) point-of-surrender) (eobp))
1999		(progn
2000		  (goto-char after-beg)
2001		  (store-match-data (list after-beg after-beg beg after-beg)))
2002	      (font-latex-put-multiline-property-maybe beg (point))
2003	      (store-match-data (list beg (point) (point) (point))))
2004	    (throw 'match t)))))))
2005
2006(defun font-latex-extend-region-backwards-quotation (beg end)
2007  "Return position to extend region backwards for quotations.
2008Return nil if region does not have to be extended for a multiline
2009quotation to fit in.  The region between the positions BEG and
2010END marks boundaries for searching for quotation ends."
2011  (if font-latex-quotes
2012      (progn
2013	(font-latex-update-quote-list)
2014	(let ((regexp-end (regexp-opt (mapcar 'cadr font-latex-quote-list) t)))
2015	  (save-excursion
2016	    (goto-char end)
2017	    (catch 'extend
2018	      (while (re-search-backward regexp-end beg t)
2019		(let ((closing-quote (match-string 0))
2020		      (nest-count 0)
2021		      (point-of-surrender (- beg font-latex-multiline-boundary))
2022		      opening-quote)
2023		  (catch 'found
2024		    (dolist (elt font-latex-quote-list)
2025		      (when (string= (cadr elt) closing-quote)
2026			(setq opening-quote (car elt))
2027			(throw 'found nil))))
2028		  ;; Find opening quote taking nested quotes into account.
2029		  (while (progn
2030			   (re-search-backward (concat opening-quote "\\|"
2031						       closing-quote)
2032					       point-of-surrender 'move)
2033			   (when (and (> (point) point-of-surrender)
2034				      (not (bobp)))
2035			     (if (string= (match-string 0) closing-quote)
2036				 (setq nest-count (1+ nest-count))
2037			       (when (/= nest-count 0)
2038				 (setq nest-count (1- nest-count)))))))
2039		  (when (< (point) beg)
2040		    (throw 'extend (point)))))
2041	      nil))))
2042    nil))
2043
2044(defun font-latex-match-script (limit)
2045  "Match subscript and superscript patterns up to LIMIT."
2046  (when (and font-latex-fontify-script
2047	     (re-search-forward "[_^] *\\([^\n\\{}]\\|\
2048\\\\\\([a-zA-Z@]+\\|[^ \t\n]\\)\\|\\({\\)\\)" limit t))
2049    (if (and (not (memq font-latex-fontify-script '(multi-level invisible)))
2050	     (font-latex-faces-present-p '(font-latex-subscript-face
2051					   font-latex-superscript-face)))
2052	;; Apply subscript and superscript highlighting only once (in case
2053	;; font-latex-fontify-script is not 'multi-level) in order to prevent
2054	;; the font size becoming too small.  We set an empty match to do that.
2055	(let ((point (point)))
2056	  (store-match-data (list point point point point)))
2057      (when (match-end 3)
2058	(let ((beg (match-beginning 3))
2059	      (end (TeX-find-closing-brace
2060		    ;; Don't match groups spanning more than one line
2061		    ;; in order to avoid visually wrong indentation in
2062		    ;; subsequent lines.
2063		    nil (line-end-position))))
2064	  (store-match-data (if end
2065				(list (match-beginning 0) end beg end)
2066			      (list beg beg beg beg))))))
2067    t))
2068
2069(defun font-latex-match-script-chars (limit)
2070  "Match subscript and superscript chars up to LIMIT."
2071  (and (re-search-forward "[^_^]\\([_^]\\)" limit t)
2072       (let ((pos (match-beginning 1)))
2073	 (and (font-latex-faces-present-p 'font-latex-math-face pos)
2074	      (not (font-latex-faces-present-p '(font-lock-constant-face
2075						 font-lock-builtin-face
2076						 font-lock-comment-face
2077						 font-latex-verbatim-face) pos))
2078	      ;; Check for backslash quoting
2079	      (not (let ((odd nil)
2080			 (pos pos))
2081		     (while (eq (char-before pos) ?\\)
2082		       (setq pos (1- pos) odd (not odd)))
2083		     odd))))))
2084
2085(defun font-latex--get-script-props (pos script-type)
2086  (let* ((old-raise (or (plist-get (get-text-property pos 'display) 'raise) 0.0))
2087	 (new-level (1+ (or (get-text-property pos 'script-level) 0)))
2088	 (disp-props (copy-sequence (cl-case script-type
2089				      (:super (cdr font-latex-script-display))
2090				      (:sub   (car font-latex-script-display)))))
2091	 (new-disp-props (let ((raise (plist-get disp-props 'raise))
2092			       (nl new-level))
2093			   (if raise
2094			       ;; This polynom approximates that the factor
2095			       ;; which is multiplied with raise is 1 for nl=1,
2096			       ;; 0.8 for nl=2, 0.64 for nl=3, etc. (so always
2097			       ;; about 80% of the previous value).
2098			       (plist-put disp-props 'raise
2099					  (+ old-raise
2100					     (* raise
2101						(+ 1.1965254857142873
2102						   (* nl -0.21841226666666758)
2103						   (* nl nl 0.012018514285714385)))))
2104			     disp-props))))
2105    `(face ,(if (<= new-level font-latex-fontify-script-max-level)
2106		(cl-case script-type
2107		  (:super 'font-latex-superscript-face)
2108		  (:sub   'font-latex-subscript-face))
2109	      nil)
2110	   script-level ,new-level
2111	   display ,new-disp-props)))
2112
2113;; Copy and adaption of `tex-font-lock-suscript' from tex-mode.el in
2114;; GNU Emacs on 2004-07-07.
2115(defun font-latex-script (pos)
2116  "Return face and display spec for subscript and superscript content."
2117  (when (and (font-latex-faces-present-p 'font-latex-math-face pos)
2118	     (not (font-latex-faces-present-p '(font-lock-constant-face
2119						font-lock-builtin-face
2120						font-lock-comment-face
2121						font-latex-verbatim-face) pos))
2122	     ;; Check for backslash quoting
2123	     (not (let ((odd nil)
2124			(pos pos))
2125		    (while (eq (char-before pos) ?\\)
2126		      (setq pos (1- pos) odd (not odd)))
2127		    odd)))
2128    ;; Adding other text properties than `face' is supported by
2129    ;; `font-lock-apply-highlight' in CVS Emacsen since 2001-10-28.
2130    ;; With the introduction of this feature the variable
2131    ;; `font-lock-extra-managed-props' was introduced and serves here
2132    ;; for feature checking.
2133    (let ((extra-props-flag (boundp 'font-lock-extra-managed-props)))
2134      (if (eq (char-after pos) ?_)
2135	  (if extra-props-flag
2136	      (font-latex--get-script-props pos :sub)
2137	    'font-latex-subscript-face)
2138	(if extra-props-flag
2139	    (font-latex--get-script-props pos :super)
2140	  'font-latex-superscript-face)))))
2141
2142(defun font-latex-script-char (pos)
2143  "Return face and display spec for subscript and superscript character at POS."
2144  (if (boundp 'font-lock-extra-managed-props)
2145      `(face font-latex-script-char-face
2146	     ,@(when (eq font-latex-fontify-script 'invisible)
2147		 '(invisible t)))
2148    'font-latex-script-char-face))
2149
2150;;; docTeX
2151
2152(defvar font-latex-doctex-preprocessor-face
2153  'font-latex-doctex-preprocessor-face
2154  "Face used to highlight preprocessor directives in docTeX mode.")
2155
2156(defface font-latex-doctex-preprocessor-face
2157  '((t (:inherit (font-latex-doctex-documentation-face
2158		  font-lock-builtin-face ; Emacs 21 does not provide
2159					; the preprocessor face.
2160		  font-lock-preprocessor-face))))
2161  "Face used to highlight preprocessor directives in docTeX mode."
2162  :group 'font-latex-highlighting-faces)
2163
2164(defvar font-latex-doctex-documentation-face
2165  'font-latex-doctex-documentation-face
2166  "Face used to highlight the documentation in docTeX mode.")
2167
2168(defface font-latex-doctex-documentation-face
2169  '((((class mono)) (:inverse-video t))
2170    (((class grayscale) (background dark)) (:background "#333"))
2171    (((class color) (background dark)) (:background "#333"))
2172    (t (:background "#eeeeee")))
2173  "Face used to highlight the documentation parts in docTeX mode."
2174  :group 'font-latex-highlighting-faces)
2175
2176(defvar font-latex-doctex-keywords
2177  (append font-latex-keywords-2
2178	  '(("^%<[^>]*>" (0 font-latex-doctex-preprocessor-face t)))))
2179
2180;; Copy and adaptation of `doctex-font-lock-^^A' in `tex-mode.el' of
2181;; CVS Emacs (March 2004)
2182(defun font-latex-doctex-^^A ()
2183  (if (eq (char-after (line-beginning-position)) ?\%)
2184      (progn
2185	(put-text-property
2186	 (1- (match-beginning 1)) (match-beginning 1) 'syntax-table
2187	 (if (= (1+ (line-beginning-position)) (match-beginning 1))
2188	     ;; The `%' is a single-char comment, which Emacs
2189	     ;; syntax-table can't deal with.  We could turn it
2190	     ;; into a non-comment, or use `\n%' or `%^' as the comment.
2191	     ;; Instead, we include it in the ^^A comment.
2192	     (eval-when-compile (string-to-syntax "< b"))
2193	   (eval-when-compile (string-to-syntax ">"))))
2194	(let ((end (line-end-position)))
2195	  (if (< end (point-max))
2196	      (put-text-property end (1+ end) 'syntax-table
2197				    (eval-when-compile
2198				      (string-to-syntax "> b")))))
2199	(eval-when-compile (string-to-syntax "< b")))))
2200
2201;; Copy and adaptation of `doctex-font-lock-syntactic-face-function'
2202;; in `tex-mode.el' of CVS Emacs (March 2004)
2203(defun font-latex-doctex-syntactic-face-function (state)
2204  ;; Mark docTeX documentation, which is parsed as a style A comment
2205  ;; starting in column 0.
2206  (if (or (nth 3 state) (nth 7 state)
2207	  (not (memq (char-before (nth 8 state))
2208		     '(?\n nil))))
2209      ;; Anything else is just as for LaTeX.
2210      (font-latex-syntactic-face-function state)
2211    font-latex-doctex-documentation-face))
2212
2213
2214;;; Installation in non-AUCTeX LaTeX mode
2215
2216;; Here used to be some code which tried to magically make things work and
2217;; thereby broke other stuff.  If you want to use font-latex with stock
2218;; latex-mode, then please just add `font-latex-setup' to `latex-mode-hook'
2219;; yourself.
2220
2221;;; Byte-compilation of generated functions
2222
2223(when (byte-code-function-p
2224       (symbol-function 'font-latex-make-built-in-keywords))
2225  (dolist (elt font-latex-built-in-keyword-classes)
2226    (let ((name (nth 0 elt)))
2227      (byte-compile (intern (concat "font-latex-match-" name)))
2228      (byte-compile (intern (concat "font-latex-match-" name "-make"))))))
2229
2230
2231;; Provide ourselves:
2232(provide 'font-latex)
2233
2234;; Local Variables:
2235;; coding: utf-8
2236;; End:
2237
2238;;; font-latex.el ends here
2239