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