]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
Help avoiding shortcut clashes by discriminating strings.
[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 "Buffer.h"
20 #include "BufferParams.h"
21 #include "ColorSet.h"
22 #include "Converter.h"
23 #include "Encoding.h"
24 #include "Floating.h"
25 #include "FloatList.h"
26 #include "Language.h"
27 #include "Layout.h"
28 #include "Lexer.h"
29 #include "LyXRC.h"
30 #include "TextClass.h"
31
32 #include "insets/InsetLayout.h"
33
34 #include "support/debug.h"
35 #include "support/docstream.h"
36 #include "support/FileName.h"
37 #include "support/filetools.h"
38 #include "support/gettext.h"
39 #include "support/lstrings.h"
40
41 #include <algorithm>
42
43
44 using namespace std;
45 using namespace lyx::support;
46
47
48 namespace lyx {
49
50 /////////////////////////////////////////////////////////////////////
51 //
52 // Strings
53 //
54 /////////////////////////////////////////////////////////////////////
55
56 //\NeedsTeXFormat{LaTeX2e}
57 //\ProvidesPackage{lyx}[1996/01/11 LLE v0.2 (LyX LaTeX Extensions)]
58 //\message{LyX LaTeX Extensions (LLE v0.2) of 11-Jan-1996.}
59
60 static docstring const lyx_def = from_ascii(
61         "\\providecommand{\\LyX}{L\\kern-.1667em\\lower.25em\\hbox{Y}\\kern-.125emX\\@}");
62
63 static docstring const lyx_hyperref_def = from_ascii(
64         "\\providecommand{\\LyX}{\\texorpdfstring%\n"
65         "  {L\\kern-.1667em\\lower.25em\\hbox{Y}\\kern-.125emX\\@}\n"
66         "  {LyX}}");
67
68 static docstring const noun_def = from_ascii(
69         "\\newcommand{\\noun}[1]{\\textsc{#1}}");
70
71 static docstring const lyxarrow_def = from_ascii(
72         "\\DeclareRobustCommand*{\\lyxarrow}{%\n"
73         "\\@ifstar\n"
74         "{\\leavevmode\\,$\\triangleleft$\\,\\allowbreak}\n"
75         "{\\leavevmode\\,$\\triangleright$\\,\\allowbreak}}");
76
77 // for quotes without babel. This does not give perfect results, but
78 // anybody serious about non-english quotes should use babel (JMarc).
79
80 static docstring const quotedblbase_def = from_ascii(
81         "\\ProvideTextCommandDefault{\\quotedblbase}{%\n"
82         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquotedblright}%\n"
83         "  \\penalty10000\\hskip0em\\relax%\n"
84         "}");
85
86 static docstring const quotesinglbase_def = from_ascii(
87         "\\ProvideTextCommandDefault{\\quotesinglbase}{%\n"
88         "  \\raisebox{-1.4ex}[1ex][.5ex]{\\textquoteright}%\n"
89         "  \\penalty10000\\hskip0em\\relax%\n"
90         "}");
91
92 static docstring const guillemotleft_def = from_ascii(
93         "\\ProvideTextCommandDefault{\\guillemotleft}{%\n"
94         "  {\\usefont{U}{lasy}{m}{n}\\char'50\\kern-.15em\\char'50}%\n"
95         "\\penalty10000\\hskip0pt\\relax%\n"
96         "}");
97
98 static docstring const guillemotright_def = from_ascii(
99         "\\ProvideTextCommandDefault{\\guillemotright}{%\n"
100         "  \\penalty10000\\hskip0pt%\n"
101         "  {\\usefont{U}{lasy}{m}{n}\\char'51\\kern-.15em\\char'51}%\n"
102         "}");
103
104 static docstring const guilsinglleft_def = from_ascii(
105         "\\ProvideTextCommandDefault{\\guilsinglleft}{%\n"
106         "  {\\usefont{U}{lasy}{m}{n}\\char'50}%\n"
107         "  \\penalty10000\\hskip0pt\\relax%\n"
108         "}");
109
110 static docstring const guilsinglright_def = from_ascii(
111         "\\ProvideTextCommandDefault{\\guilsinglright}{%\n"
112         "  \\penalty10000\\hskip0pt%\n"
113         "  {\\usefont{U}{lasy}{m}{n}\\char'51}%\n"
114         "}");
115
116 static docstring const paragraphleftindent_def = from_ascii(
117         "\\newenvironment{LyXParagraphLeftIndent}[1]%\n"
118         "{\n"
119         "  \\begin{list}{}{%\n"
120         "    \\setlength{\\topsep}{0pt}%\n"
121         "    \\addtolength{\\leftmargin}{#1}\n"
122 // ho hum, yet more things commented out with no hint as to why they
123 // weren't just removed
124 //      "%%    \\addtolength{\\leftmargin}{#1\\textwidth}\n"
125 //      "%%    \\setlength{\\textwidth}{#2\\textwidth}\n"
126 //      "%%    \\setlength\\listparindent\\parindent%\n"
127 //      "%%    \\setlength\\itemindent\\parindent%\n"
128         "    \\setlength{\\parsep}{0pt plus 1pt}%\n"
129         "  }\n"
130         "  \\item[]\n"
131         "}\n"
132         "{\\end{list}}\n");
133
134 static docstring const floatingfootnote_def = from_ascii(
135         "%% Special footnote code from the package 'stblftnt.sty'\n"
136         "%% Author: Robin Fairbairns -- Last revised Dec 13 1996\n"
137         "\\let\\SF@@footnote\\footnote\n"
138         "\\def\\footnote{\\ifx\\protect\\@typeset@protect\n"
139         "    \\expandafter\\SF@@footnote\n"
140         "  \\else\n"
141         "    \\expandafter\\SF@gobble@opt\n"
142         "  \\fi\n"
143         "}\n"
144         "\\expandafter\\def\\csname SF@gobble@opt \\endcsname{\\@ifnextchar[%]\n"
145         "  \\SF@gobble@twobracket\n"
146         "  \\@gobble\n"
147         "}\n"
148         "\\edef\\SF@gobble@opt{\\noexpand\\protect\n"
149         "  \\expandafter\\noexpand\\csname SF@gobble@opt \\endcsname}\n"
150         "\\def\\SF@gobble@twobracket[#1]#2{}\n");
151
152 static docstring const binom_def = from_ascii(
153         "%% Binom macro for standard LaTeX users\n"
154         "\\newcommand{\\binom}[2]{{#1 \\choose #2}}\n");
155
156 static docstring const mathcircumflex_def = from_ascii(
157         "%% For printing a cirumflex inside a formula\n"
158         "\\newcommand{\\mathcircumflex}[0]{\\mbox{\\^{}}}\n");
159
160 static docstring const tabularnewline_def = from_ascii(
161         "%% Because html converters don't know tabularnewline\n"
162         "\\providecommand{\\tabularnewline}{\\\\}\n");
163         
164 static docstring const lyxgreyedout_def = from_ascii(
165         "%% The greyedout annotation environment\n"
166         "\\newenvironment{lyxgreyedout}\n"
167         "  {\\textcolor{note_fontcolor}\\bgroup\\ignorespaces}\n"
168         "  {\\ignorespacesafterend\\egroup}\n");
169
170 // We want to omit the file extension for includegraphics, but this does not
171 // work when the filename contains other dots.
172 // Idea from http://www.tex.ac.uk/cgi-bin/texfaq2html?label=unkgrfextn
173 static docstring const lyxdot_def = from_ascii(
174         "%% A simple dot to overcome graphicx limitations\n"
175         "\\newcommand{\\lyxdot}{.}\n");
176
177 static docstring const changetracking_dvipost_def = from_ascii(
178         "%% Change tracking with dvipost\n"
179         "\\dvipostlayout\n"
180         "\\dvipost{osstart color push Red}\n"
181         "\\dvipost{osend color pop}\n"
182         "\\dvipost{cbstart color push Blue}\n"
183         "\\dvipost{cbend color pop}\n"
184         "\\newcommand{\\lyxadded}[3]{\\changestart#3\\changeend}\n"
185         "\\newcommand{\\lyxdeleted}[3]{%\n"
186         "\\changestart\\overstrikeon#3\\overstrikeoff\\changeend}\n");
187
188 static docstring const changetracking_xcolor_ulem_def = from_ascii(
189         "%% Change tracking with ulem\n"
190         "\\newcommand{\\lyxadded}[3]{{\\color{lyxadded}{}#3}}\n"
191         "\\newcommand{\\lyxdeleted}[3]{{\\color{lyxdeleted}\\sout{#3}}}\n");
192
193 static docstring const changetracking_xcolor_ulem_hyperref_def = from_ascii(
194         "%% Change tracking with ulem\n"
195         "\\newcommand{\\lyxadded}[3]{{\\texorpdfstring{\\color{lyxadded}{}}{}#3}}\n"
196         "\\newcommand{\\lyxdeleted}[3]{{\\texorpdfstring{\\color{lyxdeleted}\\sout{#3}}{}}}\n");
197
198 static docstring const changetracking_none_def = from_ascii(
199         "\\newcommand{\\lyxadded}[3]{#3}\n"
200         "\\newcommand{\\lyxdeleted}[3]{}\n");
201
202 static docstring const textgreek_def = from_ascii(
203         "\\DeclareRobustCommand{\\greektext}{%\n"
204         "  \\fontencoding{LGR}\\selectfont\\def\\encodingdefault{LGR}}\n"
205         "\\DeclareRobustCommand{\\textgreek}[1]{\\leavevmode{\\greektext #1}}\n"
206         "\\DeclareFontEncoding{LGR}{}{}\n"
207         "\\DeclareTextSymbol{\\~}{LGR}{126}");
208
209 static docstring const textcyr_def = from_ascii(
210         "\\DeclareRobustCommand{\\cyrtext}{%\n"
211         "  \\fontencoding{T2A}\\selectfont\\def\\encodingdefault{T2A}}\n"
212         "\\DeclareRobustCommand{\\textcyr}[1]{\\leavevmode{\\cyrtext #1}}\n"
213         "\\AtBeginDocument{\\DeclareFontEncoding{T2A}{}{}}\n");
214
215 static docstring const lyxmathsym_def = from_ascii(
216         "\\newcommand{\\lyxmathsym}[1]{\\ifmmode\\begingroup\\def\\b@ld{bold}\n"
217         "  \\text{\\ifx\\math@version\\b@ld\\bfseries\\fi#1}\\endgroup\\else#1\\fi}\n");
218
219 static docstring const papersizedvi_def = from_ascii(
220         "\\special{papersize=\\the\\paperwidth,\\the\\paperheight}\n");
221
222 static docstring const papersizepdf_def = from_ascii(
223         "\\pdfpageheight\\paperheight\n"
224         "\\pdfpagewidth\\paperwidth\n");
225
226 static docstring const cedilla_def = from_ascii(
227         "\\newcommand{\\docedilla}[2]{\\underaccent{#1\\mathchar'30}{#2}}\n"
228         "\\newcommand{\\cedilla}[1]{\\mathpalette\\docedilla{#1}}\n");
229
230 static docstring const subring_def = from_ascii(
231         "\\newcommand{\\dosubring}[2]{\\underaccent{#1\\mathchar'27}{#2}}\n"
232         "\\newcommand{\\subring}[1]{\\mathpalette\\dosubring{#1}}\n");
233
234 static docstring const subdot_def = from_ascii(
235         "\\newcommand{\\dosubdot}[2]{\\underaccent{#1.}{#2}}\n"
236         "\\newcommand{\\subdot}[1]{\\mathpalette\\dosubdot{#1}}\n");
237
238 static docstring const subhat_def = from_ascii(
239         "\\newcommand{\\dosubhat}[2]{\\underaccent{#1\\mathchar'136}{#2}}\n"
240         "\\newcommand{\\subhat}[1]{\\mathpalette\\dosubhat{#1}}\n");
241
242 static docstring const subtilde_def = from_ascii(
243         "\\newcommand{\\dosubtilde}[2]{\\underaccent{#1\\mathchar'176}{#2}}\n"
244         "\\newcommand{\\subtilde}[1]{\\mathpalette\\dosubtilde{#1}}\n");
245
246 static docstring const dacute_def = from_ascii(
247         "\\DeclareMathAccent{\\dacute}{\\mathalpha}{operators}{'175}\n");
248
249 static docstring const tipasymb_def = from_ascii(
250         "\\DeclareFontEncoding{T3}{}{}\n"
251         "\\DeclareSymbolFont{tipasymb}{T3}{cmr}{m}{n}\n");
252
253 static docstring const dgrave_def = from_ascii(
254         "\\DeclareMathAccent{\\dgrave}{\\mathord}{tipasymb}{'15}\n");
255
256 static docstring const rcap_def = from_ascii(
257         "\\DeclareMathAccent{\\rcap}{\\mathord}{tipasymb}{'20}\n");
258
259 static docstring const ogonek_def = from_ascii(
260         "\\newcommand{\\doogonek}[2]{\\setbox0=\\hbox{$#1#2$}\\underaccent{#1\\mkern-6mu\n"
261         "  \\ifx#2O\\hskip0.5\\wd0\\else\\ifx#2U\\hskip0.5\\wd0\\else\\hskip\\wd0\\fi\\fi\n"
262         "  \\ifx#2o\\mkern-2mu\\else\\ifx#2e\\mkern-1mu\\fi\\fi\n"
263         "  \\mathchar\"0\\hexnumber@\\symtipasymb0C}{#2}}\n"
264         "\\newcommand{\\ogonek}[1]{\\mathpalette\\doogonek{#1}}\n");
265
266 static docstring const lyxref_def = from_ascii(
267                 "\\RS@ifundefined{subref}\n"
268                 "  {\\def\\RSsubtxt{section~}\\newref{sub}{name = \\RSsubtxt}}\n" 
269                 "  {}\n"
270                 "\\RS@ifundefined{thmref}\n"
271                 "  {\\def\\RSthmtxt{theorem~}\\newref{thm}{name = \\RSthmtxt}}\n" 
272                 "  {}\n"
273                 "\\RS@ifundefined{lemref}\n"
274                 "  {\\def\\RSlemtxt{lemma~}\\newref{lem}{name = \\RSlemtxt}}\n" 
275                 "  {}\n");
276
277
278 /////////////////////////////////////////////////////////////////////
279 //
280 // LaTeXFeatures
281 //
282 /////////////////////////////////////////////////////////////////////
283
284 LaTeXFeatures::Packages LaTeXFeatures::packages_;
285
286
287 LaTeXFeatures::LaTeXFeatures(Buffer const & b, BufferParams const & p,
288                              OutputParams const & r)
289         : buffer_(&b), params_(p), runparams_(r), in_float_(false)
290 {}
291
292
293 bool LaTeXFeatures::useBabel() const
294 {
295         if (usePolyglossia())
296                 return false;
297         return (lyxrc.language_package_selection != LyXRC::LP_NONE)
298                 || (bufferParams().language->lang() != lyxrc.default_language
299                     && !bufferParams().language->babel().empty())
300                 || this->hasLanguages();
301 }
302
303
304 bool LaTeXFeatures::usePolyglossia() const
305 {
306         return (lyxrc.language_package_selection == LyXRC::LP_AUTO)
307                 && isRequired("polyglossia")
308                 && isAvailable("polyglossia")
309                 && !params_.documentClass().provides("babel")
310                 && this->hasPolyglossiaLanguages();
311 }
312
313
314 void LaTeXFeatures::require(string const & name)
315 {
316         features_.insert(name);
317 }
318
319
320 void LaTeXFeatures::require(set<string> const & names)
321 {
322         features_.insert(names.begin(), names.end());
323 }
324
325
326 void LaTeXFeatures::getAvailable()
327 {
328         Lexer lex;
329         support::FileName const real_file = libFileSearch("", "packages.lst");
330
331         if (real_file.empty())
332                 return;
333
334         lex.setFile(real_file);
335
336         if (!lex.isOK())
337                 return;
338
339         // Make sure that we are clean
340         packages_.clear();
341
342         bool finished = false;
343         // Parse config-file
344         while (lex.isOK() && !finished) {
345                 switch (lex.lex()) {
346                 case Lexer::LEX_FEOF:
347                         finished = true;
348                         break;
349                 default:
350                         packages_.insert(lex.getString());
351                 }
352         }
353 }
354
355
356 void LaTeXFeatures::useLayout(docstring const & layoutname)
357 {
358         // Some code to avoid loops in dependency definition
359         static int level = 0;
360         const int maxlevel = 30;
361         if (level > maxlevel) {
362                 lyxerr << "LaTeXFeatures::useLayout: maximum level of "
363                        << "recursion attained by layout "
364                        << to_utf8(layoutname) << endl;
365                 return;
366         }
367
368         DocumentClass const & tclass = params_.documentClass();
369         if (tclass.hasLayout(layoutname)) {
370                 // Is this layout already in usedLayouts?
371                 if (find(usedLayouts_.begin(), usedLayouts_.end(), layoutname) 
372                     != usedLayouts_.end())
373                         return;
374
375                 Layout const & layout = tclass[layoutname];
376                 require(layout.requires());
377
378                 if (!layout.depends_on().empty()) {
379                         ++level;
380                         useLayout(layout.depends_on());
381                         --level;
382                 }
383                 usedLayouts_.push_back(layoutname);
384         } else {
385                 lyxerr << "LaTeXFeatures::useLayout: layout `"
386                        << to_utf8(layoutname) << "' does not exist in this class"
387                        << endl;
388         }
389
390         --level;
391 }
392
393
394 void LaTeXFeatures::useInsetLayout(InsetLayout const & lay)
395 {
396         docstring const & lname = lay.name();
397         DocumentClass const & tclass = params_.documentClass();
398
399         // this is a default inset layout, nothing useful here
400         if (!tclass.hasInsetLayout(lname))
401                 return;
402         // Is this layout already in usedInsetLayouts?
403         if (find(usedInsetLayouts_.begin(), usedInsetLayouts_.end(), lname) 
404                         != usedInsetLayouts_.end())
405                 return;
406
407         require(lay.requires());
408         usedInsetLayouts_.push_back(lname);
409 }
410
411
412 bool LaTeXFeatures::isRequired(string const & name) const
413 {
414         return features_.find(name) != features_.end();
415 }
416
417
418 bool LaTeXFeatures::mustProvide(string const & name) const
419 {
420         return isRequired(name) && !params_.documentClass().provides(name);
421 }
422
423
424 bool LaTeXFeatures::isAvailable(string const & name)
425 {
426         string::size_type const i = name.find("->");
427         if (i != string::npos) {
428                 string const from = name.substr(0,i);
429                 string const to = name.substr(i+2);
430                 //LYXERR0("from=[" << from << "] to=[" << to << "]");
431                 return theConverters().isReachable(from, to);
432         }
433
434         if (packages_.empty())
435                 getAvailable();
436         string n = name;
437         if (suffixIs(n, ".sty"))
438                 n.erase(name.length() - 4);
439         return packages_.find(n) != packages_.end();
440 }
441
442
443 void LaTeXFeatures::addPreambleSnippet(string const & preamble)
444 {
445         SnippetList::const_iterator begin = preamble_snippets_.begin();
446         SnippetList::const_iterator end   = preamble_snippets_.end();
447         if (find(begin, end, preamble) == end)
448                 preamble_snippets_.push_back(preamble);
449 }
450
451
452 void LaTeXFeatures::useFloat(string const & name, bool subfloat)
453 {
454         if (!usedFloats_[name])
455                 usedFloats_[name] = subfloat;
456         if (subfloat)
457                 require("subfig");
458         // We only need float.sty if we use non builtin floats, or if we
459         // use the "H" modifier. This includes modified table and
460         // figure floats. (Lgb)
461         Floating const & fl = params_.documentClass().floats().getType(name);
462         if (!fl.floattype().empty() && fl.usesFloatPkg()) {
463                 require("float");
464         }
465 }
466
467
468 void LaTeXFeatures::useLanguage(Language const * lang)
469 {
470         if (!lang->babel().empty())
471                 UsedLanguages_.insert(lang);
472         if (lang->lang() == "vietnamese")
473                 require("vietnamese");
474         // CJK languages do not have a babel name.
475         // They use the CJK package
476         if (lang->encoding()->package() == Encoding::CJK)
477                 require("CJK");
478         // japanese package is special
479         if (lang->encoding()->package() == Encoding::japanese)
480                 require("japanese");
481 }
482
483
484 void LaTeXFeatures::includeFile(docstring const & key, string const & name)
485 {
486         IncludedFiles_[key] = name;
487 }
488
489
490 bool LaTeXFeatures::hasLanguages() const
491 {
492         return !UsedLanguages_.empty();
493 }
494
495
496 bool LaTeXFeatures::hasPolyglossiaLanguages() const
497 {
498         LanguageList::const_iterator const begin = UsedLanguages_.begin();
499         for (LanguageList::const_iterator cit = begin;
500              cit != UsedLanguages_.end();
501              ++cit) {
502                 if ((*cit)->polyglossia().empty())
503                         return false;
504         }
505         return true;
506 }
507
508
509 string LaTeXFeatures::getLanguages() const
510 {
511         ostringstream languages;
512
513         LanguageList::const_iterator const begin = UsedLanguages_.begin();
514         for (LanguageList::const_iterator cit = begin;
515              cit != UsedLanguages_.end();
516              ++cit) {
517                 if (cit != begin)
518                         languages << ',';
519                 languages << (*cit)->babel();
520         }
521         return languages.str();
522 }
523
524
525 std::map<std::string, std::string> LaTeXFeatures::getPolyglossiaLanguages() const
526 {
527         std::map<std::string, std::string> languages;
528
529         LanguageList::const_iterator const begin = UsedLanguages_.begin();
530         for (LanguageList::const_iterator cit = begin;
531              cit != UsedLanguages_.end();
532              ++cit) {
533                 languages[(*cit)->polyglossia()] = (*cit)->polyglossiaOpts();
534         }
535         return languages;
536 }
537
538
539 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
540 {
541         // This does only find encodings of languages supported by babel, but
542         // that does not matter since we don't have a language with an
543         // encoding supported by inputenc but without babel support.
544         set<string> encodings;
545         LanguageList::const_iterator it  = UsedLanguages_.begin();
546         LanguageList::const_iterator end = UsedLanguages_.end();
547         for (; it != end; ++it)
548                 if ((*it)->encoding()->latexName() != doc_encoding &&
549                     ((*it)->encoding()->package() == Encoding::inputenc
550                      || (*it)->encoding()->package() == Encoding::japanese))
551                         encodings.insert((*it)->encoding()->latexName());
552         return encodings;
553 }
554
555 namespace {
556
557 char const * simplefeatures[] = {
558 // note that the package order here will be the same in the LaTeX-output
559         "array",
560         "verbatim",
561         "longtable",
562         "rotating",
563         "latexsym",
564         "pifont",
565         // subfig is handled in BufferParams.cpp
566         "varioref",
567         "prettyref",
568         "refstyle",
569         /*For a successful cooperation of the `wrapfig' package with the
570           `float' package you should load the `wrapfig' package *after*
571           the `float' package. See the caption package documentation
572           for explanation.*/
573         "float",
574         "rotfloat",
575         "wrapfig",
576         "booktabs",
577         "dvipost",
578         "fancybox",
579         "calc",
580         "units",
581         "tipa",
582         "tipx",
583         "framed",
584         "soul",
585         "textcomp",
586         "pmboxdraw",
587         "bbding",
588         "ifsym",
589         "marvosym",
590         "txfonts",
591         "mathrsfs",
592         "ascii",
593         "url",
594         "covington",
595         "csquotes",
596         "enumitem",
597         "endnotes",
598         "hhline",
599         "ifthen",
600         // listings is handled in BufferParams.cpp
601         "bm",
602         "pdfpages",
603         "amscd",
604         "slashed",
605         "multirow",
606         "tfrupee"
607 };
608
609 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
610
611 }
612
613
614 string const LaTeXFeatures::getColorOptions() const
615 {
616         ostringstream colors;
617
618         // Handling the color packages separately is needed to be able to load them
619         // before babel when hyperref is loaded with the colorlinks option
620         // for more info see Bufferparams.cpp
621
622         // [x]color.sty
623         if (mustProvide("color") || mustProvide("xcolor")) {
624                 string const package =
625                         (mustProvide("xcolor") ? "xcolor" : "color");
626                 if (params_.graphics_driver == "default"
627                         || params_.graphics_driver == "none")
628                         colors << "\\usepackage{" << package << "}\n";
629                 else
630                         colors << "\\usepackage["
631                                  << params_.graphics_driver
632                                  << "]{" << package << "}\n";
633         }
634
635         // pdfcolmk must be loaded after color
636         if (mustProvide("pdfcolmk"))
637                 colors << "\\usepackage{pdfcolmk}\n";
638
639         // the following 3 color commands must be set after color
640         // is loaded and before pdfpages, therefore add the command
641         // here define the set color
642         if (mustProvide("pagecolor")) {
643                 colors << "\\definecolor{page_backgroundcolor}{rgb}{";
644                 colors << outputLaTeXColor(params_.backgroundcolor) << "}\n";
645                 // set the page color
646                 colors << "\\pagecolor{page_backgroundcolor}\n";
647         }
648
649         if (mustProvide("fontcolor")) {
650                 colors << "\\definecolor{document_fontcolor}{rgb}{";
651                 colors << outputLaTeXColor(params_.fontcolor) << "}\n";
652                 // set the color
653                 colors << "\\color{document_fontcolor}\n";
654         }
655
656         if (mustProvide("lyxgreyedout")) {
657                 colors << "\\definecolor{note_fontcolor}{rgb}{";
658                 colors << outputLaTeXColor(params_.notefontcolor) << "}\n";
659                 // the color will be set together with the definition of
660                 // the lyxgreyedout environment (see lyxgreyedout_def)
661         }
662
663         // color for shaded boxes
664         if (isRequired("framed") && mustProvide("color")) {
665                 colors << "\\definecolor{shadecolor}{rgb}{";
666                 colors << outputLaTeXColor(params_.boxbgcolor) << "}\n";
667                 // this color is automatically used by the LaTeX-package "framed"
668         }
669
670         return colors.str();
671 }
672
673
674 string const LaTeXFeatures::getPackages() const
675 {
676         ostringstream packages;
677         DocumentClass const & tclass = params_.documentClass();
678
679         // FIXME: currently, we can only load packages and macros known
680         // to LyX.
681         // However, with the Require tag of layouts/custom insets,
682         // also unknown packages can be requested. They are silently
683         // swallowed now. We should change this eventually.
684
685         //
686         //  These are all the 'simple' includes.  i.e
687         //  packages which we just \usepackage{package}
688         //
689         for (int i = 0; i < nb_simplefeatures; ++i) {
690                 if (mustProvide(simplefeatures[i]))
691                         packages << "\\usepackage{"
692                                  << simplefeatures[i] << "}\n";
693         }
694
695         //
696         // The rest of these packages are somewhat more complicated
697         // than those above.
698         //
699
700         // if fontspec is used, AMS packages have to be loaded before
701         // fontspec (in BufferParams)
702         if (!params_.useNonTeXFonts && !loadAMSPackages().empty())
703                 packages << loadAMSPackages();
704
705         // fixltx2e must be loaded after amsthm, since amsthm produces an error with
706         // the redefined \[ command (bug 7233). Load is as early as possible, since
707         // other packages might profit from it.
708         if (mustProvide("fixltx2e"))
709                 packages << "\\usepackage{fixltx2e}\n";
710
711         // wasysym is a simple feature, but it must be after amsmath if both
712         // are used
713         // wasysym redefines some integrals (e.g. iint) from amsmath. That
714         // leads to inconsistent integrals. We only load this package if
715         // the document does not contain integrals (then isRequired("esint")
716         // is false) or if esint is used, since esint redefines all relevant
717         // integral symbols from wasysym and amsmath.
718         // See http://www.lyx.org/trac/ticket/1942
719         if (mustProvide("wasysym") &&
720             (params_.use_esint != BufferParams::package_off || !isRequired("esint")))
721                 packages << "\\usepackage{wasysym}\n";
722
723         // accents must be loaded after amsmath
724         if (mustProvide("accents"))
725                 packages << "\\usepackage{accents}\n";
726
727         // mathdots must be loaded after amsmath
728         if (mustProvide("mathdots") &&
729                 params_.use_mathdots != BufferParams::package_off)
730                 packages << "\\usepackage{mathdots}\n";
731
732         // yhmath must be loaded after amsmath
733         if (mustProvide("yhmath"))
734                 packages << "\\usepackage{yhmath}\n";
735
736         // [x]color and pdfcolmk are handled in getColorOptions() above
737         
738         // makeidx.sty
739         if (isRequired("makeidx") || isRequired("splitidx")) {
740                 if (!tclass.provides("makeidx") && !isRequired("splitidx"))
741                         packages << "\\usepackage{makeidx}\n";
742                 if (!tclass.provides("splitidx") && isRequired("splitidx"))
743                         packages << "\\usepackage{splitidx}\n";
744                 packages << "\\makeindex\n";
745         }
746
747         // graphicx.sty
748         if (mustProvide("graphicx") && params_.graphics_driver != "none") {
749                 if (params_.graphics_driver == "default")
750                         packages << "\\usepackage{graphicx}\n";
751                 else
752                         packages << "\\usepackage["
753                                  << params_.graphics_driver
754                                  << "]{graphicx}\n";
755         }
756         
757         // lyxskak.sty --- newer chess support based on skak.sty
758         if (mustProvide("chess"))
759                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
760
761         // setspace.sty
762         if (mustProvide("setspace") && !tclass.provides("SetSpace"))
763                 packages << "\\usepackage{setspace}\n";
764
765         // esint must be after amsmath and wasysym, since it will redeclare
766         // inconsistent integral symbols
767         if ((mustProvide("esint") || mustProvide("esintoramsmath")) &&
768             params_.use_esint != BufferParams::package_off)
769                 packages << "\\usepackage{esint}\n";
770
771         // natbib.sty
772         // Some classes load natbib themselves, but still allow (or even require)
773         // plain numeric citations (ReVTeX is such a case, see bug 5182).
774         // This special case is indicated by the "natbib-internal" key.
775         if (mustProvide("natbib") && !tclass.provides("natbib-internal")) {
776                 packages << "\\usepackage[";
777                 if (params_.citeEngine() == ENGINE_NATBIB_NUMERICAL)
778                         packages << "numbers";
779                 else
780                         packages << "authoryear";
781                 packages << "]{natbib}\n";
782         }
783
784         // jurabib -- we need version 0.6 at least.
785         if (mustProvide("jurabib"))
786                 packages << "\\usepackage{jurabib}[2004/01/25]\n";
787         
788         // xargs -- we need version 1.09 at least
789         if (mustProvide("xargs"))
790                 packages << "\\usepackage{xargs}[2008/03/08]\n";
791
792         // bibtopic -- the dot provides the aux file naming which
793         // LyX can detect.
794         if (mustProvide("bibtopic"))
795                 packages << "\\usepackage[dot]{bibtopic}\n";
796
797         if (mustProvide("xy"))
798                 packages << "\\usepackage[all]{xy}\n";
799
800         if (mustProvide("feyn"))
801                 packages << "\\usepackage{feyn}\n"; //Diagram
802
803         if (mustProvide("ulem"))
804                 packages << "\\PassOptionsToPackage{normalem}{ulem}\n"
805                             "\\usepackage{ulem}\n";
806
807         if (params_.use_mhchem == BufferParams::package_on ||
808             (mustProvide("mhchem") &&
809              params_.use_mhchem != BufferParams::package_off))
810                 packages << "\\PassOptionsToPackage{version=3}{mhchem}\n"
811                             "\\usepackage{mhchem}\n";
812
813         if (mustProvide("nomencl")) {
814                 // Make it work with the new and old version of the package,
815                 // but don't use the compatibility option since it is
816                 // incompatible to other packages.
817                 packages << "\\usepackage{nomencl}\n"
818                             "% the following is useful when we have the old nomencl.sty package\n"
819                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
820                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
821                             "\\makenomenclature\n";
822         }
823
824         // fixltx2e provides subscript
825         if (mustProvide("subscript") && !isRequired("fixltx2e"))
826                 packages << "\\usepackage{subscript}\n";
827
828         return packages.str();
829 }
830
831
832 string LaTeXFeatures::getPreambleSnippets() const 
833 {
834         ostringstream snip;
835         SnippetList::const_iterator pit  = preamble_snippets_.begin();
836         SnippetList::const_iterator pend = preamble_snippets_.end();
837         for (; pit != pend; ++pit)
838                 snip << *pit << '\n';
839         return snip.str();
840 }
841
842
843 docstring const LaTeXFeatures::getMacros() const
844 {
845         odocstringstream macros;
846
847         if (!preamble_snippets_.empty()) {
848                 macros << '\n';
849                 macros << from_utf8(getPreambleSnippets());
850         }
851
852         if (mustProvide("papersize")) {
853                 if (runparams_.flavor == OutputParams::LATEX)
854                         macros << papersizedvi_def << '\n';
855                 else
856                         macros << papersizepdf_def << '\n';
857         }
858
859         if (mustProvide("LyX")) {
860                 if (isRequired("hyperref"))
861                         macros << lyx_hyperref_def << '\n';
862                 else
863                         macros << lyx_def << '\n';
864         }
865
866         if (mustProvide("noun"))
867                 macros << noun_def << '\n';
868
869         if (mustProvide("lyxarrow"))
870                 macros << lyxarrow_def << '\n';
871
872         if (!usePolyglossia() && mustProvide("textgreek")) {
873                 // Avoid a LaTeX error if times fonts are used and the grtimes
874                 // package is installed but actual fonts are not (bug 6469).
875                 if (params_.fonts_roman == "times")
876                         macros << subst(textgreek_def,
877                                         from_ascii("\\greektext #1"),
878                                         from_ascii("%\n  \\IfFileExists"
879                                                    "{grtm10.tfm}{}{\\fontfamily"
880                                                    "{cmr}}\\greektext #1"))
881                                << '\n';
882                 else
883                         macros << textgreek_def << '\n';
884         }
885
886         if (!usePolyglossia() && mustProvide("textcyr"))
887                 macros << textcyr_def << '\n';
888
889         if (mustProvide("lyxmathsym"))
890                 macros << lyxmathsym_def << '\n';
891
892         if (mustProvide("cedilla"))
893                 macros << cedilla_def << '\n';
894
895         if (mustProvide("subring"))
896                 macros << subring_def << '\n';
897
898         if (mustProvide("subdot"))
899                 macros << subdot_def << '\n';
900
901         if (mustProvide("subhat"))
902                 macros << subhat_def << '\n';
903
904         if (mustProvide("subtilde"))
905                 macros << subtilde_def << '\n';
906
907         if (mustProvide("dacute"))
908                 macros << dacute_def << '\n';
909
910         if (mustProvide("tipasymb"))
911                 macros << tipasymb_def << '\n';
912
913         if (mustProvide("dgrave"))
914                 macros << dgrave_def << '\n';
915
916         if (mustProvide("rcap"))
917                 macros << rcap_def << '\n';
918
919         if (mustProvide("ogonek"))
920                 macros << ogonek_def << '\n';
921
922         // quotes.
923         if (mustProvide("quotesinglbase"))
924                 macros << quotesinglbase_def << '\n';
925         if (mustProvide("quotedblbase"))
926                 macros << quotedblbase_def << '\n';
927         if (mustProvide("guilsinglleft"))
928                 macros << guilsinglleft_def << '\n';
929         if (mustProvide("guilsinglright"))
930                 macros << guilsinglright_def << '\n';
931         if (mustProvide("guillemotleft"))
932                 macros << guillemotleft_def << '\n';
933         if (mustProvide("guillemotright"))
934                 macros << guillemotright_def << '\n';
935
936         // Math mode
937         if (mustProvide("binom") && !isRequired("amsmath"))
938                 macros << binom_def << '\n';
939         if (mustProvide("mathcircumflex"))
940                 macros << mathcircumflex_def << '\n';
941
942         // other
943         if (mustProvide("ParagraphLeftIndent"))
944                 macros << paragraphleftindent_def;
945         if (mustProvide("NeedLyXFootnoteCode"))
946                 macros << floatingfootnote_def;
947
948         // some problems with tex->html converters
949         if (mustProvide("NeedTabularnewline"))
950                 macros << tabularnewline_def;
951
952         // greyed-out environment (note inset)
953         // the color is specified in the routine
954         // getColorOptions() to avoid LaTeX-package clashes
955         if (mustProvide("lyxgreyedout"))
956                 macros << lyxgreyedout_def;
957
958         if (mustProvide("lyxdot"))
959                 macros << lyxdot_def << '\n';
960
961         // floats
962         getFloatDefinitions(macros);
963         
964         if (mustProvide("refstyle")) 
965                 macros << lyxref_def << '\n';   
966         
967         // change tracking
968         if (mustProvide("ct-dvipost"))
969                 macros << changetracking_dvipost_def;
970         
971         if (mustProvide("ct-xcolor-ulem")) {
972                 streamsize const prec = macros.precision(2);
973         
974                 RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
975                 macros << "\\providecolor{lyxadded}{rgb}{"
976                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
977
978                 RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
979                 macros << "\\providecolor{lyxdeleted}{rgb}{"
980                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
981
982                 macros.precision(prec);
983                 
984                 if (isRequired("hyperref"))
985                         macros << changetracking_xcolor_ulem_hyperref_def;
986                 else
987                         macros << changetracking_xcolor_ulem_def;
988         }
989
990         if (mustProvide("ct-none"))
991                 macros << changetracking_none_def;
992
993         return macros.str();
994 }
995
996
997 string const LaTeXFeatures::getBabelPresettings() const
998 {
999         ostringstream tmp;
1000
1001         LanguageList::const_iterator it  = UsedLanguages_.begin();
1002         LanguageList::const_iterator end = UsedLanguages_.end();
1003         for (; it != end; ++it)
1004                 if (!(*it)->babel_presettings().empty())
1005                         tmp << (*it)->babel_presettings() << '\n';
1006         if (!params_.language->babel_presettings().empty())
1007                 tmp << params_.language->babel_presettings() << '\n';
1008
1009         return tmp.str();
1010 }
1011
1012
1013 string const LaTeXFeatures::getBabelPostsettings() const
1014 {
1015         ostringstream tmp;
1016
1017         LanguageList::const_iterator it  = UsedLanguages_.begin();
1018         LanguageList::const_iterator end = UsedLanguages_.end();
1019         for (; it != end; ++it)
1020                 if (!(*it)->babel_postsettings().empty())
1021                         tmp << (*it)->babel_postsettings() << '\n';
1022         if (!params_.language->babel_postsettings().empty())
1023                 tmp << params_.language->babel_postsettings() << '\n';
1024
1025         return tmp.str();
1026 }
1027
1028
1029 bool LaTeXFeatures::needBabelLangOptions() const
1030 {
1031         if (!lyxrc.language_global_options || params_.language->asBabelOptions())
1032                 return true;
1033
1034         LanguageList::const_iterator it  = UsedLanguages_.begin();
1035         LanguageList::const_iterator end = UsedLanguages_.end();
1036         for (; it != end; ++it)
1037                 if ((*it)->asBabelOptions())
1038                         return true;
1039
1040         return false;
1041 }
1042
1043
1044 string const LaTeXFeatures::loadAMSPackages() const
1045 {
1046         ostringstream tmp;
1047         if (mustProvide("amsthm"))
1048                 tmp << "\\usepackage{amsthm}\n";
1049
1050         // esint is preferred for esintoramsmath
1051         if ((mustProvide("amsmath")
1052              && params_.use_amsmath != BufferParams::package_off)
1053             || (mustProvide("esintoramsmath")
1054                 && params_.use_esint == BufferParams::package_off
1055                 && params_.use_amsmath != BufferParams::package_off)) {
1056                 tmp << "\\usepackage{amsmath}\n";
1057         } else {
1058                 // amsbsy and amstext are already provided by amsmath
1059                 if (mustProvide("amsbsy"))
1060                         tmp << "\\usepackage{amsbsy}\n";
1061                 if (mustProvide("amstext"))
1062                         tmp << "\\usepackage{amstext}\n";
1063         }
1064         
1065         if (mustProvide("amssymb")
1066             || params_.use_amsmath == BufferParams::package_on)
1067                 tmp << "\\usepackage{amssymb}\n";
1068
1069         return tmp.str();
1070 }
1071
1072
1073 docstring const LaTeXFeatures::getTClassPreamble() const
1074 {
1075         // the text class specific preamble
1076         DocumentClass const & tclass = params_.documentClass();
1077         odocstringstream tcpreamble;
1078
1079         tcpreamble << tclass.preamble();
1080
1081         list<docstring>::const_iterator cit = usedLayouts_.begin();
1082         list<docstring>::const_iterator end = usedLayouts_.end();
1083         for (; cit != end; ++cit)
1084                 tcpreamble << tclass[*cit].preamble();
1085
1086         cit = usedInsetLayouts_.begin();
1087         end = usedInsetLayouts_.end();
1088         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1089         for (; cit != end; ++cit) {
1090                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1091                 if (it == ils.end())
1092                         continue;
1093                 tcpreamble << it->second.preamble();
1094         }
1095
1096         return tcpreamble.str();
1097 }
1098
1099
1100 docstring const LaTeXFeatures::getTClassHTMLPreamble() const 
1101 {
1102         DocumentClass const & tclass = params_.documentClass();
1103         odocstringstream tcpreamble;
1104
1105         tcpreamble << tclass.htmlpreamble();
1106
1107         list<docstring>::const_iterator cit = usedLayouts_.begin();
1108         list<docstring>::const_iterator end = usedLayouts_.end();
1109         for (; cit != end; ++cit)
1110                 tcpreamble << tclass[*cit].htmlpreamble();
1111
1112         cit = usedInsetLayouts_.begin();
1113         end = usedInsetLayouts_.end();
1114         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1115         for (; cit != end; ++cit) {
1116                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1117                 if (it == ils.end())
1118                         continue;
1119                 tcpreamble << it->second.htmlpreamble();
1120         }
1121
1122         return tcpreamble.str();
1123 }
1124
1125
1126 docstring const LaTeXFeatures::getTClassHTMLStyles() const {
1127         DocumentClass const & tclass = params_.documentClass();
1128         odocstringstream tcpreamble;
1129
1130         list<docstring>::const_iterator cit = usedLayouts_.begin();
1131         list<docstring>::const_iterator end = usedLayouts_.end();
1132         for (; cit != end; ++cit)
1133                 tcpreamble << tclass[*cit].htmlstyle();
1134
1135         cit = usedInsetLayouts_.begin();
1136         end = usedInsetLayouts_.end();
1137         TextClass::InsetLayouts const & ils = tclass.insetLayouts();
1138         for (; cit != end; ++cit) {
1139                 TextClass::InsetLayouts::const_iterator it = ils.find(*cit);
1140                 if (it == ils.end())
1141                         continue;
1142                 tcpreamble << it->second.htmlstyle();
1143         }
1144
1145         return tcpreamble.str();
1146 }
1147
1148
1149 namespace {
1150 docstring const getFloatI18nPreamble(docstring const & type, docstring const & name, docstring const & lang)
1151 {
1152         odocstringstream os;
1153         os << "\\addto\\captions" << lang
1154            << "{\\renewcommand{\\" << type << "name}{" << name << "}}\n";
1155         return os.str();
1156 }
1157 }
1158
1159
1160 docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel, bool use_polyglossia) const
1161 {
1162         DocumentClass const & tclass = params_.documentClass();
1163         // collect preamble snippets in a set to prevent multiple identical
1164         // commands (would happen if e.g. both theorem and theorem* are used)
1165         set<docstring> snippets;
1166         typedef LanguageList::const_iterator lang_it;
1167         lang_it const lbeg = UsedLanguages_.begin();
1168         lang_it const lend =  UsedLanguages_.end();
1169         list<docstring>::const_iterator cit = usedLayouts_.begin();
1170         list<docstring>::const_iterator end = usedLayouts_.end();
1171         for (; cit != end; ++cit) {
1172                 // language dependent commands (once per document)
1173                 snippets.insert(tclass[*cit].langpreamble(buffer().language(),
1174                                                           use_polyglossia));
1175                 // commands for language changing (for multilanguage documents)
1176                 if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1177                         snippets.insert(tclass[*cit].babelpreamble(buffer().language(),
1178                                                                    use_polyglossia));
1179                         for (lang_it lit = lbeg; lit != lend; ++lit)
1180                                 snippets.insert(tclass[*cit].babelpreamble(*lit, use_polyglossia));
1181                 }
1182         }
1183         if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) {
1184                 FloatList const & floats = params_.documentClass().floats();
1185                 UsedFloats::const_iterator fit = usedFloats_.begin();
1186                 UsedFloats::const_iterator fend = usedFloats_.end();
1187                 for (; fit != fend; ++fit) {
1188                         Floating const & fl = floats.getType(fit->first);
1189                         docstring const type = from_ascii(fl.floattype());
1190                         docstring const flname = from_utf8(fl.name());
1191                         docstring name = translateIfPossible(flname,
1192                                 buffer().language()->code());
1193                         if (use_polyglossia)
1194                                 snippets.insert(getFloatI18nPreamble(
1195                                         type, name,
1196                                         from_ascii(buffer().language()->polyglossia())));
1197                         else
1198                                 snippets.insert(getFloatI18nPreamble(
1199                                         type, name,
1200                                         from_ascii(buffer().language()->babel())));
1201                         for (lang_it lit = lbeg; lit != lend; ++lit) {
1202                                 name = translateIfPossible(flname,
1203                                         (*lit)->code());
1204                                 if (use_polyglossia)
1205                                         snippets.insert(getFloatI18nPreamble(
1206                                                 type, name,
1207                                                 from_ascii((*lit)->polyglossia())));
1208                                 else
1209                                         snippets.insert(getFloatI18nPreamble(
1210                                                 type, name,
1211                                                 from_ascii((*lit)->babel())));
1212                         }
1213                 }
1214         }
1215
1216         odocstringstream tcpreamble;
1217         set<docstring>::const_iterator const send = snippets.end();
1218         set<docstring>::const_iterator it = snippets.begin();
1219         for (; it != send; ++it)
1220                 tcpreamble << *it;
1221         return tcpreamble.str();
1222 }
1223
1224
1225 docstring const LaTeXFeatures::getLyXSGMLEntities() const
1226 {
1227         // Definition of entities used in the document that are LyX related.
1228         odocstringstream entities;
1229
1230         if (mustProvide("lyxarrow")) {
1231                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
1232         }
1233
1234         return entities.str();
1235 }
1236
1237
1238 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
1239 {
1240         odocstringstream sgmlpreamble;
1241         // FIXME UNICODE
1242         docstring const basename(from_utf8(onlyPath(fname)));
1243
1244         FileMap::const_iterator end = IncludedFiles_.end();
1245         for (FileMap::const_iterator fi = IncludedFiles_.begin();
1246              fi != end; ++fi)
1247                 // FIXME UNICODE
1248                 sgmlpreamble << "\n<!ENTITY " << fi->first
1249                              << (isSGMLFileName(fi->second) ? " SYSTEM \"" : " \"")
1250                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
1251
1252         return sgmlpreamble.str();
1253 }
1254
1255
1256 void LaTeXFeatures::showStruct() const
1257 {
1258         lyxerr << "LyX needs the following commands when LaTeXing:"
1259                << "\n***** Packages:" << getPackages()
1260                << "\n***** Macros:" << to_utf8(getMacros())
1261                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
1262                << "\n***** done." << endl;
1263 }
1264
1265
1266 Buffer const & LaTeXFeatures::buffer() const
1267 {
1268         return *buffer_;
1269 }
1270
1271
1272 void LaTeXFeatures::setBuffer(Buffer const & buffer)
1273 {
1274         buffer_ = &buffer;
1275 }
1276
1277
1278 BufferParams const & LaTeXFeatures::bufferParams() const
1279 {
1280         return params_;
1281 }
1282
1283
1284 void LaTeXFeatures::getFloatDefinitions(odocstream & os) const
1285 {
1286         FloatList const & floats = params_.documentClass().floats();
1287
1288         // Here we will output the code to create the needed float styles.
1289         // We will try to do this as minimal as possible.
1290         // \floatstyle{ruled}
1291         // \newfloat{algorithm}{htbp}{loa}
1292         // \providecommand{\algorithmname}{Algorithm}
1293         // \floatname{algorithm}{\protect\algorithmname}
1294         UsedFloats::const_iterator cit = usedFloats_.begin();
1295         UsedFloats::const_iterator end = usedFloats_.end();
1296         for (; cit != end; ++cit) {
1297                 Floating const & fl = floats.getType(cit->first);
1298
1299                 // For builtin floats we do nothing.
1300                 if (fl.isPredefined())
1301                         continue;
1302
1303                 // We have to special case "table" and "figure"
1304                 if (fl.floattype() == "tabular" || fl.floattype() == "figure") {
1305                         // Output code to modify "table" or "figure"
1306                         // but only if builtin == false
1307                         // and that have to be true at this point in the
1308                         // function.
1309                         docstring const type = from_ascii(fl.floattype());
1310                         docstring const placement = from_ascii(fl.placement());
1311                         docstring const style = from_ascii(fl.style());
1312                         if (!style.empty()) {
1313                                 os << "\\floatstyle{" << style << "}\n"
1314                                    << "\\restylefloat{" << type << "}\n";
1315                         }
1316                         if (!placement.empty()) {
1317                                 os << "\\floatplacement{" << type << "}{"
1318                                    << placement << "}\n";
1319                         }
1320                 } else {
1321                         // The other non builtin floats.
1322
1323                         docstring const type = from_ascii(fl.floattype());
1324                         docstring const placement = from_ascii(fl.placement());
1325                         docstring const ext = from_ascii(fl.ext());
1326                         docstring const within = from_ascii(fl.within());
1327                         docstring const style = from_ascii(fl.style());
1328                         docstring const name = translateIfPossible(
1329                                         from_utf8(fl.name()),
1330                                         buffer().language()->code());
1331                         os << "\\floatstyle{" << style << "}\n"
1332                            << "\\newfloat{" << type << "}{" << placement
1333                            << "}{" << ext << '}';
1334                         if (!within.empty())
1335                                 os << '[' << within << ']';
1336                         os << '\n'
1337                            << "\\providecommand{\\" << type << "name}{"
1338                            << name << "}\n"
1339                            << "\\floatname{" << type << "}{\\protect\\"
1340                            << type << "name}\n";
1341
1342                         // What missing here is to code to minimalize the code
1343                         // output so that the same floatstyle will not be
1344                         // used several times, when the same style is still in
1345                         // effect. (Lgb)
1346                 }
1347                 if (cit->second)
1348                         os << "\n\\newsubfloat{" << from_ascii(fl.floattype()) << "}\n";
1349         }
1350 }
1351
1352
1353 } // namespace lyx