]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
Cleanup in order to better understand bug 3043 and 3561.
[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                  !bufferParams().language->babel().empty()) ||
196                 this->hasLanguages();
197 }
198
199
200 void LaTeXFeatures::require(string const & name)
201 {
202         if (isRequired(name))
203                 return;
204
205         features_.push_back(name);
206 }
207
208
209 void LaTeXFeatures::getAvailable()
210 {
211         Lexer lex(0, 0);
212         support::FileName const real_file = libFileSearch("", "packages.lst");
213
214         if (real_file.empty())
215                 return;
216
217         lex.setFile(real_file);
218
219         if (!lex.isOK())
220                 return;
221
222         // Make sure that we are clean
223         packages_.clear();
224
225         bool finished = false;
226         // Parse config-file
227         while (lex.isOK() && !finished) {
228                 switch (lex.lex()) {
229                 case Lexer::LEX_FEOF:
230                         finished = true;
231                         break;
232                 default:
233                         string const name = lex.getString();
234                         PackagesList::const_iterator begin = packages_.begin();
235                         PackagesList::const_iterator end   = packages_.end();
236                         if (find(begin, end, name) == end)
237                                 packages_.push_back(name);
238                 }
239         }
240 }
241
242
243 void LaTeXFeatures::useLayout(string const & layoutname)
244 {
245         // Some code to avoid loops in dependency definition
246         static int level = 0;
247         const int maxlevel = 30;
248         if (level > maxlevel) {
249                 lyxerr << "LaTeXFeatures::useLayout: maximum level of "
250                        << "recursion attained by layout "
251                        << layoutname << endl;
252                 return;
253         }
254
255         TextClass const & tclass = params_.getTextClass();
256         if (tclass.hasLayout(layoutname)) {
257                 // Is this layout already in usedLayouts?
258                 list<string>::const_iterator cit = usedLayouts_.begin();
259                 list<string>::const_iterator end = usedLayouts_.end();
260                 for (; cit != end; ++cit) {
261                         if (layoutname == *cit)
262                                 return;
263                 }
264
265                 Layout_ptr const & lyt = tclass[layoutname];
266                 if (!lyt->depends_on().empty()) {
267                         ++level;
268                         useLayout(lyt->depends_on());
269                         --level;
270                 }
271                 usedLayouts_.push_back(layoutname);
272         } else {
273                 lyxerr << "LaTeXFeatures::useLayout: layout `"
274                        << layoutname << "' does not exist in this class"
275                        << endl;
276         }
277
278         --level;
279 }
280
281
282 bool LaTeXFeatures::isRequired(string const & name) const
283 {
284         return find(features_.begin(), features_.end(), name) != features_.end();
285 }
286
287
288 bool LaTeXFeatures::mustProvide(string const & name) const
289 {
290         return isRequired(name) && !params_.getTextClass().provides(name);
291 }
292
293
294 bool LaTeXFeatures::isAvailable(string const & name)
295 {
296         if (packages_.empty())
297                 getAvailable();
298         return find(packages_.begin(), packages_.end(), name) != packages_.end();
299 }
300
301
302 void LaTeXFeatures::addPreambleSnippet(string const & preamble)
303 {
304         FeaturesList::const_iterator begin = preamble_snippets_.begin();
305         FeaturesList::const_iterator end   = preamble_snippets_.end();
306         if (find(begin, end, preamble) == end)
307                 preamble_snippets_.push_back(preamble);
308 }
309
310
311 void LaTeXFeatures::useFloat(string const & name)
312 {
313         usedFloats_.insert(name);
314         // We only need float.sty if we use non builtin floats, or if we
315         // use the "H" modifier. This includes modified table and
316         // figure floats. (Lgb)
317         Floating const & fl = params_.getTextClass().floats().getType(name);
318         if (!fl.type().empty() && !fl.builtin()) {
319                 require("float");
320         }
321 }
322
323
324 void LaTeXFeatures::useLanguage(Language const * lang)
325 {
326         if (!lang->babel().empty())
327                 UsedLanguages_.insert(lang);
328 }
329
330
331 void LaTeXFeatures::includeFile(docstring const & key, string const & name)
332 {
333         IncludedFiles_[key] = name;
334 }
335
336
337 bool LaTeXFeatures::hasLanguages() const
338 {
339         return !UsedLanguages_.empty();
340 }
341
342
343 string LaTeXFeatures::getLanguages() const
344 {
345         ostringstream languages;
346
347         LanguageList::const_iterator const begin = UsedLanguages_.begin();
348         for (LanguageList::const_iterator cit = begin;
349              cit != UsedLanguages_.end();
350              ++cit) {
351                 if (cit != begin)
352                         languages << ',';
353                 languages << (*cit)->babel();
354         }
355         return languages.str();
356 }
357
358
359 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
360 {
361         // This does only find encodings of languages supported by babel, but
362         // that does not matter since we don't have a language with an
363         // encoding supported by inputenc but without babel support.
364         set<string> encodings;
365         LanguageList::const_iterator it  = UsedLanguages_.begin();
366         LanguageList::const_iterator end = UsedLanguages_.end();
367         for (; it != end; ++it)
368                 if ((*it)->encoding()->latexName() != doc_encoding &&
369                     (*it)->encoding()->package() == Encoding::inputenc)
370                         encodings.insert((*it)->encoding()->latexName());
371         return encodings;
372 }
373
374 namespace {
375
376 char const * simplefeatures[] = {
377         "array",
378         "verbatim",
379         "longtable",
380         "rotating",
381         "latexsym",
382         "pifont",
383         "subfigure",
384         "floatflt",
385         "varioref",
386         "prettyref",
387         "float",
388         "booktabs",
389         "dvipost",
390         "fancybox",
391         "calc",
392         "nicefrac",
393         "tipa",
394         "framed",
395         "textcomp",
396 };
397
398 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
399
400 }
401
402
403 string const LaTeXFeatures::getPackages() const
404 {
405         ostringstream packages;
406         TextClass const & tclass = params_.getTextClass();
407
408         //
409         //  These are all the 'simple' includes.  i.e
410         //  packages which we just \usepackage{package}
411         //
412         for (int i = 0; i < nb_simplefeatures; ++i) {
413                 if (mustProvide(simplefeatures[i]))
414                         packages << "\\usepackage{"
415                                  << simplefeatures[i] << "}\n";
416         }
417
418         //
419         // The rest of these packages are somewhat more complicated
420         // than those above.
421         //
422
423         if (mustProvide("amsmath")
424             && params_.use_amsmath != BufferParams::package_off) {
425                 packages << "\\usepackage{amsmath}\n";
426         }
427
428         // wasysym is a simple feature, but it must be after amsmath if both
429         // are used
430         // wasysym redefines some integrals (e.g. iint) from amsmath. That
431         // leads to inconsistent integrals. We only load this package if
432         // esint is used, since esint redefines all relevant integral
433         // symbols from wasysym and amsmath.
434         // See http://bugzilla.lyx.org/show_bug.cgi?id=1942
435         if (mustProvide("wasysym") && isRequired("esint") &&
436             params_.use_esint != BufferParams::package_off)
437                 packages << "\\usepackage{wasysym}\n";
438
439         // color.sty
440         if (mustProvide("color")) {
441                 if (params_.graphicsDriver == "default")
442                         packages << "\\usepackage{color}\n";
443                 else
444                         packages << "\\usepackage["
445                                  << params_.graphicsDriver
446                                  << "]{color}\n";
447         }
448
449         // makeidx.sty
450         if (isRequired("makeidx")) {
451                 if (!tclass.provides("makeidx"))
452                         packages << "\\usepackage{makeidx}\n";
453                 packages << "\\makeindex\n";
454         }
455
456         // graphicx.sty
457         if (mustProvide("graphicx") && params_.graphicsDriver != "none") {
458                 if (params_.graphicsDriver == "default")
459                         packages << "\\usepackage{graphicx}\n";
460                 else
461                         packages << "\\usepackage["
462                                  << params_.graphicsDriver
463                                  << "]{graphicx}\n";
464         }
465         // shadecolor for shaded
466         if (mustProvide("framed")) {
467                 RGBColor c = RGBColor(lcolor.getX11Name(Color::shadedbg));
468                 packages << "\\definecolor{shadecolor}{rgb}{" 
469                         << c.r/255 << ',' << c.g/255 << ',' << c.b/255 << "}\n";
470         }
471
472         // lyxskak.sty --- newer chess support based on skak.sty
473         if (mustProvide("chess")) {
474                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
475         }
476
477         // setspace.sty
478         if ((params_.spacing().getSpace() != Spacing::Single
479              && !params_.spacing().isDefault())
480             || isRequired("setspace")) {
481                 packages << "\\usepackage{setspace}\n";
482         }
483         switch (params_.spacing().getSpace()) {
484         case Spacing::Default:
485         case Spacing::Single:
486                 // we dont use setspace.sty so dont print anything
487                 //packages += "\\singlespacing\n";
488                 break;
489         case Spacing::Onehalf:
490                 packages << "\\onehalfspacing\n";
491                 break;
492         case Spacing::Double:
493                 packages << "\\doublespacing\n";
494                 break;
495         case Spacing::Other:
496                 packages << "\\setstretch{"
497                          << params_.spacing().getValue() << "}\n";
498                 break;
499         }
500
501         // amssymb.sty
502         if (mustProvide("amssymb") 
503             || params_.use_amsmath == BufferParams::package_on)
504                 packages << "\\usepackage{amssymb}\n";
505
506         // esint must be after amsmath and wasysym, since it will redeclare
507         // inconsistent integral symbols
508         if (mustProvide("esint") 
509             && params_.use_esint != BufferParams::package_off)
510                 packages << "\\usepackage{esint}\n";
511
512         // url.sty
513         if (mustProvide("url"))
514                 packages << "\\IfFileExists{url.sty}{\\usepackage{url}}\n"
515                             "                      {\\newcommand{\\url}{\\texttt}}\n";
516
517         // natbib.sty
518         if (mustProvide("natbib")) {
519                 packages << "\\usepackage[";
520                 if (params_.getEngine() == biblio::ENGINE_NATBIB_NUMERICAL) {
521                         packages << "numbers";
522                 } else {
523                         packages << "authoryear";
524                 }
525                 packages << "]{natbib}\n";
526         }
527
528         // jurabib -- we need version 0.6 at least.
529         if (mustProvide("jurabib")) {
530                 packages << "\\usepackage{jurabib}[2004/01/25]\n";
531         }
532
533         // bibtopic -- the dot provides the aux file naming which
534         // LyX can detect.
535         if (mustProvide("bibtopic")) {
536                 packages << "\\usepackage[dot]{bibtopic}\n";
537         }
538
539         if (mustProvide("xy"))
540                 packages << "\\usepackage[all]{xy}\n";
541
542         if (mustProvide("nomencl")) {
543                 // Make it work with the new and old version of the package,
544                 // but don't use the compatibility option since it is
545                 // incompatible to other packages.
546                 packages << "\\usepackage{nomencl}\n"
547                             "% the following is useful when we have the old nomencl.sty package\n"
548                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
549                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
550                             "\\makenomenclature\n";
551         }
552  
553         return packages.str();
554 }
555
556
557 string const LaTeXFeatures::getMacros() const
558 {
559         ostringstream macros;
560
561         if (!preamble_snippets_.empty())
562                 macros << '\n';
563         FeaturesList::const_iterator pit  = preamble_snippets_.begin();
564         FeaturesList::const_iterator pend = preamble_snippets_.end();
565         for (; pit != pend; ++pit) {
566                 macros << *pit << '\n';
567         }
568
569         if (mustProvide("LyX"))
570                 macros << lyx_def << '\n';
571
572         if (mustProvide("lyxline"))
573                 macros << lyxline_def << '\n';
574
575         if (mustProvide("noun"))
576                 macros << noun_def << '\n';
577
578         if (mustProvide("lyxarrow"))
579                 macros << lyxarrow_def << '\n';
580
581         // quotes.
582         if (mustProvide("quotesinglbase"))
583                 macros << quotesinglbase_def << '\n';
584         if (mustProvide("quotedblbase"))
585                 macros << quotedblbase_def << '\n';
586         if (mustProvide("guilsinglleft"))
587                 macros << guilsinglleft_def << '\n';
588         if (mustProvide("guilsinglright"))
589                 macros << guilsinglright_def << '\n';
590         if (mustProvide("guillemotleft"))
591                 macros << guillemotleft_def << '\n';
592         if (mustProvide("guillemotright"))
593                 macros << guillemotright_def << '\n';
594
595         // Math mode
596         if (mustProvide("boldsymbol") && !isRequired("amsmath"))
597                 macros << boldsymbol_def << '\n';
598         if (mustProvide("binom") && !isRequired("amsmath"))
599                 macros << binom_def << '\n';
600         if (mustProvide("mathcircumflex"))
601                 macros << mathcircumflex_def << '\n';
602
603         // other
604         if (mustProvide("ParagraphLeftIndent"))
605                 macros << paragraphleftindent_def;
606         if (mustProvide("NeedLyXFootnoteCode"))
607                 macros << floatingfootnote_def;
608
609         // some problems with tex->html converters
610         if (mustProvide("NeedTabularnewline"))
611                 macros << tabularnewline_def;
612
613         // greyedout environment (note inset)
614         if (mustProvide("lyxgreyedout"))
615                 macros << lyxgreyedout_def;
616
617         if (mustProvide("lyxdot"))
618                 macros << lyxdot_def << '\n';
619
620         // floats
621         getFloatDefinitions(macros);
622
623         return macros.str();
624 }
625
626
627 string const LaTeXFeatures::getBabelOptions() const
628 {
629         ostringstream tmp;
630
631         LanguageList::const_iterator it  = UsedLanguages_.begin();
632         LanguageList::const_iterator end =  UsedLanguages_.end();
633         for (; it != end; ++it)
634                 if (!(*it)->latex_options().empty())
635                         tmp << (*it)->latex_options() << '\n';
636         if (!params_.language->latex_options().empty())
637                 tmp << params_.language->latex_options() << '\n';
638
639         return tmp.str();
640 }
641
642
643 docstring const LaTeXFeatures::getTClassPreamble() const
644 {
645         // the text class specific preamble
646         TextClass const & tclass = params_.getTextClass();
647         odocstringstream tcpreamble;
648
649         tcpreamble << tclass.preamble();
650
651         list<string>::const_iterator cit = usedLayouts_.begin();
652         list<string>::const_iterator end = usedLayouts_.end();
653         for (; cit != end; ++cit) {
654                 tcpreamble << tclass[*cit]->preamble();
655         }
656
657         CharStyles::iterator cs = tclass.charstyles().begin();
658         CharStyles::iterator csend = tclass.charstyles().end();
659         for (; cs != csend; ++cs) {
660                 if (isRequired(cs->name))
661                         tcpreamble << cs->preamble;
662         }
663
664         return tcpreamble.str();
665 }
666
667
668 docstring const LaTeXFeatures::getLyXSGMLEntities() const
669 {
670         // Definition of entities used in the document that are LyX related.
671         odocstringstream entities;
672
673         if (mustProvide("lyxarrow")) {
674                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
675         }
676
677         return entities.str();
678 }
679
680
681 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
682 {
683         odocstringstream sgmlpreamble;
684         // FIXME UNICODE
685         docstring const basename(from_utf8(onlyPath(fname)));
686
687         FileMap::const_iterator end = IncludedFiles_.end();
688         for (FileMap::const_iterator fi = IncludedFiles_.begin();
689              fi != end; ++fi)
690                 // FIXME UNICODE
691                 sgmlpreamble << "\n<!ENTITY " << fi->first
692                              << (isSGMLFilename(fi->second) ? " SYSTEM \"" : " \"")
693                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
694
695         return sgmlpreamble.str();
696 }
697
698
699 void LaTeXFeatures::showStruct() const {
700         lyxerr << "LyX needs the following commands when LaTeXing:"
701                << "\n***** Packages:" << getPackages()
702                << "\n***** Macros:" << getMacros()
703                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
704                << "\n***** done." << endl;
705 }
706
707
708 Buffer const & LaTeXFeatures::buffer() const
709 {
710         return *buffer_;
711 }
712
713
714 void LaTeXFeatures::setBuffer(Buffer const & buffer)
715 {
716         buffer_ = &buffer;
717 }
718
719
720 BufferParams const & LaTeXFeatures::bufferParams() const
721 {
722         return params_;
723 }
724
725
726 void LaTeXFeatures::getFloatDefinitions(ostream & os) const
727 {
728         FloatList const & floats = params_.getTextClass().floats();
729
730         // Here we will output the code to create the needed float styles.
731         // We will try to do this as minimal as possible.
732         // \floatstyle{ruled}
733         // \newfloat{algorithm}{htbp}{loa}
734         // \floatname{algorithm}{Algorithm}
735         UsedFloats::const_iterator cit = usedFloats_.begin();
736         UsedFloats::const_iterator end = usedFloats_.end();
737         // ostringstream floats;
738         for (; cit != end; ++cit) {
739                 Floating const & fl = floats.getType((*cit));
740
741                 // For builtin floats we do nothing.
742                 if (fl.builtin()) continue;
743
744                 // We have to special case "table" and "figure"
745                 if (fl.type() == "tabular" || fl.type() == "figure") {
746                         // Output code to modify "table" or "figure"
747                         // but only if builtin == false
748                         // and that have to be true at this point in the
749                         // function.
750                         string const type = fl.type();
751                         string const placement = fl.placement();
752                         string const style = fl.style();
753                         if (!style.empty()) {
754                                 os << "\\floatstyle{" << style << "}\n"
755                                    << "\\restylefloat{" << type << "}\n";
756                         }
757                         if (!placement.empty()) {
758                                 os << "\\floatplacement{" << type << "}{"
759                                    << placement << "}\n";
760                         }
761                 } else {
762                         // The other non builtin floats.
763
764                         string const type = fl.type();
765                         string const placement = fl.placement();
766                         string const ext = fl.ext();
767                         string const within = fl.within();
768                         string const style = fl.style();
769                         string const name = fl.name();
770                         os << "\\floatstyle{" << style << "}\n"
771                            << "\\newfloat{" << type << "}{" << placement
772                            << "}{" << ext << '}';
773                         if (!within.empty())
774                                 os << '[' << within << ']';
775                         os << '\n'
776                            << "\\floatname{" << type << "}{"
777                            << name << "}\n";
778
779                         // What missing here is to code to minimalize the code
780                         // output so that the same floatstyle will not be
781                         // used several times, when the same style is still in
782                         // effect. (Lgb)
783                 }
784         }
785 }
786
787
788 } // namespace lyx