commit cf07d4825f65ab75783bb81d12e882a709aea222
Author: Richard Kimberly Heck <[email protected]>
Date:   Tue Jan 5 17:25:27 2021 -0500

    Fix bug #11104. Activate refstyle support for InsetMathRef.
    
    At the moment, there is no support for plurals and capitalization.
    A long comment explains why. Support could be added for that without
    a format change.
---
 lib/lyx2lyx/lyx_2_4.py      |   40 ++++++++++++++-
 src/frontends/qt/GuiRef.cpp |   16 +++----
 src/insets/InsetRef.cpp     |   34 ++++++-------
 src/insets/InsetRef.h       |   13 +++--
 src/mathed/InsetMathRef.cpp |  113 +++++++++++++++++++++++++++++++++++++++++--
 src/mathed/InsetMathRef.h   |    6 +--
 src/mathed/MathParser.cpp   |    3 +-
 src/support/lstrings.cpp    |    8 +++
 src/support/lstrings.h      |    2 +
 src/version.h               |    4 +-
 10 files changed, 191 insertions(+), 48 deletions(-)

diff --git a/lib/lyx2lyx/lyx_2_4.py b/lib/lyx2lyx/lyx_2_4.py
index a6ce67a..c82d09f 100644
--- a/lib/lyx2lyx/lyx_2_4.py
+++ b/lib/lyx2lyx/lyx_2_4.py
@@ -3993,6 +3993,40 @@ def revert_hrquotes(document):
             document.body[i] = "\\begin_inset Quotes ard"
 
 
+def convert_math_refs(document):
+    i = 0
+    while True:
+        i = find_token(document.body, "\\begin_inset Formula", i)
+        if i == -1:
+            break
+        j = find_end_of_inset(document.body, i)
+        if j == -1:
+            document.warning("Can't find end of inset at line %d of body!" % i)
+            i += 1
+            continue
+        while i < j:
+            document.body[i] = document.body[i].replace("\\prettyref", 
"\\formatted")
+            i += 1
+        
+
+def revert_math_refs(document):
+    i = 0
+    while True:
+        i = find_token(document.body, "\\begin_inset Formula", i)
+        if i == -1:
+            break
+        j = find_end_of_inset(document.body, i)
+        if j == -1:
+            document.warning("Can't find end of inset at line %d of body!" % i)
+            i += 1
+            continue
+        while i < j:
+            document.body[i] = document.body[i].replace("\\formatted", 
"\\prettyref")
+            if "\\labelonly" in document.body[i]:
+                document.body[i] = re.sub("\\\\labelonly{([^}]+?)}", "\\1", 
document.body[i])
+            i += 1
+        
+
 ##
 # Conversion hub
 #
@@ -4054,10 +4088,12 @@ convert = [
            [597, [convert_libertinus_rm_fonts]],
            [598, []],
            [599, []],
-           [600, []]
+           [600, []],
+           [601, [convert_math_refs]]
           ]
 
-revert =  [[598, [revert_hrquotes]],
+revert =  [[599, [revert_math_refs]],
+           [598, [revert_hrquotes]],
            [598, [revert_nopagebreak]],
            [597, [revert_docbook_table_output]],
            [596, [revert_libertinus_rm_fonts,revert_libertinus_sftt_fonts]],
diff --git a/src/frontends/qt/GuiRef.cpp b/src/frontends/qt/GuiRef.cpp
index c5dd8cd..57859be 100644
--- a/src/frontends/qt/GuiRef.cpp
+++ b/src/frontends/qt/GuiRef.cpp
@@ -145,13 +145,14 @@ void GuiRef::enableView(bool enable)
 void GuiRef::enableBoxes()
 {
        QString const reftype =
-               typeCO->itemData(typeCO->currentIndex()).toString();
+           typeCO->itemData(typeCO->currentIndex()).toString();
        bool const isFormatted = (reftype == "formatted");
        bool const isLabelOnly = (reftype == "labelonly");
        bool const usingRefStyle = buffer().params().use_refstyle;
-       pluralCB->setEnabled(isFormatted && usingRefStyle);
-       capsCB->setEnabled(isFormatted && usingRefStyle);
-       noprefixCB->setEnabled(isLabelOnly);
+       bool const intext = bufferview()->cursor().inTexted();
+       pluralCB->setEnabled(intext && isFormatted && usingRefStyle);
+       capsCB->setEnabled(intext && isFormatted && usingRefStyle);
+       noprefixCB->setEnabled(intext && isLabelOnly);
 }
 
 
@@ -324,11 +325,8 @@ void GuiRef::updateContents()
        typeCO->addItem(qt_("on page <page>"), "vpageref");
        typeCO->addItem(qt_("<reference> on page <page>"), "vref");
        typeCO->addItem(qt_("Textual reference"), "nameref");
-       if (bufferview()->cursor().inTexted()) {
-               typeCO->addItem(qt_("Formatted reference"), "formatted");
-               typeCO->addItem(qt_("Label only"), "labelonly");
-       } else
-               typeCO->addItem(qt_("Formatted reference"), "prettyref");
+       typeCO->addItem(qt_("Formatted reference"), "formatted");
+       typeCO->addItem(qt_("Label only"), "labelonly");
 
        referenceED->setText(toqstr(params_["reference"]));
 
diff --git a/src/insets/InsetRef.cpp b/src/insets/InsetRef.cpp
index 200f5e5..cf24571 100644
--- a/src/insets/InsetRef.cpp
+++ b/src/insets/InsetRef.cpp
@@ -174,16 +174,6 @@ bool InsetRef::getStatus(Cursor & cur, FuncRequest const & 
cmd,
 }
 
 
-namespace {
-
-void capitalize(docstring & s) {
-       char_type t = uppercase(s[0]);
-       s[0] = t;
-}
-
-} // namespace
-
-
 // the ref argument is the label name we are referencing.
 // we expect ref to be in the form: pfx:suffix.
 //
@@ -199,7 +189,8 @@ void capitalize(docstring & s) {
 // label, thus: \prettyref{pfx:suffix}.
 //
 docstring InsetRef::getFormattedCmd(docstring const & ref,
-       docstring & label, docstring & prefix, docstring const & caps) const
+       docstring & label, docstring & prefix, bool use_refstyle,
+       bool use_caps)
 {
        static docstring const defcmd = from_ascii("\\ref");
        static docstring const prtcmd = from_ascii("\\prettyref");
@@ -216,11 +207,12 @@ docstring InsetRef::getFormattedCmd(docstring const & ref,
 
        if (prefix.empty()) {
                // we have ":xxxx"
+               LYXERR0("Label `" << ref << "' contains nothign before `:'.");
                label = ref;
                return defcmd;
        }
 
-       if (!buffer().params().use_refstyle) {
+       if (!use_refstyle) {
                // \prettyref uses the whole label
                label = ref;
                return prtcmd;
@@ -237,8 +229,8 @@ docstring InsetRef::getFormattedCmd(docstring const & ref,
                        return defcmd;
                }
        }
-       if (caps == "true") {
-               capitalize(prefix);
+       if (use_caps) {
+               prefix = support::capitalize(prefix);
        }
        return from_ascii("\\") + prefix + from_ascii("ref");
 }
@@ -261,7 +253,7 @@ void InsetRef::latex(otexstream & os, OutputParams const & 
rp) const
        if (rp.inulemcmd > 0)
                os << "\\mbox{";
 
-       if (cmd == "eqref" && buffer().params().use_refstyle) {
+       if (buffer().params().use_refstyle && cmd == "eqref") {
                // we advertise this as printing "(n)", so we'll do that, at 
least
                // for refstyle, since refstlye's own \eqref prints, by default,
                // "equation n". if one wants \eqref, one can get it by using a
@@ -271,10 +263,12 @@ void InsetRef::latex(otexstream & os, OutputParams const 
& rp) const
        else if (cmd == "formatted") {
                docstring label;
                docstring prefix;
+               bool const use_caps   = getParam("caps") == "true";
+               bool const use_plural = getParam("plural") == "true";
                docstring const fcmd =
-                       getFormattedCmd(data, label, prefix, getParam("caps"));
+                       getFormattedCmd(data, label, prefix, use_caps);
                os << fcmd;
-               if (buffer().params().use_refstyle && getParam("plural") == 
"true")
+               if (buffer().params().use_refstyle && use_plural)
                    os << "[s]";
                os << '{' << label << '}';
        }
@@ -542,9 +536,11 @@ void InsetRef::validate(LaTeXFeatures & features) const
                docstring const data = getEscapedLabel(features.runparams());
                docstring label;
                docstring prefix;
+               bool const use_refstyle = buffer().params().use_refstyle;
+               bool const use_caps   = getParam("caps") == "true";
                docstring const fcmd =
-                       getFormattedCmd(data, label, prefix, getParam("caps"));
-               if (buffer().params().use_refstyle) {
+                       getFormattedCmd(data, label, prefix, use_refstyle, 
use_caps);
+               if (use_refstyle) {
                        features.require("refstyle");
                        if (prefix == "cha")
                                
features.addPreambleSnippet(from_ascii("\\let\\charef=\\chapref"));
diff --git a/src/insets/InsetRef.h b/src/insets/InsetRef.h
index d18f619..57377e1 100644
--- a/src/insets/InsetRef.h
+++ b/src/insets/InsetRef.h
@@ -90,6 +90,13 @@ public:
        //@}
        ///
        bool outputActive() const { return active_; }
+       /// \return the command for a formatted reference to ref
+       /// \param label we're cross-referencing
+       /// \param argument for reference command
+       /// \param prefix of the label (before :)
+       /// Also used by InsetMathRef
+       static docstring getFormattedCmd(docstring const & ref, docstring & 
label,
+                       docstring & prefix, bool use_refstyle, bool use_caps = 
false);
 
 protected:
        ///
@@ -110,12 +117,6 @@ private:
 
        /// \return the label with things that need to be escaped escaped
        docstring getEscapedLabel(OutputParams const &) const;
-       /// \return the command for a formatted reference to ref
-       /// \param label we're cross-referencing
-       /// \param argument for reference command
-       /// \param prefix of the label (before :)
-       docstring getFormattedCmd(docstring const & ref, docstring & label,
-                       docstring & prefix, docstring const & caps) const;
 
        ///
        mutable docstring screen_label_;
diff --git a/src/mathed/InsetMathRef.cpp b/src/mathed/InsetMathRef.cpp
index 9efd865..7170ca6 100644
--- a/src/mathed/InsetMathRef.cpp
+++ b/src/mathed/InsetMathRef.cpp
@@ -12,6 +12,7 @@
 
 #include "InsetMathRef.h"
 
+#include "BufferParams.h"
 #include "BufferView.h"
 #include "Buffer.h"
 #include "Cursor.h"
@@ -21,14 +22,18 @@
 #include "LyX.h"
 #include "MathData.h"
 #include "MathFactory.h"
+#include "MathStream.h"
 #include "MathSupport.h"
 #include "ParIterator.h"
 #include "xml.h"
 
 #include "insets/InsetCommand.h"
+#include "insets/InsetRef.h"
 
 #include "support/debug.h"
 #include "support/gettext.h"
+#include "support/lstrings.h"
+#include "support/textutils.h"
 
 #include <ostream>
 
@@ -75,7 +80,9 @@ void InsetMathRef::doDispatch(Cursor & cur, FuncRequest & cmd)
                        MathData ar;
                        if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
                                cur.recordUndo();
+                               Buffer & buf = buffer();
                                *this = *ar[0].nucleus()->asRefInset();
+                               setBuffer(buf);
                                break;
                        }
                }
@@ -170,11 +177,24 @@ docstring const InsetMathRef::screenLabel() const
 
 void InsetMathRef::validate(LaTeXFeatures & features) const
 {
+       // This really should not happen here but does.
+       if (!buffer_) {
+               LYXERR0("Unassigned buffer_ in InsetMathRef::write!");
+               LYXERR0("LaTeX output may be wrong!");
+       }
+       bool const use_refstyle =
+               buffer_ && buffer().params().use_refstyle;
+
        if (commandname() == "vref" || commandname() == "vpageref")
                features.require("varioref");
-       else if (commandname() == "prettyref")
-               features.require("prettyref");
-       else if (commandname() == "eqref")
+       else if (commandname() == "formatted") {
+               if (use_refstyle)
+                       features.require("refstyle");
+               else
+                       features.require("prettyref");
+       }
+       // if eqref is used with refstyle, we do our own output
+       else if (commandname() == "eqref" && use_refstyle)
                features.require("amsmath");
        else if (commandname() == "nameref")
                features.require("nameref");
@@ -240,14 +260,99 @@ void InsetMathRef::changeTarget(docstring const & target)
 }
 
 
+void InsetMathRef::write(TeXMathStream & os) const
+{
+       docstring const & cmd = commandname();
+       // This should not happen, but of course it does
+       if (!buffer_) {
+               LYXERR0("Unassigned buffer_ in InsetMathRef::write!");
+               LYXERR0("LaTeX output may be wrong!");
+       }
+       bool const use_refstyle =
+               buffer_ && buffer().params().use_refstyle;
+       bool special_case =  cmd == "formatted" ||
+                       cmd == "labelonly" ||
+                       (cmd == "eqref" && use_refstyle);
+       // are we writing to the LyX file or not in a special case?
+       if (!os.latex() || !special_case) {
+               // if so, then this is easy
+               InsetMathCommand::write(os);
+               return;
+       }
+       // we need to translate 'formatted' to prettyref or refstyle-type
+       // commands and just output the label with labelonly
+       // most of this is borrowed from InsetRef and should be kept in 
+       // sync with that.
+       ModeSpecifier specifier(os, currentMode(), lockedMode(), asciiOnly());
+       MathEnsurer ensurer(os, false);
+
+       if (use_refstyle && cmd == "eqref") {
+               // we advertise this as printing "(n)", so we'll do that, at 
least
+               // for refstyle, since refstlye's own \eqref prints, by default,
+               // "equation n". if one wants \eqref, one can get it by using a
+               // formatted label in this case.
+               os << '(' << from_ascii("\\ref{") << cell(0) << 
from_ascii("})");
+       }
+       else if (cmd == "formatted") {
+               if (!use_refstyle)
+                       os << "\\prettyref{" << cell(0) << "}";
+               else {
+                        odocstringstream ods;
+                       // get the label we are referencing
+                       for (auto const & d : cell(0)) {
+                               ods << d;
+                       }
+                       docstring const ref = ods.str();
+
+                       /*
+                       At the moment, the 'plural' and 'caps' options will
+                       not work here. The reason is that we handle these as
+                       'internal' LyX argumemts, but those are not handled by
+                       InsetCommandParams::getCommand, which is what is used
+                       in createInsetMath_fromDialogStr to interpret the data
+                       coming from the dialog.
+                       If this is fixed, then what follows will get the info
+                       we need.
+                       Fixing it, I think, would mean sub-classing
+                       InsetCommandParams to InsetRefParams, and the overriding
+                       getCommand.
+                       *******************************************************
+                       // reset
+                       ods.str(docstring());
+                       ods.clear();
+                       // get the options from the optional argument
+                       for (auto const & d : cell(1))
+                               ods << d;
+                       docstring const options = ods.str();
+                       bool const caps   = support::contains(options, 'C');
+                       bool const plural = support::contains(options, 's');
+                       */
+                       docstring label;
+                       docstring prefix;
+                       docstring const fcmd =
+                               InsetRef::getFormattedCmd(ref, label, prefix, 
true);
+                       os << fcmd;
+                       //if (plural)
+                       //      os << "[s]";
+                       os << '{' << label << '}';
+               }
+       }
+       else if (cmd == "labelonly") {
+               // noprefix does not work here, for reasons given above.
+               os << cell(0);
+       }
+}
+
+
 InsetMathRef::ref_type_info InsetMathRef::types[] = {
        { from_ascii("ref"),       from_ascii(N_("Standard[[mathref]]")),   
from_ascii(N_("Ref: "))},
        { from_ascii("eqref"),     from_ascii(N_("Equation")),              
from_ascii(N_("EqRef: "))},
        { from_ascii("pageref"),   from_ascii(N_("Page Number")),           
from_ascii(N_("Page: "))},
        { from_ascii("vpageref"),  from_ascii(N_("Textual Page Number")),   
from_ascii(N_("TextPage: "))},
        { from_ascii("vref"),      from_ascii(N_("Standard+Textual Page")), 
from_ascii(N_("Ref+Text: "))},
-       { from_ascii("prettyref"), from_ascii(N_("PrettyRef")),             
from_ascii(N_("FormatRef: "))},
+       { from_ascii("formatted"), from_ascii(N_("PrettyRef")),             
from_ascii(N_("FormatRef: "))},
        { from_ascii("nameref"),   from_ascii(N_("Reference to Name")),     
from_ascii(N_("NameRef: "))},
+       { from_ascii("labelonly"), from_ascii(N_("Label Only")),             
from_ascii(N_("Label Only: "))},
        { from_ascii(""), from_ascii(""), from_ascii("") }
 };
 
diff --git a/src/mathed/InsetMathRef.h b/src/mathed/InsetMathRef.h
index acbe47b..5527a0d 100644
--- a/src/mathed/InsetMathRef.h
+++ b/src/mathed/InsetMathRef.h
@@ -29,7 +29,7 @@ public:
        ///
        void updateBuffer(ParIterator const &, UpdateType, bool const deleted = 
false) override;
        ///
-       //void write(TeXMathStream & os) const override;
+       void write(TeXMathStream & os) const override;
        ///
        void infoize(odocstream & os) const override;
        ///
@@ -62,10 +62,6 @@ public:
        };
        static ref_type_info types[];
        ///
-       static int getType(docstring const & name);
-       ///
-       static docstring const & getName(int type);
-       ///
        docstring const getTarget() const;
        ///
        InsetCode lyxCode() const override { return MATH_REF_CODE; }
diff --git a/src/mathed/MathParser.cpp b/src/mathed/MathParser.cpp
index 478e906..6d1b747 100644
--- a/src/mathed/MathParser.cpp
+++ b/src/mathed/MathParser.cpp
@@ -1546,7 +1546,8 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
 
                else if (t.cs() == "ref" || t.cs() == "eqref" || t.cs() == 
"prettyref"
                          || t.cs() == "nameref" || t.cs() == "pageref"
-                         || t.cs() == "vpageref" || t.cs() == "vref") {
+                         || t.cs() == "vpageref" || t.cs() == "vref" 
+                         || t.cs() == "formatted" || t.cs() == "labelonly") {
                        cell->push_back(MathAtom(new InsetMathRef(buf, 
t.cs())));
                        docstring const opt = parse_verbatim_option();
                        docstring const ref = parse_verbatim_item();
diff --git a/src/support/lstrings.cpp b/src/support/lstrings.cpp
index 9aac66a..b85307f 100644
--- a/src/support/lstrings.cpp
+++ b/src/support/lstrings.cpp
@@ -543,6 +543,14 @@ docstring const uppercase(docstring const & a)
 }
 
 
+docstring capitalize(docstring const & s) {
+       docstring ret = s;
+       char_type t = uppercase(ret[0]);
+       ret[0] = t;
+       return ret;
+}
+
+
 string const ascii_lowercase(string const & a)
 {
        string tmp(a);
diff --git a/src/support/lstrings.h b/src/support/lstrings.h
index 9371968..b4f99f8 100644
--- a/src/support/lstrings.h
+++ b/src/support/lstrings.h
@@ -181,6 +181,8 @@ docstring const token(docstring const & a, char_type delim, 
int n);
 int tokenPos(std::string const & a, char delim, std::string const & tok);
 int tokenPos(docstring const & a, char_type delim, docstring const & tok);
 
+///
+docstring capitalize(docstring const & s);
 
 /// Substitute all \a oldchar with \a newchar
 std::string const subst(std::string const & a, char oldchar, char newchar);
diff --git a/src/version.h b/src/version.h
index 7b31131..13cf4d0 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 600 // spitz: hungarian quote style
-#define LYX_FORMAT_TEX2LYX 600
+#define LYX_FORMAT_LYX 601 // rkh: refstyle in math
+#define LYX_FORMAT_TEX2LYX 601
 
 #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
 #ifndef _MSC_VER
-- 
lyx-cvs mailing list
[email protected]
http://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to