summaryrefslogtreecommitdiffstats
path: root/src/gui/text
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2024-02-06 13:54:00 -0700
committerShawn Rutledge <shawn.rutledge@qt.io>2024-02-13 21:37:43 -0700
commit908fc2e72b34073dc42ce0f2d6f7cc5adc9651d9 (patch)
treebd984be49776744bab8905b691ff047fa372cf67 /src/gui/text
parentf3e528b97f6836b497953935e1dd27fee134e68a (diff)
QTextMarkdownWriter: Avoid omitting or misplacing ending indicators
If we need to word-wrap a paragraph after a long formatted span, write any ending markers before the newline (amends 280d679c556ab8ead4748a627d7cd4c1950027fb ). Break before a fragment if the whole thing is past the column limit; in that case, write out any ending format markers before the newline. And now we have test coverage: prepend characters one-at-a-time to a line that already has a two-word formatted span at the end, and watch it successively break after the span, in the middle, and then before, while never putting a newline before the ending markers or failing to write them. Fixes: QTBUG-116927 Change-Id: I140e10d19a491cb599bf7ecf8514af866b5383f3 Pick-to: 6.5 6.6 6.7 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/gui/text')
-rw-r--r--src/gui/text/qtextmarkdownwriter.cpp23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp
index 5d6c673179..8cce9df0dd 100644
--- a/src/gui/text/qtextmarkdownwriter.cpp
+++ b/src/gui/text/qtextmarkdownwriter.cpp
@@ -495,6 +495,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
bool italic = false;
bool underline = false;
bool strikeOut = false;
+ bool endingMarkers = false;
QString backticks(qtmw_Backtick);
for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) {
missedBlankCodeBlockLine = false;
@@ -562,19 +563,27 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
if (startsOrEndsWithBacktick)
markers += qtmw_Space;
mono = monoFrag;
+ if (!mono)
+ endingMarkers = true;
}
if (!blockFmt.headingLevel() && !mono) {
if (fontInfo.bold() != bold) {
markers += "**"_L1;
bold = fontInfo.bold();
+ if (!bold)
+ endingMarkers = true;
}
if (fontInfo.italic() != italic) {
markers += u'*';
italic = fontInfo.italic();
+ if (!italic)
+ endingMarkers = true;
}
if (fontInfo.strikeOut() != strikeOut) {
markers += "~~"_L1;
strikeOut = fontInfo.strikeOut();
+ if (!strikeOut)
+ endingMarkers = true;
}
if (fontInfo.underline() != underline) {
// Markdown doesn't support underline, but the parser will treat a single underline
@@ -582,6 +591,8 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
// That will have to do.
markers += u'_';
underline = fontInfo.underline();
+ if (!underline)
+ endingMarkers = true;
}
}
}
@@ -591,7 +602,8 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
bool breakingLine = false;
while (i < fragLen) {
if (col >= ColumnLimit) {
- m_stream << qtmw_Newline << wrapIndentString;
+ m_stream << markers << qtmw_Newline << wrapIndentString;
+ markers.clear();
col = m_wrappedLineIndent;
while (i < fragLen && fragmentText[i].isSpace())
++i;
@@ -601,6 +613,13 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
int wi = nearestWordWrapIndex(fragmentText, j);
if (wi < 0) {
j = fragLen;
+ // can't break within the fragment: we need to break already _before_ it
+ if (endingMarkers) {
+ m_stream << markers;
+ markers.clear();
+ }
+ m_stream << qtmw_Newline << wrapIndentString;
+ col = m_wrappedLineIndent;
} else if (wi >= i) {
j = wi;
breakingLine = true;
@@ -624,7 +643,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
col += subfrag.size();
}
i = j + 1;
- }
+ } // loop over fragment characters (we know we need to break somewhere)
} else {
if (!m_linePrefixWritten && col == wrapIndentString.size()) {
m_stream << m_linePrefix;