[LyX/master] Fix crash with countExpanders in Qt6

Jean-Marc Lasgouttes lasgouttes at lyx.org
Fri Apr 8 13:45:26 UTC 2022


commit 7cb700bf675ca255f3fcbe2fa07d04f0d359ed7b
Author: Jean-Marc Lasgouttes <lasgouttes at lyx.org>
Date:   Fri Apr 8 11:51:53 2022 +0200

    Fix crash with countExpanders in Qt6
    
    It is not a good idea to contruct a QChar from a char_type that is
    really 32bits.
    
    Use lyx::isSpace, which already catters for this case.
    
    Since this code does not depend on qt anymore, move it to
    support::countExpanders.
    
    Get rid of Row::countSeparators, which is not used anymore.
    
    Fixes bug #12519.
---
 src/Row.cpp                         |   20 +-------------------
 src/Row.h                           |    5 -----
 src/frontends/FontMetrics.h         |    4 ----
 src/frontends/qt/GuiFontMetrics.cpp |   23 +----------------------
 src/frontends/qt/GuiFontMetrics.h   |    1 -
 src/frontends/qt/GuiPainter.cpp     |    3 ++-
 src/support/lstrings.cpp            |   21 +++++++++++++++++++++
 src/support/lstrings.h              |    5 +++++
 8 files changed, 30 insertions(+), 52 deletions(-)

diff --git a/src/Row.cpp b/src/Row.cpp
index f2d4aaf..3d5ab90 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -42,19 +42,11 @@ using frontend::FontMetrics;
 static double const MAX_SPACE_STRETCH = 1.5; //em
 
 
-int Row::Element::countSeparators() const
-{
-	if (type != STRING)
-		return 0;
-	return count(str.begin(), str.end(), ' ');
-}
-
-
 int Row::Element::countExpanders() const
 {
 	if (type != STRING)
 		return 0;
-	return theFontMetrics(font).countExpanders(str);
+	return support::countExpanders(str);
 }
 
 
@@ -385,16 +377,6 @@ int Row::right_x() const
 }
 
 
-int Row::countSeparators() const
-{
-	int n = 0;
-	const_iterator const end = elements_.end();
-	for (const_iterator cit = elements_.begin() ; cit != end ; ++cit)
-		n += cit->countSeparators();
-	return n;
-}
-
-
 bool Row::setExtraWidth(int w)
 {
 	if (w < 0)
diff --git a/src/Row.h b/src/Row.h
index 4c4bfce..6583fb2 100644
--- a/src/Row.h
+++ b/src/Row.h
@@ -66,9 +66,6 @@ public:
 			: type(t), pos(p), endpos(p + 1), font(f), change(ch) {}
 
 
-		// Return the number of separator in the element (only STRING type)
-		int countSeparators() const;
-
 		// Return total width of element, including separator overhead
 		// FIXME: Cache this value or the number of expanders?
 		double full_width() const { return dim.wid + extra * countExpanders(); }
@@ -238,8 +235,6 @@ public:
 	/// The offset of the right-most cursor position on the row
 	int right_x() const;
 
-	// Return the number of separators in the row
-	int countSeparators() const;
 	// Set the extra spacing for every expanding character in STRING-type
 	// elements.  \param w is the total amount of extra width for the row to be
 	// distributed among expanders.  \return false if the justification fails.
diff --git a/src/frontends/FontMetrics.h b/src/frontends/FontMetrics.h
index 66cd22d..f395270 100644
--- a/src/frontends/FontMetrics.h
+++ b/src/frontends/FontMetrics.h
@@ -168,10 +168,6 @@ public:
 		int & width,
 		int & ascent,
 		int & descent) const = 0;
-
-	/// return the number of expanding characters taken into account for
-	/// increased inter-word spacing during justification
-	virtual int countExpanders(docstring const & str) const = 0;
 };
 
 
diff --git a/src/frontends/qt/GuiFontMetrics.cpp b/src/frontends/qt/GuiFontMetrics.cpp
index e7f61c6..cb9f5af 100644
--- a/src/frontends/qt/GuiFontMetrics.cpp
+++ b/src/frontends/qt/GuiFontMetrics.cpp
@@ -18,10 +18,10 @@
 #include "Dimension.h"
 
 #include "support/convert.h"
+#include "support/debug.h"
 #include "support/lassert.h"
 #include "support/lstrings.h" // for breakString_helper with qt4
 #include "support/lyxlib.h"
-#include "support/debug.h"
 
 #define DISABLE_PMPROF
 #include "support/pmprof.h"
@@ -467,27 +467,6 @@ int GuiFontMetrics::x2pos(docstring const & s, int & x, bool const rtl,
 }
 
 
-int GuiFontMetrics::countExpanders(docstring const & str) const
-{
-	// Numbers of characters that are expanded by inter-word spacing.  These
-	// characters are spaces, except for characters 09-0D which are treated
-	// specially.  (From a combination of testing with the notepad found in qt's
-	// examples, and reading the source code.)  In addition, consecutive spaces
-	// only count as one expander.
-	bool wasspace = false;
-	int nexp = 0;
-	for (char_type c : str)
-		if (c > 0x0d && QChar(c).isSpace()) {
-			if (!wasspace) {
-				++nexp;
-				wasspace = true;
-			}
-		} else
-			wasspace = false;
-	return nexp;
-}
-
-
 namespace {
 
 const int brkStrOffset = 1 + BIDI_OFFSET;
diff --git a/src/frontends/qt/GuiFontMetrics.h b/src/frontends/qt/GuiFontMetrics.h
index 9501eb8..82c5839 100644
--- a/src/frontends/qt/GuiFontMetrics.h
+++ b/src/frontends/qt/GuiFontMetrics.h
@@ -92,7 +92,6 @@ public:
 		int & ascent,
 		int & descent) const override;
 
-	int countExpanders(docstring const & str) const override;
 	///
 	int width(QString const & str) const;
 
diff --git a/src/frontends/qt/GuiPainter.cpp b/src/frontends/qt/GuiPainter.cpp
index cf9cd7c..b243c6e 100644
--- a/src/frontends/qt/GuiPainter.cpp
+++ b/src/frontends/qt/GuiPainter.cpp
@@ -26,6 +26,7 @@
 #include "support/debug.h"
 #include "support/lassert.h"
 #include "support/lyxlib.h"
+#include "support/lstrings.h"
 
 #include <algorithm>
 
@@ -329,7 +330,7 @@ void GuiPainter::text(int x, int y, docstring const & s,
 	if (tw == 0.0)
 		// Take into account space stretching (word spacing)
 		textwidth = fm.width(s) +
-			static_cast<int>(fm.countExpanders(s) * wordspacing);
+			static_cast<int>(countExpanders(s) * wordspacing);
 	else
 		textwidth = static_cast<int>(tw);
 
diff --git a/src/support/lstrings.cpp b/src/support/lstrings.cpp
index 351c977..b9c23f5 100644
--- a/src/support/lstrings.cpp
+++ b/src/support/lstrings.cpp
@@ -1495,6 +1495,27 @@ string from_percent_encoding(string const & in)
 }
 
 
+int countExpanders(docstring const & str)
+{
+	// Numbers of characters that are expanded by inter-word spacing.  These
+	// characters are spaces, except for characters 09-0D which are treated
+	// specially.  (From a combination of testing with the notepad found in qt's
+	// examples, and reading the source code.)  In addition, consecutive spaces
+	// only count as one expander.
+	bool wasspace = false;
+	int nexp = 0;
+	for (char_type c : str)
+		if (c > 0x0d && isSpace(c)) {
+			if (!wasspace) {
+				++nexp;
+				wasspace = true;
+			}
+		} else
+			wasspace = false;
+	return nexp;
+}
+
+
 docstring bformat(docstring const & fmt, int arg1)
 {
 	LATTEST(contains(fmt, from_ascii("%1$d")));
diff --git a/src/support/lstrings.h b/src/support/lstrings.h
index 3d42bb6..390d29c 100644
--- a/src/support/lstrings.h
+++ b/src/support/lstrings.h
@@ -368,6 +368,11 @@ docstring to_percent_encoding(docstring const & in, docstring const & ex = docst
 /// Returns a string decoded from an URI/URL-style percent-encoded string \p in.
 std::string from_percent_encoding(std::string const & in);
 
+/// returns the number of expanding characters taken into account for
+/// increased inter-word spacing during justification
+int countExpanders(docstring const & str);
+
+
 docstring bformat(docstring const & fmt, int arg1);
 docstring bformat(docstring const & fmt, long arg1);
 #ifdef HAVE_LONG_LONG_INT


More information about the lyx-cvs mailing list