X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FRow.cpp;h=1c17fb299283b7a66df9e7034c096d5b2136c026;hb=d4d4654d6325e92aff96523b64e1d403655a71cc;hp=6b0faa329241fd59162d6fc290100dae467fd801;hpb=d723b90344c0e56b26fc69aa00cb3001e074a723;p=features.git diff --git a/src/Row.cpp b/src/Row.cpp index 6b0faa3292..1c17fb2992 100644 --- a/src/Row.cpp +++ b/src/Row.cpp @@ -42,19 +42,11 @@ using frontend::FontMetrics; static double const MAX_SPACE_STRETCH = 1.5; //em -int Row::Element::countSeparators() const -{ - if (type != STRING) - return 0; - return count(str.begin(), str.end(), ' '); -} - - int Row::Element::countExpanders() const { if (type != STRING) return 0; - return theFontMetrics(font).countExpanders(str); + return support::countExpanders(str); } @@ -114,6 +106,7 @@ pos_type Row::Element::x2pos(int &x) const break; case INSET: case SPACE: + case MARGINSPACE: // those elements contain only one position. Round to // the closest side. if (x > (full_width() + 1) / 2) { @@ -151,7 +144,7 @@ bool Row::Element::splitAt(int const width, int next_width, bool force, isRTL(), wrap_any | force); // if breaking did not really work, give up - if (!force && breaks.front().wid > width) { + if (!force && breaks.front().nspc_wid > width) { if (dim.wid == 0) dim.wid = fm.width(str); return false; @@ -162,10 +155,17 @@ bool Row::Element::splitAt(int const width, int next_width, bool force, bool first = true; docstring::size_type i = 0; for (FontMetrics::Break const & brk : breaks) { + /* For some reason breakString can decide to break before the + * first character (normally we use a 0-width nbsp to prevent + * that). Skip leading empty elements, they are never wanted. + */ + if (first && brk.len == 0 && breaks.size() > 1) + continue; Element e(STRING, pos + i, font, change); e.str = str.substr(i, brk.len); e.endpos = e.pos + brk.len; e.dim.wid = brk.wid; + e.nspc_wid = brk.nspc_wid; e.row_flags = CanBreakInside | BreakAfter; if (first) { // this element eventually goes to *this @@ -212,6 +212,7 @@ void Row::Element::rtrim() */ str = support::rtrim(str); endpos = pos + str.length(); + dim.wid = nspc_wid; } @@ -305,6 +306,9 @@ ostream & operator<<(ostream & os, Row::Element const & e) break; case Row::SPACE: os << "SPACE: "; + break; + case Row::MARGINSPACE: + os << "MARGINSPACE: "; } os << "width=" << e.full_width() << ", row_flags=" << e.row_flags; return os; @@ -332,7 +336,8 @@ ostream & operator<<(ostream & os, Row const & row) << " descent: " << row.dim_.des << " separator: " << row.separator << " label_hfill: " << row.label_hfill - << " row_boundary: " << row.right_boundary() << "\n"; + << " end_boundary: " << row.end_boundary() + << " flushed: " << row.flushed() << "\n"; // We cannot use the operator above, unfortunately double x = row.left_margin; for (Row::Element const & e : row.elements_) { @@ -372,16 +377,6 @@ int Row::right_x() const } -int Row::countSeparators() const -{ - int n = 0; - const_iterator const end = elements_.end(); - for (const_iterator cit = elements_.begin() ; cit != end ; ++cit) - n += cit->countSeparators(); - return n; -} - - bool Row::setExtraWidth(int w) { if (w < 0) @@ -447,12 +442,12 @@ 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, bool can_break) + Font const & f, Change const & ch) { if (!sameString(f, ch)) { finalizeLast(); Element e(STRING, pos, f, ch); - e.row_flags = can_break ? CanBreakInside : Inline; + e.row_flags = CanBreakInside; elements_.push_back(e); } back().str += c; @@ -489,6 +484,18 @@ void Row::addSpace(pos_type const pos, int const width, } +void Row::addMarginSpace(pos_type const pos, int const width, + Font const & f, Change const & ch) +{ + finalizeLast(); + Element e(MARGINSPACE, pos, f, ch); + e.dim.wid = width; + e.row_flags = NoBreakBefore; + elements_.push_back(e); + dim_.wid += e.dim.wid; +} + + void Row::push_back(Row::Element const & e) { dim_.wid += e.dim.wid; @@ -512,7 +519,7 @@ void moveElements(Row::Elements & from, Row::Elements::iterator const & it, to.insert(to.end(), it, from.end()); from.erase(it, from.end()); if (!from.empty()) - from.back().row_flags = (from.back().row_flags & ~AfterFlags) | BreakAfter; + from.back().row_flags = (from.back().row_flags & ~AfterFlags) | AlwaysBreakAfter; } } @@ -555,7 +562,7 @@ Row::Elements Row::shortenIfNeeded(int const w, int const next_width) Element brk = *cit_brk; /* If the current element is an inset that allows breaking row * after itself, and if the row is already short enough after - * this inset, then cut right after this element. + * this element, then cut right after it. */ if (wid_brk <= w && brk.row_flags & CanBreakAfter) { end_ = brk.endpos; @@ -565,6 +572,16 @@ Row::Elements Row::shortenIfNeeded(int const w, int const next_width) } // assume now that the current element is not there wid_brk -= brk.dim.wid; + /* If the current element is an inset that allows breaking row + * before itself, and if the row is already short enough before + * this element, then cut right before it. + */ + if (wid_brk <= w && brk.row_flags & CanBreakBefore && cit_brk != beg) { + end_ = (cit_brk -1)->endpos; + dim_.wid = wid_brk; + moveElements(elements_, cit_brk, tail); + return tail; + } /* We have found a suitable separable element. This is the common case. * Try to break it cleanly at a length that is both * - less than the available space on the row @@ -579,6 +596,7 @@ Row::Elements Row::shortenIfNeeded(int const w, int const next_width) */ if (wid_brk + cit_brk->dim.wid < w && dim_.wid - (wid_brk + brk.dim.wid) >= next_width) { + tail.clear(); break; } end_ = brk.endpos; @@ -612,7 +630,6 @@ Row::Elements Row::shortenIfNeeded(int const w, int const next_width) * splitting this time. */ if (cit->splitAt(w - wid, next_width, true, tail)) { - LYXERR0(*cit); end_ = cit->endpos; dim_.wid = wid + cit->dim.wid; // If there are other elements, they should be removed. @@ -620,11 +637,13 @@ Row::Elements Row::shortenIfNeeded(int const w, int const next_width) return tail; } - return Elements(); + // cit == beg; remove all elements after the first one. + moveElements(elements_, cit + 1, tail); + return tail; } -void Row::reverseRTL(bool const rtl_par) +void Row::reverseRTL() { pos_type i = 0; pos_type const end = elements_.size(); @@ -636,14 +655,13 @@ void Row::reverseRTL(bool const rtl_par) ++j; // if the direction is not the same as the paragraph // direction, the sequence has to be reverted. - if (rtl != rtl_par) + if (rtl != rtl_) reverse(elements_.begin() + i, elements_.begin() + j); i = j; } // If the paragraph itself is RTL, reverse everything - if (rtl_par) + if (rtl_) reverse(elements_.begin(), elements_.end()); - rtl_ = rtl_par; } Row::const_iterator const