]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
Restor 1.4.x behaviour: Don't touch the preamble QTextEdit if the preamble text is...
[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 "BufferParams.h"
20 #include "Color.h"
21 #include "debug.h"
22 #include "Encoding.h"
23 #include "Floating.h"
24 #include "FloatList.h"
25 #include "Language.h"
26 #include "Lexer.h"
27 #include "LyXRC.h"
28
29 #include "support/docstream.h"
30 #include "support/filetools.h"
31
32 #include "frontends/controllers/frontend_helpers.h"
33
34 namespace lyx {
35
36 using support::isSGMLFilename;
37 using support::libFileSearch;
38 using support::makeRelPath;
39 using support::onlyPath;
40
41 using std::endl;
42 using std::find;
43 using std::string;
44 using std::list;
45 using std::ostream;
46 using std::ostringstream;
47 using std::set;
48
49 /////////////////////////////////////////////////////////////////////
50 //
51 // Strings
52 //
53 /////////////////////////////////////////////////////////////////////
54
55 //\NeedsTeXFormat{LaTeX2e}
56 //\ProvidesPackage{lyx}[1996/01/11 LLE v0.2 (LyX LaTeX Extensions)]
57 //\message{LyX LaTeX Extensions (LLE v0.2) of 11-Jan-1996.}
58
59 static string const lyx_def =
60         "\\providecommand{\\LyX}{L\\kern-.1667em\\lower.25em\\hbox{Y}\\kern-.125emX\\@}";
61
62 static string const lyxline_def =
63         "\\newcommand{\\lyxline}[1][1pt]{%\n"
64         "  \\par\\noindent%\n"
65         "  \\rule[.5ex]{\\linewidth}{#1}\\par}";
66
67 static string const noun_def = "\\newcommand{\\noun}[1]{\\textsc{#1}}";
68
69 static string const lyxarrow_def =
70         "\\newcommand{\\lyxarrow}{\\leavevmode\\,$\\triangleright$\\,\\allowbreak}";
71
72 // for quotes without babel. This does not give perfect results, but
73 // anybody serious about non-english quotes should use babel (JMarc).
74
75 static string const quotedblbase_def =
76         "\\ProvideTextCommandDefault{\\quotedblbase}{%\n"
77         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquotedblright}%\n"
78         "  \\penalty10000\\hskip0em\\relax%\n"
79         "}";
80
81 static string const quotesinglbase_def =
82         "\\ProvideTextCommandDefault{\\quotesinglbase}{%\n"
83         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquoteright}%\n"
84         "  \\penalty10000\\hskip0em\\relax%\n"
85         "}";
86
87 static string const guillemotleft_def =
88         "\\ProvideTextCommandDefault{\\guillemotleft}{%\n"
89         "  {\\usefont{U}{lasy}{m}{n}\\char'50\\kern-.15em\\char'50}%\n"
90         "\\penalty10000\\hskip0pt\\relax%\n"
91         "}";
92
93 static string const guillemotright_def =
94         "\\ProvideTextCommandDefault{\\guillemotright}{%\n"
95         "  \\penalty10000\\hskip0pt%\n"
96         "  {\\usefont{U}{lasy}{m}{n}\\char'51\\kern-.15em\\char'51}%\n"
97         "}";
98
99 static string const guilsinglleft_def =
100         "\\ProvideTextCommandDefault{\\guilsinglleft}{%\n"
101         "  {\\usefont{U}{lasy}{m}{n}\\char'50}%\n"
102         "  \\penalty10000\\hskip0pt\\relax%\n"
103         "}";
104
105 static string const guilsinglright_def =
106         "\\ProvideTextCommandDefault{\\guilsinglright}{%\n"
107         "  \\penalty10000\\hskip0pt%\n"
108         "  {\\usefont{U}{lasy}{m}{n}\\char'51}%\n"
109         "}";
110
111 static string const paragraphleftindent_def =
112         "\\newenvironment{LyXParagraphLeftIndent}[1]%\n"
113         "{\n"
114         "  \\begin{list}{}{%\n"
115         "    \\setlength{\\topsep}{0pt}%\n"
116         "    \\addtolength{\\leftmargin}{#1}\n"
117 // ho hum, yet more things commented out with no hint as to why they
118 // weren't just removed
119 //      "%%    \\addtolength{\\leftmargin}{#1\\textwidth}\n"
120 //      "%%    \\setlength{\\textwidth}{#2\\textwidth}\n"
121 //      "%%    \\setlength\\listparindent\\parindent%\n"
122 //      "%%    \\setlength\\itemindent\\parindent%\n"
123         "    \\setlength{\\parsep}{0pt plus 1pt}%\n"
124         "  }\n"
125         "  \\item[]\n"
126         "}\n"
127         "{\\end{list}}\n";
128
129 static string const floatingfootnote_def =
130         "%% Special footnote code from the package 'stblftnt.sty'\n"
131         "%% Author: Robin Fairbairns -- Last revised Dec 13 1996\n"
132         "\\let\\SF@@footnote\\footnote\n"
133         "\\def\\footnote{\\ifx\\protect\\@typeset@protect\n"
134         "    \\expandafter\\SF@@footnote\n"
135         "  \\else\n"
136         "    \\expandafter\\SF@gobble@opt\n"
137         "  \\fi\n"
138         "}\n"
139         "\\expandafter\\def\\csname SF@gobble@opt \\endcsname{\\@ifnextchar[%]\n"
140         "  \\SF@gobble@twobracket\n"
141         "  \\@gobble\n"
142         "}\n"
143         "\\edef\\SF@gobble@opt{\\noexpand\\protect\n"
144         "  \\expandafter\\noexpand\\csname SF@gobble@opt \\endcsname}\n"
145         "\\def\\SF@gobble@twobracket[#1]#2{}\n";
146
147 static string const boldsymbol_def =
148         "%% Bold symbol macro for standard LaTeX users\n"
149         "\\providecommand{\\boldsymbol}[1]{\\mbox{\\boldmath $#1$}}\n";
150
151 static string const binom_def =
152         "%% Binom macro for standard LaTeX users\n"
153         "\\newcommand{\\binom}[2]{{#1 \\choose #2}}\n";
154
155 static string const mathcircumflex_def =
156         "%% For printing a cirumflex inside a formula\n"
157         "\\newcommand{\\mathcircumflex}[0]{\\mbox{\\^{}}}\n";
158
159 static string const tabularnewline_def =
160         "%% Because html converters don't know tabularnewline\n"
161         "\\providecommand{\\tabularnewline}{\\\\}\n";
162
163 static string const lyxgreyedout_def =
164         "%% The greyedout annotation environment\n"
165         "\\newenvironment{lyxgreyedout}{\\textcolor[gray]{0.8}\\bgroup}{\\egroup}\n";
166
167 // We want to omit the file extension for includegraphics, but this does not
168 // work when the filename contains other dots.
169 // Idea from http://www.tex.ac.uk/cgi-bin/texfaq2html?label=unkgrfextn
170 static string const lyxdot_def =
171         "%% A simple dot to overcome graphicx limitations\n"
172         "\\newcommand{\\lyxdot}{.}\n";
173
174
175
176 /////////////////////////////////////////////////////////////////////
177 //
178 // LaTeXFeatures
179 //
180 /////////////////////////////////////////////////////////////////////
181
182 LaTeXFeatures::PackagesList LaTeXFeatures::packages_;
183
184
185 LaTeXFeatures::LaTeXFeatures(Buffer const & b, BufferParams const & p,
186                              OutputParams const & r)
187         : buffer_(&b), params_(p), runparams_(r)
188 {}
189
190
191 bool LaTeXFeatures::useBabel() const
192 {
193         return lyxrc.language_use_babel ||
194                 bufferParams().language->lang() != lyxrc.default_language ||
195                 this->hasLanguages();
196 }
197
198
199 void LaTeXFeatures::require(string const & name)
200 {
201         if (isRequired(name))
202                 return;
203
204         features_.push_back(name);
205 }
206
207
208 void LaTeXFeatures::getAvailable()
209 {
210         Lexer lex(0, 0);
211         support::FileName const real_file = libFileSearch("", "packages.lst");
212
213         if (real_file.empty())
214                 return;
215
216         lex.setFile(real_file);
217
218         if (!lex.isOK())
219                 return;
220
221         // Make sure that we are clean
222         packages_.clear();
223
224         bool finished = false;
225         // Parse config-file
226         while (lex.isOK() && !finished) {
227                 switch (lex.lex()) {
228                 case Lexer::LEX_FEOF:
229                         finished = true;
230                         break;
231                 default:
232                         string const name = lex.getString();
233                         PackagesList::const_iterator begin = packages_.begin();
234                         PackagesList::const_iterator end   = packages_.end();
235                         if (find(begin, end, name) == end)
236                                 packages_.push_back(name);
237                 }
238         }
239 }
240
241
242 void LaTeXFeatures::useLayout(string const & layoutname)
243 {
244         // Some code to avoid loops in dependency definition
245         static int level = 0;
246         const int maxlevel = 30;
247         if (level > maxlevel) {
248                 lyxerr << "LaTeXFeatures::useLayout: maximum level of "
249                        << "recursion attained by layout "
250                        << layoutname << endl;
251                 return;
252         }
253
254         TextClass const & tclass = params_.getTextClass();
255         if (tclass.hasLayout(layoutname)) {
256                 // Is this layout already in usedLayouts?
257                 list<string>::const_iterator cit = usedLayouts_.begin();
258                 list<string>::const_iterator end = usedLayouts_.end();
259                 for (; cit != end; ++cit) {
260                         if (layoutname == *cit)
261                                 return;
262                 }
263
264                 Layout_ptr const & lyt = tclass[layoutname];
265                 if (!lyt->depends_on().empty()) {
266                         ++level;
267                         useLayout(lyt->depends_on());
268                         --level;
269                 }
270                 usedLayouts_.push_back(layoutname);
271         } else {
272                 lyxerr << "LaTeXFeatures::useLayout: layout `"
273                        << layoutname << "' does not exist in this class"
274                        << endl;
275         }
276
277         --level;
278 }
279
280
281 bool LaTeXFeatures::isRequired(string const & name) const
282 {
283         return find(features_.begin(), features_.end(), name) != features_.end();
284 }
285
286
287 bool LaTeXFeatures::mustProvide(string const & name) const
288 {
289         return isRequired(name) && !params_.getTextClass().provides(name);
290 }
291
292
293 bool LaTeXFeatures::isAvailable(string const & name)
294 {
295         if (packages_.empty())
296                 getAvailable();
297         return find(packages_.begin(), packages_.end(), name) != packages_.end();
298 }
299
300
301 void LaTeXFeatures::addPreambleSnippet(string const & preamble)
302 {
303         FeaturesList::const_iterator begin = preamble_snippets_.begin();
304         FeaturesList::const_iterator end   = preamble_snippets_.end();
305         if (find(begin, end, preamble) == end)
306                 preamble_snippets_.push_back(preamble);
307 }
308
309
310 void LaTeXFeatures::useFloat(string const & name)
311 {
312         usedFloats_.insert(name);
313         // We only need float.sty if we use non builtin floats, or if we
314         // use the "H" modifier. This includes modified table and
315         // figure floats. (Lgb)
316         Floating const & fl = params_.getTextClass().floats().getType(name);
317         if (!fl.type().empty() && !fl.builtin()) {
318                 require("float");
319         }
320 }
321
322
323 void LaTeXFeatures::useLanguage(Language const * lang)
324 {
325         UsedLanguages_.insert(lang);
326 }
327
328
329 void LaTeXFeatures::includeFile(docstring const & key, string const & name)
330 {
331         IncludedFiles_[key] = name;
332 }
333
334
335 bool LaTeXFeatures::hasLanguages() const
336 {
337         return !UsedLanguages_.empty();
338 }
339
340
341 string LaTeXFeatures::getLanguages() const
342 {
343         ostringstream languages;
344
345         for (LanguageList::const_iterator cit =
346                     UsedLanguages_.begin();
347              cit != UsedLanguages_.end();
348              ++cit)
349                 languages << (*cit)->babel() << ',';
350         return languages.str();
351 }
352
353
354 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
355 {
356         set<string> encodings;
357         LanguageList::const_iterator it  = UsedLanguages_.begin();
358         LanguageList::const_iterator end = UsedLanguages_.end();
359         for (; it != end; ++it)
360                 // thailatex does not use the inputenc package, but sets up
361                 // babel directly for tis620-0 encoding, therefore we must
362                 // not add tis620-0 to the encoding set.
363                 if ((*it)->encoding()->latexName() != doc_encoding &&
364                     (*it)->encoding()->name() != "tis620-0")
365                         encodings.insert((*it)->encoding()->latexName());
366         return encodings;
367 }
368
369 namespace {
370
371 char const * simplefeatures[] = {
372         "array",
373         "verbatim",
374         "longtable",
375         "rotating",
376         "latexsym",
377         "pifont",
378         "subfigure",
379         "floatflt",
380         "varioref",
381         "prettyref",
382         "float",
383         "booktabs",
384         "dvipost",
385         "fancybox",
386         "calc",
387         "nicefrac",
388         "tipa",
389         "framed",
390         "textcomp",
391 };
392
393 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
394
395 }
396
397
398 string const LaTeXFeatures::getPackages() const
399 {
400         ostringstream packages;
401         TextClass const & tclass = params_.getTextClass();
402
403         //
404         //  These are all the 'simple' includes.  i.e
405         //  packages which we just \usepackage{package}
406         //
407         for (int i = 0; i < nb_simplefeatures; ++i) {
408                 if (mustProvide(simplefeatures[i]))
409                         packages << "\\usepackage{"
410                                  << simplefeatures[i] << "}\n";
411         }
412
413         //
414         // The rest of these packages are somewhat more complicated
415         // than those above.
416         //
417
418         if (mustProvide("amsmath")
419             && params_.use_amsmath != BufferParams::package_off) {
420                 packages << "\\usepackage{amsmath}\n";
421         }
422
423         // wasysym is a simple feature, but it must be after amsmath if both
424         // are used
425         // wasysym redefines some integrals (e.g. iint) from amsmath. That
426         // leads to inconsistent integrals. We only load this package if
427         // esint is used, since esint redefines all relevant integral
428         // symbols from wasysym and amsmath.
429         // See http://bugzilla.lyx.org/show_bug.cgi?id=1942
430         if (mustProvide("wasysym") && isRequired("esint") &&
431             params_.use_esint != BufferParams::package_off)
432                 packages << "\\usepackage{wasysym}\n";
433
434         // color.sty
435         if (mustProvide("color")) {
436                 if (params_.graphicsDriver == "default")
437                         packages << "\\usepackage{color}\n";
438                 else
439                         packages << "\\usepackage["
440                                  << params_.graphicsDriver
441                                  << "]{color}\n";
442         }
443
444         // makeidx.sty
445         if (isRequired("makeidx")) {
446                 if (!tclass.provides("makeidx"))
447                         packages << "\\usepackage{makeidx}\n";
448                 packages << "\\makeindex\n";
449         }
450
451         // graphicx.sty
452         if (mustProvide("graphicx") && params_.graphicsDriver != "none") {
453                 if (params_.graphicsDriver == "default")
454                         packages << "\\usepackage{graphicx}\n";
455                 else
456                         packages << "\\usepackage["
457                                  << params_.graphicsDriver
458                                  << "]{graphicx}\n";
459         }
460         // shadecolor for shaded
461         if (mustProvide("framed")) {
462                 RGBColor c = RGBColor(lcolor.getX11Name(Color::shadedbg));
463                 packages << "\\definecolor{shadecolor}{rgb}{" 
464                         << c.r/255 << ',' << c.g/255 << ',' << c.b/255 << "}\n";
465         }
466
467         // lyxskak.sty --- newer chess support based on skak.sty
468         if (mustProvide("chess")) {
469                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
470         }
471
472         // setspace.sty
473         if ((params_.spacing().getSpace() != Spacing::Single
474              && !params_.spacing().isDefault())
475             || isRequired("setspace")) {
476                 packages << "\\usepackage{setspace}\n";
477         }
478         switch (params_.spacing().getSpace()) {
479         case Spacing::Default:
480         case Spacing::Single:
481                 // we dont use setspace.sty so dont print anything
482                 //packages += "\\singlespacing\n";
483                 break;
484         case Spacing::Onehalf:
485                 packages << "\\onehalfspacing\n";
486                 break;
487         case Spacing::Double:
488                 packages << "\\doublespacing\n";
489                 break;
490         case Spacing::Other:
491                 packages << "\\setstretch{"
492                          << params_.spacing().getValue() << "}\n";
493                 break;
494         }
495
496         // amssymb.sty
497         if (mustProvide("amssymb") 
498             || params_.use_amsmath == BufferParams::package_on)
499                 packages << "\\usepackage{amssymb}\n";
500
501         // esint must be after amsmath and wasysym, since it will redeclare
502         // inconsistent integral symbols
503         if (mustProvide("esint") 
504             && params_.use_esint != BufferParams::package_off)
505                 packages << "\\usepackage{esint}\n";
506
507         // url.sty
508         if (mustProvide("url"))
509                 packages << "\\IfFileExists{url.sty}{\\usepackage{url}}\n"
510                             "                      {\\newcommand{\\url}{\\texttt}}\n";
511
512         // natbib.sty
513         if (mustProvide("natbib")) {
514                 packages << "\\usepackage[";
515                 if (params_.getEngine() == biblio::ENGINE_NATBIB_NUMERICAL) {
516                         packages << "numbers";
517                 } else {
518                         packages << "authoryear";
519                 }
520                 packages << "]{natbib}\n";
521         }
522
523         // jurabib -- we need version 0.6 at least.
524         if (mustProvide("jurabib")) {
525                 packages << "\\usepackage{jurabib}[2004/01/25]\n";
526         }
527
528         // bibtopic -- the dot provides the aux file naming which
529         // LyX can detect.
530         if (mustProvide("bibtopic")) {
531                 packages << "\\usepackage[dot]{bibtopic}\n";
532         }
533
534         if (mustProvide("xy"))
535                 packages << "\\usepackage[all]{xy}\n";
536
537         if (mustProvide("nomencl")) {
538                 // Make it work with the new and old version of the package,
539                 // but don't use the compatibility option since it is
540                 // incompatible to other packages.
541                 packages << "\\usepackage{nomencl}\n"
542                             "% the following is useful when we have the old nomencl.sty package\n"
543                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
544                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
545                             "\\makenomenclature\n";
546         }
547  
548         return packages.str();
549 }
550
551
552 string const LaTeXFeatures::getMacros() const
553 {
554         ostringstream macros;
555
556         if (!preamble_snippets_.empty())
557                 macros << '\n';
558         FeaturesList::const_iterator pit  = preamble_snippets_.begin();
559         FeaturesList::const_iterator pend = preamble_snippets_.end();
560         for (; pit != pend; ++pit) {
561                 macros << *pit << '\n';
562         }
563
564         if (mustProvide("LyX"))
565                 macros << lyx_def << '\n';
566
567         if (mustProvide("lyxline"))
568                 macros << lyxline_def << '\n';
569
570         if (mustProvide("noun"))
571                 macros << noun_def << '\n';
572
573         if (mustProvide("lyxarrow"))
574                 macros << lyxarrow_def << '\n';
575
576         // quotes.
577         if (mustProvide("quotesinglbase"))
578                 macros << quotesinglbase_def << '\n';
579         if (mustProvide("quotedblbase"))
580                 macros << quotedblbase_def << '\n';
581         if (mustProvide("guilsinglleft"))
582                 macros << guilsinglleft_def << '\n';
583         if (mustProvide("guilsinglright"))
584                 macros << guilsinglright_def << '\n';
585         if (mustProvide("guillemotleft"))
586                 macros << guillemotleft_def << '\n';
587         if (mustProvide("guillemotright"))
588                 macros << guillemotright_def << '\n';
589
590         // Math mode
591         if (mustProvide("boldsymbol") && !isRequired("amsmath"))
592                 macros << boldsymbol_def << '\n';
593         if (mustProvide("binom") && !isRequired("amsmath"))
594                 macros << binom_def << '\n';
595         if (mustProvide("mathcircumflex"))
596                 macros << mathcircumflex_def << '\n';
597
598         // other
599         if (mustProvide("ParagraphLeftIndent"))
600                 macros << paragraphleftindent_def;
601         if (mustProvide("NeedLyXFootnoteCode"))
602                 macros << floatingfootnote_def;
603
604         // some problems with tex->html converters
605         if (mustProvide("NeedTabularnewline"))
606                 macros << tabularnewline_def;
607
608         // greyedout environment (note inset)
609         if (mustProvide("lyxgreyedout"))
610                 macros << lyxgreyedout_def;
611
612         if (mustProvide("lyxdot"))
613                 macros << lyxdot_def << '\n';
614
615         // floats
616         getFloatDefinitions(macros);
617
618         return macros.str();
619 }
620
621
622 string const LaTeXFeatures::getBabelOptions() const
623 {
624         ostringstream tmp;
625
626         LanguageList::const_iterator it  = UsedLanguages_.begin();
627         LanguageList::const_iterator end =  UsedLanguages_.end();
628         for (; it != end; ++it)
629                 if (!(*it)->latex_options().empty())
630                         tmp << (*it)->latex_options() << '\n';
631         if (!params_.language->latex_options().empty())
632                 tmp << params_.language->latex_options() << '\n';
633
634         return tmp.str();
635 }
636
637
638 docstring const LaTeXFeatures::getTClassPreamble() const
639 {
640         // the text class specific preamble
641         TextClass const & tclass = params_.getTextClass();
642         odocstringstream tcpreamble;
643
644         tcpreamble << tclass.preamble();
645
646         list<string>::const_iterator cit = usedLayouts_.begin();
647         list<string>::const_iterator end = usedLayouts_.end();
648         for (; cit != end; ++cit) {
649                 tcpreamble << tclass[*cit]->preamble();
650         }
651
652         CharStyles::iterator cs = tclass.charstyles().begin();
653         CharStyles::iterator csend = tclass.charstyles().end();
654         for (; cs != csend; ++cs) {
655                 if (isRequired(cs->name))
656                         tcpreamble << cs->preamble;
657         }
658
659         return tcpreamble.str();
660 }
661
662
663 docstring const LaTeXFeatures::getLyXSGMLEntities() const
664 {
665         // Definition of entities used in the document that are LyX related.
666         odocstringstream entities;
667
668         if (mustProvide("lyxarrow")) {
669                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
670         }
671
672         return entities.str();
673 }
674
675
676 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
677 {
678         odocstringstream sgmlpreamble;
679         // FIXME UNICODE
680         docstring const basename(from_utf8(onlyPath(fname)));
681
682         FileMap::const_iterator end = IncludedFiles_.end();
683         for (FileMap::const_iterator fi = IncludedFiles_.begin();
684              fi != end; ++fi)
685                 // FIXME UNICODE
686                 sgmlpreamble << "\n<!ENTITY " << fi->first
687                              << (isSGMLFilename(fi->second) ? " SYSTEM \"" : " \"")
688                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
689
690         return sgmlpreamble.str();
691 }
692
693
694 void LaTeXFeatures::showStruct() const {
695         lyxerr << "LyX needs the following commands when LaTeXing:"
696                << "\n***** Packages:" << getPackages()
697                << "\n***** Macros:" << getMacros()
698                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
699                << "\n***** done." << endl;
700 }
701
702
703 Buffer const & LaTeXFeatures::buffer() const
704 {
705         return *buffer_;
706 }
707
708
709 void LaTeXFeatures::setBuffer(Buffer const & buffer)
710 {
711         buffer_ = &buffer;
712 }
713
714
715 BufferParams const & LaTeXFeatures::bufferParams() const
716 {
717         return params_;
718 }
719
720
721 void LaTeXFeatures::getFloatDefinitions(ostream & os) const
722 {
723         FloatList const & floats = params_.getTextClass().floats();
724
725         // Here we will output the code to create the needed float styles.
726         // We will try to do this as minimal as possible.
727         // \floatstyle{ruled}
728         // \newfloat{algorithm}{htbp}{loa}
729         // \floatname{algorithm}{Algorithm}
730         UsedFloats::const_iterator cit = usedFloats_.begin();
731         UsedFloats::const_iterator end = usedFloats_.end();
732         // ostringstream floats;
733         for (; cit != end; ++cit) {
734                 Floating const & fl = floats.getType((*cit));
735
736                 // For builtin floats we do nothing.
737                 if (fl.builtin()) continue;
738
739                 // We have to special case "table" and "figure"
740                 if (fl.type() == "tabular" || fl.type() == "figure") {
741                         // Output code to modify "table" or "figure"
742                         // but only if builtin == false
743                         // and that have to be true at this point in the
744                         // function.
745                         string const type = fl.type();
746                         string const placement = fl.placement();
747                         string const style = fl.style();
748                         if (!style.empty()) {
749                                 os << "\\floatstyle{" << style << "}\n"
750                                    << "\\restylefloat{" << type << "}\n";
751                         }
752                         if (!placement.empty()) {
753                                 os << "\\floatplacement{" << type << "}{"
754                                    << placement << "}\n";
755                         }
756                 } else {
757                         // The other non builtin floats.
758
759                         string const type = fl.type();
760                         string const placement = fl.placement();
761                         string const ext = fl.ext();
762                         string const within = fl.within();
763                         string const style = fl.style();
764                         string const name = fl.name();
765                         os << "\\floatstyle{" << style << "}\n"
766                            << "\\newfloat{" << type << "}{" << placement
767                            << "}{" << ext << '}';
768                         if (!within.empty())
769                                 os << '[' << within << ']';
770                         os << '\n'
771                            << "\\floatname{" << type << "}{"
772                            << name << "}\n";
773
774                         // What missing here is to code to minimalize the code
775                         // output so that the same floatstyle will not be
776                         // used several times, when the same style is still in
777                         // effect. (Lgb)
778                 }
779         }
780 }
781
782
783 } // namespace lyx