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