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