]> git.lyx.org Git - features.git/blobdiff - src/insets/InsetListings.cpp
Use proper listings font styles with polyglossia and RTL
[features.git] / src / insets / InsetListings.cpp
index ec9ad7225f37254683f45ba25fcc7fa4851d2c7a..1f6087913ae6e6fc546023180dae86149cf178aa 100644 (file)
@@ -123,18 +123,18 @@ Encoding const * InsetListings::forcedEncoding(Encoding const * inner_enc,
                                               Encoding const * outer_enc) const
 {
        // The listings package cannot deal with multi-byte-encoded
-       // glyphs, except if full-unicode aware backends
-       // such as XeTeX or LuaTeX are used, and with pLaTeX.
+       // glyphs, except for Xe/LuaTeX (with non-TeX fonts) or pLaTeX.
        // Minted can deal with all encodings.
        if (buffer().params().use_minted
                || inner_enc->name() == "utf8-plain"
-               || (buffer().params().encoding().package() == Encoding::japanese
-                       && inner_enc->package() == Encoding::japanese)
+               || inner_enc->package() == Encoding::japanese
                || inner_enc->hasFixedWidth())
                return 0;
 
        // We try if there's a singlebyte encoding for the outer
        // language; if not, fall back to latin1.
+       // Power-users can set inputenc to utf8-plain to bypass this workaround
+       // and provide alternatives in the user-preamble.
        return (outer_enc->hasFixedWidth()) ?
                        outer_enc : encodings.fromLyXName("iso8859-1");
 }
@@ -147,6 +147,22 @@ void InsetListings::latex(otexstream & os, OutputParams const & runparams) const
        // of the listings package (see page 25 of the manual)
        bool const isInline = params().isInline();
        bool const use_minted = buffer().params().use_minted;
+       static regex const reg1("(.*)(basicstyle=\\{)([^\\}]*)(\\\\ttfamily)([^\\}]*)(\\})(.*)");
+       static regex const reg2("(.*)(basicstyle=\\{)([^\\}]*)(\\\\rmfamily)([^\\}]*)(\\})(.*)");
+       static regex const reg3("(.*)(basicstyle=\\{)([^\\}]*)(\\\\sffamily)([^\\}]*)(\\})(.*)");
+       if (runparams.use_polyglossia && runparams.local_font->isRightToLeft()) {
+               // We need to use the *latin switches (#11554)
+               smatch sub;
+               if (regex_match(param_string, sub, reg1))
+                       param_string = sub.str(1) + sub.str(2) + sub.str(3) + sub.str(4)
+                                       + "latin"  + sub.str(5) + sub.str(6) + sub.str(7);
+               if (regex_match(param_string, sub, reg2))
+                       param_string = sub.str(1) + sub.str(2) + sub.str(3) + sub.str(4)
+                                       + "latin"  + sub.str(5) + sub.str(6) + sub.str(7);
+               if (regex_match(param_string, sub, reg3))
+                       param_string = sub.str(1) + sub.str(2) + sub.str(3) + sub.str(4)
+                                       + "latin"  + sub.str(5) + sub.str(6) + sub.str(7);
+       }
        string minted_language;
        string float_placement;
        bool const isfloat = params().isFloat();
@@ -159,11 +175,11 @@ void InsetListings::latex(otexstream & os, OutputParams const & runparams) const
                        if (prefixIs(opts[i], "float")) {
                                if (prefixIs(opts[i], "float="))
                                        float_placement = opts[i].substr(6);
-                               opts.erase(opts.begin() + i--);
+                               opts.erase(opts.begin() + int(i--));
                        }
                        else if (prefixIs(opts[i], "language=")) {
                                minted_language = opts[i].substr(9);
-                               opts.erase(opts.begin() + i--);
+                               opts.erase(opts.begin() + int(i--));
                        }
                }
                param_string = getStringFromVector(opts, ",");
@@ -494,6 +510,10 @@ void InsetListings::validate(LaTeXFeatures & features) const
                OutputParams rp = features.runparams();
                if (!params().isFloat() && !getCaption(rp).str.empty())
                        features.require("lyxmintcaption");
+               if (features.usePolyglossia() && features.hasRTLLanguage())
+                       // minted loads color, but color must be loaded before bidi
+                       // (i.e., polyglossia)
+                       features.require("color");
        } else {
                features.require("listings");
                if (contains(param_string, "\\color"))
@@ -540,12 +560,15 @@ TexString InsetListings::getCaption(OutputParams const & runparams) const
        // NOTE that } is not allowed in blah2.
        regex const reg("(.*)\\\\label\\{(.*?)\\}(.*)");
        string const new_cap("$1$3},label={$2");
+       // Remove potential \protect'ion of \label.
+       docstring capstr = subst(cap.str, from_ascii("\\protect\\label"),
+                                from_ascii("\\label"));
        // TexString validity: the substitution preserves the number of newlines.
        // Moreover we assume that $2 does not contain newlines, so that the texrow
        // information remains accurate.
        // Replace '\n' with an improbable character from Private Use Area-A
        // and then return to '\n' after the regex replacement.
-       docstring const capstr = subst(cap.str, char_type('\n'), 0xffffd);
+       capstr = subst(capstr, char_type('\n'), 0xffffd);
        cap.str = subst(from_utf8(regex_replace(to_utf8(capstr), reg, new_cap)),
                        0xffffd, char_type('\n'));
        return cap;