commit e8c932ff842ced0b26c205ed6983102b6e7e50c2
Author: Juergen Spitzmueller <[email protected]>
Date:   Sat Dec 10 11:53:42 2016 +0100

    Enable InsetQuote in verbatim and Hebrew
    
    In this context, the inset outputs straight quotes in LaTeX.
    
    File format change.
    
    Fixes: #7309
---
 development/FORMAT           |    5 +++
 lib/lyx2lyx/lyx_2_3.py       |   72 +++++++++++++++++++++++++++++++++++++++--
 src/Text3.cpp                |   28 +++++-----------
 src/insets/InsetListings.cpp |   14 +++++++-
 src/insets/InsetListings.h   |    2 +-
 src/insets/InsetQuotes.cpp   |   45 ++++++++++++++++++-------
 src/insets/InsetQuotes.h     |    7 ++++
 src/insets/InsetText.cpp     |    3 +-
 src/version.h                |    4 +-
 9 files changed, 139 insertions(+), 41 deletions(-)

diff --git a/development/FORMAT b/development/FORMAT
index 225d5ca..2a06d49 100644
--- a/development/FORMAT
+++ b/development/FORMAT
@@ -11,6 +11,11 @@ adjustments are made to tex2lyx and bugs are fixed in 
lyx2lyx.
 
 -----------------------
 
+2016-12-10 Jürgen Spitzmüller <[email protected]>
+       * 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 <[email protected]>
        * Format incremented to 516: Removed \inputenc value "pt254"
 
diff --git a/lib/lyx2lyx/lyx_2_3.py b/lib/lyx2lyx/lyx_2_3.py
index 804d0e6..4d42b41 100644
--- a/lib/lyx2lyx/lyx_2_3.py
+++ b/lib/lyx2lyx/lyx_2_3.py
@@ -25,13 +25,14 @@ import sys, os
 
 # 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, \
@@ -492,6 +493,67 @@ def revert_syriac(document):
                                 "\\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
 #
@@ -506,10 +568,12 @@ convert = [
            [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]],
diff --git a/src/Text3.cpp b/src/Text3.cpp
index a2a0cc7..a7c3cd0 100644
--- a/src/Text3.cpp
+++ b/src/Text3.cpp
@@ -1548,26 +1548,15 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                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;
        }
 
@@ -2860,6 +2849,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & 
cmd,
        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;
diff --git a/src/insets/InsetListings.cpp b/src/insets/InsetListings.cpp
index a92c095..bec33b1 100644
--- a/src/insets/InsetListings.cpp
+++ b/src/insets/InsetListings.cpp
@@ -158,8 +158,20 @@ void InsetListings::latex(otexstream & os, OutputParams 
const & runparams) const
                        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!
diff --git a/src/insets/InsetListings.h b/src/insets/InsetListings.h
index 14dbda9..902fa04 100644
--- a/src/insets/InsetListings.h
+++ b/src/insets/InsetListings.h
@@ -78,7 +78,7 @@ private:
        ///
        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_;
diff --git a/src/insets/InsetQuotes.cpp b/src/insets/InsetQuotes.cpp
index 0773e28..130375d 100644
--- a/src/insets/InsetQuotes.cpp
+++ b/src/insets/InsetQuotes.cpp
@@ -24,6 +24,8 @@
 #include "MetricsInfo.h"
 #include "OutputParams.h"
 #include "output_xhtml.h"
+#include "Paragraph.h"
+#include "ParIterator.h"
 #include "texstream.h"
 
 #include "frontends/FontMetrics.h"
@@ -103,7 +105,7 @@ InsetQuotes::InsetQuotes(Buffer * buf, string const & str) 
: Inset(buf)
 }
 
 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;
@@ -188,17 +190,18 @@ void InsetQuotes::parseString(string const & s)
 }
 
 
-// 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)
@@ -253,7 +256,13 @@ void InsetQuotes::latex(otexstream & os, OutputParams 
const & runparams) const
        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)
@@ -273,14 +282,16 @@ void InsetQuotes::latex(otexstream & os, OutputParams 
const & runparams) const
                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);
 }
@@ -327,6 +338,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();
+       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_]];
diff --git a/src/insets/InsetQuotes.h b/src/insets/InsetQuotes.h
index 49bd842..b26c5d3 100644
--- a/src/insets/InsetQuotes.h
+++ b/src/insets/InsetQuotes.h
@@ -90,6 +90,9 @@ public:
        ///
        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;
        ///
@@ -118,6 +121,10 @@ private:
        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
diff --git a/src/insets/InsetText.cpp b/src/insets/InsetText.cpp
index 3c1bb23..607f7f5 100644
--- a/src/insets/InsetText.cpp
+++ b/src/insets/InsetText.cpp
@@ -768,8 +768,9 @@ ParagraphList & InsetText::paragraphs()
 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();
diff --git a/src/version.h b/src/version.h
index 15f687c..5e67fa9 100644
--- a/src/version.h
+++ b/src/version.h
@@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
 
 // 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

Reply via email to