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