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