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