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