]> git.lyx.org Git - lyx.git/blob - src/LaTeXFeatures.cpp
Simplify scrolling code. Instead of using the actionTriggered() signal we now 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_xcolor_soul_def =
177         "%% Change tracking with soul\n"
178         "\\newcommand{\\lyxadded}[3]{{\\color{lyxadded}#3}}\n"
179         "\\newcommand{\\lyxdeleted}[3]{{\\color{lyxdeleted}\\st{#3}}}\n";
180
181 static string const changetracking_xcolor_soul_hyperref_def =
182         "%% Change tracking with soul\n"
183         "\\newcommand{\\lyxadded}[3]{{\\texorpdfstring{\\color{lyxadded}}{}#3}}\n"
184         "\\newcommand{\\lyxdeleted}[3]{{\\texorpdfstring{\\color{lyxdeleted}\\st{#3}}{}}}\n";
185
186 static string const changetracking_none_def =
187         "\\newcommand{\\lyxadded}[3]{#3}\n"
188         "\\newcommand{\\lyxdeleted}[3]{}\n";
189
190 static string const textgreek_def =
191         "\\DeclareRobustCommand{\\greektext}{%\n"
192         " \\fontencoding{LGR}\\selectfont\n"
193         " \\def\\encodingdefault{LGR}}\n"
194         "\\DeclareRobustCommand{\\textgreek}[1]{\\leavevmode{\\greektext #1}}\n"
195         "\\DeclareFontEncoding{LGR}{}{}\n";
196
197 static string const textcyr_def =
198         "\\DeclareRobustCommand{\\cyrtext}{%\n"
199         " \\fontencoding{T2A}\\selectfont\n"
200         " \\def\\encodingdefault{T2A}}\n"
201         "\\DeclareRobustCommand{\\textcyr}[1]{\\leavevmode{\\cyrtext #1}}\n"
202         "\\DeclareFontEncoding{T2A}{}{}\n";
203
204 static string const newlyxcommand_def =
205         "%% Math macros with multiple optional parameters\n"
206         "% #1<-\\foo\n"
207         "\\def\\newlyxcommand#1{\n"
208         "  \\@ifnextchar[%]\n"
209         "  {\\newlyxcommand@arity{#1}}\n"
210         "  {\\newlyxcommand@arity{#1}[0]}\n"
211         "}\n"
212         "\n"
213         "% #1<-\\foo #2<-arity\n"
214         "\\def\\newlyxcommand@arity#1[#2]{\n"
215         "  \\@ifnextchar[%]\n"
216         "  {\\newlyxcommand@firstopt{#1}{}{#2}}\n"
217         "  {\\newlyxcommand@def#1{#2}}\n"
218         "}\n"
219         "\n"
220         "% #1<-\\foo #2<-iii #3<-arity #4<-default value for (#2+1)th argument\n"
221         "\\def\\newlyxcommand@firstopt#1#2#3[#4]{\n"
222         "  % ##1<-\\foo@\n"
223         "  \\def\\@defclause##1{\n"
224         "    \\def#1{\n"
225         "      \\@ifnextchar[%]\n"
226         "      {##1{}{#4}}\n"
227         "      {##1{}{#4}[#4]}}\n"
228         "  }\n"
229         "  \\expandafter\\@defclause\\csname\\expandafter\\@gobble\\string#1@\\endcsname\n"
230         "  \\@ifnextchar[%]\n"
231         "  {\\newlyxcommand@opt{#1}{#2}{#3}}\n"
232         "  {\\newlyxcommand@last{#1}{#2}{#3}[#4]}\n"
233         "}\n"
234         "\n"
235         "\\begingroup\n"
236         "\\catcode`\\Q=3\n"
237         "\\gdef\\@myempty{Q}\n"
238         "\\endgroup\n"
239         "\n"
240         "% #1<-\\foo #2<-iii #3<-arity #4<-default value for (#2+1)th argument\n"
241         "\\def\\newlyxcommand@opt#1#2#3[#4]{\n"
242         "  % ##1<-\\foo@iii ##2<-\\foo@iiii \n"
243         "  % ####1<-{a}{b}{c} ####2<-default value ####3<- default arg\n"
244         "  \\def\\@defclause##1##2{\n"
245         "    \\def##1####1####2[####3]{\n"
246         "      \\ifx\\@myempty####3\\@myempty%\n"
247         "        \\def\\@callnext{\n"
248         "          \\@ifnextchar[%]\n"
249         "          {##2{####1{####2}}{#4}}\n"
250         "          {##2{####1{####2}}{#4}[#4]}\n"
251         "      }\n"
252         "      \\else\n"
253         "        \\def\\@callnext{\n"
254         "          \\@ifnextchar[%]\n"
255         "          {##2{####1{####3}}{#4}}\n"
256         "          {##2{####1{####3}}{#4}[#4]}\n"
257         "      }\n"
258         "      \\fi\n"
259         "      \\@callnext\n"
260         "    }\n"
261         "  }\n"
262         "  \\expandafter\\def\\expandafter\\@clausename\\expandafter{\\csname\\expandafter\\@gobble\\string#1@#2\\endcsname}\n"
263         "  \\expandafter\\def\\expandafter\\@nextclausename\\expandafter{\\csname\\expandafter\\@gobble\\string#1@#2i\\endcsname}\n"
264         "  \\expandafter\\expandafter\\expandafter  \n"
265         "  \\@defclause\\expandafter\\@clausename\\@nextclausename\n"
266         "  \\@ifnextchar[%]\n"
267         "  {\\newlyxcommand@opt{#1}{#2i}{#3}}\n"
268         "  {\\newlyxcommand@last{#1}{#2i}{#3}[#4]}\n"
269         "}\n"
270         "\n"
271         "% #1<-\\foo #2<-iii #3<-arity #4<-default value for (#2+1)th argument\n"
272         "\\def\\newlyxcommand@last#1#2#3[#4]{\n"
273         "  \\def\\@defclause##1##2{\n"
274         "    \\def##1####1####2[####3]{\n"
275         "      \\ifx\\@myempty####3\\@myempty%\n"
276         "        \\def\\@callnext{##2####1{####2}}\n"
277         "      \\else\n"
278         "        \\def\\@callnext{##2####1{####3}}\n"
279         "      \\fi\n"
280         "      \\@callnext\n"
281         "    }\n"
282         "  }\n"
283         "  \\expandafter\\def\\expandafter\\@clausename\\expandafter{\\csname\\expandafter\\@gobble\\string#1@#2\\endcsname}\n"
284         "  \\expandafter\\def\\expandafter\\@nextclausename\\expandafter{\\csname\\expandafter\\@gobble\\string#1@#2i\\endcsname}\n"
285         "  \\expandafter\\expandafter\\expandafter\n"
286         "  \\@defclause\\expandafter\\@clausename\\@nextclausename\n"
287         "  \\expandafter\\newlyxcommand@def\\csname\\expandafter\\@gobble\\string#1@#2i\\endcsname{#3}\n"
288         "}\n"
289         "\n"
290         "% #1<-\\foo #2<-arity #3<-definition\n"
291         "\\def\\newlyxcommand@def#1#2#3{\n"
292         "  \\ifx#20\n"
293         "  \\def#1{#3}\n"
294         "  \\else\n"
295         "  \\def\\@splitargs##1#2##2.{\\def#1##1#2}\\@splitargs##1##2##3##4##5##6##7##8##9.{#3}\n"
296         "  \\fi\n"
297         "}\n";
298         
299 /////////////////////////////////////////////////////////////////////
300 //
301 // LaTeXFeatures
302 //
303 /////////////////////////////////////////////////////////////////////
304
305 LaTeXFeatures::PackagesList LaTeXFeatures::packages_;
306
307
308 LaTeXFeatures::LaTeXFeatures(Buffer const & b, BufferParams const & p,
309                              OutputParams const & r)
310         : buffer_(&b), params_(p), runparams_(r)
311 {}
312
313
314 bool LaTeXFeatures::useBabel() const
315 {
316         return lyxrc.language_use_babel ||
317                 (bufferParams().language->lang() != lyxrc.default_language &&
318                  !bufferParams().language->babel().empty()) ||
319                 this->hasLanguages();
320 }
321
322
323 void LaTeXFeatures::require(string const & name)
324 {
325         if (isRequired(name))
326                 return;
327
328         features_.push_back(name);
329 }
330
331
332 void LaTeXFeatures::getAvailable()
333 {
334         Lexer lex(0, 0);
335         support::FileName const real_file = libFileSearch("", "packages.lst");
336
337         if (real_file.empty())
338                 return;
339
340         lex.setFile(real_file);
341
342         if (!lex.isOK())
343                 return;
344
345         // Make sure that we are clean
346         packages_.clear();
347
348         bool finished = false;
349         // Parse config-file
350         while (lex.isOK() && !finished) {
351                 switch (lex.lex()) {
352                 case Lexer::LEX_FEOF:
353                         finished = true;
354                         break;
355                 default:
356                         string const name = lex.getString();
357                         PackagesList::const_iterator begin = packages_.begin();
358                         PackagesList::const_iterator end   = packages_.end();
359                         if (find(begin, end, name) == end)
360                                 packages_.push_back(name);
361                 }
362         }
363 }
364
365
366 void LaTeXFeatures::useLayout(docstring const & layoutname)
367 {
368         // Some code to avoid loops in dependency definition
369         static int level = 0;
370         const int maxlevel = 30;
371         if (level > maxlevel) {
372                 lyxerr << "LaTeXFeatures::useLayout: maximum level of "
373                        << "recursion attained by layout "
374                        << to_utf8(layoutname) << endl;
375                 return;
376         }
377
378         TextClass const & tclass = params_.getTextClass();
379         if (tclass.hasLayout(layoutname)) {
380                 // Is this layout already in usedLayouts?
381                 list<docstring>::const_iterator cit = usedLayouts_.begin();
382                 list<docstring>::const_iterator end = usedLayouts_.end();
383                 for (; cit != end; ++cit) {
384                         if (layoutname == *cit)
385                                 return;
386                 }
387
388                 LayoutPtr const & lyt = tclass[layoutname];
389                 if (!lyt->depends_on().empty()) {
390                         ++level;
391                         useLayout(lyt->depends_on());
392                         --level;
393                 }
394                 usedLayouts_.push_back(layoutname);
395         } else {
396                 lyxerr << "LaTeXFeatures::useLayout: layout `"
397                        << to_utf8(layoutname) << "' does not exist in this class"
398                        << endl;
399         }
400
401         --level;
402 }
403
404
405 bool LaTeXFeatures::isRequired(string const & name) const
406 {
407         return find(features_.begin(), features_.end(), name) != features_.end();
408 }
409
410
411 bool LaTeXFeatures::mustProvide(string const & name) const
412 {
413         return isRequired(name) && !params_.getTextClass().provides(name);
414 }
415
416
417 bool LaTeXFeatures::isAvailable(string const & name)
418 {
419         string n = name;
420         if (packages_.empty())
421                 getAvailable();
422         size_t loc = n.rfind(".sty");
423         if (loc == n.length() - 4) 
424                 n = n.erase(name.length() - 4);
425         return find(packages_.begin(), packages_.end(), n) != packages_.end();
426 }
427
428
429 void LaTeXFeatures::addPreambleSnippet(string const & preamble)
430 {
431         FeaturesList::const_iterator begin = preamble_snippets_.begin();
432         FeaturesList::const_iterator end   = preamble_snippets_.end();
433         if (find(begin, end, preamble) == end)
434                 preamble_snippets_.push_back(preamble);
435 }
436
437
438 void LaTeXFeatures::useFloat(string const & name)
439 {
440         usedFloats_.insert(name);
441         // We only need float.sty if we use non builtin floats, or if we
442         // use the "H" modifier. This includes modified table and
443         // figure floats. (Lgb)
444         Floating const & fl = params_.getTextClass().floats().getType(name);
445         if (!fl.type().empty() && !fl.builtin()) {
446                 require("float");
447         }
448 }
449
450
451 void LaTeXFeatures::useLanguage(Language const * lang)
452 {
453         if (!lang->babel().empty())
454                 UsedLanguages_.insert(lang);
455         // CJK languages do not have a babel name.
456         // They use the CJK package
457         if (lang->encoding()->package() == Encoding::CJK)
458                 require("CJK");
459 }
460
461
462 void LaTeXFeatures::includeFile(docstring const & key, string const & name)
463 {
464         IncludedFiles_[key] = name;
465 }
466
467
468 bool LaTeXFeatures::hasLanguages() const
469 {
470         return !UsedLanguages_.empty();
471 }
472
473
474 string LaTeXFeatures::getLanguages() const
475 {
476         ostringstream languages;
477
478         LanguageList::const_iterator const begin = UsedLanguages_.begin();
479         for (LanguageList::const_iterator cit = begin;
480              cit != UsedLanguages_.end();
481              ++cit) {
482                 if (cit != begin)
483                         languages << ',';
484                 languages << (*cit)->babel();
485         }
486         return languages.str();
487 }
488
489
490 set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
491 {
492         // This does only find encodings of languages supported by babel, but
493         // that does not matter since we don't have a language with an
494         // encoding supported by inputenc but without babel support.
495         set<string> encodings;
496         LanguageList::const_iterator it  = UsedLanguages_.begin();
497         LanguageList::const_iterator end = UsedLanguages_.end();
498         for (; it != end; ++it)
499                 if ((*it)->encoding()->latexName() != doc_encoding &&
500                     (*it)->encoding()->package() == Encoding::inputenc)
501                         encodings.insert((*it)->encoding()->latexName());
502         return encodings;
503 }
504
505 namespace {
506
507 char const * simplefeatures[] = {
508 // note that the package order here will be the same in the LaTeX-output
509         "array",
510         "verbatim",
511         "longtable",
512         "rotating",
513         "latexsym",
514         "pifont",
515         "subfigure",
516         "varioref",
517         "prettyref",
518         /*For a successful cooperation of the `wrapfig' package with the
519           `float' package you should load the `wrapfig' package *after*
520           the `float' package. See the caption package documentation
521           for explanation.*/
522         "float",
523         "rotfloat",
524         "wrapfig",
525         "booktabs",
526         "dvipost",
527         "fancybox",
528         "calc",
529         "units",
530         "tipa",
531         "framed",
532         "soul",
533         "textcomp",
534         "pmboxdraw",
535         "bbding",
536         "ifsym",
537         "marvosym",
538         "txfonts",
539         "mathrsfs",
540         "ascii",
541         "url",
542         "covington",
543         "csquotes",
544         "enumitem",
545         "endnotes",
546         "ifthen",
547         "amsthm",
548         "listings"
549 };
550
551 int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *);
552
553 }
554
555
556 string const LaTeXFeatures::getPackages() const
557 {
558         ostringstream packages;
559         TextClass const & tclass = params_.getTextClass();
560
561         // FIXME: currently, we can only load packages and macros known
562         // to LyX.
563         // However, with the Require tag of layouts/custom insets,
564         // also inknown packages can be requested. They are silently
565         // swallowed now. We should change this eventually.
566
567         //
568         //  These are all the 'simple' includes.  i.e
569         //  packages which we just \usepackage{package}
570         //
571         for (int i = 0; i < nb_simplefeatures; ++i) {
572                 if (mustProvide(simplefeatures[i]))
573                         packages << "\\usepackage{"
574                                  << simplefeatures[i] << "}\n";
575         }
576
577         //
578         // The rest of these packages are somewhat more complicated
579         // than those above.
580         //
581
582         // esint is preferred for esintoramsmath
583         if ((mustProvide("amsmath") &&
584              params_.use_amsmath != BufferParams::package_off) ||
585             (mustProvide("esintoramsmath") &&
586              params_.use_esint == BufferParams::package_off)) {
587                 packages << "\\usepackage{amsmath}\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         // [x]color.sty
603         if (mustProvide("color") || mustProvide("xcolor")) {
604                 string const package =
605                         (mustProvide("xcolor") ? "xcolor" : "color");
606                 if (params_.graphicsDriver == "default")
607                         packages << "\\usepackage{" << package << "}\n";
608                 else
609                         packages << "\\usepackage["
610                                  << params_.graphicsDriver
611                                  << "]{" << package << "}\n";
612         }
613
614         // pdfcolmk must be loaded after color
615         if (mustProvide("pdfcolmk")) {
616                 packages << "\\usepackage{pdfcolmk}\n";
617         }
618
619         // makeidx.sty
620         if (isRequired("makeidx")) {
621                 if (!tclass.provides("makeidx"))
622                         packages << "\\usepackage{makeidx}\n";
623                 packages << "\\makeindex\n";
624         }
625
626         // graphicx.sty
627         if (mustProvide("graphicx") && params_.graphicsDriver != "none") {
628                 if (params_.graphicsDriver == "default")
629                         packages << "\\usepackage{graphicx}\n";
630                 else
631                         packages << "\\usepackage["
632                                  << params_.graphicsDriver
633                                  << "]{graphicx}\n";
634         }
635         // shadecolor for shaded
636         if (isRequired("framed") && mustProvide("color")) {
637                 RGBColor c = rgbFromHexName(lcolor.getX11Name(Color_shadedbg));
638                 //255.0 to force conversion to double
639                 //NOTE As Jürgen Spitzmüller pointed out, an alternative would be
640                 //to use the xcolor package instead, and then we can do
641                 // \define{shadcolor}{RGB}...
642                 //and not do any conversion. We'd then need to require xcolor
643                 //in InsetNote::validate().
644                 int const stmSize = packages.precision(2);
645                 packages << "\\definecolor{shadecolor}{rgb}{"
646                         << c.r / 255.0 << ',' << c.g / 255.0 << ',' << c.b / 255.0 << "}\n";
647                 packages.precision(stmSize);
648         }
649
650         // lyxskak.sty --- newer chess support based on skak.sty
651         if (mustProvide("chess")) {
652                 packages << "\\usepackage[ps,mover]{lyxskak}\n";
653         }
654
655         // setspace.sty
656         if (mustProvide("setspace") && !tclass.provides("SetSpace"))
657                     packages << "\\usepackage{setspace}\n";
658
659         // amssymb.sty
660         if (mustProvide("amssymb")
661             || params_.use_amsmath == BufferParams::package_on)
662                 packages << "\\usepackage{amssymb}\n";
663
664         // esint must be after amsmath and wasysym, since it will redeclare
665         // inconsistent integral symbols
666         if ((mustProvide("esint") || mustProvide("esintoramsmath")) &&
667             params_.use_esint != BufferParams::package_off)
668                 packages << "\\usepackage{esint}\n";
669
670         // natbib.sty
671         if (mustProvide("natbib")) {
672                 packages << "\\usepackage[";
673                 if (params_.getEngine() == biblio::ENGINE_NATBIB_NUMERICAL) {
674                         packages << "numbers";
675                 } else {
676                         packages << "authoryear";
677                 }
678                 packages << "]{natbib}\n";
679         }
680
681         // jurabib -- we need version 0.6 at least.
682         if (mustProvide("jurabib")) {
683                 packages << "\\usepackage{jurabib}[2004/01/25]\n";
684         }
685
686         // bibtopic -- the dot provides the aux file naming which
687         // LyX can detect.
688         if (mustProvide("bibtopic")) {
689                 packages << "\\usepackage[dot]{bibtopic}\n";
690         }
691
692         if (mustProvide("xy"))
693                 packages << "\\usepackage[all]{xy}\n";
694
695         if (mustProvide("nomencl")) {
696                 // Make it work with the new and old version of the package,
697                 // but don't use the compatibility option since it is
698                 // incompatible to other packages.
699                 packages << "\\usepackage{nomencl}\n"
700                             "% the following is useful when we have the old nomencl.sty package\n"
701                             "\\providecommand{\\printnomenclature}{\\printglossary}\n"
702                             "\\providecommand{\\makenomenclature}{\\makeglossary}\n"
703                             "\\makenomenclature\n";
704         }
705
706         return packages.str();
707 }
708
709
710 string const LaTeXFeatures::getMacros() const
711 {
712         ostringstream macros;
713
714         if (!preamble_snippets_.empty())
715                 macros << '\n';
716         FeaturesList::const_iterator pit  = preamble_snippets_.begin();
717         FeaturesList::const_iterator pend = preamble_snippets_.end();
718         for (; pit != pend; ++pit)
719                 macros << *pit << '\n';
720
721         if (mustProvide("LyX"))
722                 macros << lyx_def << '\n';
723
724         if (mustProvide("lyxline"))
725                 macros << lyxline_def << '\n';
726
727         if (mustProvide("noun"))
728                 macros << noun_def << '\n';
729
730         if (mustProvide("lyxarrow"))
731                 macros << lyxarrow_def << '\n';
732
733         if (mustProvide("textgreek"))
734                 macros << textgreek_def << '\n';
735
736         if (mustProvide("textcyr"))
737                 macros << textcyr_def << '\n';
738
739         // quotes.
740         if (mustProvide("quotesinglbase"))
741                 macros << quotesinglbase_def << '\n';
742         if (mustProvide("quotedblbase"))
743                 macros << quotedblbase_def << '\n';
744         if (mustProvide("guilsinglleft"))
745                 macros << guilsinglleft_def << '\n';
746         if (mustProvide("guilsinglright"))
747                 macros << guilsinglright_def << '\n';
748         if (mustProvide("guillemotleft"))
749                 macros << guillemotleft_def << '\n';
750         if (mustProvide("guillemotright"))
751                 macros << guillemotright_def << '\n';
752
753         // Math mode
754         if (mustProvide("boldsymbol") && !isRequired("amsmath"))
755                 macros << boldsymbol_def << '\n';
756         if (mustProvide("binom") && !isRequired("amsmath"))
757                 macros << binom_def << '\n';
758         if (mustProvide("mathcircumflex"))
759                 macros << mathcircumflex_def << '\n';
760         if (mustProvide("newlyxcommand"))
761                 macros << newlyxcommand_def << '\n';
762
763         // other
764         if (mustProvide("ParagraphLeftIndent"))
765                 macros << paragraphleftindent_def;
766         if (mustProvide("NeedLyXFootnoteCode"))
767                 macros << floatingfootnote_def;
768
769         // some problems with tex->html converters
770         if (mustProvide("NeedTabularnewline"))
771                 macros << tabularnewline_def;
772
773         // greyedout environment (note inset)
774         if (mustProvide("lyxgreyedout"))
775                 macros << lyxgreyedout_def;
776
777         if (mustProvide("lyxdot"))
778                 macros << lyxdot_def << '\n';
779
780         // floats
781         getFloatDefinitions(macros);
782
783         // change tracking
784         if (mustProvide("ct-dvipost"))
785                 macros << changetracking_dvipost_def;
786
787         if (mustProvide("ct-xcolor-soul")) {
788                 int const prec = macros.precision(2);
789         
790                 RGBColor cadd = rgbFromHexName(lcolor.getX11Name(Color_addedtext));
791                 macros << "\\providecolor{lyxadded}{rgb}{"
792                        << cadd.r / 255.0 << ',' << cadd.g / 255.0 << ',' << cadd.b / 255.0 << "}\n";
793
794                 RGBColor cdel = rgbFromHexName(lcolor.getX11Name(Color_deletedtext));
795                 macros << "\\providecolor{lyxdeleted}{rgb}{"
796                        << cdel.r / 255.0 << ',' << cdel.g / 255.0 << ',' << cdel.b / 255.0 << "}\n";
797
798                 macros.precision(prec);
799                 
800                 if (isRequired("hyperref"))
801                         macros << changetracking_xcolor_soul_hyperref_def;
802                 else
803                         macros << changetracking_xcolor_soul_def;
804         }
805
806         if (mustProvide("ct-none"))
807                 macros << changetracking_none_def;
808
809         return macros.str();
810 }
811
812
813 string const LaTeXFeatures::getBabelOptions() const
814 {
815         ostringstream tmp;
816
817         LanguageList::const_iterator it  = UsedLanguages_.begin();
818         LanguageList::const_iterator end =  UsedLanguages_.end();
819         for (; it != end; ++it)
820                 if (!(*it)->latex_options().empty())
821                         tmp << (*it)->latex_options() << '\n';
822         if (!params_.language->latex_options().empty())
823                 tmp << params_.language->latex_options() << '\n';
824
825         return tmp.str();
826 }
827
828
829 docstring const LaTeXFeatures::getTClassPreamble() const
830 {
831         // the text class specific preamble
832         TextClass const & tclass = params_.getTextClass();
833         odocstringstream tcpreamble;
834
835         tcpreamble << tclass.preamble();
836
837         list<docstring>::const_iterator cit = usedLayouts_.begin();
838         list<docstring>::const_iterator end = usedLayouts_.end();
839         for (; cit != end; ++cit) {
840                 tcpreamble << tclass[*cit]->preamble();
841         }
842
843         return tcpreamble.str();
844 }
845
846
847 docstring const LaTeXFeatures::getLyXSGMLEntities() const
848 {
849         // Definition of entities used in the document that are LyX related.
850         odocstringstream entities;
851
852         if (mustProvide("lyxarrow")) {
853                 entities << "<!ENTITY lyxarrow \"-&gt;\">" << '\n';
854         }
855
856         return entities.str();
857 }
858
859
860 docstring const LaTeXFeatures::getIncludedFiles(string const & fname) const
861 {
862         odocstringstream sgmlpreamble;
863         // FIXME UNICODE
864         docstring const basename(from_utf8(onlyPath(fname)));
865
866         FileMap::const_iterator end = IncludedFiles_.end();
867         for (FileMap::const_iterator fi = IncludedFiles_.begin();
868              fi != end; ++fi)
869                 // FIXME UNICODE
870                 sgmlpreamble << "\n<!ENTITY " << fi->first
871                              << (isSGMLFilename(fi->second) ? " SYSTEM \"" : " \"")
872                              << makeRelPath(from_utf8(fi->second), basename) << "\">";
873
874         return sgmlpreamble.str();
875 }
876
877
878 void LaTeXFeatures::showStruct() const {
879         lyxerr << "LyX needs the following commands when LaTeXing:"
880                << "\n***** Packages:" << getPackages()
881                << "\n***** Macros:" << getMacros()
882                << "\n***** Textclass stuff:" << to_utf8(getTClassPreamble())
883                << "\n***** done." << endl;
884 }
885
886
887 Buffer const & LaTeXFeatures::buffer() const
888 {
889         return *buffer_;
890 }
891
892
893 void LaTeXFeatures::setBuffer(Buffer const & buffer)
894 {
895         buffer_ = &buffer;
896 }
897
898
899 BufferParams const & LaTeXFeatures::bufferParams() const
900 {
901         return params_;
902 }
903
904
905 void LaTeXFeatures::getFloatDefinitions(ostream & os) const
906 {
907         FloatList const & floats = params_.getTextClass().floats();
908
909         // Here we will output the code to create the needed float styles.
910         // We will try to do this as minimal as possible.
911         // \floatstyle{ruled}
912         // \newfloat{algorithm}{htbp}{loa}
913         // \floatname{algorithm}{Algorithm}
914         UsedFloats::const_iterator cit = usedFloats_.begin();
915         UsedFloats::const_iterator end = usedFloats_.end();
916         // ostringstream floats;
917         for (; cit != end; ++cit) {
918                 Floating const & fl = floats.getType((*cit));
919
920                 // For builtin floats we do nothing.
921                 if (fl.builtin()) continue;
922
923                 // We have to special case "table" and "figure"
924                 if (fl.type() == "tabular" || fl.type() == "figure") {
925                         // Output code to modify "table" or "figure"
926                         // but only if builtin == false
927                         // and that have to be true at this point in the
928                         // function.
929                         string const type = fl.type();
930                         string const placement = fl.placement();
931                         string const style = fl.style();
932                         if (!style.empty()) {
933                                 os << "\\floatstyle{" << style << "}\n"
934                                    << "\\restylefloat{" << type << "}\n";
935                         }
936                         if (!placement.empty()) {
937                                 os << "\\floatplacement{" << type << "}{"
938                                    << placement << "}\n";
939                         }
940                 } else {
941                         // The other non builtin floats.
942
943                         string const type = fl.type();
944                         string const placement = fl.placement();
945                         string const ext = fl.ext();
946                         string const within = fl.within();
947                         string const style = fl.style();
948                         string const name = fl.name();
949                         os << "\\floatstyle{" << style << "}\n"
950                            << "\\newfloat{" << type << "}{" << placement
951                            << "}{" << ext << '}';
952                         if (!within.empty())
953                                 os << '[' << within << ']';
954                         os << '\n'
955                            << "\\floatname{" << type << "}{"
956                            << name << "}\n";
957
958                         // What missing here is to code to minimalize the code
959                         // output so that the same floatstyle will not be
960                         // used several times, when the same style is still in
961                         // effect. (Lgb)
962                 }
963         }
964 }
965
966
967 } // namespace lyx