X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FLaTeXFeatures.cpp;h=48c416dc0e778f96c7a564743d89497797299fb3;hb=10be0c43f20a27a1e6af82241ad5ec6b5cad3eca;hp=6b23fc537b4f69d497235965e6d6df51d5d403a4;hpb=56ece75ad9becba27ff1eaa12a0b8e3c68bb317b;p=lyx.git diff --git a/src/LaTeXFeatures.cpp b/src/LaTeXFeatures.cpp index 6b23fc537b..48c416dc0e 100644 --- a/src/LaTeXFeatures.cpp +++ b/src/LaTeXFeatures.cpp @@ -134,24 +134,6 @@ static docstring const paragraphleftindent_def = from_ascii( "}\n" "{\\end{list}}\n"); -static docstring const floatingfootnote_def = from_ascii( - "%% Special footnote code from the package 'stblftnt.sty'\n" - "%% Author: Robin Fairbairns -- Last revised Dec 13 1996\n" - "\\let\\SF@@footnote\\footnote\n" - "\\def\\footnote{\\ifx\\protect\\@typeset@protect\n" - " \\expandafter\\SF@@footnote\n" - " \\else\n" - " \\expandafter\\SF@gobble@opt\n" - " \\fi\n" - "}\n" - "\\expandafter\\def\\csname SF@gobble@opt \\endcsname{\\@ifnextchar[%]\n" - " \\SF@gobble@twobracket\n" - " \\@gobble\n" - "}\n" - "\\edef\\SF@gobble@opt{\\noexpand\\protect\n" - " \\expandafter\\noexpand\\csname SF@gobble@opt \\endcsname}\n" - "\\def\\SF@gobble@twobracket[#1]#2{}\n"); - static docstring const binom_def = from_ascii( "%% Binom macro for standard LaTeX users\n" "\\newcommand{\\binom}[2]{{#1 \\choose #2}}\n"); @@ -314,6 +296,25 @@ static docstring const rtloutputdblcol_def = from_ascii( "\\@mparswitchtrue\n"); +///////////////////////////////////////////////////////////////////// +// +// LyXHTML strings +// +///////////////////////////////////////////////////////////////////// + +static docstring const lyxnoun_style = from_ascii( + "dfn.lyxnoun {\n" + " font-variant: small-caps;\n" + "}\n"); + + +// this is how it normally renders, but it might not always do so. +static docstring const lyxstrikeout_style = from_ascii( + "del.strikeout {\n" + " text-decoration: line-through;\n" + "}\n"); + + ///////////////////////////////////////////////////////////////////// // // LaTeXFeatures @@ -407,9 +408,14 @@ void LaTeXFeatures::require(set const & names) void LaTeXFeatures::useLayout(docstring const & layoutname) +{ + useLayout(layoutname, 0); +} + + +void LaTeXFeatures::useLayout(docstring const & layoutname, int level) { // Some code to avoid loops in dependency definition - static int level = 0; const int maxlevel = 30; if (level > maxlevel) { lyxerr << "LaTeXFeatures::useLayout: maximum level of " @@ -429,9 +435,7 @@ void LaTeXFeatures::useLayout(docstring const & layoutname) require(layout.requires()); if (!layout.depends_on().empty()) { - ++level; - useLayout(layout.depends_on()); - --level; + useLayout(layout.depends_on(), level + 1); } usedLayouts_.push_back(layoutname); } else { @@ -439,8 +443,6 @@ void LaTeXFeatures::useLayout(docstring const & layoutname) << to_utf8(layoutname) << "' does not exist in this class" << endl; } - - --level; } @@ -581,6 +583,10 @@ bool LaTeXFeatures::hasLanguages() const bool LaTeXFeatures::hasOnlyPolyglossiaLanguages() const { + // first the main language + if (params_.language->polyglossia().empty()) + return false; + // now the secondary languages LanguageList::const_iterator const begin = UsedLanguages_.begin(); for (LanguageList::const_iterator cit = begin; cit != UsedLanguages_.end(); @@ -594,11 +600,15 @@ bool LaTeXFeatures::hasOnlyPolyglossiaLanguages() const bool LaTeXFeatures::hasPolyglossiaExclusiveLanguages() const { + // first the main language + if (params_.language->isPolyglossiaExclusive()) + return true; + // now the secondary languages LanguageList::const_iterator const begin = UsedLanguages_.begin(); for (LanguageList::const_iterator cit = begin; cit != UsedLanguages_.end(); ++cit) { - if ((*cit)->babel().empty() && !(*cit)->polyglossia().empty() && (*cit)->requires().empty()) + if ((*cit)->isPolyglossiaExclusive()) return true; } return false; @@ -682,9 +692,6 @@ char const * simplefeatures[] = { "fancybox", "calc", "units", - "tipa", - "tipx", - "tone", "framed", "soul", "textcomp", @@ -698,7 +705,7 @@ char const * simplefeatures[] = { "mathrsfs", "mathabx", "mathtools", - "cancel", + // "cancel", "ascii", "url", "covington", @@ -712,10 +719,37 @@ char const * simplefeatures[] = { "pdfpages", "amscd", "slashed", + "multicol", "multirow", - "tfrupee" + "tfrupee", + "shapepar", + "rsphrase", + "algorithm2e", + "sectionbox", + "tcolorbox", + "pdfcomment", + "fixme", + "todonotes" }; +char const * bibliofeatures[] = { + // Known bibliography packages (will be loaded before natbib) + "achicago", + "apacite", + "apalike", + "astron", + "authordate1-4", + "babelbib", + "bibgerm", + "chicago", + "chscite", + "harvard", + "mslapa", + "named" +}; + +int const nb_bibliofeatures = sizeof(bibliofeatures) / sizeof(char const *); + int const nb_simplefeatures = sizeof(simplefeatures) / sizeof(char const *); } @@ -781,6 +815,22 @@ string const LaTeXFeatures::getColorOptions() const } +string const LaTeXFeatures::getPackageOptions() const +{ + ostringstream packageopts; + // Output all the package option stuff we have been asked to do. + map::const_iterator it = + params_.documentClass().packageOptions().begin(); + map::const_iterator en = + params_.documentClass().packageOptions().end(); + for (; it != en; ++it) + if (mustProvide(it->first)) + packageopts << "\\PassOptionsToPackage{" << it->second << "}" + << "{" << it->first << "}\n"; + return packageopts.str(); +} + + string const LaTeXFeatures::getPackages() const { ostringstream packages; @@ -791,25 +841,35 @@ string const LaTeXFeatures::getPackages() const // also unknown packages can be requested. They are silently // swallowed now. We should change this eventually. - // // These are all the 'simple' includes. i.e // packages which we just \usepackage{package} - // for (int i = 0; i < nb_simplefeatures; ++i) { if (mustProvide(simplefeatures[i])) - packages << "\\usepackage{" - << simplefeatures[i] << "}\n"; + packages << "\\usepackage{" << simplefeatures[i] << "}\n"; } - // // The rest of these packages are somewhat more complicated // than those above. - // - // if fontspec is used, AMS packages have to be loaded before - // fontspec (in BufferParams) + // The tipa package and its extensions (tipx, tone) must not + // be loaded with non-TeX fonts, since fontspec includes the + // respective macros + if (mustProvide("tipa") && !params_.useNonTeXFonts) + packages << "\\usepackage{tipa}\n"; + if (mustProvide("tipx") && !params_.useNonTeXFonts) + packages << "\\usepackage{tipx}\n"; + if (mustProvide("tone") && !params_.useNonTeXFonts) + packages << "\\usepackage{tone}\n"; + + // if fontspec or newtxmath is used, AMS packages have to be loaded + // before fontspec (in BufferParams) string const amsPackages = loadAMSPackages(); - if (!params_.useNonTeXFonts && !amsPackages.empty()) + bool const ot1 = (params_.font_encoding() == "default" || params_.font_encoding() == "OT1"); + bool const use_newtxmath = + theLaTeXFonts().getLaTeXFont(from_ascii(params_.fonts_math)).getUsedPackage( + ot1, false, false) == "newtxmath"; + + if (!params_.useNonTeXFonts && !use_newtxmath && !amsPackages.empty()) packages << amsPackages; // fixltx2e must be loaded after amsthm, since amsthm produces an error with @@ -818,19 +878,10 @@ string const LaTeXFeatures::getPackages() const if (mustProvide("fixltx2e")) packages << "\\usepackage{fixltx2e}\n"; - // wasysym is a simple feature, but it must be after amsmath if both - // are used - // wasysym redefines some integrals (e.g. iint) from amsmath. That - // leads to inconsistent integrals. We only load this package if - // the document does not contain integrals (then isRequired("esint") - // is false) or if esint is used, since esint redefines all relevant - // integral symbols from wasysym and amsmath. - // See http://www.lyx.org/trac/ticket/1942 - if (mustProvide("wasysym") && - params_.use_package("wasysym") != BufferParams::package_off && - (params_.use_package("esint") != BufferParams::package_off || !isRequired("esint"))) - packages << "\\usepackage{wasysym}\n"; - + if (mustProvide("cancel") && + params_.use_package("cancel") != BufferParams::package_off) + packages << "\\usepackage{cancel}\n"; + // accents must be loaded after amsmath if (mustProvide("accents") && params_.use_package("accents") != BufferParams::package_off) @@ -888,12 +939,44 @@ string const LaTeXFeatures::getPackages() const if (mustProvide("setspace") && !isProvided("SetSpace")) packages << "\\usepackage{setspace}\n"; - // esint must be after amsmath and wasysym, since it will redeclare - // inconsistent integral symbols + // we need to assure that mhchem is loaded before esint and every other + // package that redefines command of amsmath because mhchem loads amlatex + // (this info is from the author of mhchem from June 2013) + if (mustProvide("mhchem") && + params_.use_package("mhchem") != BufferParams::package_off) + packages << "\\PassOptionsToPackage{version=3}{mhchem}\n" + "\\usepackage{mhchem}\n"; + + // wasysym is a simple feature, but it must be after amsmath if both + // are used + // wasysym redefines some integrals (e.g. iint) from amsmath. That + // leads to inconsistent integrals. We only load this package if + // the document does not contain integrals (then isRequired("esint") + // is false) or if esint is used, since esint redefines all relevant + // integral symbols from wasysym and amsmath. + // See http://www.lyx.org/trac/ticket/1942 + if (mustProvide("wasysym") && + params_.use_package("wasysym") != BufferParams::package_off && + (params_.use_package("esint") != BufferParams::package_off || !isRequired("esint"))) + packages << "\\usepackage{wasysym}\n"; + + // esint must be after amsmath (and packages requiring amsmath, like mhchem) + // and wasysym, since it will redeclare inconsistent integral symbols if (mustProvide("esint") && params_.use_package("esint") != BufferParams::package_off) packages << "\\usepackage{esint}\n"; + // Known bibliography packages (simple \usepackage{package}) + for (int i = 0; i < nb_bibliofeatures; ++i) { + if (mustProvide(bibliofeatures[i])) + packages << "\\usepackage{" + << bibliofeatures[i] << "}\n"; + } + + // Compatibility between achicago and natbib + if (mustProvide("achicago") && mustProvide("natbib")) + packages << "\\let\\achicagobib\\thebibliography\n"; + // natbib.sty // Some classes load natbib themselves, but still allow (or even require) // plain numeric citations (ReVTeX is such a case, see bug 5182). @@ -907,10 +990,25 @@ string const LaTeXFeatures::getPackages() const packages << "]{natbib}\n"; } + // Compatibility between achicago and natbib + if (mustProvide("achicago") && mustProvide("natbib")) { + packages << "\\let\\thebibliography\\achicagobib\n"; + packages << "\\let\\SCcite\\astroncite\n"; + packages << "\\let\\UnexpandableProtect\\protect\n"; + } + // jurabib -- we need version 0.6 at least. if (mustProvide("jurabib")) packages << "\\usepackage{jurabib}[2004/01/25]\n"; + // opcit -- we pass custombst as we output \bibliographystyle ourselves + if (mustProvide("opcit")) { + if (isRequired("hyperref")) + packages << "\\usepackage[custombst,hyperref]{opcit}\n"; + else + packages << "\\usepackage[custombst]{opcit}\n"; + } + // xargs -- we need version 1.09 at least if (mustProvide("xargs")) packages << "\\usepackage{xargs}[2008/03/08]\n"; @@ -925,11 +1023,6 @@ string const LaTeXFeatures::getPackages() const packages << "\\PassOptionsToPackage{normalem}{ulem}\n" "\\usepackage{ulem}\n"; - if (mustProvide("mhchem") && - params_.use_package("mhchem") != BufferParams::package_off) - packages << "\\PassOptionsToPackage{version=3}{mhchem}\n" - "\\usepackage{mhchem}\n"; - if (mustProvide("nomencl")) { // Make it work with the new and old version of the package, // but don't use the compatibility option since it is @@ -945,6 +1038,12 @@ string const LaTeXFeatures::getPackages() const if (mustProvide("subscript") && !isRequired("fixltx2e")) packages << "\\usepackage{subscript}\n"; + // footmisc must be loaded after setspace + // Set options here, load the package after the user preamble to + // avoid problems with manual loaded footmisc. + if (mustProvide("footmisc")) + packages << "\\PassOptionsToPackage{stable}{footmisc}\n"; + return packages.str(); } @@ -1073,8 +1172,6 @@ docstring const LaTeXFeatures::getMacros() const // other if (mustProvide("ParagraphLeftIndent")) macros << paragraphleftindent_def; - if (mustProvide("NeedLyXFootnoteCode")) - macros << floatingfootnote_def; // some problems with tex->html converters if (mustProvide("NeedTabularnewline")) @@ -1264,6 +1361,13 @@ docstring const LaTeXFeatures::getTClassHTMLStyles() const DocumentClass const & tclass = params_.documentClass(); odocstringstream tcpreamble; + if (mustProvide("noun")) + tcpreamble << lyxnoun_style; + // this isn't exact, but it won't hurt that much if it + // wasn't for this. + if (mustProvide("ulem")) + tcpreamble << lyxstrikeout_style; + tcpreamble << tclass.htmlstyles(); list::const_iterator cit = usedLayouts_.begin(); @@ -1319,7 +1423,8 @@ docstring const getFloatI18nPreamble(docstring const & type, docstring const i18npreamble(docstring const & templ, Language const * lang, - Encoding const & enc, bool const polyglossia) + Encoding const & enc, bool const polyglossia, + bool const need_fixedwidth) { if (templ.empty()) return templ; @@ -1331,6 +1436,24 @@ docstring const i18npreamble(docstring const & templ, Language const * lang, string const langenc = lang->encoding()->iconvName(); string const texenc = lang->encoding()->latexName(); string const bufenc = enc.iconvName(); + Encoding const * testenc(&enc); + bool lang_fallback = false; + bool ascii_fallback = false; + if (need_fixedwidth && !enc.hasFixedWidth()) { + if (lang->encoding()->hasFixedWidth()) { + testenc = lang->encoding(); + lang_fallback = true; + } else { + // We need a fixed width encoding, but both the buffer + // encoding and the language encoding are variable + // width. As a last fallback, try to convert to pure + // ASCII using the LaTeX commands defined in unicodesymbols. + testenc = encodings.fromLyXName("ascii"); + if (!testenc) + return docstring(); + ascii_fallback = true; + } + } // First and second character of plane 15 (Private Use Area) string const s1 = "\xf3\xb0\x80\x80"; // U+F0000 string const s2 = "\xf3\xb0\x80\x81"; // U+F0001 @@ -1344,16 +1467,18 @@ docstring const i18npreamble(docstring const & templ, Language const * lang, docstring const name = lang->translateLayout(key); // Check whether name can be encoded in the buffer encoding bool encodable = true; - for (size_t i = 0; i < name.size(); ++i) { - if (!enc.encodable(name[i])) { + for (size_t i = 0; i < name.size() && encodable; ++i) + if (!testenc->encodable(name[i])) encodable = false; - break; - } - } - string const translated = encodable ? to_utf8(name) - : "\\inputencoding{" + texenc + "}" - + s1 + langenc + s2 + to_utf8(name) - + s1 + bufenc + s2; + string translated; + if (encodable && !lang_fallback) + translated = to_utf8(name); + else if (ascii_fallback) + translated = to_ascii(testenc->latexString(name).first); + else + translated = "\\inputencoding{" + texenc + "}" + + s1 + langenc + s2 + to_utf8(name) + + s1 + bufenc + s2; preamble = subst(preamble, sub.str(), translated); } return from_utf8(preamble); @@ -1378,20 +1503,20 @@ docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel, bool use_po snippets.insert(i18npreamble(tclass[*cit].langpreamble(), buffer().language(), buffer().params().encoding(), - use_polyglossia)); + use_polyglossia, false)); // commands for language changing (for multilanguage documents) if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) { snippets.insert(i18npreamble( tclass[*cit].babelpreamble(), buffer().language(), buffer().params().encoding(), - use_polyglossia)); + use_polyglossia, false)); for (lang_it lit = lbeg; lit != lend; ++lit) snippets.insert(i18npreamble( tclass[*cit].babelpreamble(), *lit, buffer().params().encoding(), - use_polyglossia)); + use_polyglossia, false)); } } if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) { @@ -1439,24 +1564,30 @@ docstring const LaTeXFeatures::getTClassI18nPreamble(bool use_babel, bool use_po TextClass::InsetLayouts::const_iterator it = ils.find(*cit); if (it == ils.end()) continue; + // The listings package does not work with variable width + // encodings, only with fixed width encodings. Therefore we + // need to force a fixed width encoding for + // \lstlistlistingname and \lstlistingname (bug 9382). + // This needs to be consistent with InsetListings::latex(). + bool const need_fixedwidth = it->second.fixedwidthpreambleencoding(); // language dependent commands (once per document) snippets.insert(i18npreamble(it->second.langpreamble(), buffer().language(), buffer().params().encoding(), - use_polyglossia)); + use_polyglossia, need_fixedwidth)); // commands for language changing (for multilanguage documents) if ((use_babel || use_polyglossia) && !UsedLanguages_.empty()) { snippets.insert(i18npreamble( it->second.babelpreamble(), buffer().language(), buffer().params().encoding(), - use_polyglossia)); + use_polyglossia, need_fixedwidth)); for (lang_it lit = lbeg; lit != lend; ++lit) snippets.insert(i18npreamble( it->second.babelpreamble(), *lit, buffer().params().encoding(), - use_polyglossia)); + use_polyglossia, need_fixedwidth)); } } @@ -1591,7 +1722,8 @@ void LaTeXFeatures::getFloatDefinitions(odocstream & os) const // effect. (Lgb) } if (cit->second) - os << "\n\\newsubfloat{" << from_ascii(fl.floattype()) << "}\n"; + // The subfig package is loaded later + os << "\n\\AtBeginDocument{\\newsubfloat{" << from_ascii(fl.floattype()) << "}}\n"; } }