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