]> git.lyx.org Git - lyx.git/blobdiff - src/LaTeXFeatures.cpp
#5502 add binding for full screen toggle on mac
[lyx.git] / src / LaTeXFeatures.cpp
index a7974b62c5ac062ef2bb95ee0599e71de04710bc..dcfb44c8ecc86ed53dbc3583858bf5cf504f04a0 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");
@@ -684,6 +666,30 @@ set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
        return encodings;
 }
 
+
+void LaTeXFeatures::getFontEncodings(vector<string> & encodings) const
+{
+       // these must be loaded if glyphs of this script
+       // are used (notwithstanding the language)
+       if (mustProvide("textgreek"))
+               encodings.insert(encodings.begin(), "LGR");
+       if (mustProvide("textcyr"))
+               encodings.insert(encodings.begin(), "T2A");
+
+       LanguageList::const_iterator it  = UsedLanguages_.begin();
+       LanguageList::const_iterator end = UsedLanguages_.end();
+       for (; it != end; ++it)
+               if (!(*it)->fontenc().empty()
+                   && ascii_lowercase((*it)->fontenc()) != "none") {
+                       vector<string> extraencs = getVectorFromString((*it)->fontenc());
+                       vector<string>::const_iterator fit = extraencs.begin();
+                       for (; fit != extraencs.end(); ++fit) {
+                               if (find(encodings.begin(), encodings.end(), *fit) == encodings.end())
+                                       encodings.insert(encodings.begin(), *fit);
+                       }
+               }
+}
+
 namespace {
 
 char const * simplefeatures[] = {
@@ -747,7 +753,8 @@ char const * simplefeatures[] = {
        "tcolorbox",
        "pdfcomment",
        "fixme",
-       "todonotes"
+       "todonotes",
+       "forest"
 };
 
 char const * bibliofeatures[] = {
@@ -833,6 +840,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;
@@ -843,16 +866,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) {
@@ -884,28 +897,10 @@ string const LaTeXFeatures::getPackages() const
        if (!params_.useNonTeXFonts && !use_newtxmath && !amsPackages.empty())
                packages << amsPackages;
 
-       // fixltx2e must be loaded after amsthm, since amsthm produces an error with
-       // the redefined \[ command (bug 7233). Load it as early as possible, since
-       // other packages might profit from it.
-       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";
-
+       
        // accents must be loaded after amsmath
        if (mustProvide("accents") &&
            params_.use_package("accents") != BufferParams::package_off)
@@ -963,14 +958,27 @@ string const LaTeXFeatures::getPackages() const
        if (mustProvide("setspace") && !isProvided("SetSpace"))
                packages << "\\usepackage{setspace}\n";
 
-       // we need to assure that mhchem is loaded before esint
-       // because esint must be loaded AFTER amslatex and mhchem loads amlatex
+       // 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") &&
@@ -1049,6 +1057,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();
 }
 
@@ -1177,8 +1191,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"))
@@ -1288,8 +1300,6 @@ bool LaTeXFeatures::needBabelLangOptions() const
 string const LaTeXFeatures::loadAMSPackages() const
 {
        ostringstream tmp;
-       if (mustProvide("amsthm"))
-               tmp << "\\usepackage{amsthm}\n";
 
        if (mustProvide("amsmath")
            && params_.use_package("amsmath") != BufferParams::package_off) {
@@ -1302,6 +1312,9 @@ string const LaTeXFeatures::loadAMSPackages() const
                        tmp << "\\usepackage{amstext}\n";
        }
 
+       if (mustProvide("amsthm"))
+               tmp << "\\usepackage{amsthm}\n";
+
        if (mustProvide("amssymb")
            && params_.use_package("amssymb") != BufferParams::package_off)
                tmp << "\\usepackage{amssymb}\n";
@@ -1430,7 +1443,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;
@@ -1442,6 +1456,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
@@ -1455,16 +1487,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);
@@ -1489,20 +1523,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()) {
@@ -1550,24 +1584,31 @@ 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 = !runparams_.isFullUnicode() &&
+                               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));
                }
        }