]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
Avoid full metrics computation with Update:FitCursor
[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         // the following 3 color commands must be set after color
1217         // is loaded and before pdfpages, therefore add the command
1218         // here define the set color
1219         if (mustProvide("pagecolor")) {
1220                 colors << "\\definecolor{page_backgroundcolor}{rgb}{";
1221                 colors << outputLaTeXColor(params_.backgroundcolor) << "}\n";
1222                 // set the page color
1223                 colors << "\\pagecolor{page_backgroundcolor}\n";
1224         }
1225
1226         if (mustProvide("fontcolor")) {
1227                 colors << "\\definecolor{document_fontcolor}{rgb}{";
1228                 colors << outputLaTeXColor(params_.fontcolor) << "}\n";
1229                 // set the color
1230                 colors << "\\color{document_fontcolor}\n";
1231         }
1232
1233         if (mustProvide("lyxgreyedout")) {
1234                 colors << "\\definecolor{note_fontcolor}{rgb}{";
1235                 colors << outputLaTeXColor(params_.notefontcolor) << "}\n";
1236                 // the color will be set together with the definition of
1237                 // the lyxgreyedout environment (see lyxgreyedout_def)
1238         }
1239
1240         // color for shaded boxes
1241         if (isRequired("framed") && mustProvide("color")) {
1242                 colors << "\\definecolor{shadecolor}{rgb}{";
1243                 colors << outputLaTeXColor(params_.boxbgcolor) << "}\n";
1244                 // this color is automatically used by the LaTeX-package "framed"
1245         }
1246
1247         return colors.str();
1248 }
1249
1250
1251 string const LaTeXFeatures::getPackageOptions() const
1252 {
1253         ostringstream packageopts;
1254         // Output all the package option stuff we have been asked to do.
1255         for (auto const & p : params_.documentClass().packageOptions())
1256                 if (mustProvide(p.first))
1257                         packageopts << "\\PassOptionsToPackage{" << p.second << "}"
1258                                  << "{" << p.first << "}\n";
1259         return packageopts.str();
1260 }
1261
1262
1263 string const LaTeXFeatures::getPackages() const
1264 {
1265         ostringstream packages;
1266
1267         // FIXME: currently, we can only load packages and macros known
1268         // to LyX.
1269         // However, with the Require tag of layouts/custom insets,
1270         // also unknown packages can be requested. They are silently
1271         // swallowed now. We should change this eventually.
1272
1273         // Simple hooks to add things before or after a given "simple"
1274         // feature. Useful if loading order matters.
1275         map<string, string> before_simplefeature_;
1276         map<string, string> after_simplefeature_;
1277
1278         // Babel languages with activated colon (such as French) break
1279         // with prettyref. Work around that.
1280         if (mustProvide("prettyref") && !runparams_.isFullUnicode()
1281             && useBabel() && contains(getActiveChars(), ':')) {
1282                 before_simplefeature_["prettyref"] =
1283                                 "% Make prettyref compatible with babel active colon\n"
1284                                 "% (make ':' active in prettyref definitions)\n"
1285                                 "\\edef\\lyxsavedcolcatcode{\\the\\catcode`\\:}\n"
1286                                 "\\catcode`:=13\n";
1287                 after_simplefeature_["prettyref"] =
1288                                 "% restore original catcode for :\n"
1289                                 "\\catcode`\\:=\\lyxsavedcolcatcode\\relax\n";
1290         }
1291         
1292         //  These are all the 'simple' includes.  i.e
1293         //  packages which we just \usepackage{package}
1294         //  potentially preceded and followed by the hook code
1295         for (char const * feature : simplefeatures) {
1296                 if (mustProvide(feature)) {
1297                         if (before_simplefeature_.find(feature) != before_simplefeature_.end())
1298                                 packages << before_simplefeature_[feature];
1299                         packages << "\\usepackage{" << feature << "}\n";
1300                         if (after_simplefeature_.find(feature) != after_simplefeature_.end())
1301                                 packages << after_simplefeature_[feature];
1302                 }
1303         }
1304
1305         // The rest of these packages are somewhat more complicated
1306         // than those above.
1307
1308         if (mustProvide("changebar")) {
1309                 packages << "\\usepackage";
1310                 if (runparams_.flavor == Flavor::LaTeX
1311                     || runparams_.flavor == Flavor::DviLuaTeX)
1312                         packages << "[dvips]";
1313                 packages << "{changebar}\n";
1314         }
1315
1316         if (mustProvide("footnote")) {
1317                 if (isRequired("hyperref"))
1318                         packages << "\\usepackage{footnotehyper}\n";
1319                 else
1320                         packages << "\\usepackage{footnote}\n";
1321         }
1322
1323         // [pdf]lscape is used to rotate longtables
1324         if (mustProvide("lscape")) {
1325                 if (runparams_.flavor == Flavor::LaTeX
1326                     || runparams_.flavor == Flavor::DviLuaTeX)
1327                         packages << "\\usepackage{lscape}\n";
1328                 else
1329                         packages << "\\usepackage{pdflscape}\n";
1330         }
1331
1332         // The tipa package and its extensions (tipx, tone) must not
1333         // be loaded with non-TeX fonts, since fontspec includes the
1334         // respective macros
1335         if (mustProvide("tipa") && !params_.useNonTeXFonts)
1336                 packages << "\\usepackage{tipa}\n";
1337         if (mustProvide("tipx") && !params_.useNonTeXFonts)
1338                 packages << "\\usepackage{tipx}\n";
1339         if (mustProvide("extraipa") && !params_.useNonTeXFonts)
1340                 packages << "\\usepackage{extraipa}\n";
1341         if (mustProvide("tone") && !params_.useNonTeXFonts)
1342                 packages << "\\usepackage{tone}\n";
1343
1344         // if fontspec or newtxmath is used, AMS packages have to be loaded
1345         // before fontspec (in BufferParams)
1346         string const amsPackages = loadAMSPackages();
1347         bool const ot1 = (runparams().main_fontenc == "default"
1348                           || runparams().main_fontenc == "OT1");
1349         bool const use_newtxmath =
1350                 theLaTeXFonts().getLaTeXFont(from_ascii(params_.fontsMath())).getUsedPackage(
1351                         ot1, false, false) == "newtxmath";
1352
1353         if (!params_.useNonTeXFonts && !use_newtxmath && !amsPackages.empty())
1354                 packages << amsPackages;
1355
1356         if (mustProvide("cancel") &&
1357             params_.use_package("cancel") != BufferParams::package_off)
1358                 packages << "\\usepackage{cancel}\n";
1359
1360         // marvosym and bbding both define the \Cross macro
1361         if (mustProvide("marvosym")) {
1362             if (mustProvide("bbding"))
1363                 packages << "\\let\\Cross\\relax\n";
1364             packages << "\\usepackage{marvosym}\n";
1365         }
1366
1367         // accents must be loaded after amsmath
1368         if (mustProvide("accents") &&
1369             params_.use_package("accents") != BufferParams::package_off)
1370                 packages << "\\usepackage{accents}\n";
1371
1372         // mathdots must be loaded after amsmath
1373         if (mustProvide("mathdots") &&
1374                 params_.use_package("mathdots") != BufferParams::package_off)
1375                 packages << "\\usepackage{mathdots}\n";
1376
1377         // yhmath must be loaded after amsmath
1378         if (mustProvide("yhmath") &&
1379             params_.use_package("yhmath") != BufferParams::package_off)
1380                 packages << "\\usepackage{yhmath}\n";
1381
1382         // stmaryrd must be loaded after amsmath
1383         if (mustProvide("stmaryrd") &&
1384             params_.use_package("stmaryrd") != BufferParams::package_off)
1385                 packages << "\\usepackage{stmaryrd}\n";
1386
1387         if (mustProvide("stackrel") &&
1388             params_.use_package("stackrel") != BufferParams::package_off)
1389                 packages << "\\usepackage{stackrel}\n";
1390
1391         if (mustProvide("undertilde") &&
1392                 params_.use_package("undertilde") != BufferParams::package_off)
1393                 packages << "\\usepackage{undertilde}\n";
1394
1395         // [x]color is handled in getColorOptions() above
1396
1397         // makeidx.sty
1398         if (isRequired("makeidx") || isRequired("splitidx")) {
1399                 if (!isProvided("makeidx") && !isRequired("splitidx"))
1400                         packages << "\\usepackage{makeidx}\n";
1401                 if (mustProvide("splitidx"))
1402                         packages << "\\usepackage{splitidx}\n";
1403                 packages << "\\makeindex\n";
1404         }
1405
1406         // graphicx.sty
1407         if (mustProvide("graphicx") && params_.graphics_driver != "none") {
1408                 if (params_.graphics_driver == "default")
1409                         packages << "\\usepackage{graphicx}\n";
1410                 else
1411                         packages << "\\usepackage["
1412                                  << params_.graphics_driver
1413                                  << "]{graphicx}\n";
1414         }
1415
1416         // These must be loaded after graphicx, since they try
1417         // to load graphicx without options
1418         if (mustProvide("rotating"))
1419                 packages << "\\usepackage{rotating}\n";
1420         if (mustProvide("rotfloat"))
1421                 packages << "\\usepackage{rotfloat}\n";
1422         // and this must be loaded after rotating
1423         if (mustProvide("tablefootnote"))
1424                 packages << "\\usepackage{tablefootnote}\n";
1425
1426         // lyxskak.sty --- newer chess support based on skak.sty
1427         if (mustProvide("chess"))
1428                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
1429
1430         // setspace.sty
1431         if (mustProvide("setspace") && !isProvided("SetSpace"))
1432                 packages << "\\usepackage{setspace}\n";
1433
1434         // we need to assure that mhchem is loaded before esint and every other
1435         // package that redefines command of amsmath because mhchem loads amlatex
1436         // (this info is from the author of mhchem from June 2013)
1437         if (mustProvide("mhchem") &&
1438             params_.use_package("mhchem") != BufferParams::package_off)
1439                 packages << "\\PassOptionsToPackage{version=3}{mhchem}\n"
1440                             "\\usepackage{mhchem}\n";
1441
1442         // wasysym is a simple feature, but it must be after amsmath if both
1443         // are used
1444         // wasysym redefines some integrals (e.g. iint) from amsmath. That
1445         // leads to inconsistent integrals. We only load this package if
1446         // the document does not contain integrals (then isRequired("esint")
1447         // is false) or if esint is used, since esint redefines all relevant
1448         // integral symbols from wasysym and amsmath.
1449         // See http://www.lyx.org/trac/ticket/1942
1450         if (mustProvide("wasysym") &&
1451             params_.use_package("wasysym") != BufferParams::package_off &&
1452             (params_.use_package("esint") != BufferParams::package_off || !isRequired("esint")))
1453                 packages << "\\usepackage{wasysym}\n";
1454
1455         // esint must be after amsmath (and packages requiring amsmath, like mhchem)
1456         // and wasysym, since it will redeclare inconsistent integral symbols
1457         if (mustProvide("esint") &&
1458             params_.use_package("esint") != BufferParams::package_off)
1459                 packages << "\\usepackage{esint}\n";
1460
1461         // Known bibliography packages (simple \usepackage{package})
1462         for (char const * feature : bibliofeatures) {
1463                 if (mustProvide(feature))
1464                         packages << "\\usepackage{" << feature << "}\n";
1465         }
1466
1467         // Compatibility between achicago and natbib
1468         if (mustProvide("achicago") && mustProvide("natbib"))
1469                 packages << "\\let\\achicagobib\\thebibliography\n";
1470
1471         // natbib.sty
1472         // Some classes load natbib themselves, but still allow (or even require)
1473         // plain numeric citations (ReVTeX is such a case, see bug 5182).
1474         // This special case is indicated by the "natbib-internal" key.
1475         if (mustProvide("natbib")
1476             && !isProvided("natbib-internal")
1477             && !isProvided("biblatex")
1478             && !isProvided("biblatex-natbib")
1479             && !isProvided("jurabib")) {
1480                 packages << "\\usepackage[";
1481                 if (params_.citeEngineType() == ENGINE_TYPE_NUMERICAL)
1482                         packages << "numbers";
1483                 else
1484                         packages << "authoryear";
1485                 if (!params_.biblio_opts.empty())
1486                         packages << ',' << params_.biblio_opts;
1487                 packages << "]{natbib}\n";
1488         }
1489
1490         // Compatibility between achicago and natbib
1491         if (mustProvide("achicago") && mustProvide("natbib")) {
1492                 packages << "\\let\\thebibliography\\achicagobib\n";
1493                 packages << "\\let\\SCcite\\astroncite\n";
1494                 packages << "\\let\\UnexpandableProtect\\protect\n";
1495         }
1496
1497         // jurabib -- we need version 0.6 at least.
1498         if (mustProvide("jurabib")
1499             && !isProvided("natbib-internal")
1500             && !isProvided("natbib")
1501             && !isProvided("biblatex")
1502             && !isProvided("biblatex-natbib")) {
1503                 packages << "\\usepackage";
1504                 if (!params_.biblio_opts.empty())
1505                         packages << '[' << params_.biblio_opts << ']';
1506                 packages << "{jurabib}[2004/01/25]\n";
1507         }
1508
1509         // opcit -- we pass custombst as we output \bibliographystyle ourselves
1510         if (mustProvide("opcit")) {
1511                 if (isRequired("hyperref"))
1512                         packages << "\\usepackage[custombst,hyperref]{opcit}\n";
1513                 else
1514                         packages << "\\usepackage[custombst]{opcit}\n";
1515         }
1516
1517         // xargs -- we need version 1.09 at least
1518         if (mustProvide("xargs"))
1519                 packages << "\\usepackage{xargs}[2008/03/08]\n";
1520
1521         if (mustProvide("xy"))
1522                 packages << "\\usepackage[all]{xy}\n";
1523
1524         if (mustProvide("feyn"))
1525                 packages << "\\usepackage{feyn}\n"; //Diagram
1526
1527         if (mustProvide("ulem"))
1528                 packages << "\\PassOptionsToPackage{normalem}{ulem}\n"
1529                             "\\usepackage{ulem}\n";
1530
1531         if (mustProvide("nomencl")) {
1532                 packages << "\\usepackage{nomencl}\n";
1533                 // Make it work with the new and old version of the package,
1534                 // but don't use the compatibility option since it is
1535                 // incompatible to other packages.
1536                 if (!LaTeXFeatures::isAvailableAtLeastFrom("nomencl", 2005, 3, 31)) {
1537                         packages << "% Needed with nomencl < v4.1\n"
1538                                     "\\providecommand{\\printnomenclature}{\\printglossary}\n"
1539                                     "\\providecommand{\\makenomenclature}{\\makeglossary}\n";
1540                 }
1541                 packages << "\\makenomenclature\n";
1542         }
1543
1544         // fixltx2e provides subscript
1545         if (mustProvide("subscript") && !isRequired("fixltx2e")
1546             && !isAvailableAtLeastFrom("LaTeX", 2005, 12))
1547                 packages << "\\usepackage{subscript}\n";
1548
1549         // footmisc must be loaded after setspace
1550         // Set options here, load the package after the user preamble to
1551         // avoid problems with manual loaded footmisc.
1552         if (mustProvide("footmisc"))
1553                 packages << "\\PassOptionsToPackage{stable}{footmisc}\n";
1554
1555         if (mustProvide("microtype")){
1556                 packages << "\\usepackage{microtype}\n";
1557         }
1558
1559         return packages.str();
1560 }
1561
1562
1563 TexString LaTeXFeatures::getMacros() const
1564 {
1565         otexstringstream macros;
1566
1567         if (!preamble_snippets_.empty()) {
1568                 macros << '\n';
1569                 macros << getPreambleSnippets();
1570         }
1571
1572         if (mustProvide("xetexdashbreakstate"))
1573                 macros << "\\XeTeXdashbreakstate 0" << '\n';
1574
1575         if (mustProvide("papersize")) {
1576                 if (runparams_.flavor == Flavor::LaTeX
1577                     || runparams_.flavor == Flavor::DviLuaTeX)
1578                         macros << papersizedvi_def << '\n';
1579                 else if  (runparams_.flavor == Flavor::LuaTeX)
1580                         macros << papersizepdflua_def << '\n';
1581                 else
1582                         macros << papersizepdf_def << '\n';
1583         }
1584
1585         if (mustProvide("LyX")) {
1586                 macros << "\\providecommand{\\LyX}";
1587                 // open conditional wrappers
1588                 if (runparams_.use_polyglossia && hasRTLLanguage())
1589                         macros << "{\\@ensure@LTR";
1590                 if (isRequired("hyperref"))
1591                         macros << "{\\texorpdfstring";
1592                 if (useBabel())
1593                         macros << "{\\ensureascii";
1594                 // main definition
1595                 macros << lyx_def;
1596                 // close conditional wrappers
1597                 if (useBabel())
1598                         macros << '}';
1599                 if (isRequired("hyperref"))
1600                         macros << "{LyX}}";
1601                 if (runparams_.use_polyglossia && hasRTLLanguage())
1602                         macros << '}';
1603                 macros << '\n';
1604         }
1605
1606         if (mustProvide("noun"))
1607                 macros << noun_def << '\n';
1608
1609         if (mustProvide("lyxarrow"))
1610                 macros << lyxarrow_def << '\n';
1611
1612         if (mustProvide("aastex_case"))
1613                 macros << aastex_case_def << '\n';
1614
1615         if (mustProvide("lyxzerowidthspace"))
1616                 macros << lyxZWSP_def << '\n';
1617
1618         if (!usePolyglossia() && mustProvide("textgreek")) {
1619                 // ensure LGR font encoding is defined also if fontenc is not loaded by LyX
1620                 if (runparams().main_fontenc == "default")
1621                         macros << textgreek_LGR_def;
1622                 macros << textgreek_def << '\n';
1623         }
1624
1625         if (!usePolyglossia() && mustProvide("textcyrillic")) {
1626                 // ensure T2A font encoding is set up also if fontenc is not loaded by LyX
1627                 if (runparams().main_fontenc == "default")
1628                         macros << textcyr_T2A_def;
1629                 macros << textcyr_def << '\n';
1630         }
1631
1632         // non-standard text accents:
1633         if (mustProvide("textcommaabove") || mustProvide("textcommaaboveright") ||
1634             mustProvide("textcommabelow") || mustProvide("textbaltic"))
1635                 macros << lyxaccent_def;
1636
1637         if (mustProvide("textcommabelow") || mustProvide("textbaltic"))
1638                 macros << textcommabelow_def << '\n';
1639
1640         if (mustProvide("textcommaabove") || mustProvide("textbaltic"))
1641                 macros << textcommaabove_def << '\n';
1642
1643         if (mustProvide("textcommaaboveright"))
1644                 macros << textcommaaboveright_def << '\n';
1645
1646         if (mustProvide("textbaltic"))
1647                 macros << textbaltic_def << '\n';
1648
1649         if (mustProvide("textschwa"))
1650                 macros << textschwa_def << '\n';
1651
1652         // split-level fractions
1653         if (mustProvide("xfrac") || mustProvide("smallLetterFrac"))
1654                 macros << xfrac_def << '\n';
1655
1656         if (mustProvide("smallLetterFrac"))
1657                 macros << smallLetterFrac_def << '\n';
1658
1659         if (mustProvide("lyxmathsym"))
1660                 macros << lyxmathsym_def << '\n';
1661
1662         if (mustProvide("cedilla"))
1663                 macros << cedilla_def << '\n';
1664
1665         if (mustProvide("subring"))
1666                 macros << subring_def << '\n';
1667
1668         if (mustProvide("subdot"))
1669                 macros << subdot_def << '\n';
1670
1671         if (mustProvide("subhat"))
1672                 macros << subhat_def << '\n';
1673
1674         if (mustProvide("subtilde"))
1675                 macros << subtilde_def << '\n';
1676
1677         if (mustProvide("dacute"))
1678                 macros << dacute_def << '\n';
1679
1680         if (mustProvide("tipasymb"))
1681                 macros << tipasymb_def << '\n';
1682
1683         if (mustProvide("dgrave"))
1684                 macros << dgrave_def << '\n';
1685
1686         if (mustProvide("rcap"))
1687                 macros << rcap_def << '\n';
1688
1689         if (mustProvide("ogonek"))
1690                 macros << ogonek_def << '\n';
1691
1692         // quotes.
1693         if (mustProvide("quotesinglbase"))
1694                 macros << quotesinglbase_def << '\n';
1695         if (mustProvide("quotedblbase"))
1696                 macros << quotedblbase_def << '\n';
1697         if (mustProvide("guilsinglleft"))
1698                 macros << guilsinglleft_def << '\n';
1699         if (mustProvide("guilsinglright"))
1700                 macros << guilsinglright_def << '\n';
1701         if (mustProvide("guillemotleft"))
1702                 macros << guillemotleft_def << '\n';
1703         if (mustProvide("guillemotright"))
1704                 macros << guillemotright_def << '\n';
1705         if (mustProvide("textquotedbl"))
1706                 macros << textquotedbl_def << '\n';
1707         if (mustProvide("textquotesinglep")) {
1708                 if (runparams_.flavor == Flavor::XeTeX)
1709                         macros << textquotesinglep_xetex_def << '\n';
1710                 else
1711                         macros << textquotesinglep_luatex_def << '\n';
1712         }
1713         if (mustProvide("textquotedblp")) {
1714                 if (runparams_.flavor == Flavor::XeTeX)
1715                         macros << textquotedblp_xetex_def << '\n';
1716                 else
1717                         macros << textquotedblp_luatex_def << '\n';
1718         }
1719
1720         // Math mode
1721         if (mustProvide("binom") && !isRequired("amsmath"))
1722                 macros << binom_def << '\n';
1723         if (mustProvide("mathcircumflex"))
1724                 macros << mathcircumflex_def << '\n';
1725
1726         // other
1727         if (mustProvide("ParagraphLeftIndent"))
1728                 macros << paragraphleftindent_def;
1729         if (mustProvide("NeedLyXFootnoteCode"))
1730                 macros << floatingfootnote_def;
1731
1732         // some problems with tex->html converters
1733         if (mustProvide("NeedTabularnewline"))
1734                 macros << tabularnewline_def;
1735
1736         if (mustProvide("cellvarwidth"))
1737                 macros << cellvarwidth_def;
1738
1739         // greyed-out environment (note inset)
1740         // the color is specified in the routine
1741         // getColorOptions() to avoid LaTeX-package clashes
1742         if (mustProvide("lyxgreyedout"))
1743                 // We need different version for RTL (#8647), with change tracking (#12025)
1744                 // and for some specific engine/language package combinations
1745                 macros << lyxgreyedoutDef(hasRTLLanguage(), mustProvide("ct-xcolor-ulem"),
1746                                           (runparams_.flavor == Flavor::LuaTeX), useBabel());
1747
1748         if (mustProvide("lyxdot"))
1749                 macros << lyxdot_def << '\n';
1750
1751         // floats
1752         getFloatDefinitions(macros);
1753
1754         if (mustProvide("refstyle"))
1755                 macros << lyxref_def << '\n';
1756
1757         // change tracking
1758         if (mustProvide("ct-xcolor-ulem")) {
1759                 streamsize const prec = macros.os().precision(2);
1760
1761                 RGBColor cadd = rgbFromHexName(lcolor.getX11HexName(Color_addedtext_output));
1762                 macros << "\\providecolor{lyxadded}{rgb}{"
1763                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
1764
1765                 RGBColor cdel = rgbFromHexName(lcolor.getX11HexName(Color_deletedtext_output));
1766                 macros << "\\providecolor{lyxdeleted}{rgb}{"
1767                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
1768
1769                 macros.os().precision(prec);
1770
1771                 macros << changetracking_xcolor_ulem_base_def;
1772
1773                 if (isRequired("changebar")) {
1774                         if (isRequired("hyperref"))
1775                                 macros << changetracking_xcolor_ulem_hyperref_cb_def;
1776                         else
1777                                 macros << changetracking_xcolor_ulem_cb_def;
1778                 } else {
1779                         if (isRequired("hyperref"))
1780                                 macros << changetracking_xcolor_ulem_hyperref_def;
1781                         else
1782                                 macros << changetracking_xcolor_ulem_def;
1783                 }
1784         }
1785
1786         if (mustProvide("ct-tikz-object-sout")) {
1787                 if (!mustProvide("ct-xcolor-ulem")) {
1788                         streamsize const prec = macros.os().precision(2);
1789
1790                         RGBColor cadd = rgbFromHexName(lcolor.getX11HexName(Color_addedtext_output));
1791                         macros << "\\providecolor{lyxadded}{rgb}{"
1792                                << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
1793         
1794                         RGBColor cdel = rgbFromHexName(lcolor.getX11HexName(Color_deletedtext_output));
1795                         macros << "\\providecolor{lyxdeleted}{rgb}{"
1796                                << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
1797         
1798                         macros.os().precision(prec);
1799                 }
1800                 
1801                 macros << changetracking_tikz_object_sout_def;
1802                 
1803                 if (isRequired("changebar")) {
1804                         if (isRequired("hyperref"))
1805                                 macros << changetracking_xcolor_ulem_hyperref_cb_object_def;
1806                         else
1807                                 macros << changetracking_xcolor_ulem_cb_object_def;
1808                 } else {
1809                         if (isRequired("hyperref"))
1810                                 macros << changetracking_xcolor_ulem_hyperref_object_def;
1811                         else
1812                                 macros << changetracking_xcolor_ulem_object_def;
1813                 }
1814         }
1815
1816         if (mustProvide("ct-none"))
1817                 macros << changetracking_none_def;
1818
1819         if (mustProvide("rtloutputdblcol"))
1820                 macros << rtloutputdblcol_def;
1821
1822         if (mustProvide("lyxmintcaption"))
1823                 macros << lyxmintcaption_def;
1824
1825         return macros.release();
1826 }
1827
1828
1829 docstring const LaTeXFeatures::getBabelPresettings() const
1830 {
1831         odocstringstream tmp;
1832
1833         for (auto const & lang : UsedLanguages_)
1834                 if (!lang->babel_presettings().empty())
1835                         tmp << lang->babel_presettings() << '\n';
1836         if (!params_.language->babel_presettings().empty())
1837                 tmp << params_.language->babel_presettings() << '\n';
1838
1839         if (!contains(tmp.str(), '@'))
1840                 return tmp.str();
1841
1842         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1843 }
1844
1845
1846 docstring const LaTeXFeatures::getBabelPostsettings() const
1847 {
1848         odocstringstream tmp;
1849
1850         for (auto const & lang : UsedLanguages_)
1851                 if (!lang->babel_postsettings().empty())
1852                         tmp << lang->babel_postsettings() << '\n';
1853         if (!params_.language->babel_postsettings().empty())
1854                 tmp << params_.language->babel_postsettings() << '\n';
1855
1856         if (!contains(tmp.str(), '@'))
1857                 return tmp.str();
1858
1859         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1860 }
1861
1862
1863 string const LaTeXFeatures::loadAMSPackages() const
1864 {
1865         ostringstream tmp;
1866
1867         if (mustProvide("amsmath")
1868             && params_.use_package("amsmath") != BufferParams::package_off) {
1869                 tmp << "\\usepackage{amsmath}\n";
1870         } else {
1871                 // amsbsy and amstext are already provided by amsmath
1872                 if (mustProvide("amsbsy"))
1873                         tmp << "\\usepackage{amsbsy}\n";
1874                 if (mustProvide("amstext"))
1875                         tmp << "\\usepackage{amstext}\n";
1876         }
1877
1878         if (mustProvide("amsthm"))
1879                 tmp << "\\usepackage{amsthm}\n";
1880
1881         if (mustProvide("amssymb")
1882             && params_.use_package("amssymb") != BufferParams::package_off)
1883                 tmp << "\\usepackage{amssymb}\n";
1884
1885         return tmp.str();
1886 }
1887
1888
1889 docstring const LaTeXFeatures::getTClassPreamble() const
1890 {
1891         // the text class specific preamble
1892         DocumentClass const & tclass = params_.documentClass();
1893         odocstringstream tcpreamble;
1894
1895         tcpreamble << tclass.preamble();
1896
1897         list<docstring>::const_iterator cit = usedLayouts_.begin();
1898         list<docstring>::const_iterator end = usedLayouts_.end();
1899         for (; cit != end; ++cit)
1900                 // For InPreamble layouts, we output the preamble stuff earlier
1901                 // (before the layouts). See Paragraph::Private::validate.
1902                 if (!tclass[*cit].inpreamble)
1903                         tcpreamble << tclass[*cit].preamble();
1904
1905         cit = usedInsetLayouts_.begin();
1906         end = usedInsetLayouts_.end();
1907         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1908         for (; cit != end; ++cit) {
1909                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1910                 if (it == ils.end())
1911                         continue;
1912                 tcpreamble << it->second.preamble();
1913         }
1914
1915         return tcpreamble.str();
1916 }
1917
1918
1919 docstring const LaTeXFeatures::getTClassHTMLPreamble() const
1920 {
1921         DocumentClass const & tclass = params_.documentClass();
1922         odocstringstream tcpreamble;
1923
1924         tcpreamble << tclass.htmlpreamble();
1925
1926         list<docstring>::const_iterator cit = usedLayouts_.begin();
1927         list<docstring>::const_iterator end = usedLayouts_.end();
1928         for (; cit != end; ++cit)
1929                 tcpreamble << tclass[*cit].htmlpreamble();
1930
1931         cit = usedInsetLayouts_.begin();
1932         end = usedInsetLayouts_.end();
1933         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1934         for (; cit != end; ++cit) {
1935                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1936                 if (it == ils.end())
1937                         continue;
1938                 tcpreamble << it->second.htmlpreamble();
1939         }
1940
1941         return tcpreamble.str();
1942 }
1943
1944
1945 docstring const LaTeXFeatures::getTClassHTMLStyles() const
1946 {
1947         DocumentClass const & tclass = params_.documentClass();
1948         odocstringstream tcpreamble;
1949
1950         if (mustProvide("noun"))
1951                 tcpreamble << lyxnoun_style;
1952         // this isn't exact, but it won't hurt that much if it
1953         // wasn't for this.
1954         if (mustProvide("ulem"))
1955                 tcpreamble << lyxstrikeout_style;
1956
1957         tcpreamble << tclass.htmlstyles();
1958
1959         for (auto const & c : usedLayouts_)
1960                 tcpreamble << tclass[c].htmlstyle();
1961
1962         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1963         for (auto const & c : usedInsetLayouts_) {
1964                 TextClass::InsetLayouts::const_iterator it = ils.find(c);
1965                 if (it == ils.end())
1966                         continue;
1967                 tcpreamble << it->second.htmlstyle();
1968         }
1969
1970         return tcpreamble.str();
1971 }
1972
1973
1974 namespace {
1975
1976 docstring const getFloatI18nPreamble(docstring const & type,
1977                         docstring const & name, Language const * lang,
1978                         Encoding const & enc, bool const polyglossia)
1979 {
1980         // Check whether name can be encoded in the buffer encoding
1981         bool encodable = true;
1982         for (char_type c : name) {
1983                 if (!enc.encodable(c)) {
1984                         encodable = false;
1985                         break;
1986                 }
1987         }
1988
1989         docstring const language = polyglossia ? from_ascii(lang->polyglossia())
1990                                                : from_ascii(lang->babel());
1991         docstring const langenc = from_ascii(lang->encoding()->iconvName());
1992         docstring const texenc = from_ascii(lang->encoding()->latexName());
1993         docstring const bufenc = from_ascii(enc.iconvName());
1994         docstring const s1 = docstring(1, 0xF0000);
1995         docstring const s2 = docstring(1, 0xF0001);
1996         docstring const translated = encodable ? name
1997                 : from_ascii("\\inputencoding{") + texenc + from_ascii("}")
1998                         + s1 + langenc + s2 + name + s1 + bufenc + s2;
1999
2000         odocstringstream os;
2001         os << "\\addto\\captions" << language
2002            << "{\\renewcommand{\\" << type << "name}{" << translated << "}}\n";
2003         return os.str();
2004 }
2005
2006
2007 docstring const i18npreamble(docstring const & templ, Language const * lang,
2008                              Encoding const & enc, bool const polyglossia,
2009                              bool const need_fixedwidth)
2010 {
2011         if (templ.empty())
2012                 return templ;
2013
2014         string preamble = polyglossia ?
2015                 subst(to_utf8(templ), "$$lang", lang->polyglossia()) :
2016                 subst(to_utf8(templ), "$$lang", lang->babel());
2017
2018         string const langenc = lang->encoding()->iconvName();
2019         string const texenc = lang->encoding()->latexName();
2020         string const bufenc = enc.iconvName();
2021         Encoding const * testenc(&enc);
2022         bool lang_fallback = false;
2023         bool ascii_fallback = false;
2024         if (need_fixedwidth && !enc.hasFixedWidth()) {
2025                 if (lang->encoding()->hasFixedWidth()) {
2026                         testenc = lang->encoding();
2027                         lang_fallback = true;
2028                 } else {
2029                         // We need a fixed width encoding, but both the buffer
2030                         // encoding and the language encoding are variable
2031                         // width. As a last fallback, try to convert to pure
2032                         // ASCII using the LaTeX commands defined in unicodesymbols.
2033                         testenc = encodings.fromLyXName("ascii");
2034                         if (!testenc)
2035                                 return docstring();
2036                         ascii_fallback = true;
2037                 }
2038         }
2039         // First and second character of plane 15 (Private Use Area)
2040         string const s1 = "\xf3\xb0\x80\x80"; // U+F0000
2041         string const s2 = "\xf3\xb0\x80\x81"; // U+F0001
2042         // FIXME UNICODE
2043         // lyx::regex is not unicode-safe.
2044         // Should use QRegExp or (boost::u32regex, but that requires ICU)
2045         static regex const reg("_\\(([^\\)]+)\\)");
2046         smatch sub;
2047         while (regex_search(preamble, sub, reg)) {
2048                 string const key = sub.str(1);
2049                 docstring const name = lang->translateLayout(key);
2050                 // Check whether name can be encoded in the buffer encoding
2051                 bool encodable = true;
2052                 for (size_t i = 0; i < name.size() && encodable; ++i)
2053                         if (!testenc->encodable(name[i]))
2054                                 encodable = false;
2055                 string translated;
2056                 if (encodable && !lang_fallback)
2057                         translated = to_utf8(name);
2058                 else if (ascii_fallback)
2059                         translated = to_ascii(testenc->latexString(name).first);
2060                 else
2061                         translated = "\\inputencoding{" + texenc + "}"
2062                                 + s1 + langenc + s2 + to_utf8(name)
2063                                 + s1 + bufenc + s2;
2064                 preamble = subst(preamble, sub.str(), translated);
2065         }
2066         return from_utf8(preamble);
2067 }
2068
2069 } // namespace
2070
2071
2072 docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel,
2073                                 bool use_polyglossia, bool use_minted) const
2074 {
2075         DocumentClass const & tclass = params_.documentClass();
2076         // collect preamble snippets in a set to prevent multiple identical
2077         // commands (would happen if e.g. both theorem and theorem* are used)
2078         set<docstring> snippets;
2079         typedef LanguageList::const_iterator lang_it;
2080         lang_it const lbeg = UsedLanguages_.begin();
2081         lang_it const lend =  UsedLanguages_.end();
2082         list<docstring>::const_iterator cit = usedLayouts_.begin();
2083         list<docstring>::const_iterator end = usedLayouts_.end();
2084         for (; cit != end; ++cit) {
2085                 // language dependent commands (once per document)
2086                 snippets.insert(i18npreamble(tclass[*cit].langpreamble(),
2087                                                 buffer().language(),
2088                                                 buffer().params().encoding(),
2089                                                 use_polyglossia, false));
2090                 // commands for language changing (for multilanguage documents)
2091                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
2092                         snippets.insert(i18npreamble(
2093                                                 tclass[*cit].babelpreamble(),
2094                                                 buffer().language(),
2095                                                 buffer().params().encoding(),
2096                                                 use_polyglossia, false));
2097                         for (lang_it lit = lbeg; lit != lend; ++lit)
2098                                 snippets.insert(i18npreamble(
2099                                                 tclass[*cit].babelpreamble(),
2100                                                 *lit,
2101                                                 buffer().params().encoding(),
2102                                                 use_polyglossia, false));
2103                 }
2104         }
2105         if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
2106                 FloatList const & floats = params_.documentClass().floats();
2107                 UsedFloats::const_iterator fit = usedFloats_.begin();
2108                 UsedFloats::const_iterator fend = usedFloats_.end();
2109                 for (; fit != fend; ++fit) {
2110                         Floating const & fl = floats.getType(fit->first);
2111                         // we assume builtin floats are translated
2112                         if (fl.isPredefined())
2113                                 continue;
2114                         docstring const type = from_ascii(fl.floattype());
2115                         docstring const flname = from_utf8(fl.name());
2116                         docstring name = buffer().language()->translateLayout(fl.name());
2117                         // only request translation if we have a real translation
2118                         // (that differs from the source)
2119                         if (flname != name)
2120                                 snippets.insert(getFloatI18nPreamble(
2121                                                 type, name, buffer().language(),
2122                                                 buffer().params().encoding(),
2123                                                 use_polyglossia));
2124                         for (lang_it lit = lbeg; lit != lend; ++lit) {
2125                                 string const code = (*lit)->code();
2126                                 name = (*lit)->translateLayout(fl.name());
2127                                 // we assume we have a suitable translation if
2128                                 // either the language is English (we need to
2129                                 // translate into English if English is a secondary
2130                                 // language) or if translateIfPossible returns
2131                                 // something different to the English source.
2132                                 bool const have_translation =
2133                                         (flname != name || contains(code, "en"));
2134                                 if (have_translation)
2135                                         snippets.insert(getFloatI18nPreamble(
2136                                                 type, name, *lit,
2137                                                 buffer().params().encoding(),
2138                                                 use_polyglossia));
2139                         }
2140                 }
2141         }
2142
2143         cit = usedInsetLayouts_.begin();
2144         end = usedInsetLayouts_.end();
2145         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
2146         for (; cit != end; ++cit) {
2147                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
2148                 if (it == ils.end())
2149                         continue;
2150                 // The listings package does not work with variable width
2151                 // encodings, only with fixed width encodings. Therefore we
2152                 // need to force a fixed width encoding for
2153                 // \lstlistlistingname and \lstlistingname (bug 9382).
2154                 // This needs to be consistent with InsetListings::latex()
2155                 // rsp. InsetListings::forcedEncoding().
2156                 bool const need_fixedwidth = !use_minted &&
2157                                         !runparams_.isFullUnicode() &&
2158                                         buffer().params().encoding().package() != Encoding::japanese &&
2159                                         it->second.fixedwidthpreambleencoding();
2160                 // language dependent commands (once per document)
2161                 snippets.insert(i18npreamble(it->second.langpreamble(),
2162                                                 buffer().language(),
2163                                                 buffer().params().encoding(),
2164                                                 use_polyglossia, need_fixedwidth));
2165                 // commands for language changing (for multilanguage documents)
2166                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
2167                         snippets.insert(i18npreamble(
2168                                                 it->second.babelpreamble(),
2169                                                 buffer().language(),
2170                                                 buffer().params().encoding(),
2171                                                 use_polyglossia, need_fixedwidth));
2172                         for (lang_it lit = lbeg; lit != lend; ++lit)
2173                                 snippets.insert(i18npreamble(
2174                                                 it->second.babelpreamble(),
2175                                                 *lit,
2176                                                 buffer().params().encoding(),
2177                                                 use_polyglossia, need_fixedwidth));
2178                 }
2179         }
2180
2181         odocstringstream tcpreamble;
2182         set<docstring>::const_iterator const send = snippets.end();
2183         set<docstring>::const_iterator it = snippets.begin();
2184         for (; it != send; ++it)
2185                 tcpreamble << *it;
2186         return tcpreamble.str();
2187 }
2188
2189
2190 void LaTeXFeatures::showStruct() const
2191 {
2192         lyxerr << "LyX needs the following commands when LaTeXing:"
2193                << "\n***** Packages:" << getPackages()
2194                << "\n***** Macros:" << to_utf8(getMacros().str)
2195                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
2196                << "\n***** done." << endl;
2197 }
2198
2199
2200 Buffer const & LaTeXFeatures::buffer() const
2201 {
2202         return *buffer_;
2203 }
2204
2205
2206 void LaTeXFeatures::setBuffer(Buffer const & buffer)
2207 {
2208         buffer_ = &buffer;
2209 }
2210
2211
2212 BufferParams const & LaTeXFeatures::bufferParams() const
2213 {
2214         return params_;
2215 }
2216
2217
2218 void LaTeXFeatures::getFloatDefinitions(otexstream & os) const
2219 {
2220         FloatList const & floats = params_.documentClass().floats();
2221
2222         // Here we will output the code to create the needed float styles.
2223         // We will try to do this as minimal as possible.
2224         // \floatstyle{ruled}
2225         // \newfloat{algorithm}{htbp}{loa}
2226         // \providecommand{\algorithmname}{Algorithm}
2227         // \floatname{algorithm}{\protect\algorithmname}
2228         for (auto const & cit : usedFloats_) {
2229                 Floating const & fl = floats.getType(cit.first);
2230
2231                 // For builtin floats we do nothing.
2232                 if (fl.isPredefined())
2233                         continue;
2234
2235                 // We have to special case "table" and "figure"
2236                 if (fl.floattype() == "tabular" || fl.floattype() == "figure") {
2237                         // Output code to modify "table" or "figure"
2238                         // but only if builtin == false
2239                         // and that have to be true at this point in the
2240                         // function.
2241                         docstring const type = from_ascii(fl.floattype());
2242                         docstring const placement = from_ascii(fl.placement());
2243                         docstring const style = from_ascii(fl.style());
2244                         if (!style.empty()) {
2245                                 os << "\\floatstyle{" << style << "}\n"
2246                                    << "\\restylefloat{" << type << "}\n";
2247                         }
2248                         if (!placement.empty()) {
2249                                 os << "\\floatplacement{" << type << "}{"
2250                                    << placement << "}\n";
2251                         }
2252                 } else {
2253                         // The other non builtin floats.
2254
2255                         docstring const type = from_ascii(fl.floattype());
2256                         docstring const placement = from_ascii(fl.placement());
2257                         docstring const ext = from_ascii(fl.ext());
2258                         docstring const within = from_ascii(fl.within());
2259                         docstring const style = from_ascii(fl.style());
2260                         docstring const name =
2261                                 buffer().language()->translateLayout(fl.name());
2262                         os << "\\floatstyle{" << style << "}\n"
2263                            << "\\newfloat{" << type << "}{" << placement
2264                            << "}{" << ext << '}';
2265                         if (!within.empty())
2266                                 os << '[' << within << ']';
2267                         os << '\n'
2268                            << "\\providecommand{\\" << type << "name}{"
2269                            << name << "}\n"
2270                            << "\\floatname{" << type << "}{\\protect\\"
2271                            << type << "name}\n";
2272
2273                         // What missing here is to code to minimalize the code
2274                         // output so that the same floatstyle will not be
2275                         // used several times, when the same style is still in
2276                         // effect. (Lgb)
2277                 }
2278                 if (cit.second)
2279                         // The subfig package is loaded later
2280                         os << "\n\\AtBeginDocument{\\newsubfloat{" << from_ascii(fl.floattype()) << "}}\n";
2281         }
2282 }
2283
2284
2285 void LaTeXFeatures::resolveAlternatives()
2286 {
2287         for (Features::iterator it = features_.begin(); it != features_.end();) {
2288                 if (contains(*it, '|')) {
2289                         vector<string> const alternatives = getVectorFromString(*it, "|");
2290                         vector<string>::const_iterator const end = alternatives.end();
2291                         vector<string>::const_iterator ita = alternatives.begin();
2292                         // Is any alternative already required? => use that
2293                         for (; ita != end; ++ita) {
2294                                 if (isRequired(*ita))
2295                                         break;
2296                         }
2297                         // Is any alternative available? => use the first one
2298                         // (bug 9498)
2299                         if (ita == end) {
2300                                 for (ita = alternatives.begin(); ita != end; ++ita) {
2301                                         if (isAvailable(*ita)) {
2302                                                 require(*ita);
2303                                                 break;
2304                                         }
2305                                 }
2306                         }
2307                         // This will not work, but not requiring something
2308                         // would be more confusing
2309                         if (ita == end)
2310                                 require(alternatives.front());
2311                         features_.erase(it);
2312                         it = features_.begin();
2313                 } else
2314                         ++it;
2315         }
2316 }
2317
2318
2319 void LaTeXFeatures::expandMultiples()
2320 {
2321         for (Features::iterator it = features_.begin(); it != features_.end();) {
2322                 if (contains(*it, ',')) {
2323                         // Do nothing if any multiple is already required
2324                         for (string const & pkg : getVectorFromString(*it, ",")) {
2325                                 if (!isRequired(pkg))
2326                                         require(pkg);
2327                         }
2328                         features_.erase(it);
2329                         it = features_.begin();
2330                 } else
2331                         ++it;
2332         }
2333 }
2334
2335
2336 } // namespace lyx