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