]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
Fix font of macro template name
[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=}\\textquotedbl\\egroup}");
127
128 static docstring const textquotedblp_luatex_def = from_ascii(
129         "\\providecommand\\textquotedblplain{%\n"
130         "  \\bgroup\\addfontfeatures{RawFeature=-tlig}\\textquotedbl\\egroup}");
131
132 static docstring const textquotesinglep_xetex_def = from_ascii(
133         "\\providecommand\\textquotesingleplain{%\n"
134         "  \\bgroup\\addfontfeatures{Mapping=}\\textquotesingle\\egroup}");
135
136 static docstring const textquotesinglep_luatex_def = from_ascii(
137         "\\providecommand\\textquotesingleplain{%\n"
138         "  \\bgroup\\addfontfeatures{RawFeature=-tlig}\\textquotesingle\\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_.font_encoding() == "default"
595                 || params_.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         "chicago",
967         "chscite",
968         "harvard",
969         "mslapa",
970         "named"
971 };
972
973 int const nb_bibliofeatures = sizeof(bibliofeatures) / sizeof(char const *);
974
975 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
976
977 }
978
979
980 string const LaTeXFeatures::getColorOptions() const
981 {
982         ostringstream colors;
983
984         // Handling the color packages separately is needed to be able to load them
985         // before babel when hyperref is loaded with the colorlinks option
986         // for more info see Bufferparams.cpp
987
988         // [x]color.sty
989         if (mustProvide("color") || mustProvide("xcolor")) {
990                 string const package =
991                         (mustProvide("xcolor") ? "xcolor" : "color");
992                 if (params_.graphics_driver == "default"
993                         || params_.graphics_driver == "none")
994                         colors << "\\usepackage{" << package << "}\n";
995                 else
996                         colors << "\\usepackage["
997                                  << params_.graphics_driver
998                                  << "]{" << package << "}\n";
999         }
1000
1001         // pdfcolmk must be loaded after color
1002         if (mustProvide("pdfcolmk"))
1003                 colors << "\\usepackage{pdfcolmk}\n";
1004
1005         // the following 3 color commands must be set after color
1006         // is loaded and before pdfpages, therefore add the command
1007         // here define the set color
1008         if (mustProvide("pagecolor")) {
1009                 colors << "\\definecolor{page_backgroundcolor}{rgb}{";
1010                 colors << outputLaTeXColor(params_.backgroundcolor) << "}\n";
1011                 // set the page color
1012                 colors << "\\pagecolor{page_backgroundcolor}\n";
1013         }
1014
1015         if (mustProvide("fontcolor")) {
1016                 colors << "\\definecolor{document_fontcolor}{rgb}{";
1017                 colors << outputLaTeXColor(params_.fontcolor) << "}\n";
1018                 // set the color
1019                 colors << "\\color{document_fontcolor}\n";
1020         }
1021
1022         if (mustProvide("lyxgreyedout")) {
1023                 colors << "\\definecolor{note_fontcolor}{rgb}{";
1024                 colors << outputLaTeXColor(params_.notefontcolor) << "}\n";
1025                 // the color will be set together with the definition of
1026                 // the lyxgreyedout environment (see lyxgreyedout_def)
1027         }
1028
1029         // color for shaded boxes
1030         if (isRequired("framed") && mustProvide("color")) {
1031                 colors << "\\definecolor{shadecolor}{rgb}{";
1032                 colors << outputLaTeXColor(params_.boxbgcolor) << "}\n";
1033                 // this color is automatically used by the LaTeX-package "framed"
1034         }
1035
1036         return colors.str();
1037 }
1038
1039
1040 string const LaTeXFeatures::getPackageOptions() const
1041 {
1042         ostringstream packageopts;
1043         // Output all the package option stuff we have been asked to do.
1044         map<string, string>::const_iterator it =
1045                 params_.documentClass().packageOptions().begin();
1046         map<string, string>::const_iterator en =
1047                 params_.documentClass().packageOptions().end();
1048         for (; it != en; ++it)
1049                 if (mustProvide(it->first))
1050                         packageopts << "\\PassOptionsToPackage{" << it->second << "}"
1051                                  << "{" << it->first << "}\n";
1052         return packageopts.str();
1053 }
1054
1055
1056 string const LaTeXFeatures::getPackages() const
1057 {
1058         ostringstream packages;
1059
1060         // FIXME: currently, we can only load packages and macros known
1061         // to LyX.
1062         // However, with the Require tag of layouts/custom insets,
1063         // also unknown packages can be requested. They are silently
1064         // swallowed now. We should change this eventually.
1065
1066         //  These are all the 'simple' includes.  i.e
1067         //  packages which we just \usepackage{package}
1068         for (int i = 0; i < nb_simplefeatures; ++i) {
1069                 if (mustProvide(simplefeatures[i]))
1070                         packages << "\\usepackage{" << simplefeatures[i] << "}\n";
1071         }
1072
1073         // The rest of these packages are somewhat more complicated
1074         // than those above.
1075
1076         // The tipa package and its extensions (tipx, tone) must not
1077         // be loaded with non-TeX fonts, since fontspec includes the
1078         // respective macros
1079         if (mustProvide("tipa") && !params_.useNonTeXFonts)
1080                 packages << "\\usepackage{tipa}\n";
1081         if (mustProvide("tipx") && !params_.useNonTeXFonts)
1082                 packages << "\\usepackage{tipx}\n";
1083         if (mustProvide("extraipa") && !params_.useNonTeXFonts)
1084                 packages << "\\usepackage{extraipa}\n";
1085         if (mustProvide("tone") && !params_.useNonTeXFonts)
1086                 packages << "\\usepackage{tone}\n";
1087
1088         // if fontspec or newtxmath is used, AMS packages have to be loaded
1089         // before fontspec (in BufferParams)
1090         string const amsPackages = loadAMSPackages();
1091         bool const ot1 = (params_.font_encoding() == "default" || params_.font_encoding() == "OT1");
1092         bool const use_newtxmath =
1093                 theLaTeXFonts().getLaTeXFont(from_ascii(params_.fontsMath())).getUsedPackage(
1094                         ot1, false, false) == "newtxmath";
1095
1096         if (!params_.useNonTeXFonts && !use_newtxmath && !amsPackages.empty())
1097                 packages << amsPackages;
1098
1099         if (mustProvide("cancel") &&
1100             params_.use_package("cancel") != BufferParams::package_off)
1101                 packages << "\\usepackage{cancel}\n";
1102
1103         // marvosym and bbding both define the \Cross macro
1104         if (mustProvide("marvosym")) {
1105             if (mustProvide("bbding"))
1106                 packages << "\\let\\Cross\\relax\n";
1107             packages << "\\usepackage{marvosym}\n";
1108         }
1109
1110         // accents must be loaded after amsmath
1111         if (mustProvide("accents") &&
1112             params_.use_package("accents") != BufferParams::package_off)
1113                 packages << "\\usepackage{accents}\n";
1114
1115         // mathdots must be loaded after amsmath
1116         if (mustProvide("mathdots") &&
1117                 params_.use_package("mathdots") != BufferParams::package_off)
1118                 packages << "\\usepackage{mathdots}\n";
1119
1120         // yhmath must be loaded after amsmath
1121         if (mustProvide("yhmath") &&
1122             params_.use_package("yhmath") != BufferParams::package_off)
1123                 packages << "\\usepackage{yhmath}\n";
1124
1125         // stmaryrd must be loaded after amsmath
1126         if (mustProvide("stmaryrd") &&
1127             params_.use_package("stmaryrd") != BufferParams::package_off)
1128                 packages << "\\usepackage{stmaryrd}\n";
1129
1130         if (mustProvide("stackrel") &&
1131             params_.use_package("stackrel") != BufferParams::package_off)
1132                 packages << "\\usepackage{stackrel}\n";
1133
1134         if (mustProvide("undertilde") &&
1135                 params_.use_package("undertilde") != BufferParams::package_off)
1136                 packages << "\\usepackage{undertilde}\n";
1137
1138         // [x]color and pdfcolmk are handled in getColorOptions() above
1139
1140         // makeidx.sty
1141         if (isRequired("makeidx") || isRequired("splitidx")) {
1142                 if (!isProvided("makeidx") && !isRequired("splitidx"))
1143                         packages << "\\usepackage{makeidx}\n";
1144                 if (mustProvide("splitidx"))
1145                         packages << "\\usepackage{splitidx}\n";
1146                 packages << "\\makeindex\n";
1147         }
1148
1149         // graphicx.sty
1150         if (mustProvide("graphicx") && params_.graphics_driver != "none") {
1151                 if (params_.graphics_driver == "default")
1152                         packages << "\\usepackage{graphicx}\n";
1153                 else
1154                         packages << "\\usepackage["
1155                                  << params_.graphics_driver
1156                                  << "]{graphicx}\n";
1157         }
1158
1159         // lyxskak.sty --- newer chess support based on skak.sty
1160         if (mustProvide("chess"))
1161                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
1162
1163         // setspace.sty
1164         if (mustProvide("setspace") && !isProvided("SetSpace"))
1165                 packages << "\\usepackage{setspace}\n";
1166
1167         // we need to assure that mhchem is loaded before esint and every other
1168         // package that redefines command of amsmath because mhchem loads amlatex
1169         // (this info is from the author of mhchem from June 2013)
1170         if (mustProvide("mhchem") &&
1171             params_.use_package("mhchem") != BufferParams::package_off)
1172                 packages << "\\PassOptionsToPackage{version=3}{mhchem}\n"
1173                             "\\usepackage{mhchem}\n";
1174
1175         // wasysym is a simple feature, but it must be after amsmath if both
1176         // are used
1177         // wasysym redefines some integrals (e.g. iint) from amsmath. That
1178         // leads to inconsistent integrals. We only load this package if
1179         // the document does not contain integrals (then isRequired("esint")
1180         // is false) or if esint is used, since esint redefines all relevant
1181         // integral symbols from wasysym and amsmath.
1182         // See http://www.lyx.org/trac/ticket/1942
1183         if (mustProvide("wasysym") &&
1184             params_.use_package("wasysym") != BufferParams::package_off &&
1185             (params_.use_package("esint") != BufferParams::package_off || !isRequired("esint")))
1186                 packages << "\\usepackage{wasysym}\n";
1187
1188         // esint must be after amsmath (and packages requiring amsmath, like mhchem)
1189         // and wasysym, since it will redeclare inconsistent integral symbols
1190         if (mustProvide("esint") &&
1191             params_.use_package("esint") != BufferParams::package_off)
1192                 packages << "\\usepackage{esint}\n";
1193
1194         // Known bibliography packages (simple \usepackage{package})
1195         for (int i = 0; i < nb_bibliofeatures; ++i) {
1196                 if (mustProvide(bibliofeatures[i]))
1197                         packages << "\\usepackage{"
1198                                  << bibliofeatures[i] << "}\n";
1199         }
1200
1201         // Compatibility between achicago and natbib
1202         if (mustProvide("achicago") && mustProvide("natbib"))
1203                 packages << "\\let\\achicagobib\\thebibliography\n";
1204
1205         // natbib.sty
1206         // Some classes load natbib themselves, but still allow (or even require)
1207         // plain numeric citations (ReVTeX is such a case, see bug 5182).
1208         // This special case is indicated by the "natbib-internal" key.
1209         if (mustProvide("natbib") && !isProvided("natbib-internal")) {
1210                 packages << "\\usepackage[";
1211                 if (params_.citeEngineType() == ENGINE_TYPE_NUMERICAL)
1212                         packages << "numbers";
1213                 else
1214                         packages << "authoryear";
1215                 if (!params_.biblio_opts.empty())
1216                         packages << ',' << params_.biblio_opts;
1217                 packages << "]{natbib}\n";
1218         }
1219
1220         // Compatibility between achicago and natbib
1221         if (mustProvide("achicago") && mustProvide("natbib")) {
1222                 packages << "\\let\\thebibliography\\achicagobib\n";
1223                 packages << "\\let\\SCcite\\astroncite\n";
1224                 packages << "\\let\\UnexpandableProtect\\protect\n";
1225         }
1226
1227         // jurabib -- we need version 0.6 at least.
1228         if (mustProvide("jurabib")) {
1229                 packages << "\\usepackage";
1230                 if (!params_.biblio_opts.empty())
1231                         packages << '[' << params_.biblio_opts << ']';
1232                 packages << "{jurabib}[2004/01/25]\n";
1233         }
1234
1235         // opcit -- we pass custombst as we output \bibliographystyle ourselves
1236         if (mustProvide("opcit")) {
1237                 if (isRequired("hyperref"))
1238                         packages << "\\usepackage[custombst,hyperref]{opcit}\n";
1239                 else
1240                         packages << "\\usepackage[custombst]{opcit}\n";
1241         }
1242
1243         // xargs -- we need version 1.09 at least
1244         if (mustProvide("xargs"))
1245                 packages << "\\usepackage{xargs}[2008/03/08]\n";
1246
1247         if (mustProvide("xy"))
1248                 packages << "\\usepackage[all]{xy}\n";
1249
1250         if (mustProvide("feyn"))
1251                 packages << "\\usepackage{feyn}\n"; //Diagram
1252
1253         if (mustProvide("ulem"))
1254                 packages << "\\PassOptionsToPackage{normalem}{ulem}\n"
1255                             "\\usepackage{ulem}\n";
1256
1257         if (mustProvide("nomencl")) {
1258                 // Make it work with the new and old version of the package,
1259                 // but don't use the compatibility option since it is
1260                 // incompatible to other packages.
1261                 packages << "\\usepackage{nomencl}\n"
1262                             "% the following is useful when we have the old nomencl.sty package\n"
1263                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
1264                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
1265                             "\\makenomenclature\n";
1266         }
1267
1268         // fixltx2e provides subscript
1269         if (mustProvide("subscript") && !isRequired("fixltx2e"))
1270                 packages << "\\usepackage{subscript}\n";
1271
1272         // footmisc must be loaded after setspace
1273         // Set options here, load the package after the user preamble to
1274         // avoid problems with manual loaded footmisc.
1275         if (mustProvide("footmisc"))
1276                 packages << "\\PassOptionsToPackage{stable}{footmisc}\n";
1277
1278         if (mustProvide("microtype")){
1279                 packages << "\\usepackage{microtype}\n";
1280         }
1281
1282         return packages.str();
1283 }
1284
1285
1286 TexString LaTeXFeatures::getMacros() const
1287 {
1288         otexstringstream macros;
1289
1290         if (!preamble_snippets_.empty()) {
1291                 macros << '\n';
1292                 macros << getPreambleSnippets();
1293         }
1294
1295         if (mustProvide("papersize")) {
1296                 if (runparams_.flavor == OutputParams::LATEX
1297                     || runparams_.flavor == OutputParams::DVILUATEX)
1298                         macros << papersizedvi_def << '\n';
1299                 else if  (runparams_.flavor == OutputParams::LUATEX)
1300                         macros << papersizepdflua_def << '\n';
1301                 else
1302                         macros << papersizepdf_def << '\n';
1303         }
1304
1305         if (mustProvide("LyX")) {
1306                 if (isRequired("hyperref"))
1307                         macros << lyx_hyperref_def << '\n';
1308                 else
1309                         macros << lyx_def << '\n';
1310         }
1311
1312         if (mustProvide("noun"))
1313                 macros << noun_def << '\n';
1314
1315         if (mustProvide("lyxarrow"))
1316                 macros << lyxarrow_def << '\n';
1317
1318         if (!usePolyglossia() && mustProvide("textgreek")) {
1319             // ensure LGR font encoding is defined also if fontenc is not loaded by LyX
1320                 if (params_.font_encoding() == "default")
1321                         macros << textgreek_LGR_def;
1322                 macros << textgreek_def << '\n';
1323         }
1324
1325         if (!usePolyglossia() && mustProvide("textcyr")) {
1326                 // ensure T2A font encoding is set up also if fontenc is not loaded by LyX
1327                 if (params_.font_encoding() == "default")
1328                         macros << textcyr_T2A_def;
1329                 macros << textcyr_def << '\n';
1330         }
1331
1332         // non-standard text accents:
1333         if (mustProvide("textcommaabove") || mustProvide("textcommaaboveright") ||
1334             mustProvide("textcommabelow") || mustProvide("textbaltic"))
1335                 macros << lyxaccent_def;
1336
1337         if (mustProvide("textcommabelow") || mustProvide("textbaltic"))
1338                 macros << textcommabelow_def << '\n';
1339
1340         if (mustProvide("textcommaabove") || mustProvide("textbaltic"))
1341                 macros << textcommaabove_def << '\n';
1342
1343         if (mustProvide("textcommaaboveright"))
1344                 macros << textcommaaboveright_def << '\n';
1345
1346         if (mustProvide("textbaltic"))
1347                 macros << textbaltic_def << '\n';
1348
1349         // split-level fractions
1350         if (mustProvide("xfrac") || mustProvide("smallLetterFrac"))
1351                 macros << xfrac_def << '\n';
1352
1353         if (mustProvide("smallLetterFrac"))
1354                 macros << smallLetterFrac_def << '\n';
1355
1356         if (mustProvide("lyxmathsym"))
1357                 macros << lyxmathsym_def << '\n';
1358
1359         if (mustProvide("cedilla"))
1360                 macros << cedilla_def << '\n';
1361
1362         if (mustProvide("subring"))
1363                 macros << subring_def << '\n';
1364
1365         if (mustProvide("subdot"))
1366                 macros << subdot_def << '\n';
1367
1368         if (mustProvide("subhat"))
1369                 macros << subhat_def << '\n';
1370
1371         if (mustProvide("subtilde"))
1372                 macros << subtilde_def << '\n';
1373
1374         if (mustProvide("dacute"))
1375                 macros << dacute_def << '\n';
1376
1377         if (mustProvide("tipasymb"))
1378                 macros << tipasymb_def << '\n';
1379
1380         if (mustProvide("dgrave"))
1381                 macros << dgrave_def << '\n';
1382
1383         if (mustProvide("rcap"))
1384                 macros << rcap_def << '\n';
1385
1386         if (mustProvide("ogonek"))
1387                 macros << ogonek_def << '\n';
1388
1389         // quotes.
1390         if (mustProvide("quotesinglbase"))
1391                 macros << quotesinglbase_def << '\n';
1392         if (mustProvide("quotedblbase"))
1393                 macros << quotedblbase_def << '\n';
1394         if (mustProvide("guilsinglleft"))
1395                 macros << guilsinglleft_def << '\n';
1396         if (mustProvide("guilsinglright"))
1397                 macros << guilsinglright_def << '\n';
1398         if (mustProvide("guillemotleft"))
1399                 macros << guillemotleft_def << '\n';
1400         if (mustProvide("guillemotright"))
1401                 macros << guillemotright_def << '\n';
1402         if (mustProvide("textquotedbl"))
1403                 macros << textquotedbl_def << '\n';
1404         if (mustProvide("textquotesinglep")) {
1405                 if (runparams_.flavor == OutputParams::XETEX)
1406                         macros << textquotesinglep_xetex_def << '\n';
1407                 else
1408                         macros << textquotesinglep_luatex_def << '\n';
1409         }
1410         if (mustProvide("textquotedblp")) {
1411                 if (runparams_.flavor == OutputParams::XETEX)
1412                         macros << textquotedblp_xetex_def << '\n';
1413                 else
1414                         macros << textquotedblp_luatex_def << '\n';
1415         }
1416
1417         // Math mode
1418         if (mustProvide("binom") && !isRequired("amsmath"))
1419                 macros << binom_def << '\n';
1420         if (mustProvide("mathcircumflex"))
1421                 macros << mathcircumflex_def << '\n';
1422
1423         // other
1424         if (mustProvide("ParagraphLeftIndent"))
1425                 macros << paragraphleftindent_def;
1426         if (mustProvide("NeedLyXFootnoteCode"))
1427                 macros << floatingfootnote_def;
1428
1429         // some problems with tex->html converters
1430         if (mustProvide("NeedTabularnewline"))
1431                 macros << tabularnewline_def;
1432
1433         // greyed-out environment (note inset)
1434         // the color is specified in the routine
1435         // getColorOptions() to avoid LaTeX-package clashes
1436         if (mustProvide("lyxgreyedout"))
1437                 macros << lyxgreyedout_def;
1438
1439         if (mustProvide("lyxdot"))
1440                 macros << lyxdot_def << '\n';
1441
1442         // floats
1443         getFloatDefinitions(macros);
1444
1445         if (mustProvide("refstyle"))
1446                 macros << lyxref_def << '\n';
1447
1448         // change tracking
1449         if (mustProvide("ct-dvipost"))
1450                 macros << changetracking_dvipost_def;
1451
1452         if (mustProvide("ct-xcolor-ulem")) {
1453                 streamsize const prec = macros.os().precision(2);
1454
1455                 RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
1456                 macros << "\\providecolor{lyxadded}{rgb}{"
1457                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
1458
1459                 RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
1460                 macros << "\\providecolor{lyxdeleted}{rgb}{"
1461                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
1462
1463                 macros.os().precision(prec);
1464
1465                 if (isRequired("hyperref"))
1466                         macros << changetracking_xcolor_ulem_hyperref_def;
1467                 else
1468                         macros << changetracking_xcolor_ulem_def;
1469         }
1470
1471         if (mustProvide("ct-tikz-math-sout"))
1472                         macros << changetracking_tikz_math_sout_def;
1473
1474         if (mustProvide("ct-none"))
1475                 macros << changetracking_none_def;
1476
1477         if (mustProvide("rtloutputdblcol"))
1478                 macros << rtloutputdblcol_def;
1479
1480         return macros.release();
1481 }
1482
1483
1484 docstring const LaTeXFeatures::getBabelPresettings() const
1485 {
1486         odocstringstream tmp;
1487
1488         for (Language const * lang : UsedLanguages_)
1489                 if (!lang->babel_presettings().empty())
1490                         tmp << lang->babel_presettings() << '\n';
1491         if (!params_.language->babel_presettings().empty())
1492                 tmp << params_.language->babel_presettings() << '\n';
1493
1494         if (!contains(tmp.str(), '@'))
1495                 return tmp.str();
1496
1497         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1498 }
1499
1500
1501 docstring const LaTeXFeatures::getBabelPostsettings() const
1502 {
1503         odocstringstream tmp;
1504
1505         for (Language const * lang : UsedLanguages_)
1506                 if (!lang->babel_postsettings().empty())
1507                         tmp << lang->babel_postsettings() << '\n';
1508         if (!params_.language->babel_postsettings().empty())
1509                 tmp << params_.language->babel_postsettings() << '\n';
1510
1511         if (!contains(tmp.str(), '@'))
1512                 return tmp.str();
1513
1514         return "\\makeatletter\n" + tmp.str() + "\\makeatother\n";
1515 }
1516
1517
1518 bool LaTeXFeatures::needBabelLangOptions() const
1519 {
1520         if (!lyxrc.language_global_options || params_.language->asBabelOptions())
1521                 return true;
1522
1523         LanguageList::const_iterator it  = UsedLanguages_.begin();
1524         LanguageList::const_iterator end = UsedLanguages_.end();
1525         for (; it != end; ++it)
1526                 if ((*it)->asBabelOptions())
1527                         return true;
1528
1529         return false;
1530 }
1531
1532
1533 string const LaTeXFeatures::loadAMSPackages() const
1534 {
1535         ostringstream tmp;
1536
1537         if (mustProvide("amsmath")
1538             && params_.use_package("amsmath") != BufferParams::package_off) {
1539                 tmp << "\\usepackage{amsmath}\n";
1540         } else {
1541                 // amsbsy and amstext are already provided by amsmath
1542                 if (mustProvide("amsbsy"))
1543                         tmp << "\\usepackage{amsbsy}\n";
1544                 if (mustProvide("amstext"))
1545                         tmp << "\\usepackage{amstext}\n";
1546         }
1547
1548         if (mustProvide("amsthm"))
1549                 tmp << "\\usepackage{amsthm}\n";
1550
1551         if (mustProvide("amssymb")
1552             && params_.use_package("amssymb") != BufferParams::package_off)
1553                 tmp << "\\usepackage{amssymb}\n";
1554
1555         return tmp.str();
1556 }
1557
1558
1559 docstring const LaTeXFeatures::getTClassPreamble() const
1560 {
1561         // the text class specific preamble
1562         DocumentClass const & tclass = params_.documentClass();
1563         odocstringstream tcpreamble;
1564
1565         tcpreamble << tclass.preamble();
1566
1567         list<docstring>::const_iterator cit = usedLayouts_.begin();
1568         list<docstring>::const_iterator end = usedLayouts_.end();
1569         for (; cit != end; ++cit)
1570                 tcpreamble << tclass[*cit].preamble();
1571
1572         cit = usedInsetLayouts_.begin();
1573         end = usedInsetLayouts_.end();
1574         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1575         for (; cit != end; ++cit) {
1576                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1577                 if (it == ils.end())
1578                         continue;
1579                 tcpreamble << it->second.preamble();
1580         }
1581
1582         return tcpreamble.str();
1583 }
1584
1585
1586 docstring const LaTeXFeatures::getTClassHTMLPreamble() const
1587 {
1588         DocumentClass const & tclass = params_.documentClass();
1589         odocstringstream tcpreamble;
1590
1591         tcpreamble << tclass.htmlpreamble();
1592
1593         list<docstring>::const_iterator cit = usedLayouts_.begin();
1594         list<docstring>::const_iterator end = usedLayouts_.end();
1595         for (; cit != end; ++cit)
1596                 tcpreamble << tclass[*cit].htmlpreamble();
1597
1598         cit = usedInsetLayouts_.begin();
1599         end = usedInsetLayouts_.end();
1600         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1601         for (; cit != end; ++cit) {
1602                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1603                 if (it == ils.end())
1604                         continue;
1605                 tcpreamble << it->second.htmlpreamble();
1606         }
1607
1608         return tcpreamble.str();
1609 }
1610
1611
1612 docstring const LaTeXFeatures::getTClassHTMLStyles() const
1613 {
1614         DocumentClass const & tclass = params_.documentClass();
1615         odocstringstream tcpreamble;
1616
1617         if (mustProvide("noun"))
1618                 tcpreamble << lyxnoun_style;
1619         // this isn't exact, but it won't hurt that much if it
1620         // wasn't for this.
1621         if (mustProvide("ulem"))
1622                 tcpreamble << lyxstrikeout_style;
1623
1624         tcpreamble << tclass.htmlstyles();
1625
1626         list<docstring>::const_iterator cit = usedLayouts_.begin();
1627         list<docstring>::const_iterator end = usedLayouts_.end();
1628         for (; cit != end; ++cit)
1629                 tcpreamble << tclass[*cit].htmlstyle();
1630
1631         cit = usedInsetLayouts_.begin();
1632         end = usedInsetLayouts_.end();
1633         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1634         for (; cit != end; ++cit) {
1635                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1636                 if (it == ils.end())
1637                         continue;
1638                 tcpreamble << it->second.htmlstyle();
1639         }
1640
1641         return tcpreamble.str();
1642 }
1643
1644
1645 namespace {
1646
1647 docstring const getFloatI18nPreamble(docstring const & type,
1648                         docstring const & name, Language const * lang,
1649                         Encoding const & enc, bool const polyglossia)
1650 {
1651         // Check whether name can be encoded in the buffer encoding
1652         bool encodable = true;
1653         for (size_t i = 0; i < name.size(); ++i) {
1654                 if (!enc.encodable(name[i])) {
1655                         encodable = false;
1656                         break;
1657                 }
1658         }
1659
1660         docstring const language = polyglossia ? from_ascii(lang->polyglossia())
1661                                                : from_ascii(lang->babel());
1662         docstring const langenc = from_ascii(lang->encoding()->iconvName());
1663         docstring const texenc = from_ascii(lang->encoding()->latexName());
1664         docstring const bufenc = from_ascii(enc.iconvName());
1665         docstring const s1 = docstring(1, 0xF0000);
1666         docstring const s2 = docstring(1, 0xF0001);
1667         docstring const translated = encodable ? name
1668                 : from_ascii("\\inputencoding{") + texenc + from_ascii("}")
1669                         + s1 + langenc + s2 + name + s1 + bufenc + s2;
1670
1671         odocstringstream os;
1672         os << "\\addto\\captions" << language
1673            << "{\\renewcommand{\\" << type << "name}{" << translated << "}}\n";
1674         return os.str();
1675 }
1676
1677
1678 docstring const i18npreamble(docstring const & templ, Language const * lang,
1679                              Encoding const & enc, bool const polyglossia,
1680                              bool const need_fixedwidth)
1681 {
1682         if (templ.empty())
1683                 return templ;
1684
1685         string preamble = polyglossia ?
1686                 subst(to_utf8(templ), "$$lang", lang->polyglossia()) :
1687                 subst(to_utf8(templ), "$$lang", lang->babel());
1688
1689         string const langenc = lang->encoding()->iconvName();
1690         string const texenc = lang->encoding()->latexName();
1691         string const bufenc = enc.iconvName();
1692         Encoding const * testenc(&enc);
1693         bool lang_fallback = false;
1694         bool ascii_fallback = false;
1695         if (need_fixedwidth && !enc.hasFixedWidth()) {
1696                 if (lang->encoding()->hasFixedWidth()) {
1697                         testenc = lang->encoding();
1698                         lang_fallback = true;
1699                 } else {
1700                         // We need a fixed width encoding, but both the buffer
1701                         // encoding and the language encoding are variable
1702                         // width. As a last fallback, try to convert to pure
1703                         // ASCII using the LaTeX commands defined in unicodesymbols.
1704                         testenc = encodings.fromLyXName("ascii");
1705                         if (!testenc)
1706                                 return docstring();
1707                         ascii_fallback = true;
1708                 }
1709         }
1710         // First and second character of plane 15 (Private Use Area)
1711         string const s1 = "\xf3\xb0\x80\x80"; // U+F0000
1712         string const s2 = "\xf3\xb0\x80\x81"; // U+F0001
1713         // FIXME UNICODE
1714         // lyx::regex is not unicode-safe.
1715         // Should use QRegExp or (boost::u32regex, but that requires ICU)
1716         static regex const reg("_\\(([^\\)]+)\\)");
1717         smatch sub;
1718         while (regex_search(preamble, sub, reg)) {
1719                 string const key = sub.str(1);
1720                 docstring const name = lang->translateLayout(key);
1721                 // Check whether name can be encoded in the buffer encoding
1722                 bool encodable = true;
1723                 for (size_t i = 0; i < name.size() && encodable; ++i)
1724                         if (!testenc->encodable(name[i]))
1725                                 encodable = false;
1726                 string translated;
1727                 if (encodable && !lang_fallback)
1728                         translated = to_utf8(name);
1729                 else if (ascii_fallback)
1730                         translated = to_ascii(testenc->latexString(name).first);
1731                 else
1732                         translated = "\\inputencoding{" + texenc + "}"
1733                                 + s1 + langenc + s2 + to_utf8(name)
1734                                 + s1 + bufenc + s2;
1735                 preamble = subst(preamble, sub.str(), translated);
1736         }
1737         return from_utf8(preamble);
1738 }
1739
1740 }
1741
1742
1743 docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel, bool use_polyglossia) const
1744 {
1745         DocumentClass const & tclass = params_.documentClass();
1746         // collect preamble snippets in a set to prevent multiple identical
1747         // commands (would happen if e.g. both theorem and theorem* are used)
1748         set<docstring> snippets;
1749         typedef LanguageList::const_iterator lang_it;
1750         lang_it const lbeg = UsedLanguages_.begin();
1751         lang_it const lend =  UsedLanguages_.end();
1752         list<docstring>::const_iterator cit = usedLayouts_.begin();
1753         list<docstring>::const_iterator end = usedLayouts_.end();
1754         for (; cit != end; ++cit) {
1755                 // language dependent commands (once per document)
1756                 snippets.insert(i18npreamble(tclass[*cit].langpreamble(),
1757                                                 buffer().language(),
1758                                                 buffer().params().encoding(),
1759                                                 use_polyglossia, false));
1760                 // commands for language changing (for multilanguage documents)
1761                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1762                         snippets.insert(i18npreamble(
1763                                                 tclass[*cit].babelpreamble(),
1764                                                 buffer().language(),
1765                                                 buffer().params().encoding(),
1766                                                 use_polyglossia, false));
1767                         for (lang_it lit = lbeg; lit != lend; ++lit)
1768                                 snippets.insert(i18npreamble(
1769                                                 tclass[*cit].babelpreamble(),
1770                                                 *lit,
1771                                                 buffer().params().encoding(),
1772                                                 use_polyglossia, false));
1773                 }
1774         }
1775         if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1776                 FloatList const & floats = params_.documentClass().floats();
1777                 UsedFloats::const_iterator fit = usedFloats_.begin();
1778                 UsedFloats::const_iterator fend = usedFloats_.end();
1779                 for (; fit != fend; ++fit) {
1780                         Floating const & fl = floats.getType(fit->first);
1781                         // we assume builtin floats are translated
1782                         if (fl.isPredefined())
1783                                 continue;
1784                         docstring const type = from_ascii(fl.floattype());
1785                         docstring const flname = from_utf8(fl.name());
1786                         docstring name = buffer().language()->translateLayout(fl.name());
1787                         // only request translation if we have a real translation
1788                         // (that differs from the source)
1789                         if (flname != name)
1790                                 snippets.insert(getFloatI18nPreamble(
1791                                                 type, name, buffer().language(),
1792                                                 buffer().params().encoding(),
1793                                                 use_polyglossia));
1794                         for (lang_it lit = lbeg; lit != lend; ++lit) {
1795                                 string const code = (*lit)->code();
1796                                 name = (*lit)->translateLayout(fl.name());
1797                                 // we assume we have a suitable translation if
1798                                 // either the language is English (we need to
1799                                 // translate into English if English is a secondary
1800                                 // language) or if translateIfPossible returns
1801                                 // something different to the English source.
1802                                 bool const have_translation =
1803                                         (flname != name || contains(code, "en"));
1804                                 if (have_translation)
1805                                         snippets.insert(getFloatI18nPreamble(
1806                                                 type, name, *lit,
1807                                                 buffer().params().encoding(),
1808                                                 use_polyglossia));
1809                         }
1810                 }
1811         }
1812
1813         cit = usedInsetLayouts_.begin();
1814         end = usedInsetLayouts_.end();
1815         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1816         for (; cit != end; ++cit) {
1817                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1818                 if (it == ils.end())
1819                         continue;
1820                 // The listings package does not work with variable width
1821                 // encodings, only with fixed width encodings. Therefore we
1822                 // need to force a fixed width encoding for
1823                 // \lstlistlistingname and \lstlistingname (bug 9382).
1824                 // This needs to be consistent with InsetListings::latex().
1825                 bool const need_fixedwidth = !runparams_.isFullUnicode() &&
1826                                 it->second.fixedwidthpreambleencoding();
1827                 // language dependent commands (once per document)
1828                 snippets.insert(i18npreamble(it->second.langpreamble(),
1829                                                 buffer().language(),
1830                                                 buffer().params().encoding(),
1831                                                 use_polyglossia, need_fixedwidth));
1832                 // commands for language changing (for multilanguage documents)
1833                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1834                         snippets.insert(i18npreamble(
1835                                                 it->second.babelpreamble(),
1836                                                 buffer().language(),
1837                                                 buffer().params().encoding(),
1838                                                 use_polyglossia, need_fixedwidth));
1839                         for (lang_it lit = lbeg; lit != lend; ++lit)
1840                                 snippets.insert(i18npreamble(
1841                                                 it->second.babelpreamble(),
1842                                                 *lit,
1843                                                 buffer().params().encoding(),
1844                                                 use_polyglossia, need_fixedwidth));
1845                 }
1846         }
1847
1848         odocstringstream tcpreamble;
1849         set<docstring>::const_iterator const send = snippets.end();
1850         set<docstring>::const_iterator it = snippets.begin();
1851         for (; it != send; ++it)
1852                 tcpreamble << *it;
1853         return tcpreamble.str();
1854 }
1855
1856
1857 docstring const LaTeXFeatures::getLyXSGMLEntities() const
1858 {
1859         // Definition of entities used in the document that are LyX related.
1860         odocstringstream entities;
1861
1862         if (mustProvide("lyxarrow")) {
1863                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
1864         }
1865
1866         return entities.str();
1867 }
1868
1869
1870 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
1871 {
1872         odocstringstream sgmlpreamble;
1873         // FIXME UNICODE
1874         docstring const basename(from_utf8(onlyPath(fname)));
1875
1876         FileMap::const_iterator end = IncludedFiles_.end();
1877         for (FileMap::const_iterator fi = IncludedFiles_.begin();
1878              fi != end; ++fi)
1879                 // FIXME UNICODE
1880                 sgmlpreamble << "\n<!ENTITY " << fi->first
1881                              << (isSGMLFileName(fi->second) ? " SYSTEM \"" : " \"")
1882                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
1883
1884         return sgmlpreamble.str();
1885 }
1886
1887
1888 void LaTeXFeatures::showStruct() const
1889 {
1890         lyxerr << "LyX needs the following commands when LaTeXing:"
1891                << "\n***** Packages:" << getPackages()
1892                << "\n***** Macros:" << to_utf8(getMacros().str)
1893                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
1894                << "\n***** done." << endl;
1895 }
1896
1897
1898 Buffer const & LaTeXFeatures::buffer() const
1899 {
1900         return *buffer_;
1901 }
1902
1903
1904 void LaTeXFeatures::setBuffer(Buffer const & buffer)
1905 {
1906         buffer_ = &buffer;
1907 }
1908
1909
1910 BufferParams const & LaTeXFeatures::bufferParams() const
1911 {
1912         return params_;
1913 }
1914
1915
1916 void LaTeXFeatures::getFloatDefinitions(otexstream & os) const
1917 {
1918         FloatList const & floats = params_.documentClass().floats();
1919
1920         // Here we will output the code to create the needed float styles.
1921         // We will try to do this as minimal as possible.
1922         // \floatstyle{ruled}
1923         // \newfloat{algorithm}{htbp}{loa}
1924         // \providecommand{\algorithmname}{Algorithm}
1925         // \floatname{algorithm}{\protect\algorithmname}
1926         UsedFloats::const_iterator cit = usedFloats_.begin();
1927         UsedFloats::const_iterator end = usedFloats_.end();
1928         for (; cit != end; ++cit) {
1929                 Floating const & fl = floats.getType(cit->first);
1930
1931                 // For builtin floats we do nothing.
1932                 if (fl.isPredefined())
1933                         continue;
1934
1935                 // We have to special case "table" and "figure"
1936                 if (fl.floattype() == "tabular" || fl.floattype() == "figure") {
1937                         // Output code to modify "table" or "figure"
1938                         // but only if builtin == false
1939                         // and that have to be true at this point in the
1940                         // function.
1941                         docstring const type = from_ascii(fl.floattype());
1942                         docstring const placement = from_ascii(fl.placement());
1943                         docstring const style = from_ascii(fl.style());
1944                         if (!style.empty()) {
1945                                 os << "\\floatstyle{" << style << "}\n"
1946                                    << "\\restylefloat{" << type << "}\n";
1947                         }
1948                         if (!placement.empty()) {
1949                                 os << "\\floatplacement{" << type << "}{"
1950                                    << placement << "}\n";
1951                         }
1952                 } else {
1953                         // The other non builtin floats.
1954
1955                         docstring const type = from_ascii(fl.floattype());
1956                         docstring const placement = from_ascii(fl.placement());
1957                         docstring const ext = from_ascii(fl.ext());
1958                         docstring const within = from_ascii(fl.within());
1959                         docstring const style = from_ascii(fl.style());
1960                         docstring const name =
1961                                 buffer().language()->translateLayout(fl.name());
1962                         os << "\\floatstyle{" << style << "}\n"
1963                            << "\\newfloat{" << type << "}{" << placement
1964                            << "}{" << ext << '}';
1965                         if (!within.empty())
1966                                 os << '[' << within << ']';
1967                         os << '\n'
1968                            << "\\providecommand{\\" << type << "name}{"
1969                            << name << "}\n"
1970                            << "\\floatname{" << type << "}{\\protect\\"
1971                            << type << "name}\n";
1972
1973                         // What missing here is to code to minimalize the code
1974                         // output so that the same floatstyle will not be
1975                         // used several times, when the same style is still in
1976                         // effect. (Lgb)
1977                 }
1978                 if (cit->second)
1979                         // The subfig package is loaded later
1980                         os << "\n\\AtBeginDocument{\\newsubfloat{" << from_ascii(fl.floattype()) << "}}\n";
1981         }
1982 }
1983
1984
1985 void LaTeXFeatures::resolveAlternatives()
1986 {
1987         for (Features::iterator it = features_.begin(); it != features_.end();) {
1988                 if (contains(*it, '|')) {
1989                         vector<string> const alternatives = getVectorFromString(*it, "|");
1990                         vector<string>::const_iterator const end = alternatives.end();
1991                         vector<string>::const_iterator ita = alternatives.begin();
1992                         // Is any alternative already required? => use that
1993                         for (; ita != end; ++ita) {
1994                                 if (isRequired(*ita))
1995                                         break;
1996                         }
1997                         // Is any alternative available? => use the first one
1998                         // (bug 9498)
1999                         if (ita == end) {
2000                                 for (ita = alternatives.begin(); ita != end; ++ita) {
2001                                         if (isAvailable(*ita)) {
2002                                                 require(*ita);
2003                                                 break;
2004                                         }
2005                                 }
2006                         }
2007                         // This will not work, but not requiring something
2008                         // would be more confusing
2009                         if (ita == end)
2010                                 require(alternatives.front());
2011                         features_.erase(it);
2012                         it = features_.begin();
2013                 } else
2014                         ++it;
2015         }
2016 }
2017
2018
2019 void LaTeXFeatures::expandMultiples()
2020 {
2021         for (Features::iterator it = features_.begin(); it != features_.end();) {
2022                 if (contains(*it, ',')) {
2023                         vector<string> const multiples = getVectorFromString(*it, ",");
2024                         vector<string>::const_iterator const end = multiples.end();
2025                         vector<string>::const_iterator itm = multiples.begin();
2026                         // Do nothing if any multiple is already required
2027                         for (; itm != end; ++itm) {
2028                                 if (!isRequired(*itm))
2029                                         require(*itm);
2030                         }
2031                         features_.erase(it);
2032                         it = features_.begin();
2033                 } else
2034                         ++it;
2035         }
2036 }
2037
2038
2039 } // namespace lyx