]> git.lyx.org Git - lyx.git/blobdiff - src/BufferView.cpp
SCons: msvc does not need this /TP option any more after we rename .C => .cpp. Also...
[lyx.git] / src / BufferView.cpp
index 071181bef7e8f3af047532a78251a6b5ad14e7f1..b7776050cd95b041b250c6ba6e1b036a5001d702 100644 (file)
@@ -63,6 +63,7 @@
 #include "frontends/alert.h"
 #include "frontends/FileDialog.h"
 #include "frontends/FontMetrics.h"
+#include "frontends/Selection.h"
 
 #include "graphics/Previews.h"
 
 #include <functional>
 #include <vector>
 
+using std::distance;
+using std::endl;
+using std::istringstream;
+using std::make_pair;
+using std::min;
+using std::max;
+using std::mem_fun_ref;
+using std::string;
+using std::vector;
+
 
 namespace lyx {
 
@@ -91,16 +102,6 @@ using support::isFileReadable;
 using support::makeDisplayPath;
 using support::package;
 
-using std::distance;
-using std::endl;
-using std::istringstream;
-using std::make_pair;
-using std::min;
-using std::max;
-using std::mem_fun_ref;
-using std::string;
-using std::vector;
-
 namespace Alert = frontend::Alert;
 
 namespace {
@@ -121,181 +122,38 @@ T * getInsetByCode(Cursor & cur, Inset::Code code)
 } // anon namespace
 
 
-BufferView::BufferView()
-       : width_(0), height_(0), buffer_(0), wh_(0),
+BufferView::BufferView(Buffer & buf)
+       : width_(0), height_(0), buffer_(buf), wh_(0),
          cursor_(*this),
          multiparsel_cache_(false), anchor_ref_(0), offset_ref_(0),
          intl_(new Intl), last_inset_(0)
 {
        xsel_cache_.set = false;
        intl_->initKeyMapper(lyxrc.use_kbmap);
-}
 
+       cursor_.push(buffer_.inset());
+       cursor_.resetAnchor();
+       buffer_.text().setCurrentFont(cursor_);
 
-BufferView::~BufferView()
-{
+       if (graphics::Previews::status() != LyXRC::PREVIEW_OFF)
+               graphics::Previews::get().generateBufferPreviews(buffer_);
 }
 
 
-Buffer * BufferView::buffer() const
+BufferView::~BufferView()
 {
-       return buffer_;
 }
 
 
-void BufferView::setBuffer(Buffer * b)
-{
-       LYXERR(Debug::INFO) << BOOST_CURRENT_FUNCTION
-                           << "[ b = " << b << "]" << endl;
-
-       if (buffer_) {
-               // Save the actual cursor position and anchor inside the
-               // buffer so that it can be restored in case we rechange
-               // to this buffer later on.
-               buffer_->saveCursor(cursor_.selectionBegin(),
-                                   cursor_.selectionEnd());
-               // update bookmark pit of the current buffer before switch
-               for (size_t i = 0; i < LyX::ref().session().bookmarks().size(); ++i) {
-                       BookmarksSection::Bookmark const & bm = LyX::ref().session().bookmarks().bookmark(i);
-                       if (buffer()->fileName() != bm.filename.absFilename())
-                               continue;
-                       // if top_id or bottom_pit, bottom_pos has been changed, update bookmark
-                       // see http://bugzilla.lyx.org/show_bug.cgi?id=3092
-                       pit_type new_pit;
-                       pos_type new_pos;
-                       int new_id;
-                       boost::tie(new_pit, new_pos, new_id) = moveToPosition(bm.bottom_pit, bm.bottom_pos, bm.top_id, bm.top_pos);
-                       if (bm.bottom_pit != new_pit || bm.bottom_pos != new_pos || bm.top_id != new_id )
-                               const_cast<BookmarksSection::Bookmark &>(bm).updatePos(new_pit, new_pos, new_id);
-               }
-               // current buffer is going to be switched-off, save cursor pos
-               // Ideally, the whole cursor stack should be saved, but session
-               // currently can only handle bottom (whole document) level pit and pos.
-               // That is to say, if a cursor is in a nested inset, it will be
-               // restore to the left of the top level inset.
-               LyX::ref().session().lastFilePos().save(FileName(buffer_->fileName()),
-                       boost::tie(cursor_.bottom().pit(), cursor_.bottom().pos()) );
-       }
-
-       // If we're quitting lyx, don't bother updating stuff
-       if (quitting) {
-               buffer_ = 0;
-               return;
-       }
-
-       //FIXME Fix for bug 3440 is here.
-       // If we are closing current buffer, switch to the first in
-       // buffer list.
-       if (!b) {
-               LYXERR(Debug::INFO) << BOOST_CURRENT_FUNCTION
-                                   << " No Buffer!" << endl;
-               // We are closing the buffer, use the first buffer as current
-               //FIXME 3440
-               // if (last_buffer_) buffer_ = last_buffer_;
-               // also check that this is in theBufferList()?
-               buffer_ = theBufferList().first();
-       } else {
-               //FIXME 3440
-               // last_buffer = buffer_;
-               // Set current buffer
-               buffer_ = b;
-       }
-
-       // Reset old cursor
-       cursor_ = Cursor(*this);
-       anchor_ref_ = 0;
-       offset_ref_ = 0;
-
-       if (!buffer_)
-               return;
-
-               LYXERR(Debug::INFO) << BOOST_CURRENT_FUNCTION
-                                   << "Buffer addr: " << buffer_ << endl;
-               cursor_.push(buffer_->inset());
-               cursor_.resetAnchor();
-               buffer_->text().setCurrentFont(cursor_);
-               if (buffer_->getCursor().size() > 0 &&
-                   buffer_->getAnchor().size() > 0)
-               {
-                       cursor_.setCursor(buffer_->getAnchor().asDocIterator(&(buffer_->inset())));
-                       cursor_.resetAnchor();
-                       cursor_.setCursor(buffer_->getCursor().asDocIterator(&(buffer_->inset())));
-                       cursor_.setSelection();
-                       // do not set selection to the new buffer because we
-                       // only paste recent selection.
-
-                       // Make sure that the restored cursor is not broken. This can happen for
-                       // example if this Buffer has been modified by another view.
-                       cursor_.fixIfBroken();
-               }
-               updateMetrics(false);
-       if (graphics::Previews::status() != LyXRC::PREVIEW_OFF)
-               graphics::Previews::get().generateBufferPreviews(*buffer_);
-}
-
-// FIXME There is now no need for this to be in BufferView. It should all
-// be moved to buffer_func.cpp. (Abdel)
-Buffer * BufferView::loadLyXFile(FileName const & filename, bool auto_open)
+Buffer & BufferView::buffer()
 {
-       // File already open?
-       if (theBufferList().exists(filename.absFilename())) {
-               docstring const file = makeDisplayPath(filename.absFilename(), 20);
-               docstring text = bformat(_("The document %1$s is already "
-                                                    "loaded.\n\nDo you want to revert "
-                                                    "to the saved version?"), file);
-               int const ret = Alert::prompt(_("Revert to saved document?"),
-                       text, 0, 1,  _("&Revert"), _("&Switch to document"));
-
-               if (ret != 0) {
-      Buffer * buf = theBufferList().getBuffer(filename.absFilename());
-                       setBuffer(buf);
-                       return buf;
-               }
-               // FIXME: should be LFUN_REVERT
-               if (!theBufferList().close(theBufferList().getBuffer(filename.absFilename()), false))
-                       return 0;
-               // Fall through to new load. (Asger)
-               buffer_ = 0;
-       }
-
-       Buffer * b = 0;
-
-       if (isFileReadable(filename)) {
-               b = theBufferList().newBuffer(filename.absFilename());
-               if (!lyx::loadLyXFile(b, filename)) {
-                       theBufferList().release(b);
-                       return 0;
-               }
-       } else {
-               docstring text = bformat(_("The document %1$s does not yet "
-                                                    "exist.\n\nDo you want to create "
-                                                    "a new document?"), from_utf8(filename.absFilename()));
-               int const ret = Alert::prompt(_("Create new document?"),
-                        text, 0, 1, _("&Create"), _("Cancel"));
-
-               if (ret == 0) {
-                       b = newFile(filename.absFilename(), string(), true);
-                       if (!b)
-                               return 0;
-               } else
-                       return 0;
-       }
-
-  if (!auto_open)
-       setBuffer(b);
-
-       return b;
+       return buffer_;
 }
 
 
-void BufferView::resize()
+Buffer const & BufferView::buffer() const
 {
-       if (!buffer_)
-               return;
-
-       LYXERR(Debug::DEBUG) << BOOST_CURRENT_FUNCTION << endl;
-
-       updateMetrics(false);
+       return buffer_;
 }
 
 
@@ -338,17 +196,11 @@ bool BufferView::update(Update::flags flags)
                << "[fitcursor = " << (flags & Update::FitCursor)
                << ", forceupdate = " << (flags & Update::Force)
                << ", singlepar = " << (flags & Update::SinglePar)
-               << "]  buffer: " << buffer_ << endl;
-
-       // Check needed to survive LyX startup
-       if (!buffer_)
-               return false;
-
-       LYXERR(Debug::WORKAREA) << "BufferView::update" << std::endl;
+               << "]  buffer: " << &buffer_ << endl;
 
        // Update macro store
        if (!(cursor().inMathed() && cursor().inMacroMode()))
-               buffer_->buildMacros();
+               buffer_.buildMacros();
 
        // Now do the first drawing step if needed. This consists on updating
        // the CoordCache in updateMetrics().
@@ -400,14 +252,7 @@ bool BufferView::update(Update::flags flags)
 
 void BufferView::updateScrollbar()
 {
-       if (!buffer_) {
-               LYXERR(Debug::DEBUG) << BOOST_CURRENT_FUNCTION
-                                    << " no text in updateScrollbar" << endl;
-               scrollbarParameters_.reset();
-               return;
-       }
-
-       Text & t = buffer_->text();
+       Text & t = buffer_.text();
        TextMetrics & tm = text_metrics_[&t];
 
        int const parsize = int(t.paragraphs().size() - 1);
@@ -472,10 +317,7 @@ void BufferView::scrollDocView(int value)
        LYXERR(Debug::GUI) << BOOST_CURRENT_FUNCTION
                           << "[ value = " << value << "]" << endl;
 
-       if (!buffer_)
-               return;
-
-       Text & t = buffer_->text();
+       Text & t = buffer_.text();
        TextMetrics & tm = text_metrics_[&t];
 
        float const bar = value / float(wh_ * t.paragraphs().size());
@@ -493,10 +335,7 @@ void BufferView::scrollDocView(int value)
 
 void BufferView::setCursorFromScrollbar()
 {
-       if (!buffer_)
-               return;
-
-       Text & t = buffer_->text();
+       Text & t = buffer_.text();
 
        int const height = 2 * defaultRowHeight();
        int const first = height;
@@ -509,14 +348,14 @@ void BufferView::setCursorFromScrollbar()
        case bv_funcs::CUR_ABOVE:
                // We reset the cursor because bv_funcs::status() does not
                // work when the cursor is within mathed.
-               cur.reset(buffer_->inset());
+               cur.reset(buffer_.inset());
                t.setCursorFromCoordinates(cur, 0, first);
                cur.clearSelection();
                break;
        case bv_funcs::CUR_BELOW:
                // We reset the cursor because bv_funcs::status() does not
                // work when the cursor is within mathed.
-               cur.reset(buffer_->inset());
+               cur.reset(buffer_.inset());
                t.setCursorFromCoordinates(cur, 0, last);
                cur.clearSelection();
                break;
@@ -524,7 +363,7 @@ void BufferView::setCursorFromScrollbar()
                int const y = bv_funcs::getPos(*this, cur, cur.boundary()).y_;
                int const newy = min(last, max(y, first));
                if (y != newy) {
-                       cur.reset(buffer_->inset());
+                       cur.reset(buffer_.inset());
                        t.setCursorFromCoordinates(cur, 0, newy);
                }
        }
@@ -548,7 +387,7 @@ void BufferView::saveBookmark(unsigned int idx)
        // pit and pos will be updated with bottom level pit/pos
        // when lyx exits.
        LyX::ref().session().bookmarks().save(
-               FileName(buffer_->fileName()),
+               FileName(buffer_.fileName()),
                cursor_.bottom().pit(),
                cursor_.bottom().pos(),
                cursor_.paragraph().id(),
@@ -570,8 +409,8 @@ boost::tuple<pit_type, pos_type, int> BufferView::moveToPosition(pit_type bottom
        // This is the case for a 'live' bookmark when unique paragraph ID
        // is used to track bookmarks.
        if (top_id > 0) {
-               ParIterator par = buffer_->getParFromID(top_id);
-               if (par != buffer_->par_iterator_end()) {
+               ParIterator par = buffer_.getParFromID(top_id);
+               if (par != buffer_.par_iterator_end()) {
                        DocIterator dit = makeDocIterator(par, min(par->size(), top_pos));
                        // Some slices of the iterator may not be
                        // reachable (e.g. closed collapsable inset)
@@ -596,8 +435,8 @@ boost::tuple<pit_type, pos_type, int> BufferView::moveToPosition(pit_type bottom
        // restoration is inaccurate. If a bookmark was within an inset,
        // it will be restored to the left of the outmost inset that contains
        // the bookmark.
-       if (static_cast<size_t>(bottom_pit) < buffer_->paragraphs().size()) {
-               DocIterator it = doc_iterator_begin(buffer_->inset());
+       if (static_cast<size_t>(bottom_pit) < buffer_.paragraphs().size()) {
+               DocIterator it = doc_iterator_begin(buffer_.inset());
                it.pit() = bottom_pit;
                it.pos() = min(bottom_pos, it.paragraph().size());
                setCursor(it);
@@ -653,10 +492,10 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd)
        switch (cmd.action) {
 
        case LFUN_UNDO:
-               flag.enabled(!buffer_->undostack().empty());
+               flag.enabled(!buffer_.undostack().empty());
                break;
        case LFUN_REDO:
-               flag.enabled(!buffer_->redostack().empty());
+               flag.enabled(!buffer_.redostack().empty());
                break;
        case LFUN_FILE_INSERT:
        case LFUN_FILE_INSERT_PLAINTEXT_PARA:
@@ -676,6 +515,7 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd)
        case LFUN_NOTE_NEXT:
        case LFUN_REFERENCE_NEXT:
        case LFUN_WORD_FIND:
+       case LFUN_WORD_REPLACE:
        case LFUN_MARK_OFF:
        case LFUN_MARK_ON:
        case LFUN_MARK_TOGGLE:
@@ -687,10 +527,6 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd)
                flag.enabled(true);
                break;
 
-       case LFUN_WORD_REPLACE:
-               flag.enabled(!cur.paragraph().isDeleted(cur.pos()));
-               break;
-
        case LFUN_LABEL_GOTO: {
                flag.enabled(!cmd.argument().empty()
                    || getInsetByCode<InsetRef>(cur, Inset::REF_CODE));
@@ -699,12 +535,12 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd)
 
        case LFUN_CHANGES_TRACK:
                flag.enabled(true);
-               flag.setOnOff(buffer_->params().trackChanges);
+               flag.setOnOff(buffer_.params().trackChanges);
                break;
 
        case LFUN_CHANGES_OUTPUT:
-               flag.enabled(buffer_);
-               flag.setOnOff(buffer_->params().outputChanges);
+               flag.enabled(true);
+               flag.setOnOff(buffer_.params().outputChanges);
                break;
 
        case LFUN_CHANGES_MERGE:
@@ -715,11 +551,11 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd)
                // In principle, these command should only be enabled if there
                // is a change in the document. However, without proper
                // optimizations, this will inevitably result in poor performance.
-               flag.enabled(buffer_);
+               flag.enabled(true);
                break;
 
        case LFUN_BUFFER_TOGGLE_COMPRESSION: {
-               flag.setOnOff(buffer_->params().compressed);
+               flag.setOnOff(buffer_.params().compressed);
                break;
        }
 
@@ -745,10 +581,6 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
                << " button[" << cmd.button() << ']'
                << endl;
 
-       // FIXME: this should not be possible.
-       if (!buffer_)
-               return Update::None;
-
        Cursor & cur = cursor_;
        // Default Update flags.
        Update::flags updateFlags = Update::Force | Update::FitCursor;
@@ -817,7 +649,9 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
        case LFUN_PARAGRAPH_GOTO: {
                int const id = convert<int>(to_utf8(cmd.argument()));
                int i = 0;
-               for (Buffer * b = buffer_; i == 0 || b != buffer_; b = theBufferList().next(b)) {
+               for (Buffer * b = &buffer_; i == 0 || b != &buffer_;
+                       b = theBufferList().next(b)) {
+
                        ParIterator par = b->getParFromID(id);
                        if (par == b->par_iterator_end()) {
                                LYXERR(Debug::INFO)
@@ -829,7 +663,7 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
                                        << " found in buffer `"
                                        << b->fileName() << "'." << endl;
 
-                               if (b == buffer_) {
+                               if (b == &buffer_) {
                                        // Set the cursor
                                        setCursor(makeDocIterator(par, 0));
                                } else {
@@ -849,20 +683,20 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
        case LFUN_OUTLINE_UP:
                toc::outline(toc::Up, cursor_);
                cursor_.text()->setCursor(cursor_, cursor_.pit(), 0);
-               updateLabels(*buffer_);
+               updateLabels(buffer_);
                break;
        case LFUN_OUTLINE_DOWN:
                toc::outline(toc::Down, cursor_);
                cursor_.text()->setCursor(cursor_, cursor_.pit(), 0);
-               updateLabels(*buffer_);
+               updateLabels(buffer_);
                break;
        case LFUN_OUTLINE_IN:
                toc::outline(toc::In, cursor_);
-               updateLabels(*buffer_);
+               updateLabels(buffer_);
                break;
        case LFUN_OUTLINE_OUT:
                toc::outline(toc::Out, cursor_);
-               updateLabels(*buffer_);
+               updateLabels(buffer_);
                break;
 
        case LFUN_NOTE_NEXT:
@@ -878,12 +712,12 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
        }
 
        case LFUN_CHANGES_TRACK:
-               buffer_->params().trackChanges = !buffer_->params().trackChanges;
+               buffer_.params().trackChanges = !buffer_.params().trackChanges;
                break;
 
        case LFUN_CHANGES_OUTPUT:
-               buffer_->params().outputChanges = !buffer_->params().outputChanges;
-               if (buffer_->params().outputChanges) {
+               buffer_.params().outputChanges = !buffer_.params().outputChanges;
+               if (buffer_.params().outputChanges) {
                        bool dvipost    = LaTeXFeatures::isAvailable("dvipost");
                        bool xcolorsoul = LaTeXFeatures::isAvailable("soul") &&
                                          LaTeXFeatures::isAvailable("xcolor");
@@ -915,30 +749,42 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
 
        case LFUN_ALL_CHANGES_ACCEPT:
                // select complete document
-               cursor_.reset(buffer_->inset());
+               cursor_.reset(buffer_.inset());
                cursor_.selHandle(true);
-               buffer_->text().cursorBottom(cursor_);
+               buffer_.text().cursorBottom(cursor_);
                // accept everything in a single step to support atomic undo
-               buffer_->text().acceptOrRejectChanges(cursor_, Text::ACCEPT);
+               buffer_.text().acceptOrRejectChanges(cursor_, Text::ACCEPT);
                break;
 
        case LFUN_ALL_CHANGES_REJECT:
                // select complete document
-               cursor_.reset(buffer_->inset());
+               cursor_.reset(buffer_.inset());
                cursor_.selHandle(true);
-               buffer_->text().cursorBottom(cursor_);
+               buffer_.text().cursorBottom(cursor_);
                // reject everything in a single step to support atomic undo
                // Note: reject does not work recursively; the user may have to repeat the operation
-               buffer_->text().acceptOrRejectChanges(cursor_, Text::REJECT);
+               buffer_.text().acceptOrRejectChanges(cursor_, Text::REJECT);
                break;
 
        case LFUN_WORD_FIND:
                find(this, cmd);
                break;
 
-       case LFUN_WORD_REPLACE:
-               replace(this, cmd);
+       case LFUN_WORD_REPLACE: {
+               bool has_deleted = false;
+               if (cur.selection()) {
+                       DocIterator beg = cur.selectionBegin();
+                       DocIterator end = cur.selectionEnd();
+                       if (beg.pit() == end.pit()) {
+                               for (pos_type p = beg.pos() ; p < end.pos() ; ++p) {
+                                       if (cur.paragraph().isDeleted(p))
+                                               has_deleted = true;
+                               }
+                       }
+               }
+               replace(this, cmd, has_deleted);
                break;
+       }
 
        case LFUN_MARK_OFF:
                cur.clearSelection();
@@ -976,7 +822,7 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
                                                Inset::BIBTEX_CODE);
                if (inset) {
                        if (inset->addDatabase(to_utf8(cmd.argument())))
-                               buffer_->updateBibfilesCache();
+                               buffer_.updateBibfilesCache();
                }
                break;
        }
@@ -988,7 +834,7 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
                                                Inset::BIBTEX_CODE);
                if (inset) {
                        if (inset->delDatabase(to_utf8(cmd.argument())))
-                               buffer_->updateBibfilesCache();
+                               buffer_.updateBibfilesCache();
                }
                break;
        }
@@ -999,8 +845,8 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
                        from = cur.selectionBegin();
                        to = cur.selectionEnd();
                } else {
-                       from = doc_iterator_begin(buffer_->inset());
-                       to = doc_iterator_end(buffer_->inset());
+                       from = doc_iterator_begin(buffer_.inset());
+                       to = doc_iterator_end(buffer_.inset());
                }
                int const count = countWords(from, to);
                docstring message;
@@ -1025,7 +871,7 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
 
        case LFUN_BUFFER_TOGGLE_COMPRESSION:
                // turn compression on/off
-               buffer_->params().compressed = !buffer_->params().compressed;
+               buffer_.params().compressed = !buffer_.params().compressed;
                break;
 
        case LFUN_NEXT_INSET_TOGGLE: {
@@ -1062,9 +908,6 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
 
 docstring const BufferView::requestSelection()
 {
-       if (!buffer_)
-               return docstring();
-
        Cursor & cur = cursor_;
 
        if (!cur.selection()) {
@@ -1087,17 +930,15 @@ docstring const BufferView::requestSelection()
 
 void BufferView::clearSelection()
 {
-       if (buffer_) {
-               cursor_.clearSelection();
-               // Clear the selection buffer. Otherwise a subsequent
-               // middle-mouse-button paste would use the selection buffer,
-               // not the more current external selection.
-               cap::clearSelection();
-               xsel_cache_.set = false;
-               // The buffer did not really change, but this causes the
-               // redraw we need because we cleared the selection above.
-               buffer_->changed();
-       }
+       cursor_.clearSelection();
+       // Clear the selection buffer. Otherwise a subsequent
+       // middle-mouse-button paste would use the selection buffer,
+       // not the more current external selection.
+       cap::clearSelection();
+       xsel_cache_.set = false;
+       // The buffer did not really change, but this causes the
+       // redraw we need because we cleared the selection above.
+       buffer_.changed();
 }
 
 
@@ -1109,9 +950,7 @@ void BufferView::workAreaResize(int width, int height)
 
        // The complete text metrics will be redone.
        text_metrics_.clear();
-
-       if (buffer_)
-               resize();
+       updateMetrics(false);
 }
 
 
@@ -1171,12 +1010,8 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
        // LFUN_FILE_OPEN generated by drag-and-drop.
        FuncRequest cmd = cmd0;
 
-       // E.g. Qt mouse press when no buffer
-       if (!buffer_)
-               return false;
-
        Cursor cur(*this);
-       cur.push(buffer_->inset());
+       cur.push(buffer_.inset());
        cur.selection() = cursor_.selection();
 
        // Either the inset under the cursor or the
@@ -1189,7 +1024,7 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
 
                // Get inset under mouse, if there is one.
                Inset const * covering_inset =
-                       getCoveringInset(buffer_->text(), cmd.x, cmd.y);
+                       getCoveringInset(buffer_.text(), cmd.x, cmd.y);
                if (covering_inset == last_inset_)
                        // Same inset, no need to do anything...
                        return false;
@@ -1239,7 +1074,7 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
        }
 
        // Build temporary cursor.
-       Inset * inset = buffer_->text().editXY(cur, cmd.x, cmd.y);
+       Inset * inset = buffer_.text().editXY(cur, cmd.x, cmd.y);
 
        // Put anchor at the same position.
        cur.resetAnchor();
@@ -1257,6 +1092,9 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
        if (!cur.result().dispatched())
                cur.dispatch(cmd);
 
+       //Do we have a selection?
+       theSelection().haveSelection(cursor().selection());
+
        // Redraw if requested and necessary.
        if (cur.result().dispatched() && cur.result().update())
                return update(cur.result().update());
@@ -1267,10 +1105,7 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
 
 void BufferView::scroll(int /*lines*/)
 {
-//     if (!buffer_)
-//             return;
-//
-//     Text const * t = &buffer_->text();
+//     Text const * t = buffer_.text();
 //     int const line_height = defaultRowHeight();
 //
 //     // The new absolute coordinate
@@ -1290,20 +1125,21 @@ void BufferView::setCursorFromRow(int row)
        int tmpid = -1;
        int tmppos = -1;
 
-       buffer_->texrow().getIdFromRow(row, tmpid, tmppos);
+       buffer_.texrow().getIdFromRow(row, tmpid, tmppos);
 
+       cursor_.reset(buffer_.inset());
        if (tmpid == -1)
-               buffer_->text().setCursor(cursor_, 0, 0);
+               buffer_.text().setCursor(cursor_, 0, 0);
        else
-               buffer_->text().setCursor(cursor_, buffer_->getParFromID(tmpid).pit(), tmppos);
+               buffer_.text().setCursor(cursor_, buffer_.getParFromID(tmpid).pit(), tmppos);
 }
 
 
 void BufferView::gotoLabel(docstring const & label)
 {
-       for (InsetIterator it = inset_iterator_begin(buffer_->inset()); it; ++it) {
+       for (InsetIterator it = inset_iterator_begin(buffer_.inset()); it; ++it) {
                vector<docstring> labels;
-               it->getLabelList(*buffer_, labels);
+               it->getLabelList(buffer_, labels);
                if (std::find(labels.begin(), labels.end(), label) != labels.end()) {
                        setCursor(it);
                        update();
@@ -1370,10 +1206,10 @@ bool BufferView::checkDepm(Cursor & cur, Cursor & old)
        if (!changed)
                return false;
 
-       updateLabels(*buffer_);
+       updateLabels(buffer_);
 
        updateMetrics(false);
-       buffer_->changed();
+       buffer_.changed();
        return true;
 }
 
@@ -1382,11 +1218,15 @@ bool BufferView::mouseSetCursor(Cursor & cur)
 {
        BOOST_ASSERT(&cur.bv() == this);
 
+        // this event will clear selection so we save selection for
+       // persistent selection
+       cap::saveSelection(cursor());
+
        // Has the cursor just left the inset?
        bool badcursor = false;
        bool leftinset = (&cursor_.inset() != &cur.inset());
        if (leftinset)
-               badcursor = cursor_.inset().notifyCursorLeaves(cursor_);
+               badcursor = notifyCursorLeaves(cursor_, cur);
 
        // do the dEPM magic if needed
        // FIXME: (1) move this to InsetText::notifyCursorLeaves?
@@ -1434,7 +1274,6 @@ void BufferView::putSelectionAt(DocIterator const & cur,
                        cursor_.setSelection(cursor_, -length);
                } else
                        cursor_.setSelection(cursor_, length);
-               cap::saveSelection(cursor_);
        }
 }
 
@@ -1466,7 +1305,7 @@ ViewMetricsInfo const & BufferView::viewMetricsInfo()
 // FIXME: We should split-up updateMetrics() for the singlepar case.
 void BufferView::updateMetrics(bool singlepar)
 {
-       Text & buftext = buffer_->text();
+       Text & buftext = buffer_.text();
        TextMetrics & tm = textMetrics(&buftext);
        pit_type size = int(buftext.paragraphs().size());
 
@@ -1475,6 +1314,15 @@ void BufferView::updateMetrics(bool singlepar)
                offset_ref_ = 0;
        }
 
+       if (!singlepar) {
+               // Clear out the position cache in case of full screen redraw,
+               coord_cache_.clear();
+       
+               // Clear out paragraph metrics to avoid having invalid metrics
+               // in the cache from paragraphs not relayouted below
+               tm.clear();
+       }
+
        // If the paragraph metrics has changed, we can not
        // use the singlepar optimisation.
        if (singlepar
@@ -1494,10 +1342,6 @@ void BufferView::updateMetrics(bool singlepar)
        if (!singlepar)
                tm.redoParagraph(pit);
 
-       // Clear out the position cache in case of full screen redraw.
-       if (!singlepar)
-               coord_cache_.clear();
-
        int y0 = tm.parMetrics(pit).ascent() - offset_ref_;
 
        // Redo paragraphs above anchor if necessary.
@@ -1590,13 +1434,10 @@ void BufferView::menuInsertLyXFile(string const & filenm)
                // Launch a file browser
                // FIXME UNICODE
                string initpath = lyxrc.document_path;
-
-               if (buffer_) {
-                       string const trypath = buffer_->filePath();
-                       // If directory is writeable, use this as default.
-                       if (isDirWriteable(FileName(trypath)))
-                               initpath = trypath;
-               }
+               string const trypath = buffer_.filePath();
+               // If directory is writeable, use this as default.
+               if (isDirWriteable(FileName(trypath)))
+                       initpath = trypath;
 
                // FIXME UNICODE
                FileDialog fileDlg(_("Select LyX document to insert"),
@@ -1636,7 +1477,7 @@ void BufferView::menuInsertLyXFile(string const & filenm)
        docstring res;
        Buffer buf("", false);
        if (lyx::loadLyXFile(&buf, FileName(filename))) {
-               ErrorList & el = buffer_->errorList("Parse");
+               ErrorList & el = buffer_.errorList("Parse");
                // Copy the inserted document error list into the current buffer one.
                el = buf.errorList("Parse");
                recordUndo(cursor_);
@@ -1648,8 +1489,8 @@ void BufferView::menuInsertLyXFile(string const & filenm)
 
        // emit message signal.
        message(bformat(res, disp_fn));
-       buffer_->errors("Parse");
-       resize();
+       buffer_.errors("Parse");
+       updateMetrics(false);
 }
 
 } // namespace lyx