]> git.lyx.org Git - features.git/commitdiff
Enable InsetQuote in verbatim and Hebrew
authorJuergen Spitzmueller <spitz@lyx.org>
Sat, 10 Dec 2016 10:53:42 +0000 (11:53 +0100)
committerJuergen Spitzmueller <spitz@lyx.org>
Sat, 10 Dec 2016 10:53:42 +0000 (11:53 +0100)
In this context, the inset outputs straight quotes in LaTeX.

File format change.

Fixes: #7309
development/FORMAT
lib/lyx2lyx/lyx_2_3.py
src/Text3.cpp
src/insets/InsetListings.cpp
src/insets/InsetListings.h
src/insets/InsetQuotes.cpp
src/insets/InsetQuotes.h
src/insets/InsetText.cpp
src/version.h

index 225d5caaa3a47d6c60b8696c41c1e5b7a5554175..2a06d4977213215f5bffc68dba58d5a96bf69cd5 100644 (file)
@@ -11,6 +11,11 @@ adjustments are made to tex2lyx and bugs are fixed in lyx2lyx.
 
 -----------------------
 
+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"
 
index 804d0e62c290dbf8f136dd32ded9ac61b09c23cd..4d42b41f1b3bc891e058c46fb37344254e29062c 100644 (file)
@@ -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]],
index a2a0cc729e55c16d96b3fbf25d94d0850e72de9e..a7c3cd00df0b9efe8d50b9bc8ebc87957650e4ed 100644 (file)
@@ -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;
index a92c09525c9f0dc8616b4d551e7fa6fc40817e7b..bec33b12cb44ee86ce28d927a1757a21a34cb99d 100644 (file)
@@ -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!
index 14dbda94d096f543cae1a391a0d659c4c9b61146..902fa0437e64009770293859e2540322c3b53fd9 100644 (file)
@@ -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_;
index 0773e284ef26827d1c09ac401252346645e16e7b..130375dfb04e3e61a38c1a83f521b9e8e15eb620 100644 (file)
@@ -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_]];
index 49bd84205da6ce18526f011154a51e1c5d8690f8..b26c5d3235402b6e2fe6b3020a71897f65f7b859 100644 (file)
@@ -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
index 3c1bb23f20da669448944bc8fa1b35dbe77d1447..607f7f577ab1d79c5c782ecdf451d89d971ee6e4 100644 (file)
@@ -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();
index 15f687c1359280a6a79ad78f6927c9ebc78c3e2d..5e67fa9604efb8efea6709ad090ca6abb34ec4b4 100644 (file)
@@ -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