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