]> git.lyx.org Git - lyx.git/blobdiff - src/LaTeXFeatures.cpp
Merge branch 'master' of git.lyx.org:lyx
[lyx.git] / src / LaTeXFeatures.cpp
index dcfb44c8ecc86ed53dbc3583858bf5cf504f04a0..16ec4c19864517ca3e0c76aa66e652ad0b87a86f 100644 (file)
@@ -66,7 +66,7 @@ static docstring const lyx_def = from_ascii(
 static docstring const lyx_hyperref_def = from_ascii(
        "\\providecommand{\\LyX}{\\texorpdfstring%\n"
        "  {L\\kern-.1667em\\lower.25em\\hbox{Y}\\kern-.125emX\\@}\n"
-        "  {LyX}}");
+       "  {LyX}}");
 
 static docstring const noun_def = from_ascii(
        "\\newcommand{\\noun}[1]{\\textsc{#1}}");
@@ -134,6 +134,24 @@ 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");
@@ -184,18 +202,21 @@ static docstring const changetracking_none_def = from_ascii(
        "\\newcommand{\\lyxadded}[3]{#3}\n"
        "\\newcommand{\\lyxdeleted}[3]{}\n");
 
+static docstring const textgreek_LGR_def = from_ascii(
+       "\\DeclareFontEncoding{LGR}{}{}\n");
 static docstring const textgreek_def = from_ascii(
        "\\DeclareRobustCommand{\\greektext}{%\n"
        "  \\fontencoding{LGR}\\selectfont\\def\\encodingdefault{LGR}}\n"
        "\\DeclareRobustCommand{\\textgreek}[1]{\\leavevmode{\\greektext #1}}\n"
-       "\\DeclareFontEncoding{LGR}{}{}\n"
-       "\\DeclareTextSymbol{\\~}{LGR}{126}");
+        "\\ProvideTextCommand{\\~}{LGR}[1]{\\char126#1}\n");
 
+static docstring const textcyr_T2A_def = from_ascii(
+       "\\InputIfFileExists{t2aenc.def}{}{%\n"
+        "  \\errmessage{File `t2aenc.def' not found: Cyrillic script not supported}}\n");
 static docstring const textcyr_def = from_ascii(
        "\\DeclareRobustCommand{\\cyrtext}{%\n"
        "  \\fontencoding{T2A}\\selectfont\\def\\encodingdefault{T2A}}\n"
-       "\\DeclareRobustCommand{\\textcyr}[1]{\\leavevmode{\\cyrtext #1}}\n"
-       "\\AtBeginDocument{\\DeclareFontEncoding{T2A}{}{}}\n");
+       "\\DeclareRobustCommand{\\textcyr}[1]{\\leavevmode{\\cyrtext #1}}\n");
 
 static docstring const lyxmathsym_def = from_ascii(
        "\\newcommand{\\lyxmathsym}[1]{\\ifmmode\\begingroup\\def\\b@ld{bold}\n"
@@ -248,15 +269,51 @@ static docstring const ogonek_def = from_ascii(
        "  \\mathchar\"0\\hexnumber@\\symtipasymb0C}{#2}}\n"
        "\\newcommand{\\ogonek}[1]{\\mathpalette\\doogonek{#1}}\n");
 
+static docstring const lyxaccent_def = from_ascii(
+       "%% custom text accent \\LyxTextAccent[<rise value (length)>]{<accent>}{<base>}\n"
+        "\\newcommand*{\\LyxTextAccent}[3][0ex]{%\n"
+        "  \\hmode@bgroup\\ooalign{\\null#3\\crcr\\hidewidth\n"
+        "  \\raise#1\\hbox{#2}\\hidewidth}\\egroup}\n"
+        "%% select a font size smaller than the current font size:\n"
+        "\\newcommand{\\LyxAccentSize}[1][\\sf@size]{%\n"
+        "  \\check@mathfonts\\fontsize#1\\z@\\math@fontsfalse\\selectfont\n"
+        "}\n");
+
+static docstring const textcommabelow_def = from_ascii(
+        "\\ProvideTextCommandDefault{\\textcommabelow}[1]{%%\n"
+        "  \\LyxTextAccent[-.31ex]{\\LyxAccentSize,}{#1}}\n");
+
+static docstring const textcommaabove_def = from_ascii(
+        "\\ProvideTextCommandDefault{\\textcommaabove}[1]{%%\n"
+        "  \\LyxTextAccent[.5ex]{\\LyxAccentSize`}{#1}}\n");
+
+static docstring const textcommaaboveright_def = from_ascii(
+        "\\ProvideTextCommandDefault{\\textcommaaboveright}[1]{%%\n"
+        "  \\LyxTextAccent[.5ex]{\\LyxAccentSize\\ `}{#1}}\n");
+
+// Baltic languages use a comma-accent instead of a cedilla
+static docstring const textbaltic_def = from_ascii(
+        "%% use comma accent instead of cedilla for these characters:\n"
+        "\\DeclareTextCompositeCommand{\\c}{T1}{g}{\\textcommaabove{g}}\n"
+        "\\DeclareTextCompositeCommand{\\c}{T1}{G}{\\textcommabelow{G}}\n"
+        "\\DeclareTextCompositeCommand{\\c}{T1}{k}{\\textcommabelow{k}}\n"
+        "\\DeclareTextCompositeCommand{\\c}{T1}{K}{\\textcommabelow{K}}\n"
+        "\\DeclareTextCompositeCommand{\\c}{T1}{l}{\\textcommabelow{l}}\n"
+        "\\DeclareTextCompositeCommand{\\c}{T1}{L}{\\textcommabelow{L}}\n"
+        "\\DeclareTextCompositeCommand{\\c}{T1}{n}{\\textcommabelow{n}}\n"
+        "\\DeclareTextCompositeCommand{\\c}{T1}{N}{\\textcommabelow{N}}\n"
+        "\\DeclareTextCompositeCommand{\\c}{T1}{r}{\\textcommabelow{r}}\n"
+        "\\DeclareTextCompositeCommand{\\c}{T1}{R}{\\textcommabelow{R}}\n");
+
 static docstring const lyxref_def = from_ascii(
-               "\\RS@ifundefined{subref}\n"
-               "  {\\def\\RSsubtxt{section~}\\newref{sub}{name = \\RSsubtxt}}\n"
+               "\\RS@ifundefined{subsecref}\n"
+               "  {\\newref{subsec}{name = \\RSsectxt}}\n"
                "  {}\n"
                "\\RS@ifundefined{thmref}\n"
                "  {\\def\\RSthmtxt{theorem~}\\newref{thm}{name = \\RSthmtxt}}\n"
                "  {}\n"
                "\\RS@ifundefined{lemref}\n"
-               "  {\\def\\RSlemtxt{lemma~}\\newref{lem}{name = \\RSlemtxt}}\n" 
+               "  {\\def\\RSlemtxt{lemma~}\\newref{lem}{name = \\RSlemtxt}}\n"
                "  {}\n");
 
 // Make sure the columns are also outputed as rtl
@@ -304,15 +361,15 @@ static docstring const rtloutputdblcol_def = from_ascii(
 
 static docstring const lyxnoun_style = from_ascii(
        "dfn.lyxnoun {\n"
-  "  font-variant: small-caps;\n"
-  "}\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");
+       "  text-decoration: line-through;\n"
+       "}\n");
 
 
 /////////////////////////////////////////////////////////////////////
@@ -343,18 +400,18 @@ LaTeXFeatures::LangPackage LaTeXFeatures::langPackage() const
        if (local_lp == "none")
                return LANG_PACK_NONE;
 
-       /* If "auto" is selected, we load polyglossia if required,
+       /* If "auto" is selected, we load polyglossia with non-TeX fonts,
         * 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")
+               params_.useNonTeXFonts
                && isAvailable("polyglossia")
                && !isProvided("babel")
                && this->hasOnlyPolyglossiaLanguages();
-       bool const babel_required = 
+       bool const babel_required =
                !bufferParams().language->babel().empty()
                || !this->getBabelLanguages().empty();
 
@@ -477,26 +534,29 @@ bool LaTeXFeatures::isProvided(string const & name) const
 
        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");
+       bool const complete = (params_.fontsSans() == "default"
+               && params_.fontsTypewriter() == "default");
+       bool const nomath = (params_.fontsMath() == "default");
        return params_.documentClass().provides(name)
                || theLaTeXFonts().getLaTeXFont(
-                       from_ascii(params_.fonts_roman)).provides(name, ot1,
+                       from_ascii(params_.fontsRoman())).provides(name, ot1,
                                                                  complete,
                                                                  nomath)
                || theLaTeXFonts().getLaTeXFont(
-                       from_ascii(params_.fonts_sans)).provides(name, ot1,
+                       from_ascii(params_.fontsSans())).provides(name, ot1,
                                                                 complete,
                                                                 nomath)
                || theLaTeXFonts().getLaTeXFont(
-                       from_ascii(params_.fonts_typewriter)).provides(name, ot1,
+                       from_ascii(params_.fontsTypewriter())).provides(name, ot1,
                                                                       complete,
                                                                       nomath)
                || theLaTeXFonts().getLaTeXFont(
-                       from_ascii(params_.fonts_math)).provides(name, ot1,
+                       from_ascii(params_.fontsMath())).provides(name, ot1,
                                                                       complete,
                                                                       nomath);
+       // TODO: "textbaltic" provided, if the font-encoding is "L7x"
+       //       "textgreek" provided, if a language with font-encoding LGR is used in the document
+       //       "textcyr" provided, if a language with font-encoding T2A is used in the document
 }
 
 
@@ -519,11 +579,12 @@ bool LaTeXFeatures::isAvailable(string const & name)
 }
 
 
-void LaTeXFeatures::addPreambleSnippet(string const & preamble)
+void LaTeXFeatures::addPreambleSnippet(string const & preamble,
+               bool allowdupes)
 {
        SnippetList::const_iterator begin = preamble_snippets_.begin();
        SnippetList::const_iterator end   = preamble_snippets_.end();
-       if (find(begin, end, preamble) == end)
+       if (allowdupes || find(begin, end, preamble) == end)
                preamble_snippets_.push_back(preamble);
 }
 
@@ -669,8 +730,9 @@ set<string> LaTeXFeatures::getEncodingSet(string const & doc_encoding) const
 
 void LaTeXFeatures::getFontEncodings(vector<string> & encodings) const
 {
-       // these must be loaded if glyphs of this script
-       // are used (notwithstanding the language)
+       // these must be loaded if glyphs of this script are used
+       // unless a language providing them is used in the document
+       // FIXME: currently the option is written twice in this case
        if (mustProvide("textgreek"))
                encodings.insert(encodings.begin(), "LGR");
        if (mustProvide("textcyr"))
@@ -722,7 +784,6 @@ char const * simplefeatures[] = {
        "pmboxdraw",
        "bbding",
        "ifsym",
-       "marvosym",
        "txfonts",
        "pxfonts",
        "mathdesign",
@@ -748,13 +809,15 @@ char const * simplefeatures[] = {
        "tfrupee",
        "shapepar",
        "rsphrase",
+       "hpstatement",
        "algorithm2e",
        "sectionbox",
        "tcolorbox",
        "pdfcomment",
        "fixme",
        "todonotes",
-       "forest"
+       "forest",
+       "varwidth"
 };
 
 char const * bibliofeatures[] = {
@@ -891,16 +954,23 @@ string const LaTeXFeatures::getPackages() const
        string const amsPackages = loadAMSPackages();
        bool const ot1 = (params_.font_encoding() == "default" || params_.font_encoding() == "OT1");
        bool const use_newtxmath =
-               theLaTeXFonts().getLaTeXFont(from_ascii(params_.fonts_math)).getUsedPackage(
+               theLaTeXFonts().getLaTeXFont(from_ascii(params_.fontsMath())).getUsedPackage(
                        ot1, false, false) == "newtxmath";
-       
+
        if (!params_.useNonTeXFonts && !use_newtxmath && !amsPackages.empty())
                packages << amsPackages;
 
        if (mustProvide("cancel") &&
            params_.use_package("cancel") != BufferParams::package_off)
                packages << "\\usepackage{cancel}\n";
-       
+
+       // marvosym and bbding both define the \Cross macro
+       if (mustProvide("marvosym")) {
+           if (mustProvide("bbding"))
+               packages << "\\let\\Cross\\relax\n";
+           packages << "\\usepackage{marvosym}\n";
+       }
+
        // accents must be loaded after amsmath
        if (mustProvide("accents") &&
            params_.use_package("accents") != BufferParams::package_off)
@@ -1063,6 +1133,10 @@ string const LaTeXFeatures::getPackages() const
        if (mustProvide("footmisc"))
                packages << "\\PassOptionsToPackage{stable}{footmisc}\n";
 
+       if (mustProvide("microtype")){
+               packages << "\\usepackage{microtype}\n";
+       }
+
        return packages.str();
 }
 
@@ -1119,21 +1193,35 @@ docstring const LaTeXFeatures::getMacros() const
                macros << lyxarrow_def << '\n';
 
        if (!usePolyglossia() && mustProvide("textgreek")) {
-               // Avoid a LaTeX error if times fonts are used and the grtimes
-               // package is installed but actual fonts are not (bug 6469).
-               if (params_.fonts_roman == "times")
-                       macros << subst(textgreek_def,
-                                       from_ascii("\\greektext #1"),
-                                       from_ascii("%\n  \\IfFileExists"
-                                                  "{grtm10.tfm}{}{\\fontfamily"
-                                                  "{cmr}}\\greektext #1"))
-                              << '\n';
-               else
-                       macros << textgreek_def << '\n';
+               // ensure LGR font encoding is defined also if fontenc is not loaded by LyX
+               if (params_.font_encoding() == "default")
+                       macros << textgreek_LGR_def;
+               macros << textgreek_def << '\n';
        }
 
-       if (!usePolyglossia() && mustProvide("textcyr"))
+       if (!usePolyglossia() && mustProvide("textcyr")) {
+               // ensure T2A font encoding is set up also if fontenc is not loaded by LyX
+               if (params_.font_encoding() == "default")
+                       macros << textcyr_T2A_def;
                macros << textcyr_def << '\n';
+       }
+
+        // non-standard text accents:
+       if (mustProvide("textcommaabove") || mustProvide("textcommaaboveright") ||
+           mustProvide("textcommabelow") || mustProvide("textbaltic"))
+               macros << lyxaccent_def;
+
+       if (mustProvide("textcommabelow") || mustProvide("textbaltic"))
+               macros << textcommabelow_def << '\n';
+
+       if (mustProvide("textcommaabove") || mustProvide("textbaltic"))
+               macros << textcommaabove_def << '\n';
+
+       if (mustProvide("textcommaaboveright"))
+               macros << textcommaaboveright_def << '\n';
+
+       if (mustProvide("textbaltic"))
+               macros << textbaltic_def << '\n';
 
        if (mustProvide("lyxmathsym"))
                macros << lyxmathsym_def << '\n';
@@ -1191,6 +1279,8 @@ 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"))
@@ -1756,10 +1846,23 @@ void LaTeXFeatures::resolveAlternatives()
                        vector<string> const alternatives = getVectorFromString(*it, "|");
                        vector<string>::const_iterator const end = alternatives.end();
                        vector<string>::const_iterator ita = alternatives.begin();
+                       // Is any alternative already required? => use that
                        for (; ita != end; ++ita) {
                                if (isRequired(*ita))
                                        break;
                        }
+                       // Is any alternative available? => use the first one
+                       // (bug 9498)
+                       if (ita == end) {
+                               for (ita = alternatives.begin(); ita != end; ++ita) {
+                                       if (isAvailable(*ita)) {
+                                               require(*ita);
+                                               break;
+                                       }
+                               }
+                       }
+                       // This will not work, but not requiring something
+                       // would be more confusing
                        if (ita == end)
                                require(alternatives.front());
                        features_.erase(it);