]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
e80fcbf3339ae68c6a92c0ea5ebe5127229cf845
[lyx.git] / src / LaTeXFeatures.cpp
1 /**
2  * \file LaTeXFeatures.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author José Matos
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author Jürgen Vigna
10  * \author André Pönitz
11  *
12  * Full author contact details are available in file CREDITS.
13  */
14
15 #include <config.h>
16
17 #include "LaTeXFeatures.h"
18
19 #include "Buffer.h"
20 #include "BufferParams.h"
21 #include "ColorSet.h"
22 #include "Converter.h"
23 #include "Encoding.h"
24 #include "Floating.h"
25 #include "FloatList.h"
26 #include "Language.h"
27 #include "LaTeXFonts.h"
28 #include "LaTeXPackages.h"
29 #include "Layout.h"
30 #include "Lexer.h"
31 #include "LyXRC.h"
32 #include "TextClass.h"
33 #include "TexRow.h"
34 #include "texstream.h"
35
36 #include "insets/InsetLayout.h"
37
38 #include "support/debug.h"
39 #include "support/docstream.h"
40 #include "support/FileName.h"
41 #include "support/filetools.h"
42 #include "support/gettext.h"
43 #include "support/lstrings.h"
44 #include "support/regex.h"
45
46 #include <algorithm>
47
48
49 using namespace std;
50 using namespace lyx::support;
51
52
53 namespace lyx {
54
55 /////////////////////////////////////////////////////////////////////
56 //
57 // Strings
58 //
59 /////////////////////////////////////////////////////////////////////
60
61 //\NeedsTeXFormat{LaTeX2e}
62 //\ProvidesPackage{lyx}[1996/01/11 LLE v0.2 (LyX LaTeX Extensions)]
63 //\message{LyX LaTeX Extensions (LLE v0.2) of 11-Jan-1996.}
64
65 static docstring const lyx_def = from_ascii(
66         "{%\n  L\\kern-.1667em\\lower.25em\\hbox{Y}\\kern-.125emX\\@}");
67
68 static docstring const noun_def = from_ascii(
69         "\\newcommand{\\noun}[1]{\\textsc{#1}}");
70
71 static docstring const lyxarrow_def = from_ascii(
72         "\\DeclareRobustCommand*{\\lyxarrow}{%\n"
73         "\\@ifstar\n"
74         "{\\leavevmode\\,$\\triangleleft$\\,\\allowbreak}\n"
75         "{\\leavevmode\\,$\\triangleright$\\,\\allowbreak}}");
76
77 // ZERO WIDTH SPACE (ZWSP) is actually not a space character
78 // but marks a line break opportunity. Several commands provide a
79 // line break opportunity. They differ in side-effects:
80 // \allowbreak prevents hyphenation after hyphen or dash + ZWSP
81 // \linebreak[<n>] takes an optional argument denoting "urgency".
82 // The \LyXZeroWidthSpace wrapper allows customization in the preamble.
83 static docstring const lyxZWSP_def = from_ascii(
84         "\\newcommand*\\LyXZeroWidthSpace{\\hspace{0pt}}");
85
86 // for quotes without babel. This does not give perfect results, but
87 // anybody serious about non-english quotes should use babel (JMarc).
88
89 static docstring const quotedblbase_def = from_ascii(
90         "\\ProvideTextCommandDefault{\\quotedblbase}{%\n"
91         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquotedblright}%\n"
92         "  \\penalty10000\\hskip0em\\relax%\n"
93         "}");
94
95 static docstring const quotesinglbase_def = from_ascii(
96         "\\ProvideTextCommandDefault{\\quotesinglbase}{%\n"
97         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquoteright}%\n"
98         "  \\penalty10000\\hskip0em\\relax%\n"
99         "}");
100
101 static docstring const guillemotleft_def = from_ascii(
102         "\\ProvideTextCommandDefault{\\guillemotleft}{%\n"
103         "  {\\usefont{U}{lasy}{m}{n}\\char'50\\kern-.15em\\char'50}%\n"
104         "\\penalty10000\\hskip0pt\\relax%\n"
105         "}");
106
107 static docstring const guillemotright_def = from_ascii(
108         "\\ProvideTextCommandDefault{\\guillemotright}{%\n"
109         "  \\penalty10000\\hskip0pt%\n"
110         "  {\\usefont{U}{lasy}{m}{n}\\char'51\\kern-.15em\\char'51}%\n"
111         "}");
112
113 static docstring const guilsinglleft_def = from_ascii(
114         "\\ProvideTextCommandDefault{\\guilsinglleft}{%\n"
115         "  {\\usefont{U}{lasy}{m}{n}\\char'50}%\n"
116         "  \\penalty10000\\hskip0pt\\relax%\n"
117         "}");
118
119 static docstring const guilsinglright_def = from_ascii(
120         "\\ProvideTextCommandDefault{\\guilsinglright}{%\n"
121         "  \\penalty10000\\hskip0pt%\n"
122         "  {\\usefont{U}{lasy}{m}{n}\\char'51}%\n"
123         "}");
124
125 static docstring const textquotedbl_def = from_ascii(
126         "\\DeclareTextSymbolDefault{\\textquotedbl}{T1}");
127
128 static docstring const textquotedblp_xetex_def = from_ascii(
129         "\\providecommand\\textquotedblplain{%\n"
130         "  \\bgroup\\addfontfeatures{Mapping=}\\char34\\egroup}");
131
132 static docstring const textquotedblp_luatex_def = from_ascii(
133         "\\providecommand\\textquotedblplain{%\n"
134         "  \\bgroup\\addfontfeatures{RawFeature=-tlig}\\char34\\egroup}");
135
136 static docstring const textquotesinglep_xetex_def = from_ascii(
137         "\\providecommand\\textquotesingleplain{%\n"
138         "  \\bgroup\\addfontfeatures{Mapping=}\\char39\\egroup}");
139
140 static docstring const textquotesinglep_luatex_def = from_ascii(
141         "\\providecommand\\textquotesingleplain{%\n"
142         "  \\bgroup\\addfontfeatures{RawFeature=-tlig}\\char39\\egroup}");
143
144 static docstring const paragraphleftindent_def = from_ascii(
145         "\\newenvironment{LyXParagraphLeftIndent}[1]%\n"
146         "{\n"
147         "  \\begin{list}{}{%\n"
148         "    \\setlength{\\topsep}{0pt}%\n"
149         "    \\addtolength{\\leftmargin}{#1}\n"
150 // ho hum, yet more things commented out with no hint as to why they
151 // weren't just removed
152 //      "%%    \\addtolength{\\leftmargin}{#1\\textwidth}\n"
153 //      "%%    \\setlength{\\textwidth}{#2\\textwidth}\n"
154 //      "%%    \\setlength\\listparindent\\parindent%\n"
155 //      "%%    \\setlength\\itemindent\\parindent%\n"
156         "    \\setlength{\\parsep}{0pt plus 1pt}%\n"
157         "  }\n"
158         "  \\item[]\n"
159         "}\n"
160         "{\\end{list}}\n");
161
162 static docstring const floatingfootnote_def = from_ascii(
163         "%% Special footnote code from the package 'stblftnt.sty'\n"
164         "%% Author: Robin Fairbairns -- Last revised Dec 13 1996\n"
165         "\\let\\SF@@footnote\\footnote\n"
166         "\\def\\footnote{\\ifx\\protect\\@typeset@protect\n"
167         "    \\expandafter\\SF@@footnote\n"
168         "  \\else\n"
169         "    \\expandafter\\SF@gobble@opt\n"
170         "  \\fi\n"
171         "}\n"
172         "\\expandafter\\def\\csname SF@gobble@opt \\endcsname{\\@ifnextchar[%]\n"
173         "  \\SF@gobble@twobracket\n"
174         "  \\@gobble\n"
175         "}\n"
176         "\\edef\\SF@gobble@opt{\\noexpand\\protect\n"
177         "  \\expandafter\\noexpand\\csname SF@gobble@opt \\endcsname}\n"
178         "\\def\\SF@gobble@twobracket[#1]#2{}\n");
179
180 static docstring const binom_def = from_ascii(
181         "%% Binom macro for standard LaTeX users\n"
182         "\\newcommand{\\binom}[2]{{#1 \\choose #2}}\n");
183
184 static docstring const mathcircumflex_def = from_ascii(
185         "%% For printing a cirumflex inside a formula\n"
186         "\\newcommand{\\mathcircumflex}[0]{\\mbox{\\^{}}}\n");
187
188 static docstring const tabularnewline_def = from_ascii(
189         "%% Because html converters don't know tabularnewline\n"
190         "\\providecommand{\\tabularnewline}{\\\\}\n");
191
192 static docstring const lyxgreyedout_def = from_ascii(
193         "%% The greyedout annotation environment\n"
194         "\\newenvironment{lyxgreyedout}\n"
195         "  {\\textcolor{note_fontcolor}\\bgroup\\ignorespaces}\n"
196         "  {\\ignorespacesafterend\\egroup}\n");
197
198 static docstring const lyxgreyedout_rtl_def = from_ascii(
199         "%% The greyedout annotation environment (with RTL support)\n"
200         "\\NewEnviron{lyxgreyedout}{%\n"
201         "\\if@rl%\n"
202         "\\everypar{\\textcolor{note_fontcolor}\\beginL\\ignorespaces}%\n"
203         "\\BODY\\everypar{\\ignorespacesafterend\\endL}\n"
204         "\\else%\n"
205         "\\textcolor{note_fontcolor}\\bgroup\\ignorespaces%\n"
206         "\\BODY\\ignorespacesafterend\\egroup\n"
207         "\\fi}\n");
208
209 static docstring const lyxgreyedout_luartl_def = from_ascii(
210         "%% The greyedout annotation environment (with RTL support)\n"
211         "\\NewEnviron{lyxgreyedout}{%\n"
212         "\\if@RTL%\n"
213         "\\everypar{\\color{note_fontcolor}\\pardir TRT \\textdir TRT\\ignorespaces}%\n"
214         "\\BODY\\everypar{\\ignorespacesafterend}\n"
215         "\\else%\n"
216         "\\textcolor{note_fontcolor}\\bgroup\\ignorespaces%\n"
217         "\\BODY\\ignorespacesafterend\\egroup\n"
218         "\\fi}\n");
219
220 static docstring const lyxgreyedout_luartl_babel_def = from_ascii(
221         "%% The greyedout annotation environment (with RTL support)\n"
222         "\\NewEnviron{lyxgreyedout}{%\n"
223         "\\if@rl%\n"
224         "\\everypar{\\color{note_fontcolor}\\pardir TRT \\textdir TRT\\ignorespaces}%\n"
225         "\\BODY\\everypar{\\ignorespacesafterend}\n"
226         "\\else%\n"
227         "\\textcolor{note_fontcolor}\\bgroup\\ignorespaces%\n"
228         "\\BODY\\ignorespacesafterend\\egroup\n"
229         "\\fi}\n");
230
231 // We want to omit the file extension for includegraphics, but this does not
232 // work when the filename contains other dots.
233 // Idea from http://www.tex.ac.uk/cgi-bin/texfaq2html?label=unkgrfextn
234 static docstring const lyxdot_def = from_ascii(
235         "%% A simple dot to overcome graphicx limitations\n"
236         "\\newcommand{\\lyxdot}{.}\n");
237
238 static docstring const changetracking_dvipost_def = from_ascii(
239         "%% Change tracking with dvipost\n"
240         "\\dvipostlayout\n"
241         "\\dvipost{osstart color push Red}\n"
242         "\\dvipost{osend color pop}\n"
243         "\\dvipost{cbstart color push Blue}\n"
244         "\\dvipost{cbrule 0pt}\n"
245         "\\dvipost{cbend color pop}\n"
246         "\\DeclareRobustCommand{\\lyxadded}[4][]{\\changestart#4\\changeend}\n"
247         "\\DeclareRobustCommand{\\lyxdeleted}[4][]{%\n"
248         "\\changestart\\overstrikeon#4\\overstrikeoff\\changeend}\n");
249
250 static docstring const changetracking_dvipost_cb_def = from_ascii(
251         "%% Change tracking with dvipost\n"
252         "\\dvipostlayout\n"
253         "\\dvipost{osstart color push Red}\n"
254         "\\dvipost{osend color pop}\n"
255         "\\dvipost{cbstart color push Blue}\n"
256         "\\dvipost{cbend color pop}\n"
257         "\\DeclareRobustCommand{\\lyxadded}[4][]{\\changestart#4\\changeend}\n"
258         "\\DeclareRobustCommand{\\lyxdeleted}[4][]{%\n"
259         "\\changestart\\overstrikeon#4\\overstrikeoff\\changeend}\n");
260
261 static docstring const changetracking_xcolor_ulem_base_def = from_ascii(
262         "%% Change tracking with ulem and xcolor: base macros\n"
263         "\\DeclareRobustCommand{\\mklyxadded}[1]{\\bgroup\\color{lyxadded}{}#1\\egroup}\n"
264         "\\DeclareRobustCommand{\\mklyxdeleted}[1]{\\bgroup\\color{lyxdeleted}\\mklyxsout{#1}\\egroup}\n"
265         "\\DeclareRobustCommand{\\mklyxsout}[1]{\\ifx\\\\#1\\else\\sout{#1}\\fi}\n");
266
267 static docstring const changetracking_xcolor_ulem_def = from_ascii(
268         "%% Change tracking with ulem and xcolor: ct markup\n"
269         "\\DeclareRobustCommand{\\lyxadded}[4][]{\\mklyxadded{#4}}\n"
270         "\\DeclareRobustCommand{\\lyxdeleted}[4][]{\\mklyxdeleted{#4}}\n");
271
272 static docstring const changetracking_xcolor_ulem_cb_def = from_ascii(
273         "%% Change tracking with ulem, xcolor and changebars: ct markup\n"
274         "\\DeclareRobustCommand{\\lyxadded}[4][]{%\n"
275         "    \\protect\\cbstart\\mklyxadded{#4}%\n"
276         "    \\protect\\cbend%\n"
277         "}\n"
278         "\\DeclareRobustCommand{\\lyxdeleted}[4][]{%\n"
279         "    \\protect\\cbstart\\mklyxdeleted{#4}%\n"
280         "    \\protect\\cbend%\n"
281         "}\n");
282
283 static docstring const changetracking_xcolor_ulem_hyperref_def = from_ascii(
284         "%% Change tracking with ulem, xcolor, and hyperref: ct markup\n"
285         "\\DeclareRobustCommand{\\lyxadded}[4][]{\\texorpdfstring{\\mklyxadded{#4}}{#4}}\n"
286         "\\DeclareRobustCommand{\\lyxdeleted}[4][]{\\texorpdfstring{\\mklyxdeleted{#4}}{}}\n");
287
288 static docstring const changetracking_xcolor_ulem_hyperref_cb_def = from_ascii(
289         "%% Change tracking with ulem, xcolor, hyperref and changebars: ct markup\n"
290         "\\DeclareRobustCommand{\\lyxadded}[4][]{%\n"
291         "    \\texorpdfstring{\\protect\\cbstart\\mklyxadded{#4}%\n"
292         "    \\protect\\cbend}{#4}%\n"
293         "}\n"
294         "\\DeclareRobustCommand{\\lyxdeleted}[4][]{%\n"
295         "    \\texorpdfstring{\\protect\\cbstart\\mklyxdeleted{#4}%\n"
296         "    \\protect\\cbend}{}%\n"
297         "}\n");
298
299 static docstring const changetracking_tikz_object_sout_def = from_ascii(
300         "%% Strike out display math and text objects with tikz\n"
301         "\\usetikzlibrary{calc}\n"
302         "\\newcommand{\\lyxobjectsout}[1]{%\n"
303         "  \\bgroup%\n"
304         "  \\color{lyxdeleted}%\n"
305         "  \\tikz{\n"
306         "    \\node[inner sep=0pt,outer sep=0pt](lyxdelobj){#1};\n"
307         "    \\draw($(lyxdelobj.south west)+(2em,.5em)$)--($(lyxdelobj.north east)-(2em,.5em)$);\n"
308         "  }\n"
309         "  \\egroup%\n"
310         "}\n");
311
312 static docstring const changetracking_xcolor_ulem_object_def = from_ascii(
313         "%% Change tracking with ulem and xcolor: ct markup for complex objects\n"
314         "\\DeclareRobustCommand{\\lyxobjdeleted}[4][]{\\lyxobjectsout{#4}}\n"
315         "\\DeclareRobustCommand{\\lyxdisplayobjdeleted}[4][]{\\lyxobjectsout{\\parbox{\\linewidth}{#4}}}\n"
316         "\\DeclareRobustCommand{\\lyxudisplayobjdeleted}[4][]{%\n"
317         "     \\raisebox{-\\belowdisplayshortskip}{%\n"
318         "                \\lyxobjectsout{\\parbox[b]{\\linewidth}{#4}}}%\n"
319         "}\n");
320
321 static docstring const changetracking_xcolor_ulem_cb_object_def = from_ascii(
322         "%% Change tracking with ulem, xcolor and changebars:ct markup for complex objects\n"
323         "\\DeclareRobustCommand{\\lyxobjdeleted}[4][]{%\n"
324         "    \\protect\\cbstart\\lyxobjectsout{#4}%\n"
325         "    \\protect\\cbend%\n"
326         "}\n"
327         "\\DeclareRobustCommand{\\lyxdisplayobjdeleted}[4][]{%\n"
328         "    \\protect\\cbstart%\n"
329         "    \\lyxobjectsout{\\parbox{\\linewidth}{#4}}%\n"
330         "    \\protect\\cbend%\n"
331         "}\n"
332         "\\DeclareRobustCommand{\\lyxudisplayobjdeleted}[4][]{%\n"
333         "    \\raisebox{-\\belowdisplayshortskip}{%\n"
334         "               \\protect\\cbstart%\n"
335         "               \\lyxobjectsout{\\parbox[b]{\\linewidth}{#4}}}%\n"
336         "               \\protect\\cbend%\n"
337         "}\n");
338
339 static docstring const changetracking_xcolor_ulem_hyperref_object_def = from_ascii(
340         "%% Change tracking with ulem, xcolor, and hyperref: ct markup for complex objects\n"
341         "\\DeclareRobustCommand{\\lyxobjdeleted}[4][]{\\texorpdfstring{\\lyxobjectsout{#4}}{}}\n"
342         "\\DeclareRobustCommand{\\lyxdisplayobjdeleted}[4][]{%\n"
343         "     \\texorpdfstring{\\lyxobjectsout{\\parbox{\\linewidth}{#4}}}{}%\n"
344         "}\n"
345         "\\DeclareRobustCommand{\\lyxudisplayobjdeleted}[4][]{%\n"
346         "     \\texorpdfstring{\\raisebox{-\\belowdisplayshortskip}{%\n"
347         "                \\lyxobjectsout{\\parbox[b]{\\linewidth}{#4}}}}{}%\n"
348         "}\n");
349
350 static docstring const changetracking_xcolor_ulem_hyperref_cb_object_def = from_ascii(
351         "%% Change tracking with ulem, xcolor, hyperref and changebars:\n"
352         "%% ct markup for complex objects\n"
353         "\\DeclareRobustCommand{\\lyxobjdeleted}[4][]{%\n"
354         "    \\texorpdfstring{\\protect\\cbstart\\lyxobjectsout{#4}%\n"
355         "    \\protect\\cbend}{}%\n"
356         "}\n"
357         "\\DeclareRobustCommand{\\lyxdisplayobjdeleted}[4][]{%\n"
358         "     \\texorpdfstring{\\protect\\cbstart%\n"
359         "        \\lyxobjectsout{\\parbox{\\linewidth}{#4}}%\n"
360         "        \\protect\\cbend%\n"
361         "      }{}%\n"
362         "}\n"
363         "\\DeclareRobustCommand{\\lyxudisplayobjdeleted}[4][]{%\n"
364         "     \\texorpdfstring{\\protect\\cbstart%\n"
365         "        \\raisebox{-\\belowdisplayshortskip}{%\n"
366         "                   \\lyxobjectsout{\\parbox[b]{\\linewidth}{#4}}%\n"
367         "        }%\n"
368         "     }{}%\n"
369         "}\n");
370
371 static docstring const changetracking_none_def = from_ascii(
372         "%% Change tracking: Disable markup in output\n"
373         "\\newcommand{\\lyxadded}[3]{#3}\n"
374         "\\newcommand{\\lyxdeleted}[3]{}\n"
375         "\\newcommand{\\lyxobjdeleted}[3]{}\n"
376         "\\newcommand{\\lyxdisplayobjdeleted}[3]{}\n"
377         "\\newcommand{\\lyxudisplayobjdeleted}[3]{}\n");
378
379 static docstring const textgreek_LGR_def = from_ascii(
380         "\\DeclareFontEncoding{LGR}{}{}\n");
381 static docstring const textgreek_def = from_ascii(
382         "\\DeclareRobustCommand{\\greektext}{%\n"
383         "  \\fontencoding{LGR}\\selectfont\\def\\encodingdefault{LGR}}\n"
384         "\\DeclareRobustCommand{\\textgreek}[1]{\\leavevmode{\\greektext #1}}\n");
385
386 static docstring const textcyr_T2A_def = from_ascii(
387         "\\InputIfFileExists{t2aenc.def}{}{%\n"
388         "  \\errmessage{File `t2aenc.def' not found: Cyrillic script not supported}}\n");
389 static docstring const textcyr_def = from_ascii(
390         "\\DeclareRobustCommand{\\cyrtext}{%\n"
391         "  \\fontencoding{T2A}\\selectfont\\def\\encodingdefault{T2A}}\n"
392         "\\DeclareRobustCommand{\\textcyrillic}[1]{\\leavevmode{\\cyrtext #1}}\n");
393
394 static docstring const lyxmathsym_def = from_ascii(
395         "\\newcommand{\\lyxmathsym}[1]{\\ifmmode\\begingroup\\def\\b@ld{bold}\n"
396         "  \\text{\\ifx\\math@version\\b@ld\\bfseries\\fi#1}\\endgroup\\else#1\\fi}\n");
397
398 static docstring const papersizedvi_def = from_ascii(
399         "\\special{papersize=\\the\\paperwidth,\\the\\paperheight}\n");
400
401 static docstring const papersizepdf_def = from_ascii(
402         "\\pdfpageheight\\paperheight\n"
403         "\\pdfpagewidth\\paperwidth\n");
404
405 static docstring const papersizepdflua_def = from_ascii(
406         "% Backwards compatibility for LuaTeX < 0.90\n"
407         "\\@ifundefined{pageheight}{\\let\\pageheight\\pdfpageheight}{}\n"
408         "\\@ifundefined{pagewidth}{\\let\\pagewidth\\pdfpagewidth}{}\n"
409         "\\pageheight\\paperheight\n"
410         "\\pagewidth\\paperwidth\n");
411
412 static docstring const cedilla_def = from_ascii(
413         "\\newcommand{\\docedilla}[2]{\\underaccent{#1\\mathchar'30}{#2}}\n"
414         "\\newcommand{\\cedilla}[1]{\\mathpalette\\docedilla{#1}}\n");
415
416 static docstring const subring_def = from_ascii(
417         "\\newcommand{\\dosubring}[2]{\\underaccent{#1\\mathchar'27}{#2}}\n"
418         "\\newcommand{\\subring}[1]{\\mathpalette\\dosubring{#1}}\n");
419
420 static docstring const subdot_def = from_ascii(
421         "\\newcommand{\\dosubdot}[2]{\\underaccent{#1.}{#2}}\n"
422         "\\newcommand{\\subdot}[1]{\\mathpalette\\dosubdot{#1}}\n");
423
424 static docstring const subhat_def = from_ascii(
425         "\\newcommand{\\dosubhat}[2]{\\underaccent{#1\\mathchar'136}{#2}}\n"
426         "\\newcommand{\\subhat}[1]{\\mathpalette\\dosubhat{#1}}\n");
427
428 static docstring const subtilde_def = from_ascii(
429         "\\newcommand{\\dosubtilde}[2]{\\underaccent{#1\\mathchar'176}{#2}}\n"
430         "\\newcommand{\\subtilde}[1]{\\mathpalette\\dosubtilde{#1}}\n");
431
432 static docstring const dacute_def = from_ascii(
433         "\\DeclareMathAccent{\\dacute}{\\mathalpha}{operators}{'175}\n");
434
435 static docstring const tipasymb_def = from_ascii(
436         "\\DeclareFontEncoding{T3}{}{}\n"
437         "\\DeclareSymbolFont{tipasymb}{T3}{cmr}{m}{n}\n");
438
439 static docstring const dgrave_def = from_ascii(
440         "\\DeclareMathAccent{\\dgrave}{\\mathord}{tipasymb}{'15}\n");
441
442 static docstring const rcap_def = from_ascii(
443         "\\DeclareMathAccent{\\rcap}{\\mathord}{tipasymb}{'20}\n");
444
445 static docstring const ogonek_def = from_ascii(
446         "\\newcommand{\\doogonek}[2]{\\setbox0=\\hbox{$#1#2$}\\underaccent{#1\\mkern-6mu\n"
447         "  \\ifx#2O\\hskip0.5\\wd0\\else\\ifx#2U\\hskip0.5\\wd0\\else\\hskip\\wd0\\fi\\fi\n"
448         "  \\ifx#2o\\mkern-2mu\\else\\ifx#2e\\mkern-1mu\\fi\\fi\n"
449         "  \\mathchar\"0\\hexnumber@\\symtipasymb0C}{#2}}\n"
450         "\\newcommand{\\ogonek}[1]{\\mathpalette\\doogonek{#1}}\n");
451
452 static docstring const lyxaccent_def = from_ascii(
453         "%% custom text accent \\LyxTextAccent[<rise value (length)>]{<accent>}{<base>}\n"
454         "\\newcommand*{\\LyxTextAccent}[3][0ex]{%\n"
455         "  \\hmode@bgroup\\ooalign{\\null#3\\crcr\\hidewidth\n"
456         "  \\raise#1\\hbox{#2}\\hidewidth}\\egroup}\n"
457         "%% select a font size smaller than the current font size:\n"
458         "\\newcommand{\\LyxAccentSize}[1][\\sf@size]{%\n"
459         "  \\check@mathfonts\\fontsize#1\\z@\\math@fontsfalse\\selectfont\n"
460         "}\n");
461
462 static docstring const textcommabelow_def = from_ascii(
463         "\\ProvideTextCommandDefault{\\textcommabelow}[1]{%%\n"
464         "  \\LyxTextAccent[-.31ex]{\\LyxAccentSize,}{#1}}\n");
465
466 static docstring const textcommaabove_def = from_ascii(
467         "\\ProvideTextCommandDefault{\\textcommaabove}[1]{%%\n"
468         "  \\LyxTextAccent[.5ex]{\\LyxAccentSize`}{#1}}\n");
469
470 static docstring const textcommaaboveright_def = from_ascii(
471         "\\ProvideTextCommandDefault{\\textcommaaboveright}[1]{%%\n"
472         "  \\LyxTextAccent[.5ex]{\\LyxAccentSize\\ '}{#1}}\n");
473
474 // Baltic languages use a comma-accent instead of a cedilla
475 static docstring const textbaltic_def = from_ascii(
476         "%% use comma accent instead of cedilla for these characters:\n"
477         "\\DeclareTextCompositeCommand{\\c}{T1}{g}{\\textcommaabove{g}}\n"
478         "\\DeclareTextCompositeCommand{\\c}{T1}{G}{\\textcommabelow{G}}\n"
479         "\\DeclareTextCompositeCommand{\\c}{T1}{k}{\\textcommabelow{k}}\n"
480         "\\DeclareTextCompositeCommand{\\c}{T1}{K}{\\textcommabelow{K}}\n"
481         "\\DeclareTextCompositeCommand{\\c}{T1}{l}{\\textcommabelow{l}}\n"
482         "\\DeclareTextCompositeCommand{\\c}{T1}{L}{\\textcommabelow{L}}\n"
483         "\\DeclareTextCompositeCommand{\\c}{T1}{n}{\\textcommabelow{n}}\n"
484         "\\DeclareTextCompositeCommand{\\c}{T1}{N}{\\textcommabelow{N}}\n"
485         "\\DeclareTextCompositeCommand{\\c}{T1}{r}{\\textcommabelow{r}}\n"
486         "\\DeclareTextCompositeCommand{\\c}{T1}{R}{\\textcommabelow{R}}\n");
487
488 // Use cyrillic fonts to provide letter schwa in text (see #11062)
489 static docstring const textschwa_def = from_ascii(
490         "%% letter schwa missing in Latin fonts, use Cyrillic schwa\n"
491         "\\DeclareTextSymbolDefault{\\CYRSCHWA}{T2A}\n"
492         "\\DeclareTextSymbolDefault{\\cyrschwa}{T2A}\n"
493         "\\ProvideTextCommandDefault{\\textSchwa}{\\CYRSCHWA}\n"
494         "\\ProvideTextCommandDefault{\\textschwa}{\\cyrschwa}\n");
495
496 // split-level fractions
497 static docstring const xfrac_def = from_ascii(
498            "\\usepackage{xfrac}\n");
499 static docstring const smallLetterFrac_def = from_ascii(
500         "\\DeclareCollectionInstance{smallLetterFrac}{xfrac}{default}{text}\n"
501         "  {phantom=c, scale-factor=1.0, slash-left-kern=-.05em}\n"
502         "\\DeclareCollectionInstance{smallLetterFrac}{xfrac}{lmr}{text}\n"
503         "  {slash-symbol-font=ptm, phantom=c, scale-factor=1, slash-left-kern=-.05em}\n"
504         "\\DeclareCollectionInstance{smallLetterFrac}{xfrac}{lmss}{text}\n"
505         "  {slash-symbol-font=ptm, phantom=c, scale-factor=1, slash-left-kern=-.05em}\n"
506         "\\DeclareCollectionInstance{smallLetterFrac}{xfrac}{cmr}{text}\n"
507         "  {slash-symbol-font=ptm, phantom=c, scale-factor=1, slash-left-kern=-.05em}\n"
508         "\\DeclareCollectionInstance{smallLetterFrac}{xfrac}{cmss}{text}\n"
509         "  {slash-symbol-font=ptm, phantom=c, scale-factor=1, slash-left-kern=-.05em}\n"
510         "\\newcommand{\\smallLetterFrac}[2]{%\n"
511         "  {\\UseCollection{xfrac}{smallLetterFrac}\\sfrac{#1}{#2}}}\n");
512
513 static docstring const lyxref_def = from_ascii(
514         "\\RS@ifundefined{subsecref}\n"
515         "  {\\newref{subsec}{name = \\RSsectxt}}\n"
516         "  {}\n"
517         "\\RS@ifundefined{thmref}\n"
518         "  {\\def\\RSthmtxt{theorem~}\\newref{thm}{name = \\RSthmtxt}}\n"
519         "  {}\n"
520         "\\RS@ifundefined{lemref}\n"
521         "  {\\def\\RSlemtxt{lemma~}\\newref{lem}{name = \\RSlemtxt}}\n"
522         "  {}\n");
523
524 // Make sure the columns are also outputed as rtl
525 static docstring const rtloutputdblcol_def = from_ascii(
526         "\\def\\@outputdblcol{%\n"
527         "  \\if@firstcolumn\n"
528         "    \\global \\@firstcolumnfalse\n"
529         "    \\global \\setbox\\@leftcolumn \\box\\@outputbox\n"
530         "  \\else\n"
531         "    \\global \\@firstcolumntrue\n"
532         "    \\setbox\\@outputbox \\vbox {%\n"
533         "      \\hb@xt@\\textwidth {%\n"
534         "      \\kern\\textwidth \\kern-\\columnwidth %**\n"
535         "      \\hb@xt@\\columnwidth {%\n"
536         "         \\box\\@leftcolumn \\hss}%\n"
537         "      \\kern-\\textwidth %**\n"
538         "      \\hfil\n"
539         "      {\\normalcolor\\vrule \\@width\\columnseprule}%\n"
540         "      \\hfil\n"
541         "      \\kern-\\textwidth  %**\n"
542         "      \\hb@xt@\\columnwidth {%\n"
543         "         \\box\\@outputbox \\hss}%\n"
544         "      \\kern-\\columnwidth \\kern\\textwidth %**\n"
545         "    }%\n"
546         "  }%\n"
547         "  \\@combinedblfloats\n"
548         "  \\@outputpage\n"
549         "  \\begingroup\n"
550         "  \\@dblfloatplacement\n"
551         "  \\@startdblcolumn\n"
552         "  \\@whilesw\\if@fcolmade \\fi\n"
553         "  {\\@outputpage\n"
554         "    \\@startdblcolumn}%\n"
555         "  \\endgroup\n"
556         "  \\fi\n"
557         "}\n"
558         "\\@mparswitchtrue\n");
559
560 static docstring const lyxmintcaption_def = from_ascii(
561         "\\long\\def\\lyxmintcaption[#1]#2{%\n"
562         "  \\ifx#1t\\vskip\\baselineskip\\fi%\n"
563         "  \\refstepcounter{listing}\\noindent%\n"
564         "  \\addcontentsline{lol}{listing}%\n"
565         "  {\\protect\\numberline{\\thelisting}{\\ignorespaces #2}}%\n"
566         "  \\setbox\\@tempboxa\\hbox{\\listingscaption~\\thelisting: #2}%\n"
567         "  \\ifdim \\wd\\@tempboxa >\\linewidth%\n"
568         "  \\parbox[t]{\\linewidth}{\\unhbox\\@tempboxa}\\else%\n"
569         "  \\hbox to\\linewidth{\\hfil\\box\\@tempboxa\\hfil}\\fi%\n"
570         "  \\ifx#1b\\vskip\\baselineskip\\fi\n"
571         "}\n");
572
573
574 /////////////////////////////////////////////////////////////////////
575 //
576 // LyXHTML strings
577 //
578 /////////////////////////////////////////////////////////////////////
579
580 static docstring const lyxnoun_style = from_ascii(
581         "dfn.lyxnoun {\n"
582         "  font-variant: small-caps;\n"
583         "}\n");
584
585
586 // this is how it normally renders, but it might not always do so.
587 static docstring const lyxstrikeout_style = from_ascii(
588         "del.strikeout {\n"
589         "  text-decoration: line-through;\n"
590         "}\n");
591
592
593 /////////////////////////////////////////////////////////////////////
594 //
595 // LaTeXFeatures
596 //
597 /////////////////////////////////////////////////////////////////////
598
599
600 LaTeXFeatures::LaTeXFeatures(Buffer const & b, BufferParams const & p,
601                                                          OutputParams const & r)
602         : buffer_(&b), params_(p), runparams_(r), in_float_(false),
603           in_deleted_inset_(false)
604 {}
605
606
607 LaTeXFeatures::LangPackage LaTeXFeatures::langPackage() const
608 {
609         string const local_lp = bufferParams().lang_package;
610
611         // Locally, custom is just stored as a string
612         // in bufferParams().lang_package.
613         if (local_lp != "auto"
614             && local_lp != "babel"
615             && local_lp != "default"
616             && local_lp != "none")
617                  return LANG_PACK_CUSTOM;
618
619         if (local_lp == "none")
620                 return LANG_PACK_NONE;
621
622         /* If "auto" is selected, we load polyglossia with non-TeX fonts,
623          * else we select babel.
624          * If babel is selected (either directly or via the "auto"
625          * mechanism), we really do only require it if we have
626          * a language that needs it.
627          */
628         bool const polyglossia_required =
629                 params_.useNonTeXFonts
630                 && isAvailable("polyglossia")
631                 && !isProvided("babel")
632                 && this->hasOnlyPolyglossiaLanguages();
633         bool const babel_required =
634                 !bufferParams().language->babel().empty()
635                 || !this->getBabelLanguages().empty();
636
637         if (local_lp == "auto") {
638                 // polyglossia requirement has priority over babel
639                 if (polyglossia_required)
640                         return LANG_PACK_POLYGLOSSIA;
641                 else if (babel_required)
642                         return LANG_PACK_BABEL;
643         }
644
645         if (local_lp == "babel") {
646                 if (babel_required)
647                         return LANG_PACK_BABEL;
648         }
649
650         if (local_lp == "default") {
651                 switch (lyxrc.language_package_selection) {
652                 case LyXRC::LP_AUTO:
653                         // polyglossia requirement has priority over babel
654                         if (polyglossia_required)
655                                 return LANG_PACK_POLYGLOSSIA;
656                         else if (babel_required)
657                                 return LANG_PACK_BABEL;
658                         break;
659                 case LyXRC::LP_BABEL:
660                         if (babel_required)
661                                 return LANG_PACK_BABEL;
662                         break;
663                 case LyXRC::LP_CUSTOM:
664                         return LANG_PACK_CUSTOM;
665                 case LyXRC::LP_NONE:
666                         return LANG_PACK_NONE;
667                 }
668         }
669
670         return LANG_PACK_NONE;
671 }
672
673
674 void LaTeXFeatures::require(string const & name)
675 {
676         features_.insert(name);
677 }
678
679
680 void LaTeXFeatures::require(set<string> const & names)
681 {
682         features_.insert(names.begin(), names.end());
683 }
684
685
686 void LaTeXFeatures::provide(string const & name)
687 {
688         provides_.insert(name);
689 }
690
691
692 void LaTeXFeatures::useLayout(docstring const & layoutname)
693 {
694         useLayout(layoutname, 0);
695 }
696
697
698 void LaTeXFeatures::useLayout(docstring const & layoutname, int level)
699 {
700         // Some code to avoid loops in dependency definition
701         const int maxlevel = 30;
702         if (level > maxlevel) {
703                 lyxerr << "LaTeXFeatures::useLayout: maximum level of "
704                        << "recursion attained by layout "
705                        << to_utf8(layoutname) << endl;
706                 return;
707         }
708
709         DocumentClass const & tclass = params_.documentClass();
710         if (tclass.hasLayout(layoutname)) {
711                 // Is this layout already in usedLayouts?
712                 if (find(usedLayouts_.begin(), usedLayouts_.end(), layoutname)
713                     != usedLayouts_.end())
714                         return;
715
716                 Layout const & layout = tclass[layoutname];
717                 require(layout.requires());
718
719                 if (!layout.depends_on().empty()) {
720                         useLayout(layout.depends_on(), level + 1);
721                 }
722                 usedLayouts_.push_back(layoutname);
723         } else {
724                 lyxerr << "LaTeXFeatures::useLayout: layout `"
725                        << to_utf8(layoutname) << "' does not exist in this class"
726                        << endl;
727         }
728 }
729
730
731 void LaTeXFeatures::useInsetLayout(InsetLayout const & lay)
732 {
733         docstring const & lname = lay.name();
734         DocumentClass const & tclass = params_.documentClass();
735
736         // this is a default inset layout, nothing useful here
737         if (!tclass.hasInsetLayout(lname))
738                 return;
739         // Is this layout already in usedInsetLayouts?
740         if (find(usedInsetLayouts_.begin(), usedInsetLayouts_.end(), lname)
741                         != usedInsetLayouts_.end())
742                 return;
743
744         require(lay.requires());
745         usedInsetLayouts_.push_back(lname);
746 }
747
748
749 bool LaTeXFeatures::isRequired(string const & name) const
750 {
751         return features_.find(name) != features_.end();
752 }
753
754
755 bool LaTeXFeatures::isProvided(string const & name) const
756 {
757         // Currently, this is only features provided by babel languages
758         // (such as textgreek)
759         if (provides_.find(name) != provides_.end())
760                 return true;
761
762         if (params_.useNonTeXFonts)
763                 return params_.documentClass().provides(name);
764
765         bool const ot1 = (params_.main_font_encoding() == "default"
766                 || params_.main_font_encoding() == "OT1");
767         bool const complete = (params_.fontsSans() == "default"
768                 && params_.fontsTypewriter() == "default");
769         bool const nomath = (params_.fontsMath() == "default");
770         return params_.documentClass().provides(name)
771                 || theLaTeXFonts().getLaTeXFont(
772                         from_ascii(params_.fontsRoman())).provides(name, ot1,
773                                                                   complete,
774                                                                   nomath)
775                 || theLaTeXFonts().getLaTeXFont(
776                         from_ascii(params_.fontsSans())).provides(name, ot1,
777                                                                  complete,
778                                                                  nomath)
779                 || theLaTeXFonts().getLaTeXFont(
780                         from_ascii(params_.fontsTypewriter())).provides(name, ot1,
781                                                                        complete,
782                                                                        nomath)
783                 || theLaTeXFonts().getLaTeXFont(
784                         from_ascii(params_.fontsMath())).provides(name, ot1,
785                                                                        complete,
786                                                                        nomath);
787 }
788
789
790 bool LaTeXFeatures::mustProvide(string const & name) const
791 {
792         return isRequired(name) && !isProvided(name);
793 }
794
795
796 bool LaTeXFeatures::isAvailable(string const & name)
797 {
798         string::size_type const i = name.find("->");
799         if (i != string::npos) {
800                 string const from = name.substr(0,i);
801                 string const to = name.substr(i+2);
802                 //LYXERR0("from=[" << from << "] to=[" << to << "]");
803                 return theConverters().isReachable(from, to);
804         }
805         return LaTeXPackages::isAvailable(name);
806 }
807
808
809 namespace {
810
811 void addSnippet(std::list<TexString> & list, TexString ts, bool allow_dupes)
812 {
813         if (allow_dupes ||
814             // test the absense of duplicates, i.e. elements with same str
815             none_of(list.begin(), list.end(), [&](TexString const & ts2){
816                             return ts.str == ts2.str;
817                     })
818             )
819                 list.push_back(move(ts));
820 }
821
822
823 TexString getSnippets(std::list<TexString> const & list)
824 {
825         otexstringstream snip;
826         for (TexString const & ts : list)
827                 snip << TexString(ts) << '\n';
828         return snip.release();
829 }
830
831 } // namespace
832
833
834 void LaTeXFeatures::addPreambleSnippet(TexString ts, bool allow_dupes)
835 {
836         addSnippet(preamble_snippets_, move(ts), allow_dupes);
837 }
838
839
840 void LaTeXFeatures::addPreambleSnippet(docstring const & str, bool allow_dupes)
841 {
842         addSnippet(preamble_snippets_, TexString(str), allow_dupes);
843 }
844
845
846 void LaTeXFeatures::addCSSSnippet(std::string const & snippet)
847 {
848         addSnippet(css_snippets_, TexString(from_ascii(snippet)), false);
849 }
850
851
852 TexString LaTeXFeatures::getPreambleSnippets() const
853 {
854         return getSnippets(preamble_snippets_);
855 }
856
857
858 docstring LaTeXFeatures::getCSSSnippets() const
859 {
860         return getSnippets(css_snippets_).str;
861 }
862
863
864
865 void LaTeXFeatures::useFloat(string const & name, bool subfloat)
866 {
867         if (!usedFloats_[name])
868                 usedFloats_[name] = subfloat;
869         if (subfloat)
870                 require("subfig");
871         // We only need float.sty if we use non builtin floats, or if we
872         // use the "H" modifier. This includes modified table and
873         // figure floats. (Lgb)
874         Floating const & fl = params_.documentClass().floats().getType(name);
875         if (!fl.floattype().empty()) {
876                 if (fl.usesFloatPkg())
877                         require("float");
878                 if (!fl.requires().empty()) {
879                         vector<string> reqs = getVectorFromString(fl.requires());
880                         for (auto const req : reqs)
881                                 require(req);
882                 }
883         }
884 }
885
886
887 void LaTeXFeatures::useLanguage(Language const * lang)
888 {
889         if (!lang->babel().empty() || !lang->polyglossia().empty())
890                 UsedLanguages_.insert(lang);
891         if (!lang->requires().empty())
892                 require(lang->requires());
893         // currently only supported for Babel
894         if (!lang->provides().empty() && useBabel())
895                 provide(lang->provides());
896         // CJK languages do not have a babel name.
897         // They use the CJK package
898         if (lang->encoding()->package() == Encoding::CJK)
899                 require("CJK");
900         // japanese babel language is special (tied to the pLaTeX engine).
901         if (lang->encoding()->package() == Encoding::japanese)
902                 require("japanese");
903 }
904
905
906 void LaTeXFeatures::includeFile(docstring const & key, string const & name)
907 {
908         IncludedFiles_[key] = name;
909 }
910
911
912 bool LaTeXFeatures::hasLanguages() const
913 {
914         return !UsedLanguages_.empty();
915 }
916
917
918 bool LaTeXFeatures::hasOnlyPolyglossiaLanguages() const
919 {
920         // first the main language
921         if (params_.language->polyglossia().empty())
922                 return false;
923         // now the secondary languages
924         LanguageList::const_iterator const begin = UsedLanguages_.begin();
925         for (LanguageList::const_iterator cit = begin;
926              cit != UsedLanguages_.end();
927              ++cit) {
928                 if ((*cit)->polyglossia().empty())
929                         return false;
930         }
931         return true;
932 }
933
934
935 bool LaTeXFeatures::hasPolyglossiaExclusiveLanguages() const
936 {
937         // first the main language
938         if (params_.language->isPolyglossiaExclusive())
939                 return true;
940         // now the secondary languages
941         LanguageList::const_iterator const begin = UsedLanguages_.begin();
942         for (LanguageList::const_iterator cit = begin;
943              cit != UsedLanguages_.end();
944              ++cit) {
945                 if ((*cit)->isPolyglossiaExclusive())
946                         return true;
947         }
948         return false;
949 }
950
951
952 vector<string> LaTeXFeatures::getPolyglossiaExclusiveLanguages() const
953 {
954         vector<string> result;
955         // first the main language
956         if (params_.language->isPolyglossiaExclusive())
957                 result.push_back(params_.language->display());
958         // now the secondary languages
959         LanguageList::const_iterator const begin = UsedLanguages_.begin();
960         for (LanguageList::const_iterator cit = begin;
961              cit != UsedLanguages_.end();
962              ++cit) {
963                 if ((*cit)->isPolyglossiaExclusive())
964                         result.push_back((*cit)->display());
965         }
966         return result;
967 }
968
969
970 vector<string> LaTeXFeatures::getBabelExclusiveLanguages() const
971 {
972         vector<string> result;
973         // first the main language
974         if (params_.language->isBabelExclusive())
975                 result.push_back(params_.language->display());
976         // now the secondary languages
977         LanguageList::const_iterator const begin = UsedLanguages_.begin();
978         for (LanguageList::const_iterator cit = begin;
979              cit != UsedLanguages_.end();
980              ++cit) {
981                 if ((*cit)->isBabelExclusive())
982                         result.push_back((*cit)->display());
983         }
984         return result;
985 }
986
987
988 string LaTeXFeatures::getBabelLanguages() const
989 {
990         ostringstream langs;
991
992         bool first = true;
993         LanguageList::const_iterator const begin = UsedLanguages_.begin();
994         for (LanguageList::const_iterator cit = begin;
995              cit != UsedLanguages_.end();
996              ++cit) {
997                 if ((*cit)->babel().empty())
998                         continue;
999                 if (!first)
1000                         langs << ',';
1001                 else
1002                         first = false;
1003                 langs << (*cit)->babel();
1004         }
1005         return langs.str();
1006 }
1007
1008
1009 set<string> LaTeXFeatures::getPolyglossiaLanguages() const
1010 {
1011         set<string> langs;
1012
1013         LanguageList::const_iterator const begin = UsedLanguages_.begin();
1014         for (LanguageList::const_iterator cit = begin;
1015              cit != UsedLanguages_.end();
1016              ++cit) {
1017                 // We do not need the variants here
1018                 langs.insert((*cit)->polyglossia());
1019         }
1020         return langs;
1021 }
1022
1023
1024 string LaTeXFeatures::getActiveChars() const
1025 {
1026         string res;
1027         // first the main language
1028         res += params_.language->activeChars();
1029         // now the secondary languages
1030         LanguageList::const_iterator const begin = UsedLanguages_.begin();
1031         for (LanguageList::const_iterator cit = begin;
1032              cit != UsedLanguages_.end(); ++cit)
1033                 res += ((*cit)->activeChars());
1034         return res;
1035 }
1036
1037
1038 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
1039 {
1040         // This does only find encodings of languages supported by babel, but
1041         // that does not matter since we don't have a language with an
1042         // encoding supported by inputenc but without babel support.
1043         set<string> encs;
1044         for (auto const & lang : UsedLanguages_)
1045                 if (lang->encoding()->latexName() != doc_encoding &&
1046                     lang->encoding()->package() == Encoding::inputenc)
1047                         encs.insert(lang->encoding()->latexName());
1048         return encs;
1049 }
1050
1051
1052 void LaTeXFeatures::getFontEncodings(vector<string> & encs, bool const onlylangs) const
1053 {
1054         if (!onlylangs) {
1055                 // these must be loaded if glyphs of this script are used
1056                 // unless a language providing them is used in the document
1057                 if (mustProvide("textgreek")
1058                     && find(encs.begin(), encs.end(), "LGR") == encs.end())
1059                         encs.insert(encs.begin(), "LGR");
1060                 if ((mustProvide("textcyrillic") || mustProvide("textschwa"))
1061                     && find(encs.begin(), encs.end(), "T2A") == encs.end())
1062                         encs.insert(encs.begin(), "T2A");
1063         }
1064
1065         for (auto const & lang : UsedLanguages_) {
1066                 vector<string> extraencs =
1067                         getVectorFromString(lang->fontenc(buffer().masterParams()));
1068                 for (auto const & extra : extraencs) {
1069                         if (extra != "none" && find(encs.begin(), encs.end(), extra) == encs.end())
1070                                 encs.insert(encs.begin(), extra);
1071                 }
1072         }
1073 }
1074
1075
1076 bool LaTeXFeatures::hasRTLLanguage() const
1077 {
1078         if (params_.language->rightToLeft())
1079                 return true;
1080         for (auto const & lang : UsedLanguages_)
1081                 if (lang->rightToLeft())
1082                         return true;
1083         return false;
1084 }
1085
1086
1087 namespace {
1088
1089 char const * simplefeatures[] = {
1090 // note that the package order here will be the same in the LaTeX-output
1091         "array",
1092         "verbatim",
1093         "cprotect",
1094         "longtable",
1095         "latexsym",
1096         "pifont",
1097         // subfig is handled in BufferParams.cpp
1098         "varioref",
1099         "prettyref",
1100         "refstyle",
1101         /*For a successful cooperation of the `wrapfig' package with the
1102           `float' package you should load the `wrapfig' package *after*
1103           the `float' package. See the caption package documentation
1104           for explanation.*/
1105         "float",
1106         "wrapfig",
1107         "booktabs",
1108         "dvipost",
1109         "fancybox",
1110         "calc",
1111         "units",
1112         "framed",
1113         "soul",
1114         "dingbat",
1115         "bbding",
1116         "ifsym",
1117         "txfonts",
1118         "pxfonts",
1119         "mathdesign",
1120         "mathrsfs",
1121         "mathabx",
1122         "mathtools",
1123         // "cancel",
1124         "ascii",
1125         "url",
1126         "csquotes",
1127         "enumitem",
1128         "endnotes",
1129         "enotez",
1130         "hhline",
1131         "ifthen",
1132         // listings is handled in BufferParams.cpp
1133         "bm",
1134         "pdfpages",
1135         "amscd",
1136         "slashed",
1137         "multicol",
1138         "multirow",
1139         "tfrupee",
1140         "shapepar",
1141         "rsphrase",
1142         "hpstatement",
1143         "algorithm2e",
1144         "sectionbox",
1145         "tcolorbox",
1146         "pdfcomment",
1147         "fixme",
1148         "todonotes",
1149         "forest",
1150         "varwidth",
1151         "tablefootnote",
1152         "afterpage",
1153         "tabularx",
1154         "tikz",
1155         "xltabular",
1156         "chessboard",
1157         "xskak",
1158         "pict2e",
1159         "drs",
1160         "environ"
1161 };
1162
1163 char const * bibliofeatures[] = {
1164         // Known bibliography packages (will be loaded before natbib)
1165         "achicago",
1166         "apacite",
1167         "apalike",
1168         "astron",
1169         "authordate1-4",
1170         "babelbib",
1171         "bibgerm",
1172         "chapterbib",
1173         "chicago",
1174         "chscite",
1175         "harvard",
1176         "mslapa",
1177         "named"
1178 };
1179
1180 int const nb_bibliofeatures = sizeof(bibliofeatures) / sizeof(char const *);
1181
1182 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
1183
1184 } // namespace
1185
1186
1187 string const LaTeXFeatures::getColorOptions() const
1188 {
1189         ostringstream colors;
1190
1191         // Handling the color packages separately is needed to be able to load them
1192         // before babel when hyperref is loaded with the colorlinks option
1193         // for more info see Bufferparams.cpp
1194
1195         // [x]color.sty
1196         if (mustProvide("color") || mustProvide("xcolor")) {
1197                 string const package =
1198                         (mustProvide("xcolor") ? "xcolor" : "color");
1199                 if (params_.graphics_driver == "default"
1200                         || params_.graphics_driver == "none")
1201                         colors << "\\usepackage{" << package << "}\n";
1202                 else
1203                         colors << "\\usepackage["
1204                                  << params_.graphics_driver
1205                                  << "]{" << package << "}\n";
1206         }
1207
1208         // pdfcolmk must be loaded after color
1209         if (mustProvide("pdfcolmk"))
1210                 colors << "\\usepackage{pdfcolmk}\n";
1211
1212         // the following 3 color commands must be set after color
1213         // is loaded and before pdfpages, therefore add the command
1214         // here define the set color
1215         if (mustProvide("pagecolor")) {
1216                 colors << "\\definecolor{page_backgroundcolor}{rgb}{";
1217                 colors << outputLaTeXColor(params_.backgroundcolor) << "}\n";
1218                 // set the page color
1219                 colors << "\\pagecolor{page_backgroundcolor}\n";
1220         }
1221
1222         if (mustProvide("fontcolor")) {
1223                 colors << "\\definecolor{document_fontcolor}{rgb}{";
1224                 colors << outputLaTeXColor(params_.fontcolor) << "}\n";
1225                 // set the color
1226                 colors << "\\color{document_fontcolor}\n";
1227         }
1228
1229         if (mustProvide("lyxgreyedout")) {
1230                 colors << "\\definecolor{note_fontcolor}{rgb}{";
1231                 colors << outputLaTeXColor(params_.notefontcolor) << "}\n";
1232                 // the color will be set together with the definition of
1233                 // the lyxgreyedout environment (see lyxgreyedout_def)
1234         }
1235
1236         // color for shaded boxes
1237         if (isRequired("framed") && mustProvide("color")) {
1238                 colors << "\\definecolor{shadecolor}{rgb}{";
1239                 colors << outputLaTeXColor(params_.boxbgcolor) << "}\n";
1240                 // this color is automatically used by the LaTeX-package "framed"
1241         }
1242
1243         return colors.str();
1244 }
1245
1246
1247 string const LaTeXFeatures::getPackageOptions() const
1248 {
1249         ostringstream packageopts;
1250         // Output all the package option stuff we have been asked to do.
1251         map<string, string>::const_iterator it =
1252                 params_.documentClass().packageOptions().begin();
1253         map<string, string>::const_iterator en =
1254                 params_.documentClass().packageOptions().end();
1255         for (; it != en; ++it)
1256                 if (mustProvide(it->first))
1257                         packageopts << "\\PassOptionsToPackage{" << it->second << "}"
1258                                  << "{" << it->first << "}\n";
1259         return packageopts.str();
1260 }
1261
1262
1263 string const LaTeXFeatures::getPackages() const
1264 {
1265         ostringstream packages;
1266
1267         // FIXME: currently, we can only load packages and macros known
1268         // to LyX.
1269         // However, with the Require tag of layouts/custom insets,
1270         // also unknown packages can be requested. They are silently
1271         // swallowed now. We should change this eventually.
1272
1273         //  These are all the 'simple' includes.  i.e
1274         //  packages which we just \usepackage{package}
1275         for (int i = 0; i < nb_simplefeatures; ++i) {
1276                 if (mustProvide(simplefeatures[i]))
1277                         packages << "\\usepackage{" << simplefeatures[i] << "}\n";
1278         }
1279
1280         // The rest of these packages are somewhat more complicated
1281         // than those above.
1282
1283         if (mustProvide("changebar") && !mustProvide("ct-dvipost")) {
1284                 packages << "\\usepackage{changebar}\n";
1285         }
1286
1287         if (mustProvide("footnote")) {
1288                 if (isRequired("hyperref"))
1289                         packages << "\\usepackage{footnotehyper}\n";
1290                 else
1291                         packages << "\\usepackage{footnote}\n";
1292         }
1293
1294         // [pdf]lscape is used to rotate longtables
1295         if (mustProvide("lscape")) {
1296                 if (runparams_.flavor == OutputParams::LATEX
1297                     || runparams_.flavor == OutputParams::DVILUATEX)
1298                         packages << "\\usepackage{lscape}\n";
1299                 else
1300                         packages << "\\usepackage{pdflscape}\n";
1301         }
1302
1303         // The tipa package and its extensions (tipx, tone) must not
1304         // be loaded with non-TeX fonts, since fontspec includes the
1305         // respective macros
1306         if (mustProvide("tipa") && !params_.useNonTeXFonts)
1307                 packages << "\\usepackage{tipa}\n";
1308         if (mustProvide("tipx") && !params_.useNonTeXFonts)
1309                 packages << "\\usepackage{tipx}\n";
1310         if (mustProvide("extraipa") && !params_.useNonTeXFonts)
1311                 packages << "\\usepackage{extraipa}\n";
1312         if (mustProvide("tone") && !params_.useNonTeXFonts)
1313                 packages << "\\usepackage{tone}\n";
1314
1315         // if fontspec or newtxmath is used, AMS packages have to be loaded
1316         // before fontspec (in BufferParams)
1317         string const amsPackages = loadAMSPackages();
1318         bool const ot1 = (params_.main_font_encoding() == "default"
1319                           || params_.main_font_encoding() == "OT1");
1320         bool const use_newtxmath =
1321                 theLaTeXFonts().getLaTeXFont(from_ascii(params_.fontsMath())).getUsedPackage(
1322                         ot1, false, false) == "newtxmath";
1323
1324         if (!params_.useNonTeXFonts && !use_newtxmath && !amsPackages.empty())
1325                 packages << amsPackages;
1326
1327         if (mustProvide("cancel") &&
1328             params_.use_package("cancel") != BufferParams::package_off)
1329                 packages << "\\usepackage{cancel}\n";
1330
1331         // marvosym and bbding both define the \Cross macro
1332         if (mustProvide("marvosym")) {
1333             if (mustProvide("bbding"))
1334                 packages << "\\let\\Cross\\relax\n";
1335             packages << "\\usepackage{marvosym}\n";
1336         }
1337
1338         // accents must be loaded after amsmath
1339         if (mustProvide("accents") &&
1340             params_.use_package("accents") != BufferParams::package_off)
1341                 packages << "\\usepackage{accents}\n";
1342
1343         // mathdots must be loaded after amsmath
1344         if (mustProvide("mathdots") &&
1345                 params_.use_package("mathdots") != BufferParams::package_off)
1346                 packages << "\\usepackage{mathdots}\n";
1347
1348         // yhmath must be loaded after amsmath
1349         if (mustProvide("yhmath") &&
1350             params_.use_package("yhmath") != BufferParams::package_off)
1351                 packages << "\\usepackage{yhmath}\n";
1352
1353         // stmaryrd must be loaded after amsmath
1354         if (mustProvide("stmaryrd") &&
1355             params_.use_package("stmaryrd") != BufferParams::package_off)
1356                 packages << "\\usepackage{stmaryrd}\n";
1357
1358         if (mustProvide("stackrel") &&
1359             params_.use_package("stackrel") != BufferParams::package_off)
1360                 packages << "\\usepackage{stackrel}\n";
1361
1362         if (mustProvide("undertilde") &&
1363                 params_.use_package("undertilde") != BufferParams::package_off)
1364                 packages << "\\usepackage{undertilde}\n";
1365
1366         // [x]color and pdfcolmk are handled in getColorOptions() above
1367
1368         // makeidx.sty
1369         if (isRequired("makeidx") || isRequired("splitidx")) {
1370                 if (!isProvided("makeidx") && !isRequired("splitidx"))
1371                         packages << "\\usepackage{makeidx}\n";
1372                 if (mustProvide("splitidx"))
1373                         packages << "\\usepackage{splitidx}\n";
1374                 packages << "\\makeindex\n";
1375         }
1376
1377         // graphicx.sty
1378         if (mustProvide("graphicx") && params_.graphics_driver != "none") {
1379                 if (params_.graphics_driver == "default")
1380                         packages << "\\usepackage{graphicx}\n";
1381                 else
1382                         packages << "\\usepackage["
1383                                  << params_.graphics_driver
1384                                  << "]{graphicx}\n";
1385         }
1386
1387         // These must be loaded after graphicx, since they try
1388         // to load graphicx without options
1389         if (mustProvide("rotating"))
1390                 packages << "\\usepackage{rotating}\n";
1391         if (mustProvide("rotfloat"))
1392                 packages << "\\usepackage{rotfloat}\n";
1393
1394         // lyxskak.sty --- newer chess support based on skak.sty
1395         if (mustProvide("chess"))
1396                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
1397
1398         // setspace.sty
1399         if (mustProvide("setspace") && !isProvided("SetSpace"))
1400                 packages << "\\usepackage{setspace}\n";
1401
1402         // we need to assure that mhchem is loaded before esint and every other
1403         // package that redefines command of amsmath because mhchem loads amlatex
1404         // (this info is from the author of mhchem from June 2013)
1405         if (mustProvide("mhchem") &&
1406             params_.use_package("mhchem") != BufferParams::package_off)
1407                 packages << "\\PassOptionsToPackage{version=3}{mhchem}\n"
1408                             "\\usepackage{mhchem}\n";
1409
1410         // wasysym is a simple feature, but it must be after amsmath if both
1411         // are used
1412         // wasysym redefines some integrals (e.g. iint) from amsmath. That
1413         // leads to inconsistent integrals. We only load this package if
1414         // the document does not contain integrals (then isRequired("esint")
1415         // is false) or if esint is used, since esint redefines all relevant
1416         // integral symbols from wasysym and amsmath.
1417         // See http://www.lyx.org/trac/ticket/1942
1418         if (mustProvide("wasysym") &&
1419             params_.use_package("wasysym") != BufferParams::package_off &&
1420             (params_.use_package("esint") != BufferParams::package_off || !isRequired("esint")))
1421                 packages << "\\usepackage{wasysym}\n";
1422
1423         // esint must be after amsmath (and packages requiring amsmath, like mhchem)
1424         // and wasysym, since it will redeclare inconsistent integral symbols
1425         if (mustProvide("esint") &&
1426             params_.use_package("esint") != BufferParams::package_off)
1427                 packages << "\\usepackage{esint}\n";
1428
1429         // Known bibliography packages (simple \usepackage{package})
1430         for (int i = 0; i < nb_bibliofeatures; ++i) {
1431                 if (mustProvide(bibliofeatures[i]))
1432                         packages << "\\usepackage{"
1433                                  << bibliofeatures[i] << "}\n";
1434         }
1435
1436         // Compatibility between achicago and natbib
1437         if (mustProvide("achicago") && mustProvide("natbib"))
1438                 packages << "\\let\\achicagobib\\thebibliography\n";
1439
1440         // natbib.sty
1441         // Some classes load natbib themselves, but still allow (or even require)
1442         // plain numeric citations (ReVTeX is such a case, see bug 5182).
1443         // This special case is indicated by the "natbib-internal" key.
1444         if (mustProvide("natbib")
1445             && !isProvided("natbib-internal")
1446             && !isProvided("biblatex")
1447             && !isProvided("biblatex-natbib")
1448             && !isProvided("jurabib")) {
1449                 packages << "\\usepackage[";
1450                 if (params_.citeEngineType() == ENGINE_TYPE_NUMERICAL)
1451                         packages << "numbers";
1452                 else
1453                         packages << "authoryear";
1454                 if (!params_.biblio_opts.empty())
1455                         packages << ',' << params_.biblio_opts;
1456                 packages << "]{natbib}\n";
1457         }
1458
1459         // Compatibility between achicago and natbib
1460         if (mustProvide("achicago") && mustProvide("natbib")) {
1461                 packages << "\\let\\thebibliography\\achicagobib\n";
1462                 packages << "\\let\\SCcite\\astroncite\n";
1463                 packages << "\\let\\UnexpandableProtect\\protect\n";
1464         }
1465
1466         // jurabib -- we need version 0.6 at least.
1467         if (mustProvide("jurabib")
1468             && !isProvided("natbib-internal")
1469             && !isProvided("natbib")
1470             && !isProvided("biblatex")
1471             && !isProvided("biblatex-natbib")) {
1472                 packages << "\\usepackage";
1473                 if (!params_.biblio_opts.empty())
1474                         packages << '[' << params_.biblio_opts << ']';
1475                 packages << "{jurabib}[2004/01/25]\n";
1476         }
1477
1478         // opcit -- we pass custombst as we output \bibliographystyle ourselves
1479         if (mustProvide("opcit")) {
1480                 if (isRequired("hyperref"))
1481                         packages << "\\usepackage[custombst,hyperref]{opcit}\n";
1482                 else
1483                         packages << "\\usepackage[custombst]{opcit}\n";
1484         }
1485
1486         // xargs -- we need version 1.09 at least
1487         if (mustProvide("xargs"))
1488                 packages << "\\usepackage{xargs}[2008/03/08]\n";
1489
1490         if (mustProvide("xy"))
1491                 packages << "\\usepackage[all]{xy}\n";
1492
1493         if (mustProvide("feyn"))
1494                 packages << "\\usepackage{feyn}\n"; //Diagram
1495
1496         if (mustProvide("ulem"))
1497                 packages << "\\PassOptionsToPackage{normalem}{ulem}\n"
1498                             "\\usepackage{ulem}\n";
1499
1500         if (mustProvide("nomencl")) {
1501                 // Make it work with the new and old version of the package,
1502                 // but don't use the compatibility option since it is
1503                 // incompatible to other packages.
1504                 packages << "\\usepackage{nomencl}\n"
1505                             "% the following is useful when we have the old nomencl.sty package\n"
1506                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
1507                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
1508                             "\\makenomenclature\n";
1509         }
1510
1511         // fixltx2e provides subscript
1512         if (mustProvide("subscript") && !isRequired("fixltx2e"))
1513                 packages << "\\usepackage{subscript}\n";
1514
1515         // footmisc must be loaded after setspace
1516         // Set options here, load the package after the user preamble to
1517         // avoid problems with manual loaded footmisc.
1518         if (mustProvide("footmisc"))
1519                 packages << "\\PassOptionsToPackage{stable}{footmisc}\n";
1520
1521         if (mustProvide("microtype")){
1522                 packages << "\\usepackage{microtype}\n";
1523         }
1524
1525         return packages.str();
1526 }
1527
1528
1529 TexString LaTeXFeatures::getMacros() const
1530 {
1531         otexstringstream macros;
1532
1533         if (!preamble_snippets_.empty()) {
1534                 macros << '\n';
1535                 macros << getPreambleSnippets();
1536         }
1537
1538         if (mustProvide("xetexdashbreakstate"))
1539                 macros << "\\XeTeXdashbreakstate 0" << '\n';
1540
1541         if (mustProvide("papersize")) {
1542                 if (runparams_.flavor == OutputParams::LATEX
1543                     || runparams_.flavor == OutputParams::DVILUATEX)
1544                         macros << papersizedvi_def << '\n';
1545                 else if  (runparams_.flavor == OutputParams::LUATEX)
1546                         macros << papersizepdflua_def << '\n';
1547                 else
1548                         macros << papersizepdf_def << '\n';
1549         }
1550
1551         if (mustProvide("LyX")) {
1552                 macros << "\\providecommand{\\LyX}";
1553                 // open conditional wrappers
1554                 if (runparams_.use_polyglossia && hasRTLLanguage())
1555                         macros << "{\\@ensure@LTR";
1556                 if (isRequired("hyperref"))
1557                         macros << "{\\texorpdfstring";
1558                 if (useBabel())
1559                         macros << "{\\ensureascii";
1560                 // main definition
1561                 macros << lyx_def;
1562                 // close conditional wrappers
1563                 if (useBabel())
1564                         macros << '}';
1565                 if (isRequired("hyperref"))
1566                         macros << "{LyX}}";
1567                 if (runparams_.use_polyglossia && hasRTLLanguage())
1568                         macros << '}';
1569                 macros << '\n';
1570         }
1571
1572         if (mustProvide("noun"))
1573                 macros << noun_def << '\n';
1574
1575         if (mustProvide("lyxarrow"))
1576                 macros << lyxarrow_def << '\n';
1577
1578         if (mustProvide("lyxzerowidthspace"))
1579                 macros << lyxZWSP_def << '\n';
1580
1581         if (!usePolyglossia() && mustProvide("textgreek")) {
1582             // ensure LGR font encoding is defined also if fontenc is not loaded by LyX
1583                 if (params_.main_font_encoding() == "default")
1584                         macros << textgreek_LGR_def;
1585                 macros << textgreek_def << '\n';
1586         }
1587
1588         if (!usePolyglossia() && mustProvide("textcyrillic")) {
1589                 // ensure T2A font encoding is set up also if fontenc is not loaded by LyX
1590                 if (params_.main_font_encoding() == "default")
1591                         macros << textcyr_T2A_def;
1592                 macros << textcyr_def << '\n';
1593         }
1594
1595         // non-standard text accents:
1596         if (mustProvide("textcommaabove") || mustProvide("textcommaaboveright") ||
1597             mustProvide("textcommabelow") || mustProvide("textbaltic"))
1598                 macros << lyxaccent_def;
1599
1600         if (mustProvide("textcommabelow") || mustProvide("textbaltic"))
1601                 macros << textcommabelow_def << '\n';
1602
1603         if (mustProvide("textcommaabove") || mustProvide("textbaltic"))
1604                 macros << textcommaabove_def << '\n';
1605
1606         if (mustProvide("textcommaaboveright"))
1607                 macros << textcommaaboveright_def << '\n';
1608
1609         if (mustProvide("textbaltic"))
1610                 macros << textbaltic_def << '\n';
1611
1612         if (mustProvide("textschwa"))
1613                 macros << textschwa_def << '\n';
1614
1615         // split-level fractions
1616         if (mustProvide("xfrac") || mustProvide("smallLetterFrac"))
1617                 macros << xfrac_def << '\n';
1618
1619         if (mustProvide("smallLetterFrac"))
1620                 macros << smallLetterFrac_def << '\n';
1621
1622         if (mustProvide("lyxmathsym"))
1623                 macros << lyxmathsym_def << '\n';
1624
1625         if (mustProvide("cedilla"))
1626                 macros << cedilla_def << '\n';
1627
1628         if (mustProvide("subring"))
1629                 macros << subring_def << '\n';
1630
1631         if (mustProvide("subdot"))
1632                 macros << subdot_def << '\n';
1633
1634         if (mustProvide("subhat"))
1635                 macros << subhat_def << '\n';
1636
1637         if (mustProvide("subtilde"))
1638                 macros << subtilde_def << '\n';
1639
1640         if (mustProvide("dacute"))
1641                 macros << dacute_def << '\n';
1642
1643         if (mustProvide("tipasymb"))
1644                 macros << tipasymb_def << '\n';
1645
1646         if (mustProvide("dgrave"))
1647                 macros << dgrave_def << '\n';
1648
1649         if (mustProvide("rcap"))
1650                 macros << rcap_def << '\n';
1651
1652         if (mustProvide("ogonek"))
1653                 macros << ogonek_def << '\n';
1654
1655         // quotes.
1656         if (mustProvide("quotesinglbase"))
1657                 macros << quotesinglbase_def << '\n';
1658         if (mustProvide("quotedblbase"))
1659                 macros << quotedblbase_def << '\n';
1660         if (mustProvide("guilsinglleft"))
1661                 macros << guilsinglleft_def << '\n';
1662         if (mustProvide("guilsinglright"))
1663                 macros << guilsinglright_def << '\n';
1664         if (mustProvide("guillemotleft"))
1665                 macros << guillemotleft_def << '\n';
1666         if (mustProvide("guillemotright"))
1667                 macros << guillemotright_def << '\n';
1668         if (mustProvide("textquotedbl"))
1669                 macros << textquotedbl_def << '\n';
1670         if (mustProvide("textquotesinglep")) {
1671                 if (runparams_.flavor == OutputParams::XETEX)
1672                         macros << textquotesinglep_xetex_def << '\n';
1673                 else
1674                         macros << textquotesinglep_luatex_def << '\n';
1675         }
1676         if (mustProvide("textquotedblp")) {
1677                 if (runparams_.flavor == OutputParams::XETEX)
1678                         macros << textquotedblp_xetex_def << '\n';
1679                 else
1680                         macros << textquotedblp_luatex_def << '\n';
1681         }
1682
1683         // Math mode
1684         if (mustProvide("binom") && !isRequired("amsmath"))
1685                 macros << binom_def << '\n';
1686         if (mustProvide("mathcircumflex"))
1687                 macros << mathcircumflex_def << '\n';
1688
1689         // other
1690         if (mustProvide("ParagraphLeftIndent"))
1691                 macros << paragraphleftindent_def;
1692         if (mustProvide("NeedLyXFootnoteCode"))
1693                 macros << floatingfootnote_def;
1694
1695         // some problems with tex->html converters
1696         if (mustProvide("NeedTabularnewline"))
1697                 macros << tabularnewline_def;
1698
1699         // greyed-out environment (note inset)
1700         // the color is specified in the routine
1701         // getColorOptions() to avoid LaTeX-package clashes
1702         if (mustProvide("lyxgreyedout")) {
1703                 // We need different version for RTL (#8647)
1704                 if (hasRTLLanguage()) {
1705                         if (runparams_.flavor == OutputParams::LUATEX)
1706                                 if (useBabel())
1707                                         macros << lyxgreyedout_luartl_babel_def;
1708                                 else
1709                                         macros << lyxgreyedout_luartl_def;
1710                         else
1711                                 macros << lyxgreyedout_rtl_def;
1712                 } else
1713                         macros << lyxgreyedout_def;
1714         }
1715
1716         if (mustProvide("lyxdot"))
1717                 macros << lyxdot_def << '\n';
1718
1719         // floats
1720         getFloatDefinitions(macros);
1721
1722         if (mustProvide("refstyle"))
1723                 macros << lyxref_def << '\n';
1724
1725         // change tracking
1726         if (mustProvide("ct-dvipost")) {
1727                 if (isRequired("changebar"))
1728                         macros << changetracking_dvipost_cb_def;
1729                 else
1730                         macros << changetracking_dvipost_def;
1731         }
1732
1733         if (mustProvide("ct-xcolor-ulem")) {
1734                 streamsize const prec = macros.os().precision(2);
1735
1736                 RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
1737                 macros << "\\providecolor{lyxadded}{rgb}{"
1738                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
1739
1740                 RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
1741                 macros << "\\providecolor{lyxdeleted}{rgb}{"
1742                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
1743
1744                 macros.os().precision(prec);
1745
1746                 macros << changetracking_xcolor_ulem_base_def;
1747
1748                 if (isRequired("changebar")) {
1749                         if (isRequired("hyperref"))
1750                                 macros << changetracking_xcolor_ulem_hyperref_cb_def;
1751                         else
1752                                 macros << changetracking_xcolor_ulem_cb_def;
1753                 } else {
1754                         if (isRequired("hyperref"))
1755                                 macros << changetracking_xcolor_ulem_hyperref_def;
1756                         else
1757                                 macros << changetracking_xcolor_ulem_def;
1758                 }
1759         }
1760
1761         if (mustProvide("ct-tikz-object-sout")) {
1762                 if (!mustProvide("ct-xcolor-ulem")) {
1763                         streamsize const prec = macros.os().precision(2);
1764
1765                         RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
1766                         macros << "\\providecolor{lyxadded}{rgb}{"
1767                                << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
1768         
1769                         RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
1770                         macros << "\\providecolor{lyxdeleted}{rgb}{"
1771                                << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
1772         
1773                         macros.os().precision(prec);
1774                 }
1775                 
1776                 macros << changetracking_tikz_object_sout_def;
1777                 
1778                 if (isRequired("changebar")) {
1779                         if (isRequired("hyperref"))
1780                                 macros << changetracking_xcolor_ulem_hyperref_cb_object_def;
1781                         else
1782                                 macros << changetracking_xcolor_ulem_cb_object_def;
1783                 } else {
1784                         if (isRequired("hyperref"))
1785                                 macros << changetracking_xcolor_ulem_hyperref_object_def;
1786                         else
1787                                 macros << changetracking_xcolor_ulem_object_def;
1788                 }
1789         }
1790
1791         if (mustProvide("ct-none"))
1792                 macros << changetracking_none_def;
1793
1794         if (mustProvide("rtloutputdblcol"))
1795                 macros << rtloutputdblcol_def;
1796
1797         if (mustProvide("lyxmintcaption"))
1798                 macros << lyxmintcaption_def;
1799
1800         return macros.release();
1801 }
1802
1803
1804 docstring const LaTeXFeatures::getBabelPresettings() const
1805 {
1806         odocstringstream tmp;
1807
1808         for (Language const * lang : UsedLanguages_)
1809                 if (!lang->babel_presettings().empty())
1810                         tmp << lang->babel_presettings() << '\n';
1811         if (!params_.language->babel_presettings().empty())
1812                 tmp << params_.language->babel_presettings() << '\n';
1813
1814         if (!contains(tmp.str(), '@'))
1815                 return tmp.str();
1816
1817         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1818 }
1819
1820
1821 docstring const LaTeXFeatures::getBabelPostsettings() const
1822 {
1823         odocstringstream tmp;
1824
1825         for (Language const * lang : UsedLanguages_)
1826                 if (!lang->babel_postsettings().empty())
1827                         tmp << lang->babel_postsettings() << '\n';
1828         if (!params_.language->babel_postsettings().empty())
1829                 tmp << params_.language->babel_postsettings() << '\n';
1830
1831         if (!contains(tmp.str(), '@'))
1832                 return tmp.str();
1833
1834         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1835 }
1836
1837
1838 string const LaTeXFeatures::loadAMSPackages() const
1839 {
1840         ostringstream tmp;
1841
1842         if (mustProvide("amsmath")
1843             && params_.use_package("amsmath") != BufferParams::package_off) {
1844                 tmp << "\\usepackage{amsmath}\n";
1845         } else {
1846                 // amsbsy and amstext are already provided by amsmath
1847                 if (mustProvide("amsbsy"))
1848                         tmp << "\\usepackage{amsbsy}\n";
1849                 if (mustProvide("amstext"))
1850                         tmp << "\\usepackage{amstext}\n";
1851         }
1852
1853         if (mustProvide("amsthm"))
1854                 tmp << "\\usepackage{amsthm}\n";
1855
1856         if (mustProvide("amssymb")
1857             && params_.use_package("amssymb") != BufferParams::package_off)
1858                 tmp << "\\usepackage{amssymb}\n";
1859
1860         return tmp.str();
1861 }
1862
1863
1864 docstring const LaTeXFeatures::getTClassPreamble() const
1865 {
1866         // the text class specific preamble
1867         DocumentClass const & tclass = params_.documentClass();
1868         odocstringstream tcpreamble;
1869
1870         tcpreamble << tclass.preamble();
1871
1872         list<docstring>::const_iterator cit = usedLayouts_.begin();
1873         list<docstring>::const_iterator end = usedLayouts_.end();
1874         for (; cit != end; ++cit)
1875                 // For InPreamble layouts, we output the preamble stuff earlier
1876                 // (before the layouts). See Paragraph::Private::validate.
1877                 if (!tclass[*cit].inpreamble)
1878                         tcpreamble << tclass[*cit].preamble();
1879
1880         cit = usedInsetLayouts_.begin();
1881         end = usedInsetLayouts_.end();
1882         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1883         for (; cit != end; ++cit) {
1884                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1885                 if (it == ils.end())
1886                         continue;
1887                 tcpreamble << it->second.preamble();
1888         }
1889
1890         return tcpreamble.str();
1891 }
1892
1893
1894 docstring const LaTeXFeatures::getTClassHTMLPreamble() const
1895 {
1896         DocumentClass const & tclass = params_.documentClass();
1897         odocstringstream tcpreamble;
1898
1899         tcpreamble << tclass.htmlpreamble();
1900
1901         list<docstring>::const_iterator cit = usedLayouts_.begin();
1902         list<docstring>::const_iterator end = usedLayouts_.end();
1903         for (; cit != end; ++cit)
1904                 tcpreamble << tclass[*cit].htmlpreamble();
1905
1906         cit = usedInsetLayouts_.begin();
1907         end = usedInsetLayouts_.end();
1908         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1909         for (; cit != end; ++cit) {
1910                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1911                 if (it == ils.end())
1912                         continue;
1913                 tcpreamble << it->second.htmlpreamble();
1914         }
1915
1916         return tcpreamble.str();
1917 }
1918
1919
1920 docstring const LaTeXFeatures::getTClassHTMLStyles() const
1921 {
1922         DocumentClass const & tclass = params_.documentClass();
1923         odocstringstream tcpreamble;
1924
1925         if (mustProvide("noun"))
1926                 tcpreamble << lyxnoun_style;
1927         // this isn't exact, but it won't hurt that much if it
1928         // wasn't for this.
1929         if (mustProvide("ulem"))
1930                 tcpreamble << lyxstrikeout_style;
1931
1932         tcpreamble << tclass.htmlstyles();
1933
1934         list<docstring>::const_iterator cit = usedLayouts_.begin();
1935         list<docstring>::const_iterator end = usedLayouts_.end();
1936         for (; cit != end; ++cit)
1937                 tcpreamble << tclass[*cit].htmlstyle();
1938
1939         cit = usedInsetLayouts_.begin();
1940         end = usedInsetLayouts_.end();
1941         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1942         for (; cit != end; ++cit) {
1943                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1944                 if (it == ils.end())
1945                         continue;
1946                 tcpreamble << it->second.htmlstyle();
1947         }
1948
1949         return tcpreamble.str();
1950 }
1951
1952
1953 namespace {
1954
1955 docstring const getFloatI18nPreamble(docstring const & type,
1956                         docstring const & name, Language const * lang,
1957                         Encoding const & enc, bool const polyglossia)
1958 {
1959         // Check whether name can be encoded in the buffer encoding
1960         bool encodable = true;
1961         for (size_t i = 0; i < name.size(); ++i) {
1962                 if (!enc.encodable(name[i])) {
1963                         encodable = false;
1964                         break;
1965                 }
1966         }
1967
1968         docstring const language = polyglossia ? from_ascii(lang->polyglossia())
1969                                                : from_ascii(lang->babel());
1970         docstring const langenc = from_ascii(lang->encoding()->iconvName());
1971         docstring const texenc = from_ascii(lang->encoding()->latexName());
1972         docstring const bufenc = from_ascii(enc.iconvName());
1973         docstring const s1 = docstring(1, 0xF0000);
1974         docstring const s2 = docstring(1, 0xF0001);
1975         docstring const translated = encodable ? name
1976                 : from_ascii("\\inputencoding{") + texenc + from_ascii("}")
1977                         + s1 + langenc + s2 + name + s1 + bufenc + s2;
1978
1979         odocstringstream os;
1980         os << "\\addto\\captions" << language
1981            << "{\\renewcommand{\\" << type << "name}{" << translated << "}}\n";
1982         return os.str();
1983 }
1984
1985
1986 docstring const i18npreamble(docstring const & templ, Language const * lang,
1987                              Encoding const & enc, bool const polyglossia,
1988                              bool const need_fixedwidth)
1989 {
1990         if (templ.empty())
1991                 return templ;
1992
1993         string preamble = polyglossia ?
1994                 subst(to_utf8(templ), "$$lang", lang->polyglossia()) :
1995                 subst(to_utf8(templ), "$$lang", lang->babel());
1996
1997         string const langenc = lang->encoding()->iconvName();
1998         string const texenc = lang->encoding()->latexName();
1999         string const bufenc = enc.iconvName();
2000         Encoding const * testenc(&enc);
2001         bool lang_fallback = false;
2002         bool ascii_fallback = false;
2003         if (need_fixedwidth && !enc.hasFixedWidth()) {
2004                 if (lang->encoding()->hasFixedWidth()) {
2005                         testenc = lang->encoding();
2006                         lang_fallback = true;
2007                 } else {
2008                         // We need a fixed width encoding, but both the buffer
2009                         // encoding and the language encoding are variable
2010                         // width. As a last fallback, try to convert to pure
2011                         // ASCII using the LaTeX commands defined in unicodesymbols.
2012                         testenc = encodings.fromLyXName("ascii");
2013                         if (!testenc)
2014                                 return docstring();
2015                         ascii_fallback = true;
2016                 }
2017         }
2018         // First and second character of plane 15 (Private Use Area)
2019         string const s1 = "\xf3\xb0\x80\x80"; // U+F0000
2020         string const s2 = "\xf3\xb0\x80\x81"; // U+F0001
2021         // FIXME UNICODE
2022         // lyx::regex is not unicode-safe.
2023         // Should use QRegExp or (boost::u32regex, but that requires ICU)
2024         static regex const reg("_\\(([^\\)]+)\\)");
2025         smatch sub;
2026         while (regex_search(preamble, sub, reg)) {
2027                 string const key = sub.str(1);
2028                 docstring const name = lang->translateLayout(key);
2029                 // Check whether name can be encoded in the buffer encoding
2030                 bool encodable = true;
2031                 for (size_t i = 0; i < name.size() && encodable; ++i)
2032                         if (!testenc->encodable(name[i]))
2033                                 encodable = false;
2034                 string translated;
2035                 if (encodable && !lang_fallback)
2036                         translated = to_utf8(name);
2037                 else if (ascii_fallback)
2038                         translated = to_ascii(testenc->latexString(name).first);
2039                 else
2040                         translated = "\\inputencoding{" + texenc + "}"
2041                                 + s1 + langenc + s2 + to_utf8(name)
2042                                 + s1 + bufenc + s2;
2043                 preamble = subst(preamble, sub.str(), translated);
2044         }
2045         return from_utf8(preamble);
2046 }
2047
2048 } // namespace
2049
2050
2051 docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel,
2052                                 bool use_polyglossia, bool use_minted) const
2053 {
2054         DocumentClass const & tclass = params_.documentClass();
2055         // collect preamble snippets in a set to prevent multiple identical
2056         // commands (would happen if e.g. both theorem and theorem* are used)
2057         set<docstring> snippets;
2058         typedef LanguageList::const_iterator lang_it;
2059         lang_it const lbeg = UsedLanguages_.begin();
2060         lang_it const lend =  UsedLanguages_.end();
2061         list<docstring>::const_iterator cit = usedLayouts_.begin();
2062         list<docstring>::const_iterator end = usedLayouts_.end();
2063         for (; cit != end; ++cit) {
2064                 // language dependent commands (once per document)
2065                 snippets.insert(i18npreamble(tclass[*cit].langpreamble(),
2066                                                 buffer().language(),
2067                                                 buffer().params().encoding(),
2068                                                 use_polyglossia, false));
2069                 // commands for language changing (for multilanguage documents)
2070                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
2071                         snippets.insert(i18npreamble(
2072                                                 tclass[*cit].babelpreamble(),
2073                                                 buffer().language(),
2074                                                 buffer().params().encoding(),
2075                                                 use_polyglossia, false));
2076                         for (lang_it lit = lbeg; lit != lend; ++lit)
2077                                 snippets.insert(i18npreamble(
2078                                                 tclass[*cit].babelpreamble(),
2079                                                 *lit,
2080                                                 buffer().params().encoding(),
2081                                                 use_polyglossia, false));
2082                 }
2083         }
2084         if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
2085                 FloatList const & floats = params_.documentClass().floats();
2086                 UsedFloats::const_iterator fit = usedFloats_.begin();
2087                 UsedFloats::const_iterator fend = usedFloats_.end();
2088                 for (; fit != fend; ++fit) {
2089                         Floating const & fl = floats.getType(fit->first);
2090                         // we assume builtin floats are translated
2091                         if (fl.isPredefined())
2092                                 continue;
2093                         docstring const type = from_ascii(fl.floattype());
2094                         docstring const flname = from_utf8(fl.name());
2095                         docstring name = buffer().language()->translateLayout(fl.name());
2096                         // only request translation if we have a real translation
2097                         // (that differs from the source)
2098                         if (flname != name)
2099                                 snippets.insert(getFloatI18nPreamble(
2100                                                 type, name, buffer().language(),
2101                                                 buffer().params().encoding(),
2102                                                 use_polyglossia));
2103                         for (lang_it lit = lbeg; lit != lend; ++lit) {
2104                                 string const code = (*lit)->code();
2105                                 name = (*lit)->translateLayout(fl.name());
2106                                 // we assume we have a suitable translation if
2107                                 // either the language is English (we need to
2108                                 // translate into English if English is a secondary
2109                                 // language) or if translateIfPossible returns
2110                                 // something different to the English source.
2111                                 bool const have_translation =
2112                                         (flname != name || contains(code, "en"));
2113                                 if (have_translation)
2114                                         snippets.insert(getFloatI18nPreamble(
2115                                                 type, name, *lit,
2116                                                 buffer().params().encoding(),
2117                                                 use_polyglossia));
2118                         }
2119                 }
2120         }
2121
2122         cit = usedInsetLayouts_.begin();
2123         end = usedInsetLayouts_.end();
2124         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
2125         for (; cit != end; ++cit) {
2126                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
2127                 if (it == ils.end())
2128                         continue;
2129                 // The listings package does not work with variable width
2130                 // encodings, only with fixed width encodings. Therefore we
2131                 // need to force a fixed width encoding for
2132                 // \lstlistlistingname and \lstlistingname (bug 9382).
2133                 // This needs to be consistent with InsetListings::latex()
2134                 // rsp. InsetListings::forcedEncoding().
2135                 bool const need_fixedwidth = !use_minted &&
2136                                         !runparams_.isFullUnicode() &&
2137                                         buffer().params().encoding().package() != Encoding::japanese &&
2138                                         it->second.fixedwidthpreambleencoding();
2139                 // language dependent commands (once per document)
2140                 snippets.insert(i18npreamble(it->second.langpreamble(),
2141                                                 buffer().language(),
2142                                                 buffer().params().encoding(),
2143                                                 use_polyglossia, need_fixedwidth));
2144                 // commands for language changing (for multilanguage documents)
2145                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
2146                         snippets.insert(i18npreamble(
2147                                                 it->second.babelpreamble(),
2148                                                 buffer().language(),
2149                                                 buffer().params().encoding(),
2150                                                 use_polyglossia, need_fixedwidth));
2151                         for (lang_it lit = lbeg; lit != lend; ++lit)
2152                                 snippets.insert(i18npreamble(
2153                                                 it->second.babelpreamble(),
2154                                                 *lit,
2155                                                 buffer().params().encoding(),
2156                                                 use_polyglossia, need_fixedwidth));
2157                 }
2158         }
2159
2160         odocstringstream tcpreamble;
2161         set<docstring>::const_iterator const send = snippets.end();
2162         set<docstring>::const_iterator it = snippets.begin();
2163         for (; it != send; ++it)
2164                 tcpreamble << *it;
2165         return tcpreamble.str();
2166 }
2167
2168
2169 docstring const LaTeXFeatures::getLyXSGMLEntities() const
2170 {
2171         // Definition of entities used in the document that are LyX related.
2172         odocstringstream entities;
2173
2174         if (mustProvide("lyxarrow")) {
2175                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
2176         }
2177
2178         return entities.str();
2179 }
2180
2181
2182 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
2183 {
2184         odocstringstream sgmlpreamble;
2185         // FIXME UNICODE
2186         docstring const basename(from_utf8(onlyPath(fname)));
2187
2188         FileMap::const_iterator end = IncludedFiles_.end();
2189         for (FileMap::const_iterator fi = IncludedFiles_.begin();
2190              fi != end; ++fi)
2191                 // FIXME UNICODE
2192                 sgmlpreamble << "\n<!ENTITY " << fi->first
2193                              << (isSGMLFileName(fi->second) ? " SYSTEM \"" : " \"")
2194                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
2195
2196         return sgmlpreamble.str();
2197 }
2198
2199
2200 void LaTeXFeatures::showStruct() const
2201 {
2202         lyxerr << "LyX needs the following commands when LaTeXing:"
2203                << "\n***** Packages:" << getPackages()
2204                << "\n***** Macros:" << to_utf8(getMacros().str)
2205                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
2206                << "\n***** done." << endl;
2207 }
2208
2209
2210 Buffer const & LaTeXFeatures::buffer() const
2211 {
2212         return *buffer_;
2213 }
2214
2215
2216 void LaTeXFeatures::setBuffer(Buffer const & buffer)
2217 {
2218         buffer_ = &buffer;
2219 }
2220
2221
2222 BufferParams const & LaTeXFeatures::bufferParams() const
2223 {
2224         return params_;
2225 }
2226
2227
2228 void LaTeXFeatures::getFloatDefinitions(otexstream & os) const
2229 {
2230         FloatList const & floats = params_.documentClass().floats();
2231
2232         // Here we will output the code to create the needed float styles.
2233         // We will try to do this as minimal as possible.
2234         // \floatstyle{ruled}
2235         // \newfloat{algorithm}{htbp}{loa}
2236         // \providecommand{\algorithmname}{Algorithm}
2237         // \floatname{algorithm}{\protect\algorithmname}
2238         UsedFloats::const_iterator cit = usedFloats_.begin();
2239         UsedFloats::const_iterator end = usedFloats_.end();
2240         for (; cit != end; ++cit) {
2241                 Floating const & fl = floats.getType(cit->first);
2242
2243                 // For builtin floats we do nothing.
2244                 if (fl.isPredefined())
2245                         continue;
2246
2247                 // We have to special case "table" and "figure"
2248                 if (fl.floattype() == "tabular" || fl.floattype() == "figure") {
2249                         // Output code to modify "table" or "figure"
2250                         // but only if builtin == false
2251                         // and that have to be true at this point in the
2252                         // function.
2253                         docstring const type = from_ascii(fl.floattype());
2254                         docstring const placement = from_ascii(fl.placement());
2255                         docstring const style = from_ascii(fl.style());
2256                         if (!style.empty()) {
2257                                 os << "\\floatstyle{" << style << "}\n"
2258                                    << "\\restylefloat{" << type << "}\n";
2259                         }
2260                         if (!placement.empty()) {
2261                                 os << "\\floatplacement{" << type << "}{"
2262                                    << placement << "}\n";
2263                         }
2264                 } else {
2265                         // The other non builtin floats.
2266
2267                         docstring const type = from_ascii(fl.floattype());
2268                         docstring const placement = from_ascii(fl.placement());
2269                         docstring const ext = from_ascii(fl.ext());
2270                         docstring const within = from_ascii(fl.within());
2271                         docstring const style = from_ascii(fl.style());
2272                         docstring const name =
2273                                 buffer().language()->translateLayout(fl.name());
2274                         os << "\\floatstyle{" << style << "}\n"
2275                            << "\\newfloat{" << type << "}{" << placement
2276                            << "}{" << ext << '}';
2277                         if (!within.empty())
2278                                 os << '[' << within << ']';
2279                         os << '\n'
2280                            << "\\providecommand{\\" << type << "name}{"
2281                            << name << "}\n"
2282                            << "\\floatname{" << type << "}{\\protect\\"
2283                            << type << "name}\n";
2284
2285                         // What missing here is to code to minimalize the code
2286                         // output so that the same floatstyle will not be
2287                         // used several times, when the same style is still in
2288                         // effect. (Lgb)
2289                 }
2290                 if (cit->second)
2291                         // The subfig package is loaded later
2292                         os << "\n\\AtBeginDocument{\\newsubfloat{" << from_ascii(fl.floattype()) << "}}\n";
2293         }
2294 }
2295
2296
2297 void LaTeXFeatures::resolveAlternatives()
2298 {
2299         for (Features::iterator it = features_.begin(); it != features_.end();) {
2300                 if (contains(*it, '|')) {
2301                         vector<string> const alternatives = getVectorFromString(*it, "|");
2302                         vector<string>::const_iterator const end = alternatives.end();
2303                         vector<string>::const_iterator ita = alternatives.begin();
2304                         // Is any alternative already required? => use that
2305                         for (; ita != end; ++ita) {
2306                                 if (isRequired(*ita))
2307                                         break;
2308                         }
2309                         // Is any alternative available? => use the first one
2310                         // (bug 9498)
2311                         if (ita == end) {
2312                                 for (ita = alternatives.begin(); ita != end; ++ita) {
2313                                         if (isAvailable(*ita)) {
2314                                                 require(*ita);
2315                                                 break;
2316                                         }
2317                                 }
2318                         }
2319                         // This will not work, but not requiring something
2320                         // would be more confusing
2321                         if (ita == end)
2322                                 require(alternatives.front());
2323                         features_.erase(it);
2324                         it = features_.begin();
2325                 } else
2326                         ++it;
2327         }
2328 }
2329
2330
2331 void LaTeXFeatures::expandMultiples()
2332 {
2333         for (Features::iterator it = features_.begin(); it != features_.end();) {
2334                 if (contains(*it, ',')) {
2335                         vector<string> const multiples = getVectorFromString(*it, ",");
2336                         vector<string>::const_iterator const end = multiples.end();
2337                         vector<string>::const_iterator itm = multiples.begin();
2338                         // Do nothing if any multiple is already required
2339                         for (; itm != end; ++itm) {
2340                                 if (!isRequired(*itm))
2341                                         require(*itm);
2342                         }
2343                         features_.erase(it);
2344                         it = features_.begin();
2345                 } else
2346                         ++it;
2347         }
2348 }
2349
2350
2351 } // namespace lyx