]> git.lyx.org Git - features.git/blob - src/LaTeXFeatures.cpp
Support the mathbbm font.
[features.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         LanguageList::const_iterator const begin = UsedLanguages_.begin();
928         for (LanguageList::const_iterator cit = begin;
929              cit != UsedLanguages_.end();
930              ++cit) {
931                 if ((*cit)->polyglossia().empty())
932                         return false;
933         }
934         return true;
935 }
936
937
938 bool LaTeXFeatures::hasPolyglossiaExclusiveLanguages() const
939 {
940         // first the main language
941         if (params_.language->isPolyglossiaExclusive())
942                 return true;
943         // now the secondary languages
944         LanguageList::const_iterator const begin = UsedLanguages_.begin();
945         for (LanguageList::const_iterator cit = begin;
946              cit != UsedLanguages_.end();
947              ++cit) {
948                 if ((*cit)->isPolyglossiaExclusive())
949                         return true;
950         }
951         return false;
952 }
953
954
955 vector<string> LaTeXFeatures::getPolyglossiaExclusiveLanguages() const
956 {
957         vector<string> result;
958         // first the main language
959         if (params_.language->isPolyglossiaExclusive())
960                 result.push_back(params_.language->display());
961         // now the secondary languages
962         LanguageList::const_iterator const begin = UsedLanguages_.begin();
963         for (LanguageList::const_iterator cit = begin;
964              cit != UsedLanguages_.end();
965              ++cit) {
966                 if ((*cit)->isPolyglossiaExclusive())
967                         result.push_back((*cit)->display());
968         }
969         return result;
970 }
971
972
973 vector<string> LaTeXFeatures::getBabelExclusiveLanguages() const
974 {
975         vector<string> result;
976         // first the main language
977         if (params_.language->isBabelExclusive())
978                 result.push_back(params_.language->display());
979         // now the secondary languages
980         LanguageList::const_iterator const begin = UsedLanguages_.begin();
981         for (LanguageList::const_iterator cit = begin;
982              cit != UsedLanguages_.end();
983              ++cit) {
984                 if ((*cit)->isBabelExclusive())
985                         result.push_back((*cit)->display());
986         }
987         return result;
988 }
989
990
991 string LaTeXFeatures::getBabelLanguages() const
992 {
993         ostringstream langs;
994
995         bool first = true;
996         LanguageList::const_iterator const begin = UsedLanguages_.begin();
997         for (LanguageList::const_iterator cit = begin;
998              cit != UsedLanguages_.end();
999              ++cit) {
1000                 if ((*cit)->babel().empty())
1001                         continue;
1002                 if (!first)
1003                         langs << ',';
1004                 else
1005                         first = false;
1006                 langs << (*cit)->babel();
1007         }
1008         return langs.str();
1009 }
1010
1011
1012 set<string> LaTeXFeatures::getPolyglossiaLanguages() const
1013 {
1014         set<string> langs;
1015
1016         LanguageList::const_iterator const begin = UsedLanguages_.begin();
1017         for (LanguageList::const_iterator cit = begin;
1018              cit != UsedLanguages_.end();
1019              ++cit) {
1020                 // We do not need the variants here
1021                 langs.insert((*cit)->polyglossia());
1022         }
1023         return langs;
1024 }
1025
1026
1027 string LaTeXFeatures::getActiveChars() const
1028 {
1029         string res;
1030         // first the main language
1031         res += params_.language->activeChars();
1032         // now the secondary languages
1033         LanguageList::const_iterator const begin = UsedLanguages_.begin();
1034         for (LanguageList::const_iterator cit = begin;
1035              cit != UsedLanguages_.end(); ++cit)
1036                 res += ((*cit)->activeChars());
1037         return res;
1038 }
1039
1040
1041 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
1042 {
1043         // This does only find encodings of languages supported by babel, but
1044         // that does not matter since we don't have a language with an
1045         // encoding supported by inputenc but without babel support.
1046         set<string> encs;
1047         for (auto const & lang : UsedLanguages_)
1048                 if (lang->encoding()->latexName() != doc_encoding &&
1049                     lang->encoding()->package() == Encoding::inputenc)
1050                         encs.insert(lang->encoding()->latexName());
1051         return encs;
1052 }
1053
1054
1055 void LaTeXFeatures::getFontEncodings(vector<string> & encs, bool const onlylangs) const
1056 {
1057         if (!onlylangs) {
1058                 // these must be loaded if glyphs of this script are used
1059                 // unless a language providing them is used in the document
1060                 if (mustProvide("textgreek")
1061                     && find(encs.begin(), encs.end(), "LGR") == encs.end())
1062                         encs.insert(encs.begin(), "LGR");
1063                 if ((mustProvide("textcyrillic") || mustProvide("textschwa"))
1064                     && find(encs.begin(), encs.end(), "T2A") == encs.end())
1065                         encs.insert(encs.begin(), "T2A");
1066         }
1067
1068         for (auto const & lang : UsedLanguages_) {
1069                 vector<string> extraencs =
1070                         getVectorFromString(lang->fontenc(buffer().masterParams()));
1071                 for (auto const & extra : extraencs) {
1072                         if (extra != "none" && find(encs.begin(), encs.end(), extra) == encs.end())
1073                                 encs.insert(encs.begin(), extra);
1074                 }
1075         }
1076 }
1077
1078
1079 bool LaTeXFeatures::hasRTLLanguage() const
1080 {
1081         if (params_.language->rightToLeft())
1082                 return true;
1083         for (auto const & lang : UsedLanguages_)
1084                 if (lang->rightToLeft())
1085                         return true;
1086         return false;
1087 }
1088
1089
1090 namespace {
1091
1092 char const * simplefeatures[] = {
1093 // note that the package order here will be the same in the LaTeX-output
1094         "array",
1095         "verbatim",
1096         "cprotect",
1097         "longtable",
1098         "latexsym",
1099         "pifont",
1100         // subfig is handled in BufferParams.cpp
1101         "varioref",
1102         "prettyref",
1103         "refstyle",
1104         /*For a successful cooperation of the `wrapfig' package with the
1105           `float' package you should load the `wrapfig' package *after*
1106           the `float' package. See the caption package documentation
1107           for explanation.*/
1108         "float",
1109         "wrapfig",
1110         "booktabs",
1111         "fancybox",
1112         "calc",
1113         "units",
1114         "framed",
1115         "soul",
1116         "dingbat",
1117         "bbding",
1118         "ifsym",
1119         "txfonts",
1120         "pxfonts",
1121         "mathdesign",
1122         "mathrsfs",
1123         "mathabx",
1124         "mathtools",
1125         // "cancel",
1126         "ascii",
1127         "url",
1128         "csquotes",
1129         "enumitem",
1130         "endnotes",
1131         "enotez",
1132         "hhline",
1133         "ifthen",
1134         // listings is handled in BufferParams.cpp
1135         "bm",
1136         "pdfpages",
1137         "amscd",
1138         "slashed",
1139         "multicol",
1140         "multirow",
1141         "tfrupee",
1142         "shapepar",
1143         "rsphrase",
1144         "hpstatement",
1145         "algorithm2e",
1146         "sectionbox",
1147         "tcolorbox",
1148         "pdfcomment",
1149         "fixme",
1150         "todonotes",
1151         "forest",
1152         "varwidth",
1153         "afterpage",
1154         "tabularx",
1155         "tikz",
1156         "xltabular",
1157         "chessboard",
1158         "xskak",
1159         "pict2e",
1160         "drs",
1161         "environ",
1162         "dsfont",
1163         "bbm"
1164 };
1165
1166 char const * bibliofeatures[] = {
1167         // Known bibliography packages (will be loaded before natbib)
1168         "achicago",
1169         "apacite",
1170         "apalike",
1171         "astron",
1172         "authordate1-4",
1173         "babelbib",
1174         "bibgerm",
1175         "chapterbib",
1176         "chicago",
1177         "chscite",
1178         "harvard",
1179         "mslapa",
1180         "named"
1181 };
1182
1183 int const nb_bibliofeatures = sizeof(bibliofeatures) / sizeof(char const *);
1184
1185 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
1186
1187 } // namespace
1188
1189
1190 string const LaTeXFeatures::getColorOptions() const
1191 {
1192         ostringstream colors;
1193
1194         // Handling the color packages separately is needed to be able to load them
1195         // before babel when hyperref is loaded with the colorlinks option
1196         // for more info see Bufferparams.cpp
1197
1198         // [x]color.sty
1199         if (mustProvide("color") || mustProvide("xcolor")) {
1200                 string const package =
1201                         (mustProvide("xcolor") ? "xcolor" : "color");
1202                 if (params_.graphics_driver == "default"
1203                         || params_.graphics_driver == "none")
1204                         colors << "\\usepackage{" << package << "}\n";
1205                 else
1206                         colors << "\\usepackage["
1207                                  << params_.graphics_driver
1208                                  << "]{" << package << "}\n";
1209         }
1210
1211         // pdfcolmk must be loaded after color
1212         if (mustProvide("pdfcolmk"))
1213                 colors << "\\usepackage{pdfcolmk}\n";
1214
1215         // the following 3 color commands must be set after color
1216         // is loaded and before pdfpages, therefore add the command
1217         // here define the set color
1218         if (mustProvide("pagecolor")) {
1219                 colors << "\\definecolor{page_backgroundcolor}{rgb}{";
1220                 colors << outputLaTeXColor(params_.backgroundcolor) << "}\n";
1221                 // set the page color
1222                 colors << "\\pagecolor{page_backgroundcolor}\n";
1223         }
1224
1225         if (mustProvide("fontcolor")) {
1226                 colors << "\\definecolor{document_fontcolor}{rgb}{";
1227                 colors << outputLaTeXColor(params_.fontcolor) << "}\n";
1228                 // set the color
1229                 colors << "\\color{document_fontcolor}\n";
1230         }
1231
1232         if (mustProvide("lyxgreyedout")) {
1233                 colors << "\\definecolor{note_fontcolor}{rgb}{";
1234                 colors << outputLaTeXColor(params_.notefontcolor) << "}\n";
1235                 // the color will be set together with the definition of
1236                 // the lyxgreyedout environment (see lyxgreyedout_def)
1237         }
1238
1239         // color for shaded boxes
1240         if (isRequired("framed") && mustProvide("color")) {
1241                 colors << "\\definecolor{shadecolor}{rgb}{";
1242                 colors << outputLaTeXColor(params_.boxbgcolor) << "}\n";
1243                 // this color is automatically used by the LaTeX-package "framed"
1244         }
1245
1246         return colors.str();
1247 }
1248
1249
1250 string const LaTeXFeatures::getPackageOptions() const
1251 {
1252         ostringstream packageopts;
1253         // Output all the package option stuff we have been asked to do.
1254         map<string, string>::const_iterator it =
1255                 params_.documentClass().packageOptions().begin();
1256         map<string, string>::const_iterator en =
1257                 params_.documentClass().packageOptions().end();
1258         for (; it != en; ++it)
1259                 if (mustProvide(it->first))
1260                         packageopts << "\\PassOptionsToPackage{" << it->second << "}"
1261                                  << "{" << it->first << "}\n";
1262         return packageopts.str();
1263 }
1264
1265
1266 string const LaTeXFeatures::getPackages() const
1267 {
1268         ostringstream packages;
1269
1270         // FIXME: currently, we can only load packages and macros known
1271         // to LyX.
1272         // However, with the Require tag of layouts/custom insets,
1273         // also unknown packages can be requested. They are silently
1274         // swallowed now. We should change this eventually.
1275
1276         //  These are all the 'simple' includes.  i.e
1277         //  packages which we just \usepackage{package}
1278         for (int i = 0; i < nb_simplefeatures; ++i) {
1279                 if (mustProvide(simplefeatures[i]))
1280                         packages << "\\usepackage{" << simplefeatures[i] << "}\n";
1281         }
1282
1283         // The rest of these packages are somewhat more complicated
1284         // than those above.
1285
1286         if (mustProvide("changebar")) {
1287                 packages << "\\usepackage";
1288                 if (runparams_.flavor == OutputParams::LATEX
1289                     || runparams_.flavor == OutputParams::DVILUATEX)
1290                         packages << "[dvips]";
1291                 packages << "{changebar}\n";
1292         }
1293
1294         if (mustProvide("footnote")) {
1295                 if (isRequired("hyperref"))
1296                         packages << "\\usepackage{footnotehyper}\n";
1297                 else
1298                         packages << "\\usepackage{footnote}\n";
1299         }
1300
1301         // [pdf]lscape is used to rotate longtables
1302         if (mustProvide("lscape")) {
1303                 if (runparams_.flavor == OutputParams::LATEX
1304                     || runparams_.flavor == OutputParams::DVILUATEX)
1305                         packages << "\\usepackage{lscape}\n";
1306                 else
1307                         packages << "\\usepackage{pdflscape}\n";
1308         }
1309
1310         // The tipa package and its extensions (tipx, tone) must not
1311         // be loaded with non-TeX fonts, since fontspec includes the
1312         // respective macros
1313         if (mustProvide("tipa") && !params_.useNonTeXFonts)
1314                 packages << "\\usepackage{tipa}\n";
1315         if (mustProvide("tipx") && !params_.useNonTeXFonts)
1316                 packages << "\\usepackage{tipx}\n";
1317         if (mustProvide("extraipa") && !params_.useNonTeXFonts)
1318                 packages << "\\usepackage{extraipa}\n";
1319         if (mustProvide("tone") && !params_.useNonTeXFonts)
1320                 packages << "\\usepackage{tone}\n";
1321
1322         // if fontspec or newtxmath is used, AMS packages have to be loaded
1323         // before fontspec (in BufferParams)
1324         string const amsPackages = loadAMSPackages();
1325         bool const ot1 = (params_.main_font_encoding() == "default"
1326                           || params_.main_font_encoding() == "OT1");
1327         bool const use_newtxmath =
1328                 theLaTeXFonts().getLaTeXFont(from_ascii(params_.fontsMath())).getUsedPackage(
1329                         ot1, false, false) == "newtxmath";
1330
1331         if (!params_.useNonTeXFonts && !use_newtxmath && !amsPackages.empty())
1332                 packages << amsPackages;
1333
1334         if (mustProvide("cancel") &&
1335             params_.use_package("cancel") != BufferParams::package_off)
1336                 packages << "\\usepackage{cancel}\n";
1337
1338         // marvosym and bbding both define the \Cross macro
1339         if (mustProvide("marvosym")) {
1340             if (mustProvide("bbding"))
1341                 packages << "\\let\\Cross\\relax\n";
1342             packages << "\\usepackage{marvosym}\n";
1343         }
1344
1345         // accents must be loaded after amsmath
1346         if (mustProvide("accents") &&
1347             params_.use_package("accents") != BufferParams::package_off)
1348                 packages << "\\usepackage{accents}\n";
1349
1350         // mathdots must be loaded after amsmath
1351         if (mustProvide("mathdots") &&
1352                 params_.use_package("mathdots") != BufferParams::package_off)
1353                 packages << "\\usepackage{mathdots}\n";
1354
1355         // yhmath must be loaded after amsmath
1356         if (mustProvide("yhmath") &&
1357             params_.use_package("yhmath") != BufferParams::package_off)
1358                 packages << "\\usepackage{yhmath}\n";
1359
1360         // stmaryrd must be loaded after amsmath
1361         if (mustProvide("stmaryrd") &&
1362             params_.use_package("stmaryrd") != BufferParams::package_off)
1363                 packages << "\\usepackage{stmaryrd}\n";
1364
1365         if (mustProvide("stackrel") &&
1366             params_.use_package("stackrel") != BufferParams::package_off)
1367                 packages << "\\usepackage{stackrel}\n";
1368
1369         if (mustProvide("undertilde") &&
1370                 params_.use_package("undertilde") != BufferParams::package_off)
1371                 packages << "\\usepackage{undertilde}\n";
1372
1373         // [x]color and pdfcolmk are handled in getColorOptions() above
1374
1375         // makeidx.sty
1376         if (isRequired("makeidx") || isRequired("splitidx")) {
1377                 if (!isProvided("makeidx") && !isRequired("splitidx"))
1378                         packages << "\\usepackage{makeidx}\n";
1379                 if (mustProvide("splitidx"))
1380                         packages << "\\usepackage{splitidx}\n";
1381                 packages << "\\makeindex\n";
1382         }
1383
1384         // graphicx.sty
1385         if (mustProvide("graphicx") && params_.graphics_driver != "none") {
1386                 if (params_.graphics_driver == "default")
1387                         packages << "\\usepackage{graphicx}\n";
1388                 else
1389                         packages << "\\usepackage["
1390                                  << params_.graphics_driver
1391                                  << "]{graphicx}\n";
1392         }
1393
1394         // These must be loaded after graphicx, since they try
1395         // to load graphicx without options
1396         if (mustProvide("rotating"))
1397                 packages << "\\usepackage{rotating}\n";
1398         if (mustProvide("rotfloat"))
1399                 packages << "\\usepackage{rotfloat}\n";
1400         // and this must be loaded after rotating
1401         if (mustProvide("tablefootnote"))
1402                 packages << "\\usepackage{tablefootnote}\n";
1403
1404         // lyxskak.sty --- newer chess support based on skak.sty
1405         if (mustProvide("chess"))
1406                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
1407
1408         // setspace.sty
1409         if (mustProvide("setspace") && !isProvided("SetSpace"))
1410                 packages << "\\usepackage{setspace}\n";
1411
1412         // we need to assure that mhchem is loaded before esint and every other
1413         // package that redefines command of amsmath because mhchem loads amlatex
1414         // (this info is from the author of mhchem from June 2013)
1415         if (mustProvide("mhchem") &&
1416             params_.use_package("mhchem") != BufferParams::package_off)
1417                 packages << "\\PassOptionsToPackage{version=3}{mhchem}\n"
1418                             "\\usepackage{mhchem}\n";
1419
1420         // wasysym is a simple feature, but it must be after amsmath if both
1421         // are used
1422         // wasysym redefines some integrals (e.g. iint) from amsmath. That
1423         // leads to inconsistent integrals. We only load this package if
1424         // the document does not contain integrals (then isRequired("esint")
1425         // is false) or if esint is used, since esint redefines all relevant
1426         // integral symbols from wasysym and amsmath.
1427         // See http://www.lyx.org/trac/ticket/1942
1428         if (mustProvide("wasysym") &&
1429             params_.use_package("wasysym") != BufferParams::package_off &&
1430             (params_.use_package("esint") != BufferParams::package_off || !isRequired("esint")))
1431                 packages << "\\usepackage{wasysym}\n";
1432
1433         // esint must be after amsmath (and packages requiring amsmath, like mhchem)
1434         // and wasysym, since it will redeclare inconsistent integral symbols
1435         if (mustProvide("esint") &&
1436             params_.use_package("esint") != BufferParams::package_off)
1437                 packages << "\\usepackage{esint}\n";
1438
1439         // Known bibliography packages (simple \usepackage{package})
1440         for (int i = 0; i < nb_bibliofeatures; ++i) {
1441                 if (mustProvide(bibliofeatures[i]))
1442                         packages << "\\usepackage{"
1443                                  << bibliofeatures[i] << "}\n";
1444         }
1445
1446         // Compatibility between achicago and natbib
1447         if (mustProvide("achicago") && mustProvide("natbib"))
1448                 packages << "\\let\\achicagobib\\thebibliography\n";
1449
1450         // natbib.sty
1451         // Some classes load natbib themselves, but still allow (or even require)
1452         // plain numeric citations (ReVTeX is such a case, see bug 5182).
1453         // This special case is indicated by the "natbib-internal" key.
1454         if (mustProvide("natbib")
1455             && !isProvided("natbib-internal")
1456             && !isProvided("biblatex")
1457             && !isProvided("biblatex-natbib")
1458             && !isProvided("jurabib")) {
1459                 packages << "\\usepackage[";
1460                 if (params_.citeEngineType() == ENGINE_TYPE_NUMERICAL)
1461                         packages << "numbers";
1462                 else
1463                         packages << "authoryear";
1464                 if (!params_.biblio_opts.empty())
1465                         packages << ',' << params_.biblio_opts;
1466                 packages << "]{natbib}\n";
1467         }
1468
1469         // Compatibility between achicago and natbib
1470         if (mustProvide("achicago") && mustProvide("natbib")) {
1471                 packages << "\\let\\thebibliography\\achicagobib\n";
1472                 packages << "\\let\\SCcite\\astroncite\n";
1473                 packages << "\\let\\UnexpandableProtect\\protect\n";
1474         }
1475
1476         // jurabib -- we need version 0.6 at least.
1477         if (mustProvide("jurabib")
1478             && !isProvided("natbib-internal")
1479             && !isProvided("natbib")
1480             && !isProvided("biblatex")
1481             && !isProvided("biblatex-natbib")) {
1482                 packages << "\\usepackage";
1483                 if (!params_.biblio_opts.empty())
1484                         packages << '[' << params_.biblio_opts << ']';
1485                 packages << "{jurabib}[2004/01/25]\n";
1486         }
1487
1488         // opcit -- we pass custombst as we output \bibliographystyle ourselves
1489         if (mustProvide("opcit")) {
1490                 if (isRequired("hyperref"))
1491                         packages << "\\usepackage[custombst,hyperref]{opcit}\n";
1492                 else
1493                         packages << "\\usepackage[custombst]{opcit}\n";
1494         }
1495
1496         // xargs -- we need version 1.09 at least
1497         if (mustProvide("xargs"))
1498                 packages << "\\usepackage{xargs}[2008/03/08]\n";
1499
1500         if (mustProvide("xy"))
1501                 packages << "\\usepackage[all]{xy}\n";
1502
1503         if (mustProvide("feyn"))
1504                 packages << "\\usepackage{feyn}\n"; //Diagram
1505
1506         if (mustProvide("ulem"))
1507                 packages << "\\PassOptionsToPackage{normalem}{ulem}\n"
1508                             "\\usepackage{ulem}\n";
1509
1510         if (mustProvide("nomencl")) {
1511                 // Make it work with the new and old version of the package,
1512                 // but don't use the compatibility option since it is
1513                 // incompatible to other packages.
1514                 packages << "\\usepackage{nomencl}\n"
1515                             "% the following is useful when we have the old nomencl.sty package\n"
1516                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
1517                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
1518                             "\\makenomenclature\n";
1519         }
1520
1521         // fixltx2e provides subscript
1522         if (mustProvide("subscript") && !isRequired("fixltx2e"))
1523                 packages << "\\usepackage{subscript}\n";
1524
1525         // footmisc must be loaded after setspace
1526         // Set options here, load the package after the user preamble to
1527         // avoid problems with manual loaded footmisc.
1528         if (mustProvide("footmisc"))
1529                 packages << "\\PassOptionsToPackage{stable}{footmisc}\n";
1530
1531         if (mustProvide("microtype")){
1532                 packages << "\\usepackage{microtype}\n";
1533         }
1534
1535         return packages.str();
1536 }
1537
1538
1539 TexString LaTeXFeatures::getMacros() const
1540 {
1541         otexstringstream macros;
1542
1543         if (!preamble_snippets_.empty()) {
1544                 macros << '\n';
1545                 macros << getPreambleSnippets();
1546         }
1547
1548         if (mustProvide("xetexdashbreakstate"))
1549                 macros << "\\XeTeXdashbreakstate 0" << '\n';
1550
1551         if (mustProvide("papersize")) {
1552                 if (runparams_.flavor == OutputParams::LATEX
1553                     || runparams_.flavor == OutputParams::DVILUATEX)
1554                         macros << papersizedvi_def << '\n';
1555                 else if  (runparams_.flavor == OutputParams::LUATEX)
1556                         macros << papersizepdflua_def << '\n';
1557                 else
1558                         macros << papersizepdf_def << '\n';
1559         }
1560
1561         if (mustProvide("LyX")) {
1562                 macros << "\\providecommand{\\LyX}";
1563                 // open conditional wrappers
1564                 if (runparams_.use_polyglossia && hasRTLLanguage())
1565                         macros << "{\\@ensure@LTR";
1566                 if (isRequired("hyperref"))
1567                         macros << "{\\texorpdfstring";
1568                 if (useBabel())
1569                         macros << "{\\ensureascii";
1570                 // main definition
1571                 macros << lyx_def;
1572                 // close conditional wrappers
1573                 if (useBabel())
1574                         macros << '}';
1575                 if (isRequired("hyperref"))
1576                         macros << "{LyX}}";
1577                 if (runparams_.use_polyglossia && hasRTLLanguage())
1578                         macros << '}';
1579                 macros << '\n';
1580         }
1581
1582         if (mustProvide("noun"))
1583                 macros << noun_def << '\n';
1584
1585         if (mustProvide("lyxarrow"))
1586                 macros << lyxarrow_def << '\n';
1587
1588         if (mustProvide("lyxzerowidthspace"))
1589                 macros << lyxZWSP_def << '\n';
1590
1591         if (!usePolyglossia() && mustProvide("textgreek")) {
1592             // ensure LGR font encoding is defined also if fontenc is not loaded by LyX
1593                 if (params_.main_font_encoding() == "default")
1594                         macros << textgreek_LGR_def;
1595                 macros << textgreek_def << '\n';
1596         }
1597
1598         if (!usePolyglossia() && mustProvide("textcyrillic")) {
1599                 // ensure T2A font encoding is set up also if fontenc is not loaded by LyX
1600                 if (params_.main_font_encoding() == "default")
1601                         macros << textcyr_T2A_def;
1602                 macros << textcyr_def << '\n';
1603         }
1604
1605         // non-standard text accents:
1606         if (mustProvide("textcommaabove") || mustProvide("textcommaaboveright") ||
1607             mustProvide("textcommabelow") || mustProvide("textbaltic"))
1608                 macros << lyxaccent_def;
1609
1610         if (mustProvide("textcommabelow") || mustProvide("textbaltic"))
1611                 macros << textcommabelow_def << '\n';
1612
1613         if (mustProvide("textcommaabove") || mustProvide("textbaltic"))
1614                 macros << textcommaabove_def << '\n';
1615
1616         if (mustProvide("textcommaaboveright"))
1617                 macros << textcommaaboveright_def << '\n';
1618
1619         if (mustProvide("textbaltic"))
1620                 macros << textbaltic_def << '\n';
1621
1622         if (mustProvide("textschwa"))
1623                 macros << textschwa_def << '\n';
1624
1625         // split-level fractions
1626         if (mustProvide("xfrac") || mustProvide("smallLetterFrac"))
1627                 macros << xfrac_def << '\n';
1628
1629         if (mustProvide("smallLetterFrac"))
1630                 macros << smallLetterFrac_def << '\n';
1631
1632         if (mustProvide("lyxmathsym"))
1633                 macros << lyxmathsym_def << '\n';
1634
1635         if (mustProvide("cedilla"))
1636                 macros << cedilla_def << '\n';
1637
1638         if (mustProvide("subring"))
1639                 macros << subring_def << '\n';
1640
1641         if (mustProvide("subdot"))
1642                 macros << subdot_def << '\n';
1643
1644         if (mustProvide("subhat"))
1645                 macros << subhat_def << '\n';
1646
1647         if (mustProvide("subtilde"))
1648                 macros << subtilde_def << '\n';
1649
1650         if (mustProvide("dacute"))
1651                 macros << dacute_def << '\n';
1652
1653         if (mustProvide("tipasymb"))
1654                 macros << tipasymb_def << '\n';
1655
1656         if (mustProvide("dgrave"))
1657                 macros << dgrave_def << '\n';
1658
1659         if (mustProvide("rcap"))
1660                 macros << rcap_def << '\n';
1661
1662         if (mustProvide("ogonek"))
1663                 macros << ogonek_def << '\n';
1664
1665         // quotes.
1666         if (mustProvide("quotesinglbase"))
1667                 macros << quotesinglbase_def << '\n';
1668         if (mustProvide("quotedblbase"))
1669                 macros << quotedblbase_def << '\n';
1670         if (mustProvide("guilsinglleft"))
1671                 macros << guilsinglleft_def << '\n';
1672         if (mustProvide("guilsinglright"))
1673                 macros << guilsinglright_def << '\n';
1674         if (mustProvide("guillemotleft"))
1675                 macros << guillemotleft_def << '\n';
1676         if (mustProvide("guillemotright"))
1677                 macros << guillemotright_def << '\n';
1678         if (mustProvide("textquotedbl"))
1679                 macros << textquotedbl_def << '\n';
1680         if (mustProvide("textquotesinglep")) {
1681                 if (runparams_.flavor == OutputParams::XETEX)
1682                         macros << textquotesinglep_xetex_def << '\n';
1683                 else
1684                         macros << textquotesinglep_luatex_def << '\n';
1685         }
1686         if (mustProvide("textquotedblp")) {
1687                 if (runparams_.flavor == OutputParams::XETEX)
1688                         macros << textquotedblp_xetex_def << '\n';
1689                 else
1690                         macros << textquotedblp_luatex_def << '\n';
1691         }
1692
1693         // Math mode
1694         if (mustProvide("binom") && !isRequired("amsmath"))
1695                 macros << binom_def << '\n';
1696         if (mustProvide("mathcircumflex"))
1697                 macros << mathcircumflex_def << '\n';
1698
1699         // other
1700         if (mustProvide("ParagraphLeftIndent"))
1701                 macros << paragraphleftindent_def;
1702         if (mustProvide("NeedLyXFootnoteCode"))
1703                 macros << floatingfootnote_def;
1704
1705         // some problems with tex->html converters
1706         if (mustProvide("NeedTabularnewline"))
1707                 macros << tabularnewline_def;
1708
1709         // greyed-out environment (note inset)
1710         // the color is specified in the routine
1711         // getColorOptions() to avoid LaTeX-package clashes
1712         if (mustProvide("lyxgreyedout")) {
1713                 // We need different version for RTL (#8647)
1714                 if (hasRTLLanguage()) {
1715                         if (runparams_.flavor == OutputParams::LUATEX)
1716                                 if (useBabel())
1717                                         macros << lyxgreyedout_luartl_babel_def;
1718                                 else
1719                                         macros << lyxgreyedout_luartl_def;
1720                         else
1721                                 macros << lyxgreyedout_rtl_def;
1722                 } else
1723                         macros << lyxgreyedout_def;
1724         }
1725
1726         if (mustProvide("lyxdot"))
1727                 macros << lyxdot_def << '\n';
1728
1729         // floats
1730         getFloatDefinitions(macros);
1731
1732         if (mustProvide("refstyle"))
1733                 macros << lyxref_def << '\n';
1734
1735         // change tracking
1736         if (mustProvide("ct-xcolor-ulem")) {
1737                 streamsize const prec = macros.os().precision(2);
1738
1739                 RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
1740                 macros << "\\providecolor{lyxadded}{rgb}{"
1741                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
1742
1743                 RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
1744                 macros << "\\providecolor{lyxdeleted}{rgb}{"
1745                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
1746
1747                 macros.os().precision(prec);
1748
1749                 macros << changetracking_xcolor_ulem_base_def;
1750
1751                 if (isRequired("changebar")) {
1752                         if (isRequired("hyperref"))
1753                                 macros << changetracking_xcolor_ulem_hyperref_cb_def;
1754                         else
1755                                 macros << changetracking_xcolor_ulem_cb_def;
1756                 } else {
1757                         if (isRequired("hyperref"))
1758                                 macros << changetracking_xcolor_ulem_hyperref_def;
1759                         else
1760                                 macros << changetracking_xcolor_ulem_def;
1761                 }
1762         }
1763
1764         if (mustProvide("ct-tikz-object-sout")) {
1765                 if (!mustProvide("ct-xcolor-ulem")) {
1766                         streamsize const prec = macros.os().precision(2);
1767
1768                         RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
1769                         macros << "\\providecolor{lyxadded}{rgb}{"
1770                                << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
1771         
1772                         RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
1773                         macros << "\\providecolor{lyxdeleted}{rgb}{"
1774                                << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
1775         
1776                         macros.os().precision(prec);
1777                 }
1778                 
1779                 macros << changetracking_tikz_object_sout_def;
1780                 
1781                 if (isRequired("changebar")) {
1782                         if (isRequired("hyperref"))
1783                                 macros << changetracking_xcolor_ulem_hyperref_cb_object_def;
1784                         else
1785                                 macros << changetracking_xcolor_ulem_cb_object_def;
1786                 } else {
1787                         if (isRequired("hyperref"))
1788                                 macros << changetracking_xcolor_ulem_hyperref_object_def;
1789                         else
1790                                 macros << changetracking_xcolor_ulem_object_def;
1791                 }
1792         }
1793
1794         if (mustProvide("ct-none"))
1795                 macros << changetracking_none_def;
1796
1797         if (mustProvide("rtloutputdblcol"))
1798                 macros << rtloutputdblcol_def;
1799
1800         if (mustProvide("lyxmintcaption"))
1801                 macros << lyxmintcaption_def;
1802
1803         return macros.release();
1804 }
1805
1806
1807 docstring const LaTeXFeatures::getBabelPresettings() const
1808 {
1809         odocstringstream tmp;
1810
1811         for (Language const * lang : UsedLanguages_)
1812                 if (!lang->babel_presettings().empty())
1813                         tmp << lang->babel_presettings() << '\n';
1814         if (!params_.language->babel_presettings().empty())
1815                 tmp << params_.language->babel_presettings() << '\n';
1816
1817         if (!contains(tmp.str(), '@'))
1818                 return tmp.str();
1819
1820         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1821 }
1822
1823
1824 docstring const LaTeXFeatures::getBabelPostsettings() const
1825 {
1826         odocstringstream tmp;
1827
1828         for (Language const * lang : UsedLanguages_)
1829                 if (!lang->babel_postsettings().empty())
1830                         tmp << lang->babel_postsettings() << '\n';
1831         if (!params_.language->babel_postsettings().empty())
1832                 tmp << params_.language->babel_postsettings() << '\n';
1833
1834         if (!contains(tmp.str(), '@'))
1835                 return tmp.str();
1836
1837         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1838 }
1839
1840
1841 string const LaTeXFeatures::loadAMSPackages() const
1842 {
1843         ostringstream tmp;
1844
1845         if (mustProvide("amsmath")
1846             && params_.use_package("amsmath") != BufferParams::package_off) {
1847                 tmp << "\\usepackage{amsmath}\n";
1848         } else {
1849                 // amsbsy and amstext are already provided by amsmath
1850                 if (mustProvide("amsbsy"))
1851                         tmp << "\\usepackage{amsbsy}\n";
1852                 if (mustProvide("amstext"))
1853                         tmp << "\\usepackage{amstext}\n";
1854         }
1855
1856         if (mustProvide("amsthm"))
1857                 tmp << "\\usepackage{amsthm}\n";
1858
1859         if (mustProvide("amssymb")
1860             && params_.use_package("amssymb") != BufferParams::package_off)
1861                 tmp << "\\usepackage{amssymb}\n";
1862
1863         return tmp.str();
1864 }
1865
1866
1867 docstring const LaTeXFeatures::getTClassPreamble() const
1868 {
1869         // the text class specific preamble
1870         DocumentClass const & tclass = params_.documentClass();
1871         odocstringstream tcpreamble;
1872
1873         tcpreamble << tclass.preamble();
1874
1875         list<docstring>::const_iterator cit = usedLayouts_.begin();
1876         list<docstring>::const_iterator end = usedLayouts_.end();
1877         for (; cit != end; ++cit)
1878                 // For InPreamble layouts, we output the preamble stuff earlier
1879                 // (before the layouts). See Paragraph::Private::validate.
1880                 if (!tclass[*cit].inpreamble)
1881                         tcpreamble << tclass[*cit].preamble();
1882
1883         cit = usedInsetLayouts_.begin();
1884         end = usedInsetLayouts_.end();
1885         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1886         for (; cit != end; ++cit) {
1887                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1888                 if (it == ils.end())
1889                         continue;
1890                 tcpreamble << it->second.preamble();
1891         }
1892
1893         return tcpreamble.str();
1894 }
1895
1896
1897 docstring const LaTeXFeatures::getTClassHTMLPreamble() const
1898 {
1899         DocumentClass const & tclass = params_.documentClass();
1900         odocstringstream tcpreamble;
1901
1902         tcpreamble << tclass.htmlpreamble();
1903
1904         list<docstring>::const_iterator cit = usedLayouts_.begin();
1905         list<docstring>::const_iterator end = usedLayouts_.end();
1906         for (; cit != end; ++cit)
1907                 tcpreamble << tclass[*cit].htmlpreamble();
1908
1909         cit = usedInsetLayouts_.begin();
1910         end = usedInsetLayouts_.end();
1911         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1912         for (; cit != end; ++cit) {
1913                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1914                 if (it == ils.end())
1915                         continue;
1916                 tcpreamble << it->second.htmlpreamble();
1917         }
1918
1919         return tcpreamble.str();
1920 }
1921
1922
1923 docstring const LaTeXFeatures::getTClassHTMLStyles() const
1924 {
1925         DocumentClass const & tclass = params_.documentClass();
1926         odocstringstream tcpreamble;
1927
1928         if (mustProvide("noun"))
1929                 tcpreamble << lyxnoun_style;
1930         // this isn't exact, but it won't hurt that much if it
1931         // wasn't for this.
1932         if (mustProvide("ulem"))
1933                 tcpreamble << lyxstrikeout_style;
1934
1935         tcpreamble << tclass.htmlstyles();
1936
1937         list<docstring>::const_iterator cit = usedLayouts_.begin();
1938         list<docstring>::const_iterator end = usedLayouts_.end();
1939         for (; cit != end; ++cit)
1940                 tcpreamble << tclass[*cit].htmlstyle();
1941
1942         cit = usedInsetLayouts_.begin();
1943         end = usedInsetLayouts_.end();
1944         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1945         for (; cit != end; ++cit) {
1946                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1947                 if (it == ils.end())
1948                         continue;
1949                 tcpreamble << it->second.htmlstyle();
1950         }
1951
1952         return tcpreamble.str();
1953 }
1954
1955
1956 namespace {
1957
1958 docstring const getFloatI18nPreamble(docstring const & type,
1959                         docstring const & name, Language const * lang,
1960                         Encoding const & enc, bool const polyglossia)
1961 {
1962         // Check whether name can be encoded in the buffer encoding
1963         bool encodable = true;
1964         for (size_t i = 0; i < name.size(); ++i) {
1965                 if (!enc.encodable(name[i])) {
1966                         encodable = false;
1967                         break;
1968                 }
1969         }
1970
1971         docstring const language = polyglossia ? from_ascii(lang->polyglossia())
1972                                                : from_ascii(lang->babel());
1973         docstring const langenc = from_ascii(lang->encoding()->iconvName());
1974         docstring const texenc = from_ascii(lang->encoding()->latexName());
1975         docstring const bufenc = from_ascii(enc.iconvName());
1976         docstring const s1 = docstring(1, 0xF0000);
1977         docstring const s2 = docstring(1, 0xF0001);
1978         docstring const translated = encodable ? name
1979                 : from_ascii("\\inputencoding{") + texenc + from_ascii("}")
1980                         + s1 + langenc + s2 + name + s1 + bufenc + s2;
1981
1982         odocstringstream os;
1983         os << "\\addto\\captions" << language
1984            << "{\\renewcommand{\\" << type << "name}{" << translated << "}}\n";
1985         return os.str();
1986 }
1987
1988
1989 docstring const i18npreamble(docstring const & templ, Language const * lang,
1990                              Encoding const & enc, bool const polyglossia,
1991                              bool const need_fixedwidth)
1992 {
1993         if (templ.empty())
1994                 return templ;
1995
1996         string preamble = polyglossia ?
1997                 subst(to_utf8(templ), "$$lang", lang->polyglossia()) :
1998                 subst(to_utf8(templ), "$$lang", lang->babel());
1999
2000         string const langenc = lang->encoding()->iconvName();
2001         string const texenc = lang->encoding()->latexName();
2002         string const bufenc = enc.iconvName();
2003         Encoding const * testenc(&enc);
2004         bool lang_fallback = false;
2005         bool ascii_fallback = false;
2006         if (need_fixedwidth && !enc.hasFixedWidth()) {
2007                 if (lang->encoding()->hasFixedWidth()) {
2008                         testenc = lang->encoding();
2009                         lang_fallback = true;
2010                 } else {
2011                         // We need a fixed width encoding, but both the buffer
2012                         // encoding and the language encoding are variable
2013                         // width. As a last fallback, try to convert to pure
2014                         // ASCII using the LaTeX commands defined in unicodesymbols.
2015                         testenc = encodings.fromLyXName("ascii");
2016                         if (!testenc)
2017                                 return docstring();
2018                         ascii_fallback = true;
2019                 }
2020         }
2021         // First and second character of plane 15 (Private Use Area)
2022         string const s1 = "\xf3\xb0\x80\x80"; // U+F0000
2023         string const s2 = "\xf3\xb0\x80\x81"; // U+F0001
2024         // FIXME UNICODE
2025         // lyx::regex is not unicode-safe.
2026         // Should use QRegExp or (boost::u32regex, but that requires ICU)
2027         static regex const reg("_\\(([^\\)]+)\\)");
2028         smatch sub;
2029         while (regex_search(preamble, sub, reg)) {
2030                 string const key = sub.str(1);
2031                 docstring const name = lang->translateLayout(key);
2032                 // Check whether name can be encoded in the buffer encoding
2033                 bool encodable = true;
2034                 for (size_t i = 0; i < name.size() && encodable; ++i)
2035                         if (!testenc->encodable(name[i]))
2036                                 encodable = false;
2037                 string translated;
2038                 if (encodable && !lang_fallback)
2039                         translated = to_utf8(name);
2040                 else if (ascii_fallback)
2041                         translated = to_ascii(testenc->latexString(name).first);
2042                 else
2043                         translated = "\\inputencoding{" + texenc + "}"
2044                                 + s1 + langenc + s2 + to_utf8(name)
2045                                 + s1 + bufenc + s2;
2046                 preamble = subst(preamble, sub.str(), translated);
2047         }
2048         return from_utf8(preamble);
2049 }
2050
2051 } // namespace
2052
2053
2054 docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel,
2055                                 bool use_polyglossia, bool use_minted) const
2056 {
2057         DocumentClass const & tclass = params_.documentClass();
2058         // collect preamble snippets in a set to prevent multiple identical
2059         // commands (would happen if e.g. both theorem and theorem* are used)
2060         set<docstring> snippets;
2061         typedef LanguageList::const_iterator lang_it;
2062         lang_it const lbeg = UsedLanguages_.begin();
2063         lang_it const lend =  UsedLanguages_.end();
2064         list<docstring>::const_iterator cit = usedLayouts_.begin();
2065         list<docstring>::const_iterator end = usedLayouts_.end();
2066         for (; cit != end; ++cit) {
2067                 // language dependent commands (once per document)
2068                 snippets.insert(i18npreamble(tclass[*cit].langpreamble(),
2069                                                 buffer().language(),
2070                                                 buffer().params().encoding(),
2071                                                 use_polyglossia, false));
2072                 // commands for language changing (for multilanguage documents)
2073                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
2074                         snippets.insert(i18npreamble(
2075                                                 tclass[*cit].babelpreamble(),
2076                                                 buffer().language(),
2077                                                 buffer().params().encoding(),
2078                                                 use_polyglossia, false));
2079                         for (lang_it lit = lbeg; lit != lend; ++lit)
2080                                 snippets.insert(i18npreamble(
2081                                                 tclass[*cit].babelpreamble(),
2082                                                 *lit,
2083                                                 buffer().params().encoding(),
2084                                                 use_polyglossia, false));
2085                 }
2086         }
2087         if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
2088                 FloatList const & floats = params_.documentClass().floats();
2089                 UsedFloats::const_iterator fit = usedFloats_.begin();
2090                 UsedFloats::const_iterator fend = usedFloats_.end();
2091                 for (; fit != fend; ++fit) {
2092                         Floating const & fl = floats.getType(fit->first);
2093                         // we assume builtin floats are translated
2094                         if (fl.isPredefined())
2095                                 continue;
2096                         docstring const type = from_ascii(fl.floattype());
2097                         docstring const flname = from_utf8(fl.name());
2098                         docstring name = buffer().language()->translateLayout(fl.name());
2099                         // only request translation if we have a real translation
2100                         // (that differs from the source)
2101                         if (flname != name)
2102                                 snippets.insert(getFloatI18nPreamble(
2103                                                 type, name, buffer().language(),
2104                                                 buffer().params().encoding(),
2105                                                 use_polyglossia));
2106                         for (lang_it lit = lbeg; lit != lend; ++lit) {
2107                                 string const code = (*lit)->code();
2108                                 name = (*lit)->translateLayout(fl.name());
2109                                 // we assume we have a suitable translation if
2110                                 // either the language is English (we need to
2111                                 // translate into English if English is a secondary
2112                                 // language) or if translateIfPossible returns
2113                                 // something different to the English source.
2114                                 bool const have_translation =
2115                                         (flname != name || contains(code, "en"));
2116                                 if (have_translation)
2117                                         snippets.insert(getFloatI18nPreamble(
2118                                                 type, name, *lit,
2119                                                 buffer().params().encoding(),
2120                                                 use_polyglossia));
2121                         }
2122                 }
2123         }
2124
2125         cit = usedInsetLayouts_.begin();
2126         end = usedInsetLayouts_.end();
2127         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
2128         for (; cit != end; ++cit) {
2129                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
2130                 if (it == ils.end())
2131                         continue;
2132                 // The listings package does not work with variable width
2133                 // encodings, only with fixed width encodings. Therefore we
2134                 // need to force a fixed width encoding for
2135                 // \lstlistlistingname and \lstlistingname (bug 9382).
2136                 // This needs to be consistent with InsetListings::latex()
2137                 // rsp. InsetListings::forcedEncoding().
2138                 bool const need_fixedwidth = !use_minted &&
2139                                         !runparams_.isFullUnicode() &&
2140                                         buffer().params().encoding().package() != Encoding::japanese &&
2141                                         it->second.fixedwidthpreambleencoding();
2142                 // language dependent commands (once per document)
2143                 snippets.insert(i18npreamble(it->second.langpreamble(),
2144                                                 buffer().language(),
2145                                                 buffer().params().encoding(),
2146                                                 use_polyglossia, need_fixedwidth));
2147                 // commands for language changing (for multilanguage documents)
2148                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
2149                         snippets.insert(i18npreamble(
2150                                                 it->second.babelpreamble(),
2151                                                 buffer().language(),
2152                                                 buffer().params().encoding(),
2153                                                 use_polyglossia, need_fixedwidth));
2154                         for (lang_it lit = lbeg; lit != lend; ++lit)
2155                                 snippets.insert(i18npreamble(
2156                                                 it->second.babelpreamble(),
2157                                                 *lit,
2158                                                 buffer().params().encoding(),
2159                                                 use_polyglossia, need_fixedwidth));
2160                 }
2161         }
2162
2163         odocstringstream tcpreamble;
2164         set<docstring>::const_iterator const send = snippets.end();
2165         set<docstring>::const_iterator it = snippets.begin();
2166         for (; it != send; ++it)
2167                 tcpreamble << *it;
2168         return tcpreamble.str();
2169 }
2170
2171
2172 docstring const LaTeXFeatures::getLyXSGMLEntities() const
2173 {
2174         // Definition of entities used in the document that are LyX related.
2175         odocstringstream entities;
2176
2177         if (mustProvide("lyxarrow")) {
2178                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
2179         }
2180
2181         return entities.str();
2182 }
2183
2184
2185 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
2186 {
2187         odocstringstream sgmlpreamble;
2188         // FIXME UNICODE
2189         docstring const basename(from_utf8(onlyPath(fname)));
2190
2191         FileMap::const_iterator end = IncludedFiles_.end();
2192         for (FileMap::const_iterator fi = IncludedFiles_.begin();
2193              fi != end; ++fi)
2194                 // FIXME UNICODE
2195                 sgmlpreamble << "\n<!ENTITY " << fi->first
2196                              << (isSGMLFileName(fi->second) ? " SYSTEM \"" : " \"")
2197                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
2198
2199         return sgmlpreamble.str();
2200 }
2201
2202
2203 void LaTeXFeatures::showStruct() const
2204 {
2205         lyxerr << "LyX needs the following commands when LaTeXing:"
2206                << "\n***** Packages:" << getPackages()
2207                << "\n***** Macros:" << to_utf8(getMacros().str)
2208                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
2209                << "\n***** done." << endl;
2210 }
2211
2212
2213 Buffer const & LaTeXFeatures::buffer() const
2214 {
2215         return *buffer_;
2216 }
2217
2218
2219 void LaTeXFeatures::setBuffer(Buffer const & buffer)
2220 {
2221         buffer_ = &buffer;
2222 }
2223
2224
2225 BufferParams const & LaTeXFeatures::bufferParams() const
2226 {
2227         return params_;
2228 }
2229
2230
2231 void LaTeXFeatures::getFloatDefinitions(otexstream & os) const
2232 {
2233         FloatList const & floats = params_.documentClass().floats();
2234
2235         // Here we will output the code to create the needed float styles.
2236         // We will try to do this as minimal as possible.
2237         // \floatstyle{ruled}
2238         // \newfloat{algorithm}{htbp}{loa}
2239         // \providecommand{\algorithmname}{Algorithm}
2240         // \floatname{algorithm}{\protect\algorithmname}
2241         UsedFloats::const_iterator cit = usedFloats_.begin();
2242         UsedFloats::const_iterator end = usedFloats_.end();
2243         for (; cit != end; ++cit) {
2244                 Floating const & fl = floats.getType(cit->first);
2245
2246                 // For builtin floats we do nothing.
2247                 if (fl.isPredefined())
2248                         continue;
2249
2250                 // We have to special case "table" and "figure"
2251                 if (fl.floattype() == "tabular" || fl.floattype() == "figure") {
2252                         // Output code to modify "table" or "figure"
2253                         // but only if builtin == false
2254                         // and that have to be true at this point in the
2255                         // function.
2256                         docstring const type = from_ascii(fl.floattype());
2257                         docstring const placement = from_ascii(fl.placement());
2258                         docstring const style = from_ascii(fl.style());
2259                         if (!style.empty()) {
2260                                 os << "\\floatstyle{" << style << "}\n"
2261                                    << "\\restylefloat{" << type << "}\n";
2262                         }
2263                         if (!placement.empty()) {
2264                                 os << "\\floatplacement{" << type << "}{"
2265                                    << placement << "}\n";
2266                         }
2267                 } else {
2268                         // The other non builtin floats.
2269
2270                         docstring const type = from_ascii(fl.floattype());
2271                         docstring const placement = from_ascii(fl.placement());
2272                         docstring const ext = from_ascii(fl.ext());
2273                         docstring const within = from_ascii(fl.within());
2274                         docstring const style = from_ascii(fl.style());
2275                         docstring const name =
2276                                 buffer().language()->translateLayout(fl.name());
2277                         os << "\\floatstyle{" << style << "}\n"
2278                            << "\\newfloat{" << type << "}{" << placement
2279                            << "}{" << ext << '}';
2280                         if (!within.empty())
2281                                 os << '[' << within << ']';
2282                         os << '\n'
2283                            << "\\providecommand{\\" << type << "name}{"
2284                            << name << "}\n"
2285                            << "\\floatname{" << type << "}{\\protect\\"
2286                            << type << "name}\n";
2287
2288                         // What missing here is to code to minimalize the code
2289                         // output so that the same floatstyle will not be
2290                         // used several times, when the same style is still in
2291                         // effect. (Lgb)
2292                 }
2293                 if (cit->second)
2294                         // The subfig package is loaded later
2295                         os << "\n\\AtBeginDocument{\\newsubfloat{" << from_ascii(fl.floattype()) << "}}\n";
2296         }
2297 }
2298
2299
2300 void LaTeXFeatures::resolveAlternatives()
2301 {
2302         for (Features::iterator it = features_.begin(); it != features_.end();) {
2303                 if (contains(*it, '|')) {
2304                         vector<string> const alternatives = getVectorFromString(*it, "|");
2305                         vector<string>::const_iterator const end = alternatives.end();
2306                         vector<string>::const_iterator ita = alternatives.begin();
2307                         // Is any alternative already required? => use that
2308                         for (; ita != end; ++ita) {
2309                                 if (isRequired(*ita))
2310                                         break;
2311                         }
2312                         // Is any alternative available? => use the first one
2313                         // (bug 9498)
2314                         if (ita == end) {
2315                                 for (ita = alternatives.begin(); ita != end; ++ita) {
2316                                         if (isAvailable(*ita)) {
2317                                                 require(*ita);
2318                                                 break;
2319                                         }
2320                                 }
2321                         }
2322                         // This will not work, but not requiring something
2323                         // would be more confusing
2324                         if (ita == end)
2325                                 require(alternatives.front());
2326                         features_.erase(it);
2327                         it = features_.begin();
2328                 } else
2329                         ++it;
2330         }
2331 }
2332
2333
2334 void LaTeXFeatures::expandMultiples()
2335 {
2336         for (Features::iterator it = features_.begin(); it != features_.end();) {
2337                 if (contains(*it, ',')) {
2338                         vector<string> const multiples = getVectorFromString(*it, ",");
2339                         vector<string>::const_iterator const end = multiples.end();
2340                         vector<string>::const_iterator itm = multiples.begin();
2341                         // Do nothing if any multiple is already required
2342                         for (; itm != end; ++itm) {
2343                                 if (!isRequired(*itm))
2344                                         require(*itm);
2345                         }
2346                         features_.erase(it);
2347                         it = features_.begin();
2348                 } else
2349                         ++it;
2350         }
2351 }
2352
2353
2354 } // namespace lyx