X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FTextMetrics.cpp;h=3dd052059b44e39d86c07b5eaba743f2631ed59e;hb=2a0e4c199c4f18d80ec5a2ab452f3cf18eafc56c;hp=3f6457e49c3a9ec457e806b3533cde2019c274b7;hpb=000832f9d967cba9901db5f74bea7eaf1b49e31b;p=lyx.git diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index 3f6457e49c..3dd052059b 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -482,11 +482,11 @@ bool TextMetrics::redoParagraph(pit_type const pit) if (text_->isMainText()) { if (pit == 0) { pm.rows().front().dimension().asc += 20; - /* coverity[copy_paste_error]: coverity thinks that we - * should update pm.dim().asc below, but all the rows - * heights are actually counted as part of the paragraph metric - * descent see loop above). + /* coverity thinks that we should update pm.dim().asc + * below, but all the rows heights are actually counted as + * part of the paragraph metric descent see loop above). */ + // coverity[copy_paste_error] pm.dim().des += 20; } ParagraphList const & pars = text_->paragraphs(); @@ -561,10 +561,9 @@ LyXAlignment TextMetrics::getAlign(Paragraph const & par, Row const & row) const // not justify stuff, then don't stretch. // A forced block alignment can only be overridden the 'no // justification on screen' setting. - if (((row.right_boundary() || row.endpos() == par.size()) - && !forced_block) + if ((row.flushed() && !forced_block) || !bv_->buffer().params().justification) - align = text_->isRTL(par) ? LYX_ALIGN_RIGHT : LYX_ALIGN_LEFT; + align = row.isRTL() ? LYX_ALIGN_RIGHT : LYX_ALIGN_LEFT; } return align; @@ -621,7 +620,7 @@ void TextMetrics::computeRowMetrics(Row & row, int width) const switch (getAlign(par, row)) { case LYX_ALIGN_BLOCK: // Expand expanding characters by a total of w - if (!row.setExtraWidth(w) && text_->isRTL(par)) { + if (!row.setExtraWidth(w) && row.isRTL()) { // Justification failed and the text is RTL: align to the right row.left_margin += w; row.dimension().wid += w; @@ -911,7 +910,7 @@ bool TextMetrics::breakRow(Row & row, int const right_margin) const && inset->display()) || (!row.empty() && row.back().inset && row.back().inset->display())) { - row.right_boundary(true); + row.flushed(true); need_new_row = par.isNewline(i); ++i; break; @@ -941,8 +940,15 @@ bool TextMetrics::breakRow(Row & row, int const right_margin) const // if the row is too large, try to cut at last separator. In case // of success, reset indication that the row was broken abruptly. - if (row.shortenIfNeeded(body_pos, width)) - row.right_boundary(!row.empty() && row.back().endpos == row.endpos()); + int const next_width = max_width_ - leftMargin(max_width_, row.pit(), row.endpos()) + - rightMargin(row.pit()); + + row.shortenIfNeeded(body_pos, width, next_width); + row.right_boundary(!row.empty() && row.endpos() < end + && row.back().endpos == row.endpos()); + // Last row in paragraph is flushed + if (row.endpos() == end) + row.flushed(true); // make sure that the RTL elements are in reverse ordering row.reverseRTL(is_rtl); @@ -1088,7 +1094,7 @@ void TextMetrics::setRowHeight(Row & row) const // returns the column near the specified x-coordinate of the row // x is set to the real beginning of this column pos_type TextMetrics::getPosNearX(Row const & row, int & x, - bool & boundary) const + bool & boundary, bool const select) const { //LYXERR0("getPosNearX(" << x << ") row=" << row); /// For the main Text, it is possible that this pit is not @@ -1118,7 +1124,7 @@ pos_type TextMetrics::getPosNearX(Row const & row, int & x, for ( ; cit != cend; ++cit) { if (w <= x && w + cit->full_width() > x) { int x_offset = int(x - w); - pos = cit->x2pos(x_offset); + pos = cit->x2pos(x_offset, select); x = int(x_offset + w); break; } @@ -1355,18 +1361,23 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y, if (edited == inset && cur.pos() == it->pos) { // non-editable inset, set cursor after the inset if x is // nearer to that position (bug 9628) + // TODO: This should be replaced with an improvement of + // Cursor::moveToClosestEdge that handles rtl text. (Which could not + // be tested because of #10569.) CoordCache::Insets const & insetCache = bv_->coordCache().getInsets(); - Dimension const & dim = insetCache.dim(inset); - Point p = insetCache.xy(inset); - bool const is_rtl = text_->isRTL(text_->getPar(pit)); - if (is_rtl) { - // "in front of" == "right of" - if (abs(p.x_ - x) < abs(p.x_ + dim.wid - x)) - cur.posForward(); - } else { - // "in front of" == "left of" - if (abs(p.x_ + dim.wid - x) < abs(p.x_ - x)) - cur.posForward(); + if (insetCache.has(inset)) { + Dimension const & dim = insetCache.dim(inset); + Point p = insetCache.xy(inset); + bool const is_rtl = text_->isRTL(text_->getPar(pit)); + if (is_rtl) { + // "in front of" == "right of" + if (abs(p.x_ - x) < abs(p.x_ + dim.wid - x)) + cur.posForward(); + } else { + // "in front of" == "left of" + if (abs(p.x_ + dim.wid - x) < abs(p.x_ - x)) + cur.posForward(); + } } } @@ -1376,7 +1387,8 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y, } -void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const y) +void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, + int const y, bool const select) { LASSERT(text_ == cur.text(), return); pit_type const pit = getPitNearY(y); @@ -1403,7 +1415,7 @@ void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const bool bound = false; int xx = x; - pos_type const pos = getPosNearX(row, xx, bound); + pos_type const pos = getPosNearX(row, xx, bound, select); LYXERR(Debug::DEBUG, "setting cursor pit: " << pit << " pos: " << pos); @@ -1421,28 +1433,12 @@ InsetList::InsetTable * TextMetrics::checkInsetHit(pit_type pit, int x, int y) LYXERR(Debug::DEBUG, "x: " << x << " y: " << y << " pit: " << pit); - InsetList::const_iterator iit = par.insetList().begin(); - InsetList::const_iterator iend = par.insetList().end(); - for (; iit != iend; ++iit) { - Inset * inset = iit->inset; - - LYXERR(Debug::DEBUG, "examining inset " << inset); + for (auto const & it : par.insetList()) { + LYXERR(Debug::DEBUG, "examining inset " << it.inset); - if (!insetCache.has(inset)) { - LYXERR(Debug::DEBUG, "inset has no cached position"); - return 0; - } - - Dimension const & dim = insetCache.dim(inset); - Point p = insetCache.xy(inset); - - LYXERR(Debug::DEBUG, "xo: " << p.x_ << "..." << p.x_ + dim.wid - << " yo: " << p.y_ - dim.asc << "..." << p.y_ + dim.des); - - if (x >= p.x_ && x <= p.x_ + dim.wid - && y >= p.y_ - dim.asc && y <= p.y_ + dim.des) { - LYXERR(Debug::DEBUG, "Hit inset: " << inset); - return const_cast(&(*iit)); + if (insetCache.covers(it.inset, x, y)) { + LYXERR(Debug::DEBUG, "Hit inset: " << it.inset); + return const_cast(&it); } } @@ -1465,56 +1461,6 @@ Inset * TextMetrics::checkInsetHit(int x, int y) } -Row::const_iterator const -TextMetrics::findRowElement(Row const & row, pos_type const pos, - bool const boundary, double & x) const -{ - /** - * When boundary is true, position i is in the row element (pos, endpos) - * if - * pos < i <= endpos - * whereas, when boundary is false, the test is - * pos <= i < endpos - * The correction below allows to handle both cases. - */ - int const boundary_corr = (boundary && pos) ? -1 : 0; - - x = row.left_margin; - - /** Early return in trivial cases - * 1) the row is empty - * 2) the position is the left-most position of the row; there - * is a quirk here however: if the first element is virtual - * (end-of-par marker for example), then we have to look - * closer - */ - if (row.empty() - || (pos == row.begin()->left_pos() && !boundary - && !row.begin()->isVirtual())) - return row.begin(); - - Row::const_iterator cit = row.begin(); - for ( ; cit != row.end() ; ++cit) { - /** Look whether the cursor is inside the element's - * span. Note that it is necessary to take the - * boundary into account, and to accept virtual - * elements, which have pos == endpos. - */ - if (pos + boundary_corr >= cit->pos - && (pos + boundary_corr < cit->endpos || cit->isVirtual())) { - x += cit->pos2x(pos); - break; - } - x += cit->full_width(); - } - - if (cit == row.end()) - --cit; - - return cit; -} - - int TextMetrics::cursorX(CursorSlice const & sl, bool boundary) const { @@ -1527,7 +1473,7 @@ int TextMetrics::cursorX(CursorSlice const & sl, pos_type const pos = sl.pos(); double x = 0; - findRowElement(row, pos, boundary, x); + row.findElement(pos, boundary, x); return int(x); } @@ -1982,15 +1928,14 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const rp.paintAppendix(); rp.paintDepthBar(); rp.paintChangeBar(); - bool const is_rtl = text_->isRTL(text_->getPar(pit)); - if (i == 0 && !is_rtl) + if (i == 0 && !row.isRTL()) rp.paintFirst(); - if (i == nrows - 1 && is_rtl) + if (i == nrows - 1 && row.isRTL()) rp.paintLast(); rp.paintText(); - if (i == nrows - 1 && !is_rtl) + if (i == nrows - 1 && !row.isRTL()) rp.paintLast(); - if (i == 0 && is_rtl) + if (i == 0 && row.isRTL()) rp.paintFirst(); rp.paintTooLargeMarks(row_x + row.left_x() < 0, row_x + row.right_x() > bv_->workWidth());