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