]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
Move bind file format tag to LyXAction.cpp, and rename it.
[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 "Layout.h"
28 #include "Lexer.h"
29 #include "LyXRC.h"
30 #include "TextClass.h"
31
32 #include "insets/InsetLayout.h"
33
34 #include "support/debug.h"
35 #include "support/docstream.h"
36 #include "support/FileName.h"
37 #include "support/filetools.h"
38 #include "support/gettext.h"
39 #include "support/lstrings.h"
40
41 #include <algorithm>
42
43
44 using namespace std;
45 using namespace lyx::support;
46
47
48 namespace lyx {
49
50 /////////////////////////////////////////////////////////////////////
51 //
52 // Strings
53 //
54 /////////////////////////////////////////////////////////////////////
55
56 //\NeedsTeXFormat{LaTeX2e}
57 //\ProvidesPackage{lyx}[1996/01/11 LLE v0.2 (LyX LaTeX Extensions)]
58 //\message{LyX LaTeX Extensions (LLE v0.2) of 11-Jan-1996.}
59
60 static docstring const lyx_def = from_ascii(
61         "\\providecommand{\\LyX}{L\\kern-.1667em\\lower.25em\\hbox{Y}\\kern-.125emX\\@}");
62
63 static docstring const lyx_hyperref_def = from_ascii(
64         "\\providecommand{\\LyX}{\\texorpdfstring%\n"
65         "  {L\\kern-.1667em\\lower.25em\\hbox{Y}\\kern-.125emX\\@}\n"
66         "  {LyX}}");
67
68 static docstring const noun_def = from_ascii(
69         "\\newcommand{\\noun}[1]{\\textsc{#1}}");
70
71 static docstring const lyxarrow_def = from_ascii(
72         "\\DeclareRobustCommand*{\\lyxarrow}{%\n"
73         "\\@ifstar\n"
74         "{\\leavevmode\\,$\\triangleleft$\\,\\allowbreak}\n"
75         "{\\leavevmode\\,$\\triangleright$\\,\\allowbreak}}");
76
77 // for quotes without babel. This does not give perfect results, but
78 // anybody serious about non-english quotes should use babel (JMarc).
79
80 static docstring const quotedblbase_def = from_ascii(
81         "\\ProvideTextCommandDefault{\\quotedblbase}{%\n"
82         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquotedblright}%\n"
83         "  \\penalty10000\\hskip0em\\relax%\n"
84         "}");
85
86 static docstring const quotesinglbase_def = from_ascii(
87         "\\ProvideTextCommandDefault{\\quotesinglbase}{%\n"
88         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquoteright}%\n"
89         "  \\penalty10000\\hskip0em\\relax%\n"
90         "}");
91
92 static docstring const guillemotleft_def = from_ascii(
93         "\\ProvideTextCommandDefault{\\guillemotleft}{%\n"
94         "  {\\usefont{U}{lasy}{m}{n}\\char'50\\kern-.15em\\char'50}%\n"
95         "\\penalty10000\\hskip0pt\\relax%\n"
96         "}");
97
98 static docstring const guillemotright_def = from_ascii(
99         "\\ProvideTextCommandDefault{\\guillemotright}{%\n"
100         "  \\penalty10000\\hskip0pt%\n"
101         "  {\\usefont{U}{lasy}{m}{n}\\char'51\\kern-.15em\\char'51}%\n"
102         "}");
103
104 static docstring const guilsinglleft_def = from_ascii(
105         "\\ProvideTextCommandDefault{\\guilsinglleft}{%\n"
106         "  {\\usefont{U}{lasy}{m}{n}\\char'50}%\n"
107         "  \\penalty10000\\hskip0pt\\relax%\n"
108         "}");
109
110 static docstring const guilsinglright_def = from_ascii(
111         "\\ProvideTextCommandDefault{\\guilsinglright}{%\n"
112         "  \\penalty10000\\hskip0pt%\n"
113         "  {\\usefont{U}{lasy}{m}{n}\\char'51}%\n"
114         "}");
115
116 static docstring const paragraphleftindent_def = from_ascii(
117         "\\newenvironment{LyXParagraphLeftIndent}[1]%\n"
118         "{\n"
119         "  \\begin{list}{}{%\n"
120         "    \\setlength{\\topsep}{0pt}%\n"
121         "    \\addtolength{\\leftmargin}{#1}\n"
122 // ho hum, yet more things commented out with no hint as to why they
123 // weren't just removed
124 //      "%%    \\addtolength{\\leftmargin}{#1\\textwidth}\n"
125 //      "%%    \\setlength{\\textwidth}{#2\\textwidth}\n"
126 //      "%%    \\setlength\\listparindent\\parindent%\n"
127 //      "%%    \\setlength\\itemindent\\parindent%\n"
128         "    \\setlength{\\parsep}{0pt plus 1pt}%\n"
129         "  }\n"
130         "  \\item[]\n"
131         "}\n"
132         "{\\end{list}}\n");
133
134 static docstring const floatingfootnote_def = from_ascii(
135         "%% Special footnote code from the package 'stblftnt.sty'\n"
136         "%% Author: Robin Fairbairns -- Last revised Dec 13 1996\n"
137         "\\let\\SF@@footnote\\footnote\n"
138         "\\def\\footnote{\\ifx\\protect\\@typeset@protect\n"
139         "    \\expandafter\\SF@@footnote\n"
140         "  \\else\n"
141         "    \\expandafter\\SF@gobble@opt\n"
142         "  \\fi\n"
143         "}\n"
144         "\\expandafter\\def\\csname SF@gobble@opt \\endcsname{\\@ifnextchar[%]\n"
145         "  \\SF@gobble@twobracket\n"
146         "  \\@gobble\n"
147         "}\n"
148         "\\edef\\SF@gobble@opt{\\noexpand\\protect\n"
149         "  \\expandafter\\noexpand\\csname SF@gobble@opt \\endcsname}\n"
150         "\\def\\SF@gobble@twobracket[#1]#2{}\n");
151
152 static docstring const binom_def = from_ascii(
153         "%% Binom macro for standard LaTeX users\n"
154         "\\newcommand{\\binom}[2]{{#1 \\choose #2}}\n");
155
156 static docstring const mathcircumflex_def = from_ascii(
157         "%% For printing a cirumflex inside a formula\n"
158         "\\newcommand{\\mathcircumflex}[0]{\\mbox{\\^{}}}\n");
159
160 static docstring const tabularnewline_def = from_ascii(
161         "%% Because html converters don't know tabularnewline\n"
162         "\\providecommand{\\tabularnewline}{\\\\}\n");
163         
164 static docstring const lyxgreyedout_def = from_ascii(
165         "%% The greyedout annotation environment\n"
166         "\\newenvironment{lyxgreyedout}{\\textcolor{note_fontcolor}\\bgroup}{\\egroup}\n");
167
168 // We want to omit the file extension for includegraphics, but this does not
169 // work when the filename contains other dots.
170 // Idea from http://www.tex.ac.uk/cgi-bin/texfaq2html?label=unkgrfextn
171 static docstring const lyxdot_def = from_ascii(
172         "%% A simple dot to overcome graphicx limitations\n"
173         "\\newcommand{\\lyxdot}{.}\n");
174
175 static docstring const changetracking_dvipost_def = from_ascii(
176         "%% Change tracking with dvipost\n"
177         "\\dvipostlayout\n"
178         "\\dvipost{osstart color push Red}\n"
179         "\\dvipost{osend color pop}\n"
180         "\\dvipost{cbstart color push Blue}\n"
181         "\\dvipost{cbend color pop}\n"
182         "\\newcommand{\\lyxadded}[3]{\\changestart#3\\changeend}\n"
183         "\\newcommand{\\lyxdeleted}[3]{%\n"
184         "\\changestart\\overstrikeon#3\\overstrikeoff\\changeend}\n");
185
186 static docstring const changetracking_xcolor_ulem_def = from_ascii(
187         "%% Change tracking with ulem\n"
188         "\\newcommand{\\lyxadded}[3]{{\\color{lyxadded}{}#3}}\n"
189         "\\newcommand{\\lyxdeleted}[3]{{\\color{lyxdeleted}\\sout{#3}}}\n");
190
191 static docstring const changetracking_xcolor_ulem_hyperref_def = from_ascii(
192         "%% Change tracking with ulem\n"
193         "\\newcommand{\\lyxadded}[3]{{\\texorpdfstring{\\color{lyxadded}{}}{}#3}}\n"
194         "\\newcommand{\\lyxdeleted}[3]{{\\texorpdfstring{\\color{lyxdeleted}\\sout{#3}}{}}}\n");
195
196 static docstring const changetracking_none_def = from_ascii(
197         "\\newcommand{\\lyxadded}[3]{#3}\n"
198         "\\newcommand{\\lyxdeleted}[3]{}\n");
199
200 static docstring const textgreek_def = from_ascii(
201         "\\DeclareRobustCommand{\\greektext}{%\n"
202         "  \\fontencoding{LGR}\\selectfont\\def\\encodingdefault{LGR}}\n"
203         "\\DeclareRobustCommand{\\textgreek}[1]{\\leavevmode{\\greektext #1}}\n"
204         "\\DeclareFontEncoding{LGR}{}{}\n"
205         "\\DeclareTextSymbol{\\~}{LGR}{126}");
206
207 static docstring const textcyr_def = from_ascii(
208         "\\DeclareRobustCommand{\\cyrtext}{%\n"
209         "  \\fontencoding{T2A}\\selectfont\\def\\encodingdefault{T2A}}\n"
210         "\\DeclareRobustCommand{\\textcyr}[1]{\\leavevmode{\\cyrtext #1}}\n"
211         "\\AtBeginDocument{\\DeclareFontEncoding{T2A}{}{}}\n");
212
213 static docstring const lyxmathsym_def = from_ascii(
214         "\\newcommand{\\lyxmathsym}[1]{\\ifmmode\\begingroup\\def\\b@ld{bold}\n"
215         "  \\text{\\ifx\\math@version\\b@ld\\bfseries\\fi#1}\\endgroup\\else#1\\fi}\n");
216
217 static docstring const papersizedvi_def = from_ascii(
218         "\\special{papersize=\\the\\paperwidth,\\the\\paperheight}\n");
219
220 static docstring const papersizepdf_def = from_ascii(
221         "\\pdfpageheight\\paperheight\n"
222         "\\pdfpagewidth\\paperwidth\n");
223
224 static docstring const cedilla_def = from_ascii(
225         "\\newcommand{\\docedilla}[2]{\\underaccent{#1\\mathchar'30}{#2}}\n"
226         "\\newcommand{\\cedilla}[1]{\\mathpalette\\docedilla{#1}}\n");
227
228 static docstring const subring_def = from_ascii(
229         "\\newcommand{\\dosubring}[2]{\\underaccent{#1\\mathchar'27}{#2}}\n"
230         "\\newcommand{\\subring}[1]{\\mathpalette\\dosubring{#1}}\n");
231
232 static docstring const subdot_def = from_ascii(
233         "\\newcommand{\\dosubdot}[2]{\\underaccent{#1.}{#2}}\n"
234         "\\newcommand{\\subdot}[1]{\\mathpalette\\dosubdot{#1}}\n");
235
236 static docstring const subhat_def = from_ascii(
237         "\\newcommand{\\dosubhat}[2]{\\underaccent{#1\\mathchar'136}{#2}}\n"
238         "\\newcommand{\\subhat}[1]{\\mathpalette\\dosubhat{#1}}\n");
239
240 static docstring const subtilde_def = from_ascii(
241         "\\newcommand{\\dosubtilde}[2]{\\underaccent{#1\\mathchar'176}{#2}}\n"
242         "\\newcommand{\\subtilde}[1]{\\mathpalette\\dosubtilde{#1}}\n");
243
244 static docstring const dacute_def = from_ascii(
245         "\\DeclareMathAccent{\\dacute}{\\mathalpha}{operators}{'175}\n");
246
247 static docstring const tipasymb_def = from_ascii(
248         "\\DeclareFontEncoding{T3}{}{}\n"
249         "\\DeclareSymbolFont{tipasymb}{T3}{cmr}{m}{n}\n");
250
251 static docstring const dgrave_def = from_ascii(
252         "\\DeclareMathAccent{\\dgrave}{\\mathord}{tipasymb}{'15}\n");
253
254 static docstring const rcap_def = from_ascii(
255         "\\DeclareMathAccent{\\rcap}{\\mathord}{tipasymb}{'20}\n");
256
257 static docstring const ogonek_def = from_ascii(
258         "\\newcommand{\\doogonek}[2]{\\setbox0=\\hbox{$#1#2$}\\underaccent{#1\\mkern-6mu\n"
259         "  \\ifx#2O\\hskip0.5\\wd0\\else\\ifx#2U\\hskip0.5\\wd0\\else\\hskip\\wd0\\fi\\fi\n"
260         "  \\ifx#2o\\mkern-2mu\\else\\ifx#2e\\mkern-1mu\\fi\\fi\n"
261         "  \\mathchar\"0\\hexnumber@\\symtipasymb0C}{#2}}\n"
262         "\\newcommand{\\ogonek}[1]{\\mathpalette\\doogonek{#1}}\n");
263
264 static docstring const lyxref_def = from_ascii(
265                 "\\RS@ifundefined{subref}\n"
266                 "  {\\def\\RSsubtxt{section~}\\newref{sub}{name = \\RSsubtxt}}\n" 
267                 "  {}\n"
268                 "\\RS@ifundefined{thmref}\n"
269                 "  {\\def\\RSthmtxt{theorem~}\\newref{thm}{name = \\RSthmtxt}}\n" 
270                 "  {}\n"
271                 "\\RS@ifundefined{lemref}\n"
272                 "  {\\def\\RSlemtxt{lemma~}\\newref{lem}{name = \\RSlemtxt}}\n" 
273                 "  {}\n");
274
275
276 /////////////////////////////////////////////////////////////////////
277 //
278 // LaTeXFeatures
279 //
280 /////////////////////////////////////////////////////////////////////
281
282 LaTeXFeatures::Packages LaTeXFeatures::packages_;
283
284
285 LaTeXFeatures::LaTeXFeatures(Buffer const & b, BufferParams const & p,
286                              OutputParams const & r)
287         : buffer_(&b), params_(p), runparams_(r), in_float_(false)
288 {}
289
290
291 bool LaTeXFeatures::useBabel() const
292 {
293         if (usePolyglossia())
294                 return false;
295         return (lyxrc.language_package_selection != LyXRC::LP_NONE)
296                 || (bufferParams().language->lang() != lyxrc.default_language
297                     && !bufferParams().language->babel().empty())
298                 || this->hasLanguages();
299 }
300
301
302 bool LaTeXFeatures::usePolyglossia() const
303 {
304         return (lyxrc.language_package_selection == LyXRC::LP_AUTO)
305                 && isRequired("polyglossia")
306                 && isAvailable("polyglossia")
307                 && !params_.documentClass().provides("babel")
308                 && this->hasPolyglossiaLanguages();
309 }
310
311
312 void LaTeXFeatures::require(string const & name)
313 {
314         features_.insert(name);
315 }
316
317
318 void LaTeXFeatures::require(set<string> const & names)
319 {
320         features_.insert(names.begin(), names.end());
321 }
322
323
324 void LaTeXFeatures::getAvailable()
325 {
326         Lexer lex;
327         support::FileName const real_file = libFileSearch("", "packages.lst");
328
329         if (real_file.empty())
330                 return;
331
332         lex.setFile(real_file);
333
334         if (!lex.isOK())
335                 return;
336
337         // Make sure that we are clean
338         packages_.clear();
339
340         bool finished = false;
341         // Parse config-file
342         while (lex.isOK() && !finished) {
343                 switch (lex.lex()) {
344                 case Lexer::LEX_FEOF:
345                         finished = true;
346                         break;
347                 default:
348                         packages_.insert(lex.getString());
349                 }
350         }
351 }
352
353
354 void LaTeXFeatures::useLayout(docstring const & layoutname)
355 {
356         // Some code to avoid loops in dependency definition
357         static int level = 0;
358         const int maxlevel = 30;
359         if (level > maxlevel) {
360                 lyxerr << "LaTeXFeatures::useLayout: maximum level of "
361                        << "recursion attained by layout "
362                        << to_utf8(layoutname) << endl;
363                 return;
364         }
365
366         DocumentClass const & tclass = params_.documentClass();
367         if (tclass.hasLayout(layoutname)) {
368                 // Is this layout already in usedLayouts?
369                 if (find(usedLayouts_.begin(), usedLayouts_.end(), layoutname) 
370                     != usedLayouts_.end())
371                         return;
372
373                 Layout const & layout = tclass[layoutname];
374                 require(layout.requires());
375
376                 if (!layout.depends_on().empty()) {
377                         ++level;
378                         useLayout(layout.depends_on());
379                         --level;
380                 }
381                 usedLayouts_.push_back(layoutname);
382         } else {
383                 lyxerr << "LaTeXFeatures::useLayout: layout `"
384                        << to_utf8(layoutname) << "' does not exist in this class"
385                        << endl;
386         }
387
388         --level;
389 }
390
391
392 void LaTeXFeatures::useInsetLayout(InsetLayout const & lay)
393 {
394         docstring const & lname = lay.name();
395         DocumentClass const & tclass = params_.documentClass();
396
397         // this is a default inset layout, nothing useful here
398         if (!tclass.hasInsetLayout(lname))
399                 return;
400         // Is this layout already in usedInsetLayouts?
401         if (find(usedInsetLayouts_.begin(), usedInsetLayouts_.end(), lname) 
402                         != usedInsetLayouts_.end())
403                 return;
404
405         require(lay.requires());
406         usedInsetLayouts_.push_back(lname);
407 }
408
409
410 bool LaTeXFeatures::isRequired(string const & name) const
411 {
412         return features_.find(name) != features_.end();
413 }
414
415
416 bool LaTeXFeatures::mustProvide(string const & name) const
417 {
418         return isRequired(name) && !params_.documentClass().provides(name);
419 }
420
421
422 bool LaTeXFeatures::isAvailable(string const & name)
423 {
424         string::size_type const i = name.find("->");
425         if (i != string::npos) {
426                 string const from = name.substr(0,i);
427                 string const to = name.substr(i+2);
428                 //LYXERR0("from=[" << from << "] to=[" << to << "]");
429                 return theConverters().isReachable(from, to);
430         }
431
432         if (packages_.empty())
433                 getAvailable();
434         string n = name;
435         if (suffixIs(n, ".sty"))
436                 n.erase(name.length() - 4);
437         return packages_.find(n) != packages_.end();
438 }
439
440
441 void LaTeXFeatures::addPreambleSnippet(string const & preamble)
442 {
443         SnippetList::const_iterator begin = preamble_snippets_.begin();
444         SnippetList::const_iterator end   = preamble_snippets_.end();
445         if (find(begin, end, preamble) == end)
446                 preamble_snippets_.push_back(preamble);
447 }
448
449
450 void LaTeXFeatures::useFloat(string const & name, bool subfloat)
451 {
452         if (!usedFloats_[name])
453                 usedFloats_[name] = subfloat;
454         if (subfloat)
455                 require("subfig");
456         // We only need float.sty if we use non builtin floats, or if we
457         // use the "H" modifier. This includes modified table and
458         // figure floats. (Lgb)
459         Floating const & fl = params_.documentClass().floats().getType(name);
460         if (!fl.floattype().empty() && fl.needsFloatPkg()) {
461                 require("float");
462         }
463 }
464
465
466 void LaTeXFeatures::useLanguage(Language const * lang)
467 {
468         if (!lang->babel().empty())
469                 UsedLanguages_.insert(lang);
470         if (lang->lang() == "vietnamese")
471                 require("vietnamese");
472         // CJK languages do not have a babel name.
473         // They use the CJK package
474         if (lang->encoding()->package() == Encoding::CJK)
475                 require("CJK");
476         // japanese package is special
477         if (lang->encoding()->package() == Encoding::japanese)
478                 require("japanese");
479 }
480
481
482 void LaTeXFeatures::includeFile(docstring const & key, string const & name)
483 {
484         IncludedFiles_[key] = name;
485 }
486
487
488 bool LaTeXFeatures::hasLanguages() const
489 {
490         return !UsedLanguages_.empty();
491 }
492
493
494 bool LaTeXFeatures::hasPolyglossiaLanguages() const
495 {
496         LanguageList::const_iterator const begin = UsedLanguages_.begin();
497         for (LanguageList::const_iterator cit = begin;
498              cit != UsedLanguages_.end();
499              ++cit) {
500                 if ((*cit)->polyglossia().empty())
501                         return false;
502         }
503         return true;
504 }
505
506
507 string LaTeXFeatures::getLanguages() const
508 {
509         ostringstream languages;
510
511         LanguageList::const_iterator const begin = UsedLanguages_.begin();
512         for (LanguageList::const_iterator cit = begin;
513              cit != UsedLanguages_.end();
514              ++cit) {
515                 if (cit != begin)
516                         languages << ',';
517                 languages << (*cit)->babel();
518         }
519         return languages.str();
520 }
521
522
523 std::map<std::string, std::string> LaTeXFeatures::getPolyglossiaLanguages() const
524 {
525         std::map<std::string, std::string> languages;
526
527         LanguageList::const_iterator const begin = UsedLanguages_.begin();
528         for (LanguageList::const_iterator cit = begin;
529              cit != UsedLanguages_.end();
530              ++cit) {
531                 languages[(*cit)->polyglossia()] = (*cit)->polyglossiaOpts();
532         }
533         return languages;
534 }
535
536
537 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
538 {
539         // This does only find encodings of languages supported by babel, but
540         // that does not matter since we don't have a language with an
541         // encoding supported by inputenc but without babel support.
542         set<string> encodings;
543         LanguageList::const_iterator it  = UsedLanguages_.begin();
544         LanguageList::const_iterator end = UsedLanguages_.end();
545         for (; it != end; ++it)
546                 if ((*it)->encoding()->latexName() != doc_encoding &&
547                     ((*it)->encoding()->package() == Encoding::inputenc
548                      || (*it)->encoding()->package() == Encoding::japanese))
549                         encodings.insert((*it)->encoding()->latexName());
550         return encodings;
551 }
552
553 namespace {
554
555 char const * simplefeatures[] = {
556 // note that the package order here will be the same in the LaTeX-output
557         "array",
558         "verbatim",
559         "longtable",
560         "rotating",
561         "latexsym",
562         "pifont",
563         // subfig is handled in BufferParams.cpp
564         "varioref",
565         "prettyref",
566         "refstyle",
567         /*For a successful cooperation of the `wrapfig' package with the
568           `float' package you should load the `wrapfig' package *after*
569           the `float' package. See the caption package documentation
570           for explanation.*/
571         "float",
572         "rotfloat",
573         "wrapfig",
574         "booktabs",
575         "dvipost",
576         "fancybox",
577         "calc",
578         "units",
579         "tipa",
580         "tipx",
581         "framed",
582         "soul",
583         "textcomp",
584         "pmboxdraw",
585         "bbding",
586         "ifsym",
587         "marvosym",
588         "txfonts",
589         "mathrsfs",
590         "ascii",
591         "url",
592         "covington",
593         "csquotes",
594         "enumitem",
595         "endnotes",
596         "hhline",
597         "ifthen",
598         // listings is handled in BufferParams.cpp
599         "bm",
600         "pdfpages",
601         "amscd",
602         "slashed",
603         "multirow",
604         "tfrupee"
605 };
606
607 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
608
609 }
610
611
612 string const LaTeXFeatures::getColorOptions() const
613 {
614         ostringstream colors;
615
616         // Handling the color packages separately is needed to be able to load them
617         // before babel when hyperref is loaded with the colorlinks option
618         // for more info see Bufferparams.cpp
619
620         // [x]color.sty
621         if (mustProvide("color") || mustProvide("xcolor")) {
622                 string const package =
623                         (mustProvide("xcolor") ? "xcolor" : "color");
624                 if (params_.graphics_driver == "default"
625                         || params_.graphics_driver == "none")
626                         colors << "\\usepackage{" << package << "}\n";
627                 else
628                         colors << "\\usepackage["
629                                  << params_.graphics_driver
630                                  << "]{" << package << "}\n";
631         }
632
633         // pdfcolmk must be loaded after color
634         if (mustProvide("pdfcolmk"))
635                 colors << "\\usepackage{pdfcolmk}\n";
636
637         // the following 3 color commands must be set after color
638         // is loaded and before pdfpages, therefore add the command
639         // here define the set color
640         if (mustProvide("pagecolor")) {
641                 colors << "\\definecolor{page_backgroundcolor}{rgb}{";
642                 colors << outputLaTeXColor(params_.backgroundcolor) << "}\n";
643                 // set the page color
644                 colors << "\\pagecolor{page_backgroundcolor}\n";
645         }
646
647         if (mustProvide("fontcolor")) {
648                 colors << "\\definecolor{document_fontcolor}{rgb}{";
649                 colors << outputLaTeXColor(params_.fontcolor) << "}\n";
650                 // set the color
651                 colors << "\\color{document_fontcolor}\n";
652         }
653
654         if (mustProvide("lyxgreyedout")) {
655                 colors << "\\definecolor{note_fontcolor}{rgb}{";
656                 colors << outputLaTeXColor(params_.notefontcolor) << "}\n";
657                 // the color will be set together with the definition of
658                 // the lyxgreyedout environment (see lyxgreyedout_def)
659         }
660
661         // color for shaded boxes
662         if (isRequired("framed") && mustProvide("color")) {
663                 colors << "\\definecolor{shadecolor}{rgb}{";
664                 colors << outputLaTeXColor(params_.boxbgcolor) << "}\n";
665                 // this color is automatically used by the LaTeX-package "framed"
666         }
667
668         return colors.str();
669 }
670
671
672 string const LaTeXFeatures::getPackages() const
673 {
674         ostringstream packages;
675         DocumentClass const & tclass = params_.documentClass();
676
677         // FIXME: currently, we can only load packages and macros known
678         // to LyX.
679         // However, with the Require tag of layouts/custom insets,
680         // also unknown packages can be requested. They are silently
681         // swallowed now. We should change this eventually.
682
683         //
684         //  These are all the 'simple' includes.  i.e
685         //  packages which we just \usepackage{package}
686         //
687         for (int i = 0; i < nb_simplefeatures; ++i) {
688                 if (mustProvide(simplefeatures[i]))
689                         packages << "\\usepackage{"
690                                  << simplefeatures[i] << "}\n";
691         }
692
693         //
694         // The rest of these packages are somewhat more complicated
695         // than those above.
696         //
697
698         // if fontspec is used, AMS packages have to be loaded before
699         // fontspec (in BufferParams)
700         if (!params_.useNonTeXFonts && !loadAMSPackages().empty())
701                 packages << loadAMSPackages();
702
703         // fixltx2e must be loaded after amsthm, since amsthm produces an error with
704         // the redefined \[ command (bug 7233). Load is as early as possible, since
705         // other packages might profit from it.
706         if (mustProvide("fixltx2e"))
707                 packages << "\\usepackage{fixltx2e}\n";
708
709         // wasysym is a simple feature, but it must be after amsmath if both
710         // are used
711         // wasysym redefines some integrals (e.g. iint) from amsmath. That
712         // leads to inconsistent integrals. We only load this package if
713         // the document does not contain integrals (then isRequired("esint")
714         // is false) or if esint is used, since esint redefines all relevant
715         // integral symbols from wasysym and amsmath.
716         // See http://www.lyx.org/trac/ticket/1942
717         if (mustProvide("wasysym") &&
718             (params_.use_esint != BufferParams::package_off || !isRequired("esint")))
719                 packages << "\\usepackage{wasysym}\n";
720
721         // accents must be loaded after amsmath
722         if (mustProvide("accents"))
723                 packages << "\\usepackage{accents}\n";
724
725         // mathdots must be loaded after amsmath
726         if (mustProvide("mathdots") &&
727                 params_.use_mathdots != BufferParams::package_off)
728                 packages << "\\usepackage{mathdots}\n";
729
730         // yhmath must be loaded after amsmath
731         if (mustProvide("yhmath"))
732                 packages << "\\usepackage{yhmath}\n";
733
734         // [x]color and pdfcolmk are handled in getColorOptions() above
735         
736         // makeidx.sty
737         if (isRequired("makeidx") || isRequired("splitidx")) {
738                 if (!tclass.provides("makeidx") && !isRequired("splitidx"))
739                         packages << "\\usepackage{makeidx}\n";
740                 if (!tclass.provides("splitidx") && isRequired("splitidx"))
741                         packages << "\\usepackage{splitidx}\n";
742                 packages << "\\makeindex\n";
743         }
744
745         // graphicx.sty
746         if (mustProvide("graphicx") && params_.graphics_driver != "none") {
747                 if (params_.graphics_driver == "default")
748                         packages << "\\usepackage{graphicx}\n";
749                 else
750                         packages << "\\usepackage["
751                                  << params_.graphics_driver
752                                  << "]{graphicx}\n";
753         }
754         
755         // lyxskak.sty --- newer chess support based on skak.sty
756         if (mustProvide("chess"))
757                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
758
759         // setspace.sty
760         if (mustProvide("setspace") && !tclass.provides("SetSpace"))
761                 packages << "\\usepackage{setspace}\n";
762
763         // esint must be after amsmath and wasysym, since it will redeclare
764         // inconsistent integral symbols
765         if ((mustProvide("esint") || mustProvide("esintoramsmath")) &&
766             params_.use_esint != BufferParams::package_off)
767                 packages << "\\usepackage{esint}\n";
768
769         // natbib.sty
770         // Some classes load natbib themselves, but still allow (or even require)
771         // plain numeric citations (ReVTeX is such a case, see bug 5182).
772         // This special case is indicated by the "natbib-internal" key.
773         if (mustProvide("natbib") && !tclass.provides("natbib-internal")) {
774                 packages << "\\usepackage[";
775                 if (params_.citeEngine() == ENGINE_NATBIB_NUMERICAL)
776                         packages << "numbers";
777                 else
778                         packages << "authoryear";
779                 packages << "]{natbib}\n";
780         }
781
782         // jurabib -- we need version 0.6 at least.
783         if (mustProvide("jurabib"))
784                 packages << "\\usepackage{jurabib}[2004/01/25]\n";
785         
786         // xargs -- we need version 1.09 at least
787         if (mustProvide("xargs"))
788                 packages << "\\usepackage{xargs}[2008/03/08]\n";
789
790         // bibtopic -- the dot provides the aux file naming which
791         // LyX can detect.
792         if (mustProvide("bibtopic"))
793                 packages << "\\usepackage[dot]{bibtopic}\n";
794
795         if (mustProvide("xy"))
796                 packages << "\\usepackage[all]{xy}\n";
797
798         if (mustProvide("feyn"))
799                 packages << "\\usepackage{feyn}\n"; //Diagram
800
801         if (mustProvide("ulem"))
802                 packages << "\\PassOptionsToPackage{normalem}{ulem}\n"
803                             "\\usepackage{ulem}\n";
804
805         if (params_.use_mhchem == BufferParams::package_on ||
806             (mustProvide("mhchem") &&
807              params_.use_mhchem != BufferParams::package_off))
808                 packages << "\\PassOptionsToPackage{version=3}{mhchem}\n"
809                             "\\usepackage{mhchem}\n";
810
811         if (mustProvide("nomencl")) {
812                 // Make it work with the new and old version of the package,
813                 // but don't use the compatibility option since it is
814                 // incompatible to other packages.
815                 packages << "\\usepackage{nomencl}\n"
816                             "% the following is useful when we have the old nomencl.sty package\n"
817                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
818                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
819                             "\\makenomenclature\n";
820         }
821
822         // fixltx2e provides subscript
823         if (mustProvide("subscript") && !isRequired("fixltx2e"))
824                 packages << "\\usepackage{subscript}\n";
825
826         return packages.str();
827 }
828
829
830 string LaTeXFeatures::getPreambleSnippets() const 
831 {
832         ostringstream snip;
833         SnippetList::const_iterator pit  = preamble_snippets_.begin();
834         SnippetList::const_iterator pend = preamble_snippets_.end();
835         for (; pit != pend; ++pit)
836                 snip << *pit << '\n';
837         return snip.str();
838 }
839
840
841 docstring const LaTeXFeatures::getMacros() const
842 {
843         odocstringstream macros;
844
845         if (!preamble_snippets_.empty()) {
846                 macros << '\n';
847                 macros << from_utf8(getPreambleSnippets());
848         }
849
850         if (mustProvide("papersize")) {
851                 if (runparams_.flavor == OutputParams::LATEX)
852                         macros << papersizedvi_def << '\n';
853                 else
854                         macros << papersizepdf_def << '\n';
855         }
856
857         if (mustProvide("LyX")) {
858                 if (isRequired("hyperref"))
859                         macros << lyx_hyperref_def << '\n';
860                 else
861                         macros << lyx_def << '\n';
862         }
863
864         if (mustProvide("noun"))
865                 macros << noun_def << '\n';
866
867         if (mustProvide("lyxarrow"))
868                 macros << lyxarrow_def << '\n';
869
870         if (!usePolyglossia() && mustProvide("textgreek")) {
871                 // Avoid a LaTeX error if times fonts are used and the grtimes
872                 // package is installed but actual fonts are not (bug 6469).
873                 if (params_.fonts_roman == "times")
874                         macros << subst(textgreek_def,
875                                         from_ascii("\\greektext #1"),
876                                         from_ascii("%\n  \\IfFileExists"
877                                                    "{grtm10.tfm}{}{\\fontfamily"
878                                                    "{cmr}}\\greektext #1"))
879                                << '\n';
880                 else
881                         macros << textgreek_def << '\n';
882         }
883
884         if (!usePolyglossia() && mustProvide("textcyr"))
885                 macros << textcyr_def << '\n';
886
887         if (mustProvide("lyxmathsym"))
888                 macros << lyxmathsym_def << '\n';
889
890         if (mustProvide("cedilla"))
891                 macros << cedilla_def << '\n';
892
893         if (mustProvide("subring"))
894                 macros << subring_def << '\n';
895
896         if (mustProvide("subdot"))
897                 macros << subdot_def << '\n';
898
899         if (mustProvide("subhat"))
900                 macros << subhat_def << '\n';
901
902         if (mustProvide("subtilde"))
903                 macros << subtilde_def << '\n';
904
905         if (mustProvide("dacute"))
906                 macros << dacute_def << '\n';
907
908         if (mustProvide("tipasymb"))
909                 macros << tipasymb_def << '\n';
910
911         if (mustProvide("dgrave"))
912                 macros << dgrave_def << '\n';
913
914         if (mustProvide("rcap"))
915                 macros << rcap_def << '\n';
916
917         if (mustProvide("ogonek"))
918                 macros << ogonek_def << '\n';
919
920         // quotes.
921         if (mustProvide("quotesinglbase"))
922                 macros << quotesinglbase_def << '\n';
923         if (mustProvide("quotedblbase"))
924                 macros << quotedblbase_def << '\n';
925         if (mustProvide("guilsinglleft"))
926                 macros << guilsinglleft_def << '\n';
927         if (mustProvide("guilsinglright"))
928                 macros << guilsinglright_def << '\n';
929         if (mustProvide("guillemotleft"))
930                 macros << guillemotleft_def << '\n';
931         if (mustProvide("guillemotright"))
932                 macros << guillemotright_def << '\n';
933
934         // Math mode
935         if (mustProvide("binom") && !isRequired("amsmath"))
936                 macros << binom_def << '\n';
937         if (mustProvide("mathcircumflex"))
938                 macros << mathcircumflex_def << '\n';
939
940         // other
941         if (mustProvide("ParagraphLeftIndent"))
942                 macros << paragraphleftindent_def;
943         if (mustProvide("NeedLyXFootnoteCode"))
944                 macros << floatingfootnote_def;
945
946         // some problems with tex->html converters
947         if (mustProvide("NeedTabularnewline"))
948                 macros << tabularnewline_def;
949
950         // greyed-out environment (note inset)
951         // the color is specified in the routine
952         // getColorOptions() to avoid LaTeX-package clashes
953         if (mustProvide("lyxgreyedout"))
954                 macros << lyxgreyedout_def;
955
956         if (mustProvide("lyxdot"))
957                 macros << lyxdot_def << '\n';
958
959         // floats
960         getFloatDefinitions(macros);
961         
962         if (mustProvide("refstyle")) 
963                 macros << lyxref_def << '\n';   
964         
965         // change tracking
966         if (mustProvide("ct-dvipost"))
967                 macros << changetracking_dvipost_def;
968         
969         if (mustProvide("ct-xcolor-ulem")) {
970                 streamsize const prec = macros.precision(2);
971         
972                 RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
973                 macros << "\\providecolor{lyxadded}{rgb}{"
974                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
975
976                 RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
977                 macros << "\\providecolor{lyxdeleted}{rgb}{"
978                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
979
980                 macros.precision(prec);
981                 
982                 if (isRequired("hyperref"))
983                         macros << changetracking_xcolor_ulem_hyperref_def;
984                 else
985                         macros << changetracking_xcolor_ulem_def;
986         }
987
988         if (mustProvide("ct-none"))
989                 macros << changetracking_none_def;
990
991         return macros.str();
992 }
993
994
995 string const LaTeXFeatures::getBabelPresettings() const
996 {
997         ostringstream tmp;
998
999         LanguageList::const_iterator it  = UsedLanguages_.begin();
1000         LanguageList::const_iterator end = UsedLanguages_.end();
1001         for (; it != end; ++it)
1002                 if (!(*it)->babel_presettings().empty())
1003                         tmp << (*it)->babel_presettings() << '\n';
1004         if (!params_.language->babel_presettings().empty())
1005                 tmp << params_.language->babel_presettings() << '\n';
1006
1007         return tmp.str();
1008 }
1009
1010
1011 string const LaTeXFeatures::getBabelPostsettings() const
1012 {
1013         ostringstream tmp;
1014
1015         LanguageList::const_iterator it  = UsedLanguages_.begin();
1016         LanguageList::const_iterator end = UsedLanguages_.end();
1017         for (; it != end; ++it)
1018                 if (!(*it)->babel_postsettings().empty())
1019                         tmp << (*it)->babel_postsettings() << '\n';
1020         if (!params_.language->babel_postsettings().empty())
1021                 tmp << params_.language->babel_postsettings() << '\n';
1022
1023         return tmp.str();
1024 }
1025
1026
1027 bool LaTeXFeatures::needBabelLangOptions() const
1028 {
1029         if (!lyxrc.language_global_options || params_.language->asBabelOptions())
1030                 return true;
1031
1032         LanguageList::const_iterator it  = UsedLanguages_.begin();
1033         LanguageList::const_iterator end = UsedLanguages_.end();
1034         for (; it != end; ++it)
1035                 if ((*it)->asBabelOptions())
1036                         return true;
1037
1038         return false;
1039 }
1040
1041
1042 string const LaTeXFeatures::loadAMSPackages() const
1043 {
1044         ostringstream tmp;
1045         if (mustProvide("amsthm"))
1046                 tmp << "\\usepackage{amsthm}\n";
1047
1048         // esint is preferred for esintoramsmath
1049         if ((mustProvide("amsmath")
1050              && params_.use_amsmath != BufferParams::package_off)
1051             || (mustProvide("esintoramsmath")
1052                 && params_.use_esint == BufferParams::package_off
1053                 && params_.use_amsmath != BufferParams::package_off)) {
1054                 tmp << "\\usepackage{amsmath}\n";
1055         } else {
1056                 // amsbsy and amstext are already provided by amsmath
1057                 if (mustProvide("amsbsy"))
1058                         tmp << "\\usepackage{amsbsy}\n";
1059                 if (mustProvide("amstext"))
1060                         tmp << "\\usepackage{amstext}\n";
1061         }
1062         
1063         if (mustProvide("amssymb")
1064             || params_.use_amsmath == BufferParams::package_on)
1065                 tmp << "\\usepackage{amssymb}\n";
1066
1067         return tmp.str();
1068 }
1069
1070
1071 docstring const LaTeXFeatures::getTClassPreamble() const
1072 {
1073         // the text class specific preamble
1074         DocumentClass const & tclass = params_.documentClass();
1075         odocstringstream tcpreamble;
1076
1077         tcpreamble << tclass.preamble();
1078
1079         list<docstring>::const_iterator cit = usedLayouts_.begin();
1080         list<docstring>::const_iterator end = usedLayouts_.end();
1081         for (; cit != end; ++cit)
1082                 tcpreamble << tclass[*cit].preamble();
1083
1084         cit = usedInsetLayouts_.begin();
1085         end = usedInsetLayouts_.end();
1086         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1087         for (; cit != end; ++cit) {
1088                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1089                 if (it == ils.end())
1090                         continue;
1091                 tcpreamble << it->second.preamble();
1092         }
1093
1094         return tcpreamble.str();
1095 }
1096
1097
1098 docstring const LaTeXFeatures::getTClassHTMLPreamble() const 
1099 {
1100         DocumentClass const & tclass = params_.documentClass();
1101         odocstringstream tcpreamble;
1102
1103         tcpreamble << tclass.htmlpreamble();
1104
1105         list<docstring>::const_iterator cit = usedLayouts_.begin();
1106         list<docstring>::const_iterator end = usedLayouts_.end();
1107         for (; cit != end; ++cit)
1108                 tcpreamble << tclass[*cit].htmlpreamble();
1109
1110         cit = usedInsetLayouts_.begin();
1111         end = usedInsetLayouts_.end();
1112         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1113         for (; cit != end; ++cit) {
1114                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1115                 if (it == ils.end())
1116                         continue;
1117                 tcpreamble << it->second.htmlpreamble();
1118         }
1119
1120         return tcpreamble.str();
1121 }
1122
1123
1124 docstring const LaTeXFeatures::getTClassHTMLStyles() const {
1125         DocumentClass const & tclass = params_.documentClass();
1126         odocstringstream tcpreamble;
1127
1128         list<docstring>::const_iterator cit = usedLayouts_.begin();
1129         list<docstring>::const_iterator end = usedLayouts_.end();
1130         for (; cit != end; ++cit)
1131                 tcpreamble << tclass[*cit].htmlstyle();
1132
1133         cit = usedInsetLayouts_.begin();
1134         end = usedInsetLayouts_.end();
1135         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1136         for (; cit != end; ++cit) {
1137                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1138                 if (it == ils.end())
1139                         continue;
1140                 tcpreamble << it->second.htmlstyle();
1141         }
1142
1143         return tcpreamble.str();
1144 }
1145
1146
1147 namespace {
1148 docstring const getFloatI18nPreamble(docstring const & type, docstring const & name, docstring const & lang)
1149 {
1150         odocstringstream os;
1151         os << "\\addto\\captions" << lang
1152            << "{\\renewcommand{\\" << type << "name}{" << name << "}}\n";
1153         return os.str();
1154 }
1155 }
1156
1157
1158 docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel, bool use_polyglossia) const
1159 {
1160         DocumentClass const & tclass = params_.documentClass();
1161         // collect preamble snippets in a set to prevent multiple identical
1162         // commands (would happen if e.g. both theorem and theorem* are used)
1163         set<docstring> snippets;
1164         typedef LanguageList::const_iterator lang_it;
1165         lang_it const lbeg = UsedLanguages_.begin();
1166         lang_it const lend =  UsedLanguages_.end();
1167         list<docstring>::const_iterator cit = usedLayouts_.begin();
1168         list<docstring>::const_iterator end = usedLayouts_.end();
1169         for (; cit != end; ++cit) {
1170                 // language dependent commands (once per document)
1171                 snippets.insert(tclass[*cit].langpreamble(buffer().language(),
1172                                                           use_polyglossia));
1173                 // commands for language changing (for multilanguage documents)
1174                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1175                         snippets.insert(tclass[*cit].babelpreamble(buffer().language(),
1176                                                                    use_polyglossia));
1177                         for (lang_it lit = lbeg; lit != lend; ++lit)
1178                                 snippets.insert(tclass[*cit].babelpreamble(*lit, use_polyglossia));
1179                 }
1180         }
1181         if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1182                 FloatList const & floats = params_.documentClass().floats();
1183                 UsedFloats::const_iterator fit = usedFloats_.begin();
1184                 UsedFloats::const_iterator fend = usedFloats_.end();
1185                 for (; fit != fend; ++fit) {
1186                         Floating const & fl = floats.getType(fit->first);
1187                         docstring const type = from_ascii(fl.floattype());
1188                         docstring const flname = from_utf8(fl.name());
1189                         docstring name = translateIfPossible(flname,
1190                                 buffer().language()->code());
1191                         if (use_polyglossia)
1192                                 snippets.insert(getFloatI18nPreamble(
1193                                         type, name,
1194                                         from_ascii(buffer().language()->polyglossia())));
1195                         else
1196                                 snippets.insert(getFloatI18nPreamble(
1197                                         type, name,
1198                                         from_ascii(buffer().language()->babel())));
1199                         for (lang_it lit = lbeg; lit != lend; ++lit) {
1200                                 name = translateIfPossible(flname,
1201                                         (*lit)->code());
1202                                 if (use_polyglossia)
1203                                         snippets.insert(getFloatI18nPreamble(
1204                                                 type, name,
1205                                                 from_ascii((*lit)->polyglossia())));
1206                                 else
1207                                         snippets.insert(getFloatI18nPreamble(
1208                                                 type, name,
1209                                                 from_ascii((*lit)->babel())));
1210                         }
1211                 }
1212         }
1213
1214         odocstringstream tcpreamble;
1215         set<docstring>::const_iterator const send = snippets.end();
1216         set<docstring>::const_iterator it = snippets.begin();
1217         for (; it != send; ++it)
1218                 tcpreamble << *it;
1219         return tcpreamble.str();
1220 }
1221
1222
1223 docstring const LaTeXFeatures::getLyXSGMLEntities() const
1224 {
1225         // Definition of entities used in the document that are LyX related.
1226         odocstringstream entities;
1227
1228         if (mustProvide("lyxarrow")) {
1229                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
1230         }
1231
1232         return entities.str();
1233 }
1234
1235
1236 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
1237 {
1238         odocstringstream sgmlpreamble;
1239         // FIXME UNICODE
1240         docstring const basename(from_utf8(onlyPath(fname)));
1241
1242         FileMap::const_iterator end = IncludedFiles_.end();
1243         for (FileMap::const_iterator fi = IncludedFiles_.begin();
1244              fi != end; ++fi)
1245                 // FIXME UNICODE
1246                 sgmlpreamble << "\n<!ENTITY " << fi->first
1247                              << (isSGMLFileName(fi->second) ? " SYSTEM \"" : " \"")
1248                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
1249
1250         return sgmlpreamble.str();
1251 }
1252
1253
1254 void LaTeXFeatures::showStruct() const
1255 {
1256         lyxerr << "LyX needs the following commands when LaTeXing:"
1257                << "\n***** Packages:" << getPackages()
1258                << "\n***** Macros:" << to_utf8(getMacros())
1259                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
1260                << "\n***** done." << endl;
1261 }
1262
1263
1264 Buffer const & LaTeXFeatures::buffer() const
1265 {
1266         return *buffer_;
1267 }
1268
1269
1270 void LaTeXFeatures::setBuffer(Buffer const & buffer)
1271 {
1272         buffer_ = &buffer;
1273 }
1274
1275
1276 BufferParams const & LaTeXFeatures::bufferParams() const
1277 {
1278         return params_;
1279 }
1280
1281
1282 void LaTeXFeatures::getFloatDefinitions(odocstream & os) const
1283 {
1284         FloatList const & floats = params_.documentClass().floats();
1285
1286         // Here we will output the code to create the needed float styles.
1287         // We will try to do this as minimal as possible.
1288         // \floatstyle{ruled}
1289         // \newfloat{algorithm}{htbp}{loa}
1290         // \providecommand{\algorithmname}{Algorithm}
1291         // \floatname{algorithm}{\protect\algorithmname}
1292         UsedFloats::const_iterator cit = usedFloats_.begin();
1293         UsedFloats::const_iterator end = usedFloats_.end();
1294         for (; cit != end; ++cit) {
1295                 Floating const & fl = floats.getType(cit->first);
1296
1297                 // For builtin floats we do nothing.
1298                 if (!fl.needsFloatPkg()) 
1299                         continue;
1300
1301                 // We have to special case "table" and "figure"
1302                 if (fl.floattype() == "tabular" || fl.floattype() == "figure") {
1303                         // Output code to modify "table" or "figure"
1304                         // but only if builtin == false
1305                         // and that have to be true at this point in the
1306                         // function.
1307                         docstring const type = from_ascii(fl.floattype());
1308                         docstring const placement = from_ascii(fl.placement());
1309                         docstring const style = from_ascii(fl.style());
1310                         if (!style.empty()) {
1311                                 os << "\\floatstyle{" << style << "}\n"
1312                                    << "\\restylefloat{" << type << "}\n";
1313                         }
1314                         if (!placement.empty()) {
1315                                 os << "\\floatplacement{" << type << "}{"
1316                                    << placement << "}\n";
1317                         }
1318                 } else {
1319                         // The other non builtin floats.
1320
1321                         docstring const type = from_ascii(fl.floattype());
1322                         docstring const placement = from_ascii(fl.placement());
1323                         docstring const ext = from_ascii(fl.ext());
1324                         docstring const within = from_ascii(fl.within());
1325                         docstring const style = from_ascii(fl.style());
1326                         docstring const name = translateIfPossible(
1327                                         from_utf8(fl.name()),
1328                                         buffer().language()->code());
1329                         os << "\\floatstyle{" << style << "}\n"
1330                            << "\\newfloat{" << type << "}{" << placement
1331                            << "}{" << ext << '}';
1332                         if (!within.empty())
1333                                 os << '[' << within << ']';
1334                         os << '\n'
1335                            << "\\providecommand{\\" << type << "name}{"
1336                            << name << "}\n"
1337                            << "\\floatname{" << type << "}{\\protect\\"
1338                            << type << "name}\n";
1339
1340                         // What missing here is to code to minimalize the code
1341                         // output so that the same floatstyle will not be
1342                         // used several times, when the same style is still in
1343                         // effect. (Lgb)
1344                 }
1345                 if (cit->second)
1346                         os << "\n\\newsubfloat{" << from_ascii(fl.floattype()) << "}\n";
1347         }
1348 }
1349
1350
1351 } // namespace lyx