X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferView.cpp;h=fbfe41c6dbeb465a7135216a6284b4ae5f0fa4be;hb=69f838bbf3e5c1cd0eb1a64dfbf8de469dc10d97;hp=3c7940a049d9065eb1bf9a2f6fd28c71f2700250;hpb=ff7cdf1b74f5c17a966af24dc70d49fc162f007e;p=lyx.git diff --git a/src/BufferView.cpp b/src/BufferView.cpp index 3c7940a049..fbfe41c6db 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -18,7 +18,6 @@ #include "BranchList.h" #include "Buffer.h" -#include "buffer_funcs.h" #include "BufferList.h" #include "BufferParams.h" #include "CoordCache.h" @@ -26,49 +25,34 @@ #include "CutAndPaste.h" #include "DispatchResult.h" #include "ErrorList.h" -#include "factory.h" -#include "FloatList.h" #include "FuncRequest.h" #include "FuncStatus.h" #include "Intl.h" -#include "InsetIterator.h" #include "Language.h" -#include "LaTeXFeatures.h" #include "LayoutFile.h" -#include "Length.h" #include "Lexer.h" #include "LyX.h" #include "LyXAction.h" #include "lyxfind.h" -#include "Layout.h" #include "LyXRC.h" #include "MetricsInfo.h" #include "Paragraph.h" -#include "ParagraphParameters.h" -#include "ParIterator.h" -#include "RowPainter.h" #include "Session.h" #include "Text.h" -#include "TextClass.h" #include "TextMetrics.h" #include "TexRow.h" #include "TocBackend.h" -#include "WordLangTuple.h" #include "insets/InsetBibtex.h" #include "insets/InsetCitation.h" #include "insets/InsetCommand.h" // ChangeRefs -#include "insets/InsetExternal.h" #include "insets/InsetGraphics.h" -#include "insets/InsetNote.h" #include "insets/InsetRef.h" #include "insets/InsetText.h" #include "mathed/MathData.h" -#include "mathed/InsetMathNest.h" #include "frontends/alert.h" -#include "frontends/Application.h" #include "frontends/Delegates.h" #include "frontends/FontMetrics.h" #include "frontends/NullPainter.h" @@ -77,16 +61,18 @@ #include "support/convert.h" #include "support/debug.h" -#include "support/ExceptionMessage.h" +#include "support/docstring.h" #include "support/filetools.h" #include "support/gettext.h" #include "support/lassert.h" +#include "support/Length.h" #include "support/lstrings.h" #include "support/lyxlib.h" -#include "support/Package.h" #include "support/types.h" +#include #include +#include #include #include #include @@ -596,25 +582,29 @@ void BufferView::updateScrollbar() } // Look at paragraph heights on-screen - for (pit_type pit = tm.firstPit(); pit <= tm.lastPit(); ++pit) { + pair first = tm.first(); + pair last = tm.last(); + for (pit_type pit = first.first; pit <= last.first; ++pit) { d->par_height_[pit] = tm.parMetrics(pit).height(); LYXERR(Debug::SCROLLING, "storing height for pit " << pit << " : " << d->par_height_[pit]); } - bool first_visible = tm.firstPit() == 0 && tm.topPosition() >= 0; - bool last_visible = tm.lastPit() + 1 == int(parsize) && tm.bottomPosition() <= height_; + int top_pos = first.second->position() - first.second->ascent(); + int bottom_pos = last.second->position() + last.second->descent(); + bool first_visible = first.first == 0 && top_pos >= 0; + bool last_visible = last.first + 1 == int(parsize) && bottom_pos <= height_; if (first_visible && last_visible) { d->scrollbarParameters_.min = 0; d->scrollbarParameters_.max = 0; return; } - d->scrollbarParameters_.min = tm.topPosition(); - for (size_t i = 0; i != size_t(tm.firstPit()); ++i) + d->scrollbarParameters_.min = top_pos; + for (size_t i = 0; i != size_t(first.first); ++i) d->scrollbarParameters_.min -= d->par_height_[i]; - d->scrollbarParameters_.max = tm.bottomPosition(); - for (size_t i = tm.lastPit() + 1; i != parsize; ++i) + d->scrollbarParameters_.max = bottom_pos; + for (size_t i = last.first + 1; i != parsize; ++i) d->scrollbarParameters_.max += d->par_height_[i]; // The reference is the top position so we remove one page. @@ -943,7 +933,7 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter) TextMetrics & tm = d->text_metrics_[bot.text()]; pos_type const max_pit = pos_type(bot.text()->paragraphs().size() - 1); - int bot_pit = bot.pit(); + pos_type bot_pit = bot.pit(); if (bot_pit > max_pit) { // FIXME: Why does this happen? LYXERR0("bottom pit is greater that max pit: " @@ -951,9 +941,9 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter) bot_pit = max_pit; } - if (bot_pit == tm.firstPit() - 1) + if (bot_pit == tm.first().first - 1) tm.newParMetricsUp(); - else if (bot_pit == tm.lastPit() + 1) + else if (bot_pit == tm.last().first + 1) tm.newParMetricsDown(); if (tm.contains(bot_pit)) { @@ -963,7 +953,8 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter) CursorSlice const & cs = dit.innerTextSlice(); int offset = coordOffset(dit).y_; int ypos = pm.position() + offset; - Row const & row = pm.getRow(cs.pos(), dit.boundary()); + Dimension const & row_dim = + pm.getRow(cs.pos(), dit.boundary()).dim(); int scrolled = 0; if (recenter) scrolled = scroll(ypos - height_/2); @@ -972,7 +963,7 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter) // the screen height, we scroll to a heuristic value of height_ / 4. // FIXME: This heuristic value should be replaced by a recursive search // for a row in the inset that can be visualized completely. - else if (row.height() > height_) { + else if (row_dim.height() > height_) { if (ypos < defaultRowHeight()) scrolled = scroll(ypos - height_ / 4); else if (ypos > height_ - defaultRowHeight()) @@ -981,14 +972,14 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter) // If the top part of the row falls of the screen, we scroll // up to align the top of the row with the top of the screen. - else if (ypos - row.totalAscent() < 0 && ypos < height_) { - int ynew = row.totalAscent(); + else if (ypos - row_dim.ascent() < 0 && ypos < height_) { + int ynew = row_dim.ascent(); scrolled = scrollUp(ynew - ypos); } // If the bottom of the row falls of the screen, we scroll down. - else if (ypos + row.totalDescent() > height_ && ypos > 0) { - int ynew = height_ - row.totalDescent(); + else if (ypos + row_dim.descent() > height_ && ypos > 0) { + int ynew = height_ - row_dim.descent(); scrolled = scrollDown(ypos - ynew); } @@ -1006,14 +997,15 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter) d->anchor_pit_ = bot_pit; CursorSlice const & cs = dit.innerTextSlice(); - Row const & row = pm.getRow(cs.pos(), dit.boundary()); + Dimension const & row_dim = + pm.getRow(cs.pos(), dit.boundary()).dim(); if (recenter) d->anchor_ypos_ = height_/2; else if (d->anchor_pit_ == 0) d->anchor_ypos_ = offset + pm.ascent(); else if (d->anchor_pit_ == max_pit) - d->anchor_ypos_ = height_ - offset - row.totalDescent(); + d->anchor_ypos_ = height_ - offset - row_dim.descent(); else if (offset > height_) d->anchor_ypos_ = height_ - offset - defaultRowHeight(); else @@ -2449,10 +2441,11 @@ int BufferView::scrollDown(int offset) TextMetrics & tm = d->text_metrics_[text]; int const ymax = height_ + offset; while (true) { - int bottom_pos = tm.bottomPosition(); + pair last = tm.last(); + int bottom_pos = last.second->position() + last.second->descent(); if (lyxrc.scroll_below_document) bottom_pos += height_ - minVisiblePart(); - if (tm.lastPit() + 1 == int(text->paragraphs().size())) { + if (last.first + 1 == int(text->paragraphs().size())) { if (bottom_pos <= height_) return 0; offset = min(offset, bottom_pos - height_); @@ -2473,8 +2466,9 @@ int BufferView::scrollUp(int offset) TextMetrics & tm = d->text_metrics_[text]; int ymin = - offset; while (true) { - int const top_pos = tm.topPosition(); - if (tm.firstPit() == 0) { + pair first = tm.first(); + int top_pos = first.second->position() - first.second->ascent(); + if (first.first == 0) { if (top_pos >= 0) return 0; offset = min(offset, - top_pos); @@ -2769,7 +2763,7 @@ bool BufferView::singleParUpdate() Text & buftext = buffer_.text(); pit_type const bottom_pit = d->cursor_.bottom().pit(); TextMetrics & tm = textMetrics(&buftext); - int old_height = tm.parMetrics(bottom_pit).height(); + Dimension const old_dim = tm.parMetrics(bottom_pit).dim(); // make sure inline completion pointer is ok if (d->inlineCompletionPos_.fixIfBroken()) @@ -2780,11 +2774,16 @@ bool BufferView::singleParUpdate() // (if this paragraph contains insets etc., rebreaking will // recursively descend) tm.redoParagraph(bottom_pit); - ParagraphMetrics const & pm = tm.parMetrics(bottom_pit); - if (pm.height() != old_height) + ParagraphMetrics & pm = tm.parMetrics(bottom_pit); + if (pm.height() != old_dim.height()) { // Paragraph height has changed so we cannot proceed to // the singlePar optimisation. return false; + } + // Since position() points to the baseline of the first row, we + // may have to update it. See ticket #11601 for an example where + // the height does not change but the ascent does. + pm.setPosition(pm.position() - old_dim.ascent() + pm.ascent()); tm.updatePosCache(bottom_pit); @@ -2832,7 +2831,7 @@ void BufferView::updateMetrics(Update::flags & update_flags) // Rebreak anchor paragraph. tm.redoParagraph(d->anchor_pit_); - ParagraphMetrics & anchor_pm = tm.par_metrics_[d->anchor_pit_]; + ParagraphMetrics & anchor_pm = tm.parMetrics(d->anchor_pit_); // position anchor if (d->anchor_pit_ == 0) { @@ -2859,7 +2858,7 @@ void BufferView::updateMetrics(Update::flags & update_flags) pit_type pit1 = d->anchor_pit_ - 1; for (; pit1 >= 0 && y1 >= 0; --pit1) { tm.redoParagraph(pit1); - ParagraphMetrics & pm = tm.par_metrics_[pit1]; + ParagraphMetrics & pm = tm.parMetrics(pit1); y1 -= pm.descent(); // Save the paragraph position in the cache. pm.setPosition(y1); @@ -2873,7 +2872,7 @@ void BufferView::updateMetrics(Update::flags & update_flags) pit_type pit2 = d->anchor_pit_ + 1; for (; pit2 < npit && y2 <= height_; ++pit2) { tm.redoParagraph(pit2); - ParagraphMetrics & pm = tm.par_metrics_[pit2]; + ParagraphMetrics & pm = tm.parMetrics(pit2); y2 += pm.ascent(); // Save the paragraph position in the cache. pm.setPosition(y2); @@ -2989,7 +2988,7 @@ Point BufferView::coordOffset(DocIterator const & dit) const ParagraphMetrics const & pm = tm.parMetrics(sl.pit()); LBUFERR(!pm.rows().empty()); - y -= pm.rows()[0].totalAscent(); + y -= pm.rows()[0].ascent(); #if 1 // FIXME: document this mess size_t rend; @@ -3006,7 +3005,7 @@ Point BufferView::coordOffset(DocIterator const & dit) const #endif for (size_t rit = 0; rit != rend; ++rit) y += pm.rows()[rit].height(); - y += pm.rows()[rend].totalAscent(); + y += pm.rows()[rend].ascent(); TextMetrics const & bottom_tm = textMetrics(dit.bottom().text()); @@ -3049,23 +3048,24 @@ bool BufferView::paragraphVisible(DocIterator const & dit) const } -void BufferView::caretPosAndHeight(Point & p, int & h) const +void BufferView::caretPosAndDim(Point & p, Dimension & dim) const { - int asc, des; Cursor const & cur = cursor(); if (cur.inMathed()) { MathRow const & mrow = mathRow(&cur.cell()); - asc = mrow.caret_ascent; - des = mrow.caret_descent; + dim = mrow.caret_dim; } else { Font const font = cur.real_current_font; frontend::FontMetrics const & fm = theFontMetrics(font); - asc = fm.maxAscent(); - des = fm.maxDescent(); + dim.wid = fm.lineWidth(); + dim.asc = fm.maxAscent(); + dim.des = fm.maxDescent(); } - h = asc + des; + if (lyxrc.cursor_width > 0) + dim.wid = lyxrc.cursor_width; + p = getPos(cur); - p.y_ -= asc; + p.y_ -= dim.asc; } @@ -3074,11 +3074,11 @@ bool BufferView::caretInView() const if (!paragraphVisible(cursor())) return false; Point p; - int h; - caretPosAndHeight(p, h); + Dimension dim; + caretPosAndDim(p, dim); // does the cursor touch the screen ? - if (p.y_ + h < 0 || p.y_ >= workHeight()) + if (p.y_ + dim.height() < 0 || p.y_ >= workHeight()) return false; return true; } @@ -3195,7 +3195,7 @@ void BufferView::draw(frontend::Painter & pain, bool paint_caret) : "\t\t*** START DRAWING ***")); Text & text = buffer_.text(); TextMetrics const & tm = d->text_metrics_[&text]; - int const y = tm.parMetrics(tm.firstPit()).position(); + int const y = tm.first().second->position(); PainterInfo pi(this, pain); // Check whether the row where the cursor lives needs to be scrolled. @@ -3250,7 +3250,8 @@ void BufferView::draw(frontend::Painter & pain, bool paint_caret) tm.draw(pi, 0, y); // and possibly grey out below - int const y2 = tm.bottomPosition(); + pair lastpm = tm.last(); + int const y2 = lastpm.second->position() + lastpm.second->descent(); if (y2 < height_) { Color color = buffer().isInternal() @@ -3263,10 +3264,13 @@ void BufferView::draw(frontend::Painter & pain, bool paint_caret) : "\t\t *** END DRAWING ***")); // The scrollbar needs an update. + // FIXME: does it always? see ticket #11947. updateScrollbar(); // Normalize anchor for next time - for (pit_type pit = tm.firstPit(); pit <= tm.lastPit(); ++pit) { + pair firstpm = tm.first(); + pair lastpm = tm.last(); + for (pit_type pit = firstpm.first; pit <= lastpm.first; ++pit) { ParagraphMetrics const & pm = tm.parMetrics(pit); if (pm.position() + pm.descent() > 0) { if (d->anchor_pit_ != pit @@ -3392,7 +3396,7 @@ docstring const & BufferView::inlineCompletion() const } -size_t const & BufferView::inlineCompletionUniqueChars() const +size_t BufferView::inlineCompletionUniqueChars() const { return d->inlineCompletionUniqueChars_; }