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