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