X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetQuotes.cpp;h=2f70f87222709651f7ddaac33509d3e1fbe3565b;hb=2748e33be542862f94af4a131a17dde5ebc064b2;hp=7ae2d0ff9b08af7c801dc2e2c507c22b6c8f53a0;hpb=3add3e2eae8f75cf25aa0f32141a62eaef01650d;p=lyx.git diff --git a/src/insets/InsetQuotes.cpp b/src/insets/InsetQuotes.cpp index 7ae2d0ff9b..2f70f87222 100644 --- a/src/insets/InsetQuotes.cpp +++ b/src/insets/InsetQuotes.cpp @@ -111,10 +111,9 @@ InsetQuotesParams::QuoteStyle InsetQuotesParams::getQuoteStyle(string const & s, str = "eld"; } - int i; - // '.' wildcard means: keep current style if (!allow_wildcards || str[0] != '.') { + int i; for (i = 0; i < stylescount(); ++i) { if (str[0] == style_char[i]) { res = QuoteStyle(i); @@ -144,10 +143,9 @@ InsetQuotesParams::QuoteSide InsetQuotesParams::getQuoteSide(string const & s, str = "eld"; } - int i; - // '.' wildcard means: keep current side if (!allow_wildcards || str[1] != '.') { + int i; for (i = 0; i < 2; ++i) { if (str[1] == side_char[i]) { res = InsetQuotesParams::QuoteSide(i); @@ -177,10 +175,9 @@ InsetQuotesParams::QuoteLevel InsetQuotesParams::getQuoteLevel(string const & s, str = "eld"; } - int i; - // '.' wildcard means: keep current level if (!allow_wildcards || str[2] != '.') { + int i; for (i = 0; i < 2; ++i) { if (str[2] == level_char[i]) { res = InsetQuotesParams::QuoteLevel(i); @@ -199,7 +196,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 +318,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 +334,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 +349,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; @@ -388,14 +392,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; @@ -579,9 +585,9 @@ docstring const InsetQuotesParams::getGuiLabel(QuoteStyle const & qs, bool langd } -docstring const InsetQuotesParams::getShortGuiLabel(docstring const string) +docstring const InsetQuotesParams::getShortGuiLabel(docstring const & str) { - std::string const s = to_ascii(string); + string const s = to_ascii(str); QuoteStyle const style = getQuoteStyle(s); QuoteSide const side = getQuoteSide(s); QuoteLevel const level = getQuoteLevel(s); @@ -603,7 +609,7 @@ docstring const InsetQuotesParams::getShortGuiLabel(docstring const string) InsetQuotes::InsetQuotes(Buffer * buf, string const & str) : Inset(buf), style_(InsetQuotesParams::EnglishQuotes), side_(InsetQuotesParams::OpeningQuote), - pass_thru_(false), internal_fontenc_(false) + pass_thru_(false), internal_fontenc_(false), rtl_(false) { if (buf) { global_style_ = buf->masterBuffer()->params().quotes_style; @@ -620,7 +626,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), internal_fontenc_(false) + : Inset(buf), level_(level), pass_thru_(false), fontspec_(false), + internal_fontenc_(false), rtl_(false) { bool dynamic = false; if (buf) { @@ -630,7 +637,7 @@ InsetQuotes::InsetQuotes(Buffer * buf, char_type c, InsetQuotesParams::QuoteLeve fontspec_ = buf->masterBuffer()->params().useNonTeXFonts; } else { global_style_ = InsetQuotesParams::EnglishQuotes; - fontenc_ = lyxrc.fontenc; + fontenc_ = "OT1"; fontspec_ = false; } if (style.empty()) @@ -720,7 +727,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") @@ -800,7 +807,7 @@ void InsetQuotes::doDispatch(Cursor & cur, FuncRequest & cmd) } cur.recordUndoInset(this); parseString(cmd.getArg(1), true); - cur.buffer()->updateBuffer(); + cur.forceBufferUpdate(); break; } default: @@ -836,7 +843,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 @@ -853,8 +860,11 @@ void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const // (spacing and kerning is then handled respectively) qstr = docstring(1, quotechar); } + // The CJK marks are not yet covered by utf8 inputenc (we don't have the entry in + // unicodesymbols, since we don't want to add fake synbols there). else if (style == InsetQuotesParams::CJKQuotes || style == InsetQuotesParams::CJKAngleQuotes) { - if (runparams.encoding && runparams.encoding->encodable(quotechar)) + if (runparams.encoding && runparams.encoding->name() != "utf8" + && runparams.encoding->encodable(quotechar)) qstr = docstring(1, quotechar); else qstr = quoteparams.getLaTeXQuote(quotechar, "int"); @@ -870,6 +880,10 @@ void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const qstr = from_ascii("\\og"); else qstr = from_ascii("\\fg"); + } else if (runparams.use_hyperref && runparams.moving_arg) { + // Use internal commands in headings with hyperref + // (ligatures not featured in PDF strings) + qstr = quoteparams.getLaTeXQuote(quotechar, "int", rtl_); } else if (fontenc_ == "T1" && !runparams.local_font->language()->internalFontEncoding()) { // Quotation marks for T1 font encoding @@ -878,7 +892,7 @@ 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 @@ -898,15 +912,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; @@ -973,15 +993,17 @@ void InsetQuotes::forOutliner(docstring & os, size_t const, bool const) const } -void InsetQuotes::updateBuffer(ParIterator const & it, UpdateType /* utype*/) +void InsetQuotes::updateBuffer(ParIterator const & it, UpdateType /* utype*/, bool const /*deleted*/) { 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(); - internal_fontenc_ = it.paragraph().getFontSettings(bp, it.pos()).language()->internalFontEncoding(); + 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(); } @@ -1039,10 +1061,12 @@ void InsetQuotes::validate(LaTeXFeatures & features) const features.require("textquotedbl"); break; } - // we fake these from math + // we fake these from math (also for utf8 inputenc + // currently; see above) case 0x300e: // LEFT WHITE CORNER BRACKET case 0x300f: // RIGHT WHITE CORNER BRACKET if (!features.runparams().encoding + || features.runparams().encoding->name() == "utf8" || !features.runparams().encoding->encodable(type)) features.require("stmaryrd"); break;