X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FLaTeXFeatures.cpp;h=c68729f5aaf47768595126991941f1b3b511b176;hb=cb351665f432671eb263eec76164aa546abd7151;hp=2a3d099ff5c5a13f1f03c3d01790d9174b54a203;hpb=b86c984bf408b47fbd6fc92c4009f9129d0d1ef8;p=lyx.git diff --git a/src/LaTeXFeatures.cpp b/src/LaTeXFeatures.cpp index 2a3d099ff5..c68729f5aa 100644 --- a/src/LaTeXFeatures.cpp +++ b/src/LaTeXFeatures.cpp @@ -24,6 +24,7 @@ #include "Floating.h" #include "FloatList.h" #include "Language.h" +#include "LaTeXFonts.h" #include "LaTeXPackages.h" #include "Layout.h" #include "Lexer.h" @@ -183,19 +184,19 @@ static docstring const changetracking_dvipost_def = from_ascii( "\\dvipost{osend color pop}\n" "\\dvipost{cbstart color push Blue}\n" "\\dvipost{cbend color pop}\n" - "\\newcommand{\\lyxadded}[3]{\\changestart#3\\changeend}\n" - "\\newcommand{\\lyxdeleted}[3]{%\n" + "\\DeclareRobustCommand{\\lyxadded}[3]{\\changestart#3\\changeend}\n" + "\\DeclareRobustCommand{\\lyxdeleted}[3]{%\n" "\\changestart\\overstrikeon#3\\overstrikeoff\\changeend}\n"); static docstring const changetracking_xcolor_ulem_def = from_ascii( "%% Change tracking with ulem\n" - "\\newcommand{\\lyxadded}[3]{{\\color{lyxadded}{}#3}}\n" - "\\newcommand{\\lyxdeleted}[3]{{\\color{lyxdeleted}\\sout{#3}}}\n"); + "\\DeclareRobustCommand{\\lyxadded}[3]{{\\color{lyxadded}{}#3}}\n" + "\\DeclareRobustCommand{\\lyxdeleted}[3]{{\\color{lyxdeleted}\\sout{#3}}}\n"); static docstring const changetracking_xcolor_ulem_hyperref_def = from_ascii( "%% Change tracking with ulem\n" - "\\newcommand{\\lyxadded}[3]{{\\texorpdfstring{\\color{lyxadded}{}}{}#3}}\n" - "\\newcommand{\\lyxdeleted}[3]{{\\texorpdfstring{\\color{lyxdeleted}\\sout{#3}}{}}}\n"); + "\\DeclareRobustCommand{\\lyxadded}[3]{{\\texorpdfstring{\\color{lyxadded}{}}{}#3}}\n" + "\\DeclareRobustCommand{\\lyxdeleted}[3]{{\\texorpdfstring{\\color{lyxdeleted}\\sout{#3}}{}}}\n"); static docstring const changetracking_none_def = from_ascii( "\\newcommand{\\lyxadded}[3]{#3}\n" @@ -276,6 +277,61 @@ static docstring const lyxref_def = from_ascii( " {\\def\\RSlemtxt{lemma~}\\newref{lem}{name = \\RSlemtxt}}\n" " {}\n"); +// Make sure the columns are also outputed as rtl +static docstring const rtloutputdblcol_def = from_ascii( + "\\def\\@outputdblcol{%\n" + " \\if@firstcolumn\n" + " \\global \\@firstcolumnfalse\n" + " \\global \\setbox\\@leftcolumn \\box\\@outputbox\n" + " \\else\n" + " \\global \\@firstcolumntrue\n" + " \\setbox\\@outputbox \\vbox {%\n" + " \\hb@xt@\\textwidth {%\n" + " \\kern\\textwidth \\kern-\\columnwidth %**\n" + " \\hb@xt@\\columnwidth {%\n" + " \\box\\@leftcolumn \\hss}%\n" + " \\kern-\\textwidth %**\n" + " \\hfil\n" + " {\\normalcolor\\vrule \\@width\\columnseprule}%\n" + " \\hfil\n" + " \\kern-\\textwidth %**\n" + " \\hb@xt@\\columnwidth {%\n" + " \\box\\@outputbox \\hss}%\n" + " \\kern-\\columnwidth \\kern\\textwidth %**\n" + " }%\n" + " }%\n" + " \\@combinedblfloats\n" + " \\@outputpage\n" + " \\begingroup\n" + " \\@dblfloatplacement\n" + " \\@startdblcolumn\n" + " \\@whilesw\\if@fcolmade \\fi\n" + " {\\@outputpage\n" + " \\@startdblcolumn}%\n" + " \\endgroup\n" + " \\fi\n" + "}\n" + "\\@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"); + ///////////////////////////////////////////////////////////////////// // @@ -290,35 +346,70 @@ LaTeXFeatures::LaTeXFeatures(Buffer const & b, BufferParams const & p, {} -bool LaTeXFeatures::useBabel() const +LaTeXFeatures::LangPackage LaTeXFeatures::langPackage() const { - if (usePolyglossia()) - return false; - if (bufferParams().lang_package == "default") - return (lyxrc.language_package_selection != LyXRC::LP_NONE) - || (bufferParams().language->lang() != lyxrc.default_language - && !bufferParams().language->babel().empty()) - || this->hasLanguages(); - return (bufferParams().lang_package != "none") - || (bufferParams().language->lang() != lyxrc.default_language - && !bufferParams().language->babel().empty()) - || this->hasLanguages(); -} + string const local_lp = bufferParams().lang_package; + + // Locally, custom is just stored as a string + // in bufferParams().lang_package. + if (local_lp != "auto" + && local_lp != "babel" + && local_lp != "default" + && local_lp != "none") + return LANG_PACK_CUSTOM; + + if (local_lp == "none") + return LANG_PACK_NONE; + + /* If "auto" is selected, we load polyglossia if required, + * else we select babel. + * If babel is selected (either directly or via the "auto" + * mechanism), we really do only require it if we have + * a language that needs it. + */ + bool const polyglossia_required = + isRequired("polyglossia") + && isAvailable("polyglossia") + && !isProvided("babel") + && this->hasOnlyPolyglossiaLanguages(); + bool const babel_required = + !bufferParams().language->babel().empty() + || !this->getBabelLanguages().empty(); + + if (local_lp == "auto") { + // polyglossia requirement has priority over babel + if (polyglossia_required) + return LANG_PACK_POLYGLOSSIA; + else if (babel_required) + return LANG_PACK_BABEL; + } + if (local_lp == "babel") { + if (babel_required) + return LANG_PACK_BABEL; + } -bool LaTeXFeatures::usePolyglossia() const -{ - if (bufferParams().lang_package == "default") - return (lyxrc.language_package_selection == LyXRC::LP_AUTO) - && isRequired("polyglossia") - && isAvailable("polyglossia") - && !params_.documentClass().provides("babel") - && this->hasPolyglossiaLanguages(); - return (bufferParams().lang_package == "auto") - && isRequired("polyglossia") - && isAvailable("polyglossia") - && !params_.documentClass().provides("babel") - && this->hasPolyglossiaLanguages(); + if (local_lp == "default") { + switch (lyxrc.language_package_selection) { + case LyXRC::LP_AUTO: + // polyglossia requirement has priority over babel + if (polyglossia_required) + return LANG_PACK_POLYGLOSSIA; + else if (babel_required) + return LANG_PACK_BABEL; + break; + case LyXRC::LP_BABEL: + if (babel_required) + return LANG_PACK_BABEL; + break; + case LyXRC::LP_CUSTOM: + return LANG_PACK_CUSTOM; + case LyXRC::LP_NONE: + return LANG_PACK_NONE; + } + } + + return LANG_PACK_NONE; } @@ -396,9 +487,39 @@ bool LaTeXFeatures::isRequired(string const & name) const } +bool LaTeXFeatures::isProvided(string const & name) const +{ + if (params_.useNonTeXFonts) + return params_.documentClass().provides(name); + + bool const ot1 = (params_.font_encoding() == "default" + || params_.font_encoding() == "OT1"); + bool const complete = (params_.fonts_sans == "default") + && (params_.fonts_typewriter == "default"); + bool const nomath = (params_.fonts_math == "default"); + return params_.documentClass().provides(name) + || theLaTeXFonts().getLaTeXFont( + from_ascii(params_.fonts_roman)).provides(name, ot1, + complete, + nomath) + || theLaTeXFonts().getLaTeXFont( + from_ascii(params_.fonts_sans)).provides(name, ot1, + complete, + nomath) + || theLaTeXFonts().getLaTeXFont( + from_ascii(params_.fonts_typewriter)).provides(name, ot1, + complete, + nomath) + || theLaTeXFonts().getLaTeXFont( + from_ascii(params_.fonts_math)).provides(name, ot1, + complete, + nomath); +} + + bool LaTeXFeatures::mustProvide(string const & name) const { - return isRequired(name) && !params_.documentClass().provides(name); + return isRequired(name) && !isProvided(name); } @@ -451,10 +572,10 @@ void LaTeXFeatures::useFloat(string const & name, bool subfloat) void LaTeXFeatures::useLanguage(Language const * lang) { - if (!lang->babel().empty()) + if (!lang->babel().empty() || !lang->polyglossia().empty()) UsedLanguages_.insert(lang); - if (lang->lang() == "vietnamese") - require("vietnamese"); + if (!lang->requires().empty()) + require(lang->requires()); // CJK languages do not have a babel name. // They use the CJK package if (lang->encoding()->package() == Encoding::CJK) @@ -477,8 +598,12 @@ bool LaTeXFeatures::hasLanguages() const } -bool LaTeXFeatures::hasPolyglossiaLanguages() 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(); @@ -490,16 +615,38 @@ bool LaTeXFeatures::hasPolyglossiaLanguages() const } -string LaTeXFeatures::getLanguages() 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)->isPolyglossiaExclusive()) + return true; + } + return false; +} + + +string LaTeXFeatures::getBabelLanguages() const { ostringstream languages; + bool first = true; LanguageList::const_iterator const begin = UsedLanguages_.begin(); for (LanguageList::const_iterator cit = begin; cit != UsedLanguages_.end(); ++cit) { - if (cit != begin) + if ((*cit)->babel().empty()) + continue; + if (!first) languages << ','; + else + first = false; languages << (*cit)->babel(); } return languages.str(); @@ -562,8 +709,6 @@ char const * simplefeatures[] = { "fancybox", "calc", "units", - "tipa", - "tipx", "framed", "soul", "textcomp", @@ -577,7 +722,7 @@ char const * simplefeatures[] = { "mathrsfs", "mathabx", "mathtools", - "cancel", + // "cancel", "ascii", "url", "covington", @@ -591,10 +736,32 @@ char const * simplefeatures[] = { "pdfpages", "amscd", "slashed", + "multicol", "multirow", - "tfrupee" + "tfrupee", + "shapepar", + "rsphrase", + "algorithm2e" }; +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 *); } @@ -663,7 +830,6 @@ string const LaTeXFeatures::getColorOptions() const string const LaTeXFeatures::getPackages() const { ostringstream packages; - DocumentClass const & tclass = params_.documentClass(); // FIXME: currently, we can only load packages and macros known // to LyX. @@ -671,25 +837,45 @@ string const LaTeXFeatures::getPackages() const // also unknown packages can be requested. They are silently // swallowed now. We should change this eventually. - // + // 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)) + packages << "\\PassOptionsToPackage{" << it->second << "}" + << "{" << it->first << "}\n"; + // 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 @@ -698,6 +884,9 @@ string const LaTeXFeatures::getPackages() const if (mustProvide("fixltx2e")) packages << "\\usepackage{fixltx2e}\n"; + if (mustProvide("cancel") && + params_.use_package("cancel") != BufferParams::package_off) + packages << "\\usepackage{cancel}\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 @@ -726,6 +915,15 @@ string const LaTeXFeatures::getPackages() const params_.use_package("yhmath") != BufferParams::package_off) packages << "\\usepackage{yhmath}\n"; + // stmaryrd must be loaded after amsmath + if (mustProvide("stmaryrd") && + params_.use_package("stmaryrd") != BufferParams::package_off) + packages << "\\usepackage{stmaryrd}\n"; + + if (mustProvide("stackrel") && + params_.use_package("stackrel") != BufferParams::package_off) + packages << "\\usepackage{stackrel}\n"; + if (mustProvide("undertilde") && params_.use_package("undertilde") != BufferParams::package_off) packages << "\\usepackage{undertilde}\n"; @@ -734,9 +932,9 @@ string const LaTeXFeatures::getPackages() const // makeidx.sty if (isRequired("makeidx") || isRequired("splitidx")) { - if (!tclass.provides("makeidx") && !isRequired("splitidx")) + if (!isProvided("makeidx") && !isRequired("splitidx")) packages << "\\usepackage{makeidx}\n"; - if (!tclass.provides("splitidx") && isRequired("splitidx")) + if (mustProvide("splitidx")) packages << "\\usepackage{splitidx}\n"; packages << "\\makeindex\n"; } @@ -756,20 +954,39 @@ string const LaTeXFeatures::getPackages() const packages << "\\usepackage[ps,mover]{lyxskak}\n"; // setspace.sty - if (mustProvide("setspace") && !tclass.provides("SetSpace")) + 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 + // because esint must be loaded AFTER amslatex and 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"; + + // 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). // This special case is indicated by the "natbib-internal" key. - if (mustProvide("natbib") && !tclass.provides("natbib-internal")) { + if (mustProvide("natbib") && !isProvided("natbib-internal")) { packages << "\\usepackage["; if (params_.citeEngineType() == ENGINE_TYPE_NUMERICAL) packages << "numbers"; @@ -778,19 +995,29 @@ 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"; - // bibtopic -- the dot provides the aux file naming which - // LyX can detect. - if (mustProvide("bibtopic")) - packages << "\\usepackage[dot]{bibtopic}\n"; - if (mustProvide("xy")) packages << "\\usepackage[all]{xy}\n"; @@ -801,11 +1028,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 @@ -997,6 +1219,9 @@ docstring const LaTeXFeatures::getMacros() const if (mustProvide("ct-none")) macros << changetracking_none_def; + if (mustProvide("rtloutputdblcol")) + macros << rtloutputdblcol_def; + return macros.str(); } @@ -1013,7 +1238,10 @@ string const LaTeXFeatures::getBabelPresettings() const if (!params_.language->babel_presettings().empty()) tmp << params_.language->babel_presettings() << '\n'; - return tmp.str(); + if (!contains(tmp.str(), '@')) + return tmp.str(); + + return "\\makeatletter\n" + tmp.str() + "\\makeatother\n"; } @@ -1029,7 +1257,10 @@ string const LaTeXFeatures::getBabelPostsettings() const if (!params_.language->babel_postsettings().empty()) tmp << params_.language->babel_postsettings() << '\n'; - return tmp.str(); + if (!contains(tmp.str(), '@')) + return tmp.str(); + + return "\\makeatletter\n" + tmp.str() + "\\makeatother\n"; } @@ -1131,6 +1362,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(); @@ -1153,6 +1391,7 @@ docstring const LaTeXFeatures::getTClassHTMLStyles() const namespace { + docstring const getFloatI18nPreamble(docstring const & type, docstring const & name, Language const * lang, Encoding const & enc, bool const polyglossia) @@ -1457,7 +1696,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"; } }