]> git.lyx.org Git - lyx.git/blobdiff - src/LaTeXFeatures.cpp
Adjust indentation after ff42fea8.
[lyx.git] / src / LaTeXFeatures.cpp
index d23f8b0b47157c37e387415b41554a4a244d6038..48c416dc0e778f96c7a564743d89497797299fb3 100644 (file)
@@ -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");
@@ -426,9 +408,14 @@ void LaTeXFeatures::require(set<string> 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 "
@@ -448,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 {
@@ -458,8 +443,6 @@ void LaTeXFeatures::useLayout(docstring const & layoutname)
                       << to_utf8(layoutname) << "' does not exist in this class"
                       << endl;
        }
-
-       --level;
 }
 
 
@@ -600,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();
@@ -613,6 +600,10 @@ 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();
@@ -701,9 +692,6 @@ char const * simplefeatures[] = {
        "fancybox",
        "calc",
        "units",
-       "tipa",
-       "tipx",
-       "tone",
        "framed",
        "soul",
        "textcomp",
@@ -735,7 +723,13 @@ char const * simplefeatures[] = {
        "multirow",
        "tfrupee",
        "shapepar",
-       "rsphrase"
+       "rsphrase",
+       "algorithm2e",
+       "sectionbox",
+       "tcolorbox",
+       "pdfcomment",
+       "fixme",
+       "todonotes"
 };
 
 char const * bibliofeatures[] = {
@@ -821,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<string, string>::const_iterator it =
+               params_.documentClass().packageOptions().begin();
+       map<string, string>::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;
@@ -831,16 +841,6 @@ 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<string, string>::const_iterator it =
-           params_.documentClass().packageOptions().begin();
-       map<string, string>::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) {
@@ -851,10 +851,25 @@ string const LaTeXFeatures::getPackages() const
        // 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
@@ -863,22 +878,10 @@ 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
-       // 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)
@@ -936,8 +939,29 @@ 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";
@@ -999,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
@@ -1019,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();
 }
 
@@ -1147,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"))
@@ -1400,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;
@@ -1412,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
@@ -1425,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);
@@ -1459,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()) {
@@ -1520,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));
                }
        }
 
@@ -1672,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";
        }
 }