]> git.lyx.org Git - features.git/commitdiff
Fix ticket #9224: text overflows through adjacent insets
authorJean-Marc Lasgouttes <lasgouttes@lyx.org>
Wed, 15 Oct 2014 15:34:56 +0000 (17:34 +0200)
committerJean-Marc Lasgouttes <lasgouttes@lyx.org>
Thu, 16 Oct 2014 12:53:54 +0000 (14:53 +0200)
The logic of Row::shortenIfNeeded is completely changed to look at the row from the start and not the end. This leads to clearer code.

src/Row.cpp
src/TextMetrics.cpp

index aeede91d85e7d0e61371eec64cc2edffc56bab5d..d1f589c9ffdfc1c6e7a730c070377751a40d847a 100644 (file)
@@ -362,37 +362,50 @@ void Row::shortenIfNeeded(pos_type const keep, int const w)
        if (empty() || width() <= w)
                return;
 
-       /** First, we try to remove elements one by one from the end
-        * until a separator is found. cit points to the first element
-        * we want to remove from the row.
-        */
        Elements::iterator const beg = elements_.begin();
        Elements::iterator const end = elements_.end();
-       Elements::iterator cit = end;
-       Elements::iterator first_below = end;
-       int new_end = end_;
-       int new_wid = dim_.wid;
-       // if the row ends with a separator, skip it.
-       if (cit != beg && boost::prior(cit)->type == SEPARATOR && new_end > keep) {
-               --cit;
-               new_end = cit->pos;
-               new_wid -= cit->dim.wid;
+       Elements::iterator last_sep = elements_.end();
+       double last_width = 0;
+       double wid = x;
+
+       Elements::iterator cit = beg;
+       for ( ; cit != end ; ++cit) {
+               if (cit->type == SEPARATOR && cit->pos >= keep) {
+                       last_sep = cit;
+                       last_width = wid;
+               }
+               if (wid + cit->width() > w)
+                       break;
+               wid += cit->width();
        }
 
-       // Search for a separator where the row can be broken.
-       while (cit != beg && boost::prior(cit)->type != SEPARATOR && new_end > keep) {
+       if (last_sep != end) {
+               // We have found a suitable separator. This is the
+               // common case.
+               end_ = last_sep->endpos;
+               dim_.wid = last_width;
+               elements_.erase(last_sep, end);
+               return;
+       }
+
+       if (cit == end) {
+               // This should not happen since the row is too long.
+               LYXERR0("Something is wrong cannot shorten row: " << *this);
+               return;
+       }
+
+       if (cit != beg && cit->type == VIRTUAL) {
+               // It is not possible to separate a virtual element from the
+               // previous one.
                --cit;
-               new_end = cit->pos;
-               new_wid -= cit->dim.wid;
-               if (new_wid < w && first_below == end)
-                       first_below = cit;
+               wid -= cit->width();
        }
 
        if (cit != beg) {
-               // We have found a suitable separator. This is the
-               // common case.
-               end_ = new_end;
-               dim_.wid = new_wid;
+               // There is no separator, but several elements (probably
+               // insets) have been added. We can cut at this place.
+               end_ = cit->pos;
+               dim_.wid = wid;
                elements_.erase(cit, end);
                return;
        }
@@ -402,17 +415,11 @@ void Row::shortenIfNeeded(pos_type const keep, int const w)
         * something: when we have one big string, maybe with some
         * other things after it.
         */
-       double max_w = w - x;
-       if (first_below->breakAt(max_w)) {
-               end_ = first_below->endpos;
-               dim_.wid = int(x + first_below->width());
+       if (cit->breakAt(w - x)) {
+               end_ = cit->endpos;
+               dim_.wid = int(x + cit->width());
                // If there are other elements, they should be removed.
-               elements_.erase(boost::next(first_below), end);
-       } else if (first_below->pos > pos_) {
-               end_ = first_below->pos;
-               dim_.wid = new_wid;
-               // Remove all elements from first_below.
-               elements_.erase(first_below, end);
+               elements_.erase(boost::next(cit), end);
        }
 }
 
index c99517c5176eaad2439bf768be8e7426d0b725ce..637ce1f4534648cd97c62aafb780cd67f5660ce3 100644 (file)
@@ -802,7 +802,9 @@ void TextMetrics::breakRow(Row & row, int const right_margin, pit_type const pit
        int const width = max_width_ - right_margin;
        pos_type const body_pos = par.beginOfBody();
        row.clear();
-       row.dimension().wid = leftMargin(max_width_, pit, pos);
+       // This make get changed in computeRowMetrics depending on RTL
+       row.x = leftMargin(max_width_, pit, pos);
+       row.dimension().wid = row.x;
        row.right_margin = right_margin;
 
        if (pos >= end || row.width() > width) {