X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetQuotes.cpp;h=bc5d6d527f832a3e57e68c66f893f6d944aa997e;hb=89ce0c9069d36748bea0701c52225a32d5e5d66b;hp=248d5deab955ef17a79fbec0c2ee688cb71b570d;hpb=2e255b1c4f3264571a6bd9ade8651c1657c995c6;p=lyx.git diff --git a/src/insets/InsetQuotes.cpp b/src/insets/InsetQuotes.cpp index 248d5deab9..bc5d6d527f 100644 --- a/src/insets/InsetQuotes.cpp +++ b/src/insets/InsetQuotes.cpp @@ -18,6 +18,7 @@ #include "BufferView.h" #include "Cursor.h" #include "Dimension.h" +#include "Encoding.h" #include "Font.h" #include "FuncStatus.h" #include "FuncRequest.h" @@ -56,12 +57,20 @@ namespace { * s ''swedish'' ('inner quotation') * g ,,german`` (,inner quotation`) * p ,,polish'' (,inner quotation') - * f <> () + * c <> () * a >>danish<< (>inner quotation<) * q "plain" ('inner quotation') + * b `british' (``inner quotation'') + * w >>swedishg>> ('inner quotation') ["g" = Guillemets] + * f <> (``inner quotation'') + * i <> (<>) ["in" = Imprimerie Nationale] + * r <> (,,inner quotation``) + * j [U+300C]cjk[U+300D] ([U+300E]inner quotation[U+300F]) [CORNER BRACKETS] + * k [U+300A]cjkangle[U+300B] ([U+3008]inner quotation[U+3009]) [ANGLE BRACKETS] + * x dynamic style (inherits document settings) */ -char const * const style_char = "esgpfaq"; +char const * const style_char = "esgpcaqbwfirjkx"; char const * const side_char = "lr" ; char const * const level_char = "sd"; @@ -124,7 +133,7 @@ char_type InsetQuotesParams::getQuoteChar(QuoteStyle const & style, QuoteLevel c right_secondary = 0x2019; // ' break; } - case FrenchQuotes: { + case SwissQuotes: { left_primary = 0x00ab; // << right_primary = 0x00bb; // >> left_secondary = 0x2039; // < @@ -145,6 +154,56 @@ char_type InsetQuotesParams::getQuoteChar(QuoteStyle const & style, QuoteLevel c right_secondary = 0x0027; // ' break; } + case BritishQuotes: { + left_primary = 0x2018; // ` + right_primary = 0x2019; // ' + left_secondary = 0x201c; // `` + right_secondary = 0x201d; // '' + break; + } + case SwedishGQuotes: { + left_primary = 0x00bb; // >> + right_primary = 0x00bb; // >> + left_secondary = 0x2019; // ' + right_secondary = 0x2019; // ' + break; + } + case FrenchQuotes: { + left_primary = 0x00ab; // << + right_primary = 0x00bb; // >> + left_secondary = 0x201c; // `` + right_secondary = 0x201d; // '' + break; + } + case FrenchINQuotes:{ + left_primary = 0x00ab; // << + right_primary = 0x00bb; // >> + left_secondary = 0x00ab; // << + right_secondary = 0x00bb; // >> + break; + } + case RussianQuotes:{ + left_primary = 0x00ab; // << + right_primary = 0x00bb; // >> + left_secondary = 0x201e; // ,, + right_secondary = 0x201c; // `` + break; + } + case CJKQuotes:{ + left_primary = 0x300c; // LEFT CORNER BRACKET + right_primary = 0x300d; // RIGHT CORNER BRACKET + left_secondary = 0x300e; // LEFT WHITE CORNER BRACKET + right_secondary = 0x300f; // RIGHT WHITE CORNER BRACKET + break; + } + case CJKAngleQuotes:{ + left_primary = 0x300a; // LEFT DOUBLE ANGLE BRACKET + right_primary = 0x300b; // RIGHT DOUBLE ANGLE BRACKET + left_secondary = 0x3008; // LEFT ANGLE BRACKET + right_secondary = 0x3009; // RIGHT ANGLE BRACKET + break; + } + case DynamicQuotes: default: // should not happen left_primary = 0x003f; // ? @@ -155,10 +214,10 @@ char_type InsetQuotesParams::getQuoteChar(QuoteStyle const & style, QuoteLevel c } switch (level) { - case SingleQuotes: - return (side == LeftQuote) ? left_secondary : right_secondary; - case DoubleQuotes: - return (side == LeftQuote) ? left_primary : right_primary; + case SecondaryQuotes: + return (side == OpeningQuote) ? left_secondary : right_secondary; + case PrimaryQuotes: + return (side == OpeningQuote) ? left_primary : right_primary; default: break; } @@ -257,6 +316,33 @@ docstring InsetQuotesParams::getLaTeXQuote(char_type c, string const & op) const res = "\\textquotedbl"; break; } + // The following are fakes + // This is just to get something symbolic + // in encodings where this chars would not be used ayway + case 0x300c: // LEFT CORNER BRACKET + res = "\\ensuremath{\\lceil}"; + break; + case 0x300d: // RIGHT CORNER BRACKET + res = "\\ensuremath{\\rfloor}"; + break; + case 0x300e: // LEFT WHITE CORNER BRACKET + res = "\\ensuremath{\\llceil}"; + break; + case 0x300f: // RIGHT WHITE CORNER BRACKET + res = "\\ensuremath{\\rrfloor}"; + break; + case 0x300a: // LEFT DOUBLE ANGLE BRACKET + res = "\\ensuremath{\\langle\\kern-2.5pt\\langle}"; + break; + case 0x300b: // RIGHT DOUBLE ANGLE BRACKET + res = "\\ensuremath{\\rangle\\kern-2.5pt\\rangle}"; + break; + case 0x3008: // LEFT ANGLE BRACKET + res = "\\ensuremath{\\langle}"; + break; + case 0x3009: // RIGHT ANGLE BRACKET + res = "\\ensuremath{\\rangle}"; + break; default: break; } @@ -306,6 +392,30 @@ docstring InsetQuotesParams::getHTMLQuote(char_type c) const case 0x0022: // " res = """; break; + case 0x300c: // LEFT CORNER BRACKET + res = "「"; + break; + case 0x300d: // RIGHT CORNER BRACKET + res = "」"; + break; + case 0x300e: // LEFT WHITE CORNER BRACKET + res = "『"; + break; + case 0x300f: // RIGHT WHITE CORNER BRACKET + res = "』"; + break; + case 0x300a: // LEFT DOUBLE ANGLE BRACKET + res = "《"; + break; + case 0x300b: // RIGHT DOUBLE ANGLE BRACKET + res = "》"; + break; + case 0x3008: // LEFT ANGLE BRACKET + res = "〈"; + break; + case 0x3009: // RIGHT ANGLE BRACKET + res = "〉"; + break; default: break; } @@ -327,6 +437,8 @@ map InsetQuotesParams::getTypes() const // get all quote types for (sty = 0; sty < stylescount(); ++sty) { style = QuoteStyle(sty); + if (style == DynamicQuotes) + continue; for (sid = 0; sid < 2; ++sid) { side = QuoteSide(sid); for (lev = 0; lev < 2; ++lev) { @@ -346,10 +458,10 @@ map InsetQuotesParams::getTypes() const docstring const InsetQuotesParams::getGuiLabel(QuoteStyle const & qs) { return bformat(_("%1$souter%2$s and %3$sinner%4$s[[quotation marks]]"), - docstring(1, quoteparams.getQuoteChar(qs, DoubleQuotes, LeftQuote)), - docstring(1, quoteparams.getQuoteChar(qs, DoubleQuotes, RightQuote)), - docstring(1, quoteparams.getQuoteChar(qs, SingleQuotes, LeftQuote)), - docstring(1, quoteparams.getQuoteChar(qs, SingleQuotes, RightQuote)) + docstring(1, quoteparams.getQuoteChar(qs, PrimaryQuotes, OpeningQuote)), + docstring(1, quoteparams.getQuoteChar(qs, PrimaryQuotes, ClosingQuote)), + docstring(1, quoteparams.getQuoteChar(qs, SecondaryQuotes, OpeningQuote)), + docstring(1, quoteparams.getQuoteChar(qs, SecondaryQuotes, ClosingQuote)) ); } @@ -362,6 +474,11 @@ docstring const InsetQuotesParams::getGuiLabel(QuoteStyle const & qs) InsetQuotes::InsetQuotes(Buffer * buf, string const & str) : Inset(buf) { + if (buf) + global_style_ = buf->masterBuffer()->params().quotes_style; + else + global_style_ = InsetQuotesParams::EnglishQuotes; + parseString(str); } @@ -370,19 +487,25 @@ InsetQuotes::InsetQuotes(Buffer * buf, char_type c, InsetQuotesParams::QuoteLeve string const & side, string const & style) : Inset(buf), level_(level), pass_thru_(false) { + bool dynamic = false; if (buf) { - style_ = style.empty() ? buf->params().quotes_style : getStyle(style); - fontenc_ = (buf->params().fontenc == "global") + global_style_ = buf->masterBuffer()->params().quotes_style; + fontenc_ = (buf->masterBuffer()->params().fontenc == "global") ? lyxrc.fontenc : buf->params().fontenc; + dynamic = buf->masterBuffer()->params().dynamic_quotes; } else { - style_ = style.empty() ? InsetQuotesParams::EnglishQuotes : getStyle(style); + global_style_ = InsetQuotesParams::EnglishQuotes; fontenc_ = lyxrc.fontenc; } + if (style.empty()) + style_ = dynamic ? InsetQuotesParams::DynamicQuotes : global_style_; + else + style_ = getStyle(style); - if (side == "left") - side_ = InsetQuotesParams::LeftQuote; - else if (side == "right") - side_ = InsetQuotesParams::RightQuote; + if (side == "left" || side == "opening") + side_ = InsetQuotesParams::OpeningQuote; + else if (side == "right" || side == "closing") + side_ = InsetQuotesParams::ClosingQuote; else setSide(c); } @@ -396,15 +519,15 @@ docstring InsetQuotes::layoutName() const void InsetQuotes::setSide(char_type c) { - // Decide whether left or right + // Decide whether opening or closing quote switch (c) { case ' ': case '(': case '[': - side_ = InsetQuotesParams::LeftQuote; // left quote + side_ = InsetQuotesParams::OpeningQuote;// opening quote break; default: - side_ = InsetQuotesParams::RightQuote; // right quote + side_ = InsetQuotesParams::ClosingQuote;// closing quote } } @@ -446,7 +569,7 @@ void InsetQuotes::parseString(string const & s, bool const allow_wildcards) if (i >= 2) { LYXERR0("ERROR (InsetQuotes::InsetQuotes):" " bad side specification."); - side_ = InsetQuotesParams::LeftQuote; + side_ = InsetQuotesParams::OpeningQuote; } } @@ -461,7 +584,7 @@ void InsetQuotes::parseString(string const & s, bool const allow_wildcards) if (i >= 2) { LYXERR0("ERROR (InsetQuotes::InsetQuotes):" " bad level specification."); - level_ = InsetQuotesParams::DoubleQuotes; + level_ = InsetQuotesParams::PrimaryQuotes; } } } @@ -479,12 +602,28 @@ InsetQuotesParams::QuoteStyle InsetQuotes::getStyle(string const & s) qs = InsetQuotesParams::GermanQuotes; else if (s == "polish") qs = InsetQuotesParams::PolishQuotes; - else if (s == "french") - qs = InsetQuotesParams::FrenchQuotes; + else if (s == "swiss") + qs = InsetQuotesParams::SwissQuotes; else if (s == "danish") qs = InsetQuotesParams::DanishQuotes; else if (s == "plain") qs = InsetQuotesParams::PlainQuotes; + else if (s == "british") + qs = InsetQuotesParams::BritishQuotes; + else if (s == "swedishg") + qs = InsetQuotesParams::SwedishGQuotes; + else if (s == "french") + qs = InsetQuotesParams::FrenchQuotes; + else if (s == "frenchin") + qs = InsetQuotesParams::FrenchINQuotes; + else if (s == "russian") + qs = InsetQuotesParams::RussianQuotes; + else if (s == "cjk") + qs = InsetQuotesParams::CJKQuotes; + else if (s == "cjkangle") + qs = InsetQuotesParams::CJKAngleQuotes; + else if (s == "dynamic") + qs = InsetQuotesParams::DynamicQuotes; return qs; } @@ -494,18 +633,23 @@ docstring InsetQuotes::displayString() const { // In PassThru, we use straight quotes if (pass_thru_) - return (level_ == InsetQuotesParams::DoubleQuotes) ? + return (level_ == InsetQuotesParams::PrimaryQuotes) ? from_ascii("\"") : from_ascii("'"); - docstring retdisp = docstring(1, quoteparams.getQuoteChar(style_, level_, side_)); + InsetQuotesParams::QuoteStyle style = + (style_ == InsetQuotesParams::DynamicQuotes) ? global_style_ : style_; + + docstring retdisp = docstring(1, quoteparams.getQuoteChar(style, level_, side_)); // in French, thin spaces are added inside double guillemets if (prefixIs(context_lang_, "fr") - && level_ == InsetQuotesParams::DoubleQuotes - && style_ == InsetQuotesParams::FrenchQuotes) { + && level_ == InsetQuotesParams::PrimaryQuotes + && (style == InsetQuotesParams::SwissQuotes + || style == InsetQuotesParams::FrenchQuotes + || style == InsetQuotesParams::FrenchINQuotes)) { // THIN SPACE (U+2009) char_type const thin_space = 0x2009; - if (side_ == InsetQuotesParams::LeftQuote) + if (side_ == InsetQuotesParams::OpeningQuote) retdisp += thin_space; else retdisp = thin_space + retdisp; @@ -528,7 +672,10 @@ void InsetQuotes::metrics(MetricsInfo & mi, Dimension & dim) const void InsetQuotes::draw(PainterInfo & pi, int x, int y) const { FontInfo font = pi.base.font; - font.setPaintColor(pi.textColor(font.realColor())); + if (style_ == InsetQuotesParams::DynamicQuotes) + font.setPaintColor(Color_special); + else + font.setPaintColor(pi.textColor(font.realColor())); pi.pain.text(x, y, displayString(), font); } @@ -606,16 +753,18 @@ bool InsetQuotes::getStatus(Cursor & cur, FuncRequest const & cmd, void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const { - char_type quotechar = quoteparams.getQuoteChar(style_, level_, side_); + InsetQuotesParams::QuoteStyle style = + (style_ == InsetQuotesParams::DynamicQuotes) ? global_style_ : style_; + char_type quotechar = quoteparams.getQuoteChar(style, level_, side_); docstring qstr; // In pass-thru context, we output plain quotes if (runparams.pass_thru) - qstr = (level_ == InsetQuotesParams::DoubleQuotes) ? from_ascii("\"") : from_ascii("'"); - else if (style_ == InsetQuotesParams::PlainQuotes && runparams.isFullUnicode()) { + qstr = (level_ == InsetQuotesParams::PrimaryQuotes) ? from_ascii("\"") : from_ascii("'"); + else if (style == InsetQuotesParams::PlainQuotes && runparams.isFullUnicode()) { // For XeTeX and LuaTeX,we need to disable mapping to get straight // quotes. We define our own commands that do this - qstr = (level_ == InsetQuotesParams::DoubleQuotes) ? + qstr = (level_ == InsetQuotesParams::PrimaryQuotes) ? from_ascii("\\textquotedblplain") : from_ascii("\\textquotesingleplain"); } else if (runparams.use_polyglossia) { @@ -623,12 +772,20 @@ void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const // (spacing and kerning is then handled respectively) qstr = docstring(1, quotechar); } - else if (style_ == InsetQuotesParams::FrenchQuotes - && level_ == InsetQuotesParams::DoubleQuotes + else if (style == InsetQuotesParams::CJKQuotes || style == InsetQuotesParams::CJKAngleQuotes) { + if (runparams.encoding && runparams.encoding->encodable(quotechar)) + qstr = docstring(1, quotechar); + else + qstr = quoteparams.getLaTeXQuote(quotechar, "int"); + } + else if ((style == InsetQuotesParams::SwissQuotes + || style == InsetQuotesParams::FrenchQuotes + || style == InsetQuotesParams::FrenchINQuotes) + && level_ == InsetQuotesParams::PrimaryQuotes && prefixIs(runparams.local_font->language()->code(), "fr")) { // Specific guillemets of French babel // including correct French spacing - if (side_ == InsetQuotesParams::LeftQuote) + if (side_ == InsetQuotesParams::OpeningQuote) qstr = from_ascii("\\og"); else qstr = from_ascii("\\fg"); @@ -671,7 +828,7 @@ void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const os << qstr; - if (prefixIs(qstr, from_ascii("\\"))) + if (prefixIs(qstr, from_ascii("\\")) && !suffixIs(qstr, '}')) // properly terminate the command depending on the context os << termcmd; } @@ -687,14 +844,18 @@ int InsetQuotes::plaintext(odocstringstream & os, docstring InsetQuotes::getQuoteEntity() const { - docstring res = quoteparams.getHTMLQuote(quoteparams.getQuoteChar(style_, level_, side_)); + InsetQuotesParams::QuoteStyle style = + (style_ == InsetQuotesParams::DynamicQuotes) ? global_style_ : style_; + docstring res = quoteparams.getHTMLQuote(quoteparams.getQuoteChar(style, level_, side_)); // in French, thin spaces are added inside double guillemets if (prefixIs(context_lang_, "fr") - && level_ == InsetQuotesParams::DoubleQuotes - && style_ == InsetQuotesParams::FrenchQuotes) { + && level_ == InsetQuotesParams::PrimaryQuotes + && (style == InsetQuotesParams::FrenchQuotes + || style == InsetQuotesParams::FrenchINQuotes + || style == InsetQuotesParams::SwissQuotes)) { // THIN SPACE (U+2009) docstring const thin_space = from_ascii(" "); - if (side_ == InsetQuotesParams::LeftQuote) + if (side_ == InsetQuotesParams::OpeningQuote) res += thin_space; else res = thin_space + res; @@ -735,12 +896,15 @@ void InsetQuotes::updateBuffer(ParIterator const & it, UpdateType /* utype*/) pass_thru_ = it.paragraph().isPassThru(); context_lang_ = it.paragraph().getFontSettings(bp, it.pos()).language()->code(); fontenc_ = (bp.fontenc == "global") ? lyxrc.fontenc : bp.fontenc; + global_style_ = bp.quotes_style; } void InsetQuotes::validate(LaTeXFeatures & features) const { - char_type type = quoteparams.getQuoteChar(style_, level_, side_); + InsetQuotesParams::QuoteStyle style = + (style_ == InsetQuotesParams::DynamicQuotes) ? global_style_ : style_; + char_type type = quoteparams.getQuoteChar(style, level_, side_); // Handle characters that are not natively supported by // specific font encodings (we roll our own definitions) @@ -790,6 +954,13 @@ void InsetQuotes::validate(LaTeXFeatures & features) const features.require("textquotedbl"); break; } + // we fake these from math + case 0x300e: // LEFT WHITE CORNER BRACKET + case 0x300f: // RIGHT WHITE CORNER BRACKET + if (!features.runparams().encoding + || !features.runparams().encoding->encodable(type)) + features.require("stmaryrd"); + break; default: break; }