]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiView.cpp
* fix spelling in comments to please John.
[lyx.git] / src / frontends / qt4 / GuiView.cpp
index 222f67bdaccb637b42217046a619152b7caf2607..fe0c201b8dc3fe26d20f4ab403dcc02555094797 100644 (file)
@@ -3,10 +3,10 @@
  * This file is part of LyX, the document processor.
  * Licence details can be found in the file COPYING.
  *
- * \author Lars Gullik Bjønnes
+ * \author Lars Gullik Bjønnes
  * \author John Levon
  * \author Abdelrazak Younes
- * \author Peter Kümmel
+ * \author Peter Kümmel
  *
  * Full author contact details are available in file CREDITS.
  */
 #include "GuiView.h"
 
 #include "Dialog.h"
+#include "DispatchResult.h"
 #include "FileDialog.h"
+#include "FontLoader.h"
 #include "GuiApplication.h"
 #include "GuiCommandBuffer.h"
 #include "GuiCompleter.h"
-#include "GuiWorkArea.h"
 #include "GuiKeySymbol.h"
+#include "GuiToc.h"
 #include "GuiToolbar.h"
+#include "GuiWorkArea.h"
+#include "LayoutBox.h"
 #include "Menus.h"
 #include "TocModel.h"
 
@@ -37,6 +41,7 @@
 #include "BufferView.h"
 #include "Converter.h"
 #include "Cursor.h"
+#include "CutAndPaste.h"
 #include "Encoding.h"
 #include "ErrorList.h"
 #include "Format.h"
 #include "Intl.h"
 #include "Layout.h"
 #include "Lexer.h"
+#include "LyXAction.h"
 #include "LyXFunc.h"
 #include "LyX.h"
 #include "LyXRC.h"
 #include "LyXVC.h"
 #include "Paragraph.h"
+#include "SpellChecker.h"
 #include "TextClass.h"
 #include "Text.h"
 #include "Toolbars.h"
 #include "version.h"
 
-#include "support/lassert.h"
+#include "support/convert.h"
 #include "support/debug.h"
 #include "support/ExceptionMessage.h"
 #include "support/FileName.h"
 #include "support/filetools.h"
 #include "support/gettext.h"
+#include "support/filetools.h"
 #include "support/ForkedCalls.h"
+#include "support/lassert.h"
 #include "support/lstrings.h"
 #include "support/os.h"
 #include "support/Package.h"
+#include "support/Path.h"
+#include "support/Systemcall.h"
 #include "support/Timeout.h"
+#include "support/ProgressInterface.h"
+#include "GuiProgress.h"
 
 #include <QAction>
 #include <QApplication>
@@ -79,6 +92,7 @@
 #include <QMenuBar>
 #include <QPainter>
 #include <QPixmap>
+#include <QPixmapCache>
 #include <QPoint>
 #include <QPushButton>
 #include <QSettings>
 #include <QSplitter>
 #include <QStackedWidget>
 #include <QStatusBar>
+#include <QTime>
 #include <QTimer>
 #include <QToolBar>
 #include <QUrl>
 #include <QScrollBar>
 
+#define EXPORT_in_THREAD 1
+
+
+// QtConcurrent was introduced in Qt 4.4
+#if (QT_VERSION >= 0x040400)
+#include <QFuture>
+#include <QFutureWatcher>
+#include <QtConcurrentRun>
+#endif
+
 #include <boost/bind.hpp>
 
+#include <sstream>
+
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
 #endif
@@ -117,7 +144,7 @@ public:
                /// The text to be written on top of the pixmap
                QString const text = lyx_version ?
                        qt_("version ") + lyx_version : qt_("unknown version");
-               splash_ = QPixmap(":/images/banner.png");
+               splash_ = getPixmap("images/", "banner", "png");
 
                QPainter pain(&splash_);
                pain.setPen(QColor(0, 0, 0));
@@ -127,7 +154,8 @@ public:
                font.setWeight(QFont::Bold);
                font.setPointSize(int(toqstr(lyxrc.font_sizes[FONT_SIZE_LARGE]).toDouble()));
                pain.setFont(font);
-               pain.drawText(190, 225, text);
+               pain.drawText(260, 15, text);
+               setFocusPolicy(Qt::StrongFocus);
        }
 
        void paintEvent(QPaintEvent *)
@@ -138,12 +166,25 @@ public:
                pain.drawPixmap(x, y, splash_);
        }
 
+       void keyPressEvent(QKeyEvent * ev)
+       {
+               KeySymbol sym;
+               setKeySymbol(&sym, ev);
+               if (sym.isOK()) {
+                       guiApp->processKeySym(sym, q_key_state(ev->modifiers()));
+                       ev->accept();
+               } else {
+                       ev->ignore();
+               }
+       }
+
 private:
        QPixmap splash_;
 };
 
+
 /// Toolbar store providing access to individual toolbars by name.
-typedef std::map<std::string, GuiToolbar *> ToolbarMap;
+typedef map<string, GuiToolbar *> ToolbarMap;
 
 typedef boost::shared_ptr<Dialog> DialogPtr;
 
@@ -152,14 +193,15 @@ typedef boost::shared_ptr<Dialog> DialogPtr;
 
 struct GuiView::GuiViewPrivate
 {
-       GuiViewPrivate()
-               : current_work_area_(0), layout_(0), autosave_timeout_(5000),
+       GuiViewPrivate(GuiView * gv)
+               : gv_(gv), current_work_area_(0), current_main_work_area_(0),
+               layout_(0), autosave_timeout_(5000),
                in_show_(false)
        {
                // hardcode here the platform specific icon size
-               smallIconSize = 14;     // scaling problems
-               normalIconSize = 20;    // ok, default
-               bigIconSize = 26;               // better for some math icons
+               smallIconSize = 14;  // scaling problems
+               normalIconSize = 20; // ok, default
+               bigIconSize = 26;    // better for some math icons
 
                splitter_ = new QSplitter;
                bg_widget_ = new BackgroundWidget;
@@ -167,6 +209,7 @@ struct GuiView::GuiViewPrivate
                stack_widget_->addWidget(bg_widget_);
                stack_widget_->addWidget(splitter_);
                setBackground();
+               progress_ = new GuiProgress(gv);
        }
 
        ~GuiViewPrivate()
@@ -174,6 +217,7 @@ struct GuiView::GuiViewPrivate
                delete splitter_;
                delete bg_widget_;
                delete stack_widget_;
+               delete progress_;
        }
 
        QMenu * toolBarPopup(GuiView * parent)
@@ -218,6 +262,7 @@ struct GuiView::GuiViewPrivate
        {
                stack_widget_->setCurrentWidget(bg_widget_);
                bg_widget_->setUpdatesEnabled(true);
+               bg_widget_->setFocus();
        }
 
        TabWorkArea * tabWorkArea(int i)
@@ -233,7 +278,7 @@ struct GuiView::GuiViewPrivate
 
                for (int i = 0; i != splitter_->count(); ++i) {
                        TabWorkArea * twa = tabWorkArea(i);
-                       if (current_work_area_ == twa->currentWorkArea())
+                       if (current_main_work_area_ == twa->currentWorkArea())
                                return twa;
                }
 
@@ -241,13 +286,28 @@ struct GuiView::GuiViewPrivate
                return tabWorkArea(0);
        }
 
+#if (QT_VERSION >= 0x040400)
+       void setPreviewFuture(QFuture<docstring> const & f)
+       {
+               if (preview_watcher_.isRunning()) {
+                       // we prefer to cancel this preview in order to keep a snappy
+                       // interface.
+                       return;
+               }
+               preview_watcher_.setFuture(f);
+       }
+#endif
+
 public:
+       GuiView * gv_;
        GuiWorkArea * current_work_area_;
+       GuiWorkArea * current_main_work_area_;
        QSplitter * splitter_;
        QStackedWidget * stack_widget_;
        BackgroundWidget * bg_widget_;
        /// view's toolbars
        ToolbarMap toolbars_;
+       ProgressInterface* progress_;
        /// The main layout box.
        /** 
         * \warning Don't Delete! The layout box is actually owned by
@@ -257,10 +317,7 @@ public:
         * FIXME: replace that with a proper model so that we are not limited
         * to only one dialog.
         */
-       GuiLayoutBox * layout_;
-
-       ///
-       map<string, Inset *> open_insets_;
+       LayoutBox * layout_;
 
        ///
        map<string, DialogPtr> dialogs_;
@@ -277,11 +334,20 @@ public:
 
        ///
        TocModels toc_models_;
+
+#if (QT_VERSION >= 0x040400)
+       ///
+       QFutureWatcher<docstring> autosave_watcher_;
+       QFutureWatcher<docstring> preview_watcher_;
+#else
+       struct DummyWatcher { bool isRunning(){return false;} }; 
+       DummyWatcher preview_watcher_;
+#endif
 };
 
 
 GuiView::GuiView(int id)
-       : d(*new GuiViewPrivate), id_(id), closing_(false)
+       : d(*new GuiViewPrivate(this)), id_(id), closing_(false)
 {
        // GuiToolbars *must* be initialised before the menu bar.
        normalSizedIcons(); // at least on Mac the default is 32 otherwise, which is huge
@@ -290,7 +356,7 @@ GuiView::GuiView(int id)
        // set ourself as the current view. This is needed for the menu bar
        // filling, at least for the static special menu item on Mac. Otherwise
        // they are greyed out.
-       theLyXFunc().setLyXView(this);
+       guiApp->setCurrentView(this);
        
        // Fill up the menu bar.
        guiApp->menus().fillMenuBar(menuBar(), this, true);
@@ -312,13 +378,30 @@ GuiView::GuiView(int id)
 #if (!defined(Q_WS_WIN) && !defined(Q_WS_MACX))
        // assign an icon to main form. We do not do it under Qt/Win or Qt/Mac,
        // since the icon is provided in the application bundle.
-       setWindowIcon(QPixmap(":/images/lyx.png"));
+       setWindowIcon(getPixmap("images/", "lyx", "png"));
+#endif
+
+#if (QT_VERSION >= 0x040300)
+       // use tabbed dock area for multiple docks
+       // (such as "source" and "messages")
+       setDockOptions(QMainWindow::ForceTabbedDocks);
 #endif
 
        // For Drag&Drop.
        setAcceptDrops(true);
 
        statusBar()->setSizeGripEnabled(true);
+       updateStatusBar();
+
+#if (QT_VERSION >= 0x040400)
+       connect(&d.autosave_watcher_, SIGNAL(finished()), this,
+               SLOT(threadFinished()));
+       connect(&d.preview_watcher_, SIGNAL(finished()), this,
+               SLOT(threadFinished()));
+#endif
+
+       connect(this, SIGNAL(triggerShowDialog(QString const &, QString const &, Inset *)),
+               SLOT(doShowDialog(QString const &, QString const &, Inset *)));
 
        // Forbid too small unresizable window because it can happen
        // with some window manager under X11.
@@ -330,10 +413,11 @@ GuiView::GuiView(int id)
                        return;
        }
 
-       // No session handling, default to a sane size.
+       // no session handling, default to a sane size.
        setGeometry(50, 50, 690, 510);
        initToolbars();
-       // This enables to clear session data if any.
+
+       // clear session data if any.
        QSettings settings;
        settings.remove("views");
 }
@@ -345,6 +429,16 @@ GuiView::~GuiView()
 }
 
 
+void GuiView::threadFinished()
+{
+#if (QT_VERSION >= 0x040400)
+       QFutureWatcher<docstring> const * watcher =
+               static_cast<QFutureWatcher<docstring> const *>(sender());
+       message(watcher->result());
+#endif
+}
+
+
 void GuiView::saveLayout() const
 {
        QSettings settings;
@@ -370,6 +464,7 @@ bool GuiView::restoreLayout()
        if (!settings.contains(icon_key))
                return false;
 
+       //code below is skipped when when ~/.config/LyX is (re)created
        setIconSize(settings.value(icon_key).toSize());
 #ifdef Q_WS_X11
        QPoint pos = settings.value("pos", QPoint(50, 50)).toPoint();
@@ -377,15 +472,26 @@ bool GuiView::restoreLayout()
        resize(size);
        move(pos);
 #else
-       if (!restoreGeometry(settings.value("geometry").toByteArray()))
-               setGeometry(50, 50, 690, 510);
+       // Work-around for bug #6034: the window ends up in an undetermined
+       // state when trying to restore a maximized window when it is
+       // already maximized.
+       if (!(windowState() & Qt::WindowMaximized))
+               if (!restoreGeometry(settings.value("geometry").toByteArray()))
+                       setGeometry(50, 50, 690, 510);
 #endif
        // Make sure layout is correctly oriented.
        setLayoutDirection(qApp->layoutDirection());
 
        // Allow the toc and view-source dock widget to be restored if needed.
-       findOrBuild("toc", true);
-       findOrBuild("view-source", true);
+       Dialog * dialog;
+       if ((dialog = findOrBuild("toc", true)))
+               // see bug 5082. At least setup title and enabled state.
+               // Visibility will be adjusted by restoreState below.
+               dialog->prepareView();
+       if ((dialog = findOrBuild("view-source", true)))
+               dialog->prepareView();
+       if ((dialog = findOrBuild("progress", true)))
+               dialog->prepareView();
 
        if (!restoreState(settings.value("layout").toByteArray(), 0))
                initToolbars();
@@ -412,7 +518,12 @@ void GuiView::constructToolbars()
        for (; it != d.toolbars_.end(); ++it)
                delete it->second;
        d.toolbars_.clear();
-       d.layout_ = 0;
+
+       // I don't like doing this here, but the standard toolbar
+       // destroys this object when it's destroyed itself (vfr)
+       d.layout_ = new LayoutBox(*this);
+       d.stack_widget_->addWidget(d.layout_);
+       d.layout_->move(0,0);
 
        // extracts the toolbars from the backend
        Toolbars::Infos::iterator cit = guiApp->toolbars().begin();
@@ -432,7 +543,7 @@ void GuiView::initToolbars()
                if (!tb)
                        continue;
                int const visibility = guiApp->toolbars().defaultVisibility(cit->name);
-               bool newline = true;
+               bool newline = !(visibility & Toolbars::SAMEROW);
                tb->setVisible(false);
                tb->setVisibility(visibility);
 
@@ -445,7 +556,8 @@ void GuiView::initToolbars()
                if (visibility & Toolbars::BOTTOM) {
                        // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
 #if (QT_VERSION >= 0x040202)
-                       addToolBarBreak(Qt::BottomToolBarArea);
+                       if (newline)
+                               addToolBarBreak(Qt::BottomToolBarArea);
 #endif
                        addToolBar(Qt::BottomToolBarArea, tb);
                }
@@ -453,7 +565,8 @@ void GuiView::initToolbars()
                if (visibility & Toolbars::LEFT) {
                        // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
 #if (QT_VERSION >= 0x040202)
-                       addToolBarBreak(Qt::LeftToolBarArea);
+                       if (newline)
+                               addToolBarBreak(Qt::LeftToolBarArea);
 #endif
                        addToolBar(Qt::LeftToolBarArea, tb);
                }
@@ -461,7 +574,8 @@ void GuiView::initToolbars()
                if (visibility & Toolbars::RIGHT) {
                        // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
 #if (QT_VERSION >= 0x040202)
-                       addToolBarBreak(Qt::RightToolBarArea);
+                       if (newline)
+                               addToolBarBreak(Qt::RightToolBarArea);
 #endif
                        addToolBar(Qt::RightToolBarArea, tb);
                }
@@ -480,12 +594,23 @@ TocModels & GuiView::tocModels()
 
 void GuiView::setFocus()
 {
+       LYXERR(Debug::DEBUG, "GuiView::setFocus()" << this);
+       QMainWindow::setFocus();
+}
+
+
+void GuiView::focusInEvent(QFocusEvent * e)
+{
+       LYXERR(Debug::DEBUG, "GuiView::focusInEvent()" << this);
+       QMainWindow::focusInEvent(e);
        // Make sure LyXFunc points to the correct view.
        guiApp->setCurrentView(this);
-       theLyXFunc().setLyXView(this);
-       QMainWindow::setFocus();
-       if (d.current_work_area_)
-               d.current_work_area_->setFocus();
+       if (currentMainWorkArea())
+               currentMainWorkArea()->setFocus();
+       else if (currentWorkArea())
+               currentWorkArea()->setFocus();
+       else
+               d.bg_widget_->setFocus();
 }
 
 
@@ -509,53 +634,26 @@ void GuiView::showEvent(QShowEvent * e)
 }
 
 
+/** Destroy only all tabbed WorkAreas. Destruction of other WorkAreas
+ ** is responsibility of the container (e.g., dialog)
+ **/
 void GuiView::closeEvent(QCloseEvent * close_event)
 {
+       LYXERR(Debug::DEBUG, "GuiView::closeEvent()");
        closing_ = true;
 
+       writeSession();
+
        // it can happen that this event arrives without selecting the view,
        // e.g. when clicking the close button on a background window.
        setFocus();
-
-       while (Buffer * b = buffer()) {
-               if (b->parent()) {
-                       // This is a child document, just close the tab after saving
-                       // but keep the file loaded.
-                       if (!saveBuffer(*b)) {
-                               closing_ = false;
-                               close_event->ignore();
-                               return;
-                       }
-                       removeWorkArea(d.current_work_area_);
-                       continue;
-               }
-
-               QList<int> const ids = guiApp->viewIds();
-               for (int i = 0; i != ids.size(); ++i) {
-                       if (id_ == ids[i])
-                               continue;
-                       if (guiApp->view(ids[i]).workArea(*b)) {
-                               // FIXME 1: should we put an alert box here that the buffer
-                               // is viewed elsewhere?
-                               // FIXME 2: should we try to save this buffer in any case?
-                               //saveBuffer(b);
-
-                               // This buffer is also opened in another view, so
-                               // close the associated work area...
-                               removeWorkArea(d.current_work_area_);
-                               // ... but don't close the buffer.
-                               b = 0;
-                               break;
-                       }
-               }
-               if (b && !closeBuffer(*b, true)) {
-                       closing_ = false;
-                       close_event->ignore();
-                       return;
-               }
+       if (!closeWorkAreaAll()) {
+               closing_ = false;
+               close_event->ignore();
+               return;
        }
 
-       // Make sure that nothing will use this close to be closed View.
+       // Make sure that nothing will use this to be closed View.
        guiApp->unregisterView(this);
 
        if (isFullScreen()) {
@@ -596,7 +694,7 @@ void GuiView::dragEnterEvent(QDragEnterEvent * event)
 }
 
 
-void GuiView::dropEvent(QDropEvent* event)
+void GuiView::dropEvent(QDropEvent * event)
 {
        QList<QUrl> files = event->mimeData()->urls();
        if (files.isEmpty())
@@ -606,8 +704,42 @@ void GuiView::dropEvent(QDropEvent* event)
        for (int i = 0; i != files.size(); ++i) {
                string const file = os::internal_path(fromqstr(
                        files.at(i).toLocalFile()));
-               if (!file.empty())
-                       lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, file));
+               if (file.empty())
+                       continue;
+
+               string const ext = support::getExtension(file);
+               vector<const Format *> found_formats;
+
+               // Find all formats that have the correct extension.
+               vector<const Format *> const & import_formats 
+                       = theConverters().importableFormats();
+               vector<const Format *>::const_iterator it = import_formats.begin();
+               for (; it != import_formats.end(); ++it)
+                       if ((*it)->extension() == ext)
+                               found_formats.push_back(*it);
+
+               FuncRequest cmd;
+               if (found_formats.size() >= 1) {
+                       if (found_formats.size() > 1) {
+                               //FIXME: show a dialog to choose the correct importable format
+                               LYXERR(Debug::FILES,
+                                       "Multiple importable formats found, selecting first");
+                       }
+                       string const arg = found_formats[0]->name() + " " + file;
+                       cmd = FuncRequest(LFUN_BUFFER_IMPORT, arg);
+               } 
+               else {
+                       //FIXME: do we have to explicitly check whether it's a lyx file?
+                       LYXERR(Debug::FILES,
+                               "No formats found, trying to open it as a lyx file");
+                       cmd = FuncRequest(LFUN_FILE_OPEN, file);
+               }
+
+               // Asynchronously post the event. DropEvent usually comes
+               // from the BufferView. But reloading a file might close
+               // the BufferView from within its own event handler.
+               guiApp->dispatchDelayed(cmd);
+               event->accept();
        }
 }
 
@@ -616,8 +748,15 @@ void GuiView::message(docstring const & str)
 {
        if (ForkedProcess::iAmAChild())
                return;
+       
+       // call is moved to GUI-thread by GuiProgress
+       d.progress_->appendMessage(toqstr(str));
+}
+
 
-       statusBar()->showMessage(toqstr(str));
+void GuiView::updateMessage(QString const & str)
+{
+       statusBar()->showMessage(str);
        d.statusbar_timer_.stop();
        d.statusbar_timer_.start(3000);
 }
@@ -643,17 +782,20 @@ void GuiView::bigSizedIcons()
 
 void GuiView::clearMessage()
 {
-       if (!hasFocus())
-               return;
-       theLyXFunc().setLyXView(this);
-       statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
+       // FIXME: This code was introduced in r19643 to fix bug #4123. However,
+       // the hasFocus function mostly returns false, even if the focus is on
+       // a workarea in this view.
+       //if (!hasFocus())
+       //      return;
+       showMessage();
        d.statusbar_timer_.stop();
 }
 
 
 void GuiView::updateWindowTitle(GuiWorkArea * wa)
 {
-       if (wa != d.current_work_area_)
+       if (wa != d.current_work_area_
+           || wa->bufferView().buffer().isInternal())
                return;
        setWindowTitle(qt_("LyX: ") + wa->windowTitle());
        setWindowIconText(wa->windowIconText());
@@ -698,6 +840,7 @@ void GuiView::on_lastWorkAreaRemoved()
        updateDialogs();
 
        resetWindowTitleAndIconText();
+       updateStatusBar();
 
        if (lyxrc.open_buffers_in_tabs)
                // Nothing more to do, the window should stay open.
@@ -723,14 +866,21 @@ void GuiView::updateStatusBar()
        if (d.statusbar_timer_.isActive())
                return;
 
-       theLyXFunc().setLyXView(this);
-       statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
+       showMessage();
 }
 
 
-bool GuiView::hasFocus() const
+void GuiView::showMessage()
 {
-       return qApp->activeWindow() == this;
+       QString msg = toqstr(theGuiApp()->viewStatusMessage());
+       if (msg.isEmpty()) {
+               BufferView const * bv = currentBufferView();
+               if (bv)
+                       msg = toqstr(bv->cursor().currentState());
+               else
+                       msg = qt_("Welcome to LyX!");
+       }
+       statusBar()->showMessage(msg);
 }
 
 
@@ -754,12 +904,17 @@ bool GuiView::event(QEvent * e)
        //      break;
 
        case QEvent::WindowActivate: {
-               if (this == guiApp->currentView()) {
+               GuiView * old_view = guiApp->currentView();
+               if (this == old_view) {
                        setFocus();
                        return QMainWindow::event(e);
                }
+               if (old_view && old_view->currentBufferView()) {
+                       // save current selection to the selection buffer to allow
+                       // middle-button paste in this window.
+                       cap::saveSelection(old_view->currentBufferView()->cursor());
+               }
                guiApp->setCurrentView(this);
-               theLyXFunc().setLyXView(this);
                if (d.current_work_area_) {
                        BufferView & bv = d.current_work_area_->bufferView();
                        connectBufferView(bv);
@@ -779,39 +934,21 @@ bool GuiView::event(QEvent * e)
 
        case QEvent::ShortcutOverride: {
 
-#ifndef Q_WS_X11
-               // FIXME bug 4888
+// See bug 4888
+#if (!defined Q_WS_X11) || (QT_VERSION >= 0x040500)
                if (isFullScreen() && menuBar()->isHidden()) {
                        QKeyEvent * ke = static_cast<QKeyEvent*>(e);
                        // FIXME: we should also try to detect special LyX shortcut such as
                        // Alt-P and Alt-M. Right now there is a hack in
                        // GuiWorkArea::processKeySym() that hides again the menubar for
                        // those cases.
-                       if (ke->modifiers() & Qt::AltModifier && ke->key() != Qt::Key_Alt)
+                       if (ke->modifiers() & Qt::AltModifier && ke->key() != Qt::Key_Alt) {
                                menuBar()->show();
-                       return QMainWindow::event(e);
+                               return QMainWindow::event(e);
+                       }
                }
 #endif
-
-               if (d.current_work_area_)
-                       // Nothing special to do.
-                       return QMainWindow::event(e);
-
-               QKeyEvent * ke = static_cast<QKeyEvent*>(e);
-               // Let Qt handle menu access and the Tab keys to navigate keys to navigate
-               // between controls.
-               if (ke->modifiers() & Qt::AltModifier || ke->key() == Qt::Key_Tab 
-                       || ke->key() == Qt::Key_Backtab)
-                       return QMainWindow::event(e);
-
-               // Allow processing of shortcuts that are allowed even when no Buffer
-               // is viewed.
-               theLyXFunc().setLyXView(this);
-               KeySymbol sym;
-               setKeySymbol(&sym, ke);
-               theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
-               e->accept();
-               return true;
+               return QMainWindow::event(e);
        }
 
        default:
@@ -851,6 +988,9 @@ void GuiView::setBusy(bool busy)
 
 GuiWorkArea * GuiView::workArea(Buffer & buffer)
 {
+       if (currentWorkArea()
+           && &currentWorkArea()->bufferView().buffer() == &buffer)
+               return (GuiWorkArea *) currentWorkArea();
        if (TabWorkArea * twa = d.currentTabWorkArea())
                return twa->workArea(buffer);
        return 0;
@@ -886,14 +1026,63 @@ GuiWorkArea const * GuiView::currentWorkArea() const
 }
 
 
+GuiWorkArea * GuiView::currentWorkArea()
+{
+       return d.current_work_area_;
+}
+
+
+GuiWorkArea const * GuiView::currentMainWorkArea() const
+{
+       if (d.currentTabWorkArea() == NULL)
+               return NULL;
+       return d.currentTabWorkArea()->currentWorkArea();
+}
+
+
+GuiWorkArea * GuiView::currentMainWorkArea()
+{
+       if (d.currentTabWorkArea() == NULL)
+               return NULL;
+       return d.currentTabWorkArea()->currentWorkArea();
+}
+
+
 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
 {
-       LASSERT(wa, return);
+       LYXERR(Debug::DEBUG, "Setting current wa: " << wa << endl);
+       if (wa == NULL) {
+               d.current_work_area_ = NULL;
+               d.setBackground();
+               return;
+       }
+       GuiWorkArea * old_gwa = theGuiApp()->currentView()->currentWorkArea();
+       if (old_gwa == wa)
+               return;
+
+       if (currentBufferView())
+               cap::saveSelection(currentBufferView()->cursor());
+
+       theGuiApp()->setCurrentView(this);
        d.current_work_area_ = wa;
        for (int i = 0; i != d.splitter_->count(); ++i) {
-               if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
+               if (d.tabWorkArea(i)->setCurrentWorkArea(wa)) {
+                       //if (d.current_main_work_area_)
+                       //      d.current_main_work_area_->setFrameStyle(QFrame::NoFrame);
+                       d.current_main_work_area_ = wa;
+                       //d.current_main_work_area_->setFrameStyle(QFrame::Box | QFrame::Plain);
+                       //d.current_main_work_area_->setLineWidth(2);
+                       LYXERR(Debug::DEBUG, "Current wa: " << currentWorkArea() << ", Current main wa: " << currentMainWorkArea());
                        return;
+               }
        }
+       LYXERR(Debug::DEBUG, "This is not a tabbed wa");
+       on_currentWorkAreaChanged(wa);
+       BufferView & bv = wa->bufferView();
+       bv.cursor().fixIfBroken();
+       bv.updateMetrics();
+       wa->setUpdatesEnabled(true);
+       LYXERR(Debug::DEBUG, "Current wa: " << currentWorkArea() << ", Current main wa: " << currentMainWorkArea());
 }
 
 
@@ -904,39 +1093,47 @@ void GuiView::removeWorkArea(GuiWorkArea * wa)
                disconnectBuffer();
                disconnectBufferView();
                d.current_work_area_ = 0;
+               d.current_main_work_area_ = 0;
        }
 
+       bool found_twa = false;
        for (int i = 0; i != d.splitter_->count(); ++i) {
                TabWorkArea * twa = d.tabWorkArea(i);
-               if (!twa->removeWorkArea(wa))
-                       // Not found in this tab group.
-                       continue;
-
-               // We found and removed the GuiWorkArea.
-               if (!twa->count()) {
-                       // No more WorkAreas in this tab group, so delete it.
-                       delete twa;
+               if (twa->removeWorkArea(wa)) {
+                       // Found in this tab group, and deleted the GuiWorkArea.
+                       found_twa = true;
+                       if (twa->count() != 0) {
+                               if (d.current_work_area_ == 0)
+                                       // This means that we are closing the current GuiWorkArea, so
+                                       // switch to the next GuiWorkArea in the found TabWorkArea.
+                                       setCurrentWorkArea(twa->currentWorkArea());
+                       } else {
+                               // No more WorkAreas in this tab group, so delete it.
+                               delete twa;
+                       }
                        break;
                }
+       }
 
-               if (d.current_work_area_)
-                       // This means that we are not closing the current GuiWorkArea;
-                       break;
+       // It is not a tabbed work area (i.e., the search work area), so it
+       // should be deleted by other means.
+       LASSERT(found_twa, /* */);
 
-               // Switch to the next GuiWorkArea in the found TabWorkArea.
-               d.current_work_area_ = twa->currentWorkArea();
-               break;
+       if (d.current_work_area_ == 0) {
+               if (d.splitter_->count() != 0) {
+                       TabWorkArea * twa = d.currentTabWorkArea();
+                       setCurrentWorkArea(twa->currentWorkArea());
+               } else {
+                       // No more work areas, switch to the background widget.
+                       setCurrentWorkArea(0);
+               }
        }
-
-       if (d.splitter_->count() == 0)
-               // No more work area, switch to the background widget.
-               d.setBackground();
 }
 
 
-void GuiView::setLayoutDialog(GuiLayoutBox * layout)
+LayoutBox * GuiView::getLayoutDialog() const
 {
-       d.layout_ = layout;
+       return d.layout_;
 }
 
 
@@ -969,30 +1166,15 @@ void GuiView::updateToolbars()
 }
 
 
-Buffer * GuiView::buffer()
-{
-       if (d.current_work_area_)
-               return &d.current_work_area_->bufferView().buffer();
-       return 0;
-}
-
-
-Buffer const * GuiView::buffer() const
-{
-       if (d.current_work_area_)
-               return &d.current_work_area_->bufferView().buffer();
-       return 0;
-}
-
-
 void GuiView::setBuffer(Buffer * newBuffer)
 {
+       LYXERR(Debug::DEBUG, "Setting buffer: " << newBuffer << endl);
        LASSERT(newBuffer, return);
        setBusy(true);
 
        GuiWorkArea * wa = workArea(*newBuffer);
        if (wa == 0) {
-               updateLabels(*newBuffer->masterBuffer());
+               newBuffer->masterBuffer()->updateLabels();
                wa = addWorkArea(*newBuffer);
        } else {
                //Disconnect the old buffer...there's no new one.
@@ -1015,7 +1197,7 @@ void GuiView::connectBuffer(Buffer & buf)
 void GuiView::disconnectBuffer()
 {
        if (d.current_work_area_)
-               d.current_work_area_->bufferView().setGuiDelegate(0);
+               d.current_work_area_->bufferView().buffer().setGuiDelegate(0);
 }
 
 
@@ -1032,15 +1214,20 @@ void GuiView::disconnectBufferView()
 }
 
 
-void GuiView::errors(string const & error_type)
+void GuiView::errors(string const & error_type, bool from_master)
 {
-       ErrorList & el = buffer()->errorList(error_type);
+       ErrorList & el = from_master ? 
+               documentBufferView()->buffer().masterBuffer()->errorList(error_type)
+               : documentBufferView()->buffer().errorList(error_type);
+       string data = error_type;
+       if (from_master)
+               data = "from_master|" + error_type;
        if (!el.empty())
-               showDialog("errorlist", error_type);
+               showDialog("errorlist", data);
 }
 
 
-void GuiView::updateTocItem(std::string const & type, DocIterator const & dit)
+void GuiView::updateTocItem(string const & type, DocIterator const & dit)
 {
        d.toc_models_.updateItem(toqstr(type), dit);
 }
@@ -1048,7 +1235,7 @@ void GuiView::updateTocItem(std::string const & type, DocIterator const & dit)
 
 void GuiView::structureChanged()
 {
-       d.toc_models_.reset(view());
+       d.toc_models_.reset(documentBufferView());
        // Navigator needs more than a simple update in this case. It needs to be
        // rebuilt.
        updateDialog("toc", "");
@@ -1070,18 +1257,71 @@ void GuiView::updateDialog(string const & name, string const & data)
 }
 
 
-BufferView * GuiView::view()
+BufferView * GuiView::documentBufferView()
+{
+       return currentMainWorkArea()
+               ? &currentMainWorkArea()->bufferView()
+               : 0;
+}
+
+
+BufferView const * GuiView::documentBufferView() const 
+{
+       return currentMainWorkArea()
+               ? &currentMainWorkArea()->bufferView()
+               : 0;
+}
+
+
+BufferView * GuiView::currentBufferView()
+{
+       return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
+}
+
+
+BufferView const * GuiView::currentBufferView() const
 {
        return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
 }
 
 
+#if (QT_VERSION >= 0x040400)
+static docstring saveAndDestroyBuffer(Buffer * buffer, FileName const & fname)
+{
+       bool failed = true;
+       FileName const tmp_ret = FileName::tempName("lyxauto");
+       if (!tmp_ret.empty()) {
+               if (buffer->writeFile(tmp_ret))
+                       failed = !tmp_ret.moveTo(fname);
+       }
+       if (failed) {
+               // failed to write/rename tmp_ret so try writing direct
+               failed = buffer->writeFile(fname);
+       }
+       delete buffer;
+       return failed
+               ? _("Automatic save failed!")
+               : _("Automatic save done.");
+}
+#endif
+
+
 void GuiView::autoSave()
 {
        LYXERR(Debug::INFO, "Running autoSave()");
 
-       if (buffer())
-               view()->buffer().autoSave();
+       Buffer * buffer = documentBufferView()
+               ? &documentBufferView()->buffer() : 0;
+       if (!buffer)
+               return;
+
+#if (QT_VERSION >= 0x040400)
+       QFuture<docstring> f = QtConcurrent::run(saveAndDestroyBuffer, buffer->clone(),
+               buffer->getAutosaveFilename());
+       d.autosave_watcher_.setFuture(f);
+#else
+       buffer->autoSave();
+#endif
 }
 
 
@@ -1095,34 +1335,105 @@ void GuiView::resetAutosaveTimers()
 bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
 {
        bool enable = true;
-       Buffer * buf = buffer();
-
-       /* 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-related.
+       Buffer * buf = currentBufferView()
+               ? &currentBufferView()->buffer() : 0;
+       Buffer * doc_buffer = documentBufferView()
+               ? &(documentBufferView()->buffer()) : 0;
+
+       // 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 true;
+       }
 
-          Note that this code is not perfect, as bug 1941 attests:
-          http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
-       */
-       if (cmd.origin == FuncRequest::MENU && !hasFocus())
-               buf = 0;
+       if (cmd.origin == FuncRequest::TOC) {
+               GuiToc * toc = static_cast<GuiToc*>(findOrBuild("toc", false));
+               FuncStatus fs;
+               if (toc->getStatus(documentBufferView()->cursor(), cmd, fs))
+                       flag |= fs;
+               else
+                       flag.setEnabled(false);
+               return true;
+       }
 
        switch(cmd.action) {
+       case LFUN_BUFFER_IMPORT:
+               break;
+
+       case LFUN_MASTER_BUFFER_UPDATE:
+       case LFUN_MASTER_BUFFER_VIEW: 
+               enable = doc_buffer && doc_buffer->parent() != 0
+                       && !d.preview_watcher_.isRunning();
+               break;
+
+       case LFUN_BUFFER_UPDATE:
+       case LFUN_BUFFER_VIEW: {
+               if (!doc_buffer || d.preview_watcher_.isRunning()) {
+                       enable = false;
+                       break;
+               }
+               string format = to_utf8(cmd.argument());
+               if (cmd.argument().empty())
+                       format = doc_buffer->getDefaultOutputFormat();
+               enable = doc_buffer->isExportableFormat(format);
+               break;
+       }
+
+       case LFUN_BUFFER_RELOAD:
+               enable = doc_buffer && !doc_buffer->isUnnamed()
+                       && doc_buffer->fileName().exists()
+                       && (!doc_buffer->isClean()
+                          || doc_buffer->isExternallyModified(Buffer::timestamp_method));
+               break;
+
+       case LFUN_BUFFER_CHILD_OPEN:
+               enable = doc_buffer;
+               break;
+
        case LFUN_BUFFER_WRITE:
-               enable = buf && (buf->isUnnamed() || !buf->isClean());
+               enable = doc_buffer && (doc_buffer->isUnnamed() || !doc_buffer->isClean());
+               break;
+
+       //FIXME: This LFUN should be moved to GuiApplication.
+       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_BUFFER_WRITE_AS:
-               enable = buf;
+               enable = doc_buffer;
+               break;
+
+       case LFUN_BUFFER_CLOSE:
+               enable = doc_buffer;
+               break;
+
+       case LFUN_BUFFER_CLOSE_ALL:
+               enable = theBufferList().last() != theBufferList().first();
                break;
 
        case LFUN_SPLIT_VIEW:
                if (cmd.getArg(0) == "vertical")
-                       enable = buf && (d.splitter_->count() == 1 ||
+                       enable = doc_buffer && (d.splitter_->count() == 1 ||
                                         d.splitter_->orientation() == Qt::Vertical);
                else
-                       enable = buf && (d.splitter_->count() == 1 ||
+                       enable = doc_buffer && (d.splitter_->count() == 1 ||
                                         d.splitter_->orientation() == Qt::Horizontal);
                break;
 
@@ -1135,49 +1446,53 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                        flag.setOnOff(t->isVisible());
                break;
 
+       case LFUN_DROP_LAYOUTS_CHOICE:
+               enable = buf; 
+               break;
+
        case LFUN_UI_TOGGLE:
                flag.setOnOff(isFullScreen());
                break;
 
+       case LFUN_DIALOG_DISCONNECT_INSET:
+               break;
+
+       case LFUN_DIALOG_HIDE:
+               // FIXME: should we check if the dialog is shown?
+               break;
+
        case LFUN_DIALOG_TOGGLE:
                flag.setOnOff(isDialogVisible(cmd.getArg(0)));
                // fall through to set "enable"
        case LFUN_DIALOG_SHOW: {
                string const name = cmd.getArg(0);
-               if (!buf)
+               if (!doc_buffer)
                        enable = name == "aboutlyx"
                                || name == "file" //FIXME: should be removed.
                                || name == "prefs"
-                               || name == "texinfo";
+                               || name == "texinfo"
+                               || name == "progress"
+                               || name == "compare";
                else if (name == "print")
-                       enable = buf->isExportable("dvi")
+                       enable = doc_buffer->isExportable("dvi")
                                && lyxrc.print_command != "none";
-               else if (name == "character") {
-                       if (!view())
-                               enable = false;
-                       else {
-                               InsetCode ic = view()->cursor().inset().lyxCode();
-                               enable = ic != ERT_CODE && ic != LISTINGS_CODE;
-                       }
-               }
-               else if (name == "symbols") {
-                       if (!view() || view()->cursor().inMathed())
+               else if (name == "character" || name == "symbols") {
+                       if (!buf || buf->isReadonly()
+                               || !currentBufferView()->cursor().inTexted())
                                enable = false;
                        else {
-                               InsetCode ic = view()->cursor().inset().lyxCode();
-                               enable = ic != ERT_CODE && ic != LISTINGS_CODE;
+                               // FIXME we should consider passthru
+                               // paragraphs too.
+                               Inset const & in = currentBufferView()->cursor().inset();
+                               enable = !in.getLayout().isPassThru();
                        }
                }
                else if (name == "latexlog")
-                       enable = FileName(buf->logName()).isReadableFile();
+                       enable = FileName(doc_buffer->logName()).isReadableFile();
                else if (name == "spellchecker")
-#if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
-                       enable = !buf->isReadonly();
-#else
-                       enable = false;
-#endif
+                       enable = theSpellChecker() && !doc_buffer->isReadonly();
                else if (name == "vclog")
-                       enable = buf->lyxvc().inUse();
+                       enable = doc_buffer->lyxvc().inUse();
                break;
        }
 
@@ -1188,44 +1503,41 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                break;
        }
 
-       case LFUN_INSET_APPLY: {
-               string const name = cmd.getArg(0);
-               Inset * inset = getOpenInset(name);
-               if (inset) {
-                       FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
-                       FuncStatus fs;
-                       if (!inset->getStatus(view()->cursor(), fr, fs)) {
-                               // Every inset is supposed to handle this
-                               LASSERT(false, break);
-                       }
-                       flag |= fs;
-               } else {
-                       FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
-                       flag |= lyx::getStatus(fr);
-               }
-               enable = flag.enabled();
+       case LFUN_COMMAND_EXECUTE:
+       case LFUN_MESSAGE:
+       case LFUN_MENU_OPEN:
+               // Nothing to check.
                break;
-       }
 
        case LFUN_COMPLETION_INLINE:
                if (!d.current_work_area_
-                   || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
+                   || !d.current_work_area_->completer().inlinePossible(
+                       currentBufferView()->cursor()))
                    enable = false;
                break;
 
        case LFUN_COMPLETION_POPUP:
                if (!d.current_work_area_
-                   || !d.current_work_area_->completer().popupPossible(view()->cursor()))
+                   || !d.current_work_area_->completer().popupPossible(
+                       currentBufferView()->cursor()))
                    enable = false;
                break;
 
        case LFUN_COMPLETION_COMPLETE:
                if (!d.current_work_area_
-                       || !d.current_work_area_->completer().inlinePossible(view()->cursor()))
+                       || !d.current_work_area_->completer().inlinePossible(
+                       currentBufferView()->cursor()))
                    enable = false;
                break;
 
        case LFUN_COMPLETION_ACCEPT:
+               if (!d.current_work_area_
+                   || (!d.current_work_area_->completer().popupVisible()
+                       && !d.current_work_area_->completer().inlineVisible()
+                       && !d.current_work_area_->completer().completionAvailable()))
+                       enable = false;
+               break;
+
        case LFUN_COMPLETION_CANCEL:
                if (!d.current_work_area_
                    || (!d.current_work_area_->completer().popupVisible()
@@ -1233,6 +1545,60 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                        enable = false;
                break;
 
+       case LFUN_BUFFER_ZOOM_OUT:
+               enable = doc_buffer && lyxrc.zoom > 10;
+               break;
+
+       case LFUN_BUFFER_ZOOM_IN:
+               enable = doc_buffer;
+               break;
+       
+       case LFUN_BUFFER_NEXT:
+       case LFUN_BUFFER_PREVIOUS:
+               // FIXME: should we check is there is an previous or next buffer?
+               break;
+       case LFUN_BUFFER_SWITCH:
+               // toggle on the current buffer, but do not toggle off
+               // the other ones (is that a good idea?)
+               if (doc_buffer
+                       && to_utf8(cmd.argument()) == doc_buffer->absFileName())
+                       flag.setOnOff(true);
+               break;
+
+       case LFUN_VC_REGISTER:
+               enable = doc_buffer && !doc_buffer->lyxvc().inUse();
+               break;
+       case LFUN_VC_CHECK_IN:
+               enable = doc_buffer && doc_buffer->lyxvc().checkInEnabled();
+               break;
+       case LFUN_VC_CHECK_OUT:
+               enable = doc_buffer && doc_buffer->lyxvc().checkOutEnabled();
+               break;
+       case LFUN_VC_LOCKING_TOGGLE:
+               enable = doc_buffer && !doc_buffer->isReadonly()
+                       && doc_buffer->lyxvc().lockingToggleEnabled();
+               flag.setOnOff(enable && !doc_buffer->lyxvc().locker().empty());
+               break;
+       case LFUN_VC_REVERT:
+               enable = doc_buffer && doc_buffer->lyxvc().inUse();
+               break;
+       case LFUN_VC_UNDO_LAST:
+               enable = doc_buffer && doc_buffer->lyxvc().undoLastEnabled();
+               break;
+       case LFUN_VC_REPO_UPDATE:
+               enable = doc_buffer && doc_buffer->lyxvc().inUse();
+               break;
+       case LFUN_VC_COMMAND: {
+               if (cmd.argument().empty())
+                       enable = false;
+               if (!doc_buffer && contains(cmd.getArg(0), 'D'))
+                       enable = false;
+               break;
+       }
+
+       case LFUN_SERVER_GOTO_FILE_ROW:
+               break;
+
        default:
                return false;
        }
@@ -1279,7 +1645,7 @@ Buffer * GuiView::loadDocument(FileName const & filename, bool tolastfiles)
        if (lyxrc.use_lastfilepos) {
                LastFilePosSection::FilePos filepos =
                        theSession().lastFilePos().load(filename);
-               view()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
+               documentBufferView()->moveToPosition(filepos.pit, filepos.pos, 0, 0);
        }
 
        if (tolastfiles)
@@ -1294,8 +1660,8 @@ void GuiView::openDocument(string const & fname)
 {
        string initpath = lyxrc.document_path;
 
-       if (buffer()) {
-               string const trypath = buffer()->filePath();
+       if (documentBufferView()) {
+               string const trypath = documentBufferView()->buffer().filePath();
                // If directory is writeable, use this as default.
                if (FileName(trypath).isDirWritable())
                        initpath = trypath;
@@ -1312,7 +1678,8 @@ void GuiView::openDocument(string const & fname)
                QStringList filter(qt_("LyX Documents (*.lyx)"));
                filter << qt_("LyX-1.3.x Documents (*.lyx13)")
                        << qt_("LyX-1.4.x Documents (*.lyx14)")
-                       << qt_("LyX-1.5.x Documents (*.lyx15)");
+                       << qt_("LyX-1.5.x Documents (*.lyx15)")
+                       << qt_("LyX-1.6.x Documents (*.lyx16)");
                FileDialog::Result result =
                        dlg.open(toqstr(initpath), filter);
 
@@ -1338,7 +1705,7 @@ void GuiView::openDocument(string const & fname)
 
        if (!fullname.onlyPath().isDirectory()) {
                Alert::warning(_("Invalid filename"),
-                               bformat(_("The directory in the given path\n%1$s\ndoes not exists."),
+                               bformat(_("The directory in the given path\n%1$s\ndoes not exist."),
                                from_utf8(fullname.absFilename())));
                return;
        }
@@ -1357,8 +1724,7 @@ void GuiView::openDocument(string const & fname)
        docstring str2;
        Buffer * buf = loadDocument(fullname);
        if (buf) {
-               updateLabels(*buf);
-               
+               buf->updateLabels();
                setBuffer(buf);
                buf->errors("Parse");
                str2 = bformat(_("Document %1$s opened."), disp_fn);
@@ -1407,7 +1773,7 @@ static bool import(GuiView * lv, FileName const & filename,
                Buffer * buf = lv->loadDocument(lyxfile);
                if (!buf)
                        return false;
-               updateLabels(*buf);
+               buf->updateLabels();
                lv->setBuffer(buf);
                buf->errors("Parse");
        } else {
@@ -1419,8 +1785,9 @@ static bool import(GuiView * lv, FileName const & filename,
                string filename2 = (loader_format == format) ? filename.absFilename()
                        : support::changeExtension(filename.absFilename(),
                                          formats.extension(loader_format));
-               lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs);
-               theLyXFunc().setLyXView(lv);
+               lv->currentBufferView()->insertPlaintextFile(FileName(filename2),
+                       as_paragraphs);
+               guiApp->setCurrentView(lv);
                lyx::dispatch(FuncRequest(LFUN_MARK_OFF));
        }
 
@@ -1438,10 +1805,8 @@ void GuiView::importDocument(string const & argument)
        // need user interaction
        if (filename.empty()) {
                string initpath = lyxrc.document_path;
-
-               Buffer const * buf = buffer();
-               if (buf) {
-                       string const trypath = buf->filePath();
+               if (documentBufferView()) {
+                       string const trypath = documentBufferView()->buffer().filePath();
                        // If directory is writeable, use this as default.
                        if (FileName(trypath).isDirWritable())
                                initpath = trypath;
@@ -1523,32 +1888,40 @@ void GuiView::importDocument(string const & argument)
 void GuiView::newDocument(string const & filename, bool from_template)
 {
        FileName initpath(lyxrc.document_path);
-       Buffer * buf = buffer();
-       if (buf) {
-               FileName const trypath(buf->filePath());
+       if (documentBufferView()) {
+               FileName const trypath(documentBufferView()->buffer().filePath());
                // If directory is writeable, use this as default.
                if (trypath.isDirWritable())
                        initpath = trypath;
        }
 
-       string templatefile = from_template ?
-               selectTemplateFile().absFilename() : string();
+       string templatefile;
+       if (from_template) {
+               templatefile = selectTemplateFile().absFilename();
+               if (templatefile.empty())
+                       return;
+       }
+       
        Buffer * b;
        if (filename.empty())
-               b = newUnnamedFile(templatefile, initpath);
+               b = newUnnamedFile(initpath, to_utf8(_("newfile")), templatefile);
        else
                b = newFile(filename, templatefile, true);
 
        if (b)
                setBuffer(b);
-       // Ensure the cursor is correctly positionned on screen.
-       view()->showCursor();
+
+       // If no new document could be created, it is unsure 
+       // whether there is a valid BufferView.
+       if (currentBufferView())
+               // Ensure the cursor is correctly positioned on screen.
+               currentBufferView()->showCursor();
 }
 
 
 void GuiView::insertLyXFile(docstring const & fname)
 {
-       BufferView * bv = view();
+       BufferView * bv = documentBufferView();
        if (!bv)
                return;
 
@@ -1598,10 +1971,15 @@ void GuiView::insertLyXFile(docstring const & fname)
 void GuiView::insertPlaintextFile(docstring const & fname,
        bool asParagraph)
 {
-       BufferView * bv = view();
+       BufferView * bv = documentBufferView();
        if (!bv)
                return;
 
+       if (!fname.empty() && !FileName::isAbsolute(to_utf8(fname))) {
+               message(_("Absolute filename expected."));
+               return;
+       }
+
        // FIXME UNICODE
        FileName filename(to_utf8(fname));
        
@@ -1614,7 +1992,7 @@ void GuiView::insertPlaintextFile(docstring const & fname,
                LFUN_FILE_INSERT_PLAINTEXT_PARA : LFUN_FILE_INSERT_PLAINTEXT));
 
        FileDialog::Result result = dlg.open(toqstr(bv->buffer().filePath()),
-               QStringList());
+               QStringList(qt_("All Files (*)")));
 
        if (result.first == FileDialog::Later)
                return;
@@ -1645,7 +2023,7 @@ bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
                // Switch to this Buffer.
                setBuffer(&b);
 
-               /// No argument? Ask user through dialog.
+               // No argument? Ask user through dialog.
                // FIXME UNICODE
                FileDialog dlg(qt_("Choose a filename to save document as"),
                                   LFUN_BUFFER_WRITE_AS);
@@ -1687,6 +2065,8 @@ bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
                }
        }
 
+       FileName oldauto = b.getAutosaveFilename();
+
        // Ok, change the name of the buffer
        b.setFileName(fname.absFilename());
        b.markDirty();
@@ -1694,10 +2074,15 @@ bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
        b.setUnnamed(false);
        b.saveCheckSum(fname);
 
+       // bring the autosave file with us, just in case.
+       b.moveAutosaveFile(oldauto);
+       
        if (!saveBuffer(b)) {
+               oldauto = b.getAutosaveFilename();
                b.setFileName(oldname.absFilename());
                b.setUnnamed(unnamed);
                b.saveCheckSum(oldname);
+               b.moveAutosaveFile(oldauto);
                return false;
        }
 
@@ -1707,6 +2092,9 @@ bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
 
 bool GuiView::saveBuffer(Buffer & b)
 {
+       if (workArea(b) && workArea(b)->inDialogMode())
+               return true;
+
        if (b.isUnnamed())
                return renameBuffer(b, docstring());
 
@@ -1740,30 +2128,169 @@ bool GuiView::saveBuffer(Buffer & b)
 }
 
 
-bool GuiView::closeBuffer()
+bool GuiView::hideWorkArea(GuiWorkArea * wa)
 {
-       Buffer * buf = buffer();
-       return buf && closeBuffer(*buf);
+       return closeWorkArea(wa, false);
 }
 
 
-bool GuiView::closeBuffer(Buffer & buf, bool tolastopened)
+bool GuiView::closeWorkArea(GuiWorkArea * wa)
 {
+       Buffer & buf = wa->bufferView().buffer();
+       return closeWorkArea(wa, !buf.parent());
+}
+
+
+bool GuiView::closeBuffer()
+{
+       GuiWorkArea * wa = currentMainWorkArea();
+       setCurrentWorkArea(wa);
+       Buffer & buf = wa->bufferView().buffer();
+       return wa && closeWorkArea(wa, !buf.parent());
+}
+
+
+void GuiView::writeSession() const {
+       GuiWorkArea const * active_wa = currentMainWorkArea();
+       for (int i = 0; i < d.splitter_->count(); ++i) {
+               TabWorkArea * twa = d.tabWorkArea(i);
+               for (int j = 0; j < twa->count(); ++j) {
+                       GuiWorkArea * wa = static_cast<GuiWorkArea *>(twa->widget(j));
+                       Buffer & buf = wa->bufferView().buffer();
+                       theSession().lastOpened().add(buf.fileName(), wa == active_wa);
+               }
+       }
+}
+
+
+bool GuiView::closeBufferAll()
+{
+       // Close the workareas in all other views
+       QList<int> const ids = guiApp->viewIds();
+       for (int i = 0; i != ids.size(); ++i) {
+               if (id_ != ids[i] && !guiApp->view(ids[i]).closeWorkAreaAll())
+                       return false;
+       }
+
+       // Close our own workareas
+       if (!closeWorkAreaAll())
+               return false;
+
+       // Now close the hidden buffers. We prevent hidden buffers from being
+       // dirty, so we can just close them.
+       theBufferList().closeAll();
+       return true;
+}
+
+
+bool GuiView::closeWorkAreaAll()
+{
+       setCurrentWorkArea(currentMainWorkArea());
+
+       // We might be in a situation that there is still a tabWorkArea, but
+       // there are no tabs anymore. This can happen when we get here after a 
+       // TabWorkArea::lastWorkAreaRemoved() signal. Therefore we count how
+       // many TabWorkArea's have no documents anymore.
+       int empty_twa = 0;
+
+       // We have to call count() each time, because it can happen that
+       // more than one splitter will disappear in one iteration (bug 5998).
+       for (; d.splitter_->count() > empty_twa; ) {
+               TabWorkArea * twa = d.tabWorkArea(empty_twa);
+
+               if (twa->count() == 0)
+                       ++empty_twa;
+               else {
+                       setCurrentWorkArea(twa->currentWorkArea());
+                       if (!closeTabWorkArea(twa))
+                               return false;
+               }
+       }
+       return true;
+}
+
+
+bool GuiView::closeWorkArea(GuiWorkArea * wa, bool close_buffer)
+{
+       if (!wa)
+               return false;
+
+       Buffer & buf = wa->bufferView().buffer();
+
+       if (close_buffer)
+               return closeBuffer(buf);
+       else {
+               if (!inMultiTabs(wa))
+                       if (!saveBufferIfNeeded(buf, true))
+                               return false;
+               removeWorkArea(wa);
+               return true;
+       }
+}
+
+
+bool GuiView::closeBuffer(Buffer & buf)
+{
+       // If we are in a close_event all children will be closed in some time,
+       // so no need to do it here. This will ensure that the children end up
+       // in the session file in the correct order. If we close the master
+       // buffer, we can close or release the child buffers here too.
+       if (!closing_) {
+               vector<Buffer *> clist = buf.getChildren(false);
+               for (vector<Buffer *>::const_iterator it = clist.begin();
+                        it != clist.end(); ++it) {
+                       // If a child is dirty, do not close
+                       // without user intervention
+                       //FIXME: should we look in other tabworkareas?
+                       Buffer * child_buf = *it;
+                       GuiWorkArea * child_wa = workArea(*child_buf);
+                       if (child_wa) {
+                               if (!closeWorkArea(child_wa, true))
+                                       return false;
+                       } else
+                               theBufferList().releaseChild(&buf, child_buf);
+               }
+       }
        // goto bookmark to update bookmark pit.
        //FIXME: we should update only the bookmarks related to this buffer!
+       LYXERR(Debug::DEBUG, "GuiView::closeBuffer()");
        for (size_t i = 0; i < theSession().bookmarks().size(); ++i)
                theLyXFunc().gotoBookmark(i+1, false, false);
 
-       if (buf.isClean() || buf.paragraphs().empty()) {
-               if (buf.masterBuffer() == &buf && tolastopened)
-                       theSession().lastOpened().add(buf.fileName());
-               if (buf.parent())
-                       // Don't close child documents.
-                       removeWorkArea(d.current_work_area_);
-               else
-                       theBufferList().release(&buf);
+       if (saveBufferIfNeeded(buf, false)) {
+               theBufferList().release(&buf);
                return true;
        }
+       return false;
+}
+
+
+bool GuiView::closeTabWorkArea(TabWorkArea * twa)
+{
+       while (twa == d.currentTabWorkArea()) {
+               twa->setCurrentIndex(twa->count()-1);
+
+               GuiWorkArea * wa = twa->currentWorkArea();
+               Buffer & b = wa->bufferView().buffer();
+
+               // We only want to close the buffer if the same buffer is not visible
+               // in another view, and if this is not a child and if we are closing
+               // a view (not a tabgroup).
+               bool const close_buffer = 
+                       !inMultiViews(wa) && !b.parent() && closing_;
+
+               if (!closeWorkArea(wa, close_buffer))
+                       return false;
+       }
+       return true;
+}
+
+
+bool GuiView::saveBufferIfNeeded(Buffer & buf, bool hiding)
+{
+       if (buf.isClean() || buf.paragraphs().empty())
+               return true;
+
        // Switch to this Buffer.
        setBuffer(&buf);
 
@@ -1778,10 +2305,21 @@ bool GuiView::closeBuffer(Buffer & buf, bool tolastopened)
        raise();
        activateWindow();
 
-       docstring const text = bformat(_("The document %1$s has unsaved changes."
-               "\n\nDo you want to save the document or discard the changes?"), file);
-       int const ret = Alert::prompt(_("Save changed document?"),
-               text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
+       int ret;
+       if (hiding && buf.isUnnamed()) {
+               docstring const text = bformat(_("The document %1$s has not been "
+                                            "saved yet.\n\nDo you want to save "
+                                            "the document?"), file);
+               ret = Alert::prompt(_("Save new document?"), 
+                       text, 0, 1, _("&Save"), _("&Cancel"));
+               if (ret == 1)
+                       ++ret;
+       } else {
+               docstring const text = bformat(_("The document %1$s has unsaved changes."
+                       "\n\nDo you want to save the document or discard the changes?"), file);
+               ret = Alert::prompt(_("Save changed document?"),
+                       text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
+       }
 
        switch (ret) {
        case 0:
@@ -1792,51 +2330,503 @@ bool GuiView::closeBuffer(Buffer & buf, bool tolastopened)
                // if we crash after this we could
                // have no autosave file but I guess
                // this is really improbable (Jug)
-               removeAutosaveFile(buf.absFileName());
+               buf.removeAutosaveFile();
+               if (hiding)
+                       // revert all changes
+                       buf.reload();
+               buf.markClean();
                break;
        case 2:
                return false;
        }
+       return true;
+}
 
-       // save file names to .lyx/session
-       // if master/slave are both open, do not save slave since it
-       // will be automatically loaded when the master is loaded
-       if (buf.masterBuffer() == &buf && tolastopened)
-               theSession().lastOpened().add(buf.fileName());
 
-       if (buf.parent())
-               // Don't close child documents.
-               removeWorkArea(d.current_work_area_);
-       else
-               theBufferList().release(&buf);
+bool GuiView::inMultiTabs(GuiWorkArea * wa)
+{
+       Buffer & buf = wa->bufferView().buffer();
 
+       for (int i = 0; i != d.splitter_->count(); ++i) {
+               GuiWorkArea * wa_ = d.tabWorkArea(i)->workArea(buf);
+               if (wa_ && wa_ != wa)
+                       return true;
+       }
+       return inMultiViews(wa);
+}
+
+
+bool GuiView::inMultiViews(GuiWorkArea * wa)
+{
+       QList<int> const ids = guiApp->viewIds();
+       Buffer & buf = wa->bufferView().buffer();
+
+       int found_twa = 0;
+       for (int i = 0; i != ids.size() && found_twa <= 1; ++i) {
+               if (id_ == ids[i])
+                       continue;
+               
+               if (guiApp->view(ids[i]).workArea(buf))
+                       return true;
+       }
+       return false;
+}
+
+
+void GuiView::gotoNextOrPreviousBuffer(NextOrPrevious np)
+{
+       Buffer * const curbuf = documentBufferView()
+               ? &documentBufferView()->buffer() : 0;
+       Buffer * nextbuf = curbuf;
+       while (true) {
+               if (np == NEXTBUFFER)
+                       nextbuf = theBufferList().next(nextbuf);
+               else
+                       nextbuf = theBufferList().previous(nextbuf);
+               if (nextbuf == curbuf)
+                       break;
+               if (nextbuf == 0) {
+                       nextbuf = curbuf;
+                       break;
+               }
+               if (workArea(*nextbuf))
+                       break;
+       }
+       setBuffer(nextbuf);
+}
+
+
+/// make sure the document is saved
+static bool ensureBufferClean(Buffer * buffer)
+{
+       LASSERT(buffer, return false);
+       if (buffer->isClean() && !buffer->isUnnamed())
+               return true;
+
+       docstring const file = buffer->fileName().displayName(30);
+       docstring title;
+       docstring text;
+       if (!buffer->isUnnamed()) {
+               text = bformat(_("The document %1$s has unsaved "
+                                            "changes.\n\nDo you want to save "
+                                            "the document?"), file);
+               title = _("Save changed document?");
+               
+       } else {
+               text = bformat(_("The document %1$s has not been "
+                                            "saved yet.\n\nDo you want to save "
+                                            "the document?"), file);
+               title = _("Save new document?");
+       }
+       int const ret = Alert::prompt(title, text, 0, 1, _("&Save"), _("&Cancel"));
+
+       if (ret == 0)
+               dispatch(FuncRequest(LFUN_BUFFER_WRITE));
+
+       return buffer->isClean() && !buffer->isUnnamed();
+}
+
+
+void GuiView::reloadBuffer()
+{
+       Buffer * buf = &documentBufferView()->buffer();
+       buf->reload();
+}
+
+
+void GuiView::checkExternallyModifiedBuffers()
+{
+       BufferList::iterator bit = theBufferList().begin();
+       BufferList::iterator const bend = theBufferList().end();
+       for (; bit != bend; ++bit) {
+               if ((*bit)->fileName().exists()
+                   && (*bit)->isExternallyModified(Buffer::checksum_method)) {
+                       docstring text = bformat(_("Document \n%1$s\n has been externally modified."
+                                       " Reload now? Any local changes will be lost."),
+                                       from_utf8((*bit)->absFileName()));
+                       int const ret = Alert::prompt(_("Reload externally changed document?"),
+                                               text, 0, 1, _("&Reload"), _("&Cancel"));
+                       if (!ret)
+                               (*bit)->reload();
+               }
+       }
+}
+
+
+//FIXME use a DispatchResult object to transmit messages
+void GuiView::dispatchVC(FuncRequest const & cmd)
+{
+       // message for statusbar
+       string msg;
+       Buffer * buffer = documentBufferView()
+               ? &(documentBufferView()->buffer()) : 0;
+
+       switch (cmd.action) {
+       case LFUN_VC_REGISTER:
+               if (!buffer || !ensureBufferClean(buffer))
+                       break;
+               if (!buffer->lyxvc().inUse()) {
+                       if (buffer->lyxvc().registrer())
+                               reloadBuffer();
+               }
+               break;
+
+       case LFUN_VC_CHECK_IN:
+               if (!buffer || !ensureBufferClean(buffer))
+                       break;
+               if (buffer->lyxvc().inUse() && !buffer->isReadonly()) {
+                       msg = buffer->lyxvc().checkIn();
+                       if (!msg.empty())
+                               reloadBuffer();
+               }
+               break;
+
+       case LFUN_VC_CHECK_OUT:
+               if (!buffer || !ensureBufferClean(buffer))
+                       break;
+               if (buffer->lyxvc().inUse()) {
+                       msg = buffer->lyxvc().checkOut();
+                       reloadBuffer();
+               }
+               break;
+
+       case LFUN_VC_LOCKING_TOGGLE:
+               LASSERT(buffer, return);
+               if (!ensureBufferClean(buffer) || buffer->isReadonly())
+                       break;
+               if (buffer->lyxvc().inUse()) {
+                       string res = buffer->lyxvc().lockingToggle();
+                       if (res.empty()) {
+                               frontend::Alert::error(_("Revision control error."),
+                               _("Error when setting the locking property."));
+                       } else {
+                               msg = res;
+                               reloadBuffer();
+                       }
+               }
+               break;
+
+       case LFUN_VC_REVERT:
+               LASSERT(buffer, return);
+               buffer->lyxvc().revert();
+               reloadBuffer();
+               break;
+
+       case LFUN_VC_UNDO_LAST:
+               LASSERT(buffer, return);
+               buffer->lyxvc().undoLast();
+               reloadBuffer();
+               break;
+
+       case LFUN_VC_REPO_UPDATE:
+               LASSERT(buffer, return);
+               if (ensureBufferClean(buffer)) {
+                       msg = buffer->lyxvc().repoUpdate();
+                       checkExternallyModifiedBuffers();
+               }
+               break;
+
+       case LFUN_VC_COMMAND: {
+               string flag = cmd.getArg(0);
+               if (buffer && contains(flag, 'R') && !ensureBufferClean(buffer))
+                       break;
+               docstring message;
+               if (contains(flag, 'M')) {
+                       if (!Alert::askForText(message, _("LyX VC: Log Message")))
+                               break;
+               }
+               string path = cmd.getArg(1);
+               if (contains(path, "$$p") && buffer)
+                       path = subst(path, "$$p", buffer->filePath());
+               LYXERR(Debug::LYXVC, "Directory: " << path);
+               FileName pp(path);
+               if (!pp.isReadableDirectory()) {
+                       lyxerr << _("Directory is not accessible.") << endl;
+                       break;
+               }
+               support::PathChanger p(pp);
+
+               string command = cmd.getArg(2);
+               if (command.empty())
+                       break;
+               if (buffer) {
+                       command = subst(command, "$$i", buffer->absFileName());
+                       command = subst(command, "$$p", buffer->filePath());
+               }
+               command = subst(command, "$$m", to_utf8(message));
+               LYXERR(Debug::LYXVC, "Command: " << command);
+               Systemcall one;
+               one.startscript(Systemcall::Wait, command);
+
+               if (!buffer)
+                       break;
+               if (contains(flag, 'I'))
+                       buffer->markDirty();
+               if (contains(flag, 'R'))
+                       reloadBuffer();
+
+               break;
+               }
+       default:
+               break;
+       }
+
+       if (!msg.empty())
+               message(from_utf8(msg));
+}
+
+
+void GuiView::openChildDocument(string const & fname)
+{
+       LASSERT(documentBufferView(), return);
+       Buffer & buffer = documentBufferView()->buffer();
+       FileName const filename = support::makeAbsPath(fname, buffer.filePath());
+       documentBufferView()->saveBookmark(false);
+       Buffer * child = 0;
+       bool parsed = false;
+       if (theBufferList().exists(filename)) {
+               child = theBufferList().getBuffer(filename);
+       } else {
+               message(bformat(_("Opening child document %1$s..."),
+               makeDisplayPath(filename.absFilename())));
+               child = loadDocument(filename, false);
+               parsed = true;
+       }
+       if (!child)
+               return;
+
+       // Set the parent name of the child document.
+       // This makes insertion of citations and references in the child work,
+       // when the target is in the parent or another child document.
+       child->setParent(&buffer);
+       child->masterBuffer()->updateLabels();
+       setBuffer(child);
+       if (parsed)
+               child->errors("Parse");
+}
+
+
+bool GuiView::goToFileRow(string const & argument)
+{
+       string file_name;
+       int row;
+       size_t i = argument.find_last_of(' ');
+       if (i != string::npos) {
+               file_name = os::internal_path(trim(argument.substr(0, i)));
+               istringstream is(argument.substr(i + 1));
+               is >> row;
+               if (is.fail())
+                       i = string::npos;
+       }
+       if (i == string::npos) {
+               LYXERR0("Wrong argument: " << argument);
+               return false;
+       }
+       Buffer * buf = 0;
+       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(),
+                                             support::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 = loadDocument(s);
+                       buf->updateLabels();
+                       buf->errors("Parse");
+               } else {
+                       message(bformat(
+                                       _("File does not exist: %1$s"),
+                                       makeDisplayPath(file_name)));
+                       return false;
+               }
+       }
+       setBuffer(buf);
+       documentBufferView()->setCursorFromRow(row);
        return true;
 }
 
 
-bool GuiView::dispatch(FuncRequest const & cmd)
+#if (QT_VERSION >= 0x040400)
+static docstring exportAndDestroy(Buffer * buffer, string const & format)
 {
-       BufferView * bv = view();
+       bool const update_unincluded =
+                               buffer->params().maintain_unincluded_children
+                               && !buffer->params().getIncludedChildren().empty();
+       bool const success = buffer->doExport(format, true, update_unincluded);
+       delete buffer;
+       return success
+               ? bformat(_("Successful export to format: %1$s"), from_utf8(format))
+               : bformat(_("Error exporting to format: %1$s"), from_utf8(format));
+}
+
+
+static docstring previewAndDestroy(Buffer * buffer, string const & format)
+{
+       bool const update_unincluded =
+                               buffer->params().maintain_unincluded_children
+                               && !buffer->params().getIncludedChildren().empty();
+       bool const success = buffer->preview(format, update_unincluded);
+       delete buffer;
+       return success
+               ? bformat(_("Successful preview of format: %1$s"), from_utf8(format))
+               : bformat(_("Error previewing format: %1$s"), from_utf8(format));
+}
+#endif
+
+
+void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
+{
+       BufferView * bv = currentBufferView();
        // By default we won't need any update.
-       if (bv)
-               bv->cursor().updateFlags(Update::None);
-       bool dispatched = true;
+       dr.update(Update::None);
+       // assume cmd will be dispatched
+       dr.dispatched(true);
+
+       Buffer * doc_buffer = documentBufferView()
+               ? &(documentBufferView()->buffer()) : 0;
+
+       if (cmd.origin == FuncRequest::TOC) {
+               GuiToc * toc = static_cast<GuiToc*>(findOrBuild("toc", false));
+               // FIXME: do we need to pass a DispatchResult object here?
+               toc->doDispatch(bv->cursor(), cmd);
+               return;
+       }
+
+       string const argument = to_utf8(cmd.argument());
 
        switch(cmd.action) {
+               case LFUN_BUFFER_CHILD_OPEN:
+                       openChildDocument(to_utf8(cmd.argument()));
+                       break;
+
                case LFUN_BUFFER_IMPORT:
                        importDocument(to_utf8(cmd.argument()));
                        break;
 
+               case LFUN_BUFFER_EXPORT: {
+                       if (!doc_buffer)
+                               break;
+                       if (cmd.argument() == "custom") {
+                               dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"), 
+                                        dr);
+                               break;
+                       }
+                       if (doc_buffer->doExport(argument, false)) {
+                               dr.setError(true);
+                               dr.setMessage(bformat(_("Error exporting to format: %1$s."),
+                                       cmd.argument()));
+                       }
+                       break;
+               }
+
+               case LFUN_BUFFER_UPDATE: {
+                       if (!doc_buffer)
+                               break;
+                       string format = argument;
+                       if (argument.empty())
+                               format = doc_buffer->getDefaultOutputFormat();
+#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+                       d.progress_->clearMessages();
+                       message(_("Exporting ..."));
+                       QFuture<docstring> f = QtConcurrent::run(exportAndDestroy,
+                               doc_buffer->clone(), format);
+                       d.setPreviewFuture(f);
+#else
+                       bool const update_unincluded =
+                               doc_buffer->params().maintain_unincluded_children
+                               && !doc_buffer->params().getIncludedChildren().empty();
+                       doc_buffer->doExport(format, true, update_unincluded);
+#endif
+                       break;
+               }
+               case LFUN_BUFFER_VIEW: {
+                       if (!doc_buffer)
+                               break;
+                       string format = argument;
+                       if (argument.empty())
+                               format = doc_buffer->getDefaultOutputFormat();
+#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+                       d.progress_->clearMessages();
+                       message(_("Previewing ..."));
+                       QFuture<docstring> f = QtConcurrent::run(previewAndDestroy,
+                               doc_buffer->clone(), format);
+                       d.setPreviewFuture(f);
+#else
+                       bool const update_unincluded =
+                               doc_buffer->params().maintain_unincluded_children
+                               && !doc_buffer->params().getIncludedChildren().empty();
+                       doc_buffer->preview(format, update_unincluded);
+#endif
+                       break;
+               }
+               case LFUN_MASTER_BUFFER_UPDATE: {
+                       if (!doc_buffer)
+                               break;
+                       string format = argument;
+                       Buffer const * master = doc_buffer->masterBuffer();
+                       if (argument.empty())
+                               format = master->getDefaultOutputFormat();
+#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+                       QFuture<docstring> f = QtConcurrent::run(exportAndDestroy,
+                               master->clone(), format);
+                       d.setPreviewFuture(f);
+#else
+                       bool const update_unincluded =
+                               master->params().maintain_unincluded_children
+                               && !master->params().getIncludedChildren().empty();
+                       master->doExport(format, true);
+#endif
+                       break;
+               }
+               case LFUN_MASTER_BUFFER_VIEW: {
+                       string format = argument;
+                       Buffer const * master = doc_buffer->masterBuffer();
+                       if (argument.empty())
+                               format = master->getDefaultOutputFormat();
+#if EXPORT_in_THREAD && (QT_VERSION >= 0x040400)
+                       QFuture<docstring> f = QtConcurrent::run(previewAndDestroy,
+                               master->clone(), format);
+                       d.setPreviewFuture(f);
+#else
+                       master->preview(format);
+#endif
+                       break;
+               }
                case LFUN_BUFFER_SWITCH:
-                       setBuffer(theBufferList().getBuffer(FileName(to_utf8(cmd.argument()))));
+                       if (FileName::isAbsolute(to_utf8(cmd.argument()))) {
+                               Buffer * buffer = 
+                                       theBufferList().getBuffer(FileName(to_utf8(cmd.argument())));
+                               if (buffer)
+                                       setBuffer(buffer);
+                               else {
+                                       dr.setError(true);
+                                       dr.setMessage(_("Document not loaded"));
+                               }
+                       }
                        break;
 
                case LFUN_BUFFER_NEXT:
-                       setBuffer(theBufferList().next(buffer()));
+                       gotoNextOrPreviousBuffer(NEXTBUFFER);
                        break;
 
                case LFUN_BUFFER_PREVIOUS:
-                       setBuffer(theBufferList().previous(buffer()));
+                       gotoNextOrPreviousBuffer(PREVBUFFER);
                        break;
 
                case LFUN_COMMAND_EXECUTE: {
@@ -1851,8 +2841,7 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                        break;
                }
                case LFUN_DROP_LAYOUTS_CHOICE:
-                       if (d.layout_)
-                               d.layout_->showPopup();
+                       d.layout_->showPopup();
                        break;
 
                case LFUN_MENU_OPEN:
@@ -1871,14 +2860,29 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                        insertPlaintextFile(cmd.argument(), false);
                        break;
 
+               case LFUN_BUFFER_RELOAD: {
+                       LASSERT(doc_buffer, break);
+                       docstring const file = makeDisplayPath(doc_buffer->absFileName(), 20);
+                       docstring text = bformat(_("Any changes will be lost. Are you sure "
+                                                            "you want to revert to the saved version of the document %1$s?"), file);
+                       int const ret = Alert::prompt(_("Revert to saved document?"),
+                               text, 1, 1, _("&Revert"), _("&Cancel"));
+
+                       if (ret == 0) {
+                               doc_buffer->markClean();
+                               reloadBuffer();
+                       }
+                       break;
+               }
+
                case LFUN_BUFFER_WRITE:
-                       if (bv)
-                               saveBuffer(bv->buffer());
+                       LASSERT(doc_buffer, break);
+                       saveBuffer(*doc_buffer);
                        break;
 
                case LFUN_BUFFER_WRITE_AS:
-                       if (bv)
-                               renameBuffer(bv->buffer(), cmd.argument());
+                       LASSERT(doc_buffer, break);
+                       renameBuffer(*doc_buffer, cmd.argument());
                        break;
 
                case LFUN_BUFFER_WRITE_ALL: {
@@ -1899,6 +2903,14 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                        break;
                }
 
+               case LFUN_BUFFER_CLOSE:
+                       closeBuffer();
+                       break;
+
+               case LFUN_BUFFER_CLOSE_ALL:
+                       closeBufferAll();
+                       break;
+
                case LFUN_TOOLBAR_TOGGLE: {
                        string const name = cmd.getArg(0);
                        if (GuiToolbar * t = toolbar(name))
@@ -1908,14 +2920,19 @@ bool GuiView::dispatch(FuncRequest const & cmd)
 
                case LFUN_DIALOG_UPDATE: {
                        string const name = to_utf8(cmd.argument());
-                       // Can only update a dialog connected to an existing inset
-                       Inset * inset = getOpenInset(name);
-                       if (inset) {
+                       if (currentBufferView()) {
+                               Inset * inset = currentBufferView()->editedInset(name);
+                               // Can only update a dialog connected to an existing inset
+                               if (!inset)
+                                       break;
+                               // FIXME: get rid of this indirection; GuiView ask the inset
+                               // if he is kind enough to update itself...
                                FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
-                               inset->dispatch(view()->cursor(), fr);
+                               //FIXME: pass DispatchResult here?
+                               inset->dispatch(currentBufferView()->cursor(), fr);
                        } else if (name == "paragraph") {
                                lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
-                       } else if (name == "prefs") {
+                       } else if (name == "prefs" || name == "document") {
                                updateDialog(name, string());
                        }
                        break;
@@ -1923,9 +2940,9 @@ bool GuiView::dispatch(FuncRequest const & cmd)
 
                case LFUN_DIALOG_TOGGLE: {
                        if (isDialogVisible(cmd.getArg(0)))
-                               dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
+                               dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()), dr);
                        else
-                               dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
+                               dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()), dr);
                        break;
                }
 
@@ -1948,7 +2965,7 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                                        showDialog("character", data);
                        } else if (name == "latexlog") {
                                Buffer::LogType type; 
-                               string const logfile = buffer()->logName(&type);
+                               string const logfile = doc_buffer->logName(&type);
                                switch (type) {
                                case Buffer::latexlog:
                                        data = "latex ";
@@ -1961,37 +2978,25 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                                showDialog("log", data);
                        } else if (name == "vclog") {
                                string const data = "vc " +
-                                       Lexer::quoteString(buffer()->lyxvc().getLogFile());
+                                       Lexer::quoteString(doc_buffer->lyxvc().getLogFile());
                                showDialog("log", data);
                        } else if (name == "symbols") {
                                data = bv->cursor().getEncoding()->name();
                                if (!data.empty())
                                        showDialog("symbols", data);
+                       // bug 5274
+                       } else if (name == "prefs" && isFullScreen()) {
+                               FuncRequest fr(LFUN_INSET_INSERT, "fullscreen");
+                               lfunUiToggle(fr);
+                               showDialog("prefs", data);
                        } else
                                showDialog(name, data);
                        break;
                }
 
-               case LFUN_INSET_APPLY: {
-                       string const name = cmd.getArg(0);
-                       Inset * inset = getOpenInset(name);
-                       if (inset) {
-                               // put cursor in front of inset.
-                               if (!view()->setCursorFromInset(inset))
-                                       LASSERT(false, break);
-                               
-                               // useful if we are called from a dialog.
-                               view()->cursor().beginUndoGroup();
-                               view()->cursor().recordUndo();
-                               FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
-                               inset->dispatch(view()->cursor(), fr);
-                               view()->cursor().endUndoGroup();
-                       } else {
-                               FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
-                               lyx::dispatch(fr);
-                       }
+               case LFUN_MESSAGE:
+                       message(cmd.argument());
                        break;
-               }
 
                case LFUN_UI_TOGGLE:
                        lfunUiToggle(cmd);
@@ -1999,32 +3004,28 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                        setFocus();
                        break;
 
-               case LFUN_SPLIT_VIEW:
-                       if (Buffer * buf = buffer()) {
-                               string const orientation = cmd.getArg(0);
-                               d.splitter_->setOrientation(orientation == "vertical"
-                                       ? Qt::Vertical : Qt::Horizontal);
-                               TabWorkArea * twa = addTabWorkArea();
-                               GuiWorkArea * wa = twa->addWorkArea(*buf, *this);
-                               setCurrentWorkArea(wa);
-                       }
+               case LFUN_SPLIT_VIEW: {
+                       LASSERT(doc_buffer, break);
+                       string const orientation = cmd.getArg(0);
+                       d.splitter_->setOrientation(orientation == "vertical"
+                               ? Qt::Vertical : Qt::Horizontal);
+                       TabWorkArea * twa = addTabWorkArea();
+                       GuiWorkArea * wa = twa->addWorkArea(*doc_buffer, *this);
+                       setCurrentWorkArea(wa);
                        break;
-
+               }
                case LFUN_CLOSE_TAB_GROUP:
                        if (TabWorkArea * twa = d.currentTabWorkArea()) {
-                               delete twa;
+                               closeTabWorkArea(twa);
+                               d.current_work_area_ = 0;
                                twa = d.currentTabWorkArea();
                                // Switch to the next GuiWorkArea in the found TabWorkArea.
                                if (twa) {
-                                       d.current_work_area_ = twa->currentWorkArea();
                                        // Make sure the work area is up to date.
-                                       twa->setCurrentWorkArea(d.current_work_area_);
+                                       setCurrentWorkArea(twa->currentWorkArea());
                                } else {
-                                       d.current_work_area_ = 0;
+                                       setCurrentWorkArea(0);
                                }
-                               if (d.splitter_->count() == 0)
-                                       // No more work area, switch to the background widget.
-                                       d.setBackground();
                        }
                        break;
                        
@@ -2058,21 +3059,55 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                                d.current_work_area_->completer().activate();
                        break;
 
+               case LFUN_BUFFER_ZOOM_IN:
+               case LFUN_BUFFER_ZOOM_OUT:
+                       if (cmd.argument().empty()) {
+                               if (cmd.action == LFUN_BUFFER_ZOOM_IN)
+                                       lyxrc.zoom += 20;
+                               else
+                                       lyxrc.zoom -= 20;
+                       } else
+                               lyxrc.zoom += convert<int>(cmd.argument());
+
+                       if (lyxrc.zoom < 10)
+                               lyxrc.zoom = 10;
+                               
+                       // The global QPixmapCache is used in GuiPainter to cache text
+                       // painting so we must reset it.
+                       QPixmapCache::clear();
+                       guiApp->fontLoader().update();
+                       lyx::dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
+                       break;
+
+               case LFUN_VC_REGISTER:
+               case LFUN_VC_CHECK_IN:
+               case LFUN_VC_CHECK_OUT:
+               case LFUN_VC_REPO_UPDATE:
+               case LFUN_VC_LOCKING_TOGGLE:
+               case LFUN_VC_REVERT:
+               case LFUN_VC_UNDO_LAST:
+               case LFUN_VC_COMMAND:
+                       dispatchVC(cmd);
+                       break;
+
+               case LFUN_SERVER_GOTO_FILE_ROW:
+                       goToFileRow(to_utf8(cmd.argument()));
+                       break;
 
                default:
-                       dispatched = false;
+                       dr.dispatched(false);
                        break;
        }
 
        // Part of automatic menu appearance feature.
        if (isFullScreen()) {
-               if (menuBar()->isVisible())
+               if (menuBar()->isVisible() && lyxrc.full_screen_menubar)
                        menuBar()->hide();
                if (statusBar()->isVisible())
                        statusBar()->hide();
        }
 
-       return dispatched;
+       return;
 }
 
 
@@ -2135,6 +3170,8 @@ void GuiView::toggleFullScreen()
                menuBar()->show();
                statusBar()->show();
        } else {
+               // bug 5274
+               hideDialogs("prefs", 0);
                for (int i = 0; i != d.splitter_->count(); ++i)
                        d.tabWorkArea(i)->setFullScreen(true);
 #if QT_VERSION >= 0x040300
@@ -2143,7 +3180,8 @@ void GuiView::toggleFullScreen()
                saveLayout();
                setWindowState(windowState() ^ Qt::WindowFullScreen);
                statusBar()->hide();
-               menuBar()->hide();
+               if (lyxrc.full_screen_menubar)
+                       menuBar()->hide();
                if (lyxrc.full_screen_toolbars) {
                        ToolbarMap::iterator end = d.toolbars_.end();
                        for (ToolbarMap::iterator it = d.toolbars_.begin(); it != end; ++it)
@@ -2198,16 +3236,13 @@ namespace {
 
 char const * const dialognames[] = {
 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
-"citation", "document", "errorlist", "ert", "external", "file",
-"findreplace", "float", "graphics", "include", "index", "info", "nomenclature", "label", "log",
-"mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print", 
-"ref", "sendto", "space", "spellchecker", "symbols", "tabular", "tabularcreate",
-
-#ifdef HAVE_LIBAIKSAURUS
-"thesaurus",
-#endif
-
-"texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
+"citation", "compare", "document", "errorlist", "ert", "external", "file",
+"findreplace", "findreplaceadv", "float", "graphics", "href", "include",
+"index", "index_print", "info", "listings", "label", "log", "mathdelimiter",
+"mathmatrix", "mathspace", "nomenclature", "nomencl_print", "note",
+"paragraph", "phantom", "prefs", "print", "ref", "sendto", "space",
+"spellchecker", "symbols", "tabular", "tabularcreate", "thesaurus", "texinfo",
+"toc", "view-source", "vspace", "wrap", "progress"};
 
 char const * const * const end_dialognames =
        dialognames + (sizeof(dialognames) / sizeof(char *));
@@ -2235,15 +3270,14 @@ bool isValidName(string const & name)
 void GuiView::resetDialogs()
 {
        // Make sure that no LFUN uses any LyXView.
-       theLyXFunc().setLyXView(0);
+       guiApp->setCurrentView(0);
        saveLayout();
        menuBar()->clear();
        constructToolbars();
        guiApp->menus().fillMenuBar(menuBar(), this, false);
-       if (d.layout_)
-               d.layout_->updateContents(true);
+       d.layout_->updateContents(true);
        // Now update controls with current buffer.
-       theLyXFunc().setLyXView(this);
+       guiApp->setCurrentView(this);
        restoreLayout();
        restartCursor();
 }
@@ -2274,17 +3308,27 @@ Dialog * GuiView::findOrBuild(string const & name, bool hide_it)
 
 void GuiView::showDialog(string const & name, string const & data,
        Inset * inset)
+{
+       triggerShowDialog(toqstr(name), toqstr(data), inset);
+}
+
+
+void GuiView::doShowDialog(QString const & qname, QString const & qdata,
+       Inset * inset)
 {
        if (d.in_show_)
                return;
 
+       const string name = fromqstr(qname);
+       const string data = fromqstr(qdata);
+
        d.in_show_ = true;
        try {
                Dialog * dialog = findOrBuild(name, false);
                if (dialog) {
                        dialog->showData(data);
-                       if (inset)
-                               d.open_insets_[name] = inset;
+                       if (inset && currentBufferView())
+                               currentBufferView()->editInset(name, inset);
                }
        }
        catch (ExceptionMessage const & ex) {
@@ -2300,7 +3344,7 @@ bool GuiView::isDialogVisible(string const & name) const
        map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
        if (it == d.dialogs_.end())
                return false;
-       return it->second.get()->isVisibleView();
+       return it->second.get()->isVisibleView() && !it->second.get()->isClosing();
 }
 
 
@@ -2310,13 +3354,15 @@ void GuiView::hideDialog(string const & name, Inset * inset)
        if (it == d.dialogs_.end())
                return;
 
-       if (inset && inset != getOpenInset(name))
+       if (inset && currentBufferView()
+               && inset != currentBufferView()->editedInset(name))
                return;
 
        Dialog * const dialog = it->second.get();
        if (dialog->isVisibleView())
                dialog->hideView();
-       d.open_insets_[name] = 0;
+       if (currentBufferView())
+               currentBufferView()->editInset(name, 0);
 }
 
 
@@ -2324,19 +3370,8 @@ void GuiView::disconnectDialog(string const & name)
 {
        if (!isValidName(name))
                return;
-
-       if (d.open_insets_.find(name) != d.open_insets_.end())
-               d.open_insets_[name] = 0;
-}
-
-
-Inset * GuiView::getOpenInset(string const & name) const
-{
-       if (!isValidName(name))
-               return 0;
-
-       map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
-       return it == d.open_insets_.end() ? 0 : it->second;
+       if (currentBufferView())
+               currentBufferView()->editInset(name, 0);
 }
 
 
@@ -2357,8 +3392,12 @@ void GuiView::updateDialogs()
 
        for(; it != end; ++it) {
                Dialog * dialog = it->second.get();
-               if (dialog && dialog->isVisibleView())
-                       dialog->checkStatus();
+               if (dialog) {
+                       if (dialog->isBufferDependent() && !documentBufferView())
+                               hideDialog(fromqstr(dialog->name()), 0);
+                       else if (dialog->isVisibleView())
+                               dialog->checkStatus();
+               }
        }
        updateToolbars();
        updateLayoutList();
@@ -2374,6 +3413,7 @@ Dialog * createGuiBranch(GuiView & lv);
 Dialog * createGuiChanges(GuiView & lv);
 Dialog * createGuiCharacter(GuiView & lv);
 Dialog * createGuiCitation(GuiView & lv);
+Dialog * createGuiCompare(GuiView & lv);
 Dialog * createGuiDelimiter(GuiView & lv);
 Dialog * createGuiDocument(GuiView & lv);
 Dialog * createGuiErrorList(GuiView & lv);
@@ -2381,20 +3421,25 @@ Dialog * createGuiERT(GuiView & lv);
 Dialog * createGuiExternal(GuiView & lv);
 Dialog * createGuiFloat(GuiView & lv);
 Dialog * createGuiGraphics(GuiView & lv);
-Dialog * createGuiHSpace(GuiView & lv);
 Dialog * createGuiInclude(GuiView & lv);
+Dialog * createGuiIndex(GuiView & lv);
 Dialog * createGuiInfo(GuiView & lv);
 Dialog * createGuiLabel(GuiView & lv);
 Dialog * createGuiListings(GuiView & lv);
 Dialog * createGuiLog(GuiView & lv);
+Dialog * createGuiMathHSpace(GuiView & lv);
 Dialog * createGuiMathMatrix(GuiView & lv);
 Dialog * createGuiNomenclature(GuiView & lv);
 Dialog * createGuiNote(GuiView & lv);
 Dialog * createGuiParagraph(GuiView & lv);
+Dialog * createGuiPhantom(GuiView & lv);
 Dialog * createGuiPreferences(GuiView & lv);
 Dialog * createGuiPrint(GuiView & lv);
+Dialog * createGuiPrintindex(GuiView & lv);
+Dialog * createGuiPrintNomencl(GuiView & lv);
 Dialog * createGuiRef(GuiView & lv);
 Dialog * createGuiSearch(GuiView & lv);
+Dialog * createGuiSearchAdv(GuiView & lv);
 Dialog * createGuiSendTo(GuiView & lv);
 Dialog * createGuiShowFile(GuiView & lv);
 Dialog * createGuiSpellchecker(GuiView & lv);
@@ -2402,12 +3447,15 @@ Dialog * createGuiSymbols(GuiView & lv);
 Dialog * createGuiTabularCreate(GuiView & lv);
 Dialog * createGuiTabular(GuiView & lv);
 Dialog * createGuiTexInfo(GuiView & lv);
+Dialog * createGuiTextHSpace(GuiView & lv);
 Dialog * createGuiToc(GuiView & lv);
 Dialog * createGuiThesaurus(GuiView & lv);
 Dialog * createGuiHyperlink(GuiView & lv);
 Dialog * createGuiVSpace(GuiView & lv);
 Dialog * createGuiViewSource(GuiView & lv);
 Dialog * createGuiWrap(GuiView & lv);
+Dialog * createGuiProgressView(GuiView & lv);
+
 
 
 Dialog * GuiView::build(string const & name)
@@ -2430,6 +3478,8 @@ Dialog * GuiView::build(string const & name)
                return createGuiCharacter(*this);
        if (name == "citation")
                return createGuiCitation(*this);
+       if (name == "compare")
+               return createGuiCompare(*this);
        if (name == "document")
                return createGuiDocument(*this);
        if (name == "errorlist")
@@ -2442,30 +3492,44 @@ Dialog * GuiView::build(string const & name)
                return createGuiShowFile(*this);
        if (name == "findreplace")
                return createGuiSearch(*this);
+       if (name == "findreplaceadv")
+               return createGuiSearchAdv(*this);
        if (name == "float")
                return createGuiFloat(*this);
        if (name == "graphics")
                return createGuiGraphics(*this);
+       if (name == "href")
+               return createGuiHyperlink(*this);
        if (name == "include")
                return createGuiInclude(*this);
+       if (name == "index")
+               return createGuiIndex(*this);
+       if (name == "index_print")
+               return createGuiPrintindex(*this);
        if (name == "info")
                return createGuiInfo(*this);
-       if (name == "nomenclature")
-               return createGuiNomenclature(*this);
        if (name == "label")
                return createGuiLabel(*this);
+       if (name == "listings")
+               return createGuiListings(*this);
        if (name == "log")
                return createGuiLog(*this);
-       if (name == "view-source")
-               return createGuiViewSource(*this);
        if (name == "mathdelimiter")
                return createGuiDelimiter(*this);
+       if (name == "mathspace")
+               return createGuiMathHSpace(*this);
        if (name == "mathmatrix")
                return createGuiMathMatrix(*this);
+       if (name == "nomenclature")
+               return createGuiNomenclature(*this);
+       if (name == "nomencl_print")
+               return createGuiPrintNomencl(*this);
        if (name == "note")
                return createGuiNote(*this);
        if (name == "paragraph")
                return createGuiParagraph(*this);
+       if (name == "phantom")
+               return createGuiPhantom(*this);
        if (name == "prefs")
                return createGuiPreferences(*this);
        if (name == "print")
@@ -2475,7 +3539,7 @@ Dialog * GuiView::build(string const & name)
        if (name == "sendto")
                return createGuiSendTo(*this);
        if (name == "space")
-               return createGuiHSpace(*this);
+               return createGuiTextHSpace(*this);
        if (name == "spellchecker")
                return createGuiSpellchecker(*this);
        if (name == "symbols")
@@ -2486,20 +3550,18 @@ Dialog * GuiView::build(string const & name)
                return createGuiTabularCreate(*this);
        if (name == "texinfo")
                return createGuiTexInfo(*this);
-#ifdef HAVE_LIBAIKSAURUS
        if (name == "thesaurus")
                return createGuiThesaurus(*this);
-#endif
        if (name == "toc")
                return createGuiToc(*this);
-       if (name == "href")
-               return createGuiHyperlink(*this);
+       if (name == "view-source")
+               return createGuiViewSource(*this);
        if (name == "vspace")
                return createGuiVSpace(*this);
        if (name == "wrap")
                return createGuiWrap(*this);
-       if (name == "listings")
-               return createGuiListings(*this);
+       if (name == "progress")
+               return createGuiProgressView(*this);
 
        return 0;
 }
@@ -2508,4 +3570,4 @@ Dialog * GuiView::build(string const & name)
 } // namespace frontend
 } // namespace lyx
 
-#include "GuiView_moc.cpp"
+#include "moc_GuiView.cpp"