]> git.lyx.org Git - features.git/commitdiff
Handle the case where breakAt cuts after trailing space
authorJean-Marc Lasgouttes <lasgouttes@lyx.org>
Tue, 31 Aug 2021 13:58:56 +0000 (15:58 +0200)
committerJean-Marc Lasgouttes <lasgouttes@lyx.org>
Tue, 23 Nov 2021 15:31:30 +0000 (16:31 +0100)
In this case, the extra element returned should empty but valid. The
row flag BreakAfter is set to indicate that we have a break there
(this principle will be used more generally in a forthcoming commit).

To detect that we cut at the trailing space, it is necessary to rely
on the difference between QTextLine::horizontalAdvance() and
QTextLine::naturalTextWidth() when the flag
QTextOption::IncludeTrailingSpaces is used: the trailing space is
taken into account in the later, but not in the former.

Somme comments have been added to make code intent clearer.

src/Row.cpp
src/TextMetrics.cpp
src/frontends/qt/GuiFontMetrics.cpp

index 6e975a5a65cfe06af9a6972d0ab75228b7e1aa5d..38dbb856964321819582d82efae099bc0a13cdef 100644 (file)
@@ -142,13 +142,19 @@ Row::Element Row::Element::splitAt(int w, bool force)
        dim.wid = w;
        int const i = fm.breakAt(str, dim.wid, isRTL(), force);
        if (i != -1) {
+               //Create a second row element to return
                Element ret(STRING, pos + i, font, change);
                ret.str = str.substr(i);
                ret.endpos = ret.pos + ret.str.length();
+               // Copy the after flags of the original element to the second one.
                ret.row_flags = row_flags & (CanBreakInside | AfterFlags);
+
+               // Now update ourselves
                str.erase(i);
                endpos = pos + i;
-               //lyxerr << "breakAt(" << w << ")  Row element Broken at " << x << "(w(str)=" << fm.width(str) << "): e=" << *this << endl;
+               // Row should be broken after the original element
+               row_flags = (row_flags & ~AfterFlags) | BreakAfter;
+               //LYXERR0("breakAt(" << w << ")  Row element Broken at " << w << "(w(str)=" << fm.width(str) << "): e=" << *this);
                return ret;
        }
 
@@ -251,7 +257,7 @@ ostream & operator<<(ostream & os, Row::Element const & e)
                os << "INVALID: ";
                break;
        }
-       os << "width=" << e.full_width();
+       os << "width=" << e.full_width() << ", row_flags=" << e.row_flags;
        return os;
 }
 
@@ -522,7 +528,7 @@ Row::Elements Row::shortenIfNeeded(int const w, int const next_width)
                 *   break-up.
                 */
                Element remainder = brk.splitAt(min(w - wid_brk, brk.dim.wid - 2), !word_wrap);
-               if (remainder.isValid()) {
+               if (brk.row_flags & BreakAfter) {
                        /* if this element originally did not cause a row overflow
                         * in itself, and the remainder of the row would still be
                         * too large after breaking, then we will have issues in
@@ -544,7 +550,11 @@ Row::Elements Row::shortenIfNeeded(int const w, int const next_width)
                        *cit_brk = brk;
                        dim_.wid = wid_brk + brk.dim.wid;
                        // If there are other elements, they should be removed.
-                       return splitFrom(elements_, next(cit_brk, 1), remainder);
+                       // remainder can be empty when splitting at trailing space
+                       if (remainder.str.empty())
+                               return splitFrom(elements_, next(cit_brk, 1));
+                       else
+                               return splitFrom(elements_, next(cit_brk, 1), remainder);
                }
        }
 
index c7e84f614afecd653f9e0a44a62b78e68953f3f5..37894f61dbd2162da358c5e0aa4db453e693560b 100644 (file)
@@ -1157,7 +1157,8 @@ RowList TextMetrics::breakParagraph(Row const & bigrow) const
                        // Add a new next element on the pile
                        if (next_elt.isValid()) {
                                // do as if we inserted this element in the original row
-                               fcit.put(next_elt);
+                               if (!next_elt.str.empty())
+                                       fcit.put(next_elt);
                                need_new_row = true;
                        }
                }
index 56ed67690463614068e9e4b8a6cec09119781905..47537ae0a37f548ee00c660863fbb699465e8c24 100644 (file)
@@ -525,6 +525,9 @@ GuiFontMetrics::breakAt_helper(docstring const & s, int const x,
        QTextOption to;
        to.setWrapMode(force ? QTextOption::WrapAtWordBoundaryOrAnywhere
                             : QTextOption::WordWrap);
+       // Let QTextLine::naturalTextWidth() account for trailing spaces
+       // (horizontalAdvance() still does not).
+       to.setFlags(QTextOption::IncludeTrailingSpaces);
        tl.setTextOption(to);
        tl.beginLayout();
        QTextLine line = tl.createLine();
@@ -557,8 +560,11 @@ GuiFontMetrics::breakAt_helper(docstring const & s, int const x,
                --len;
        LASSERT(len > 0 || qlen == 0, /**/);
 #endif
-       // Do not cut is the string is already short enough
-       if (len == static_cast<int>(s.length())) {
+       // Do not cut is the string is already short enough. We rely on
+       // naturalTextWidth() to catch the case where we cut at the trailing
+       // space.
+       if (len == static_cast<int>(s.length())
+               && line.naturalTextWidth() <= x) {
                len = -1;
 #if QT_VERSION < 0x050000
                // With some monospace fonts, the value of horizontalAdvance()