[LyX features/biginset] Fix label escaping in InsetMathRef (#12980)

Juergen Spitzmueller spitz at lyx.org
Fri Apr 5 13:41:47 UTC 2024


commit 98080ca0d548b754433a99f9f097054134117184
Author: Juergen Spitzmueller <spitz at lyx.org>
Date:   Tue Apr 2 08:15:53 2024 +0200

    Fix label escaping in InsetMathRef (#12980)
    
    This was completely broken: the IDs have been escaped in the LyX file
    (which they absolutely shouldn't) but not in all LaTeX output (which
    they should).
---
 src/insets/InsetCommandParams.cpp |  9 ++++++---
 src/insets/InsetCommandParams.h   |  2 +-
 src/mathed/InsetMathRef.cpp       | 22 ++++++++++++----------
 src/mathed/MathExtern.cpp         | 15 ++++++++++-----
 src/mathed/MathFactory.cpp        |  2 +-
 5 files changed, 30 insertions(+), 20 deletions(-)

diff --git a/src/insets/InsetCommandParams.cpp b/src/insets/InsetCommandParams.cpp
index 034f9d59c8..9c3552a4b7 100644
--- a/src/insets/InsetCommandParams.cpp
+++ b/src/insets/InsetCommandParams.cpp
@@ -569,7 +569,7 @@ docstring InsetCommandParams::prepareCommand(OutputParams const & runparams,
 }
 
 
-docstring InsetCommandParams::getCommand(OutputParams const & runparams, bool starred) const
+docstring InsetCommandParams::getCommand(OutputParams const & runparams, bool starred, bool unhandled) const
 {
 	docstring s = '\\' + from_ascii(cmdName_);
 	if (starred)
@@ -579,20 +579,23 @@ docstring InsetCommandParams::getCommand(OutputParams const & runparams, bool st
 	ParamInfo::const_iterator end = info_.end();
 	for (; it != end; ++it) {
 		std::string const & name = it->name();
+		ParamInfo::ParamHandling handling = unhandled ?
+					ParamInfo::HANDLING_NONE
+				      : it->handling();
 		switch (it->type()) {
 		case ParamInfo::LYX_INTERNAL:
 			break;
 
 		case ParamInfo::LATEX_REQUIRED: {
 			docstring const data =
-				prepareCommand(runparams, (*this)[name], it->handling());
+				prepareCommand(runparams, (*this)[name], handling);
 			s += '{' + data + '}';
 			noparam = false;
 			break;
 		}
 		case ParamInfo::LATEX_OPTIONAL: {
 			docstring data =
-				prepareCommand(runparams, (*this)[name], it->handling());
+				prepareCommand(runparams, (*this)[name], handling);
 			if (!data.empty()) {
 				s += '[' + protectArgument(data) + ']';
 				noparam = false;
diff --git a/src/insets/InsetCommandParams.h b/src/insets/InsetCommandParams.h
index 134b46a604..f05fb61ddc 100644
--- a/src/insets/InsetCommandParams.h
+++ b/src/insets/InsetCommandParams.h
@@ -136,7 +136,7 @@ public:
 	///
 	void Write(std::ostream & os, Buffer const * buf) const;
 	/// Build the complete LaTeX command
-	docstring getCommand(OutputParams const &, bool starred = false) const;
+	docstring getCommand(OutputParams const &, bool starred = false, bool unhandled = false) const;
 	/// Return the command name
 	std::string const & getCmdName() const { return cmdName_; }
 	/// Set the name to \p n. This must be a known name. All parameters
diff --git a/src/mathed/InsetMathRef.cpp b/src/mathed/InsetMathRef.cpp
index ad2e499167..082a341cf4 100644
--- a/src/mathed/InsetMathRef.cpp
+++ b/src/mathed/InsetMathRef.cpp
@@ -76,7 +76,7 @@ void InsetMathRef::doDispatch(Cursor & cur, FuncRequest & cmd)
 	switch (cmd.action()) {
 	case LFUN_INSET_MODIFY: {
 		string const arg0 = cmd.getArg(0);
-		string const arg1   = cmd.getArg(1);
+		string const arg1 = cmd.getArg(1);
 		if (arg0 == "ref") {
 			if (arg1 == "changetarget") {
 				string const oldtarget = cmd.getArg(2);
@@ -295,25 +295,27 @@ void InsetMathRef::write(TeXMathStream & os) const
 		LYXERR0("Unassigned buffer_ in InsetMathRef::write!");
 		LYXERR0("LaTeX output may be wrong!");
 	}
+	// are we writing to the LyX file?
+	if (!os.latex()) {
+		// if so, then this is easy
+		InsetMathCommand::write(os);
+		return;
+	}
 	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") {
+	if (!special_case) {
+		os << from_ascii("\\") << cmd << "{" << cell(0) << from_ascii("}");
+	}
+	else 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
@@ -324,7 +326,7 @@ void InsetMathRef::write(TeXMathStream & os) const
 		if (!use_refstyle)
 			os << "\\prettyref{" << cell(0) << "}";
 		else {
-			 odocstringstream ods;
+			odocstringstream ods;
 			// get the label we are referencing
 			for (auto const & d : cell(0)) {
 				ods << d;
diff --git a/src/mathed/MathExtern.cpp b/src/mathed/MathExtern.cpp
index e273aac791..610878455e 100644
--- a/src/mathed/MathExtern.cpp
+++ b/src/mathed/MathExtern.cpp
@@ -1463,18 +1463,23 @@ void write(MathData const & dat, TeXMathStream & wi)
 void writeString(docstring const & s, TeXMathStream & os)
 {
 	if (!os.latex()) {
-		os << (os.asciiOnly() ? escape(s) : s);
+		os << s;
 		return;
 	}
-	else if (os.output() == TeXMathStream::wsSearchAdv) {
-		os << s;
+
+	docstring str = s;
+	if (os.asciiOnly())
+		str = escape(s);
+
+	if (os.output() == TeXMathStream::wsSearchAdv) {
+		os << str;
 		return;
 	}
 
 	if (os.lockedMode()) {
 		bool space;
 		docstring cmd;
-		for (char_type c : s) {
+		for (char_type c : str) {
 			try {
 				Encodings::latexMathChar(c, true, os.encoding(), cmd, space);
 				os << cmd;
@@ -1512,7 +1517,7 @@ void writeString(docstring const & s, TeXMathStream & os)
 	// We will take care of matching braces.
 	os.pendingBrace(false);
 
-	for (char_type const c : s) {
+	for (char_type const c : str) {
 		bool mathmode = in_forced_mode ? os.textMode() : !os.textMode();
 		docstring command(1, c);
 		try {
diff --git a/src/mathed/MathFactory.cpp b/src/mathed/MathFactory.cpp
index 66535beb8d..299cf00c05 100644
--- a/src/mathed/MathFactory.cpp
+++ b/src/mathed/MathFactory.cpp
@@ -703,7 +703,7 @@ bool createInsetMath_fromDialogStr(docstring const & str, MathData & ar)
 		InsetCommand::string2params(to_utf8(str), icp);
 		Encoding const * const utf8 = encodings.fromLyXName("utf8");
 		OutputParams op(utf8);
-		mathed_parse_cell(ar, icp.getCommand(op));
+		mathed_parse_cell(ar, icp.getCommand(op, false, true));
 	} else if (name == "mathspace") {
 		InsetSpaceParams isp(true);
 		InsetSpace::string2params(to_utf8(str), isp);


More information about the lyx-cvs mailing list