X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FTextMetrics.cpp;h=6e22bf7852cb692a7a28309145b0da6bf0530bc2;hb=823e44822e6638824900eee2f7e2e7165af97f8d;hp=a85073c5ac34c39656b12829511c257345d3f8e4;hpb=a942cf9e86136857008930d10bcfa632164bc4cd;p=lyx.git diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp index a85073c5ac..6e22bf7852 100644 --- a/src/TextMetrics.cpp +++ b/src/TextMetrics.cpp @@ -4,12 +4,12 @@ * Licence details can be found in the file COPYING. * * \author Asger Alstrup - * \author Lars Gullik Bjønnes + * \author Lars Gullik Bjønnes * \author Jean-Marc Lasgouttes * \author John Levon - * \author André Pönitz + * \author André Pönitz * \author Dekel Tsur - * \author Jürgen Vigna + * \author Jürgen Vigna * \author Abdelrazak Younes * * Full author contact details are available in file CREDITS. @@ -321,15 +321,9 @@ bool TextMetrics::isRTLBoundary(pit_type pit, pos_type pos) const if (pos == 0) return false; - Paragraph const & par = text_->getPar(pit); + Font const & left_font = displayFont(pit, pos - 1); - bool left = displayFont(pit, pos - 1).isVisibleRightToLeft(); - bool right; - if (pos == par.size()) - right = par.isRTL(bv_->buffer().params()); - else - right = displayFont(pit, pos).isVisibleRightToLeft(); - return left != right; + return isRTLBoundary(pit, pos, left_font); } @@ -390,7 +384,7 @@ bool TextMetrics::redoParagraph(pit_type const pit) LYXERR(Debug::INFO, "MacroContext not initialised!" << " Going through the buffer again and hope" << " the context is better then."); - updateLabels(bv_->buffer()); + bv_->buffer().updateLabels(); parPos = text_->macrocontextPosition(); LASSERT(!parPos.empty(), /**/); parPos.pit() = pit; @@ -425,8 +419,10 @@ bool TextMetrics::redoParagraph(pit_type const pit) MetricsInfo mi(bv_, font.fontInfo(), w, mc); ii->inset->metrics(mi, dim); Dimension const old_dim = pm.insetDimension(ii->inset); - pm.setInsetDimension(ii->inset, dim); - changed |= (old_dim != dim); + if (old_dim != dim) { + pm.setInsetDimension(ii->inset, dim); + changed = true; + } } par.setBeginOfBody(); @@ -551,19 +547,18 @@ void TextMetrics::computeRowMetrics(pit_type const pit, align = par.params().align(); // handle alignment inside tabular cells - if (Inset const * owner = par.inInset()) { - switch (owner->contentAlignment()) { - case LYX_ALIGN_CENTER: - case LYX_ALIGN_LEFT: - case LYX_ALIGN_RIGHT: - if (align == LYX_ALIGN_NONE - || align == LYX_ALIGN_BLOCK) - align = owner->contentAlignment(); - break; - default: - // unchanged (use align) - break; - } + Inset const & owner = par.inInset(); + switch (owner.contentAlignment()) { + case LYX_ALIGN_CENTER: + case LYX_ALIGN_LEFT: + case LYX_ALIGN_RIGHT: + if (align == LYX_ALIGN_NONE + || align == LYX_ALIGN_BLOCK) + align = owner.contentAlignment(); + break; + default: + // unchanged (use align) + break; } // Display-style insets should always be on a centred row @@ -990,8 +985,8 @@ Dimension TextMetrics::rowHeight(pit_type const pit, pos_type const first, InsetList::const_iterator ii = par.insetList().begin(); InsetList::const_iterator iend = par.insetList().end(); for ( ; ii != iend; ++ii) { - Dimension const & dim = pm.insetDimension(ii->inset); if (ii->pos >= first && ii->pos < end) { + Dimension const & dim = pm.insetDimension(ii->inset); maxasc = max(maxasc, dim.ascent()); maxdesc = max(maxdesc, dim.descent()); } @@ -1316,7 +1311,8 @@ void TextMetrics::newParMetricsUp() // y is screen coordinate pit_type TextMetrics::getPitNearY(int y) { - LASSERT(!text_->paragraphs().empty(), /**/); + LASSERT(!text_->paragraphs().empty(), return -1); + LASSERT(!par_metrics_.empty(), return -1); LYXERR(Debug::DEBUG, "y: " << y << " cache size: " << par_metrics_.size()); // look for highest numbered paragraph with y coordinate less than given y @@ -1399,7 +1395,7 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y) cur.bv().coordCache().dump(); } pit_type pit = getPitNearY(y); - LASSERT(pit != -1, /**/); + LASSERT(pit != -1, return 0); Row const & row = getRowNearY(y, pit); bool bound = false; @@ -1453,6 +1449,7 @@ void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const { LASSERT(text_ == cur.text(), /**/); pit_type pit = getPitNearY(y); + LASSERT(pit != -1, return); ParagraphMetrics const & pm = par_metrics_[pit]; @@ -1489,7 +1486,7 @@ void TextMetrics::setCursorFromCoordinates(Cursor & cur, int const x, int const Inset * TextMetrics::checkInsetHit(int x, int y) { pit_type pit = getPitNearY(y); - LASSERT(pit != -1, /**/); + LASSERT(pit != -1, return 0); Paragraph const & par = text_->paragraphs()[pit]; ParagraphMetrics const & pm = par_metrics_[pit]; @@ -1732,7 +1729,7 @@ void TextMetrics::deleteLineForward(Cursor & cur) text_->cursorForward(cur); } else { cur.resetAnchor(); - cur.selection() = true; // to avoid deletion + cur.setSelection(true); // to avoid deletion cursorEnd(cur); cur.setSelection(); // What is this test for ??? (JMarc) @@ -1853,11 +1850,11 @@ int TextMetrics::leftMargin(int max_width, case MARGIN_FIRST_DYNAMIC: if (layout.labeltype == LABEL_MANUAL) { - if (pos >= par.beginOfBody()) { + // if we are at position 0, we are never in the body + if (pos > 0 && pos >= par.beginOfBody()) l_margin += labelfont_metrics.signedWidth(layout.leftmargin); - } else { + else l_margin += labelfont_metrics.signedWidth(layout.labelindent); - } } else if (pos != 0 // Special case to fix problems with // theorems (JMarc) @@ -1916,7 +1913,7 @@ int TextMetrics::leftMargin(int max_width, && align == LYX_ALIGN_BLOCK && !par.params().noindent() // in some insets, paragraphs are never indented - && !(par.inInset() && par.inInset()->neverIndent()) + && !par.inInset().neverIndent() // display style insets are always centered, omit indentation && !(!par.empty() && par.isInset(pos) @@ -1987,15 +1984,19 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co && cur.anchor().text() == text_ && pit >= sel_beg.pit() && pit <= sel_end.pit(); + // We store the begin and end pos of the selection relative to this par + DocIterator sel_beg_par = cur.selectionBegin(); + DocIterator sel_end_par = cur.selectionEnd(); + // We care only about visible selection. if (selection) { if (pit != sel_beg.pit()) { - sel_beg.pit() = pit; - sel_beg.pos() = 0; + sel_beg_par.pit() = pit; + sel_beg_par.pos() = 0; } if (pit != sel_end.pit()) { - sel_end.pit() = pit; - sel_end.pos() = sel_end.lastpos(); + sel_end_par.pit() = pit; + sel_end_par.pos() = sel_end_par.lastpos(); } } @@ -2012,9 +2013,18 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co RowPainter rp(pi, *text_, pit, row, bidi, x, y); if (selection) - row.setSelection(sel_beg.pos(), sel_end.pos()); + row.setSelectionAndMargins(sel_beg_par, sel_end_par); else row.setSelection(-1, -1); + + // The row knows nothing about the paragraph, so we have to check + // whether this row is the first or last and update the margins. + if (row.selection()) { + if (row.sel_beg == 0) + row.begin_margin_sel = sel_beg.pit() < pit; + if (row.sel_end == sel_end_par.lastpos()) + row.end_margin_sel = sel_end.pit() > pit; + } // Row signature; has row changed since last paint? row.setCrc(pm.computeRowSignature(row, bparams)); @@ -2036,34 +2046,18 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co pi.pain.fillRectangle(x, y - row.ascent(), width(), row.height(), pi.background_color); } - - bool row_selection = row.sel_beg != -1 && row.sel_end != -1; - if (row_selection) { - DocIterator beg = bv_->cursor().selectionBegin(); - DocIterator end = bv_->cursor().selectionEnd(); - // FIXME (not here): pit is not updated when extending - // a selection to a new row with cursor right/left - bool const beg_margin = beg.pit() < pit; - bool const end_margin = end.pit() > pit; - beg.pit() = pit; - beg.pos() = row.sel_beg; - end.pit() = pit; - end.pos() = row.sel_end; - if (end.pos() == row.endpos()) { - // selection goes till the end of the row. - end.boundary(true); - } - drawRowSelection(pi, x, row, beg, end, beg_margin, end_margin); - } + + if (row.selection()) + drawRowSelection(pi, x, row, cur, pit); // Instrumentation for testing row cache (see also // 12 lines lower): if (lyxerr.debugging(Debug::PAINTING) && inside - && (row_selection || pi.full_repaint || row_has_changed)) { + && (row.selection() || pi.full_repaint || row_has_changed)) { string const foreword = text_->isMainText(bv_->buffer()) ? "main text redraw " : "inset text redraw: "; LYXERR(Debug::PAINTING, foreword << "pit=" << pit << " row=" << i - << " row_selection=" << row_selection + << " row_selection=" << row.selection() << " full_repaint=" << pi.full_repaint << " row_has_changed=" << row_has_changed); } @@ -2092,34 +2086,48 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type pit, int x, int y) co void TextMetrics::drawRowSelection(PainterInfo & pi, int x, Row const & row, - DocIterator const & beg, DocIterator const & end, - bool drawOnBegMargin, bool drawOnEndMargin) const + Cursor const & curs, pit_type pit) const { + DocIterator beg = curs.selectionBegin(); + beg.pit() = pit; + beg.pos() = row.sel_beg; + + DocIterator end = curs.selectionEnd(); + end.pit() = pit; + end.pos() = row.sel_end; + + bool const begin_boundary = beg.pos() >= row.endpos(); + bool const end_boundary = row.sel_end == row.endpos(); + Buffer & buffer = bv_->buffer(); DocIterator cur = beg; - int x1 = cursorX(beg.top(), beg.boundary()); - int x2 = cursorX(end.top(), end.boundary()); - int y1 = bv_->getPos(cur, cur.boundary()).y_ - row.ascent(); - int y2 = y1 + row.height(); + cur.boundary(begin_boundary); + int x1 = cursorX(beg.top(), begin_boundary); + int x2 = cursorX(end.top(), end_boundary); + int const y1 = bv_->getPos(cur, cur.boundary()).y_ - row.ascent(); + int const y2 = y1 + row.height(); + + int const rm = text_->isMainText(buffer) ? bv_->rightMargin() : 0; + int const lm = text_->isMainText(buffer) ? bv_->leftMargin() : 0; // draw the margins - if (drawOnBegMargin) { + if (row.begin_margin_sel) { if (text_->isRTL(buffer, beg.paragraph())) { - int lm = bv_->leftMargin(); - pi.pain.fillRectangle(x + x1, y1, width() - lm - x1, y2 - y1, Color_selection); + pi.pain.fillRectangle(x + x1, y1, width() - rm - x1, y2 - y1, + Color_selection); } else { - int rm = bv_->rightMargin(); - pi.pain.fillRectangle(rm, y1, x1 - rm, y2 - y1, Color_selection); + pi.pain.fillRectangle(x + lm, y1, x1 - lm, y2 - y1, + Color_selection); } } - if (drawOnEndMargin) { + if (row.end_margin_sel) { if (text_->isRTL(buffer, beg.paragraph())) { - int rm = bv_->rightMargin(); - pi.pain.fillRectangle(x + rm, y1, x2 - rm, y2 - y1, Color_selection); + pi.pain.fillRectangle(x + lm, y1, x2 - lm, y2 - y1, + Color_selection); } else { - int lm = bv_->leftMargin(); - pi.pain.fillRectangle(x + x2, y1, width() - lm - x2, y2 - y1, Color_selection); + pi.pain.fillRectangle(x + x2, y1, width() - rm - x2, y2 - y1, + Color_selection); } } @@ -2137,13 +2145,13 @@ void TextMetrics::drawRowSelection(PainterInfo & pi, int x, Row const & row, // descend into insets and which does not go into the // next line. Compare the logic with the original cursorForward - // if left of boundary -> just jump to right side - // but for RTL boundaries don't, because: abc|DDEEFFghi -> abcDDEEF|Fghi + // if left of boundary -> just jump to right side, but + // for RTL boundaries don't, because: abc|DDEEFFghi -> abcDDEEF|Fghi if (cur.boundary()) { cur.boundary(false); } else if (isRTLBoundary(cur.pit(), cur.pos() + 1)) { - // in front of RTL boundary -> Stay on this side of the boundary because: - // ab|cDDEEFFghi -> abc|DDEEFFghi + // in front of RTL boundary -> Stay on this side of the boundary + // because: ab|cDDEEFFghi -> abc|DDEEFFghi ++cur.pos(); cur.boundary(true); drawNow = true;