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