In this context, the inset outputs straight quotes in LaTeX.
File format change.
Fixes: #7309
-----------------------
+2016-12-10 Jürgen Spitzmüller <spitz@lyx.org>
+ * Format incremented to 517: InsetQuote now works in verbatim
+ and Hebrew. On reversion, it is replaced by straight quotes
+ in these contexts.
+
2016-12-07 Günter Milde <milde@lyx.org>
* Format incremented to 516: Removed \inputenc value "pt254"
# Uncomment only what you need to import, please.
-from parser_tools import find_end_of#, find_token, find_tokens, \
+from parser_tools import find_end_of, find_token_backwards#,
+# find_token, find_tokens, \
# find_token_exact, find_end_of_inset, find_end_of_layout, \
-# find_token_backwards, is_in_inset, get_value, get_quoted_value, \
+# is_in_inset, get_value, get_quoted_value, \
# del_token, check_token, get_option_value, get_bool_value
from parser_tools import find_token, find_end_of_inset, get_value, \
- get_bool_value
+ get_bool_value, get_containing_layout
from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert
# get_ert, lyx2latex, \
"\\end_layout", ""]
+def revert_quotes(document):
+ " Revert Quote Insets in verbatim or Hebrew context to plain quotes "
+
+ # First handle verbatim insets
+ i = 0
+ j = 0
+ while i < len(document.body):
+ words = document.body[i].split()
+ if len(words) > 1 and words[0] == "\\begin_inset" and \
+ ( words[1] in ["ERT", "listings"] or words[2] == "URL" ):
+ j = find_end_of_inset(document.body, i)
+ if j == -1:
+ document.warning("Malformed LyX document: Can't find end of " + words[1] + " inset at line " + str(i))
+ i += 1
+ continue
+ while True:
+ k = find_token(document.body, '\\begin_inset Quotes', i, j)
+ if k == -1:
+ i += 1
+ break
+ l = find_end_of_inset(document.body, k)
+ if l == -1:
+ document.warning("Malformed LyX document: Can't find end of Quote inset at line " + str(k))
+ i = k
+ continue
+ replace = "\""
+ if document.body[k].endswith("s"):
+ replace = "'"
+ document.body[k:l+1] = [replace]
+ else:
+ i += 1
+ continue
+
+ # Now handle Hebrew
+ i = 0
+ j = 0
+ while True:
+ k = find_token(document.body, '\\begin_inset Quotes', i, j)
+ if k == -1:
+ return
+ l = find_end_of_inset(document.body, k)
+ if l == -1:
+ document.warning("Malformed LyX document: Can't find end of Quote inset at line " + str(k))
+ i = k
+ continue
+ hebrew = False
+ parent = get_containing_layout(document.body, k)
+ ql = find_token_backwards(document.body, "\\lang", k)
+ if ql == -1 or ql < parent[1]:
+ hebrew = document.language == "hebrew"
+ elif document.body[ql] == "\\lang hebrew":
+ hebrew = True
+ if hebrew:
+ replace = "\""
+ if document.body[k].endswith("s"):
+ replace = "'"
+ document.body[k:l+1] = [replace]
+ i += 1
+
+
+
##
# Conversion hub
#
[514, []],
[515, []],
[516, [convert_inputenc]],
+ [517, []]
]
revert = [
- [516, []],
+ [516, [revert_quotes]],
+ [515, []],
[514, [revert_urdu, revert_syriac]],
[513, [revert_amharic, revert_asturian, revert_kannada, revert_khmer]],
[512, [revert_bosnian, revert_friulan, revert_macedonian, revert_piedmontese, revert_romansh]],
while (pos > 0 && par.isDeleted(pos - 1))
--pos;
- BufferParams const & bufparams = bv->buffer().params();
- bool const hebrew =
- par.getFontSettings(bufparams, pos).language()->lang() == "hebrew";
- bool const allow_inset_quote = !(par.isPassThru() || hebrew);
-
string const arg = to_utf8(cmd.argument());
- if (allow_inset_quote) {
- char_type c = ' ';
- if (pos > 0 && (!cur.prevInset() || !cur.prevInset()->isSpace()))
- c = par.getChar(pos - 1);
- InsetQuotes::QuoteTimes const quote_type = (arg == "single")
- ? InsetQuotes::SingleQuotes : InsetQuotes::DoubleQuotes;
- cur.insert(new InsetQuotes(cur.buffer(), c, quote_type));
- cur.posForward();
- } else {
- // The cursor might have been invalidated by the replaceSelection.
- cur.buffer()->changed(true);
- string const quote_string = (arg == "single") ? "'" : "\"";
- lyx::dispatch(FuncRequest(LFUN_SELF_INSERT, quote_string));
- }
+ char_type c = ' ';
+ if (pos > 0 && (!cur.prevInset() || !cur.prevInset()->isSpace()))
+ c = par.getChar(pos - 1);
+ InsetQuotes::QuoteTimes const quote_type = (arg == "single")
+ ? InsetQuotes::SingleQuotes : InsetQuotes::DoubleQuotes;
+ cur.insert(new InsetQuotes(cur.buffer(), c, quote_type));
+ cur.buffer()->updateBuffer();
+ cur.posForward();
break;
}
case LFUN_QUOTE_INSERT:
// always allow this, since we will inset a raw quote
// if an inset is not allowed.
+ allow_in_passthru = true;
break;
case LFUN_SPECIALCHAR_INSERT:
code = SPECIALCHAR_CODE;
if (i == 0 && par->isInset(i) && i + 1 == siz)
captionline = true;
// ignore all struck out text and (caption) insets
- if (par->isDeleted(i) || par->isInset(i))
+ if (par->isDeleted(i)
+ || (par->isInset(i) && par->getInset(i)->lyxCode() == CAPTION_CODE))
continue;
+ if (par->isInset(i)) {
+ // Currently, this can only be a quote inset
+ // that is output as plain quote here, but
+ // we use more generic code anyway.
+ otexstringstream ots;
+ OutputParams rp = runparams;
+ rp.pass_thru = true;
+ par->getInset(i)->latex(ots, rp);
+ code += ots.str();
+ continue;
+ }
char_type c = par->getChar(i);
// we can only output characters covered by the current
// encoding!
///
TexString getCaption(OutputParams const &) const;
///
- bool insetAllowed(InsetCode c) const { return c == CAPTION_CODE; }
+ bool insetAllowed(InsetCode c) const { return c == CAPTION_CODE || c == QUOTE_CODE; }
///
InsetListingsParams params_;
#include "MetricsInfo.h"
#include "OutputParams.h"
#include "output_xhtml.h"
+#include "Paragraph.h"
+#include "ParIterator.h"
#include "texstream.h"
#include "frontends/FontMetrics.h"
}
InsetQuotes::InsetQuotes(Buffer * buf, char_type c, QuoteTimes t)
- : Inset(buf), times_(t)
+ : Inset(buf), times_(t), pass_thru_(false)
{
if (buf) {
language_ = buf->params().quotes_language;
}
-// FIXME: should we add a language or a font parameter member?
docstring InsetQuotes::displayString() const
{
- Language const * loclang =
- isBufferValid() ? buffer().params().language : 0;
+ // In PassThru and Hebrew, we use straight quotes
+ if (pass_thru_ || context_lang_ == "he_IL")
+ return (times_ == DoubleQuotes) ? from_ascii("\"") : from_ascii("'");
+
int const index = quote_index[side_][language_];
docstring retdisp = docstring(1, display_quote_char[times_][index]);
- // in french, thin spaces are added inside double quotes
+ // in French, thin spaces are added inside double quotes
// FIXME: this should be done by a separate quote type.
- if (times_ == DoubleQuotes && loclang && prefixIs(loclang->code(), "fr")) {
+ if (times_ == DoubleQuotes && prefixIs(context_lang_, "fr")) {
// THIN SPACE (U+2009)
char_type const thin_space = 0x2009;
if (side_ == LeftQuote)
const int quoteind = quote_index[side_][language_];
string qstr;
- if (language_ == FrenchQuotes && times_ == DoubleQuotes
+ // In some context, we output plain quotes
+ bool const force_plain =
+ runparams.pass_thru
+ || runparams.local_font->language()->lang() == "hebrew";
+ if (force_plain)
+ qstr = (times_ == DoubleQuotes) ? "\"" : "'";
+ else if (language_ == FrenchQuotes && times_ == DoubleQuotes
&& prefixIs(runparams.local_font->language()->code(), "fr")
&& !runparams.use_polyglossia) {
if (side_ == LeftQuote)
qstr = latex_quote_babel[times_][quoteind];
}
- // Always guard against unfortunate ligatures (!` ?` `` '' ,, << >>)
- char_type const lastchar = os.lastChar();
- if (prefixIs(qstr, "`")) {
- if (lastchar == '!' || lastchar == '?')
+ if (!force_plain) {
+ // Always guard against unfortunate ligatures (!` ?` `` '' ,, << >>)
+ char_type const lastchar = os.lastChar();
+ if (prefixIs(qstr, "`")) {
+ if (lastchar == '!' || lastchar == '?')
+ qstr.insert(0, "{}");
+ }
+ if (qstr[1] == lastchar)
qstr.insert(0, "{}");
}
- if (qstr[1] == lastchar)
- qstr.insert(0, "{}");
os << from_ascii(qstr);
}
}
+void InsetQuotes::updateBuffer(ParIterator const & it, UpdateType /* utype*/)
+{
+ BufferParams const & bp = buffer().masterBuffer()->params();
+ pass_thru_ = it.paragraph().isPassThru();
+ context_lang_ = it.paragraph().getFontSettings(bp, it.pos()).language()->code();
+}
+
+
void InsetQuotes::validate(LaTeXFeatures & features) const
{
char type = quote_char[quote_index[side_][language_]];
///
void forOutliner(docstring &, size_t const maxlen, bool const) const;
+ /// Update the contextual information of this inset
+ void updateBuffer(ParIterator const &, UpdateType);
+
///
void validate(LaTeXFeatures &) const;
///
QuoteTimes times_;
///
std::string fontenc_;
+ /// Code of the contextual language
+ std::string context_lang_;
+ /// Is this in a pass-thru context?
+ bool pass_thru_;
};
} // namespace lyx
bool InsetText::insetAllowed(InsetCode code) const
{
switch (code) {
- // Arguments are also allowed in PassThru insets
+ // Arguments and (plain) quotes are also allowed in PassThru insets
case ARG_CODE:
+ case QUOTE_CODE:
return true;
default:
return !isPassThru();
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
-#define LYX_FORMAT_LYX 516 // Removed \inputenc value "pt254"
-#define LYX_FORMAT_TEX2LYX 516
+#define LYX_FORMAT_LYX 517 // spitz: quote inset in verbatim
+#define LYX_FORMAT_TEX2LYX 517
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER