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