X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferView.cpp;h=2068f050cfeddf283516763aecc57adab3c6a8e6;hb=22f599250e926555bdef0d50ee2198b3eb2da02a;hp=e2648a151ca6179848bbfabee257803977c6d381;hpb=99bfe201208a5cb4553cb88d0633ebc1c64b828c;p=lyx.git diff --git a/src/BufferView.cpp b/src/BufferView.cpp index e2648a151c..2068f050cf 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -239,8 +239,7 @@ struct BufferView::Private last_inset_(0), clickable_inset_(false), mouse_position_cache_(), bookmark_edit_position_(-1), gui_(0), - horiz_scroll_offset_(0), - caret_ascent_(0), caret_descent_(0) + horiz_scroll_offset_(0) { xsel_cache_.set = false; } @@ -253,6 +252,9 @@ struct BufferView::Private Update::flags update_flags_; /// CoordCache coord_cache_; + /// + typedef map MathRows; + MathRows math_rows_; /// Estimated average par height for scrollbar. int wh_; @@ -316,15 +318,6 @@ struct BufferView::Private /// a slice pointing to the start of the row where the cursor /// is (at last draw time) CursorSlice current_row_slice_; - /// a slice pointing to the start of the row where cursor was - /// at previous draw event - CursorSlice last_row_slice_; - - // The vertical size of the blinking caret. Only used for math - // Using it for text could be bad when undo restores the cursor - // current font, since the caret size could become wrong. - int caret_ascent_; - int caret_descent_; }; @@ -440,6 +433,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_; @@ -500,11 +507,6 @@ void BufferView::processUpdateFlags(Update::flags flags) */ buffer_.updateMacros(); - // SinglePar is ignored for now (this should probably change). We - // set it ourselves below, at the price of always rebreaking the - // paragraph at cursor. This can be expensive for large tables. - flags = flags & ~Update::SinglePar; - // First check whether the metrics and inset positions should be updated if (flags & Update::Force) { // This will update the CoordCache items and replace Force @@ -512,15 +514,14 @@ void BufferView::processUpdateFlags(Update::flags flags) updateMetrics(flags); } - // Detect whether we can only repaint a single paragraph. + // Detect whether we can only repaint a single paragraph (if we + // are not already redrawing all). // We handle this before FitCursor because the later will require // correct metrics at cursor position. - if (!(flags & Update::ForceDraw)) { - if (singleParUpdate()) - flags = flags | Update::SinglePar; - else + if (!(flags & Update::ForceDraw) + && (flags & Update::SinglePar) + && !singleParUpdate()) updateMetrics(flags); - } // Then make sure that the screen contains the cursor if needed if (flags & Update::FitCursor) { @@ -538,7 +539,7 @@ void BufferView::processUpdateFlags(Update::flags flags) LYXERR(Debug::PAINTING, "Cumulative flags: " << flagsAsString(flags)); // Now compute the update strategy - // Possibly values in flag are None, Decoration, ForceDraw + // Possibly values in flag are None, SinglePar, Decoration, ForceDraw LATTEST((d->update_flags_ & ~(Update::None | Update::SinglePar | Update::Decoration | Update::ForceDraw)) == 0); @@ -956,7 +957,7 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter) int offset = coordOffset(dit).y_; int ypos = pm.position() + offset; Dimension const & row_dim = - pm.getRow(cs.pos(), dit.boundary()).dimension(); + pm.getRow(cs.pos(), dit.boundary()).dim(); int scrolled = 0; if (recenter) scrolled = scroll(ypos - height_/2); @@ -1000,7 +1001,7 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool const recenter) d->anchor_pit_ = bot_pit; CursorSlice const & cs = dit.innerTextSlice(); Dimension const & row_dim = - pm.getRow(cs.pos(), dit.boundary()).dimension(); + pm.getRow(cs.pos(), dit.boundary()).dim(); if (recenter) d->anchor_ypos_ = height_/2; @@ -1904,10 +1905,12 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) // At least one complete cell is selected and inset is a table. // Select all cells cur.idx() = 0; + cur.pit() = 0; cur.pos() = 0; cur.resetAnchor(); cur.selection(true); cur.idx() = cur.lastidx(); + cur.pit() = cur.lastpit(); cur.pos() = cur.lastpos(); } else { // select current cell @@ -2515,15 +2518,26 @@ bool BufferView::setCursorFromInset(Inset const * inset) void BufferView::gotoLabel(docstring const & label) { + FuncRequest action; + bool have_inactive = false; for (Buffer const * buf : buffer().allRelatives()) { // find label for (TocItem const & item : *buf->tocBackend().toc("label")) { - if (label == item.str()) { + if (label == item.str() && item.isOutput()) { lyx::dispatch(item.action()); return; } + // If we find an inactive label, save it for the case + // that no active one is there + if (label == item.str() && !have_inactive) { + have_inactive = true; + action = item.action(); + } } } + // We only found an inactive label. Go there. + if (have_inactive) + lyx::dispatch(action); } @@ -2538,8 +2552,9 @@ TextMetrics & BufferView::textMetrics(Text const * t) LBUFERR(t); TextMetricsCache::iterator tmc_it = d->text_metrics_.find(t); if (tmc_it == d->text_metrics_.end()) { - tmc_it = d->text_metrics_.insert( - make_pair(t, TextMetrics(this, const_cast(t)))).first; + tmc_it = d->text_metrics_.emplace(std::piecewise_construct, + std::forward_as_tuple(t), + std::forward_as_tuple(this, const_cast(t))).first; } return tmc_it->second; } @@ -2595,7 +2610,7 @@ bool BufferView::checkDepm(Cursor & cur, Cursor & old) return false; bool need_anchor_change = false; - bool changed = d->cursor_.text()->deleteEmptyParagraphMechanism(cur, old, + bool changed = Text::deleteEmptyParagraphMechanism(cur, old, need_anchor_change); if (need_anchor_change) @@ -2773,6 +2788,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 @@ -2870,7 +2886,7 @@ void BufferView::updatePosCache() } -void BufferView::insertLyXFile(FileName const & fname) +void BufferView::insertLyXFile(FileName const & fname, bool const ignorelang) { LASSERT(d->cursor_.inTexted(), return); @@ -2888,8 +2904,12 @@ void BufferView::insertLyXFile(FileName const & fname) ErrorList & el = buffer_.errorList("Parse"); // Copy the inserted document error list into the current buffer one. el = buf.errorList("Parse"); + ParagraphList & pars = buf.paragraphs(); + if (ignorelang) + // set main language of imported file to context language + buf.changeLanguage(buf.language(), d->cursor_.getFont().language()); buffer_.undo().recordUndo(d->cursor_); - cap::pasteParagraphList(d->cursor_, buf.paragraphs(), + cap::pasteParagraphList(d->cursor_, pars, buf.params().documentClassPtr(), el); res = _("Document %1$s inserted."); } else { @@ -3004,20 +3024,14 @@ bool BufferView::paragraphVisible(DocIterator const & dit) const } -void BufferView::setCaretAscentDescent(int asc, int des) -{ - d->caret_ascent_ = asc; - d->caret_descent_ = des; -} - - void BufferView::caretPosAndHeight(Point & p, int & h) const { int asc, des; Cursor const & cur = cursor(); if (cur.inMathed()) { - asc = d->caret_ascent_; - des = d->caret_descent_; + 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); @@ -3059,30 +3073,24 @@ int BufferView::horizScrollOffset(Text const * text, } -bool BufferView::hadHorizScrollOffset(Text const * text, - pit_type pit, pos_type pos) const -{ - return !d->last_row_slice_.empty() - && &text->inset() == d->last_row_slice_.inset().asInsetText() - && pit == d->last_row_slice_.pit() - && pos == d->last_row_slice_.pos(); -} - - void BufferView::setCurrentRowSlice(CursorSlice const & rowSlice) { // nothing to do if the cursor was already on this row - if (d->current_row_slice_ == rowSlice) { - d->last_row_slice_ = CursorSlice(); + if (d->current_row_slice_ == rowSlice) return; - } // if the (previous) current row was scrolled, we have to // remember it in order to repaint it next time. - if (d->horiz_scroll_offset_ != 0) - d->last_row_slice_ = d->current_row_slice_; - else - d->last_row_slice_ = CursorSlice(); + if (d->horiz_scroll_offset_ != 0) { + // search the old row in cache and mark it changed + for (auto & tm_pair : d->text_metrics_) { + if (&tm_pair.first->inset() == rowSlice.inset().asInsetText()) { + tm_pair.second.setRowChanged(rowSlice.pit(), rowSlice.pos()); + // We found it, no need to continue. + break; + } + } + } // Since we changed row, the scroll offset is not valid anymore d->horiz_scroll_offset_ = 0; @@ -3139,8 +3147,7 @@ void BufferView::checkCursorScrollOffset() << d->horiz_scroll_offset_ << " to " << offset); if (d->update_strategy_ == NoScreenUpdate - && (offset != d->horiz_scroll_offset_ - || !d->last_row_slice_.empty())) { + && offset != d->horiz_scroll_offset_) { // FIXME: if one uses SingleParUpdate, then home/end // will not work on long rows. Why? d->update_strategy_ = FullScreenUpdate;