X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FBufferView.cpp;h=e31efcf673d433a52ab8efef42dca41d8335cb33;hb=cf14e814124ccbc8155fa1dde98d03be319c0e87;hp=ac6aa6ba76b66e04fc3bb70b2e4eb5e55c69db16;hpb=048f9ee08e6d9473a609c9478db8352c39f71833;p=lyx.git diff --git a/src/BufferView.cpp b/src/BufferView.cpp index ac6aa6ba76..e31efcf673 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -110,7 +110,7 @@ T * getInsetByCode(Cursor const & cur, InsetCode code) Inset * inset = it.nextInset(); if (inset && inset->lyxCode() == code) return static_cast(inset); - return 0; + return nullptr; } @@ -233,13 +233,11 @@ struct BufferView::Private Private(BufferView & bv) : update_strategy_(FullScreenUpdate), update_flags_(Update::Force), - wh_(0), cursor_(bv), - anchor_pit_(0), anchor_ypos_(0), - inlineCompletionUniqueChars_(0), - last_inset_(0), clickable_inset_(false), - mouse_position_cache_(), - bookmark_edit_position_(-1), gui_(0), - horiz_scroll_offset_(0) + cursor_(bv), anchor_pit_(0), anchor_ypos_(0), + wh_(0), inlineCompletionUniqueChars_(0), + last_inset_(nullptr), mouse_position_cache_(), + gui_(nullptr), bookmark_edit_position_(-1), + horiz_scroll_offset_(0), clickable_inset_(false) { xsel_cache_.set = false; } @@ -252,9 +250,10 @@ struct BufferView::Private Update::flags update_flags_; /// CoordCache coord_cache_; + /// + typedef map MathRows; + MathRows math_rows_; - /// Estimated average par height for scrollbar. - int wh_; /// this is used to handle XSelection events in the right manner. struct { CursorSlice cursor; @@ -267,6 +266,8 @@ struct BufferView::Private pit_type anchor_pit_; /// int anchor_ypos_; + /// Estimated average par height for scrollbar. + int wh_; /// vector par_height_; @@ -285,17 +286,12 @@ struct BufferView::Private * Not owned, so don't delete. */ Inset const * last_inset_; - /// are we hovering something that we can click - bool clickable_inset_; /// position of the mouse at the time of the last mouse move /// This is used to update the hovering status of inset in /// cases where the buffer is scrolled, but the mouse didn't move. Point mouse_position_cache_; - // cache for id of the paragraph which was edited the last time - int bookmark_edit_position_; - mutable TextMetricsCache text_metrics_; /// Whom to notify. @@ -311,10 +307,15 @@ struct BufferView::Private /// When the row where the cursor lies is scrolled, this /// contains the scroll offset + // cache for id of the paragraph which was edited the last time + int bookmark_edit_position_; + int horiz_scroll_offset_; /// a slice pointing to the start of the row where the cursor /// is (at last draw time) CursorSlice current_row_slice_; + /// are we hovering something that we can click + bool clickable_inset_; }; @@ -342,9 +343,10 @@ BufferView::~BufferView() // That is to say, if a cursor is in a nested inset, it will be // restore to the left of the top level inset. LastFilePosSection::FilePos fp; + fp.file = buffer_.fileName(); fp.pit = d->cursor_.bottom().pit(); fp.pos = d->cursor_.bottom().pos(); - theSession().lastFilePos().save(buffer_.fileName(), fp); + theSession().lastFilePos().save(fp); if (d->last_inset_) d->last_inset_->setMouseHover(this, false); @@ -430,6 +432,20 @@ CoordCache const & BufferView::coordCache() const } +MathRow const & BufferView::mathRow(MathData const * cell) const +{ + auto it = d->math_rows_.find(cell); + LATTEST(it != d->math_rows_.end()); + return it->second; +} + + +void BufferView::setMathRow(MathData const * cell, MathRow const & mrow) +{ + d->math_rows_[cell] = mrow; +} + + Buffer & BufferView::buffer() { return buffer_; @@ -509,7 +525,13 @@ void BufferView::processUpdateFlags(Update::flags flags) // Then make sure that the screen contains the cursor if needed if (flags & Update::FitCursor) { if (needsFitCursor()) { - scrollToCursor(d->cursor_, false); + // First try to make the selection start visible + // (which is just the cursor when there is no selection) + scrollToCursor(d->cursor_.selectionBegin(), false); + // Is the cursor visible? (only useful if cursor is at end of selection) + if (needsFitCursor()) + // then try to make cursor visible instead + scrollToCursor(d->cursor_, false); // Metrics have to be recomputed (maybe again) updateMetrics(flags); } @@ -1242,7 +1264,7 @@ bool BufferView::getStatus(FuncRequest const & cmd, FuncStatus & flag) Inset * BufferView::editedInset(string const & name) const { map::const_iterator it = d->edited_insets_.find(name); - return it == d->edited_insets_.end() ? 0 : it->second; + return it == d->edited_insets_.end() ? nullptr : it->second; } @@ -1515,12 +1537,18 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) case LFUN_CHANGE_NEXT: findNextChange(this); + if (cur.inset().isTable()) + // In tables, there might be whole changed rows or columns + cur.dispatch(cmd); // FIXME: Move this LFUN to Buffer so that we don't have to do this: dr.screenUpdate(Update::Force | Update::FitCursor); break; case LFUN_CHANGE_PREVIOUS: findPreviousChange(this); + if (cur.inset().isTable()) + // In tables, there might be whole changed rows or columns + cur.dispatch(cmd); // FIXME: Move this LFUN to Buffer so that we don't have to do this: dr.screenUpdate(Update::Force | Update::FitCursor); break; @@ -1533,32 +1561,43 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) } break; - case LFUN_ALL_CHANGES_ACCEPT: + case LFUN_ALL_CHANGES_ACCEPT: { // select complete document cur.reset(); cur.selHandle(true); buffer_.text().cursorBottom(cur); // accept everything in a single step to support atomic undo + // temporarily disable track changes in order to end with really + // no new (e.g., DPSM-caused) changes (see #7487) + bool const track = buffer_.params().track_changes; + buffer_.params().track_changes = false; buffer_.text().acceptOrRejectChanges(cur, Text::ACCEPT); + buffer_.params().track_changes = track; cur.resetAnchor(); // FIXME: Move this LFUN to Buffer so that we don't have to do this: dr.screenUpdate(Update::Force | Update::FitCursor); dr.forceBufferUpdate(); break; + } - case LFUN_ALL_CHANGES_REJECT: + case LFUN_ALL_CHANGES_REJECT: { // select complete document cur.reset(); cur.selHandle(true); buffer_.text().cursorBottom(cur); // reject everything in a single step to support atomic undo - // Note: reject does not work recursively; the user may have to repeat the operation + // temporarily disable track changes in order to end with really + // no new (e.g., DPSM-caused) changes (see #7487) + bool const track = buffer_.params().track_changes; + buffer_.params().track_changes = false; buffer_.text().acceptOrRejectChanges(cur, Text::REJECT); + buffer_.params().track_changes = track; cur.resetAnchor(); // FIXME: Move this LFUN to Buffer so that we don't have to do this: dr.screenUpdate(Update::Force | Update::FitCursor); dr.forceBufferUpdate(); break; + } case LFUN_WORD_FIND_FORWARD: case LFUN_WORD_FIND_BACKWARD: { @@ -2165,7 +2204,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) } -docstring const BufferView::requestSelection() +docstring BufferView::requestSelection() { Cursor & cur = d->cursor_; @@ -2222,7 +2261,7 @@ Inset const * BufferView::getCoveringInset(Text const & text, TextMetrics & tm = d->text_metrics_[&text]; Inset * inset = tm.checkInsetHit(x, y); if (!inset) - return 0; + return nullptr; if (!inset->descendable(*this)) // No need to go further down if the inset is not @@ -2263,7 +2302,7 @@ void BufferView::updateHoveredInset() const if (d->last_inset_) { // Remove the hint on the last hovered inset (if any). need_redraw |= d->last_inset_->setMouseHover(this, false); - d->last_inset_ = 0; + d->last_inset_ = nullptr; } if (covering_inset && covering_inset->setMouseHover(this, true)) { @@ -2294,7 +2333,7 @@ void BufferView::clearLastInset(Inset * inset) const LYXERR0("Wrong last_inset!"); LATTEST(false); } - d->last_inset_ = 0; + d->last_inset_ = nullptr; } @@ -2771,6 +2810,7 @@ void BufferView::updateMetrics(Update::flags & update_flags) // Clear out the position cache in case of full screen redraw, d->coord_cache_.clear(); + d->math_rows_.clear(); // Clear out paragraph metrics to avoid having invalid metrics // in the cache from paragraphs not relayouted below @@ -3011,8 +3051,9 @@ void BufferView::caretPosAndHeight(Point & p, int & h) const int asc, des; Cursor const & cur = cursor(); if (cur.inMathed()) { - asc = cur.cell().caretAscent(this); - des = cur.cell().caretDescent(this); + MathRow const & mrow = mathRow(&cur.cell()); + asc = mrow.caret_ascent; + des = mrow.caret_descent; } else { Font const font = cur.real_current_font; frontend::FontMetrics const & fm = theFontMetrics(font); @@ -3025,11 +3066,16 @@ void BufferView::caretPosAndHeight(Point & p, int & h) const } -bool BufferView::cursorInView(Point const & p, int h) const +bool BufferView::caretInView() const { - Cursor const & cur = cursor(); + if (!paragraphVisible(cursor())) + return false; + Point p; + int h; + caretPosAndHeight(p, h); + // does the cursor touch the screen ? - if (p.y_ + h < 0 || p.y_ >= workHeight() || !paragraphVisible(cur)) + if (p.y_ + h < 0 || p.y_ >= workHeight()) return false; return true; } @@ -3160,7 +3206,6 @@ void BufferView::draw(frontend::Painter & pain, bool paint_caret) // however, the different coordinates of insets and paragraphs // needs to be updated. LYXERR(Debug::PAINTING, "Strategy: NoScreenUpdate"); - pi.full_repaint = false; if (pain.isNull()) { pi.full_repaint = true; tm.draw(pi, 0, y);