]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
a20dc683929d5bba61ed65aa816c135f9f6ece7a
[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         for (LanguageList::const_iterator cit =
348                     UsedLanguages_.begin();
349              cit != UsedLanguages_.end();
350              ++cit)
351                 languages << (*cit)->babel() << ',';
352         return languages.str();
353 }
354
355
356 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
357 {
358         set<string> encodings;
359         LanguageList::const_iterator it  = UsedLanguages_.begin();
360         LanguageList::const_iterator end = UsedLanguages_.end();
361         for (; it != end; ++it)
362                 // thailatex does not use the inputenc package, but sets up
363                 // babel directly for tis620-0 encoding, therefore we must
364                 // not add tis620-0 to the encoding set.
365                 if ((*it)->encoding()->latexName() != doc_encoding &&
366                     (*it)->encoding()->name() != "tis620-0")
367                         encodings.insert((*it)->encoding()->latexName());
368         return encodings;
369 }
370
371 namespace {
372
373 char const * simplefeatures[] = {
374         "array",
375         "verbatim",
376         "longtable",
377         "rotating",
378         "latexsym",
379         "pifont",
380         "subfigure",
381         "floatflt",
382         "varioref",
383         "prettyref",
384         "float",
385         "booktabs",
386         "dvipost",
387         "fancybox",
388         "calc",
389         "nicefrac",
390         "tipa",
391         "framed",
392         "textcomp",
393 };
394
395 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
396
397 }
398
399
400 string const LaTeXFeatures::getPackages() const
401 {
402         ostringstream packages;
403         TextClass const & tclass = params_.getTextClass();
404
405         //
406         //  These are all the 'simple' includes.  i.e
407         //  packages which we just \usepackage{package}
408         //
409         for (int i = 0; i < nb_simplefeatures; ++i) {
410                 if (mustProvide(simplefeatures[i]))
411                         packages << "\\usepackage{"
412                                  << simplefeatures[i] << "}\n";
413         }
414
415         //
416         // The rest of these packages are somewhat more complicated
417         // than those above.
418         //
419
420         if (mustProvide("amsmath")
421             && params_.use_amsmath != BufferParams::package_off) {
422                 packages << "\\usepackage{amsmath}\n";
423         }
424
425         // wasysym is a simple feature, but it must be after amsmath if both
426         // are used
427         // wasysym redefines some integrals (e.g. iint) from amsmath. That
428         // leads to inconsistent integrals. We only load this package if
429         // esint is used, since esint redefines all relevant integral
430         // symbols from wasysym and amsmath.
431         // See http://bugzilla.lyx.org/show_bug.cgi?id=1942
432         if (mustProvide("wasysym") && isRequired("esint") &&
433             params_.use_esint != BufferParams::package_off)
434                 packages << "\\usepackage{wasysym}\n";
435
436         // color.sty
437         if (mustProvide("color")) {
438                 if (params_.graphicsDriver == "default")
439                         packages << "\\usepackage{color}\n";
440                 else
441                         packages << "\\usepackage["
442                                  << params_.graphicsDriver
443                                  << "]{color}\n";
444         }
445
446         // makeidx.sty
447         if (isRequired("makeidx")) {
448                 if (!tclass.provides("makeidx"))
449                         packages << "\\usepackage{makeidx}\n";
450                 packages << "\\makeindex\n";
451         }
452
453         // graphicx.sty
454         if (mustProvide("graphicx") && params_.graphicsDriver != "none") {
455                 if (params_.graphicsDriver == "default")
456                         packages << "\\usepackage{graphicx}\n";
457                 else
458                         packages << "\\usepackage["
459                                  << params_.graphicsDriver
460                                  << "]{graphicx}\n";
461         }
462         // shadecolor for shaded
463         if (mustProvide("framed")) {
464                 RGBColor c = RGBColor(lcolor.getX11Name(Color::shadedbg));
465                 packages << "\\definecolor{shadecolor}{rgb}{" 
466                         << c.r/255 << ',' << c.g/255 << ',' << c.b/255 << "}\n";
467         }
468
469         // lyxskak.sty --- newer chess support based on skak.sty
470         if (mustProvide("chess")) {
471                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
472         }
473
474         // setspace.sty
475         if ((params_.spacing().getSpace() != Spacing::Single
476              && !params_.spacing().isDefault())
477             || isRequired("setspace")) {
478                 packages << "\\usepackage{setspace}\n";
479         }
480         switch (params_.spacing().getSpace()) {
481         case Spacing::Default:
482         case Spacing::Single:
483                 // we dont use setspace.sty so dont print anything
484                 //packages += "\\singlespacing\n";
485                 break;
486         case Spacing::Onehalf:
487                 packages << "\\onehalfspacing\n";
488                 break;
489         case Spacing::Double:
490                 packages << "\\doublespacing\n";
491                 break;
492         case Spacing::Other:
493                 packages << "\\setstretch{"
494                          << params_.spacing().getValue() << "}\n";
495                 break;
496         }
497
498         // amssymb.sty
499         if (mustProvide("amssymb") 
500             || params_.use_amsmath == BufferParams::package_on)
501                 packages << "\\usepackage{amssymb}\n";
502
503         // esint must be after amsmath and wasysym, since it will redeclare
504         // inconsistent integral symbols
505         if (mustProvide("esint") 
506             && params_.use_esint != BufferParams::package_off)
507                 packages << "\\usepackage{esint}\n";
508
509         // url.sty
510         if (mustProvide("url"))
511                 packages << "\\IfFileExists{url.sty}{\\usepackage{url}}\n"
512                             "                      {\\newcommand{\\url}{\\texttt}}\n";
513
514         // natbib.sty
515         if (mustProvide("natbib")) {
516                 packages << "\\usepackage[";
517                 if (params_.getEngine() == biblio::ENGINE_NATBIB_NUMERICAL) {
518                         packages << "numbers";
519                 } else {
520                         packages << "authoryear";
521                 }
522                 packages << "]{natbib}\n";
523         }
524
525         // jurabib -- we need version 0.6 at least.
526         if (mustProvide("jurabib")) {
527                 packages << "\\usepackage{jurabib}[2004/01/25]\n";
528         }
529
530         // bibtopic -- the dot provides the aux file naming which
531         // LyX can detect.
532         if (mustProvide("bibtopic")) {
533                 packages << "\\usepackage[dot]{bibtopic}\n";
534         }
535
536         if (mustProvide("xy"))
537                 packages << "\\usepackage[all]{xy}\n";
538
539         if (mustProvide("nomencl")) {
540                 // Make it work with the new and old version of the package,
541                 // but don't use the compatibility option since it is
542                 // incompatible to other packages.
543                 packages << "\\usepackage{nomencl}\n"
544                             "% the following is useful when we have the old nomencl.sty package\n"
545                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
546                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
547                             "\\makenomenclature\n";
548         }
549  
550         return packages.str();
551 }
552
553
554 string const LaTeXFeatures::getMacros() const
555 {
556         ostringstream macros;
557
558         if (!preamble_snippets_.empty())
559                 macros << '\n';
560         FeaturesList::const_iterator pit  = preamble_snippets_.begin();
561         FeaturesList::const_iterator pend = preamble_snippets_.end();
562         for (; pit != pend; ++pit) {
563                 macros << *pit << '\n';
564         }
565
566         if (mustProvide("LyX"))
567                 macros << lyx_def << '\n';
568
569         if (mustProvide("lyxline"))
570                 macros << lyxline_def << '\n';
571
572         if (mustProvide("noun"))
573                 macros << noun_def << '\n';
574
575         if (mustProvide("lyxarrow"))
576                 macros << lyxarrow_def << '\n';
577
578         // quotes.
579         if (mustProvide("quotesinglbase"))
580                 macros << quotesinglbase_def << '\n';
581         if (mustProvide("quotedblbase"))
582                 macros << quotedblbase_def << '\n';
583         if (mustProvide("guilsinglleft"))
584                 macros << guilsinglleft_def << '\n';
585         if (mustProvide("guilsinglright"))
586                 macros << guilsinglright_def << '\n';
587         if (mustProvide("guillemotleft"))
588                 macros << guillemotleft_def << '\n';
589         if (mustProvide("guillemotright"))
590                 macros << guillemotright_def << '\n';
591
592         // Math mode
593         if (mustProvide("boldsymbol") && !isRequired("amsmath"))
594                 macros << boldsymbol_def << '\n';
595         if (mustProvide("binom") && !isRequired("amsmath"))
596                 macros << binom_def << '\n';
597         if (mustProvide("mathcircumflex"))
598                 macros << mathcircumflex_def << '\n';
599
600         // other
601         if (mustProvide("ParagraphLeftIndent"))
602                 macros << paragraphleftindent_def;
603         if (mustProvide("NeedLyXFootnoteCode"))
604                 macros << floatingfootnote_def;
605
606         // some problems with tex->html converters
607         if (mustProvide("NeedTabularnewline"))
608                 macros << tabularnewline_def;
609
610         // greyedout environment (note inset)
611         if (mustProvide("lyxgreyedout"))
612                 macros << lyxgreyedout_def;
613
614         if (mustProvide("lyxdot"))
615                 macros << lyxdot_def << '\n';
616
617         // floats
618         getFloatDefinitions(macros);
619
620         return macros.str();
621 }
622
623
624 string const LaTeXFeatures::getBabelOptions() const
625 {
626         ostringstream tmp;
627
628         LanguageList::const_iterator it  = UsedLanguages_.begin();
629         LanguageList::const_iterator end =  UsedLanguages_.end();
630         for (; it != end; ++it)
631                 if (!(*it)->latex_options().empty())
632                         tmp << (*it)->latex_options() << '\n';
633         if (!params_.language->latex_options().empty())
634                 tmp << params_.language->latex_options() << '\n';
635
636         return tmp.str();
637 }
638
639
640 docstring const LaTeXFeatures::getTClassPreamble() const
641 {
642         // the text class specific preamble
643         TextClass const & tclass = params_.getTextClass();
644         odocstringstream tcpreamble;
645
646         tcpreamble << tclass.preamble();
647
648         list<string>::const_iterator cit = usedLayouts_.begin();
649         list<string>::const_iterator end = usedLayouts_.end();
650         for (; cit != end; ++cit) {
651                 tcpreamble << tclass[*cit]->preamble();
652         }
653
654         CharStyles::iterator cs = tclass.charstyles().begin();
655         CharStyles::iterator csend = tclass.charstyles().end();
656         for (; cs != csend; ++cs) {
657                 if (isRequired(cs->name))
658                         tcpreamble << cs->preamble;
659         }
660
661         return tcpreamble.str();
662 }
663
664
665 docstring const LaTeXFeatures::getLyXSGMLEntities() const
666 {
667         // Definition of entities used in the document that are LyX related.
668         odocstringstream entities;
669
670         if (mustProvide("lyxarrow")) {
671                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
672         }
673
674         return entities.str();
675 }
676
677
678 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
679 {
680         odocstringstream sgmlpreamble;
681         // FIXME UNICODE
682         docstring const basename(from_utf8(onlyPath(fname)));
683
684         FileMap::const_iterator end = IncludedFiles_.end();
685         for (FileMap::const_iterator fi = IncludedFiles_.begin();
686              fi != end; ++fi)
687                 // FIXME UNICODE
688                 sgmlpreamble << "\n<!ENTITY " << fi->first
689                              << (isSGMLFilename(fi->second) ? " SYSTEM \"" : " \"")
690                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
691
692         return sgmlpreamble.str();
693 }
694
695
696 void LaTeXFeatures::showStruct() const {
697         lyxerr << "LyX needs the following commands when LaTeXing:"
698                << "\n***** Packages:" << getPackages()
699                << "\n***** Macros:" << getMacros()
700                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
701                << "\n***** done." << endl;
702 }
703
704
705 Buffer const & LaTeXFeatures::buffer() const
706 {
707         return *buffer_;
708 }
709
710
711 void LaTeXFeatures::setBuffer(Buffer const & buffer)
712 {
713         buffer_ = &buffer;
714 }
715
716
717 BufferParams const & LaTeXFeatures::bufferParams() const
718 {
719         return params_;
720 }
721
722
723 void LaTeXFeatures::getFloatDefinitions(ostream & os) const
724 {
725         FloatList const & floats = params_.getTextClass().floats();
726
727         // Here we will output the code to create the needed float styles.
728         // We will try to do this as minimal as possible.
729         // \floatstyle{ruled}
730         // \newfloat{algorithm}{htbp}{loa}
731         // \floatname{algorithm}{Algorithm}
732         UsedFloats::const_iterator cit = usedFloats_.begin();
733         UsedFloats::const_iterator end = usedFloats_.end();
734         // ostringstream floats;
735         for (; cit != end; ++cit) {
736                 Floating const & fl = floats.getType((*cit));
737
738                 // For builtin floats we do nothing.
739                 if (fl.builtin()) continue;
740
741                 // We have to special case "table" and "figure"
742                 if (fl.type() == "tabular" || fl.type() == "figure") {
743                         // Output code to modify "table" or "figure"
744                         // but only if builtin == false
745                         // and that have to be true at this point in the
746                         // function.
747                         string const type = fl.type();
748                         string const placement = fl.placement();
749                         string const style = fl.style();
750                         if (!style.empty()) {
751                                 os << "\\floatstyle{" << style << "}\n"
752                                    << "\\restylefloat{" << type << "}\n";
753                         }
754                         if (!placement.empty()) {
755                                 os << "\\floatplacement{" << type << "}{"
756                                    << placement << "}\n";
757                         }
758                 } else {
759                         // The other non builtin floats.
760
761                         string const type = fl.type();
762                         string const placement = fl.placement();
763                         string const ext = fl.ext();
764                         string const within = fl.within();
765                         string const style = fl.style();
766                         string const name = fl.name();
767                         os << "\\floatstyle{" << style << "}\n"
768                            << "\\newfloat{" << type << "}{" << placement
769                            << "}{" << ext << '}';
770                         if (!within.empty())
771                                 os << '[' << within << ']';
772                         os << '\n'
773                            << "\\floatname{" << type << "}{"
774                            << name << "}\n";
775
776                         // What missing here is to code to minimalize the code
777                         // output so that the same floatstyle will not be
778                         // used several times, when the same style is still in
779                         // effect. (Lgb)
780                 }
781         }
782 }
783
784
785 } // namespace lyx