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