[LyX/master] CharInfo: allow to store several commands (both text and math) for each character.

Thibaut Cuvelier tcuvelier at lyx.org
Sun Feb 20 00:01:30 UTC 2022


commit 3f9e21b826926f90474c9b7a5aeea5032d19207f
Author: Thibaut Cuvelier <tcuvelier at lyx.org>
Date:   Fri Feb 18 22:11:04 2022 +0100

    CharInfo: allow to store several commands (both text and math) for each character.
    
    Only the first one is returned by default with existing methods to guarantee compatibility with existing code.
---
 src/BufferEncodings.cpp |   10 ++--
 src/Encoding.cpp        |  137 +++++++++++++++++++++++++++--------------------
 src/Encoding.h          |   62 ++++++++++++---------
 src/Paragraph.cpp       |    4 +-
 4 files changed, 121 insertions(+), 92 deletions(-)

diff --git a/src/BufferEncodings.cpp b/src/BufferEncodings.cpp
index dcf422d..fe7e90c 100644
--- a/src/BufferEncodings.cpp
+++ b/src/BufferEncodings.cpp
@@ -52,7 +52,7 @@ void BufferEncodings::validate(char_type c, LaTeXFeatures & features, bool for_m
 	CharInfo const & ci = Encodings::unicodeCharInfo(c);
 	if (ci.isUnicodeSymbol()) {
 		// In mathed, c could be used both in textmode and mathmode
-		docstring const textcommand = ci.textcommand();
+		docstring const textcommand = ci.textCommand();
 		bool const math_mode = for_mathed && isMathCmd(c);
 		bool const use_math = math_mode ||
 		                      (!for_mathed && textcommand.empty());
@@ -65,9 +65,9 @@ void BufferEncodings::validate(char_type c, LaTeXFeatures & features, bool for_m
 		// and if we do not use unicode-math
 		if ((math_mode && !unicode_math)
 		     || (use_math && !plain_utf8)) {
-			string const mathpreamble = ci.mathpreamble();
+			string const mathpreamble = ci.mathPreamble();
 			if (!mathpreamble.empty()) {
-				if (ci.mathfeature()) {
+				if (ci.mathFeature()) {
 					string feats = mathpreamble;
 					while (!feats.empty()) {
 						string feat;
@@ -80,9 +80,9 @@ void BufferEncodings::validate(char_type c, LaTeXFeatures & features, bool for_m
 		}
 		// with utf8-plain, we do not load packages (see #7766)
 		if (use_text && !plain_utf8) {
-			string const textpreamble = ci.textpreamble();
+			string const textpreamble = ci.textPreamble();
 			if (!textpreamble.empty()) {
-				if (ci.textfeature()) {
+				if (ci.textFeature()) {
 					string feats = textpreamble;
 					while (!feats.empty()) {
 						string feat;
diff --git a/src/Encoding.cpp b/src/Encoding.cpp
index c7ea237..b0d5649 100644
--- a/src/Encoding.cpp
+++ b/src/Encoding.cpp
@@ -75,12 +75,23 @@ const char * EncodingException::what() const noexcept
 
 
 CharInfo::CharInfo(
-	docstring const & textcommand, docstring const & mathcommand,
-	std::string const & textpreamble, std::string const & mathpreamble,
-	std::string const & tipashortcut, unsigned int flags)
-	: textcommand_(textcommand), mathcommand_(mathcommand),
-	  textpreamble_(textpreamble), mathpreamble_(mathpreamble),
-	  tipashortcut_(tipashortcut), flags_(flags)
+		docstring const & text_command, docstring const & math_command,
+		std::string const & text_preamble, std::string const & math_preamble,
+		std::string const & tipa_shortcut, unsigned int flags)
+	: text_commands_({text_command}), math_commands_({math_command}),
+	  text_preamble_(text_preamble), math_preamble_(math_preamble),
+	  tipa_shortcut_(tipa_shortcut), flags_(flags)
+{
+}
+
+
+CharInfo::CharInfo(
+		std::vector<docstring> const & text_commands, std::vector<docstring> const & math_commands,
+		std::string const & text_preamble, std::string const & math_preamble,
+		std::string const & tipa_shortcut, unsigned int flags)
+	: text_commands_(text_commands), math_commands_(math_commands),
+	  text_preamble_(text_preamble), math_preamble_(math_preamble),
+	  tipa_shortcut_(tipa_shortcut), flags_(flags)
 {
 }
 
@@ -216,11 +227,11 @@ pair<docstring, bool> Encoding::latexChar(char_type c) const
 	CharInfoMap::const_iterator const it = unicodesymbols.find(c);
 	if (it == unicodesymbols.end())
 		throw EncodingException(c);
-	// at least one of mathcommand and textcommand is nonempty
-	if (it->second.textcommand().empty())
+	// at least one of mathCommand and textCommand is nonempty
+	if (it->second.textCommand().empty())
 		return make_pair(
-			"\\ensuremath{" + it->second.mathcommand() + '}', false);
-	return make_pair(it->second.textcommand(), !it->second.textnotermination());
+				"\\ensuremath{" + it->second.mathCommand() + '}', false);
+	return make_pair(it->second.textCommand(), !it->second.textNoTermination());
 }
 
 
@@ -302,17 +313,17 @@ bool Encodings::latexMathChar(char_type c, bool mathmode,
 			addMathSym(c);
 		return false;
 	}
-	// at least one of mathcommand and textcommand is nonempty
-	bool use_math = (mathmode && !it->second.mathcommand().empty()) ||
-			(!mathmode && it->second.textcommand().empty());
+	// at least one of mathCommand and textCommand is nonempty
+	bool use_math = (mathmode && !it->second.mathCommand().empty()) ||
+	                (!mathmode && it->second.textCommand().empty());
 	if (use_math) {
-		command = it->second.mathcommand();
-		needsTermination = !it->second.mathnotermination();
+		command = it->second.mathCommand();
+		needsTermination = !it->second.mathNoTermination();
 		addMathCmd(c);
 	} else {
 		if (!encoding || command.empty()) {
-			command = it->second.textcommand();
-			needsTermination = !it->second.textnotermination();
+			command = it->second.textCommand();
+			needsTermination = !it->second.textNoTermination();
 		}
 		if (mathmode)
 			addMathSym(c);
@@ -331,23 +342,31 @@ char_type Encodings::fromLaTeXCommand(docstring const & cmd, int cmdtype,
 	for (combining = false; it != end; ++it) {
 		if (it->second.deprecated())
 			continue;
-		docstring const math = it->second.mathcommand();
-		docstring const text = it->second.textcommand();
-		if ((cmdtype & MATH_CMD) && math == cmd) {
-			combining = it->second.combining();
-			needsTermination = !it->second.mathnotermination();
-			if (req && it->second.mathfeature() &&
-			    !it->second.mathpreamble().empty())
-				req->insert(it->second.mathpreamble());
-			return it->first;
+
+		if (cmdtype & MATH_CMD) {
+			for (const docstring& math : it->second.mathCommands()) {
+				if ((cmdtype & MATH_CMD) && math == cmd) {
+					combining = it->second.combining();
+					needsTermination = !it->second.mathNoTermination();
+					if (req && it->second.mathFeature() &&
+					    !it->second.mathPreamble().empty())
+						req->insert(it->second.mathPreamble());
+					return it->first;
+				}
+			}
 		}
-		if ((cmdtype & TEXT_CMD) && text == cmd) {
-			combining = it->second.combining();
-			needsTermination = !it->second.textnotermination();
-			if (req && it->second.textfeature() &&
-			    !it->second.textpreamble().empty())
-				req->insert(it->second.textpreamble());
-			return it->first;
+
+		if (cmdtype & TEXT_CMD) {
+			for (const docstring& text : it->second.textCommands()) {
+				if (text == cmd) {
+					combining = it->second.combining();
+					needsTermination = !it->second.textNoTermination();
+					if (req && it->second.textFeature() &&
+					    !it->second.textPreamble().empty())
+						req->insert(it->second.textPreamble());
+					return it->first;
+				}
+			}
 		}
 	}
 	needsTermination = false;
@@ -418,9 +437,9 @@ docstring Encodings::fromLaTeXCommand(docstring const & cmd, int cmdtype,
 		for (; it != uniend; ++it) {
 			if (it->second.deprecated())
 				continue;
-			docstring const math = mathmode ? it->second.mathcommand()
+			docstring const math = mathmode ? it->second.mathCommand()
 							: docstring();
-			docstring const text = textmode ? it->second.textcommand()
+			docstring const text = textmode ? it->second.textCommand()
 							: docstring();
 			if (!combcmd.empty() && it->second.combining() &&
 			    (math == combcmd || text == combcmd))
@@ -496,16 +515,16 @@ docstring Encodings::fromLaTeXCommand(docstring const & cmd, int cmdtype,
 				i = j + 1;
 				unicmd_size = cur_size;
 				if (math == tmp)
-					needsTermination = !it->second.mathnotermination();
+					needsTermination = !it->second.mathNoTermination();
 				else
-					needsTermination = !it->second.textnotermination();
+					needsTermination = !it->second.textNoTermination();
 				if (req) {
-					if (math == tmp && it->second.mathfeature() &&
-					    !it->second.mathpreamble().empty())
-						req->insert(it->second.mathpreamble());
-					if (text == tmp && it->second.textfeature() &&
-					    !it->second.textpreamble().empty())
-						req->insert(it->second.textpreamble());
+					if (math == tmp && it->second.mathFeature() &&
+					    !it->second.mathPreamble().empty())
+						req->insert(it->second.mathPreamble());
+					if (text == tmp && it->second.textFeature() &&
+					    !it->second.textPreamble().empty())
+						req->insert(it->second.textPreamble());
 				}
 			}
 		}
@@ -584,7 +603,7 @@ string const Encodings::TIPAShortcut(char_type c)
 {
 	CharInfoMap::const_iterator const it = unicodesymbols.find(c);
 	if (it != unicodesymbols.end())
-		return it->second.tipashortcut();
+		return it->second.tipaShortcut();
 	return string();
 }
 
@@ -595,11 +614,11 @@ string const Encodings::isKnownScriptChar(char_type const c)
 
 	if (it == unicodesymbols.end())
 		return string();
-	// FIXME: parse complex textpreamble (may be list or alternatives,
+	// FIXME: parse complex textPreamble (may be list or alternatives,
 	// 		  e.g., "subscript,textgreek" or "textcomp|textgreek")
-	if (it->second.textpreamble() == "textgreek"
-		|| it->second.textpreamble() == "textcyrillic")
-		return it->second.textpreamble();
+	if (it->second.textPreamble() == "textgreek"
+		|| it->second.textPreamble() == "textcyrillic")
+		return it->second.textPreamble();
 	return string();
 }
 
@@ -627,7 +646,7 @@ bool Encodings::isUnicodeTextOnly(char_type c)
 		return false;
 
 	CharInfoMap::const_iterator const it = unicodesymbols.find(c);
-	return it == unicodesymbols.end() || it->second.mathcommand().empty();
+	return it == unicodesymbols.end() || it->second.mathCommand().empty();
 }
 
 
@@ -754,7 +773,7 @@ void Encodings::read(FileName const & encfile, FileName const & symbolsfile)
 			} else if (flag == "notermination=none") {
 				flags &= ~CharInfoTextNoTermination;
 				flags &= ~CharInfoMathNoTermination;
-			} else if (contains(flag, "tipashortcut=")) {
+			} else if (contains(flag, "tipaShortcut=")) {
 				tipashortcut = split(flag, '=');
 			} else if (flag == "deprecated") {
 				flags |= CharInfoDeprecated;
@@ -765,7 +784,7 @@ void Encodings::read(FileName const & encfile, FileName const & symbolsfile)
 				       << "'." << endl;
 			}
 		}
-		// mathcommand and mathpreamble have been added for 1.6.0.
+		// mathCommand and mathPreamble have been added for 1.6.0.
 		// make them optional so that old files still work.
 		int const lineno = symbolslex.lineNumber();
 		bool breakout = false;
@@ -773,7 +792,7 @@ void Encodings::read(FileName const & encfile, FileName const & symbolsfile)
 		string mathpreamble;
 		if (symbolslex.next(true)) {
 			if (symbolslex.lineNumber() != lineno) {
-				// line in old format without mathcommand and mathpreamble
+				// line in old format without mathCommand and mathPreamble
 				getNextToken = false;
 			} else {
 				mathcommand = symbolslex.getDocString();
@@ -781,10 +800,10 @@ void Encodings::read(FileName const & encfile, FileName const & symbolsfile)
 					flags |= CharInfoMathNoTermination;
 				if (symbolslex.next(true)) {
 					if (symbolslex.lineNumber() != lineno) {
-						// line in new format with mathcommand only
+						// line in new format with mathCommand only
 						getNextToken = false;
 					} else {
-						// line in new format with mathcommand and mathpreamble
+						// line in new format with mathCommand and mathPreamble
 						mathpreamble = symbolslex.getString();
 					}
 				} else
@@ -810,12 +829,12 @@ void Encodings::read(FileName const & encfile, FileName const & symbolsfile)
 			textpreamble, mathpreamble,
 			tipashortcut, flags);
 		LYXERR(Debug::INFO, "Read unicode symbol " << symbol << " '"
-			   << to_utf8(info.textcommand()) << "' '" << info.textpreamble()
-			   << " '" << info.textfeature() << ' ' << info.textnotermination()
-			   << ' ' << to_utf8(info.mathcommand()) << "' '" << info.mathpreamble()
-			   << "' " << info.mathfeature() << ' ' << info.mathnotermination()
+		                                           << to_utf8(info.textCommand()) << "' '" << info.textPreamble()
+		                                           << " '" << info.textFeature() << ' ' << info.textNoTermination()
+		                                           << ' ' << to_utf8(info.mathCommand()) << "' '" << info.mathPreamble()
+		                                           << "' " << info.mathFeature() << ' ' << info.mathNoTermination()
 			   << ' ' << info.combining() << ' ' << info.force()
-			   << ' ' << info.forceselected());
+			   << ' ' << info.forceSelected());
 
 		// we assume that at least one command is nonempty when using unicodesymbols
 		if (info.isUnicodeSymbol()) {
diff --git a/src/Encoding.h b/src/Encoding.h
index 6a96843..2bfbda0 100644
--- a/src/Encoding.h
+++ b/src/Encoding.h
@@ -62,52 +62,62 @@ class CharInfo {
 public:
 	CharInfo() : flags_(0) {}
 	CharInfo(
-		docstring const & textcommand, docstring const & mathcommand,
-		std::string const & textpreamble, std::string const & mathpreamble,
-		std::string const & tipashortcut, unsigned int flags);
+		docstring const & text_command, docstring const & math_command,
+		std::string const & text_preamble, std::string const & math_preamble,
+		std::string const & tipa_shortcut, unsigned int flags);
+	CharInfo(
+		std::vector<docstring> const & text_commands, std::vector<docstring> const & math_commands,
+		std::string const & text_preamble, std::string const & math_preamble,
+		std::string const & tipa_shortcut, unsigned int flags);
 	// we assume that at least one command is nonempty when using unicodesymbols
-	bool isUnicodeSymbol() const { return !textcommand_.empty() || !mathcommand_.empty(); }
+	bool isUnicodeSymbol() const { return !text_commands_.empty() || !math_commands_.empty(); }
 	/// LaTeX command (text mode) for this character
-	docstring const textcommand() const { return textcommand_; }
+	docstring textCommand() const { return text_commands_[0]; }
+	/// All known LaTeX commands (text mode) for this character
+	std::vector<docstring> textCommands() const { return text_commands_; }
 	/// LaTeX command (math mode) for this character
-	docstring mathcommand() const { return mathcommand_; }
+	docstring mathCommand() const { return math_commands_[0]; }
+	/// All known LaTeX commands (math mode) for this character
+	std::vector<docstring> mathCommands() const { return math_commands_; }
 	/// Needed LaTeX preamble (or feature) for text mode
-	std::string textpreamble() const { return textpreamble_; }
+	std::string textPreamble() const { return text_preamble_; }
 	/// Needed LaTeX preamble (or feature) for math mode
-	std::string mathpreamble() const { return mathpreamble_; }
+	std::string mathPreamble() const { return math_preamble_; }
 	/// Is this a combining character?
 	bool combining() const { return flags_ & CharInfoCombining; }
-	/// Is \c textpreamble a feature known by LaTeXFeatures, or a raw LaTeX
+	/// Is \c textPreamble a feature known by LaTeXFeatures, or a raw LaTeX
 	/// command?
-	bool textfeature() const { return flags_ & CharInfoTextFeature; }
-	/// Is \c mathpreamble a feature known by LaTeXFeatures, or a raw LaTeX
+	bool textFeature() const { return flags_ & CharInfoTextFeature; }
+	/// Is \c mathPreamble a feature known by LaTeXFeatures, or a raw LaTeX
 	/// command?
-	bool mathfeature() const { return flags_ & CharInfoMathFeature; }
+	bool mathFeature() const { return flags_ & CharInfoMathFeature; }
 	/// Always force the LaTeX command, even if the encoding contains
 	/// this character?
 	bool force() const { return flags_ & CharInfoForce; }
 	/// Force the LaTeX command for some encodings?
-	bool forceselected() const { return flags_ & CharInfoForceSelected; }
+	bool forceSelected() const { return flags_ & CharInfoForceSelected; }
 	/// Disable LaTeX command => char_type conversion for this deprecated symbol?
 	bool deprecated() const { return flags_ & CharInfoDeprecated; }
 	/// TIPA shortcut
-	std::string const tipashortcut() const { return tipashortcut_; }
-	/// \c textcommand needs no termination (such as {} or space).
-	bool textnotermination() const { return flags_ & CharInfoTextNoTermination; }
-	/// \c mathcommand needs no termination (such as {} or space).
-	bool mathnotermination() const { return flags_ & CharInfoMathNoTermination; }
+	std::string const tipaShortcut() const { return tipa_shortcut_; }
+	/// \c textCommand needs no termination (such as {} or space).
+	bool textNoTermination() const { return flags_ & CharInfoTextNoTermination; }
+	/// \c mathCommand needs no termination (such as {} or space).
+	bool mathNoTermination() const { return flags_ & CharInfoMathNoTermination; }
 	///
 private:
-	/// LaTeX command (text mode) for this character
-	trivdocstring textcommand_;
-	/// LaTeX command (math mode) for this character
-	trivdocstring mathcommand_;
+	/// LaTeX commands (text mode) for this character. The first one is the default, the others
+	/// are only present for compatibility other ways users may encode the character
+	std::vector<trivdocstring> text_commands_;
+	/// LaTeX command (math mode) for this character. The first one is the default, the others
+	//	/// are only present for compatibility other ways users may encode the character
+	std::vector<trivdocstring> math_commands_;
 	/// Needed LaTeX preamble (or feature) for text mode
-	trivstring textpreamble_;
+	trivstring text_preamble_;
 	/// Needed LaTeX preamble (or feature) for math mode
-	trivstring mathpreamble_;
+	trivstring math_preamble_;
 	/// TIPA shortcut
-	trivstring tipashortcut_;
+	trivstring tipa_shortcut_;
 	/// feature flags
 	unsigned int flags_;
 };
@@ -288,7 +298,7 @@ public:
 	/**
 	 * Do we have to wrap in \text this character when in mathmode?
 	 * This is true if \p c is not ascii and the "mathalpha" flag is not
-	 * set and a mathcommand is not defined in the unicodesymbols file.
+	 * set and a mathCommand is not defined in the unicodesymbols file.
 	 */
 	static bool isUnicodeTextOnly(char_type c);
 	/**
diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp
index 48b8519..3a4c399 100644
--- a/src/Paragraph.cpp
+++ b/src/Paragraph.cpp
@@ -1535,9 +1535,9 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const
 			else if (features.runparams().main_fontenc != "T1"
 				 || ((&owner_->getFontSettings(bp, i))->language()->internalFontEncoding()))
 				features.require("textquotedbl");
-		} else if (ci.textfeature() && contains(ci.textpreamble(), '=')) {
+		} else if (ci.textFeature() && contains(ci.textPreamble(), '=')) {
 			// features that depend on the font or input encoding
-			string feats = ci.textpreamble();
+			string feats = ci.textPreamble();
 			string fontenc = (&owner_->getFontSettings(bp, i))->language()->fontenc(bp);
 			if (fontenc.empty())
 				fontenc = features.runparams().main_fontenc;


More information about the lyx-cvs mailing list