]> git.lyx.org Git - lyx.git/blobdiff - src/BufferView_pimpl.C
make boundary property an iterator property instead of a CursorSlice property
[lyx.git] / src / BufferView_pimpl.C
index 56fe22748f1a1324bd87090959aec72108a0d134..1c52d6e331492a1cd2398a980ab57fe763a184ee 100644 (file)
@@ -51,6 +51,7 @@
 #include "undo.h"
 #include "vspace.h"
 
+#include "insets/insetbibtex.h"
 #include "insets/insetref.h"
 #include "insets/insettext.h"
 
 #include "support/types.h"
 
 #include <boost/bind.hpp>
+#include <boost/current_function.hpp>
 
 #include <functional>
+#include <vector>
 
 using lyx::pos_type;
 
@@ -96,6 +99,7 @@ using std::min;
 using std::max;
 using std::string;
 using std::mem_fun_ref;
+using std::vector;
 
 
 extern BufferList bufferlist;
@@ -119,7 +123,7 @@ boost::signals::connection selectioncon;
 boost::signals::connection lostcon;
 
 
-/// Get next inset of this class from current cursor position
+/// Return an inset of this class if it exists at the current cursor position
 template <class T>
 T * getInsetByCode(LCursor & cur, InsetBase::Code code)
 {
@@ -132,7 +136,6 @@ T * getInsetByCode(LCursor & cur, InsetBase::Code code)
        return inset;
 }
 
-
 } // anon namespace
 
 
@@ -237,8 +240,8 @@ void BufferView::Pimpl::newFile(string const & filename, string const & tname,
 
 bool BufferView::Pimpl::loadLyXFile(string const & filename, bool tolastfiles)
 {
-       // get absolute path of file and add ".lyx" to the filename if
-       // necessary
+       // Get absolute path of file and add ".lyx"
+       // to the filename if necessary
        string s = FileSearch(string(), filename, "lyx");
 
        bool const found = !s.empty();
@@ -246,7 +249,7 @@ bool BufferView::Pimpl::loadLyXFile(string const & filename, bool tolastfiles)
        if (!found)
                s = filename;
 
-       // file already open?
+       // File already open?
        if (bufferlist.exists(s)) {
                string const file = MakeDisplayPath(s, 20);
                string text = bformat(_("The document %1$s is already "
@@ -317,35 +320,38 @@ Painter & BufferView::Pimpl::painter() const
 
 void BufferView::Pimpl::setBuffer(Buffer * b)
 {
-       lyxerr[Debug::INFO] << "Setting buffer in BufferView ("
-                           << b << ')' << endl;
+       lyxerr[Debug::INFO] << BOOST_CURRENT_FUNCTION
+                           << "[ b = " << b << "]" << endl;
+
        if (buffer_)
                disconnectBuffer();
 
-       // if we are closing current buffer, switch to the first in
+       // If we are closing current buffer, switch to the first in
        // buffer list.
        if (!b) {
-               lyxerr[Debug::INFO] << "  No Buffer!" << endl;
-               // we are closing the buffer, use the first buffer as current
+               lyxerr[Debug::INFO] << BOOST_CURRENT_FUNCTION
+                                   << " No Buffer!" << endl;
+               // We are closing the buffer, use the first buffer as current
                buffer_ = bufferlist.first();
                owner_->getDialogs().hideBufferDependent();
        } else {
-               // set current buffer
+               // Set current buffer
                buffer_ = b;
        }
 
-       // reset old cursor
+       // Reset old cursor
        cursor_ = LCursor(*bv_);
        anchor_ref_ = 0;
        offset_ref_ = 0;
 
 
-       // if we're quitting lyx, don't bother updating stuff
+       // If we're quitting lyx, don't bother updating stuff
        if (quitting)
                return;
 
        if (buffer_) {
-               lyxerr[Debug::INFO] << "Buffer addr: " << buffer_ << endl;
+               lyxerr[Debug::INFO] << BOOST_CURRENT_FUNCTION
+                                   << "Buffer addr: " << buffer_ << endl;
                connectBuffer(*buffer_);
 
                cursor_.push(buffer_->inset());
@@ -377,7 +383,7 @@ void BufferView::Pimpl::setBuffer(Buffer * b)
 
 void BufferView::Pimpl::resizeCurrentBuffer()
 {
-       lyxerr[Debug::DEBUG] << "resizeCurrentBuffer" << endl;
+       lyxerr[Debug::DEBUG] << BOOST_CURRENT_FUNCTION << endl;
        owner_->busy(true);
        owner_->message(_("Formatting document..."));
 
@@ -391,7 +397,7 @@ void BufferView::Pimpl::resizeCurrentBuffer()
        switchKeyMap();
        owner_->busy(false);
 
-       // reset the "Formatting..." message
+       // Reset the "Formatting..." message
        owner_->clearMessage();
 
        updateScrollbar();
@@ -401,7 +407,8 @@ void BufferView::Pimpl::resizeCurrentBuffer()
 void BufferView::Pimpl::updateScrollbar()
 {
        if (!bv_->text()) {
-               lyxerr[Debug::DEBUG] << "no text in updateScrollbar" << endl;
+               lyxerr[Debug::DEBUG] << BOOST_CURRENT_FUNCTION
+                                    << " no text in updateScrollbar" << endl;
                workarea().setScrollbarParams(0, 0, 0);
                return;
        }
@@ -413,12 +420,13 @@ void BufferView::Pimpl::updateScrollbar()
        }
 
        lyxerr[Debug::GUI]
-               << "Updating scrollbar: height: " << t.paragraphs().size()
-               << " curr par: " << bv_->cursor().bottom().pit()
+               << BOOST_CURRENT_FUNCTION
+               << " Updating scrollbar: height: " << t.paragraphs().size()
+               << " curr par: " << cursor_.bottom().pit()
                << " default height " << defaultRowHeight() << endl;
 
-       //it would be better to fix the scrollbar to understand
-       //values in [0..1] and divide everything by wh
+       // It would be better to fix the scrollbar to understand
+       // values in [0..1] and divide everything by wh
        int const wh = workarea().workHeight() / 4;
        int const h = t.getPar(anchor_ref_).height();
        workarea().setScrollbarParams(t.paragraphs().size() * wh, anchor_ref_ * wh + int(offset_ref_ * wh / float(h)), int (wh * defaultRowHeight() / float(h)));
@@ -428,7 +436,8 @@ void BufferView::Pimpl::updateScrollbar()
 
 void BufferView::Pimpl::scrollDocView(int value)
 {
-       lyxerr[Debug::GUI] << "scrollDocView of " << value << endl;
+       lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION
+                          << "[ value = " << value << "]" << endl;
 
        if (!buffer_)
                return;
@@ -453,7 +462,7 @@ void BufferView::Pimpl::scrollDocView(int value)
        int const height = 2 * defaultRowHeight();
        int const first = height;
        int const last = workarea().workHeight() - height;
-       LCursor & cur = bv_->cursor();
+       LCursor & cur = cursor_;
 
        bv_funcs::CurStatus st = bv_funcs::status(bv_, cur);
 
@@ -467,10 +476,10 @@ void BufferView::Pimpl::scrollDocView(int value)
                cur.clearSelection();
                break;
        case bv_funcs::CUR_INSIDE:
-               int const y = bv_funcs::getPos(cur).y_;
+               int const y = bv_funcs::getPos(cur, cur.boundary()).y_;
                int const newy = min(last, max(y, first));
                if (y != newy) {
-                       cur.reset(bv_->buffer()->inset());
+                       cur.reset(buffer_->inset());
                        t.setCursorFromCoordinates(cur, 0, newy);
                }
        }
@@ -478,7 +487,7 @@ void BufferView::Pimpl::scrollDocView(int value)
 }
 
 
-void BufferView::Pimpl::scroll(int lines)
+void BufferView::Pimpl::scroll(int /*lines*/)
 {
 //     if (!buffer_)
 //             return;
@@ -503,7 +512,7 @@ void BufferView::Pimpl::scroll(int lines)
 void BufferView::Pimpl::workAreaKeyPress(LyXKeySymPtr key,
                                         key_modifier::state state)
 {
-       bv_->owner()->getLyXFunc().processKeySym(key, state);
+       owner_->getLyXFunc().processKeySym(key, state);
 
        /* This is perhaps a bit of a hack. When we move
         * around, or type, it's nice to be able to see
@@ -512,10 +521,8 @@ void BufferView::Pimpl::workAreaKeyPress(LyXKeySymPtr key,
         * of the cursor. Note we cannot do this inside
         * dispatch() itself, because that's called recursively.
         */
-       if (available()) {
-               cursor_timeout.restart();
+       if (available())
                screen().showCursor(*bv_);
-       }
 }
 
 
@@ -526,7 +533,7 @@ void BufferView::Pimpl::selectionRequested()
        if (!available())
                return;
 
-       LCursor & cur = bv_->cursor();
+       LCursor & cur = cursor_;
 
        if (!cur.selection()) {
                xsel_cache_.set = false;
@@ -534,11 +541,11 @@ void BufferView::Pimpl::selectionRequested()
        }
 
        if (!xsel_cache_.set ||
-           cur.back() != xsel_cache_.cursor ||
-           cur.anchor_.back() != xsel_cache_.anchor)
+           cur.top() != xsel_cache_.cursor ||
+           cur.anchor_.top() != xsel_cache_.anchor)
        {
-               xsel_cache_.cursor = cur.back();
-               xsel_cache_.anchor = cur.anchor_.back();
+               xsel_cache_.cursor = cur.top();
+               xsel_cache_.anchor = cur.anchor_.top();
                xsel_cache_.set = cur.selection();
                sel = cur.selectionAsString(false);
                if (!sel.empty())
@@ -551,7 +558,7 @@ void BufferView::Pimpl::selectionLost()
 {
        if (available()) {
                screen().hideCursor();
-               bv_->cursor().clearSelection();
+               cursor_.clearSelection();
                xsel_cache_.set = false;
        }
 }
@@ -565,7 +572,7 @@ void BufferView::Pimpl::workAreaResize()
        bool const widthChange = workarea().workWidth() != work_area_width;
        bool const heightChange = workarea().workHeight() != work_area_height;
 
-       // update from work area
+       // Update from work area
        work_area_width = workarea().workWidth();
        work_area_height = workarea().workHeight();
 
@@ -577,7 +584,7 @@ void BufferView::Pimpl::workAreaResize()
        if (widthChange || heightChange)
                update();
 
-       // always make sure that the scrollbar is sane.
+       // Always make sure that the scrollbar is sane.
        updateScrollbar();
        owner_->updateLayoutChoice();
 }
@@ -585,54 +592,63 @@ void BufferView::Pimpl::workAreaResize()
 
 bool BufferView::Pimpl::fitCursor()
 {
-       if (bv_funcs::status(bv_, bv_->cursor()) == bv_funcs::CUR_INSIDE) {
-               LyXFont const font = bv_->cursor().getFont();
+       if (bv_funcs::status(bv_, cursor_) == bv_funcs::CUR_INSIDE) {
+               LyXFont const font = cursor_.getFont();
                int const asc = font_metrics::maxAscent(font);
                int const des = font_metrics::maxDescent(font);
-               Point p = bv_funcs::getPos(bv_->cursor());
-               if (p.y_ - asc >= 0 && p.y_ + des < bv_->workHeight())
+               Point const p = bv_funcs::getPos(cursor_, cursor_.boundary());
+               if (p.y_ - asc >= 0 && p.y_ + des < workarea().workHeight())
                        return false;
        }
-       bv_->center();
+       center();
        return true;
 }
 
 
-void BufferView::Pimpl::update(bool fitcursor, bool forceupdate)
+void BufferView::Pimpl::update(Update::flags flags)
 {
-       lyxerr << "BufferView::Pimpl::update(fc=" << fitcursor << ", fu="
-              << forceupdate << ")  buffer: " << buffer_ << endl;
-
-       // check needed to survive LyX startup
+       lyxerr[Debug::DEBUG]
+                << BOOST_CURRENT_FUNCTION
+                << "[fitcursor = " << (flags & Update::FitCursor)
+                << ", forceupdate = " << (flags & Update::Force)
+                << ", singlepar = " << (flags & Update::SinglePar)
+                << "]  buffer: " << buffer_ << endl;
+
+       // Check needed to survive LyX startup
        if (buffer_) {
-               // update macro store
+               // Update macro store
                buffer_->buildMacros();
-               // first drawing step
 
                CoordCache backup;
                std::swap(theCoords, backup);
+
+               // This, together with doneUpdating(), verifies (using
+               // asserts) that screen redraw is not called from
+               // within itself.
                theCoords.startUpdating();
-               //
+
+               // First drawing step
                ViewMetricsInfo vi = metrics();
+               bool forceupdate(flags & Update::Force);
 
-               if (fitcursor && fitCursor()) {
+               if ((flags & Update::FitCursor) && fitCursor()) {
                        forceupdate = true;
-                       vi = metrics();
+                       vi = metrics(flags & Update::SinglePar);
                }
                if (forceupdate) {
-                       // second drawing step
+                       // Second drawing step
                        screen().redraw(*bv_, vi);
-                       theCoords.doneUpdating();
                } else {
-                       // Abort updating of the coord cache - just restore the old one
+                       // Abort updating of the coord
+                       // cache - just restore the old one
                        std::swap(theCoords, backup);
                }
        } else
                screen().greyOut();
 
-       // and the scrollbar
+       // And the scrollbar
        updateScrollbar();
-       bv_->owner()->view_state_changed();
+       owner_->view_state_changed();
 }
 
 
@@ -646,8 +662,7 @@ void BufferView::Pimpl::cursorToggle()
                // have finished but are waiting to communicate this fact
                // to the rest of LyX.
                ForkedcallsController & fcc = ForkedcallsController::get();
-               if (fcc.processesCompleted())
-                       fcc.handleCompletedProcesses();
+               fcc.handleCompletedProcesses();
        }
 
        cursor_timeout.restart();
@@ -662,11 +677,11 @@ bool BufferView::Pimpl::available() const
 
 Change const BufferView::Pimpl::getCurrentChange()
 {
-       if (!bv_->buffer()->params().tracking_changes)
+       if (!buffer_->params().tracking_changes)
                return Change(Change::UNCHANGED);
 
        LyXText * text = bv_->getLyXText();
-       LCursor & cur = bv_->cursor();
+       LCursor & cur = cursor_;
 
        if (!cur.selection())
                return Change(Change::UNCHANGED);
@@ -680,10 +695,10 @@ void BufferView::Pimpl::savePosition(unsigned int i)
 {
        if (i >= saved_positions_num)
                return;
-       BOOST_ASSERT(bv_->cursor().inTexted());
+       BOOST_ASSERT(cursor_.inTexted());
        saved_positions[i] = Position(buffer_->fileName(),
-                                     bv_->cursor().paragraph().id(),
-                                     bv_->cursor().pos());
+                                     cursor_.paragraph().id(),
+                                     cursor_.pos());
        if (i > 0)
                owner_->message(bformat(_("Saved bookmark %1$d"), i));
 }
@@ -696,7 +711,7 @@ void BufferView::Pimpl::restorePosition(unsigned int i)
 
        string const fname = saved_positions[i].filename;
 
-       bv_->cursor().clearSelection();
+       cursor_.clearSelection();
 
        if (fname != buffer_->fileName()) {
                Buffer * b = 0;
@@ -704,7 +719,8 @@ void BufferView::Pimpl::restorePosition(unsigned int i)
                        b = bufferlist.getBuffer(fname);
                else {
                        b = bufferlist.newBuffer(fname);
-                       ::loadLyXFile(b, fname); // don't ask, just load it
+                       // Don't ask, just load it
+                       ::loadLyXFile(b, fname);
                }
                if (b)
                        setBuffer(b);
@@ -714,8 +730,7 @@ void BufferView::Pimpl::restorePosition(unsigned int i)
        if (par == buffer_->par_iterator_end())
                return;
 
-       bv_->text()->setCursor(bv_->cursor(), par.pit(),
-               min(par->size(), saved_positions[i].par_pos));
+       bv_->setCursor(makeDocIterator(par, min(par->size(), saved_positions[i].par_pos)));
 
        if (i > 0)
                owner_->message(bformat(_("Moved to bookmark %1$d"), i));
@@ -746,13 +761,13 @@ void BufferView::Pimpl::switchKeyMap()
 
 void BufferView::Pimpl::center()
 {
-       CursorSlice & bot = bv_->cursor().bottom();
+       CursorSlice & bot = cursor_.bottom();
        lyx::pit_type const pit = bot.pit();
        bot.text()->redoParagraph(pit);
        Paragraph const & par = bot.text()->paragraphs()[pit];
        anchor_ref_ = pit;
-       offset_ref_ = bv_funcs::coordOffset(bv_->cursor()).y_ + par.ascent()
-               - workarea().workHeight() / 2;
+       offset_ref_ = bv_funcs::coordOffset(cursor_, cursor_.boundary()).y_
+               + par.ascent() - workarea().workHeight() / 2;
 }
 
 
@@ -801,21 +816,21 @@ void BufferView::Pimpl::MenuInsertLyXFile(string const & filenm)
                }
        }
 
-       // get absolute path of file and add ".lyx" to the filename if
-       // necessary
+       // Get absolute path of file and add ".lyx"
+       // to the filename if necessary
        filename = FileSearch(string(), filename, "lyx");
 
        string const disp_fn = MakeDisplayPath(filename);
        owner_->message(bformat(_("Inserting document %1$s..."), disp_fn));
 
-       bv_->cursor().clearSelection();
-       bv_->getLyXText()->breakParagraph(bv_->cursor());
+       cursor_.clearSelection();
+       bv_->getLyXText()->breakParagraph(cursor_);
 
-       BOOST_ASSERT(bv_->cursor().inTexted());
+       BOOST_ASSERT(cursor_.inTexted());
 
        string const fname = MakeAbsPath(filename);
-       bool const res = bv_->buffer()->readFile(fname, bv_->cursor().pit());
-       bv_->resize();
+       bool const res = buffer_->readFile(fname, cursor_.pit());
+       resizeCurrentBuffer();
 
        string s = res ? _("Document %1$s inserted.")
                       : _("Could not insert document %1$s");
@@ -825,65 +840,64 @@ void BufferView::Pimpl::MenuInsertLyXFile(string const & filenm)
 
 void BufferView::Pimpl::trackChanges()
 {
-       Buffer * buf = bv_->buffer();
-       bool const tracking = buf->params().tracking_changes;
+       bool const tracking = buffer_->params().tracking_changes;
 
        if (!tracking) {
-               for_each(buf->par_iterator_begin(),
-                        buf->par_iterator_end(),
+               for_each(buffer_->par_iterator_begin(),
+                        buffer_->par_iterator_end(),
                         bind(&Paragraph::trackChanges, _1, Change::UNCHANGED));
-               buf->params().tracking_changes = true;
+               buffer_->params().tracking_changes = true;
 
-               // we cannot allow undos beyond the freeze point
-               buf->undostack().clear();
+               // We cannot allow undos beyond the freeze point
+               buffer_->undostack().clear();
        } else {
                update();
-               bv_->text()->setCursor(bv_->cursor(), 0, 0);
+               bv_->text()->setCursor(cursor_, 0, 0);
 #ifdef WITH_WARNINGS
 #warning changes FIXME
 #endif
-               bool found = lyx::find::findNextChange(bv_);
+               bool const found = lyx::find::findNextChange(bv_);
                if (found) {
                        owner_->getDialogs().show("changes");
                        return;
                }
 
-               for_each(buf->par_iterator_begin(),
-                        buf->par_iterator_end(),
+               for_each(buffer_->par_iterator_begin(),
+                        buffer_->par_iterator_end(),
                         mem_fun_ref(&Paragraph::untrackChanges));
 
-               buf->params().tracking_changes = false;
+               buffer_->params().tracking_changes = false;
        }
 
-       buf->redostack().clear();
+       buffer_->redostack().clear();
 }
 
 
 bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd0)
 {
-       lyxerr << "BufferView::Pimpl::workAreaDispatch: request: "
-         << cmd0 << std::endl;
-       // this is only called for mouse related events including
+       //lyxerr << BOOST_CURRENT_FUNCTION << "[ cmd0 " << cmd0 << "]" << endl;
+
+       // This is only called for mouse related events including
        // LFUN_FILE_OPEN generated by drag-and-drop.
        FuncRequest cmd = cmd0;
 
-       // handle drag&drop
+       // Handle drag&drop
        if (cmd.action == LFUN_FILE_OPEN) {
                owner_->dispatch(cmd);
                return true;
        }
 
-       if (!bv_->buffer())
+       if (!buffer_)
                return false;
 
        LCursor cur(*bv_);
-       cur.push(bv_->buffer()->inset());
-       cur.selection() = bv_->cursor().selection();
+       cur.push(buffer_->inset());
+       cur.selection() = cursor_.selection();
 
        // Doesn't go through lyxfunc, so we need to update
        // the layout choice etc. ourselves
 
-       // e.g. Qt mouse press when no buffer
+       // E.g. Qt mouse press when no buffer
        if (!available())
                return false;
 
@@ -893,10 +907,12 @@ bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd0)
        // surrounding LyXText will handle this event.
 
        // Build temporary cursor.
-       cmd.y = min(max(cmd.y,-1), bv_->workHeight());
+       cmd.y = min(max(cmd.y,-1), workarea().workHeight());
        InsetBase * inset = bv_->text()->editXY(cur, cmd.x, cmd.y);
-       lyxerr << " * hit inset at tip: " << inset << endl;
-       lyxerr << " * created temp cursor:" << cur << endl;
+       //lyxerr << BOOST_CURRENT_FUNCTION
+       //       << " * hit inset at tip: " << inset << endl;
+       //lyxerr << BOOST_CURRENT_FUNCTION
+       //       << " * created temp cursor:" << cur << endl;
 
        // Put anchor at the same position.
        cur.resetAnchor();
@@ -915,20 +931,23 @@ bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd0)
 
        if (cur.result().dispatched()) {
                // Redraw if requested or necessary.
-               update(cur.result().update(), cur.result().update());
+               if (cur.result().update())
+                       update(Update::FitCursor | Update::Force);
+               else
+                       update();
        }
 
-       // see workAreaKeyPress
+       // See workAreaKeyPress
        cursor_timeout.restart();
        screen().showCursor(*bv_);
 
-       // skip these when selecting
+       // Skip these when selecting
        if (cmd.action != LFUN_MOUSE_MOTION) {
                owner_->updateLayoutChoice();
                owner_->updateToolbars();
        }
 
-       // slight hack: this is only called currently when we
+       // Slight hack: this is only called currently when we
        // clicked somewhere, so we force through the display
        // of the new status here.
        owner_->clearMessage();
@@ -938,17 +957,15 @@ bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd0)
 
 FuncStatus BufferView::Pimpl::getStatus(FuncRequest const & cmd)
 {
-       Buffer * buf = bv_->buffer();
-
        FuncStatus flag;
 
        switch (cmd.action) {
 
        case LFUN_UNDO:
-               flag.enabled(!buf->undostack().empty());
+               flag.enabled(!buffer_->undostack().empty());
                break;
        case LFUN_REDO:
-               flag.enabled(!buf->redostack().empty());
+               flag.enabled(!buffer_->redostack().empty());
                break;
        case LFUN_FILE_INSERT:
        case LFUN_FILE_INSERT_ASCII_PARA:
@@ -956,30 +973,41 @@ FuncStatus BufferView::Pimpl::getStatus(FuncRequest const & cmd)
        case LFUN_FONT_STATE:
        case LFUN_INSERT_LABEL:
        case LFUN_BOOKMARK_SAVE:
-       case LFUN_REF_GOTO:
+       case LFUN_GOTO_PARAGRAPH:
+       case LFUN_GOTOERROR:
+       case LFUN_GOTONOTE:
+       case LFUN_REFERENCE_GOTO:
        case LFUN_WORD_FIND:
        case LFUN_WORD_REPLACE:
        case LFUN_MARK_OFF:
        case LFUN_MARK_ON:
        case LFUN_SETMARK:
        case LFUN_CENTER:
+       case LFUN_BIBDB_ADD:
+       case LFUN_BIBDB_DEL:
        case LFUN_WORDS_COUNT:
                flag.enabled(true);
                break;
 
+       case LFUN_LABEL_GOTO: {
+               flag.enabled(!cmd.argument.empty()
+                   || getInsetByCode<InsetRef>(cursor_, InsetBase::REF_CODE));
+               break;
+       }
+
        case LFUN_BOOKMARK_GOTO:
-               flag.enabled(bv_->isSavedPosition(convert<unsigned int>(cmd.argument)));
+               flag.enabled(isSavedPosition(convert<unsigned int>(cmd.argument)));
                break;
        case LFUN_TRACK_CHANGES:
                flag.enabled(true);
-               flag.setOnOff(buf->params().tracking_changes);
+               flag.setOnOff(buffer_->params().tracking_changes);
                break;
 
        case LFUN_OUTPUT_CHANGES: {
-               LaTeXFeatures features(*buf, buf->params(), false);
-               flag.enabled(buf && buf->params().tracking_changes
+               LaTeXFeatures features(*buffer_, buffer_->params(), false);
+               flag.enabled(buffer_ && buffer_->params().tracking_changes
                        && features.isAvailable("dvipost"));
-               flag.setOnOff(buf->params().output_changes);
+               flag.setOnOff(buffer_->params().output_changes);
                break;
        }
 
@@ -988,7 +1016,7 @@ FuncStatus BufferView::Pimpl::getStatus(FuncRequest const & cmd)
        case LFUN_REJECT_CHANGE: // what about these two
        case LFUN_ACCEPT_ALL_CHANGES:
        case LFUN_REJECT_ALL_CHANGES:
-               flag.enabled(buf && buf->params().tracking_changes);
+               flag.enabled(buffer_ && buffer_->params().tracking_changes);
                break;
        default:
                flag.enabled(false);
@@ -1001,9 +1029,11 @@ FuncStatus BufferView::Pimpl::getStatus(FuncRequest const & cmd)
 
 bool BufferView::Pimpl::dispatch(FuncRequest const & cmd)
 {
-       //lyxerr << "BufferView::Pimpl::dispatch  cmd: " << cmd << std::endl;
+       //lyxerr << BOOST_CURRENT_FUNCTION
+       //       << [ cmd = " << cmd << "]" << endl;
+
        // Make sure that the cached BufferView is correct.
-       lyxerr[Debug::ACTION] << "BufferView::Pimpl::Dispatch:"
+       lyxerr[Debug::ACTION] << BOOST_CURRENT_FUNCTION
                << " action[" << cmd.action << ']'
                << " arg[" << cmd.argument << ']'
                << " x[" << cmd.x << ']'
@@ -1011,7 +1041,7 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & cmd)
                << " button[" << cmd.button() << ']'
                << endl;
 
-       LCursor & cur = bv_->cursor();
+       LCursor & cur = cursor_;
 
        switch (cmd.action) {
 
@@ -1061,11 +1091,11 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & cmd)
                restorePosition(convert<unsigned int>(cmd.argument));
                break;
 
-       case LFUN_REF_GOTO: {
+       case LFUN_LABEL_GOTO: {
                string label = cmd.argument;
                if (label.empty()) {
                        InsetRef * inset =
-                               getInsetByCode<InsetRef>(bv_->cursor(),
+                               getInsetByCode<InsetRef>(cursor_,
                                                         InsetBase::REF_CODE);
                        if (inset) {
                                label = inset->getContents();
@@ -1078,14 +1108,49 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & cmd)
                break;
        }
 
+       case LFUN_GOTO_PARAGRAPH: {
+               int const id = convert<int>(cmd.argument);
+               ParIterator par = buffer_->getParFromID(id);
+               if (par == buffer_->par_iterator_end()) {
+                       lyxerr[Debug::INFO] << "No matching paragraph found! ["
+                                           << id << ']' << endl;
+                       break;
+               } else {
+                       lyxerr[Debug::INFO] << "Paragraph " << par->id()
+                                           << " found." << endl;
+               }
+
+               // Set the cursor
+               bv_->setCursor(makeDocIterator(par, 0));
+
+               update();
+               switchKeyMap();
+               break;
+       }
+
+       case LFUN_GOTOERROR:
+               bv_funcs::gotoInset(bv_, InsetBase::ERROR_CODE, false);
+               break;
+
+       case LFUN_GOTONOTE:
+               bv_funcs::gotoInset(bv_, InsetBase::NOTE_CODE, false);
+               break;
+
+       case LFUN_REFERENCE_GOTO: {
+               vector<InsetBase_code> tmp;
+               tmp.push_back(InsetBase::LABEL_CODE);
+               tmp.push_back(InsetBase::REF_CODE);
+               bv_funcs::gotoInset(bv_, tmp, true);
+               break;
+       }
+
        case LFUN_TRACK_CHANGES:
                trackChanges();
                break;
 
        case LFUN_OUTPUT_CHANGES: {
-               Buffer * buf = bv_->buffer();
-               bool const state = buf->params().output_changes;
-               buf->params().output_changes = !state;
+               bool const state = buffer_->params().output_changes;
+               buffer_->params().output_changes = !state;
                break;
        }
 
@@ -1094,23 +1159,23 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & cmd)
                break;
 
        case LFUN_ACCEPT_ALL_CHANGES: {
-               bv_->cursor().reset(bv_->buffer()->inset());
+               cursor_.reset(buffer_->inset());
 #ifdef WITH_WARNINGS
 #warning FIXME changes
 #endif
                while (lyx::find::findNextChange(bv_))
-                       bv_->getLyXText()->acceptChange(bv_->cursor());
+                       bv_->getLyXText()->acceptChange(cursor_);
                update();
                break;
        }
 
        case LFUN_REJECT_ALL_CHANGES: {
-               bv_->cursor().reset(bv_->buffer()->inset());
+               cursor_.reset(buffer_->inset());
 #ifdef WITH_WARNINGS
 #warning FIXME changes
 #endif
                while (lyx::find::findNextChange(bv_))
-                       bv_->getLyXText()->rejectChange(bv_->cursor());
+                       bv_->getLyXText()->rejectChange(cursor_);
                break;
        }
 
@@ -1148,17 +1213,37 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & cmd)
                break;
 
        case LFUN_CENTER:
-               bv_->center();
+               center();
                break;
 
+       case LFUN_BIBDB_ADD: {
+               LCursor tmpcur = cursor_;
+               bv_funcs::findInset(tmpcur, InsetBase::BIBTEX_CODE, false);
+               InsetBibtex * inset = getInsetByCode<InsetBibtex>(tmpcur,
+                                               InsetBase::BIBTEX_CODE);
+               if (inset)
+                       inset->addDatabase(cmd.argument);
+               break;
+       }
+
+       case LFUN_BIBDB_DEL: {
+               LCursor tmpcur = cursor_;
+               bv_funcs::findInset(tmpcur, InsetBase::BIBTEX_CODE, false);
+               InsetBibtex * inset = getInsetByCode<InsetBibtex>(tmpcur,
+                                               InsetBase::BIBTEX_CODE);
+               if (inset)
+                       inset->delDatabase(cmd.argument);
+               break;
+       }
+
        case LFUN_WORDS_COUNT: {
                DocIterator from, to;
                if (cur.selection()) {
                        from = cur.selectionBegin();
                        to = cur.selectionEnd();
                } else {
-                       from = doc_iterator_begin(bv_->buffer()->inset());
-                       to = doc_iterator_end(bv_->buffer()->inset());
+                       from = doc_iterator_begin(buffer_->inset());
+                       to = doc_iterator_end(buffer_->inset());
                }
                int const count = countWords(from, to);
                string message;
@@ -1188,9 +1273,9 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & cmd)
 }
 
 
-ViewMetricsInfo BufferView::Pimpl::metrics()
+ViewMetricsInfo BufferView::Pimpl::metrics(bool singlepar)
 {
-       // remove old position cache
+       // Remove old position cache
        theCoords.clear();
        BufferView & bv = *bv_;
        LyXText * const text = bv.text();
@@ -1202,17 +1287,22 @@ ViewMetricsInfo BufferView::Pimpl::metrics()
        lyx::pit_type const pit = anchor_ref_;
        int pit1 = pit;
        int pit2 = pit;
-       size_t npit = text->paragraphs().size();
-       lyxerr << "npit: " << npit << " pit1: " << pit1
-               << " pit2: " << pit2 << endl;
+       size_t const npit = text->paragraphs().size();
 
-       // rebreak anchor par
+       lyxerr[Debug::DEBUG]
+                << BOOST_CURRENT_FUNCTION
+                << " npit: " << npit
+                << " pit1: " << pit1
+                << " pit2: " << pit2
+                << endl;
+
+       // Rebreak anchor par
        text->redoParagraph(pit);
        int y0 = text->getPar(pit1).ascent() - offset_ref_;
 
-       // redo paragraphs above cursor if necessary
+       // Redo paragraphs above cursor if necessary
        int y1 = y0;
-       while (y1 > 0 && pit1 > 0) {
+       while (!singlepar && y1 > 0 && pit1 > 0) {
                y1 -= text->getPar(pit1).ascent();
                --pit1;
                text->redoParagraph(pit1);
@@ -1220,33 +1310,33 @@ ViewMetricsInfo BufferView::Pimpl::metrics()
        }
 
 
-       // take care of ascent of first line
+       // Take care of ascent of first line
        y1 -= text->getPar(pit1).ascent();
 
-       //normalize anchor for next time
+       // Normalize anchor for next time
        anchor_ref_ = pit1;
        offset_ref_ = -y1;
 
-       // grey at the beginning is ugly
+       // Grey at the beginning is ugly
        if (pit1 == 0 && y1 > 0) {
                y0 -= y1;
                y1 = 0;
                anchor_ref_ = 0;
        }
 
-       // redo paragraphs below cursor if necessary
+       // Redo paragraphs below cursor if necessary
        int y2 = y0;
-       while (y2 < bv.workHeight() && pit2 < int(npit) - 1) {
+       while (!singlepar && y2 < bv.workHeight() && pit2 < int(npit) - 1) {
                y2 += text->getPar(pit2).descent();
                ++pit2;
                text->redoParagraph(pit2);
                y2 += text->getPar(pit2).ascent();
        }
 
-       // take care of descent of last line
+       // Take care of descent of last line
        y2 += text->getPar(pit2).descent();
 
-       // the coordinates of all these paragraphs are correct, cache them
+       // The coordinates of all these paragraphs are correct, cache them
        int y = y1;
        for (lyx::pit_type pit = pit1; pit <= pit2; ++pit) {
                y += text->getPar(pit).ascent();
@@ -1254,6 +1344,11 @@ ViewMetricsInfo BufferView::Pimpl::metrics()
                y += text->getPar(pit).descent();
        }
 
-       lyxerr << "bv:metrics:  y1: " << y1 << " y2: " << y2 << endl;
-       return ViewMetricsInfo(pit1, pit2, y1, y2);
+       lyxerr[Debug::DEBUG]
+                << BOOST_CURRENT_FUNCTION
+                << " y1: " << y1
+                << " y2: " << y2
+                << endl;
+
+       return ViewMetricsInfo(pit1, pit2, y1, y2, singlepar);
 }