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