]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
cmake: make the merged build much more usable by adding all the source files to the IDE
[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         "fixltx2e",
585         "pmboxdraw",
586         "bbding",
587         "ifsym",
588         "marvosym",
589         "txfonts",
590         "mathrsfs",
591         "ascii",
592         "url",
593         "covington",
594         "csquotes",
595         "enumitem",
596         "endnotes",
597         "hhline",
598         "ifthen",
599         // listings is handled in BufferParams.cpp
600         "bm",
601         "pdfpages",
602         "amscd",
603         "slashed",
604         "multirow",
605         "tfrupee"
606 };
607
608 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
609
610 }
611
612
613 string const LaTeXFeatures::getColorOptions() const
614 {
615         ostringstream colors;
616
617         // Handling the color packages separately is needed to be able to load them
618         // before babel when hyperref is loaded with the colorlinks option
619         // for more info see Bufferparams.cpp
620
621         // [x]color.sty
622         if (mustProvide("color") || mustProvide("xcolor")) {
623                 string const package =
624                         (mustProvide("xcolor") ? "xcolor" : "color");
625                 if (params_.graphics_driver == "default"
626                         || params_.graphics_driver == "none")
627                         colors << "\\usepackage{" << package << "}\n";
628                 else
629                         colors << "\\usepackage["
630                                  << params_.graphics_driver
631                                  << "]{" << package << "}\n";
632         }
633
634         // pdfcolmk must be loaded after color
635         if (mustProvide("pdfcolmk"))
636                 colors << "\\usepackage{pdfcolmk}\n";
637
638         // the following 3 color commands must be set after color
639         // is loaded and before pdfpages, therefore add the command
640         // here define the set color
641         if (mustProvide("pagecolor")) {
642                 colors << "\\definecolor{page_backgroundcolor}{rgb}{";
643                 colors << outputLaTeXColor(params_.backgroundcolor) << "}\n";
644                 // set the page color
645                 colors << "\\pagecolor{page_backgroundcolor}\n";
646         }
647
648         if (mustProvide("fontcolor")) {
649                 colors << "\\definecolor{document_fontcolor}{rgb}{";
650                 colors << outputLaTeXColor(params_.fontcolor) << "}\n";
651                 // set the color
652                 colors << "\\color{document_fontcolor}\n";
653         }
654
655         if (mustProvide("lyxgreyedout")) {
656                 colors << "\\definecolor{note_fontcolor}{rgb}{";
657                 colors << outputLaTeXColor(params_.notefontcolor) << "}\n";
658                 // the color will be set together with the definition of
659                 // the lyxgreyedout environment (see lyxgreyedout_def)
660         }
661
662         // color for shaded boxes
663         if (isRequired("framed") && mustProvide("color")) {
664                 colors << "\\definecolor{shadecolor}{rgb}{";
665                 colors << outputLaTeXColor(params_.boxbgcolor) << "}\n";
666                 // this color is automatically used by the LaTeX-package "framed"
667         }
668
669         return colors.str();
670 }
671
672
673 string const LaTeXFeatures::getPackages() const
674 {
675         ostringstream packages;
676         DocumentClass const & tclass = params_.documentClass();
677
678         // FIXME: currently, we can only load packages and macros known
679         // to LyX.
680         // However, with the Require tag of layouts/custom insets,
681         // also unknown packages can be requested. They are silently
682         // swallowed now. We should change this eventually.
683
684         //
685         //  These are all the 'simple' includes.  i.e
686         //  packages which we just \usepackage{package}
687         //
688         for (int i = 0; i < nb_simplefeatures; ++i) {
689                 if (mustProvide(simplefeatures[i]))
690                         packages << "\\usepackage{"
691                                  << simplefeatures[i] << "}\n";
692         }
693
694         //
695         // The rest of these packages are somewhat more complicated
696         // than those above.
697         //
698
699         // if fontspec is used, AMS packages have to be loaded before
700         // fontspec (in BufferParams)
701         if (!params_.useNonTeXFonts && !loadAMSPackages().empty())
702                 packages << loadAMSPackages();
703
704         // wasysym is a simple feature, but it must be after amsmath if both
705         // are used
706         // wasysym redefines some integrals (e.g. iint) from amsmath. That
707         // leads to inconsistent integrals. We only load this package if
708         // the document does not contain integrals (then isRequired("esint")
709         // is false) or if esint is used, since esint redefines all relevant
710         // integral symbols from wasysym and amsmath.
711         // See http://www.lyx.org/trac/ticket/1942
712         if (mustProvide("wasysym") &&
713             (params_.use_esint != BufferParams::package_off || !isRequired("esint")))
714                 packages << "\\usepackage{wasysym}\n";
715
716         // accents must be loaded after amsmath
717         if (mustProvide("accents"))
718                 packages << "\\usepackage{accents}\n";
719
720         // mathdots must be loaded after amsmath
721         if (mustProvide("mathdots") &&
722                 params_.use_mathdots != BufferParams::package_off)
723                 packages << "\\usepackage{mathdots}\n";
724
725         // yhmath must be loaded after amsmath
726         if (mustProvide("yhmath"))
727                 packages << "\\usepackage{yhmath}\n";
728
729         // [x]color and pdfcolmk are handled in getColorOptions() above
730         
731         // makeidx.sty
732         if (isRequired("makeidx") || isRequired("splitidx")) {
733                 if (!tclass.provides("makeidx") && !isRequired("splitidx"))
734                         packages << "\\usepackage{makeidx}\n";
735                 if (!tclass.provides("splitidx") && isRequired("splitidx"))
736                         packages << "\\usepackage{splitidx}\n";
737                 packages << "\\makeindex\n";
738         }
739
740         // graphicx.sty
741         if (mustProvide("graphicx") && params_.graphics_driver != "none") {
742                 if (params_.graphics_driver == "default")
743                         packages << "\\usepackage{graphicx}\n";
744                 else
745                         packages << "\\usepackage["
746                                  << params_.graphics_driver
747                                  << "]{graphicx}\n";
748         }
749         
750         // lyxskak.sty --- newer chess support based on skak.sty
751         if (mustProvide("chess"))
752                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
753
754         // setspace.sty
755         if (mustProvide("setspace") && !tclass.provides("SetSpace"))
756                 packages << "\\usepackage{setspace}\n";
757
758         // esint must be after amsmath and wasysym, since it will redeclare
759         // inconsistent integral symbols
760         if ((mustProvide("esint") || mustProvide("esintoramsmath")) &&
761             params_.use_esint != BufferParams::package_off)
762                 packages << "\\usepackage{esint}\n";
763
764         // natbib.sty
765         // Some classes load natbib themselves, but still allow (or even require)
766         // plain numeric citations (ReVTeX is such a case, see bug 5182).
767         // This special case is indicated by the "natbib-internal" key.
768         if (mustProvide("natbib") && !tclass.provides("natbib-internal")) {
769                 packages << "\\usepackage[";
770                 if (params_.citeEngine() == ENGINE_NATBIB_NUMERICAL)
771                         packages << "numbers";
772                 else
773                         packages << "authoryear";
774                 packages << "]{natbib}\n";
775         }
776
777         // jurabib -- we need version 0.6 at least.
778         if (mustProvide("jurabib"))
779                 packages << "\\usepackage{jurabib}[2004/01/25]\n";
780         
781         // xargs -- we need version 1.09 at least
782         if (mustProvide("xargs"))
783                 packages << "\\usepackage{xargs}[2008/03/08]\n";
784
785         // bibtopic -- the dot provides the aux file naming which
786         // LyX can detect.
787         if (mustProvide("bibtopic"))
788                 packages << "\\usepackage[dot]{bibtopic}\n";
789
790         if (mustProvide("xy"))
791                 packages << "\\usepackage[all]{xy}\n";
792
793         if (mustProvide("feyn"))
794                 packages << "\\usepackage{feyn}\n"; //Diagram
795
796         if (mustProvide("ulem"))
797                 packages << "\\PassOptionsToPackage{normalem}{ulem}\n"
798                             "\\usepackage{ulem}\n";
799
800         if (params_.use_mhchem == BufferParams::package_on ||
801             (mustProvide("mhchem") &&
802              params_.use_mhchem != BufferParams::package_off))
803                 packages << "\\PassOptionsToPackage{version=3}{mhchem}\n"
804                             "\\usepackage{mhchem}\n";
805
806         if (mustProvide("nomencl")) {
807                 // Make it work with the new and old version of the package,
808                 // but don't use the compatibility option since it is
809                 // incompatible to other packages.
810                 packages << "\\usepackage{nomencl}\n"
811                             "% the following is useful when we have the old nomencl.sty package\n"
812                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
813                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
814                             "\\makenomenclature\n";
815         }
816
817         // fixltx2e provides subscript
818         if (mustProvide("subscript") && !isRequired("fixltx2e"))
819                 packages << "\\usepackage{subscript}\n";
820
821         return packages.str();
822 }
823
824
825 string LaTeXFeatures::getPreambleSnippets() const 
826 {
827         ostringstream snip;
828         SnippetList::const_iterator pit  = preamble_snippets_.begin();
829         SnippetList::const_iterator pend = preamble_snippets_.end();
830         for (; pit != pend; ++pit)
831                 snip << *pit << '\n';
832         return snip.str();
833 }
834
835
836 docstring const LaTeXFeatures::getMacros() const
837 {
838         odocstringstream macros;
839
840         if (!preamble_snippets_.empty()) {
841                 macros << '\n';
842                 macros << from_utf8(getPreambleSnippets());
843         }
844
845         if (mustProvide("papersize")) {
846                 if (runparams_.flavor == OutputParams::LATEX)
847                         macros << papersizedvi_def << '\n';
848                 else
849                         macros << papersizepdf_def << '\n';
850         }
851
852         if (mustProvide("LyX")) {
853                 if (isRequired("hyperref"))
854                         macros << lyx_hyperref_def << '\n';
855                 else
856                         macros << lyx_def << '\n';
857         }
858
859         if (mustProvide("noun"))
860                 macros << noun_def << '\n';
861
862         if (mustProvide("lyxarrow"))
863                 macros << lyxarrow_def << '\n';
864
865         if (!usePolyglossia() && mustProvide("textgreek")) {
866                 // Avoid a LaTeX error if times fonts are used and the grtimes
867                 // package is installed but actual fonts are not (bug 6469).
868                 if (params_.fonts_roman == "times")
869                         macros << subst(textgreek_def,
870                                         from_ascii("\\greektext #1"),
871                                         from_ascii("%\n  \\IfFileExists"
872                                                    "{grtm10.tfm}{}{\\fontfamily"
873                                                    "{cmr}}\\greektext #1"))
874                                << '\n';
875                 else
876                         macros << textgreek_def << '\n';
877         }
878
879         if (!usePolyglossia() && mustProvide("textcyr"))
880                 macros << textcyr_def << '\n';
881
882         if (mustProvide("lyxmathsym"))
883                 macros << lyxmathsym_def << '\n';
884
885         if (mustProvide("cedilla"))
886                 macros << cedilla_def << '\n';
887
888         if (mustProvide("subring"))
889                 macros << subring_def << '\n';
890
891         if (mustProvide("subdot"))
892                 macros << subdot_def << '\n';
893
894         if (mustProvide("subhat"))
895                 macros << subhat_def << '\n';
896
897         if (mustProvide("subtilde"))
898                 macros << subtilde_def << '\n';
899
900         if (mustProvide("dacute"))
901                 macros << dacute_def << '\n';
902
903         if (mustProvide("tipasymb"))
904                 macros << tipasymb_def << '\n';
905
906         if (mustProvide("dgrave"))
907                 macros << dgrave_def << '\n';
908
909         if (mustProvide("rcap"))
910                 macros << rcap_def << '\n';
911
912         if (mustProvide("ogonek"))
913                 macros << ogonek_def << '\n';
914
915         // quotes.
916         if (mustProvide("quotesinglbase"))
917                 macros << quotesinglbase_def << '\n';
918         if (mustProvide("quotedblbase"))
919                 macros << quotedblbase_def << '\n';
920         if (mustProvide("guilsinglleft"))
921                 macros << guilsinglleft_def << '\n';
922         if (mustProvide("guilsinglright"))
923                 macros << guilsinglright_def << '\n';
924         if (mustProvide("guillemotleft"))
925                 macros << guillemotleft_def << '\n';
926         if (mustProvide("guillemotright"))
927                 macros << guillemotright_def << '\n';
928
929         // Math mode
930         if (mustProvide("binom") && !isRequired("amsmath"))
931                 macros << binom_def << '\n';
932         if (mustProvide("mathcircumflex"))
933                 macros << mathcircumflex_def << '\n';
934
935         // other
936         if (mustProvide("ParagraphLeftIndent"))
937                 macros << paragraphleftindent_def;
938         if (mustProvide("NeedLyXFootnoteCode"))
939                 macros << floatingfootnote_def;
940
941         // some problems with tex->html converters
942         if (mustProvide("NeedTabularnewline"))
943                 macros << tabularnewline_def;
944
945         // greyed-out environment (note inset)
946         // the color is specified in the routine
947         // getColorOptions() to avoid LaTeX-package clashes
948         if (mustProvide("lyxgreyedout"))
949                 macros << lyxgreyedout_def;
950
951         if (mustProvide("lyxdot"))
952                 macros << lyxdot_def << '\n';
953
954         // floats
955         getFloatDefinitions(macros);
956         
957         if (mustProvide("refstyle")) 
958                 macros << lyxref_def << '\n';   
959         
960         // change tracking
961         if (mustProvide("ct-dvipost"))
962                 macros << changetracking_dvipost_def;
963         
964         if (mustProvide("ct-xcolor-ulem")) {
965                 streamsize const prec = macros.precision(2);
966         
967                 RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
968                 macros << "\\providecolor{lyxadded}{rgb}{"
969                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
970
971                 RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
972                 macros << "\\providecolor{lyxdeleted}{rgb}{"
973                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
974
975                 macros.precision(prec);
976                 
977                 if (isRequired("hyperref"))
978                         macros << changetracking_xcolor_ulem_hyperref_def;
979                 else
980                         macros << changetracking_xcolor_ulem_def;
981         }
982
983         if (mustProvide("ct-none"))
984                 macros << changetracking_none_def;
985
986         return macros.str();
987 }
988
989
990 string const LaTeXFeatures::getBabelPresettings() const
991 {
992         ostringstream tmp;
993
994         LanguageList::const_iterator it  = UsedLanguages_.begin();
995         LanguageList::const_iterator end = UsedLanguages_.end();
996         for (; it != end; ++it)
997                 if (!(*it)->babel_presettings().empty())
998                         tmp << (*it)->babel_presettings() << '\n';
999         if (!params_.language->babel_presettings().empty())
1000                 tmp << params_.language->babel_presettings() << '\n';
1001
1002         return tmp.str();
1003 }
1004
1005
1006 string const LaTeXFeatures::getBabelPostsettings() const
1007 {
1008         ostringstream tmp;
1009
1010         LanguageList::const_iterator it  = UsedLanguages_.begin();
1011         LanguageList::const_iterator end = UsedLanguages_.end();
1012         for (; it != end; ++it)
1013                 if (!(*it)->babel_postsettings().empty())
1014                         tmp << (*it)->babel_postsettings() << '\n';
1015         if (!params_.language->babel_postsettings().empty())
1016                 tmp << params_.language->babel_postsettings() << '\n';
1017
1018         return tmp.str();
1019 }
1020
1021
1022 bool LaTeXFeatures::needBabelLangOptions() const
1023 {
1024         if (!lyxrc.language_global_options || params_.language->asBabelOptions())
1025                 return true;
1026
1027         LanguageList::const_iterator it  = UsedLanguages_.begin();
1028         LanguageList::const_iterator end = UsedLanguages_.end();
1029         for (; it != end; ++it)
1030                 if ((*it)->asBabelOptions())
1031                         return true;
1032
1033         return false;
1034 }
1035
1036
1037 string const LaTeXFeatures::loadAMSPackages() const
1038 {
1039         ostringstream tmp;
1040         if (mustProvide("amsthm"))
1041                 tmp << "\\usepackage{amsthm}\n";
1042
1043         // esint is preferred for esintoramsmath
1044         if ((mustProvide("amsmath")
1045              && params_.use_amsmath != BufferParams::package_off)
1046             || (mustProvide("esintoramsmath")
1047                 && params_.use_esint == BufferParams::package_off
1048                 && params_.use_amsmath != BufferParams::package_off)) {
1049                 tmp << "\\usepackage{amsmath}\n";
1050         } else {
1051                 // amsbsy and amstext are already provided by amsmath
1052                 if (mustProvide("amsbsy"))
1053                         tmp << "\\usepackage{amsbsy}\n";
1054                 if (mustProvide("amstext"))
1055                         tmp << "\\usepackage{amstext}\n";
1056         }
1057         
1058         if (mustProvide("amssymb")
1059             || params_.use_amsmath == BufferParams::package_on)
1060                 tmp << "\\usepackage{amssymb}\n";
1061
1062         return tmp.str();
1063 }
1064
1065
1066 docstring const LaTeXFeatures::getTClassPreamble() const
1067 {
1068         // the text class specific preamble
1069         DocumentClass const & tclass = params_.documentClass();
1070         odocstringstream tcpreamble;
1071
1072         tcpreamble << tclass.preamble();
1073
1074         list<docstring>::const_iterator cit = usedLayouts_.begin();
1075         list<docstring>::const_iterator end = usedLayouts_.end();
1076         for (; cit != end; ++cit)
1077                 tcpreamble << tclass[*cit].preamble();
1078
1079         cit = usedInsetLayouts_.begin();
1080         end = usedInsetLayouts_.end();
1081         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1082         for (; cit != end; ++cit) {
1083                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1084                 if (it == ils.end())
1085                         continue;
1086                 tcpreamble << it->second.preamble();
1087         }
1088
1089         return tcpreamble.str();
1090 }
1091
1092
1093 docstring const LaTeXFeatures::getTClassHTMLPreamble() const 
1094 {
1095         DocumentClass const & tclass = params_.documentClass();
1096         odocstringstream tcpreamble;
1097
1098         tcpreamble << tclass.htmlpreamble();
1099
1100         list<docstring>::const_iterator cit = usedLayouts_.begin();
1101         list<docstring>::const_iterator end = usedLayouts_.end();
1102         for (; cit != end; ++cit)
1103                 tcpreamble << tclass[*cit].htmlpreamble();
1104
1105         cit = usedInsetLayouts_.begin();
1106         end = usedInsetLayouts_.end();
1107         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1108         for (; cit != end; ++cit) {
1109                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1110                 if (it == ils.end())
1111                         continue;
1112                 tcpreamble << it->second.htmlpreamble();
1113         }
1114
1115         return tcpreamble.str();
1116 }
1117
1118
1119 docstring const LaTeXFeatures::getTClassHTMLStyles() const {
1120         DocumentClass const & tclass = params_.documentClass();
1121         odocstringstream tcpreamble;
1122
1123         list<docstring>::const_iterator cit = usedLayouts_.begin();
1124         list<docstring>::const_iterator end = usedLayouts_.end();
1125         for (; cit != end; ++cit)
1126                 tcpreamble << tclass[*cit].htmlstyle();
1127
1128         cit = usedInsetLayouts_.begin();
1129         end = usedInsetLayouts_.end();
1130         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1131         for (; cit != end; ++cit) {
1132                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1133                 if (it == ils.end())
1134                         continue;
1135                 tcpreamble << it->second.htmlstyle();
1136         }
1137
1138         return tcpreamble.str();
1139 }
1140
1141
1142 namespace {
1143 docstring const getFloatI18nPreamble(docstring const & type, docstring const & name, docstring const & lang)
1144 {
1145         odocstringstream os;
1146         os << "\\addto\\captions" << lang
1147            << "{\\renewcommand{\\" << type << "name}{" << name << "}}\n";
1148         return os.str();
1149 }
1150 }
1151
1152
1153 docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel, bool use_polyglossia) const
1154 {
1155         DocumentClass const & tclass = params_.documentClass();
1156         // collect preamble snippets in a set to prevent multiple identical
1157         // commands (would happen if e.g. both theorem and theorem* are used)
1158         set<docstring> snippets;
1159         typedef LanguageList::const_iterator lang_it;
1160         lang_it const lbeg = UsedLanguages_.begin();
1161         lang_it const lend =  UsedLanguages_.end();
1162         list<docstring>::const_iterator cit = usedLayouts_.begin();
1163         list<docstring>::const_iterator end = usedLayouts_.end();
1164         for (; cit != end; ++cit) {
1165                 // language dependent commands (once per document)
1166                 snippets.insert(tclass[*cit].langpreamble(buffer().language(),
1167                                                           use_polyglossia));
1168                 // commands for language changing (for multilanguage documents)
1169                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1170                         snippets.insert(tclass[*cit].babelpreamble(buffer().language(),
1171                                                                    use_polyglossia));
1172                         for (lang_it lit = lbeg; lit != lend; ++lit)
1173                                 snippets.insert(tclass[*cit].babelpreamble(*lit, use_polyglossia));
1174                 }
1175         }
1176         if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1177                 FloatList const & floats = params_.documentClass().floats();
1178                 UsedFloats::const_iterator fit = usedFloats_.begin();
1179                 UsedFloats::const_iterator fend = usedFloats_.end();
1180                 for (; fit != fend; ++fit) {
1181                         Floating const & fl = floats.getType(fit->first);
1182                         docstring const type = from_ascii(fl.floattype());
1183                         docstring const flname = from_utf8(fl.name());
1184                         docstring name = translateIfPossible(flname,
1185                                 buffer().language()->code());
1186                         if (use_polyglossia)
1187                                 snippets.insert(getFloatI18nPreamble(
1188                                         type, name,
1189                                         from_ascii(buffer().language()->polyglossia())));
1190                         else
1191                                 snippets.insert(getFloatI18nPreamble(
1192                                         type, name,
1193                                         from_ascii(buffer().language()->babel())));
1194                         for (lang_it lit = lbeg; lit != lend; ++lit) {
1195                                 name = translateIfPossible(flname,
1196                                         (*lit)->code());
1197                                 if (use_polyglossia)
1198                                         snippets.insert(getFloatI18nPreamble(
1199                                                 type, name,
1200                                                 from_ascii((*lit)->polyglossia())));
1201                                 else
1202                                         snippets.insert(getFloatI18nPreamble(
1203                                                 type, name,
1204                                                 from_ascii((*lit)->babel())));
1205                         }
1206                 }
1207         }
1208
1209         odocstringstream tcpreamble;
1210         set<docstring>::const_iterator const send = snippets.end();
1211         set<docstring>::const_iterator it = snippets.begin();
1212         for (; it != send; ++it)
1213                 tcpreamble << *it;
1214         return tcpreamble.str();
1215 }
1216
1217
1218 docstring const LaTeXFeatures::getLyXSGMLEntities() const
1219 {
1220         // Definition of entities used in the document that are LyX related.
1221         odocstringstream entities;
1222
1223         if (mustProvide("lyxarrow")) {
1224                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
1225         }
1226
1227         return entities.str();
1228 }
1229
1230
1231 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
1232 {
1233         odocstringstream sgmlpreamble;
1234         // FIXME UNICODE
1235         docstring const basename(from_utf8(onlyPath(fname)));
1236
1237         FileMap::const_iterator end = IncludedFiles_.end();
1238         for (FileMap::const_iterator fi = IncludedFiles_.begin();
1239              fi != end; ++fi)
1240                 // FIXME UNICODE
1241                 sgmlpreamble << "\n<!ENTITY " << fi->first
1242                              << (isSGMLFileName(fi->second) ? " SYSTEM \"" : " \"")
1243                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
1244
1245         return sgmlpreamble.str();
1246 }
1247
1248
1249 void LaTeXFeatures::showStruct() const
1250 {
1251         lyxerr << "LyX needs the following commands when LaTeXing:"
1252                << "\n***** Packages:" << getPackages()
1253                << "\n***** Macros:" << to_utf8(getMacros())
1254                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
1255                << "\n***** done." << endl;
1256 }
1257
1258
1259 Buffer const & LaTeXFeatures::buffer() const
1260 {
1261         return *buffer_;
1262 }
1263
1264
1265 void LaTeXFeatures::setBuffer(Buffer const & buffer)
1266 {
1267         buffer_ = &buffer;
1268 }
1269
1270
1271 BufferParams const & LaTeXFeatures::bufferParams() const
1272 {
1273         return params_;
1274 }
1275
1276
1277 void LaTeXFeatures::getFloatDefinitions(odocstream & os) const
1278 {
1279         FloatList const & floats = params_.documentClass().floats();
1280
1281         // Here we will output the code to create the needed float styles.
1282         // We will try to do this as minimal as possible.
1283         // \floatstyle{ruled}
1284         // \newfloat{algorithm}{htbp}{loa}
1285         // \providecommand{\algorithmname}{Algorithm}
1286         // \floatname{algorithm}{\protect\algorithmname}
1287         UsedFloats::const_iterator cit = usedFloats_.begin();
1288         UsedFloats::const_iterator end = usedFloats_.end();
1289         for (; cit != end; ++cit) {
1290                 Floating const & fl = floats.getType(cit->first);
1291
1292                 // For builtin floats we do nothing.
1293                 if (!fl.needsFloatPkg()) 
1294                         continue;
1295
1296                 // We have to special case "table" and "figure"
1297                 if (fl.floattype() == "tabular" || fl.floattype() == "figure") {
1298                         // Output code to modify "table" or "figure"
1299                         // but only if builtin == false
1300                         // and that have to be true at this point in the
1301                         // function.
1302                         docstring const type = from_ascii(fl.floattype());
1303                         docstring const placement = from_ascii(fl.placement());
1304                         docstring const style = from_ascii(fl.style());
1305                         if (!style.empty()) {
1306                                 os << "\\floatstyle{" << style << "}\n"
1307                                    << "\\restylefloat{" << type << "}\n";
1308                         }
1309                         if (!placement.empty()) {
1310                                 os << "\\floatplacement{" << type << "}{"
1311                                    << placement << "}\n";
1312                         }
1313                 } else {
1314                         // The other non builtin floats.
1315
1316                         docstring const type = from_ascii(fl.floattype());
1317                         docstring const placement = from_ascii(fl.placement());
1318                         docstring const ext = from_ascii(fl.ext());
1319                         docstring const within = from_ascii(fl.within());
1320                         docstring const style = from_ascii(fl.style());
1321                         docstring const name = translateIfPossible(
1322                                         from_utf8(fl.name()),
1323                                         buffer().language()->code());
1324                         os << "\\floatstyle{" << style << "}\n"
1325                            << "\\newfloat{" << type << "}{" << placement
1326                            << "}{" << ext << '}';
1327                         if (!within.empty())
1328                                 os << '[' << within << ']';
1329                         os << '\n'
1330                            << "\\providecommand{\\" << type << "name}{"
1331                            << name << "}\n"
1332                            << "\\floatname{" << type << "}{\\protect\\"
1333                            << type << "name}\n";
1334
1335                         // What missing here is to code to minimalize the code
1336                         // output so that the same floatstyle will not be
1337                         // used several times, when the same style is still in
1338                         // effect. (Lgb)
1339                 }
1340                 if (cit->second)
1341                         os << "\n\\newsubfloat{" << from_ascii(fl.floattype()) << "}\n";
1342         }
1343 }
1344
1345
1346 } // namespace lyx