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