]> git.lyx.org Git - lyx.git/blobdiff - src/BufferView_pimpl.C
Oops...
[lyx.git] / src / BufferView_pimpl.C
index 01bbd70f642223418ad6b9b5a2931c54b1725266..cac2fb0e59a4a7cb11d29fc71c422818989e4fbb 100644 (file)
@@ -8,55 +8,44 @@
 
 #include <config.h>
 
-#ifdef __GNUG__
-#pragma implementation
-#endif
-
 #include "BufferView_pimpl.h"
-#include "frontends/WorkArea.h"
-#include "frontends/screen.h"
-#include "frontends/LyXScreenFactory.h"
-#include "frontends/WorkAreaFactory.h"
-#include "frontends/Dialogs.h"
-#include "frontends/Alert.h"
-#include "frontends/FileDialog.h"
-#include "frontends/mouse_state.h"
-#include "lyxtext.h"
-#include "lyxrow.h"
-#include "paragraph.h"
-#include "frontends/LyXView.h"
+#include "bufferlist.h"
+#include "bufferview_funcs.h"
 #include "commandtags.h"
-#include "lyxfunc.h"
 #include "debug.h"
-#include "bufferview_funcs.h"
-#include "TextCache.h"
-#include "bufferlist.h"
-#include "lyxrc.h"
-#include "intl.h"
-// added for Dispatch functions
-#include "lyx_cb.h"
-#include "lyx_main.h"
+#include "factory.h"
 #include "FloatList.h"
+#include "funcrequest.h"
 #include "gettext.h"
+#include "intl.h"
+#include "iterators.h"
+#include "lyx_cb.h" // added for Dispatch functions
+#include "lyx_main.h"
+#include "lyxfind.h"
+#include "lyxfunc.h"
+#include "lyxtext.h"
+#include "lyxrc.h"
+#include "lyxrow.h"
+#include "paragraph.h"
 #include "ParagraphParameters.h"
+#include "TextCache.h"
 #include "undo_funcs.h"
-#include "funcrequest.h"
-#include "box.h"
 
-#include "insets/insetbib.h"
-#include "insets/insettext.h"
-#include "insets/inseturl.h"
-#include "insets/insetlatexaccent.h"
-#include "insets/insettoc.h"
-#include "insets/insetref.h"
-#include "insets/insetparent.h"
-#include "insets/insetindex.h"
-#include "insets/insetinclude.h"
-#include "insets/insetcite.h"
-#include "insets/insetgraphics.h"
-#include "insets/insetmarginal.h"
-#include "insets/insetcaption.h"
 #include "insets/insetfloatlist.h"
+#include "insets/insetgraphics.h"
+#include "insets/insetinclude.h"
+#include "insets/insetref.h"
+#include "insets/insettext.h"
+
+#include "frontends/Alert.h"
+#include "frontends/Dialogs.h"
+#include "frontends/FileDialog.h"
+#include "frontends/LyXView.h"
+#include "frontends/LyXScreenFactory.h"
+#include "frontends/mouse_state.h"
+#include "frontends/screen.h"
+#include "frontends/WorkArea.h"
+#include "frontends/WorkAreaFactory.h"
 
 #include "mathed/formulabase.h"
 
@@ -68,6 +57,7 @@
 
 #include <boost/bind.hpp>
 #include <boost/signals/connection.hpp>
+#include "BoostFormat.h"
 
 #include <unistd.h>
 #include <sys/wait.h>
@@ -104,71 +94,6 @@ boost::signals::connection selectioncon;
 boost::signals::connection lostcon;
 
 
-       /**
-        * Return the on-screen dimensions of the inset at the cursor.
-        * Pre-condition: the cursor must be at an inset.
-        */
-Box insetDimensions(BufferView * bv, LyXText const & text,
-                                      LyXCursor const & cursor)
-{
-       Paragraph /*const*/ & par = *cursor.par();
-       pos_type const pos = cursor.pos();
-
-       lyx::Assert(par.getInset(pos));
-
-       Inset const & inset(*par.getInset(pos));
-
-       LyXFont const & font = text.getFont(bv->buffer(), &par, pos);
-
-       int const width = inset.width(bv, font);
-       int const inset_x = font.isVisibleRightToLeft()
-               ? (cursor.ix() - width) : cursor.ix();
-
-       return Box(
-               inset_x + inset.scroll(),
-               inset_x + width,
-               cursor.iy() - inset.ascent(bv, font),
-               cursor.iy() + inset.descent(bv, font));
-}
-
-
-/**
- * check if the given co-ordinates are inside an inset at the
- * given cursor, if one exists. If so, the inset is returned,
- * and the co-ordinates are made relative. Otherwise, 0 is returned.
- */
-Inset * checkInset(BufferView * bv, LyXText const & text,
-                                     LyXCursor const & cursor, int & x, int & y)
-{
-       pos_type const pos = cursor.pos();
-       Paragraph /*const*/ & par(*cursor.par());
-
-       if (pos >= par.size() || !par.isInset(pos)) {
-               return 0;
-       }
-
-       Inset /*const*/ * inset = par.getInset(pos);
-
-       if (!isEditableInset(inset)) 
-               return 0;
-
-       Box b = insetDimensions(bv, text, cursor);
-
-       if (!b.contained(x, y)) {
-               lyxerr[Debug::GUI] << "Missed inset at x,y " << x << "," << y
-                       << " box " << b << endl;
-               return 0;
-       }
-
-       text.setCursor(bv, &par, pos, true);
-
-       x -= b.x1;
-       // The origin of an inset is on the baseline
-       y -= text.cursor.iy();
-
-       return inset;
-}
-
 } // anon namespace
 
 
@@ -222,7 +147,7 @@ Painter & BufferView::Pimpl::painter() const
 void BufferView::Pimpl::buffer(Buffer * b)
 {
        lyxerr[Debug::INFO] << "Setting buffer in BufferView ("
-                           << b << ")" << endl;
+                           << b << ')' << endl;
        if (buffer_) {
                buffer_->delUser(bv_);
 
@@ -240,7 +165,9 @@ void BufferView::Pimpl::buffer(Buffer * b)
        // set current buffer
        buffer_ = b;
 
-       if (bufferlist.getState() == BufferList::CLOSING) return;
+       // if we're quitting lyx, don't bother updating stuff
+       if (quitting)
+               return;
 
        // if we are closing the buffer, use the first buffer as current
        if (!buffer_) {
@@ -333,7 +260,7 @@ int BufferView::Pimpl::resizeCurrentBuffer()
        bool selection = false;
        bool mark_set  = false;
 
-       owner_->prohibitInput();
+       owner_->busy(true);
 
        owner_->message(_("Formatting document..."));
 
@@ -366,6 +293,8 @@ int BufferView::Pimpl::resizeCurrentBuffer()
                        //      bv_->text->owner(bv_);
                        if (lyxerr.debugging())
                                textcache.show(lyxerr, "resizeCurrentBuffer");
+
+                       buffer_->resizeInsets(bv_);
                } else {
                        bv_->text = new LyXText(bv_);
                        bv_->text->init(bv_);
@@ -396,7 +325,7 @@ int BufferView::Pimpl::resizeCurrentBuffer()
        bv_->text->first_y = screen().topCursorVisible(bv_->text->cursor, bv_->text->first_y);
 
        switchKeyMap();
-       owner_->allowInput();
+       owner_->busy(false);
 
        updateScrollbar();
 
@@ -422,9 +351,9 @@ void BufferView::Pimpl::updateScrollbar()
        LyXText const & t = *bv_->text;
 
        lyxerr[Debug::GUI] << "Updating scrollbar: h " << t.height << ", first_y "
-               << t.first_y << ", default height " << t.defaultHeight() << endl;
+               << t.first_y << ", default height " << defaultRowHeight() << endl;
 
-       workarea().setScrollbarParams(t.height, t.first_y, t.defaultHeight());
+       workarea().setScrollbarParams(t.height, t.first_y, defaultRowHeight());
 }
 
 
@@ -432,17 +361,17 @@ void BufferView::Pimpl::scrollDocView(int value)
 {
        lyxerr[Debug::GUI] << "scrollDocView of " << value << endl;
 
-       if (!buffer_) return;
+       if (!buffer_)
+               return;
 
        screen().draw(bv_->text, bv_, value);
 
-       if (!lyxrc.cursor_follows_scrollbar) {
+       if (!lyxrc.cursor_follows_scrollbar)
                return;
-       }
 
        LyXText * vbt = bv_->text;
 
-       int const height = vbt->defaultHeight();
+       int const height = defaultRowHeight();
        int const first = static_cast<int>((bv_->text->first_y + height));
        int const last = static_cast<int>((bv_->text->first_y + workarea().workHeight() - height));
 
@@ -453,19 +382,26 @@ void BufferView::Pimpl::scrollDocView(int value)
 }
 
 
-int BufferView::Pimpl::scroll(long time)
+void BufferView::Pimpl::scroll(int lines)
 {
-       if (!buffer_)
-               return 0;
+       if (!buffer_) {
+               return;
+       }
 
        LyXText const * t = bv_->text;
+       int const line_height = defaultRowHeight();
 
-       double const diff = t->defaultHeight()
-               + double(time) * double(time) * 0.125;
+       // The new absolute coordinate
+       int new_first_y = t->first_y + lines * line_height;
 
-       scrollDocView(int(diff));
-       workarea().setScrollbarParams(t->height, t->first_y, t->defaultHeight());
-       return 0;
+       // Restrict to a valid value
+       new_first_y = std::min(t->height - 4 * line_height, new_first_y);
+       new_first_y = std::max(0, new_first_y);
+
+       scrollDocView(new_first_y);
+
+       // Update the scrollbar.
+       workarea().setScrollbarParams(t->height, t->first_y, defaultRowHeight());
 }
 
 
@@ -514,37 +450,6 @@ void BufferView::Pimpl::selectionLost()
 }
 
 
-
-Inset * BufferView::Pimpl::checkInsetHit(LyXText * text, int & x, int & y)
-{
-       int y_tmp = y + text->first_y;
-
-       LyXCursor cursor;
-       text->setCursorFromCoordinates(bv_, cursor, x, y_tmp);
-
-       Inset * inset = checkInset(bv_, *text, cursor, x, y_tmp);
-
-       if (inset) {
-               y = y_tmp;
-               return inset;
-       }
-
-       // look at previous position
-       if (cursor.pos() == 0) {
-               return 0;
-       }
-
-       // move back one
-       text->setCursor(bv_, cursor, cursor.par(), cursor.pos() - 1, true);
-
-       inset = checkInset(bv_, *text, cursor, x, y_tmp);
-       if (inset) {
-               y = y_tmp;
-       }
-       return inset;
-}
-
-
 void BufferView::Pimpl::workAreaResize()
 {
        static int work_area_width;
@@ -696,10 +601,6 @@ void BufferView::Pimpl::cursorToggle()
                return;
        }
 
-       /* FIXME */
-       extern void reapSpellchecker(void);
-       reapSpellchecker();
-
        if (!bv_->theLockingInset()) {
                screen().cursorToggle(bv_);
        } else {
@@ -718,6 +619,21 @@ bool BufferView::Pimpl::available() const
 }
 
 
+Change const BufferView::Pimpl::getCurrentChange()
+{
+       if (!bv_->buffer()->params.tracking_changes)
+               return Change(Change::UNCHANGED);
+
+       LyXText * t(bv_->getLyXText());
+
+       if (!t->selection.set())
+               return Change(Change::UNCHANGED);
+
+       LyXCursor const & cur(t->selection.start);
+       return cur.par()->lookupChangeFull(cur.pos());
+}
+
+
 void BufferView::Pimpl::beforeChange(LyXText * text)
 {
        toggleSelection();
@@ -734,8 +650,12 @@ void BufferView::Pimpl::savePosition(unsigned int i)
                                      bv_->text->cursor.pos());
        if (i > 0) {
                ostringstream str;
-               str << _("Saved bookmark") << ' ' << i;
-               owner_->message(str.str().c_str());
+#if USE_BOOST_FORMAT
+               str << boost::format(_("Saved bookmark %1$d")) % i;
+#else
+               str << _("Saved bookmark ") << i;
+#endif
+               owner_->message(STRCONV(str.str()));
        }
 }
 
@@ -766,8 +686,12 @@ void BufferView::Pimpl::restorePosition(unsigned int i)
        update(bv_->text, BufferView::SELECT | BufferView::FITCUR);
        if (i > 0) {
                ostringstream str;
-               str << _("Moved to bookmark") << ' ' << i;
-               owner_->message(str.str().c_str());
+#if USE_BOOST_FORMAT
+               str << boost::format(_("Moved to bookmark %1$d")) % i;
+#else
+               str << _("Moved to bookmark ") << i;
+#endif
+               owner_->message(STRCONV(str.str()));
        }
 }
 
@@ -943,8 +867,7 @@ void BufferView::Pimpl::MenuInsertLyXFile(string const & filen)
                                initpath = trypath;
                }
 
-               FileDialog fileDlg(bv_->owner(),
-                                  _("Select LyX document to insert"),
+               FileDialog fileDlg(_("Select LyX document to insert"),
                        LFUN_FILE_INSERT,
                        make_pair(string(_("Documents|#o#O")),
                                  string(lyxrc.document_path)),
@@ -952,7 +875,7 @@ void BufferView::Pimpl::MenuInsertLyXFile(string const & filen)
                                  string(AddPath(system_lyxdir, "examples"))));
 
                FileDialog::Result result =
-                       fileDlg.Select(initpath,
+                       fileDlg.open(initpath,
                                       _("*.lyx| LyX Documents (*.lyx)"));
 
                if (result.first == FileDialog::Later)
@@ -974,48 +897,92 @@ void BufferView::Pimpl::MenuInsertLyXFile(string const & filen)
        string const disp_fn(MakeDisplayPath(filename));
 
        ostringstream s1;
-       s1 << _("Inserting document") << ' '
-          << disp_fn << " ...";
-       owner_->message(s1.str().c_str());
+#if USE_BOOST_FORMAT
+       s1 << boost::format(_("Inserting document %1$s...")) % disp_fn;
+#else
+       s1 << _("Inserting document ") << disp_fn << _("...");
+#endif
+       owner_->message(STRCONV(s1.str()));
        bool const res = bv_->insertLyXFile(filename);
        if (res) {
                ostringstream str;
-               str << _("Document") << ' ' << disp_fn
-                   << ' ' << _("inserted.");
-               owner_->message(str.str().c_str());
+#if USE_BOOST_FORMAT
+               str << boost::format(_("Document %1$s inserted.")) % disp_fn;
+#else
+               str << _("Document ") << disp_fn << _(" inserted.");
+#endif
+               owner_->message(STRCONV(str.str()));
        } else {
                ostringstream str;
-               str << _("Could not insert document") << ' '
-                   << disp_fn;
-               owner_->message(str.str().c_str());
+#if USE_BOOST_FORMAT
+               str << boost::format(_("Could not insert document %1$s")) % disp_fn;
+#else
+               str << _("Could not insert document ") << disp_fn;
+#endif
+               owner_->message(STRCONV(str.str()));
        }
 }
 
 
-bool BufferView::Pimpl::dispatch(FuncRequest const & ev)
+void BufferView::Pimpl::trackChanges()
 {
+       Buffer * buf(bv_->buffer());
+       bool const tracking(buf->params.tracking_changes);
+
+       if (!tracking) {
+               ParIterator const end = buf->par_iterator_end();
+               for (ParIterator it = buf->par_iterator_begin(); it != end; ++it) {
+                       (*it)->trackChanges();
+               }
+               buf->params.tracking_changes = true;
+
+               // we cannot allow undos beyond the freeze point
+               buf->undostack.clear();
+       } else {
+               bv_->update(bv_->text, BufferView::SELECT | BufferView::FITCUR);
+               bv_->text->setCursor(bv_, &(*buf->paragraphs.begin()), 0);
+#warning changes FIXME
+               //moveCursorUpdate(false);
+
+               bool found = lyxfind::findNextChange(bv_);
+               if (found) {
+                       owner_->getDialogs().showMergeChanges();
+                       return;
+               }
+
+               ParIterator const end = buf->par_iterator_end();
+               for (ParIterator it = buf->par_iterator_begin(); it != end; ++it) {
+                       (*it)->untrackChanges();
+               }
+               buf->params.tracking_changes = false;
+       }
+
+       buf->redostack.clear();
+}
+
+
+bool BufferView::Pimpl::dispatch(FuncRequest const & ev_in)
+{
+       // Make sure that the cached BufferView is correct.
+       FuncRequest ev = ev_in;
+       ev.setView(bv_);
+
        lyxerr[Debug::ACTION] << "BufferView::Pimpl::Dispatch:"
-               << " action[" << ev.action <<"]"
-               << " arg[" << ev.argument << "]"
-               << " x[" << ev.x << "]"
-               << " y[" << ev.y << "]"
-               << " button[" << ev.button() << "]"
+               << " action[" << ev.action << ']'
+               << " arg[" << ev.argument << ']'
+               << " x[" << ev.x << ']'
+               << " y[" << ev.y << ']'
+               << " button[" << ev.button() << ']'
                << endl;
 
+       // e.g. Qt mouse press when no buffer
+       if (!buffer_)
+               return false;
+
        LyXTextClass const & tclass = buffer_->params.getLyXTextClass();
 
        switch (ev.action) {
 
-       case LFUN_TOC_INSERT:
-       {
-               InsetCommandParams p;
-               p.setCmdName("tableofcontents");
-               Inset * inset = new InsetTOC(p);
-               if (!insertInset(inset, tclass.defaultLayoutName()))
-                       delete inset;
-               break;
-       }
-
        case LFUN_SCROLL_INSET:
                // this is not handled here as this function is only active
                // if we have a locking_inset and that one is (or contains)
@@ -1123,25 +1090,15 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev)
                owner_->getLyXFunc().setMessage(currentState(bv_));
                break;
 
-       case LFUN_INSERT_LABEL:
-               MenuInsertLabel(bv_, ev.argument);
-               break;
-
-       case LFUN_REF_INSERT:
-               if (ev.argument.empty()) {
-                       InsetCommandParams p("ref");
-                       owner_->getDialogs().createRef(p.getAsString());
-               } else {
-                       InsetCommandParams p;
-                       p.setFromString(ev.argument);
-
-                       InsetRef * inset = new InsetRef(p, *buffer_);
-                       if (!insertInset(inset))
-                               delete inset;
-                       else
-                               updateInset(inset, true);
-               }
-               break;
+       case LFUN_INSERT_LABEL: {
+               // Try and generate a valid label
+               string const contents = ev.argument.empty() ?
+                       getPossibleLabel(*bv_) : ev.argument;
+               InsetCommandParams icp("label", contents);
+               string data = InsetCommandMailer::params2string("label", icp);
+               owner_->getDialogs().show("label", data, 0);
+       }
+       break;
 
        case LFUN_BOOKMARK_SAVE:
                savePosition(strToUnsignedInt(ev.argument));
@@ -1173,52 +1130,6 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev)
        }
        break;
 
-       case LFUN_HTMLURL:
-       case LFUN_URL:
-       {
-               InsetCommandParams p;
-               if (ev.action == LFUN_HTMLURL)
-                       p.setCmdName("htmlurl");
-               else
-                       p.setCmdName("url");
-               owner_->getDialogs().createUrl(p.getAsString());
-       }
-       break;
-
-       case LFUN_INSERT_URL:
-       {
-               InsetCommandParams p;
-               p.setFromString(ev.argument);
-
-               InsetUrl * inset = new InsetUrl(p);
-               if (!insertInset(inset))
-                       delete inset;
-               else
-                       updateInset(inset, true);
-       }
-       break;
-
-       case LFUN_INSET_CAPTION:
-       {
-               // Do we have a locking inset...
-               if (bv_->theLockingInset()) {
-                       lyxerr << "Locking inset code: "
-                              << static_cast<int>(bv_->theLockingInset()->lyxCode());
-                       InsetCaption * new_inset =
-                               new InsetCaption(buffer_->params);
-                       new_inset->setOwner(bv_->theLockingInset());
-                       new_inset->setAutoBreakRows(true);
-                       new_inset->setDrawFrame(0, InsetText::LOCKED);
-                       new_inset->setFrameColor(0, LColor::captionframe);
-                       if (insertInset(new_inset))
-                               new_inset->edit(bv_);
-                       else
-                               delete new_inset;
-               }
-       }
-       break;
-
-
        // --- accented characters ---------------------------
 
        case LFUN_UMLAUT:
@@ -1260,118 +1171,44 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev)
        case LFUN_MATH_DISPLAY:          // Open or create a displayed math inset
        case LFUN_MATH_MODE:             // Open or create an inlined math inset
        case LFUN_GREEK:                 // Insert a single greek letter
-               mathDispatch(FuncRequest(bv_, ev.action, ev.argument));
+               mathDispatch(ev);
                break;
 
-       case LFUN_CITATION_INSERT:
-       {
-               InsetCommandParams p;
-               p.setFromString(ev.argument);
-
-               InsetCitation * inset = new InsetCitation(p);
-               if (!insertInset(inset))
-                       delete inset;
-               else
-                       updateInset(inset, true);
-       }
-       break;
-
-       case LFUN_INSERT_BIBTEX:
-       {
-               // ale970405+lasgoutt970425
-               // The argument can be up to two tokens separated
-               // by a space. The first one is the bibstyle.
-               string const db = token(ev.argument, ' ', 0);
-               string bibstyle = token(ev.argument, ' ', 1);
-               if (bibstyle.empty())
-                       bibstyle = "plain";
-
-               InsetCommandParams p("BibTeX", db, bibstyle);
-               InsetBibtex * inset = new InsetBibtex(p);
-
-               if (insertInset(inset)) {
-                       if (ev.argument.empty())
-                               inset->edit(bv_);
-               } else
-                       delete inset;
-       }
-       break;
-
-       // BibTeX data bases
-       case LFUN_BIBDB_ADD:
-       {
-               InsetBibtex * inset =
-                       static_cast<InsetBibtex*>(getInsetByCode(Inset::BIBTEX_CODE));
-               if (inset) {
-                       inset->addDatabase(ev.argument);
-               }
-       }
-       break;
-
-       case LFUN_BIBDB_DEL:
-       {
-               InsetBibtex * inset =
-                       static_cast<InsetBibtex*>(getInsetByCode(Inset::BIBTEX_CODE));
-               if (inset) {
-                       inset->delDatabase(ev.argument);
-               }
-       }
-       break;
-
-       case LFUN_BIBTEX_STYLE:
-       {
-               InsetBibtex * inset =
-                       static_cast<InsetBibtex*>(getInsetByCode(Inset::BIBTEX_CODE));
-               if (inset) {
-                       inset->setOptions(ev.argument);
-               }
-       }
-       break;
-
-       case LFUN_INDEX_INSERT:
-       {
-               string entry = ev.argument;
-               if (entry.empty())
-                       entry = bv_->getLyXText()->getStringToIndex(bv_);
-
-               if (entry.empty()) {
-                       owner_->getDialogs().createIndex();
-                       break;
-               }
-
-               InsetIndex * inset = new InsetIndex(InsetCommandParams("index", entry));
+       case LFUN_INSET_APPLY: {
+               string const name = ev.getArg(0);
 
-               if (!insertInset(inset)) {
-                       delete inset;
+               InsetBase * base = owner_->getDialogs().getOpenInset(name);
+               if (base) {
+                       // This works both for 'original' and 'mathed' insets.
+                       // Note that the localDispatch performs updateInset
+                       // also.
+                       FuncRequest fr(bv_, LFUN_INSET_MODIFY, ev.argument);
+                       base->localDispatch(fr);
                } else {
-                       updateInset(inset, true);
+                       Inset * inset = createInset(ev);
+                       if (inset && insertInset(inset)) {
+                               updateInset(inset, true);
+                       } else {
+                               delete inset;
+                       }
                }
-       }
-       break;
-
-       case LFUN_INDEX_PRINT:
-       {
-               InsetCommandParams p("printindex");
-               Inset * inset = new InsetPrintIndex(p);
-               if (!insertInset(inset, tclass.defaultLayoutName()))
-                       delete inset;
-       }
-       break;
 
-       case LFUN_PARENTINSERT:
-       {
-               InsetCommandParams p("lyxparent", ev.argument);
-               Inset * inset = new InsetParent(p, *buffer_);
-               if (!insertInset(inset, tclass.defaultLayoutName()))
-                       delete inset;
+               if (name == "bibitem") {
+                       // We need to do a redraw because the maximum
+                       // InsetBibitem width could have changed
+#warning please check you mean repaint() not update(),
+#warning and whether the repaint() is needed at all
+                       bv_->repaint();
+                       bv_->fitCursor();
+               }
        }
-
        break;
 
        case LFUN_CHILD_INSERT:
        {
                InsetInclude::Params p;
-               p.cparams.setFromString(ev.argument);
+               if (!ev.argument.empty())
+                       p.cparams.setFromString(ev.argument);
                p.masterFilename_ = buffer_->fileName();
 
                InsetInclude * inset = new InsetInclude(p);
@@ -1416,6 +1253,56 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev)
        }
                break;
 
+       case LFUN_TRACK_CHANGES:
+               trackChanges();
+               break;
+
+       case LFUN_MERGE_CHANGES:
+               owner_->getDialogs().showMergeChanges();
+               break;
+
+       case LFUN_ACCEPT_ALL_CHANGES: {
+               bv_->update(bv_->text, BufferView::SELECT | BufferView::FITCUR);
+               bv_->text->setCursor(bv_, &(*bv_->buffer()->paragraphs.begin()), 0);
+#warning FIXME changes
+               //moveCursorUpdate(false);
+
+               while (lyxfind::findNextChange(bv_)) {
+                       bv_->getLyXText()->acceptChange(bv_);
+               }
+               update(bv_->text,
+                       BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE);
+               break;
+       }
+
+       case LFUN_REJECT_ALL_CHANGES: {
+               bv_->update(bv_->text, BufferView::SELECT | BufferView::FITCUR);
+               bv_->text->setCursor(bv_, &(*bv_->buffer()->paragraphs.begin()), 0);
+#warning FIXME changes
+               //moveCursorUpdate(false);
+
+               while (lyxfind::findNextChange(bv_)) {
+                       bv_->getLyXText()->rejectChange(bv_);
+               }
+               update(bv_->text,
+                       BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE);
+               break;
+       }
+
+       case LFUN_ACCEPT_CHANGE: {
+               bv_->getLyXText()->acceptChange(bv_);
+               update(bv_->text,
+                       BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE);
+               break;
+       }
+
+       case LFUN_REJECT_CHANGE: {
+               bv_->getLyXText()->rejectChange(bv_);
+               update(bv_->text,
+                       BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE);
+               break;
+       }
+
        case LFUN_UNKNOWN_ACTION:
                ev.errorMessage(N_("Unknown function!"));
                break;
@@ -1434,7 +1321,7 @@ bool BufferView::Pimpl::insertInset(Inset * inset, string const & lout)
        // inset there otherwise this is a illegal function now
        if (bv_->theLockingInset()) {
                if (bv_->theLockingInset()->insetAllowed(inset))
-                   return bv_->theLockingInset()->insertInset(bv_, inset);
+                       return bv_->theLockingInset()->insertInset(bv_, inset);
                return false;
        }