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