]> git.lyx.org Git - lyx.git/blobdiff - src/LyXFunc.cpp
Fix crash noticed by Bennett:
[lyx.git] / src / LyXFunc.cpp
index 46929f83cb5d2fb1d048826e1e379c6b29350a7f..ef568b57e5471275cc567ac07110bcb026abd7d6 100644 (file)
@@ -43,6 +43,7 @@
 #include "Intl.h"
 #include "KeyMap.h"
 #include "Language.h"
+#include "LaTeXFeatures.h"
 #include "Lexer.h"
 #include "LyXAction.h"
 #include "lyxfind.h"
 #include "Session.h"
 #include "SpellChecker.h"
 
-#include "insets/InsetBox.h"
-#include "insets/InsetBranch.h"
-#include "insets/InsetCommand.h"
-#include "insets/InsetERT.h"
-#include "insets/InsetExternal.h"
-#include "insets/InsetFloat.h"
-#include "insets/InsetGraphics.h"
-#include "insets/InsetInclude.h"
-#include "insets/InsetListings.h"
-#include "insets/InsetNote.h"
-#include "insets/InsetPhantom.h"
-#include "insets/InsetSpace.h"
-#include "insets/InsetTabular.h"
-#include "insets/InsetVSpace.h"
-#include "insets/InsetWrap.h"
-
 #include "frontends/alert.h"
 #include "frontends/Application.h"
 #include "frontends/KeySymbol.h"
@@ -84,6 +69,7 @@
 #include "support/FileName.h"
 #include "support/filetools.h"
 #include "support/gettext.h"
+#include "support/lassert.h"
 #include "support/lstrings.h"
 #include "support/Path.h"
 #include "support/Package.h"
@@ -142,62 +128,11 @@ void reconfigure(LyXView * lv, string const & option)
                             "updated document class specifications."));
 }
 
-
-bool getLocalStatus(Cursor cursor, FuncRequest const & cmd, FuncStatus & status)
-{
-       // Try to fix cursor in case it is broken.
-       cursor.fixIfBroken();
-
-       // This is, of course, a mess. Better create a new doc iterator and use
-       // this in Inset::getStatus. This might require an additional
-       // BufferView * arg, though (which should be avoided)
-       //Cursor safe = *this;
-       bool res = false;
-       for ( ; cursor.depth(); cursor.pop()) {
-               //lyxerr << "\nCursor::getStatus: cmd: " << cmd << endl << *this << endl;
-               LASSERT(cursor.idx() <= cursor.lastidx(), /**/);
-               LASSERT(cursor.pit() <= cursor.lastpit(), /**/);
-               LASSERT(cursor.pos() <= cursor.lastpos(), /**/);
-
-               // The inset's getStatus() will return 'true' if it made
-               // a definitive decision on whether it want to handle the
-               // request or not. The result of this decision is put into
-               // the 'status' parameter.
-               if (cursor.inset().getStatus(cursor, cmd, status)) {
-                       res = true;
-                       break;
-               }
-       }
-       return res;
-}
-
-
-/** Return the change status at cursor position, taking in account the
- * status at each level of the document iterator (a table in a deleted
- * footnote is deleted).
- * When \param outer is true, the top slice is not looked at.
- */
-Change::Type lookupChangeType(DocIterator const & dit, bool outer = false)
-{
-       size_t const depth = dit.depth() - (outer ? 1 : 0);
-
-       for (size_t i = 0 ; i < depth ; ++i) {
-               CursorSlice const & slice = dit[i];
-               if (!slice.inset().inMathed()
-                   && slice.pos() < slice.paragraph().size()) {
-                       Change::Type const ch = slice.paragraph().lookupChange(slice.pos()).type;
-                       if (ch != Change::UNCHANGED)
-                               return ch;
-               }
-       }
-       return Change::UNCHANGED;
-}
-
 }
 
 
 LyXFunc::LyXFunc()
-       : lyx_view_(0), encoded_last_key(0), meta_fake_bit(NoModifier)
+       : encoded_last_key(0), meta_fake_bit(NoModifier)
 {
 }
 
@@ -209,25 +144,15 @@ void LyXFunc::initKeySequences(KeyMap * kb)
 }
 
 
-void LyXFunc::setLyXView(LyXView * lv)
-{
-       if (lyx_view_ && lyx_view_->currentBufferView() && lyx_view_ != lv)
-               // save current selection to the selection buffer to allow
-               // middle-button paste in another window
-               cap::saveSelection(lyx_view_->currentBufferView()->cursor());
-       lyx_view_ = lv;
-}
-
-
 void LyXFunc::handleKeyFunc(FuncCode action)
 {
        char_type c = encoded_last_key;
 
        if (keyseq.length())
                c = 0;
-
-       LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
-       BufferView * bv = lyx_view_->currentBufferView();
+       LyXView * lv = theApp()->currentWindow();
+       LASSERT(lv && lv->currentBufferView(), /**/);
+       BufferView * bv = lv->currentBufferView();
        bv->getIntl().getTransManager().deadkey(
                c, get_accent(action).accent, bv->cursor().innerText(),
                bv->cursor());
@@ -243,7 +168,8 @@ void LyXFunc::handleKeyFunc(FuncCode action)
 // to GuiView and be GuiView and be window dependent.
 void LyXFunc::gotoBookmark(unsigned int idx, bool openFile, bool switchToBuffer)
 {
-       LASSERT(lyx_view_, /**/);
+       LyXView * lv = theApp()->currentWindow();
+       LASSERT(lv, /**/);
        if (!theSession().bookmarks().isValid(idx))
                return;
        BookmarksSection::Bookmark const & bm = theSession().bookmarks().bookmark(idx);
@@ -268,15 +194,15 @@ void LyXFunc::gotoBookmark(unsigned int idx, bool openFile, bool switchToBuffer)
                dispatch(FuncRequest(LFUN_BOOKMARK_SAVE, "0"));
 
        // if the current buffer is not that one, switch to it.
-       if (!lyx_view_->documentBufferView()
-               || lyx_view_->documentBufferView()->buffer().fileName() != tmp.filename) {
+       if (!lv->documentBufferView()
+               || lv->documentBufferView()->buffer().fileName() != tmp.filename) {
                if (!switchToBuffer)
                        return;
                dispatch(FuncRequest(LFUN_BUFFER_SWITCH, file));
        }
 
        // moveToPosition try paragraph id first and then paragraph (pit, pos).
-       if (!lyx_view_->documentBufferView()->moveToPosition(
+       if (!lv->documentBufferView()->moveToPosition(
                tmp.bottom_pit, tmp.bottom_pos, tmp.top_id, tmp.top_pos))
                return;
 
@@ -285,7 +211,7 @@ void LyXFunc::gotoBookmark(unsigned int idx, bool openFile, bool switchToBuffer)
                return;
 
        // Cursor jump succeeded!
-       Cursor const & cur = lyx_view_->documentBufferView()->cursor();
+       Cursor const & cur = lv->documentBufferView()->cursor();
        pit_type new_pit = cur.pit();
        pos_type new_pos = cur.pos();
        int new_id = cur.paragraph().id();
@@ -304,21 +230,23 @@ void LyXFunc::processKeySym(KeySymbol const & keysym, KeyModifier state)
 {
        LYXERR(Debug::KEY, "KeySym is " << keysym.getSymbolName());
 
+       LyXView * lv = theApp()->currentWindow();
+
        // Do nothing if we have nothing (JMarc)
        if (!keysym.isOK()) {
                LYXERR(Debug::KEY, "Empty kbd action (probably composing)");
-               lyx_view_->restartCursor();
+               lv->restartCursor();
                return;
        }
 
        if (keysym.isModifier()) {
                LYXERR(Debug::KEY, "isModifier true");
-               if (lyx_view_)
-                       lyx_view_->restartCursor();
+               if (lv)
+                       lv->restartCursor();
                return;
        }
 
-       //Encoding const * encoding = lyx_view_->documentBufferView()->cursor().getEncoding();
+       //Encoding const * encoding = lv->documentBufferView()->cursor().getEncoding();
        //encoded_last_key = keysym.getISOEncoded(encoding ? encoding->name() : "");
        // FIXME: encoded_last_key shadows the member variable of the same
        // name. Is that intended?
@@ -355,7 +283,7 @@ void LyXFunc::processKeySym(KeySymbol const & keysym, KeyModifier state)
        // num_bytes == 0? (Lgb)
 
        if (keyseq.length() > 1)
-               lyx_view_->message(keyseq.print(KeySequence::ForGui));
+               lv->message(keyseq.print(KeySequence::ForGui));
 
 
        // Maybe user can only reach the key via holding down shift.
@@ -376,8 +304,8 @@ void LyXFunc::processKeySym(KeySymbol const & keysym, KeyModifier state)
                                           FuncRequest::KEYBOARD);
                } else {
                        LYXERR(Debug::KEY, "Unknown, !isText() - giving up");
-                       lyx_view_->message(_("Unknown function."));
-                       lyx_view_->restartCursor();
+                       lv->message(_("Unknown function."));
+                       lv->restartCursor();
                        return;
                }
        }
@@ -391,7 +319,7 @@ void LyXFunc::processKeySym(KeySymbol const & keysym, KeyModifier state)
                }
        } else {
                dispatch(func);
-               if (!lyx_view_)
+               if (!lv)
                        return;
        }
 }
@@ -402,24 +330,6 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
        //lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl;
        FuncStatus flag;
 
-       /* In LyX/Mac, when a dialog is open, the menus of the
-          application can still be accessed without giving focus to
-          the main window. In this case, we want to disable the menu
-          entries that are buffer or view-related.
-
-          If this code is moved somewhere else (like in
-          GuiView::getStatus), then several functions will not be
-          handled correctly.
-       */
-       frontend::LyXView * lv = 0;
-       Buffer * buf = 0;
-       if (lyx_view_ 
-           && (cmd.origin != FuncRequest::MENU || lyx_view_->hasFocus())) {
-               lv = lyx_view_;
-               if (lyx_view_->documentBufferView())
-                       buf = &lyx_view_->documentBufferView()->buffer();
-       }
-
        if (cmd.action == LFUN_NOACTION) {
                flag.message(from_utf8(N_("Nothing to do")));
                flag.setEnabled(false);
@@ -447,15 +357,6 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
                return flag;
        }
 
-       // Check whether we need a buffer
-       if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
-               // no, exit directly
-               flag.message(from_utf8(N_("Command not allowed with"
-                                   "out any document open")));
-               flag.setEnabled(false);
-               return flag;
-       }
-
        // I would really like to avoid having this switch and rather try to
        // encode this in the function itself.
        // -- And I'd rather let an inset decide which LFUNs it is willing
@@ -463,12 +364,6 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
        bool enable = true;
        switch (cmd.action) {
 
-       case LFUN_CITATION_INSERT: {
-               FuncRequest fr(LFUN_INSET_INSERT, "citation");
-               enable = getStatus(fr).enabled();
-               break;
-       }
-       
        // This could be used for the no-GUI version. The GUI version is handled in
        // LyXView::getStatus(). See above.
        /*
@@ -480,24 +375,6 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
        }
        */
 
-       case LFUN_BUFFER_WRITE_ALL: {
-               // We enable the command only if there are some modified buffers
-               Buffer * first = theBufferList().first();
-               enable = false;
-               if (!first)
-                       break;
-               Buffer * b = first;
-               // We cannot use a for loop as the buffer list is a cycle.
-               do {
-                       if (!b->isClean()) {
-                               enable = true;
-                               break;
-                       }
-                       b = theBufferList().next(b);
-               } while (b != first); 
-               break;
-       }
-
        case LFUN_BOOKMARK_GOTO: {
                const unsigned int num = convert<unsigned int>(to_utf8(cmd.argument()));
                enable = theSession().bookmarks().isValid(num);
@@ -558,22 +435,14 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
        case LFUN_CANCEL:
        case LFUN_META_PREFIX:
        case LFUN_RECONFIGURE:
-       case LFUN_HELP_OPEN:
        case LFUN_DROP_LAYOUTS_CHOICE:
        case LFUN_SERVER_GET_FILENAME:
        case LFUN_SERVER_NOTIFY:
-       case LFUN_SERVER_GOTO_FILE_ROW:
        case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
        case LFUN_REPEAT:
        case LFUN_PREFERENCES_SAVE:
        case LFUN_INSET_EDIT:
-       case LFUN_TEXTCLASS_APPLY:
-       case LFUN_TEXTCLASS_LOAD:
        case LFUN_BUFFER_SAVE_AS_DEFAULT:
-       case LFUN_BUFFER_PARAMS_APPLY:
-       case LFUN_LAYOUT_MODULES_CLEAR:
-       case LFUN_LAYOUT_MODULE_ADD:
-       case LFUN_LAYOUT_RELOAD:
        case LFUN_LYXRC_APPLY:
                // these are handled in our dispatch()
                break;
@@ -587,6 +456,7 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
                        break;
 
                // Does the view know something?
+               LyXView * lv = theApp()->currentWindow();
                if (!lv) {
                        enable = false;
                        break;
@@ -601,16 +471,8 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
                        enable = false;
                        break;
                }
-               // Is this a function that acts on inset at point?
-               Inset * inset = bv->cursor().nextInset();
-               if (lyxaction.funcHasFlag(cmd.action, LyXAction::AtPoint)
-                   && inset && inset->getStatus(bv->cursor(), cmd, flag))
-                       break;
-
-               bool decided = getLocalStatus(bv->cursor(), cmd, flag);
-               if (!decided)
-                       // try the BufferView
-                       decided = bv->getStatus(cmd, flag);
+               // try the BufferView
+               bool decided = bv->getStatus(cmd, flag);
                if (!decided)
                        // try the Buffer
                        decided = bv->buffer().getStatus(cmd, flag);
@@ -622,24 +484,6 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
        if (!enable)
                flag.setEnabled(false);
 
-       // Can we use a readonly buffer?
-       if (buf && buf->isReadonly()
-           && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
-           && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
-               flag.message(from_utf8(N_("Document is read-only")));
-               flag.setEnabled(false);
-       }
-
-       // Are we in a DELETED change-tracking region?
-       if (lyx_view_ && lyx_view_->documentBufferView()
-               && (lookupChangeType(lyx_view_->documentBufferView()->cursor(), true)
-                   == Change::DELETED)
-           && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
-           && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
-               flag.message(from_utf8(N_("This portion of the document is deleted.")));
-               flag.setEnabled(false);
-       }
-
        // the default error message if we disable the command
        if (!flag.enabled() && flag.message().empty())
                flag.message(from_utf8(N_("Command disabled")));
@@ -650,26 +494,6 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
 
 namespace {
 
-bool loadLayoutFile(string const & name, string const & buf_path)
-{
-       if (!LayoutFileList::get().haveClass(name)) {
-               lyxerr << "Document class \"" << name
-                      << "\" does not exist."
-                      << endl;
-               return false;
-       }
-
-       LayoutFile & tc = LayoutFileList::get()[name];
-       if (!tc.load(buf_path)) {
-               docstring s = bformat(_("The document class %1$s "
-                                  "could not be loaded."), from_utf8(name));
-               Alert::error(_("Could not load class"), s);
-               return false;
-       }
-       return true;
-}
-
-
 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
 
 } //namespace anon
@@ -691,6 +515,8 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
        //This is done unless explicitely requested otherwise
        Update::flags updateFlags = Update::FitCursor;
 
+       LyXView * lv = theApp()->currentWindow();
+
        FuncStatus const flag = getStatus(cmd);
        if (!flag.enabled()) {
                // We cannot use this function here
@@ -698,24 +524,19 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
                       << lyxaction.getActionName(action)
                       << " [" << action << "] is disabled at this location");
                setErrorMessage(flag.message());
-               if (lyx_view_)
-                       lyx_view_->restartCursor();
+               if (lv)
+                       lv->restartCursor();
        } else {
-               Buffer * buffer = 0;
-               if (lyx_view_ && lyx_view_->currentBufferView())
-                       buffer = &lyx_view_->currentBufferView()->buffer();
                switch (action) {
 
                case LFUN_COMMAND_PREFIX:
-                       LASSERT(lyx_view_, /**/);
-                       lyx_view_->message(keyseq.printOptions(true));
+                       dispatch(FuncRequest(LFUN_MESSAGE, keyseq.printOptions(true)));
                        break;
 
                case LFUN_CANCEL:
-                       LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
                        keyseq.reset();
                        meta_fake_bit = NoModifier;
-                       if (buffer)
+                       if (lv && lv->currentBufferView())
                                // cancel any selection
                                dispatch(FuncRequest(LFUN_MARK_OFF));
                        setMessage(from_ascii(N_("Cancel")));
@@ -729,238 +550,24 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
                // --- Menus -----------------------------------------------
                case LFUN_RECONFIGURE:
                        // argument is any additional parameter to the configure.py command
-                       reconfigure(lyx_view_, argument);
+                       reconfigure(lv, argument);
                        break;
 
-               case LFUN_HELP_OPEN: {
-                       if (lyx_view_ == 0)
-                               theApp()->dispatch(FuncRequest(LFUN_WINDOW_NEW));
-                       string const arg = argument;
-                       if (arg.empty()) {
-                               setErrorMessage(from_utf8(N_("Missing argument")));
-                               break;
-                       }
-                       FileName fname = i18nLibFileSearch("doc", arg, "lyx");
-                       if (fname.empty()) 
-                               fname = i18nLibFileSearch("examples", arg, "lyx");
-
-                       if (fname.empty()) {
-                               lyxerr << "LyX: unable to find documentation file `"
-                                                        << arg << "'. Bad installation?" << endl;
-                               break;
-                       }
-                       lyx_view_->message(bformat(_("Opening help file %1$s..."),
-                               makeDisplayPath(fname.absFilename())));
-                       Buffer * buf = lyx_view_->loadDocument(fname, false);
-                       if (buf) {
-                               buf->updateLabels();
-                               lyx_view_->setBuffer(buf);
-                               buf->errors("Parse");
-                       }
-                       updateFlags = Update::None;
-                       break;
-               }
-
                // --- lyxserver commands ----------------------------
-               case LFUN_SERVER_GET_FILENAME:
-                       LASSERT(lyx_view_ && buffer, /**/);
-                       setMessage(from_utf8(buffer->absFileName()));
-                       LYXERR(Debug::INFO, "FNAME["
-                               << buffer->absFileName() << ']');
+               case LFUN_SERVER_GET_FILENAME: {
+                       LASSERT(lv && lv->documentBufferView(), return);
+                       docstring const fname = from_utf8(
+                               lv->documentBufferView()->buffer().absFileName());
+                       setMessage(fname);
+                       LYXERR(Debug::INFO, "FNAME[" << fname << ']');
                        break;
-
+               }
                case LFUN_SERVER_NOTIFY:
                        dispatch_buffer = keyseq.print(KeySequence::Portable);
                        theServer().notifyClient(to_utf8(dispatch_buffer));
                        break;
 
-               case LFUN_SERVER_GOTO_FILE_ROW: {
-                       LASSERT(lyx_view_, /**/);
-                       string file_name;
-                       int row;
-                       istringstream is(argument);
-                       is >> file_name >> row;
-                       file_name = os::internal_path(file_name);
-                       Buffer * buf = 0;
-                       bool loaded = false;
-                       string const abstmp = package().temp_dir().absFilename();
-                       string const realtmp = package().temp_dir().realPath();
-                       // We have to use os::path_prefix_is() here, instead of
-                       // simply prefixIs(), because the file name comes from
-                       // an external application and may need case adjustment.
-                       if (os::path_prefix_is(file_name, abstmp, os::CASE_ADJUSTED)
-                           || os::path_prefix_is(file_name, realtmp, os::CASE_ADJUSTED)) {
-                               // Needed by inverse dvi search. If it is a file
-                               // in tmpdir, call the apropriated function.
-                               // If tmpdir is a symlink, we may have the real
-                               // path passed back, so we correct for that.
-                               if (!prefixIs(file_name, abstmp))
-                                       file_name = subst(file_name, realtmp, abstmp);
-                               buf = theBufferList().getBufferFromTmp(file_name);
-                       } else {
-                               // Must replace extension of the file to be .lyx
-                               // and get full path
-                               FileName const s = fileSearch(string(), changeExtension(file_name, ".lyx"), "lyx");
-                               // Either change buffer or load the file
-                               if (theBufferList().exists(s))
-                                       buf = theBufferList().getBuffer(s);
-                               else if (s.exists()) {
-                                       buf = lyx_view_->loadDocument(s);
-                                       loaded = true;
-                               } else
-                                       lyx_view_->message(bformat(
-                                               _("File does not exist: %1$s"),
-                                               makeDisplayPath(file_name)));
-                       }
-
-                       if (!buf) {
-                               updateFlags = Update::None;
-                               break;
-                       }
-
-                       buf->updateLabels();
-                       lyx_view_->setBuffer(buf);
-                       lyx_view_->documentBufferView()->setCursorFromRow(row);
-                       if (loaded)
-                               buf->errors("Parse");
-                       updateFlags = Update::FitCursor;
-                       break;
-               }
-
-
-               case LFUN_DIALOG_SHOW_NEW_INSET: {
-                       LASSERT(lyx_view_, /**/);
-                       string const name = cmd.getArg(0);
-                       InsetCode code = insetCode(name);
-                       string data = trim(to_utf8(cmd.argument()).substr(name.size()));
-                       bool insetCodeOK = true;
-                       switch (code) {
-                       case BIBITEM_CODE:
-                       case BIBTEX_CODE:
-                       case INDEX_CODE:
-                       case LABEL_CODE:
-                       case NOMENCL_CODE:
-                       case NOMENCL_PRINT_CODE:
-                       case REF_CODE:
-                       case TOC_CODE:
-                       case HYPERLINK_CODE: {
-                               InsetCommandParams p(code);
-                               data = InsetCommand::params2string(name, p);
-                               break;
-                       }
-                       case INCLUDE_CODE: {
-                               // data is the include type: one of "include",
-                               // "input", "verbatiminput" or "verbatiminput*"
-                               if (data.empty())
-                                       // default type is requested
-                                       data = "include";
-                               InsetCommandParams p(INCLUDE_CODE, data);
-                               data = InsetCommand::params2string("include", p);
-                               break;
-                       }
-                       case BOX_CODE: {
-                               // \c data == "Boxed" || "Frameless" etc
-                               InsetBoxParams p(data);
-                               data = InsetBox::params2string(p);
-                               break;
-                       }
-                       case BRANCH_CODE: {
-                               InsetBranchParams p;
-                               data = InsetBranch::params2string(p);
-                               break;
-                       }
-                       case CITE_CODE: {
-                               InsetCommandParams p(CITE_CODE);
-                               data = InsetCommand::params2string(name, p);
-                               break;
-                       }
-                       case ERT_CODE: {
-                               data = InsetERT::params2string(InsetCollapsable::Open);
-                               break;
-                       }
-                       case EXTERNAL_CODE: {
-                               InsetExternalParams p;
-                               data = InsetExternal::params2string(p, *buffer);
-                               break;
-                       }
-                       case FLOAT_CODE:  {
-                               InsetFloatParams p;
-                               data = InsetFloat::params2string(p);
-                               break;
-                       }
-                       case LISTINGS_CODE: {
-                               InsetListingsParams p;
-                               data = InsetListings::params2string(p);
-                               break;
-                       }
-                       case GRAPHICS_CODE: {
-                               InsetGraphicsParams p;
-                               data = InsetGraphics::params2string(p, *buffer);
-                               break;
-                       }
-                       case NOTE_CODE: {
-                               InsetNoteParams p;
-                               data = InsetNote::params2string(p);
-                               break;
-                       }
-                       case PHANTOM_CODE: {
-                               InsetPhantomParams p;
-                               data = InsetPhantom::params2string(p);
-                               break;
-                       }
-                       case SPACE_CODE: {
-                               InsetSpaceParams p;
-                               data = InsetSpace::params2string(p);
-                               break;
-                       }
-                       case VSPACE_CODE: {
-                               VSpace space;
-                               data = InsetVSpace::params2string(space);
-                               break;
-                       }
-                       case WRAP_CODE: {
-                               InsetWrapParams p;
-                               data = InsetWrap::params2string(p);
-                               break;
-                       }
-                       default:
-                               lyxerr << "Inset type '" << name << 
-                                       "' not recognized in LFUN_DIALOG_SHOW_NEW_INSET" <<  endl;
-                               insetCodeOK = false;
-                               break;
-                       } // end switch(code)
-                       if (insetCodeOK)
-                               dispatch(FuncRequest(LFUN_DIALOG_SHOW, name + " " + data));
-                       break;
-               }
-
-               case LFUN_CITATION_INSERT: {
-                       LASSERT(lyx_view_, /**/);
-                       if (!argument.empty()) {
-                               // we can have one optional argument, delimited by '|'
-                               // citation-insert <key>|<text_before>
-                               // this should be enhanced to also support text_after
-                               // and citation style
-                               string arg = argument;
-                               string opt1;
-                               if (contains(argument, "|")) {
-                                       arg = token(argument, '|', 0);
-                                       opt1 = token(argument, '|', 1);
-                               }
-                               InsetCommandParams icp(CITE_CODE);
-                               icp["key"] = from_utf8(arg);
-                               if (!opt1.empty())
-                                       icp["before"] = from_utf8(opt1);
-                               string icstr = InsetCommand::params2string("citation", icp);
-                               FuncRequest fr(LFUN_INSET_INSERT, icstr);
-                               dispatch(fr);
-                       } else
-                               dispatch(FuncRequest(LFUN_DIALOG_SHOW_NEW_INSET, "citation"));
-                       break;
-               }
-
                case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
-                       LASSERT(lyx_view_, /**/);
                        lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
                        break;
 
@@ -980,7 +587,13 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
                case LFUN_COMMAND_SEQUENCE: {
                        // argument contains ';'-terminated commands
                        string arg = argument;
-                       if (theBufferList().isLoaded(buffer))
+                       // FIXME: this LFUN should also work without any view.
+                       Buffer * buffer = (lv && lv->documentBufferView())
+                               ? &(lv->documentBufferView()->buffer()) : 0;
+                       buffer = &lv->currentBufferView()->buffer();
+                       if (buffer && !theBufferList().isLoaded(buffer))
+                               buffer = 0;
+                       if (buffer)
                                buffer->undo().beginUndoGroup();
                        while (!arg.empty()) {
                                string first;
@@ -989,7 +602,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
                                func.origin = cmd.origin;
                                dispatch(func);
                        }
-                       if (theBufferList().isLoaded(buffer))
+                       if (buffer)
                                buffer->undo().endUndoGroup();
                        break;
                }
@@ -1066,106 +679,6 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
                        break;
                }
 
-               case LFUN_BUFFER_PARAMS_APPLY: {
-                       LASSERT(lyx_view_, /**/);
-                       
-                       DocumentClass const * const oldClass = buffer->params().documentClassPtr();
-                       Cursor & cur = lyx_view_->documentBufferView()->cursor();
-                       cur.recordUndoFullDocument();
-                       
-                       istringstream ss(argument);
-                       Lexer lex;
-                       lex.setStream(ss);
-                       int const unknown_tokens = buffer->readHeader(lex);
-
-                       if (unknown_tokens != 0) {
-                               lyxerr << "Warning in LFUN_BUFFER_PARAMS_APPLY!\n"
-                                               << unknown_tokens << " unknown token"
-                                               << (unknown_tokens == 1 ? "" : "s")
-                                               << endl;
-                       }
-                       
-                       updateLayout(oldClass, buffer);
-                       
-                       updateFlags = Update::Force | Update::FitCursor;
-                       // We are most certainly here because of a change in the document
-                       // It is then better to make sure that all dialogs are in sync with
-                       // current document settings. LyXView::restartCursor() achieve this.
-                       lyx_view_->restartCursor();
-                       break;
-               }
-               
-               case LFUN_LAYOUT_MODULES_CLEAR: {
-                       LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
-                       DocumentClass const * const oldClass = buffer->params().documentClassPtr();
-                       lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
-                       buffer->params().clearLayoutModules();
-                       buffer->params().makeDocumentClass();
-                       updateLayout(oldClass, buffer);
-                       updateFlags = Update::Force | Update::FitCursor;
-                       break;
-               }
-               
-               case LFUN_LAYOUT_MODULE_ADD: {
-                       LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
-                       BufferParams const & params = buffer->params();
-                       if (!params.moduleCanBeAdded(argument)) {
-                               LYXERR0("Module `" << argument << 
-                                               "' cannot be added due to failed requirements or "
-                                               "conflicts with installed modules.");
-                               break;
-                       }
-                       DocumentClass const * const oldClass = params.documentClassPtr();
-                       lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
-                       buffer->params().addLayoutModule(argument);
-                       buffer->params().makeDocumentClass();
-                       updateLayout(oldClass, buffer);
-                       updateFlags = Update::Force | Update::FitCursor;
-                       break;
-               }
-
-               case LFUN_TEXTCLASS_APPLY: {
-                       LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
-
-                       if (!loadLayoutFile(argument, buffer->temppath()) &&
-                               !loadLayoutFile(argument, buffer->filePath()))
-                               break;
-
-                       LayoutFile const * old_layout = buffer->params().baseClass();
-                       LayoutFile const * new_layout = &(LayoutFileList::get()[argument]);
-
-                       if (old_layout == new_layout)
-                               // nothing to do
-                               break;
-
-                       //Save the old, possibly modular, layout for use in conversion.
-                       DocumentClass const * const oldDocClass =
-                               buffer->params().documentClassPtr();
-                       lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
-                       buffer->params().setBaseClass(argument);
-                       buffer->params().makeDocumentClass();
-                       updateLayout(oldDocClass, buffer);
-                       updateFlags = Update::Force | Update::FitCursor;
-                       break;
-               }
-               
-               case LFUN_LAYOUT_RELOAD: {
-                       LASSERT(lyx_view_, /**/);
-                       DocumentClass const * const oldClass = buffer->params().documentClassPtr();
-                       LayoutFileIndex bc = buffer->params().baseClassID();
-                       LayoutFileList::get().reset(bc);
-                       buffer->params().setBaseClass(bc);
-                       buffer->params().makeDocumentClass();
-                       updateLayout(oldClass, buffer);
-                       updateFlags = Update::Force | Update::FitCursor;
-                       break;
-               }
-
-               case LFUN_TEXTCLASS_LOAD:
-                       loadLayoutFile(argument, buffer->temppath()) ||
-                       loadLayoutFile(argument, buffer->filePath());
-                       break;
-
                case LFUN_LYXRC_APPLY: {
                        // reset active key sequences, since the bindings
                        // are updated (bug 6064)
@@ -1213,49 +726,65 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
                                // Nothing more to do.
                                return;
 
-                       // Everything below is only for active lyx_view_
-                       if (lyx_view_ == 0)
+                       // Everything below is only for active window
+                       if (lv == 0)
                                break;
 
+                       Buffer * doc_buffer = (lv && lv->documentBufferView())
+                               ? &(lv->documentBufferView()->buffer()) : 0;
+                       if (doc_buffer && !theBufferList().isLoaded(doc_buffer))
+                               doc_buffer = 0;
                        // Start an undo group. This may be needed for
                        // some stuff like inset-apply on labels.
-                       if (theBufferList().isLoaded(buffer))
-                               buffer->undo().beginUndoGroup();
-                               
+                       if (doc_buffer)
+                               doc_buffer->undo().beginUndoGroup();
+
                        // Let the current LyXView dispatch its own actions.
-                       if (lyx_view_->dispatch(cmd)) {
-                               if (lyx_view_->currentBufferView()) {
-                                       updateFlags = lyx_view_->currentBufferView()->cursor().result().update();
-                                       if (theBufferList().isLoaded(buffer))
+                       if (lv->dispatch(cmd)) {
+                               BufferView * bv = lv->currentBufferView();
+                               if (bv) {
+                                       Buffer * buffer = &(bv->buffer());
+                                       updateFlags = bv->cursor().result().update();
+                                       if (buffer == doc_buffer && theBufferList().isLoaded(buffer))
                                                buffer->undo().endUndoGroup();
                                }
                                break;
                        }
 
-                       LASSERT(lyx_view_->currentBufferView(), /**/);
+                       BufferView * bv = lv->currentBufferView();
+                       LASSERT(bv, /**/);
 
                        // Let the current BufferView dispatch its own actions.
-                       if (lyx_view_->currentBufferView()->dispatch(cmd)) {
+                       if (bv->dispatch(cmd)) {
+                               // The BufferView took care of its own updates if needed.
+                               Buffer * buffer = &(bv->buffer());
+                               updateFlags = Update::None;
+                               if (buffer == doc_buffer && theBufferList().isLoaded(buffer))
+                                       buffer->undo().endUndoGroup();
+                               break;
+                       }
+
+                       BufferView * doc_bv = lv->documentBufferView();
+                       // Try with the document BufferView dispatch if any.
+                       if (doc_bv && doc_bv->dispatch(cmd)) {
                                // The BufferView took care of its own updates if needed.
+                               Buffer * buffer = &(doc_bv->buffer());
                                updateFlags = Update::None;
-                               if (theBufferList().isLoaded(buffer))
+                               if (buffer == doc_buffer && theBufferList().isLoaded(buffer))
                                        buffer->undo().endUndoGroup();
                                break;
                        }
 
-                       // OK, so try the Buffer itself
+                       // OK, so try the current Buffer itself...
                        DispatchResult dr;
-                       BufferView * bv = lyx_view_->currentBufferView();
                        bv->buffer().dispatch(cmd, dr);
                        if (dr.dispatched()) {
                                updateFlags = dr.update();
                                break;
                        }
-                       // OK, so try with the document Buffer.
-                       BufferView * doc_bv = lyx_view_->documentBufferView();
+                       // and with the document Buffer.
                        if (doc_bv) {
-                               buffer = &(doc_bv->buffer());
-                               buffer->dispatch(cmd, dr);
+                               doc_bv->buffer().dispatch(cmd, dr);
                                if (dr.dispatched()) {
                                        updateFlags = dr.update();
                                        break;
@@ -1289,8 +818,8 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
                                if (badcursor)
                                        bv->cursor().fixIfBroken();
                        }
-
-                       if (theBufferList().isLoaded(buffer))
+                       Buffer * buffer = &(bv->buffer());
+                       if (buffer == doc_buffer && theBufferList().isLoaded(buffer))
                                buffer->undo().endUndoGroup();
 
                        // update completion. We do it here and not in
@@ -1299,38 +828,41 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
                        if (cmd.origin == FuncRequest::KEYBOARD) {
                                if (cmd.action == LFUN_SELF_INSERT
                                    || (cmd.action == LFUN_ERT_INSERT && bv->cursor().inMathed()))
-                                       lyx_view_->updateCompletion(bv->cursor(), true, true);
+                                       lv->updateCompletion(bv->cursor(), true, true);
                                else if (cmd.action == LFUN_CHAR_DELETE_BACKWARD)
-                                       lyx_view_->updateCompletion(bv->cursor(), false, true);
+                                       lv->updateCompletion(bv->cursor(), false, true);
                                else
-                                       lyx_view_->updateCompletion(bv->cursor(), false, false);
+                                       lv->updateCompletion(bv->cursor(), false, false);
                        }
 
                        updateFlags = bv->cursor().result().update();
                }
 
                // if we executed a mutating lfun, mark the buffer as dirty
-               if (theBufferList().isLoaded(buffer) && flag.enabled()
+               Buffer * doc_buffer = (lv && lv->documentBufferView())
+                       ? &(lv->documentBufferView()->buffer()) : 0;
+               if (doc_buffer && theBufferList().isLoaded(doc_buffer)
+                       && flag.enabled()
                    && !lyxaction.funcHasFlag(action, LyXAction::NoBuffer)
                    && !lyxaction.funcHasFlag(action, LyXAction::ReadOnly))
-                       buffer->markDirty();                    
+                       doc_buffer->markDirty();                        
 
-               if (lyx_view_ && lyx_view_->currentBufferView()) {
+               if (lv && lv->currentBufferView()) {
                        // BufferView::update() updates the ViewMetricsInfo and
                        // also initializes the position cache for all insets in
                        // (at least partially) visible top-level paragraphs.
                        // We will redraw the screen only if needed.
-                       lyx_view_->currentBufferView()->processUpdateFlags(updateFlags);
+                       lv->currentBufferView()->processUpdateFlags(updateFlags);
 
                        // Do we have a selection?
                        theSelection().haveSelection(
-                               lyx_view_->currentBufferView()->cursor().selection());
+                               lv->currentBufferView()->cursor().selection());
                        
                        // update gui
-                       lyx_view_->restartCursor();
+                       lv->restartCursor();
                }
        }
-       if (lyx_view_) {
+       if (lv) {
                // Some messages may already be translated, so we cannot use _()
                sendDispatchMessage(translateIfPossible(getMessage()), cmd);
        }
@@ -1343,10 +875,11 @@ void LyXFunc::sendDispatchMessage(docstring const & msg, FuncRequest const & cmd
                              || cmd.origin == FuncRequest::TOOLBAR
                              || cmd.origin == FuncRequest::COMMANDBUFFER);
 
+       LyXView * lv = theApp()->currentWindow();
        if (cmd.action == LFUN_SELF_INSERT || !verbose) {
                LYXERR(Debug::ACTION, "dispatch msg is " << to_utf8(msg));
                if (!msg.empty())
-                       lyx_view_->message(msg);
+                       lv->message(msg);
                return;
        }
 
@@ -1379,11 +912,11 @@ void LyXFunc::sendDispatchMessage(docstring const & msg, FuncRequest const & cmd
 
        LYXERR(Debug::ACTION, "verbose dispatch msg " << to_utf8(dispatch_msg));
        if (!dispatch_msg.empty())
-               lyx_view_->message(dispatch_msg);
+               lv->message(dispatch_msg);
 }
 
 
-// Each "lyx_view_" should have it's own message method. lyxview and
+// Each LyXView should have it's own message method. lyxview and
 // the minibuffer would use the minibuffer, but lyxserver would
 // send an ERROR signal to its client.  Alejandro 970603
 // This function is bit problematic when it comes to NLS, to make the
@@ -1413,11 +946,7 @@ docstring LyXFunc::viewStatusMessage()
        if (keyseq.length() > 0 && !keyseq.deleted())
                return keyseq.printOptions(true);
 
-       LASSERT(lyx_view_, /**/);
-       if (!lyx_view_->currentBufferView())
-               return _("Welcome to LyX!");
-
-       return lyx_view_->currentBufferView()->cursor().currentState();
+       return docstring();
 }
 
 
@@ -1427,23 +956,6 @@ bool LyXFunc::wasMetaKey() const
 }
 
 
-void LyXFunc::updateLayout(DocumentClass const * const oldlayout, Buffer * buf)
-{
-       lyx_view_->message(_("Converting document to new document class..."));
-       
-       StableDocIterator backcur(lyx_view_->currentBufferView()->cursor());
-       ErrorList & el = buf->errorList("Class Switch");
-       cap::switchBetweenClasses(
-                       oldlayout, buf->params().documentClassPtr(),
-                       static_cast<InsetText &>(buf->inset()), el);
-
-       lyx_view_->currentBufferView()->setCursor(backcur.asDocIterator(buf));
-
-       buf->errors("Class Switch");
-       buf->updateLabels();
-}
-
-
 namespace {
 
 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)