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