X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferView.cpp;h=2068f050cfeddf283516763aecc57adab3c6a8e6;hb=22f599250e926555bdef0d50ee2198b3eb2da02a;hp=b8bc705434e4cc9512ce493a907c2828649868b5;hpb=641ae5c7add025e51a2da718cdbb0dff098b29e7;p=lyx.git diff --git a/src/BufferView.cpp b/src/BufferView.cpp index b8bc705434..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_; @@ -477,7 +484,8 @@ string flagsAsString(Update::flags flags) return string((flags & Update::FitCursor) ? "FitCursor " : "") + ((flags & Update::Force) ? "Force " : "") + ((flags & Update::ForceDraw) ? "ForceDraw " : "") - + ((flags & Update::SinglePar) ? "SinglePar " : ""); + + ((flags & Update::SinglePar) ? "SinglePar " : "") + + ((flags & Update::Decoration) ? "Decoration " : ""); } } @@ -491,10 +499,13 @@ void BufferView::processUpdateFlags(Update::flags flags) if (flags == Update::None) return; - // 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; + /* FIXME We would like to avoid doing this here, since it is very + * expensive and is called in updateBuffer already. However, even + * inserting a plain character can invalidate the overly fragile + * tables of child documents built by updateMacros. Some work is + * needed to avoid doing that when not necessary. + */ + buffer_.updateMacros(); // First check whether the metrics and inset positions should be updated if (flags & Update::Force) { @@ -503,6 +514,15 @@ void BufferView::processUpdateFlags(Update::flags flags) updateMetrics(flags); } + // 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) + && (flags & Update::SinglePar) + && !singleParUpdate()) + updateMetrics(flags); + // Then make sure that the screen contains the cursor if needed if (flags & Update::FitCursor) { if (needsFitCursor()) { @@ -513,21 +533,13 @@ void BufferView::processUpdateFlags(Update::flags flags) flags = flags & ~Update::FitCursor; } - // Finally detect whether we can only repaint a single paragraph - if (!(flags & Update::ForceDraw)) { - if (singleParUpdate()) - flags = flags | Update::SinglePar; - else - updateMetrics(flags); - } - // Add flags to the the update flags. These will be reset to None // after the redraw is actually done d->update_flags_ = d->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); @@ -857,7 +869,7 @@ bool BufferView::moveToPosition(pit_type bottom_pit, pos_type bottom_pos, d->cursor_.setCurrentFont(); // Do not forget to reset the anchor (see #9912) d->cursor_.resetAnchor(); - processUpdateFlags(Update::FitCursor); + processUpdateFlags(Update::Force | Update::FitCursor); } return success; @@ -945,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); @@ -989,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; @@ -1253,7 +1265,10 @@ Inset * BufferView::editedInset(string const & name) const void BufferView::editInset(string const & name, Inset * inset) { - d->edited_insets_[name] = inset; + if (inset) + d->edited_insets_[name] = inset; + else + d->edited_insets_.erase(name); } @@ -1355,7 +1370,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) // without calling recordUndo. Fix this before using // recordUndoBufferParams(). cur.recordUndoFullBuffer(); - buffer_.params().setBaseClass(argument); + buffer_.params().setBaseClass(argument, buffer_.layoutPos()); makeDocumentClass(); dr.screenUpdate(Update::Force); dr.forceBufferUpdate(); @@ -1379,7 +1394,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) case LFUN_LAYOUT_RELOAD: { LayoutFileIndex bc = buffer_.params().baseClassID(); LayoutFileList::get().reset(bc); - buffer_.params().setBaseClass(bc); + buffer_.params().setBaseClass(bc, buffer_.layoutPos()); makeDocumentClass(); dr.screenUpdate(Update::Force); dr.forceBufferUpdate(); @@ -1392,14 +1407,14 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) // We need to find out if the bibliography information // has changed. See bug #11055. // So these should not be references... - LayoutModuleList const engines = buffer().params().citeEngine(); + string const engine = buffer().params().citeEngine(); CiteEngineType const enginetype = buffer().params().citeEngineType(); - if (!cur.textUndo()) + if (!cur.undoAction()) dr.setMessage(_("No further undo information")); else { dr.screenUpdate(Update::Force | Update::FitCursor); dr.forceBufferUpdate(); - if (buffer().params().citeEngine() != engines || + if (buffer().params().citeEngine() != engine || buffer().params().citeEngineType() != enginetype) buffer().invalidateCiteLabels(); } @@ -1412,14 +1427,14 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) // We need to find out if the bibliography information // has changed. See bug #11055. // So these should not be references... - LayoutModuleList const engines = buffer().params().citeEngine(); + string const engine = buffer().params().citeEngine(); CiteEngineType const enginetype = buffer().params().citeEngineType(); - if (!cur.textRedo()) + if (!cur.redoAction()) dr.setMessage(_("No further redo information")); else { dr.screenUpdate(Update::Force | Update::FitCursor); dr.forceBufferUpdate(); - if (buffer().params().citeEngine() != engines || + if (buffer().params().citeEngine() != engine || buffer().params().citeEngineType() != enginetype) buffer().invalidateCiteLabels(); } @@ -1890,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 @@ -2501,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); } @@ -2524,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; } @@ -2581,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) @@ -2759,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 @@ -2856,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); @@ -2874,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 { @@ -2990,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); @@ -3045,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; @@ -3125,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;