2 * \file LaTeXFeatures.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
12 * Full author contact details are available in file CREDITS.
17 #include "LaTeXFeatures.h"
20 #include "BufferParams.h"
22 #include "Converter.h"
25 #include "FloatList.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"
42 using namespace lyx::support
;
47 /////////////////////////////////////////////////////////////////////
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"
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"
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"
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"
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"
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"
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"
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"
113 static docstring
const paragraphleftindent_def
= from_ascii(
114 "\\newenvironment{LyXParagraphLeftIndent}[1]%\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"
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"
138 " \\expandafter\\SF@gobble@opt\n"
141 "\\expandafter\\def\\csname SF@gobble@opt \\endcsname{\\@ifnextchar[%]\n"
142 " \\SF@gobble@twobracket\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"
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"
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 /////////////////////////////////////////////////////////////////////
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()
302 support::FileName
const real_file
= libFileSearch("", "packages.lst");
304 if (real_file
.empty())
307 lex
.setFile(real_file
);
312 // Make sure that we are clean
315 bool finished
= false;
317 while (lex
.isOK() && !finished
) {
319 case Lexer::LEX_FEOF
:
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
;
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())
348 Layout
const & layout
= tclass
[layoutname
];
349 require(layout
.requires());
351 if (!layout
.depends_on().empty()) {
353 useLayout(layout
.depends_on());
356 usedLayouts_
.push_back(layoutname
);
358 lyxerr
<< "LaTeXFeatures::useLayout: layout `"
359 << to_utf8(layoutname
) << "' does not exist in this class"
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
))
375 // Is this layout already in usedInsetLayouts?
376 if (find(usedInsetLayouts_
.begin(), usedInsetLayouts_
.end(), lname
)
377 != usedInsetLayouts_
.end())
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())
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
;
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()) {
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
)
451 // japanese package is special
452 if (lang
->encoding()->package() == Encoding::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();
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());
503 char const * simplefeatures
[] = {
504 // note that the package order here will be the same in the LaTeX-output
511 // subfig is handled in BufferParams.cpp
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
545 // listings is handled in BufferParams.cpp
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
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";
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";
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
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
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";
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
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
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";
673 if (mustProvide("graphicx") && params_
.graphicsDriver
!= "none") {
674 if (params_
.graphicsDriver
== "default")
675 packages
<< "\\usepackage{graphicx}\n";
677 packages
<< "\\usepackage["
678 << params_
.graphicsDriver
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";
701 if (mustProvide("setspace") && !tclass
.provides("SetSpace"))
702 packages
<< "\\usepackage{setspace}\n";
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";
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";
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
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())
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';
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';
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';
852 if (mustProvide("binom") && !isRequired("amsmath"))
853 macros
<< binom_def
<< '\n';
854 if (mustProvide("mathcircumflex"))
855 macros
<< mathcircumflex_def
<< '\n';
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';
875 getFloatDefinitions(macros
);
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
;
897 macros
<< changetracking_xcolor_ulem_def
;
900 if (mustProvide("ct-none"))
901 macros
<< changetracking_none_def
;
907 string
const LaTeXFeatures::getBabelOptions() const
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';
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
);
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
);
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
);
992 tcpreamble
<< it
->second
.htmlstyle();
995 return tcpreamble
.str();
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";
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(
1043 from_ascii(buffer().language()->babel())));
1044 for (lang_it lit
= lbeg
; lit
!= lend
; ++lit
) {
1045 name
= translateIfPossible(flname
,
1047 snippets
.insert(getFloatI18nPreamble(
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
)
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 \"->\">" << '\n';
1072 return entities
.str();
1076 docstring
const LaTeXFeatures::getIncludedFiles(string
const & fname
) const
1078 odocstringstream sgmlpreamble
;
1080 docstring
const basename(from_utf8(onlyPath(fname
)));
1082 FileMap::const_iterator end
= IncludedFiles_
.end();
1083 for (FileMap::const_iterator fi
= IncludedFiles_
.begin();
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
1110 void LaTeXFeatures::setBuffer(Buffer
const & buffer
)
1116 BufferParams
const & LaTeXFeatures::bufferParams() const
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
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";
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
<< ']';
1174 << "\\providecommand{\\" << type
<< "name}{"
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
1185 os
<< "\n\\newsubfloat{" << from_ascii(fl
.type()) << "}\n";