X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetQuotes.cpp;h=8b1645945d84be8db01fd5699448214c74810763;hb=b9116e8b81f55ee795ea444ee02ff921bf82606a;hp=7032a068a3c3765500c0634a16e42bb4209e2577;hpb=91d8a3982d4acd9118217b4d30a5500e3bbd178e;p=lyx.git diff --git a/src/insets/InsetQuotes.cpp b/src/insets/InsetQuotes.cpp index 7032a068a3..8b1645945d 100644 --- a/src/insets/InsetQuotes.cpp +++ b/src/insets/InsetQuotes.cpp @@ -75,7 +75,7 @@ char const * const style_char = "esgpcaqbwfirjkx"; char const * const side_char = "lr" ; char const * const level_char = "sd"; -} // namespace anon +} // namespace ///////////////////////////////////////////////////////////////////// @@ -199,7 +199,7 @@ InsetQuotesParams::QuoteLevel InsetQuotesParams::getQuoteLevel(string const & s, char_type InsetQuotesParams::getQuoteChar(QuoteStyle const & style, QuoteLevel const & level, - QuoteSide const & side) const + QuoteSide const & side, bool const rtl) const { // main opening quotation mark char_type left_primary; @@ -321,8 +321,12 @@ char_type InsetQuotesParams::getQuoteChar(QuoteStyle const & style, QuoteLevel c switch (level) { case SecondaryQuotes: + if (rtl) + return (side == ClosingQuote) ? left_secondary : right_secondary; return (side == OpeningQuote) ? left_secondary : right_secondary; case PrimaryQuotes: + if (rtl) + return (side == ClosingQuote) ? left_primary : right_primary; return (side == OpeningQuote) ? left_primary : right_primary; default: break; @@ -333,7 +337,8 @@ char_type InsetQuotesParams::getQuoteChar(QuoteStyle const & style, QuoteLevel c } -docstring InsetQuotesParams::getLaTeXQuote(char_type c, string const & op) const +docstring InsetQuotesParams::getLaTeXQuote(char_type c, string const & op, + bool const rtl) const { string res; @@ -347,14 +352,16 @@ docstring InsetQuotesParams::getLaTeXQuote(char_type c, string const & op) const } case 0x2019: {// ' if (op == "int") - res = "\\textquoteleft"; + // This macro is redefined in rtl mode + res = rtl ? "\\textquoteright" : "\\textquoteleft"; else res = "'"; break; } case 0x2018: {// ` if (op == "int") - res = "\\textquoteright"; + // This macro is redefined in rtl mode + res = rtl ? "\\textquoteleft" : "\\textquoteright"; else res = "`"; break; @@ -374,10 +381,7 @@ docstring InsetQuotesParams::getLaTeXQuote(char_type c, string const & op) const break; } case 0x0027: {// ' (plain) - if (op == "t1") - res = "\\textquotesingle"; - else - res = "\\char39"; + res = "\\textquotesingle"; break; } case 0x201e: {// ,, @@ -391,14 +395,16 @@ docstring InsetQuotesParams::getLaTeXQuote(char_type c, string const & op) const } case 0x201d: {// '' if (op == "int") - res = "\\textquotedblleft"; + // This macro is redefined in rtl mode + res = rtl ? "\\textquotedblright" : "\\textquotedblleft"; else res = "''"; break; } case 0x201c: {// `` if (op == "int") - res = "\\textquotedblright"; + // This macro is redefined in rtl mode + res = rtl ? "\\textquotedblleft" : "\\textquotedblright"; else res = "``"; break; @@ -422,10 +428,7 @@ docstring InsetQuotesParams::getLaTeXQuote(char_type c, string const & op) const break; } case 0x0022: {// " - if (op == "t1") - res = "\\textquotedbl"; - else - res = "\\char34"; + res = "\\textquotedbl"; break; } // The following are fakes @@ -458,7 +461,7 @@ docstring InsetQuotesParams::getLaTeXQuote(char_type c, string const & op) const default: break; } - + return from_ascii(res); } @@ -531,7 +534,7 @@ docstring InsetQuotesParams::getHTMLQuote(char_type c) const default: break; } - + return from_ascii(res); } @@ -607,9 +610,9 @@ docstring const InsetQuotesParams::getShortGuiLabel(docstring const string) /////////////////////////////////////////////////////////////////////// InsetQuotes::InsetQuotes(Buffer * buf, string const & str) - : Inset(buf), + : Inset(buf), style_(InsetQuotesParams::EnglishQuotes), side_(InsetQuotesParams::OpeningQuote), - pass_thru_(false) + pass_thru_(false), internal_fontenc_(false), rtl_(false) { if (buf) { global_style_ = buf->masterBuffer()->params().quotes_style; @@ -626,7 +629,8 @@ InsetQuotes::InsetQuotes(Buffer * buf, string const & str) InsetQuotes::InsetQuotes(Buffer * buf, char_type c, InsetQuotesParams::QuoteLevel level, string const & side, string const & style) - : Inset(buf), level_(level), pass_thru_(false), fontspec_(false) + : Inset(buf), level_(level), pass_thru_(false), fontspec_(false), + internal_fontenc_(false), rtl_(false) { bool dynamic = false; if (buf) { @@ -680,7 +684,7 @@ void InsetQuotes::parseString(string const & s, bool const allow_wildcards) InsetQuotesParams::QuoteStyle InsetQuotes::getStyle(string const & s) { InsetQuotesParams::QuoteStyle qs = InsetQuotesParams::EnglishQuotes; - + if (s == "english") qs = InsetQuotesParams::EnglishQuotes; else if (s == "swedish") @@ -726,7 +730,7 @@ docstring InsetQuotes::displayString() const InsetQuotesParams::QuoteStyle style = (style_ == InsetQuotesParams::DynamicQuotes) ? global_style_ : style_; - docstring retdisp = docstring(1, quoteparams.getQuoteChar(style, level_, side_)); + docstring retdisp = docstring(1, quoteparams.getQuoteChar(style, level_, side_, rtl_)); // in French, thin spaces are added inside double guillemets if (prefixIs(context_lang_, "fr") @@ -806,7 +810,7 @@ void InsetQuotes::doDispatch(Cursor & cur, FuncRequest & cmd) } cur.recordUndoInset(this); parseString(cmd.getArg(1), true); - cur.buffer()->updateBuffer(); + cur.forceBufferUpdate(); break; } default: @@ -842,7 +846,7 @@ void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const { InsetQuotesParams::QuoteStyle style = (style_ == InsetQuotesParams::DynamicQuotes) ? global_style_ : style_; - char_type quotechar = quoteparams.getQuoteChar(style, level_, side_); + char_type quotechar = quoteparams.getQuoteChar(style, level_, side_, rtl_); docstring qstr; // In pass-thru context, we output plain quotes @@ -855,7 +859,7 @@ void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const from_ascii("\\textquotedblplain") : from_ascii("\\textquotesingleplain"); } else if (runparams.use_polyglossia) { - // For polyglossia, we directly output the respective unicode chars + // For polyglossia, we directly output the respective unicode chars // (spacing and kerning is then handled respectively) qstr = docstring(1, quotechar); } @@ -884,15 +888,20 @@ void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const } else if (runparams.local_font->language()->internalFontEncoding()) { // Quotation marks for internal font encodings // (ligatures not featured) - qstr = quoteparams.getLaTeXQuote(quotechar, "int"); + qstr = quoteparams.getLaTeXQuote(quotechar, "int", rtl_); #ifdef DO_USE_DEFAULT_LANGUAGE - } else if (doclang == "default") { + } else if ((doclang == "default" #else - } else if (!runparams.use_babel || runparams.isFullUnicode()) { + } else if ((!runparams.use_babel #endif + || fontenc_ == "T2A") + || runparams.isFullUnicode()) { // Standard quotation mark macros // These are also used by babel // without fontenc (XeTeX/LuaTeX) + // We use those for T2A (russian), since + // babel falls back for ugly OT1 versions for + // the guillemots. qstr = quoteparams.getLaTeXQuote(quotechar, "ot1"); } else { // Babel shorthand quotation marks (for T1/OT1) @@ -902,15 +911,21 @@ void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const if (!runparams.pass_thru) { // Guard against unwanted ligatures with preceding text char_type const lastchar = os.lastChar(); + // LuaTeX does not respect {} as ligature breaker by design, + // see https://tex.stackexchange.com/q/349725/19291 + docstring const nolig = + (runparams.flavor == OutputParams::LUATEX + || runparams.flavor == OutputParams::DVILUATEX) ? + from_ascii("\\/") : from_ascii("{}"); // !` ?` => !{}` ?{}` if (prefixIs(qstr, from_ascii("`")) && (lastchar == '!' || lastchar == '?')) - os << "{}"; + os << nolig; // ``` ''' ,,, <<< >>> // => `{}`` '{}'' ,{},, <{}<< >{}>> if (contains(from_ascii(",'`<>"), lastchar) && prefixIs(qstr, lastchar)) - os << "{}"; + os << nolig; } os << qstr; @@ -921,7 +936,7 @@ void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const } -int InsetQuotes::plaintext(odocstringstream & os, +int InsetQuotes::plaintext(odocstringstream & os, OutputParams const &, size_t) const { docstring const str = displayString(); @@ -980,11 +995,14 @@ void InsetQuotes::forOutliner(docstring & os, size_t const, bool const) const void InsetQuotes::updateBuffer(ParIterator const & it, UpdateType /* utype*/) { BufferParams const & bp = buffer().masterBuffer()->params(); + Font const & font = it.paragraph().getFontSettings(bp, it.pos()); pass_thru_ = it.paragraph().isPassThru(); - context_lang_ = it.paragraph().getFontSettings(bp, it.pos()).language()->code(); + context_lang_ = font.language()->code(); + internal_fontenc_ = font.language()->internalFontEncoding(); fontenc_ = bp.main_font_encoding(); global_style_ = bp.quotes_style; fontspec_ = bp.useNonTeXFonts; + rtl_ = font.isRightToLeft(); } @@ -1038,7 +1056,7 @@ void InsetQuotes::validate(LaTeXFeatures & features) const case 0x0022: { if (features.runparams().isFullUnicode() && fontspec_) features.require("textquotedblp"); - else if (fontenc_ != "T1") + else if (fontenc_ != "T1" || internal_fontenc_) features.require("textquotedbl"); break; }