X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferView.cpp;h=84194605a59200d3a6f816f22aa40e02d73e6720;hb=a213faf20adbb99c8d76a8038c59329425812fd1;hp=af167d4821d8941813f15c8092dc1a558b7988f1;hpb=a35e512e902cc511e0b0afb0aa5f4122a18fb295;p=lyx.git diff --git a/src/BufferView.cpp b/src/BufferView.cpp index af167d4821..84194605a5 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -54,6 +54,7 @@ #include "WordLangTuple.h" #include "insets/InsetBibtex.h" +#include "insets/InsetCitation.h" #include "insets/InsetCommand.h" // ChangeRefs #include "insets/InsetExternal.h" #include "insets/InsetGraphics.h" @@ -105,6 +106,7 @@ T * getInsetByCode(Cursor const & cur, InsetCode code) return 0; } + /// Note that comparing contents can only be used for InsetCommand bool findNextInset(DocIterator & dit, vector const & codes, docstring const & contents) @@ -874,7 +876,7 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool recenter) if (tm.contains(bot_pit)) { ParagraphMetrics const & pm = tm.parMetrics(bot_pit); - LASSERT(!pm.rows().empty(), /**/); + LBUFERR(!pm.rows().empty()); // FIXME: smooth scrolling doesn't work in mathed. CursorSlice const & cs = dit.innerTextSlice(); int offset = coordOffset(dit).y_; @@ -941,7 +943,15 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool recenter) } -void BufferView::updateDocumentClass(DocumentClass const * const olddc) +void BufferView::makeDocumentClass() +{ + DocumentClassConstPtr olddc = buffer_.params().documentClassPtr(); + buffer_.params().makeDocumentClass(); + updateDocumentClass(olddc); +} + + +void BufferView::updateDocumentClass(DocumentClassConstPtr olddc) { message(_("Converting document to new document class...")); @@ -956,6 +966,7 @@ void BufferView::updateDocumentClass(DocumentClass const * const olddc) buffer_.errors("Class Switch"); } + /** Return the change status at cursor position, taking in account the * status at each level of the document iterator (a table in a deleted * footnote is deleted). @@ -1036,13 +1047,12 @@ bool BufferView::getStatus(FuncRequest const & cmd, FuncStatus & flag) break; case LFUN_FILE_INSERT_PLAINTEXT_PARA: case LFUN_FILE_INSERT_PLAINTEXT: { - bool enabled = true; docstring const fname = cmd.argument(); if (!FileName::isAbsolute(to_utf8(fname))) { flag.message(_("Absolute filename expected.")); return false; } - flag.setEnabled(enabled && cur.inTexted()); + flag.setEnabled(cur.inTexted()); break; } case LFUN_FILE_INSERT: @@ -1060,7 +1070,6 @@ bool BufferView::getStatus(FuncRequest const & cmd, FuncStatus & flag) case LFUN_WORD_FIND: case LFUN_WORD_FIND_FORWARD: case LFUN_WORD_FIND_BACKWARD: - case LFUN_WORD_FINDADV: case LFUN_WORD_REPLACE: case LFUN_MARK_OFF: case LFUN_MARK_ON: @@ -1078,6 +1087,14 @@ bool BufferView::getStatus(FuncRequest const & cmd, FuncStatus & flag) flag.setEnabled(true); break; + case LFUN_WORD_FINDADV: { + FindAndReplaceOptions opt; + istringstream iss(to_utf8(cmd.argument())); + iss >> opt; + flag.setEnabled(opt.repl_buf_name.empty() + || !buffer_.isReadonly()); + } + case LFUN_LABEL_GOTO: { flag.setEnabled(!cmd.argument().empty() || getInsetByCode(cur, REF_CODE)); @@ -1169,17 +1186,6 @@ bool BufferView::getStatus(FuncRequest const & cmd, FuncStatus & flag) break; } - // FIXME We do not really want this here, but at present we need to - // handle their dispatch here, for reasons explained there, so we'll - // handle this here, too, for consistency. - case LFUN_BRANCH_ACTIVATE: - case LFUN_BRANCH_DEACTIVATE: { - BranchList const & branchList = buffer().params().branchlist(); - docstring const branchName = cmd.argument(); - flag.setEnabled(!branchName.empty() && branchList.find(branchName)); - break; - } - default: return false; } @@ -1203,14 +1209,7 @@ void BufferView::editInset(string const & name, Inset * inset) void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) { - //lyxerr << [ cmd = " << cmd << "]" << endl; - - // Make sure that the cached BufferView is correct. - LYXERR(Debug::ACTION, " action[" << cmd.action() << ']' - << " arg[" << to_utf8(cmd.argument()) << ']' - << " x[" << cmd.x() << ']' - << " y[" << cmd.y() << ']' - << " button[" << cmd.button() << ']'); + LYXERR(Debug::ACTION, "BufferView::dispatch: cmd: " << cmd); string const argument = to_utf8(cmd.argument()); Cursor & cur = d->cursor_; @@ -1228,7 +1227,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) switch (act) { case LFUN_BUFFER_PARAMS_APPLY: { - DocumentClass const * const oldClass = buffer_.params().documentClassPtr(); + DocumentClassConstPtr olddc = buffer_.params().documentClassPtr(); cur.recordUndoFullDocument(); istringstream ss(to_utf8(cmd.argument())); Lexer lex; @@ -1239,7 +1238,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) << unknown_tokens << " unknown token" << (unknown_tokens == 1 ? "" : "s")); } - updateDocumentClass(oldClass); + updateDocumentClass(olddc); // We are most certainly here because of a change in the document // It is then better to make sure that all dialogs are in sync with @@ -1250,12 +1249,9 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) } case LFUN_LAYOUT_MODULES_CLEAR: { - DocumentClass const * const oldClass = - buffer_.params().documentClassPtr(); cur.recordUndoFullDocument(); buffer_.params().clearLayoutModules(); - buffer_.params().makeDocumentClass(); - updateDocumentClass(oldClass); + makeDocumentClass(); dr.screenUpdate(Update::Force); dr.forceBufferUpdate(); break; @@ -1263,17 +1259,15 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) case LFUN_LAYOUT_MODULE_ADD: { BufferParams const & params = buffer_.params(); - if (!params.moduleCanBeAdded(argument)) { + if (!params.layoutModuleCanBeAdded(argument)) { LYXERR0("Module `" << argument << "' cannot be added due to failed requirements or " "conflicts with installed modules."); break; } - DocumentClass const * const oldClass = params.documentClassPtr(); cur.recordUndoFullDocument(); buffer_.params().addLayoutModule(argument); - buffer_.params().makeDocumentClass(); - updateDocumentClass(oldClass); + makeDocumentClass(); dr.screenUpdate(Update::Force); dr.forceBufferUpdate(); break; @@ -1300,12 +1294,9 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) break; // Save the old, possibly modular, layout for use in conversion. - DocumentClass const * const oldDocClass = - buffer_.params().documentClassPtr(); cur.recordUndoFullDocument(); buffer_.params().setBaseClass(argument); - buffer_.params().makeDocumentClass(); - updateDocumentClass(oldDocClass); + makeDocumentClass(); dr.screenUpdate(Update::Force); dr.forceBufferUpdate(); break; @@ -1326,12 +1317,10 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) } case LFUN_LAYOUT_RELOAD: { - DocumentClass const * const oldClass = buffer_.params().documentClassPtr(); LayoutFileIndex bc = buffer_.params().baseClassID(); LayoutFileList::get().reset(bc); buffer_.params().setBaseClass(bc); - buffer_.params().makeDocumentClass(); - updateDocumentClass(oldClass); + makeDocumentClass(); dr.screenUpdate(Update::Force); dr.forceBufferUpdate(); break; @@ -1524,8 +1513,14 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) docstring const data = find2string(searched_string, true, false, fw); bool found = lyxfind(this, FuncRequest(LFUN_WORD_FIND, data)); - if (found) + if (found) { dr.screenUpdate(Update::Force | Update::FitCursor); + cur.dispatched(); + dispatched = true; + } else { + cur.undispatched(); + dispatched = false; + } break; } @@ -1537,10 +1532,14 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) lyx::dispatch(FuncRequest(LFUN_DIALOG_SHOW, "findreplace")); break; } - if (lyxfind(this, req)) + if (lyxfind(this, req)) { dr.screenUpdate(Update::Force | Update::FitCursor); - else - message(_("String not found!")); + cur.dispatched(); + dispatched = true; + } else { + cur.undispatched(); + dispatched = false; + } d->search_request_cache_ = req; break; } @@ -1562,6 +1561,11 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) if (lyxreplace(this, cmd, has_deleted)) { dr.forceBufferUpdate(); dr.screenUpdate(Update::Force | Update::FitCursor); + cur.dispatched(); + dispatched = true; + } else { + cur.undispatched(); + dispatched = false; } break; } @@ -1649,9 +1653,10 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) from = doc_iterator_begin(&buffer_); to = doc_iterator_end(&buffer_); } - int const words = countWords(from, to); - int const chars = countChars(from, to, false); - int const chars_blanks = countChars(from, to, true); + buffer_.updateStatistics(from, to); + int const words = buffer_.wordCount(); + int const chars = buffer_.charCount(false); + int const chars_blanks = buffer_.charCount(true); docstring message; if (cur.selection()) message = _("Statistics for the selection:"); @@ -1716,10 +1721,11 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) //FIXME: what to do with cur.x_target()? bool update = in_texted && cur.bv().checkDepm(cur, old); cur.finishUndo(); - if (update || cur.selection()) { - dr.screenUpdate(Update::Force | Update::FitCursor); + + if (update || cur.mark()) + dr.screenUpdate(Update::Force | Update::FitCursor); + if (update) dr.forceBufferUpdate(); - } break; } @@ -1749,6 +1755,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) } case LFUN_SCREEN_UP_SELECT: { + // FIXME: why is the algorithm different from LFUN_SCREEN_UP? cur.selHandle(true); if (isTopScreen()) { lyx::dispatch(FuncRequest(LFUN_BUFFER_BEGIN_SELECT)); @@ -1766,6 +1773,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) } case LFUN_SCREEN_DOWN_SELECT: { + // FIXME: why is the algorithm different from LFUN_SCREEN_DOWN? cur.selHandle(true); if (isBottomScreen()) { lyx::dispatch(FuncRequest(LFUN_BUFFER_END_SELECT)); @@ -1791,7 +1799,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) FuncRequest const fr = lyxaction.lookupFunc(commandstr); // an arbitrary number to limit number of iterations - const int max_iter = 10000; + const int max_iter = 100000; int iterations = 0; Cursor & cur = d->cursor_; Cursor const savecur = cur; @@ -1800,7 +1808,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) cur.forwardInset(); cur.beginUndoGroup(); while(cur && iterations < max_iter) { - Inset * ins = cur.nextInset(); + Inset * const ins = cur.nextInset(); if (!ins) break; docstring insname = ins->layoutName(); @@ -1816,7 +1824,9 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) break; insname = insname.substr(0, i); } - cur.forwardInset(); + // if we did not delete the inset, skip it + if (!cur.nextInset() || cur.nextInset() == ins) + cur.forwardInset(); } cur.endUndoGroup(); cur = savecur; @@ -1899,6 +1909,23 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) arg = token(argument, '|', 0); opt1 = token(argument, '|', 1); } + + // if our cursor is directly in front of or behind a citation inset, + // we will instead add the new key to it. + Inset * inset = cur.nextInset(); + if (!inset || inset->lyxCode() != CITE_CODE) + inset = cur.prevInset(); + if (inset && inset->lyxCode() == CITE_CODE) { + InsetCitation * icite = static_cast(inset); + if (icite->addKey(arg)) { + dr.forceBufferUpdate(); + dr.screenUpdate(Update::FitCursor | Update::SinglePar); + if (!opt1.empty()) + LYXERR0("Discarding optional argument to citation-insert."); + } + dispatched = true; + break; + } InsetCommandParams icp(CITE_CODE); icp["key"] = from_utf8(arg); if (!opt1.empty()) @@ -1946,6 +1973,7 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) cur.setCurrentFont(); dr.forceBufferUpdate(); } + break; } case LFUN_FILE_INSERT_PLAINTEXT_PARA: @@ -1959,41 +1987,6 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) break; } - // FIXME We do not really want this here, but it has to be at present - // because we need a cursor for the recordUndoFullDocument call. What - // we would really like is a recordUndoBufferParams call that did not - // need a cursor, but we do not have that yet. - // So, if this does get fixed, this code can be moved back to Buffer.cpp, - // and the corresponding code in getStatus() should be moved back, too. - case LFUN_BRANCH_ACTIVATE: - case LFUN_BRANCH_DEACTIVATE: { - BranchList & branch_list = buffer().params().branchlist(); - docstring const branch_name = cmd.argument(); - // the case without a branch name is handled elsewhere - if (branch_name.empty()) { - dispatched = false; - break; - } - Branch * branch = branch_list.find(branch_name); - if (!branch) { - LYXERR0("Branch " << branch_name << " does not exist."); - dr.setError(true); - docstring const msg = - bformat(_("Branch \"%1$s\" does not exist."), branch_name); - dr.setMessage(msg); - break; - } - bool activate = cmd.action() == LFUN_BRANCH_ACTIVATE; - if (branch->isSelected() != activate) { - branch->setSelected(activate); - cur.recordUndoFullDocument(); - dr.setError(false); - dr.screenUpdate(Update::Force); - dr.forceBufferUpdate(); - } - break; - } - default: // OK, so try the Buffer itself... buffer_.dispatch(cmd, dr); @@ -2133,7 +2126,7 @@ void BufferView::clearLastInset(Inset * inset) const { if (d->last_inset_ != inset) { LYXERR0("Wrong last_inset!"); - LASSERT(false, /**/); + LATTEST(false); } d->last_inset_ = 0; } @@ -2190,8 +2183,8 @@ void BufferView::mouseEventDispatch(FuncRequest const & cmd0) // Notify left insets if (cur != old) { - old.fixIfBroken(); - bool badcursor = notifyCursorLeavesOrEnters(old, cur); + bool badcursor = old.fixIfBroken() | cur.fixIfBroken(); + badcursor |= notifyCursorLeavesOrEnters(old, cur); if (badcursor) cursor().fixIfBroken(); } @@ -2365,7 +2358,7 @@ TextMetrics const & BufferView::textMetrics(Text const * t) const TextMetrics & BufferView::textMetrics(Text const * t) { - LASSERT(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( @@ -2422,16 +2415,19 @@ bool BufferView::checkDepm(Cursor & cur, Cursor & old) return false; d->cursor_ = cur; + + // we would rather not do this here, but it needs to be done before + // the changed() signal is sent. + buffer_.updateBuffer(); - cur.forceBufferUpdate(); - cur.screenUpdateFlags(Update::Force); + buffer_.changed(true); return true; } bool BufferView::mouseSetCursor(Cursor & cur, bool select) { - LASSERT(&cur.bv() == this, /**/); + LASSERT(&cur.bv() == this, return false); if (!select) // this event will clear selection so we save selection for @@ -2439,6 +2435,8 @@ bool BufferView::mouseSetCursor(Cursor & cur, bool select) cap::saveSelection(cursor()); d->cursor_.macroModeClose(); + // If a macro has been finalized, the cursor might have been broken + cur.fixIfBroken(); // Has the cursor just left the inset? bool const leftinset = (&d->cursor_.inset() != &cur.inset()); @@ -2670,7 +2668,7 @@ void BufferView::updateMetrics() void BufferView::insertLyXFile(FileName const & fname) { - LASSERT(d->cursor_.inTexted(), /**/); + LASSERT(d->cursor_.inTexted(), return); // Get absolute path of file and add ".lyx" // to the filename if necessary @@ -2753,7 +2751,8 @@ Point BufferView::coordOffset(DocIterator const & dit) const CursorSlice const & sl = dit[0]; TextMetrics const & tm = textMetrics(sl.text()); ParagraphMetrics const & pm = tm.parMetrics(sl.pit()); - LASSERT(!pm.rows().empty(), /**/); + + LBUFERR(!pm.rows().empty()); y -= pm.rows()[0].ascent(); #if 1 // FIXME: document this mess