X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferView.cpp;h=588dea74b47ea7aecb18c6bda57c232bb2d3148c;hb=00ec2dd10648ba3220ce97c7502897520bb85ac6;hp=edea2eb3205fffd4216a53ce189c988a62d4856e;hpb=e836cc0aacb4a90e582690ca26f61fb94fbe8280;p=lyx.git diff --git a/src/BufferView.cpp b/src/BufferView.cpp index edea2eb320..588dea74b4 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -65,6 +65,7 @@ #include "insets/InsetText.h" #include "mathed/MathData.h" +#include "mathed/InsetMathNest.h" #include "frontends/alert.h" #include "frontends/Application.h" @@ -228,7 +229,8 @@ enum ScreenUpdateStrategy { struct BufferView::Private { - Private(BufferView & bv) : update_strategy_(FullScreenUpdate), + Private(BufferView & bv) : + update_strategy_(FullScreenUpdate), update_flags_(Update::Force), wh_(0), cursor_(bv), anchor_pit_(0), anchor_ypos_(0), @@ -236,7 +238,8 @@ struct BufferView::Private last_inset_(0), clickable_inset_(false), mouse_position_cache_(), bookmark_edit_position_(-1), gui_(0), - horiz_scroll_offset_(0), repaint_caret_row_(false) + horiz_scroll_offset_(0), + caret_ascent_(0), caret_descent_(0) { xsel_cache_.set = false; } @@ -316,11 +319,11 @@ struct BufferView::Private /// at previous draw event CursorSlice last_row_slice_; - /// a slice pointing to where the cursor has been drawn after the current - /// draw() call. - CursorSlice caret_slice_; - /// indicates whether the caret slice needs to be repainted in this draw() run. - bool repaint_caret_row_; + // 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_; }; @@ -458,7 +461,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 " : ""); } } @@ -484,6 +488,16 @@ void BufferView::processUpdateFlags(Update::flags flags) updateMetrics(flags); } + // Detect whether we can only repaint a single paragraph. + // 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 + updateMetrics(flags); + } + // Then make sure that the screen contains the cursor if needed if (flags & Update::FitCursor) { if (needsFitCursor()) { @@ -494,14 +508,6 @@ 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; @@ -1367,25 +1373,45 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) break; } - case LFUN_UNDO: + case LFUN_UNDO: { dr.setMessage(_("Undo")); cur.clearSelection(); + // 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(); + CiteEngineType const enginetype = buffer().params().citeEngineType(); if (!cur.textUndo()) dr.setMessage(_("No further undo information")); - else + else { dr.screenUpdate(Update::Force | Update::FitCursor); - dr.forceBufferUpdate(); + dr.forceBufferUpdate(); + if (buffer().params().citeEngine() != engines || + buffer().params().citeEngineType() != enginetype) + buffer().invalidateCiteLabels(); + } break; + } - case LFUN_REDO: + case LFUN_REDO: { dr.setMessage(_("Redo")); cur.clearSelection(); + // 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(); + CiteEngineType const enginetype = buffer().params().citeEngineType(); if (!cur.textRedo()) dr.setMessage(_("No further redo information")); - else + else { dr.screenUpdate(Update::Force | Update::FitCursor); - dr.forceBufferUpdate(); + dr.forceBufferUpdate(); + if (buffer().params().citeEngine() != engines || + buffer().params().citeEngineType() != enginetype) + buffer().invalidateCiteLabels(); + } break; + } case LFUN_FONT_STATE: dr.setMessage(cur.currentState(false)); @@ -1637,10 +1663,8 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) InsetBibtex * inset = getInsetByCode(tmpcur, BIBTEX_CODE); if (inset) { - if (inset->addDatabase(cmd.argument())) { - buffer_.invalidateBibfileCache(); + if (inset->addDatabase(cmd.argument())) dr.forceBufferUpdate(); - } } break; } @@ -1651,10 +1675,8 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) InsetBibtex * inset = getInsetByCode(tmpcur, BIBTEX_CODE); if (inset) { - if (inset->delDatabase(cmd.argument())) { - buffer_.invalidateBibfileCache(); + if (inset->delDatabase(cmd.argument())) dr.forceBufferUpdate(); - } } break; } @@ -1667,11 +1689,12 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) from = cur.selectionBegin(); to = cur.selectionEnd(); - string newId = cmd.getArg(0); - bool fetchId=newId.empty(); //if we wait for groupId from first graphics inset + string const newId = cmd.getArg(0); + bool fetchId = newId.empty(); //if we wait for groupId from first graphics inset InsetGraphicsParams grp_par; - InsetGraphics::string2params(graphics::getGroupParams(buffer_, newId), buffer_, grp_par); + if (!fetchId) + InsetGraphics::string2params(graphics::getGroupParams(buffer_, newId), buffer_, grp_par); if (!from.nextInset()) //move to closest inset from.forwardInset(); @@ -1681,17 +1704,14 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) if (!inset) break; if (inset->lyxCode() == GRAPHICS_CODE) { - InsetGraphics * ig = inset->asInsetGraphics(); - if (!ig) - break; - InsetGraphicsParams inspar = ig->getParams(); + InsetGraphics & ig = static_cast(*inset); + InsetGraphicsParams inspar = ig.getParams(); if (fetchId) { grp_par = inspar; fetchId = false; - } else { grp_par.filename = inspar.filename; - ig->setParams(grp_par); + ig.setParams(grp_par); } } from.forwardInset(); @@ -1877,6 +1897,33 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) } + case LFUN_UNICODE_INSERT: { + if (cmd.argument().empty()) + break; + + FuncCode code = cur.inset().currentMode() == Inset::MATH_MODE ? + LFUN_MATH_INSERT : LFUN_SELF_INSERT; + int i = 0; + while (true) { + docstring const arg = from_utf8(cmd.getArg(i)); + if (arg.empty()) + break; + if (!isHex(arg)) { + LYXERR0("Not a hexstring: " << arg); + ++i; + continue; + } + char_type c = hexToInt(arg); + if (c >= 32 && c < 0x10ffff) { + LYXERR(Debug::KEY, "Inserting c: " << c); + lyx::dispatch(FuncRequest(code, docstring(1, c))); + } + ++i; + } + break; + } + + // This would be in Buffer class if only Cursor did not // require a bufferview case LFUN_INSET_FORALL: { @@ -2024,6 +2071,8 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) icp["key"] = from_utf8(arg); if (!opt1.empty()) icp["before"] = from_utf8(opt1); + icp["literal"] = + from_ascii(InsetCitation::last_literal ? "true" : "false"); string icstr = InsetCommand::params2string(icp); FuncRequest fr(LFUN_INSET_INSERT, icstr); lyx::dispatch(fr); @@ -2946,13 +2995,26 @@ 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(); - Font const font = cur.real_current_font; - frontend::FontMetrics const & fm = theFontMetrics(font); - int const asc = fm.maxAscent(); - int const des = fm.maxDescent(); + if (cur.inMathed()) { + asc = d->caret_ascent_; + des = d->caret_descent_; + } else { + Font const font = cur.real_current_font; + frontend::FontMetrics const & fm = theFontMetrics(font); + asc = fm.maxAscent(); + des = fm.maxDescent(); + } h = asc + des; p = getPos(cur); p.y_ -= asc; @@ -3019,29 +3081,6 @@ void BufferView::setCurrentRowSlice(CursorSlice const & rowSlice) } -namespace { - -bool sliceInRow(CursorSlice const & cs, Text const * text, Row const & row) -{ - /* The normal case is the last line. The previous line takes care - * of empty rows (e.g. empty paragraphs). Cursor boundary issues - * are taken care of when setting caret_slice_ in - * BufferView::draw. - */ - return !cs.empty() && cs.text() == text && cs.pit() == row.pit() - && ((row.pos() == row.endpos() && row.pos() == cs.pos()) - || (row.pos() <= cs.pos() && cs.pos() < row.endpos())); -} - -} - - -bool BufferView::needRepaint(Text const * text, Row const & row) const -{ - return d->repaint_caret_row_ && sliceInRow(d->caret_slice_, text, row); -} - - void BufferView::checkCursorScrollOffset() { CursorSlice rowSlice = d->cursor_.bottom(); @@ -3113,16 +3152,6 @@ void BufferView::draw(frontend::Painter & pain, bool paint_caret) int const y = tm.first().second->position(); PainterInfo pi(this, pain); - /** A repaint of the previous caret row is needed if there is - * caret painted on screen and either - * 1/ a new caret has to be painted at a place different from - * the existing one; - * 2/ there is no need for a caret anymore. - */ - d->repaint_caret_row_ = !d->caret_slice_.empty() && - ((paint_caret && d->cursor_.top() != d->caret_slice_) - || ! paint_caret); - // Check whether the row where the cursor lives needs to be scrolled. // Update the drawing strategy if needed. checkCursorScrollOffset(); @@ -3138,7 +3167,7 @@ void BufferView::draw(frontend::Painter & pain, bool paint_caret) if (pain.isNull()) { pi.full_repaint = true; tm.draw(pi, 0, y); - } else if (d->repaint_caret_row_) { + } else { pi.full_repaint = false; tm.draw(pi, 0, y); } @@ -3212,15 +3241,15 @@ void BufferView::draw(frontend::Painter & pain, bool paint_caret) d->update_flags_ = Update::None; } - // Remember what has just been done for the next draw() step + // If a caret has to be painted, mark its text row as dirty to + //make sure that it will be repainted on next redraw. + /* FIXME: investigate whether this can be avoided when the cursor did not + * move at all + */ if (paint_caret) { - d->caret_slice_ = d->cursor_.top(); - if (d->caret_slice_.pos() > 0 - && (d->cursor_.boundary() - || d->caret_slice_.pos() == d->caret_slice_.lastpos())) - --d->caret_slice_.pos(); - } else - d->caret_slice_ = CursorSlice(); + Row const & caret_row = d->cursor_.textRow(); + caret_row.changed(true); + } }