#include "BufferView.h"
#include "Cursor.h"
#include "Dimension.h"
+#include "Encoding.h"
#include "Font.h"
#include "FuncStatus.h"
#include "FuncRequest.h"
* s ''swedish'' ('inner quotation')
* g ,,german`` (,inner quotation`)
* p ,,polish'' (,inner quotation')
- * f <<french>> (<inner quotation>)
+ * c <<swiss>> (<inner quotation>)
* a >>danish<< (>inner quotation<)
* q "plain" ('inner quotation')
+ * b `british' (``inner quotation'')
+ * w >>swedishg>> ('inner quotation') ["g" = Guillemets]
+ * f <<french>> (``inner quotation'')
+ * i <<frenchin>> (<<inner quotation>>) ["in" = Imprimerie Nationale]
+ * r <<russian>> (,,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";
right_secondary = 0x2019; // '
break;
}
- case FrenchQuotes: {
+ case SwissQuotes: {
left_primary = 0x00ab; // <<
right_primary = 0x00bb; // >>
left_secondary = 0x2039; // <
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; // ?
}
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;
}
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;
}
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;
}
// 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) {
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))
);
}
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);
}
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);
}
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
}
}
if (i >= 2) {
LYXERR0("ERROR (InsetQuotes::InsetQuotes):"
" bad side specification.");
- side_ = InsetQuotesParams::LeftQuote;
+ side_ = InsetQuotesParams::OpeningQuote;
}
}
if (i >= 2) {
LYXERR0("ERROR (InsetQuotes::InsetQuotes):"
" bad level specification.");
- level_ = InsetQuotesParams::DoubleQuotes;
+ level_ = InsetQuotesParams::PrimaryQuotes;
}
}
}
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;
}
{
// 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;
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);
}
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) {
// (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");
os << qstr;
- if (prefixIs(qstr, from_ascii("\\")))
+ if (prefixIs(qstr, from_ascii("\\")) && !suffixIs(qstr, '}'))
// properly terminate the command depending on the context
os << termcmd;
}
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;
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)
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;
}