commit 6e6976fbc5a61928c51c5193de985e26d94454bd
Author: Jean-Marc Lasgouttes <[email protected]>
Date:   Tue Aug 31 15:58:56 2021 +0200

    Handle the case where breakAt cuts after trailing space
    
    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                         |   18 ++++++++++++++----
 src/TextMetrics.cpp                 |    3 ++-
 src/frontends/qt/GuiFontMetrics.cpp |   10 ++++++++--
 3 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/src/Row.cpp b/src/Row.cpp
index 6e975a5..38dbb85 100644
--- a/src/Row.cpp
+++ b/src/Row.cpp
@@ -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);
                }
        }
 
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index c7e84f6..37894f6 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -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;
                        }
                }
diff --git a/src/frontends/qt/GuiFontMetrics.cpp 
b/src/frontends/qt/GuiFontMetrics.cpp
index 56ed676..47537ae 100644
--- a/src/frontends/qt/GuiFontMetrics.cpp
+++ b/src/frontends/qt/GuiFontMetrics.cpp
@@ -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()
-- 
lyx-cvs mailing list
[email protected]
http://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to