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