]> git.lyx.org Git - features.git/blobdiff - src/Row.cpp
Implement handling of row_flags for row breaking
[features.git] / src / Row.cpp
index 2f6db3deaf35b22af36753721a29f00d0b74b215..3bc8ef0d519f4462f7df692f68c39825ca8abb76 100644 (file)
@@ -124,53 +124,44 @@ pos_type Row::Element::x2pos(int &x) const
                        x = 0;
                        i = isRTL();
                }
+               break;
+       case INVALID:
+               LYXERR0("x2pos: INVALID row element !");
        }
        //lyxerr << "=> p=" << pos + i << " x=" << x << endl;
        return pos + i;
 }
 
 
-bool Row::Element::breakAt(int w, bool force)
+Row::Element Row::Element::splitAt(int w, bool force)
 {
-       if (type != STRING)
-               return false;
+       if (type != STRING || !(row_flags & CanBreakInside))
+               return Element();
 
        FontMetrics const & fm = theFontMetrics(font);
        dim.wid = w;
        int const i = fm.breakAt(str, dim.wid, isRTL(), force);
        if (i != -1) {
+               Element ret(STRING, pos + i, font, change);
+               ret.str = str.substr(i);
+               ret.endpos = ret.pos + ret.str.length();
+               ret.row_flags = row_flags & (CanBreakInside | AfterFlags);
                str.erase(i);
                endpos = pos + i;
                //lyxerr << "breakAt(" << w << ")  Row element Broken at " << x << "(w(str)=" << fm.width(str) << "): e=" << *this << endl;
+               return ret;
        }
 
-       return i != - 1;
-}
-
-
-pos_type Row::Element::left_pos() const
-{
-       return isRTL() ? endpos : pos;
+       return Element();
 }
 
 
-pos_type Row::Element::right_pos() const
+bool Row::Element::breakAt(int w, bool force)
 {
-       return isRTL() ? pos : endpos;
+       return splitAt(w, force).isValid();
 }
 
 
-Row::Row()
-       : separator(0), label_hfill(0), left_margin(0), right_margin(0),
-         sel_beg(-1), sel_end(-1),
-         begin_margin_sel(false), end_margin_sel(false),
-         changed_(true),
-         pit_(0), pos_(0), end_(0),
-         right_boundary_(false), flushed_(false), rtl_(false),
-         changebar_(false)
-{}
-
-
 bool Row::isMarginSelected(bool left, DocIterator const & beg,
                DocIterator const & end) const
 {
@@ -262,6 +253,9 @@ ostream & operator<<(ostream & os, Row::Element const & e)
        case Row::SPACE:
                os << "SPACE: ";
                break;
+       case Row::INVALID:
+               os << "INVALID: ";
+               break;
        }
        os << "width=" << e.full_width();
        return os;
@@ -376,8 +370,7 @@ void Row::finalizeLast()
        if (elt.change.changed())
                changebar_ = true;
 
-       if (elt.type == STRING) {
-               dim_.wid -= elt.dim.wid;
+       if (elt.type == STRING && elt.dim.wid == 0) {
                elt.dim.wid = theFontMetrics(elt.font).width(elt.str);
                dim_.wid += elt.dim.wid;
        }
@@ -385,12 +378,13 @@ void Row::finalizeLast()
 
 
 void Row::add(pos_type const pos, Inset const * ins, Dimension const & dim,
-             Font const & f, Change const & ch)
+              Font const & f, Change const & ch)
 {
        finalizeLast();
        Element e(INSET, pos, f, ch);
        e.inset = ins;
        e.dim = dim;
+       e.row_flags = ins->rowFlags();
        elements_.push_back(e);
        dim_.wid += dim.wid;
        changebar_ |= ins->isChanged();
@@ -398,23 +392,16 @@ void Row::add(pos_type const pos, Inset const * ins, Dimension const & dim,
 
 
 void Row::add(pos_type const pos, char_type const c,
-             Font const & f, Change const & ch)
+              Font const & f, Change const & ch, bool can_break)
 {
        if (!sameString(f, ch)) {
                finalizeLast();
                Element e(STRING, pos, f, ch);
+               e.row_flags = can_break ? CanBreakInside : Inline;
                elements_.push_back(e);
        }
-       if (back().str.length() % 30 == 0) {
-               dim_.wid -= back().dim.wid;
-               back().str += c;
-               back().endpos = pos + 1;
-               back().dim.wid = theFontMetrics(back().font).width(back().str);
-               dim_.wid += back().dim.wid;
-       } else {
-               back().str += c;
-               back().endpos = pos + 1;
-       }
+       back().str += c;
+       back().endpos = pos + 1;
 }
 
 
@@ -427,6 +414,10 @@ void Row::addVirtual(pos_type const pos, docstring const & s,
        e.dim.wid = theFontMetrics(f).width(s);
        dim_.wid += e.dim.wid;
        e.endpos = pos;
+       // Copy after* flags from previous elements, forbid break before element
+       int const prev_row_flags = elements_.empty() ? Inline : elements_.back().row_flags;
+       int const can_inherit = AfterFlags & ~AlwaysBreakAfter;
+       e.row_flags = (prev_row_flags & can_inherit) | NoBreakBefore;
        elements_.push_back(e);
        finalizeLast();
 }
@@ -443,6 +434,13 @@ void Row::addSpace(pos_type const pos, int const width,
 }
 
 
+void Row::push_back(Row::Element const & e)
+{
+       dim_.wid += e.dim.wid;
+       elements_.push_back(e);
+}
+
+
 void Row::pop_back()
 {
        dim_.wid -= elements_.back().dim.wid;
@@ -450,7 +448,7 @@ void Row::pop_back()
 }
 
 
-bool Row::shortenIfNeeded(pos_type const keep, int const w, int const next_width)
+bool Row::shortenIfNeeded(int const w, int const next_width)
 {
        if (empty() || width() <= w)
                return false;
@@ -482,11 +480,10 @@ bool Row::shortenIfNeeded(pos_type const keep, int const w, int const next_width
                // make a copy of the element to work on it.
                Element brk = *cit_brk;
                /* If the current element is an inset that allows breaking row
-                * after itself, and it the row is already short enough after
+                * after itself, and if the row is already short enough after
                 * this inset, then cut right after this element.
                 */
-               if (wid_brk <= w && brk.type == INSET
-                   && brk.inset->rowFlags() & Inset::CanBreakAfter) {
+               if (wid_brk <= w && brk.row_flags & CanBreakAfter) {
                        end_ = brk.endpos;
                        dim_.wid = wid_brk;
                        elements_.erase(cit_brk + 1, end);
@@ -504,10 +501,6 @@ bool Row::shortenIfNeeded(pos_type const keep, int const w, int const next_width
                 * not allowed at the beginning or end of line.
                */
                bool const word_wrap = brk.font.language()->wordWrap();
-               // When there is text before the body part (think description
-               // environment), do not try to break.
-               if (brk.pos < keep)
-                       continue;
                /* We have found a suitable separable element. This is the common case.
                 * Try to break it cleanly (at word boundary) at a length that is both
                 * - less than the available space on the row