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