From 22cdac5d5d53c4a5f4ecc9d2af0f5eeaf0f8295b Mon Sep 17 00:00:00 2001 From: Martin Vermeer Date: Fri, 10 Mar 2006 16:10:35 +0000 Subject: [PATCH] Fix bug 2195: Slowness in rendering inside insets, especially on the Mac git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@13328 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/BufferView.C | 12 ++++ src/BufferView.h | 8 ++- src/BufferView_pimpl.C | 19 +++++- src/BufferView_pimpl.h | 12 +++- src/ChangeLog | 9 +++ src/LyXAction.C | 20 +++--- src/debug.C | 1 + src/debug.h | 2 + src/insets/ChangeLog | 6 +- src/insets/insetcollapsable.C | 3 +- src/insets/insettext.C | 20 +++--- src/insets/insettext.h | 6 +- src/rowpainter.C | 117 ++++++++++++++++++++++++++++------ src/text3.C | 16 ++++- 14 files changed, 201 insertions(+), 50 deletions(-) diff --git a/src/BufferView.C b/src/BufferView.C index 75544d0623..d5160a7420 100644 --- a/src/BufferView.C +++ b/src/BufferView.C @@ -369,6 +369,18 @@ void BufferView::putSelectionAt(DocIterator const & cur, } +bool const BufferView::repaintAll() const +{ + return pimpl_->repaintAll(); +} + + +void const BufferView::repaintAll(bool r) const +{ + pimpl_->repaintAll(r); +} + + LCursor & BufferView::cursor() { return pimpl_->cursor_; diff --git a/src/BufferView.h b/src/BufferView.h index 426e90a293..2940d77586 100644 --- a/src/BufferView.h +++ b/src/BufferView.h @@ -40,7 +40,8 @@ namespace Update { enum flags { FitCursor = 1, Force = 2, - SinglePar = 4 + SinglePar = 4, + MultiParSel = 8 }; inline flags operator|(flags const f, flags const g) @@ -198,7 +199,10 @@ public: */ void putSelectionAt(DocIterator const & cur, int length, bool backwards); - + /// + bool const repaintAll() const; + /// + void const repaintAll(bool r) const; private: /// diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index 87bc17b337..776bb78c08 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -658,6 +658,17 @@ bool BufferView::Pimpl::fitCursor() } +bool BufferView::Pimpl::multiParSel() +{ + if (!cursor_.selection()) + return false; + bool ret = multiparsel_cache_; + multiparsel_cache_ = cursor_.selBegin().pit() != cursor_.selEnd().pit(); + // Either this, or previous selection spans paragraphs + return ret || multiparsel_cache_; +} + + void BufferView::Pimpl::update(Update::flags flags) { lyxerr[Debug::DEBUG] @@ -682,12 +693,16 @@ void BufferView::Pimpl::update(Update::flags flags) // First drawing step ViewMetricsInfo vi = metrics(flags & Update::SinglePar); - bool forceupdate(flags & Update::Force); + bool forceupdate(flags & (Update::Force | Update::SinglePar)); if ((flags & Update::FitCursor) && fitCursor()) { forceupdate = true; vi = metrics(); } + if ((flags & Update::MultiParSel) && multiParSel()) { + forceupdate = true; + vi = metrics(); + } if (forceupdate) { // Second drawing step screen().redraw(*bv_, vi); @@ -989,7 +1004,7 @@ bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd0) if (cur.result().update()) update(Update::FitCursor | Update::Force); else - update(); + update(Update::FitCursor | Update::MultiParSel); } // See workAreaKeyPress diff --git a/src/BufferView_pimpl.h b/src/BufferView_pimpl.h index b55cf924e2..c6ac78f6f7 100644 --- a/src/BufferView_pimpl.h +++ b/src/BufferView_pimpl.h @@ -59,6 +59,8 @@ public: void resizeCurrentBuffer(); // bool fitCursor(); + // + bool multiParSel(); /// void update(Update::flags flags = Update::Force); /// @@ -103,6 +105,10 @@ public: FuncStatus getStatus(FuncRequest const & cmd); /// a function should be executed bool dispatch(FuncRequest const & ev); + /// Flag: do a full redraw of inside text of inset + bool repaintAll() { return refresh_inside_; } + /// + void repaintAll(bool r) {refresh_inside_ = r; } private: /// An error list (replaces the error insets) ErrorList errorlist_; @@ -183,13 +189,15 @@ private: /// LCursor cursor_; /// + bool multiparsel_cache_; /// lyx::pit_type anchor_ref_; /// int offset_ref_; /// ViewMetricsInfo metrics(bool singlepar = false); - - + /// Working variable indicating a full screen refresh + mutable bool refresh_inside_; + }; #endif // BUFFERVIEW_PIMPL_H diff --git a/src/ChangeLog b/src/ChangeLog index 760a4b65f3..5b32b815d8 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2006-03-10 Martin Vermeer + + * BufferView.[Ch]: + * BufferView_pimpl.[Ch]: + * LyXAction.C: + * debug.[Ch]: + * rowpainter.C: + * text3.C: Inside-inset speedup, esp. for the Mac (bug 2195) + 2006-03-07 Georg Baum * pch.h: fix nullstream.hpp location for boost 1.33.0 diff --git a/src/LyXAction.C b/src/LyXAction.C index 9c98b95881..911bef3d4c 100644 --- a/src/LyXAction.C +++ b/src/LyXAction.C @@ -97,7 +97,7 @@ void LyXAction::init() { LFUN_UNDERBAR, "accent-underbar", Noop }, { LFUN_UNDERDOT, "accent-underdot", Noop }, { LFUN_APPENDIX, "appendix", Noop }, - { LFUN_LEFTSEL, "backward-select", ReadOnly }, + { LFUN_LEFTSEL, "backward-select", ReadOnly | SingleParUpdate }, { LFUN_BOOKMARK_GOTO, "bookmark-goto", ReadOnly }, { LFUN_BOOKMARK_SAVE, "bookmark-save", ReadOnly }, { LFUN_BREAKLINE, "break-line", Noop }, @@ -143,8 +143,8 @@ void LyXAction::init() { LFUN_DEPTH_MIN, "depth-decrement", Noop }, { LFUN_DEPTH_PLUS, "depth-increment", Noop }, { LFUN_LDOTS, "dots-insert", Noop }, - { LFUN_DOWN, "down", ReadOnly | NoUpdate}, - { LFUN_DOWNSEL, "down-select", ReadOnly }, + { LFUN_DOWN, "down", ReadOnly | NoUpdate }, + { LFUN_DOWNSEL, "down-select", ReadOnly | SingleParUpdate }, { LFUN_DROP_LAYOUTS_CHOICE, "drop-layouts-choice", ReadOnly }, { LFUN_END_OF_SENTENCE, "end-of-sentence-period-insert", Noop }, { LFUN_ENVIRONMENT_INSERT, "environment-insert", Noop }, @@ -173,7 +173,7 @@ void LyXAction::init() { LFUN_FONT_STATE, "font-state", ReadOnly }, { LFUN_UNDERLINE, "font-underline", Noop }, { LFUN_INSET_FOOTNOTE, "footnote-insert", Noop }, - { LFUN_RIGHTSEL, "forward-select", ReadOnly }, + { LFUN_RIGHTSEL, "forward-select", ReadOnly | SingleParUpdate }, { LFUN_HFILL, "hfill-insert", Noop }, { LFUN_HELP_OPEN, "help-open", NoBuffer | Argument}, { LFUN_HTMLURL, "html-insert", Noop }, @@ -198,10 +198,10 @@ void LyXAction::init() { LFUN_LAYOUT_PARAGRAPH, "layout-paragraph", ReadOnly }, { LFUN_LAYOUT_TABULAR, "layout-tabular", Noop }, { LFUN_HOME, "line-begin", ReadOnly | NoUpdate}, - { LFUN_HOMESEL, "line-begin-select", ReadOnly }, + { LFUN_HOMESEL, "line-begin-select", ReadOnly | SingleParUpdate }, { LFUN_DELETE_LINE_FORWARD, "line-delete-forward", Noop }, { LFUN_END, "line-end", ReadOnly | NoUpdate}, - { LFUN_ENDSEL, "line-end-select", ReadOnly }, + { LFUN_ENDSEL, "line-end-select", ReadOnly | SingleParUpdate }, #if 0 { LFUN_INSET_LIST, "list-insert", Noop }, #endif @@ -283,7 +283,7 @@ void LyXAction::init() { LFUN_TOGGLECURSORFOLLOW, "toggle-cursor-follows-scrollbar", ReadOnly }, { LFUN_UNDO, "undo", Noop }, { LFUN_UP, "up", ReadOnly | NoUpdate}, - { LFUN_UPSEL, "up-select", ReadOnly }, + { LFUN_UPSEL, "up-select", ReadOnly | SingleParUpdate }, { LFUN_URL, "url-insert", Noop }, { LFUN_VC_CHECKIN, "vc-check-in", ReadOnly }, { LFUN_VC_CHECKOUT, "vc-check-out", ReadOnly }, @@ -291,14 +291,14 @@ void LyXAction::init() { LFUN_VC_REVERT, "vc-revert", ReadOnly }, { LFUN_VC_UNDO, "vc-undo-last", ReadOnly }, { LFUN_WORDLEFT, "word-backward", ReadOnly | NoUpdate}, - { LFUN_WORDLEFTSEL, "word-backward-select", ReadOnly }, + { LFUN_WORDLEFTSEL, "word-backward-select", ReadOnly | SingleParUpdate }, { LFUN_CAPITALIZE_WORD, "word-capitalize", Noop }, { LFUN_DELETE_WORD_BACKWARD, "word-delete-backward", Noop }, { LFUN_DELETE_WORD_FORWARD, "word-delete-forward", Noop }, { LFUN_WORDFINDBACKWARD, "word-find-backward", ReadOnly }, { LFUN_WORDFINDFORWARD, "word-find-forward", ReadOnly }, { LFUN_WORDRIGHT, "word-forward", ReadOnly | NoUpdate}, - { LFUN_WORDRIGHTSEL, "word-forward-select", ReadOnly }, + { LFUN_WORDRIGHTSEL, "word-forward-select", ReadOnly | SingleParUpdate }, { LFUN_LOWCASE_WORD, "word-lowcase", Noop }, { LFUN_WORDSEL, "word-select", ReadOnly }, { LFUN_UPCASE_WORD, "word-upcase", Noop }, @@ -348,7 +348,7 @@ void LyXAction::init() { LFUN_FINISHED_UP, "", ReadOnly }, { LFUN_FINISHED_DOWN, "", ReadOnly }, { LFUN_MOUSE_PRESS, "", ReadOnly }, - { LFUN_MOUSE_MOTION, "", ReadOnly }, + { LFUN_MOUSE_MOTION, "", ReadOnly | SingleParUpdate }, { LFUN_MOUSE_RELEASE, "", ReadOnly }, { LFUN_MOUSE_DOUBLE, "", ReadOnly }, { LFUN_MOUSE_TRIPLE, "", ReadOnly }, diff --git a/src/debug.C b/src/debug.C index 24977bc1b8..2b4badfcfa 100644 --- a/src/debug.C +++ b/src/debug.C @@ -63,6 +63,7 @@ error_item errorTags[] = { { Debug::GRAPHICS, "graphics", N_("Graphics conversion and loading")}, { Debug::CHANGES, "changes", N_("Change tracking")}, { Debug::EXTERNAL, "external", N_("External template/inset messages")}, + { Debug::PAINTING, "painting", N_("RowPainter profiling")}, { Debug::DEBUG, "debug", N_("Developers' general debug messages")}, { Debug::ANY, "any", N_("All debugging messages")} }; diff --git a/src/debug.h b/src/debug.h index af7b04067e..c338b7a228 100644 --- a/src/debug.h +++ b/src/debug.h @@ -74,6 +74,8 @@ public: /// EXTERNAL = (1 << 23), /// + PAINTING = (1 << 24), + /// DEBUG = (1 << 31), /// ANY = 0xffffffff diff --git a/src/insets/ChangeLog b/src/insets/ChangeLog index 6c79f3a4d6..7bf7d96913 100644 --- a/src/insets/ChangeLog +++ b/src/insets/ChangeLog @@ -1,4 +1,8 @@ -2005-02-25 Martin Vermeer +2005-03-10 Martin Vermeer + + * insetcollapsable.C: + * insettext.[Ch]: Inside-inset speedup, esp. for the Mac (bug 2195) + 2006-02-25 Georg Baum * insetert.[Ch] (read): new, force all paragraphs to latex_language diff --git a/src/insets/insetcollapsable.C b/src/insets/insetcollapsable.C index 11b02bb1d2..02a6b375db 100644 --- a/src/insets/insetcollapsable.C +++ b/src/insets/insetcollapsable.C @@ -138,7 +138,7 @@ void InsetCollapsable::metrics(MetricsInfo & mi, Dimension & dim) const dim = dimensionCollapsed(); if (status() == Open) { InsetText::metrics(mi, textdim_); - openinlined_ = (textdim_.wid + dim.wid <= mi.base.textwidth); + openinlined_ = textdim_.wid + 2 * dim.wid <= mi.base.textwidth; if (openinlined_) { dim.wid += textdim_.wid; dim.des = max(dim.des - textdim_.asc + dim.asc, textdim_.des); @@ -171,6 +171,7 @@ void InsetCollapsable::draw(PainterInfo & pi, int x, int y) const button_dim.y2 = top + dimc.height(); pi.pain.buttonText(xx, top + dimc.asc, label, labelfont_); + if (status() == Open) { int textx, texty; if (openinlined_) { diff --git a/src/insets/insettext.C b/src/insets/insettext.C index 99ff0b3186..bd02ffcc4a 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -200,6 +200,7 @@ void InsetText::draw(PainterInfo & pi, int x, int y) const // update our idea of where we are setPosCache(pi, x, y); + text_.background_color_ = backgroundColor(); text_.draw(pi, x + border_, y); if (drawFrame_) { @@ -207,7 +208,7 @@ void InsetText::draw(PainterInfo & pi, int x, int y) const int const a = text_.ascent() + border_; int const h = a + text_.descent() + border_; int const ww = pi.base.bv->workWidth(); - if (w > ww - 40) { + if (w > ww - 40 || Wide()) { pi.pain.line(0, y - a, ww, y - a, frameColor()); pi.pain.line(0, y - a + h, ww, y - a + h, frameColor()); } else { @@ -219,13 +220,16 @@ void InsetText::draw(PainterInfo & pi, int x, int y) const void InsetText::drawSelection(PainterInfo & pi, int x, int y) const { - if (backgroundColor() != LColor::background) { - // repaint the background if needed - int const w = text_.width() + 2 * border_; - int const a = text_.ascent() + border_; - int const h = a + text_.descent() + border_; - pi.pain.fillRectangle(x, y - a, w, h, backgroundColor()); - } + int const w = text_.width() + 2 * border_; + int const a = text_.ascent() + border_; + int const h = a + text_.descent() + border_; + int const ww = pi.base.bv->workWidth(); + if (Wide()) + pi.pain.fillRectangle(0, y - a, ww, h, + backgroundColor()); + else + pi.pain.fillRectangle(x, y - a, w, h, + backgroundColor()); text_.drawSelection(pi, x, y); } diff --git a/src/insets/insettext.h b/src/insets/insettext.h index c6ba640afb..dadc5593a1 100644 --- a/src/insets/insettext.h +++ b/src/insets/insettext.h @@ -137,7 +137,9 @@ public: bool neverIndent() const; /// InsetText(InsetText const &); - + /// + bool & Wide() const { return wide_inset_; } + protected: /// virtual void doDispatch(LCursor & cur, FuncRequest & cmd); @@ -158,6 +160,8 @@ private: mutable lyx::pit_type old_pit; /// static int border_; + /// + mutable bool wide_inset_; public: /// mutable LyXText text_; diff --git a/src/rowpainter.C b/src/rowpainter.C index 2b8193f5ea..deaf1d7209 100644 --- a/src/rowpainter.C +++ b/src/rowpainter.C @@ -151,6 +151,15 @@ int RowPainter::leftMargin() const } +bool isTrueTextInset(InsetBase * in) +{ + // Math and tabular insets have isTextInset = true, though they are + // not derived from InsetText. Paint them fully + return (in && in->isTextInset() && in->asMathInset() == 0 + && in->lyxCode() != InsetBase::TABULAR_CODE); +} + + void RowPainter::paintInset(pos_type const pos, LyXFont const & font) { InsetBase const * inset = par_.getInset(pos); @@ -164,8 +173,15 @@ void RowPainter::paintInset(pos_type const pos, LyXFont const & font) pi.ltr_pos = (text_.bidi.level(pos) % 2 == 0); pi.erased_ = erased_ || isDeletedText(par_, pos); theCoords.insets().add(inset, int(x_), yo_); - inset->drawSelection(pi, int(x_), yo_); + InsetBase * in = const_cast(inset); + // non-wide insets are painted completely. Recursive + bool tmp = bv_.repaintAll(); + if (!isTrueTextInset(in) || !static_cast(in)->Wide()) + bv_.repaintAll(true); + if (bv_.repaintAll()) + inset->drawSelection(pi, int(x_), yo_); inset->draw(pi, int(x_), yo_); + bv_.repaintAll(tmp); x_ += inset->width(); } @@ -720,25 +736,52 @@ void RowPainter::paintText() } -lyx::size_type calculateRowSignature(Row const & row, Paragraph const & par) +lyx::size_type calculateRowSignature(Row const & row, Paragraph const & par, + int x, int y) { boost::crc_32_type crc; for (lyx::pos_type i = row.pos(); i < row.endpos(); ++i) { const unsigned char b[] = { par.getChar(i) }; crc.process_bytes(b, 1); } + const unsigned char b[] = { x, y, row.width() }; + crc.process_bytes(b, 3); return crc.checksum(); } -bool isCursorOnRow(PainterInfo & pi, pit_type pit, RowList::const_iterator rit) +bool CursorOnRow(PainterInfo & pi, pit_type const pit, + RowList::const_iterator rit, LyXText const & text) { + // Is there a cursor on this row (or inside inset on row) LCursor & cur = pi.base.bv->cursor(); - for (lyx::size_type d = 0; d < cur.depth(); d++) - if (cur[d].pit() == pit - && cur[d].pos() >= rit->pos() - && cur[d].pos() <= rit->endpos()) + for (lyx::size_type d = 0; d < cur.depth(); d++) { + CursorSlice const & sl = cur[d]; + if (sl.text() == &text + && sl.pit() == pit + && sl.pos() >= rit->pos() + && sl.pos() < rit->endpos()) return true; + } + return false; +} + + +bool innerCursorOnRow(PainterInfo & pi, pit_type pit, + RowList::const_iterator rit, LyXText const & text) +{ + // Is there a cursor inside an inset on this row, and is this inset + // the only "character" on this row + LCursor & cur = pi.base.bv->cursor(); + if (rit->pos() + 1 != rit->endpos()) + return false; + for (lyx::size_type d = 0; d < cur.depth(); d++) { + CursorSlice const & sl = cur[d]; + if (sl.text() == &text + && sl.pit() == pit + && sl.pos() == rit->pos()) + return d < cur.depth() - 1; + } return false; } @@ -762,17 +805,31 @@ void paintPar lyx::size_type rowno(0); for (RowList::const_iterator rit = rb; rit != re; ++rit, ++rowno) { y += rit->ascent(); + // Allow setting of bv->repaintAll() for nested insets in + // this row only + bool tmp = pi.base.bv->repaintAll(); // Row signature; has row changed since last paint? - lyx::size_type const row_sig = calculateRowSignature(*rit, par); - - bool cursor_on_row = isCursorOnRow(pi, pit, rit); + lyx::size_type const row_sig = calculateRowSignature(*rit, par, x, y); + bool row_has_changed = par.rowSignature()[rowno] != row_sig; - // If selection is on, the current row signature differs from + bool cursor_on_row = CursorOnRow(pi, pit, rit, text); + bool in_inset_alone_on_row = innerCursorOnRow(pi, pit, rit, + text); + + // If this is the only object on the row, we can make it wide + for (pos_type i = rit->pos() ; i != rit->endpos(); ++i) { + InsetBase* in + = const_cast(par.getInset(i)); + if (isTrueTextInset(in)) + static_cast(in)->Wide() + = in_inset_alone_on_row; + } + + // If selection is on, the current row signature differs // from cache, or cursor is inside an inset _on this row_, // then paint the row - if (repaintAll || par.rowSignature()[rowno] != row_sig - || cursor_on_row) { + if (repaintAll || row_has_changed || cursor_on_row) { // Add to row signature cache par.rowSignature()[rowno] = row_sig; @@ -781,15 +838,25 @@ void paintPar RowPainter rp(inside ? pi : nullpi, text, pit, *rit, x, y); // Clear background of this row // (if paragraph background was not cleared) - if (!repaintAll) { - pi.pain.fillRectangle(x, y - rit->ascent(), + if (!repaintAll && + (!in_inset_alone_on_row || row_has_changed)) { + pi.pain.fillRectangle(( rowno ? 0 : x - 10 ), y - rit->ascent(), pi.base.bv->workWidth(), rit->height(), text.backgroundColor()); + // If outer row has changed, force nested + // insets to repaint completely + if (row_has_changed) + pi.base.bv->repaintAll(true); } // Instrumentation for testing row cache (see also // 12 lines lower): - //lyxerr << "#"; + if (text.isMainText()) + lyxerr[Debug::PAINTING] << "#"; + else + lyxerr[Debug::PAINTING] << "[" << + repaintAll << row_has_changed << + cursor_on_row << "]"; rp.paintAppendix(); rp.paintDepthBar(); rp.paintChangeBar(); @@ -800,8 +867,10 @@ void paintPar rp.paintText(); } y += rit->descent(); + // Restore, see above + pi.base.bv->repaintAll(tmp); } - //lyxerr << "." << endl; + lyxerr[Debug::PAINTING] << "." << endl; } } // namespace anon @@ -814,8 +883,11 @@ void paintText(BufferView const & bv, ViewMetricsInfo const & vi) bool const select = bv.cursor().selection(); PainterInfo pi(const_cast(&bv), pain); - if (select || !vi.singlepar) { - // Clear background (Delegated to rows if no selection) + // Should the whole screen, including insets, be refreshed? + bool repaintAll(select || !vi.singlepar); + + if (repaintAll) { + // Clear background (if not delegated to rows) pain.fillRectangle(0, vi.y1, bv.workWidth(), vi.y2 - vi.y1, text->backgroundColor()); } @@ -826,9 +898,10 @@ void paintText(BufferView const & bv, ViewMetricsInfo const & vi) int yy = vi.y1; // draw contents for (pit_type pit = vi.p1; pit <= vi.p2; ++pit) { + bv.repaintAll(repaintAll); Paragraph const & par = text->getPar(pit); yy += par.ascent(); - paintPar(pi, *bv.text(), pit, 0, yy, select || !vi.singlepar); + paintPar(pi, *bv.text(), pit, 0, yy, repaintAll); yy += par.descent(); } @@ -865,9 +938,11 @@ void paintTextInset(LyXText const & text, PainterInfo & pi, int x, int y) // lyxerr << " paintTextInset: y: " << y << endl; y -= text.getPar(0).ascent(); + // This flag can not be set from within same inset: + bool repaintAll = pi.base.bv->repaintAll(); for (int pit = 0; pit < int(text.paragraphs().size()); ++pit) { y += text.getPar(pit).ascent(); - paintPar(pi, text, pit, x, y, true); + paintPar(pi, text, pit, x, y, repaintAll); y += text.getPar(pit).descent(); } } diff --git a/src/text3.C b/src/text3.C index 9acb2a7610..a06748a0a2 100644 --- a/src/text3.C +++ b/src/text3.C @@ -628,12 +628,16 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd) case LFUN_DELETE: if (!cur.selection()) { + if (cur.pos() == cur.paragraph().size()) + // Par boundary, force full-screen update + singleParUpdate = false; needsUpdate = Delete(cur); cur.resetAnchor(); // It is possible to make it a lot faster still // just comment out the line below... } else { cutSelection(cur, true, false); + singleParUpdate = false; } moveCursor(cur, false); break; @@ -656,6 +660,9 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd) case LFUN_BACKSPACE: if (!cur.selection()) { if (bv->owner()->getIntl().getTransManager().backspace()) { + // Par boundary, full-screen update + if (cur.pos() == 0) + singleParUpdate = false; needsUpdate = backspace(cur); cur.resetAnchor(); // It is possible to make it a lot faster still @@ -663,6 +670,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd) } } else { cutSelection(cur, true, false); + singleParUpdate = false; } bv->switchKeyMap(); break; @@ -1532,10 +1540,14 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd) if (singleParUpdate) // Inserting characters does not change par height - if (cur.bottom().paragraph().dim().height() + if (cur.bottom().paragraph().dim().height() == olddim.height()) { // if so, update _only_ this paragraph - cur.bv().update(Update::SinglePar | Update::Force); + cur.bv().update(Update::SinglePar | + Update::FitCursor | + Update::MultiParSel); + cur.noUpdate(); + return; } else needsUpdate = true; if (!needsUpdate -- 2.39.5