]> git.lyx.org Git - lyx.git/blobdiff - src/LyX.cpp
The --batch patch.
[lyx.git] / src / LyX.cpp
index 29c8defc23149d180a26a0e89131a8d7b676848f..3445dfdc3721494a0f7cdf7dcf3179d5182682ac 100644 (file)
@@ -4,10 +4,10 @@
  * Licence details can be found in the file COPYING.
  *
  * \author Alfredo Braunstein
- * \author Lars Gullik Bjønnes
+ * \author Lars Gullik Bjønnes
  * \author Jean-Marc Lasgouttes
  * \author John Levon
- * \author André Pönitz
+ * \author André Pönitz
  *
  * Full author contact details are available in file CREDITS.
  */
 
 #include "LyX.h"
 
+#include "ASpell_local.h"
 #include "Buffer.h"
 #include "BufferList.h"
 #include "CmdDef.h"
-#include "Color.h"
+#include "ColorSet.h"
 #include "ConverterCache.h"
 #include "Converter.h"
 #include "CutAndPaste.h"
 #include "Encoding.h"
 #include "ErrorList.h"
 #include "Format.h"
+#include "FuncStatus.h"
 #include "KeyMap.h"
 #include "Language.h"
+#include "LayoutFile.h"
 #include "Lexer.h"
 #include "LyXAction.h"
 #include "LyXFunc.h"
 #include "LyXRC.h"
-#include "MenuBackend.h"
 #include "ModuleList.h"
 #include "Mover.h"
 #include "Server.h"
 #include "ServerSocket.h"
 #include "Session.h"
-#include "TextClassList.h"
-#include "ToolbarBackend.h"
 
 #include "frontends/alert.h"
 #include "frontends/Application.h"
 
+#include "graphics/Previews.h"
+
+#include "support/lassert.h"
 #include "support/debug.h"
 #include "support/environment.h"
 #include "support/ExceptionMessage.h"
@@ -83,8 +86,6 @@ namespace os = support::os;
 
 bool use_gui = true;
 
-bool quitting; // flag, that we are quitting the program
-
 namespace {
 
 // Filled with the command line arguments "foo" of "-sysdir foo" or
@@ -127,7 +128,19 @@ struct LyX::Impl
                // The language used will be derived from the environment
                // variables.
                messages_["GUI"] = Messages();
+
+#if defined(USE_ASPELL)
+               spell_checker_ = new ASpell();
+#else
+               spell_checker_ = 0;
+#endif
+       }
+
+       ~Impl()
+       {
+               delete spell_checker_;
        }
+
        /// our function handler
        LyXFunc lyxfunc_;
        ///
@@ -165,7 +178,12 @@ struct LyX::Impl
        /// has this user started lyx for the first time?
        bool first_start;
        /// the parsed command line batch command if any
-       string batch_command;
+       vector<string> batch_commands;
+
+       ///
+       graphics::Previews preview_;
+       ///
+       SpellChecker * spell_checker_;
 };
 
 ///
@@ -180,11 +198,12 @@ frontend::Application * theApp()
 
 LyX::~LyX()
 {
+       singleton_ = 0;
        delete pimpl_;
 }
 
 
-void LyX::exit(int exit_code) const
+void lyx_exit(int exit_code)
 {
        if (exit_code)
                // Something wrong happened so better save everything, just in
@@ -204,20 +223,6 @@ void LyX::exit(int exit_code) const
 }
 
 
-LyX & LyX::ref()
-{
-       BOOST_ASSERT(singleton_);
-       return *singleton_;
-}
-
-
-LyX const & LyX::cref()
-{
-       BOOST_ASSERT(singleton_);
-       return *singleton_;
-}
-
-
 LyX::LyX()
        : first_start(false)
 {
@@ -226,117 +231,7 @@ LyX::LyX()
 }
 
 
-BufferList & LyX::bufferList()
-{
-       return pimpl_->buffer_list_;
-}
-
-
-BufferList const & LyX::bufferList() const
-{
-       return pimpl_->buffer_list_;
-}
-
-
-Session & LyX::session()
-{
-       BOOST_ASSERT(pimpl_->session_.get());
-       return *pimpl_->session_.get();
-}
-
-
-Session const & LyX::session() const
-{
-       BOOST_ASSERT(pimpl_->session_.get());
-       return *pimpl_->session_.get();
-}
-
-
-LyXFunc & LyX::lyxFunc()
-{
-       return pimpl_->lyxfunc_;
-}
-
-
-LyXFunc const & LyX::lyxFunc() const
-{
-       return pimpl_->lyxfunc_;
-}
-
-
-Server & LyX::server()
-{
-       BOOST_ASSERT(pimpl_->lyx_server_.get());
-       return *pimpl_->lyx_server_.get();
-}
-
-
-Server const & LyX::server() const
-{
-       BOOST_ASSERT(pimpl_->lyx_server_.get());
-       return *pimpl_->lyx_server_.get();
-}
-
-
-ServerSocket & LyX::socket()
-{
-       BOOST_ASSERT(pimpl_->lyx_socket_.get());
-       return *pimpl_->lyx_socket_.get();
-}
-
-
-ServerSocket const & LyX::socket() const
-{
-       BOOST_ASSERT(pimpl_->lyx_socket_.get());
-       return *pimpl_->lyx_socket_.get();
-}
-
-
-frontend::Application & LyX::application()
-{
-       BOOST_ASSERT(pimpl_->application_.get());
-       return *pimpl_->application_.get();
-}
-
-
-frontend::Application const & LyX::application() const
-{
-       BOOST_ASSERT(pimpl_->application_.get());
-       return *pimpl_->application_.get();
-}
-
-
-KeyMap & LyX::topLevelKeymap()
-{
-       return pimpl_->toplevel_keymap_;
-}
-
-
-CmdDef & LyX::topLevelCmdDef()
-{
-       return pimpl_->toplevel_cmddef_;
-}
-
-
-Converters & LyX::converters()
-{
-       return pimpl_->converters_;
-}
-
-
-Converters & LyX::systemConverters()
-{
-       return pimpl_->system_converters_;
-}
-
-
-KeyMap const & LyX::topLevelKeymap() const
-{
-       return pimpl_->toplevel_keymap_;
-}
-
-
-Messages & LyX::getMessages(string const & language)
+Messages & LyX::messages(string const & language)
 {
        map<string, Messages>::iterator it = pimpl_->messages_.find(language);
 
@@ -346,20 +241,27 @@ Messages & LyX::getMessages(string const & language)
        pair<map<string, Messages>::iterator, bool> result =
                        pimpl_->messages_.insert(make_pair(language, Messages(language)));
 
-       BOOST_ASSERT(result.second);
+       LASSERT(result.second, /**/);
        return result.first->second;
 }
 
 
-Messages & LyX::getGuiMessages()
-{
-       return pimpl_->messages_["GUI"];
-}
-
-
-void LyX::setGuiLanguage(string const & language)
+void setRcGuiLanguage()
 {
-       pimpl_->messages_["GUI"] = Messages(language);
+       LASSERT(singleton_, /**/);
+       if (lyxrc.gui_language == "auto")
+               return;
+       Language const * language = languages.getLanguage(lyxrc.gui_language);
+       if (language) {
+               LYXERR(Debug::LOCALE, "Setting LANGUAGE to " << language->code());
+               if (!setEnv("LANGUAGE", language->code()))
+                       LYXERR(Debug::LOCALE, "\t... failed!");
+       }
+       LYXERR(Debug::LOCALE, "Setting LC_ALL to en_US");
+       if (!setEnv("LC_ALL", "en_US"))
+               LYXERR(Debug::LOCALE, "\t... failed!");
+       Messages::init();
+       singleton_->pimpl_->messages_["GUI"] = Messages();
 }
 
 
@@ -376,7 +278,7 @@ int LyX::exec(int & argc, char * argv[])
        } catch (ExceptionMessage const & message) {
                if (message.type_ == ErrorException) {
                        Alert::error(message.title_, message.details_);
-                       exit(1);
+                       lyx_exit(1);
                } else if (message.type_ == WarningException) {
                        Alert::warning(message.title_, message.details_);
                }
@@ -394,11 +296,12 @@ int LyX::exec(int & argc, char * argv[])
                        return exit_status;
                }
 
-               loadFiles();
+               // this is correct, since return values are inverted.
+               exit_status = !loadFiles();
 
-               if (pimpl_->batch_command.empty() || pimpl_->buffer_list_.empty()) {
+               if (pimpl_->batch_commands.empty() || pimpl_->buffer_list_.empty()) {
                        prepareExit();
-                       return EXIT_SUCCESS;
+                       return exit_status;
                }
 
                BufferList::iterator begin = pimpl_->buffer_list_.begin();
@@ -408,9 +311,14 @@ int LyX::exec(int & argc, char * argv[])
                        Buffer * buf = *I;
                        if (buf != buf->masterBuffer())
                                continue;
-                       bool success = false;
-                       buf->dispatch(pimpl_->batch_command, &success);
-                       final_success |= success;
+                       vector<string>::const_iterator bcit  = pimpl_->batch_commands.begin();
+                       vector<string>::const_iterator bcend = pimpl_->batch_commands.end();
+                       DispatchResult dr;
+                       for (; bcit != bcend; bcit++) {
+                               LYXERR(Debug::ACTION, "Buffer::dispatch: cmd: " << *bcit);
+                               buf->dispatch(*bcit, dr);
+                               final_success |= !dr.error();
+                       }
                }
                prepareExit();
                return !final_success;
@@ -419,6 +327,10 @@ int LyX::exec(int & argc, char * argv[])
        // Let the frontend parse and remove all arguments that it knows
        pimpl_->application_.reset(createApplication(argc, argv));
 
+       // Reestablish our defaults, as Qt overwrites them
+       // after createApplication()
+       locale_init();
+
        // Parse and remove all known arguments in the LyX singleton
        // Give an error for all remaining ones.
        int exit_status = init(argc, argv);
@@ -429,7 +341,7 @@ int LyX::exec(int & argc, char * argv[])
                prepareExit();
                return exit_status;
        }
-
        // FIXME
        /* Create a CoreApplication class that will provide the main event loop
        * and the socket callback registering. With Qt4, only QtCore
@@ -458,10 +370,6 @@ void LyX::prepareExit()
        cap::clearCutStack();
        cap::clearSelection();
 
-       // Set a flag that we do quitting from the program,
-       // so no refreshes are necessary.
-       quitting = true;
-
        // close buffers first
        pimpl_->buffer_list_.closeAll();
 
@@ -476,14 +384,21 @@ void LyX::prepareExit()
 
        // do any other cleanup procedures now
        if (package().temp_dir() != package().system_temp_dir()) {
-               LYXERR(Debug::INFO, "Deleting tmp dir "
-                                   << package().temp_dir().absFilename());
-
-               if (!package().temp_dir().destroyDirectory()) {
+               string const abs_tmpdir = package().temp_dir().absFilename();
+               if (!contains(package().temp_dir().absFilename(), "lyx_tmpdir")) {
                        docstring const msg =
-                               bformat(_("Unable to remove the temporary directory %1$s"),
-                               from_utf8(package().temp_dir().absFilename()));
-                       Alert::warning(_("Unable to remove temporary directory"), msg);
+                               bformat(_("%1$s does not appear like a LyX created temporary directory."),
+                               from_utf8(abs_tmpdir));
+                       Alert::warning(_("Cannot remove temporary directory"), msg);
+               } else {
+                       LYXERR(Debug::INFO, "Deleting tmp dir "
+                               << package().temp_dir().absFilename());
+                       if (!package().temp_dir().destroyDirectory()) {
+                               docstring const msg =
+                                       bformat(_("Unable to remove the temporary directory %1$s"),
+                                       from_utf8(package().temp_dir().absFilename()));
+                               Alert::warning(_("Unable to remove temporary directory"), msg);
+                       }
                }
        }
 
@@ -496,7 +411,7 @@ void LyX::prepareExit()
 
 void LyX::earlyExit(int status)
 {
-       BOOST_ASSERT(pimpl_->application_.get());
+       LASSERT(pimpl_->application_.get(), /**/);
        // LyX::pimpl_::application_ is not initialised at this
        // point so it's safe to just exit after some cleanup.
        prepareExit();
@@ -537,19 +452,10 @@ int LyX::init(int & argc, char * argv[])
 }
 
 
-void LyX::addFileToLoad(string const & fname)
-{
-       vector<string>::const_iterator cit = find(
-               pimpl_->files_to_load_.begin(), pimpl_->files_to_load_.end(),
-               fname);
-
-       if (cit == pimpl_->files_to_load_.end())
-               pimpl_->files_to_load_.push_back(fname);
-}
-
-
-void LyX::loadFiles()
+bool LyX::loadFiles()
 {
+       LASSERT(!use_gui, /**/);
+       bool success = true;
        vector<string>::const_iterator it = pimpl_->files_to_load_.begin();
        vector<string>::const_iterator end = pimpl_->files_to_load_.end();
 
@@ -569,29 +475,39 @@ void LyX::loadFiles()
                                for_each(el.begin(), el.end(),
                                boost::bind(&LyX::printError, this, _1));
                }
-               else
+               else {
                        pimpl_->buffer_list_.release(buf);
+                       success = false;
+               }
        }
+       return success;
+}
+
+
+void execBatchCommands()
+{
+       LASSERT(singleton_, /**/);
+       singleton_->execCommands();
 }
 
 
-void LyX::execBatchCommands()
+void LyX::execCommands()
 {
        // The advantage of doing this here is that the event loop
        // is already started. So any need for interaction will be
        // aknowledged.
 
        // if reconfiguration is needed.
-       while (textclasslist.empty()) {
-           switch (Alert::prompt(
-                   _("No textclass is found"),
-                   _("LyX cannot continue because no textclass is found. "
-                     "You can either reconfigure normally, or reconfigure using "
-                     "default textclasses, or quit LyX."),
-                   0, 2,
-                   _("&Reconfigure"),
-                   _("&Use Default"),
-                   _("&Exit LyX")))
+       while (LayoutFileList::get().empty()) {
+               switch (Alert::prompt(
+                       _("No textclass is found"),
+                       _("LyX cannot continue because no textclass is found. "
+                               "You can either reconfigure normally, or reconfigure using "
+                               "default textclasses, or quit LyX."),
+                       0, 2,
+                       _("&Reconfigure"),
+                       _("&Use Default"),
+                       _("&Exit LyX")))
                {
                case 0:
                        // regular reconfigure
@@ -620,17 +536,19 @@ void LyX::execBatchCommands()
                }
                // clear this list to save a few bytes of RAM
                pimpl_->files_to_load_.clear();
-       }
-       else
+       } else
                pimpl_->application_->restoreGuiSession();
 
        // Execute batch commands if available
-       if (pimpl_->batch_command.empty())
+       if (pimpl_->batch_commands.empty())
                return;
 
-       LYXERR(Debug::INIT, "About to handle -x '" << pimpl_->batch_command << '\'');
-
-       pimpl_->lyxfunc_.dispatch(lyxaction.lookupFunc(pimpl_->batch_command));
+       vector<string>::const_iterator bcit  = pimpl_->batch_commands.begin();
+       vector<string>::const_iterator bcend = pimpl_->batch_commands.end();
+       for (; bcit != bcend; bcit++) {
+               LYXERR(Debug::INIT, "About to handle -x '" << *bcit << '\'');
+               pimpl_->lyxfunc_.dispatch(lyxaction.lookupFunc(*bcit));
+       }
 }
 
 
@@ -641,7 +559,7 @@ The SIGHUP signal does not exist on Windows and does not need to be handled.
 
 Windows handles SIGFPE and SIGSEGV signals as expected.
 
-Cntl+C interrupts (mapped to SIGINT by Windows' POSIX compatability layer)
+Ctrl+C interrupts (mapped to SIGINT by Windows' POSIX compatability layer)
 cause a new thread to be spawned. This may well result in unexpected
 behaviour by the single-threaded LyX.
 
@@ -676,7 +594,7 @@ static void error_handler(int err_sig)
 
        // We have received a signal indicating a fatal error, so
        // try and save the data ASAP.
-       LyX::cref().emergencyCleanup();
+       emergencyCleanup();
 
        // These lyxerr calls may or may not work:
 
@@ -773,7 +691,7 @@ bool LyX::init()
                return false;
 
        // Set the language defined by the distributor.
-       //setGuiLanguage(lyxrc.gui_language);
+       setRcGuiLanguage();
 
        // Set the PATH correctly.
 #if !defined (USE_POSIX_PACKAGING)
@@ -804,6 +722,9 @@ bool LyX::init()
        // Read lyxrc.dist again to be able to override viewer auto-detection.
        readRcFile("lyxrc.dist");
 
+       // Set again the language defined by the distributor.
+       setRcGuiLanguage();
+
        system_lyxrc = lyxrc;
        system_formats = formats;
        pimpl_->system_converters_ = pimpl_->converters_;
@@ -819,20 +740,20 @@ bool LyX::init()
        if (!readLanguagesFile("languages"))
                return false;
 
+       // Set the language defined by the user.
+       setRcGuiLanguage();
+
        // Load the layouts
        LYXERR(Debug::INIT, "Reading layouts...");
        if (!LyXSetStyle())
                return false;
        //...and the modules
-       moduleList.load();
+       moduleList.read();
 
        // read keymap and ui files in batch mode as well
        // because InsetInfo needs to know these to produce
        // the correct output
 
-       // Set the language defined by the user.
-       //setGuiLanguage(lyxrc.gui_language);
-
        // Set up command definitions
        pimpl_->toplevel_cmddef_.read(lyxrc.def_file);
 
@@ -844,10 +765,6 @@ bool LyX::init()
 
        pimpl_->lyxfunc_.initKeySequences(&pimpl_->toplevel_keymap_);
 
-       // Read menus
-       if (use_gui && !readUIFile(lyxrc.ui_file))
-               return false;
-
        if (lyxerr.debugging(Debug::LYXRC))
                lyxrc.print();
 
@@ -859,12 +776,12 @@ bool LyX::init()
        if (document_path.exists() && document_path.isDirectory())
                package().document_dir() = document_path;
 
-       package().temp_dir() = createLyXTmpDir(FileName(lyxrc.tempdir_path));
+       package().set_temp_dir(createLyXTmpDir(FileName(lyxrc.tempdir_path)));
        if (package().temp_dir().empty()) {
                Alert::error(_("Could not create temporary directory"),
                             bformat(_("Could not create a temporary directory in\n"
-                                                   "%1$s. Make sure that this\n"
-                                                   "path exists and is writable and try again."),
+                                                      "\"%1$s\"\n"
+                                                          "Make sure that this path exists and is writable and try again."),
                                     from_utf8(lyxrc.tempdir_path)));
                // createLyXTmpDir() tries sufficiently hard to create a
                // usable temp dir, so the probability to come here is
@@ -883,54 +800,28 @@ bool LyX::init()
        // This must happen after package initialization and after lyxrc is
        // read, therefore it can't be done by a static object.
        ConverterCache::init();
-
+               
        return true;
 }
 
 
-void LyX::emergencyCleanup() const
+void emergencyCleanup()
 {
        // what to do about tmpfiles is non-obvious. we would
        // like to delete any we find, but our lyxdir might
        // contain documents etc. which might be helpful on
        // a crash
 
-       pimpl_->buffer_list_.emergencyWriteAll();
+       singleton_->pimpl_->buffer_list_.emergencyWriteAll();
        if (use_gui) {
-               if (pimpl_->lyx_server_)
-                       pimpl_->lyx_server_->emergencyCleanup();
-               pimpl_->lyx_server_.reset();
-               pimpl_->lyx_socket_.reset();
+               if (singleton_->pimpl_->lyx_server_)
+                       singleton_->pimpl_->lyx_server_->emergencyCleanup();
+               singleton_->pimpl_->lyx_server_.reset();
+               singleton_->pimpl_->lyx_socket_.reset();
        }
 }
 
 
-void LyX::deadKeyBindings(KeyMap * kbmap)
-{
-       // bindKeyings for transparent handling of deadkeys
-       // The keysyms are gotten from XFree86 X11R6
-       kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACCENT_ACUTE));
-       kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_ACCENT_BREVE));
-       kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_ACCENT_CARON));
-       kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_ACCENT_CEDILLA));
-       kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_ACCENT_CIRCLE));
-       kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_ACCENT_CIRCUMFLEX));
-       kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_ACCENT_DOT));
-       kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_ACCENT_GRAVE));
-       kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_ACCENT_HUNGARIAN_UMLAUT));
-       kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_ACCENT_MACRON));
-       // nothing with this name
-       // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_ACCENT_SPECIAL_CARON);
-       kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_ACCENT_TILDE));
-       kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_ACCENT_UMLAUT));
-       // nothing with this name either...
-       //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_ACCENT_UNDERBAR));
-       kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_ACCENT_UNDERDOT));
-       kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_ACCENT_TIE));
-       kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_ACCENT_OGONEK));
-}
-
-
 // return true if file does not exist or is older than configure.py.
 static bool needsUpdate(string const & file)
 {
@@ -1014,100 +905,6 @@ bool LyX::readRcFile(string const & name)
        return true;
 }
 
-
-// Read the ui file `name'
-bool LyX::readUIFile(string const & name, bool include)
-{
-       enum Uitags {
-               ui_menuset = 1,
-               ui_toolbars,
-               ui_toolbarset,
-               ui_include,
-               ui_last
-       };
-
-       struct keyword_item uitags[ui_last - 1] = {
-               { "include", ui_include },
-               { "menuset", ui_menuset },
-               { "toolbars", ui_toolbars },
-               { "toolbarset", ui_toolbarset }
-       };
-
-       // Ensure that a file is read only once (prevents include loops)
-       static list<string> uifiles;
-       list<string>::const_iterator it  = uifiles.begin();
-       list<string>::const_iterator end = uifiles.end();
-       it = find(it, end, name);
-       if (it != end) {
-               LYXERR(Debug::INIT, "UI file '" << name << "' has been read already. "
-                                   << "Is this an include loop?");
-               return false;
-       }
-
-       LYXERR(Debug::INIT, "About to read " << name << "...");
-
-
-       FileName ui_path;
-       if (include) {
-               ui_path = libFileSearch("ui", name, "inc");
-               if (ui_path.empty())
-                       ui_path = libFileSearch("ui",
-                                               changeExtension(name, "inc"));
-       }
-       else
-               ui_path = libFileSearch("ui", name, "ui");
-
-       if (ui_path.empty()) {
-               LYXERR(Debug::INIT, "Could not find " << name);
-               showFileError(name);
-               return false;
-       }
-
-       uifiles.push_back(name);
-
-       LYXERR(Debug::INIT, "Found " << name << " in " << ui_path);
-       Lexer lex(uitags, ui_last - 1);
-       lex.setFile(ui_path);
-       if (!lex.isOK()) {
-               lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
-                      << endl;
-       }
-
-       if (lyxerr.debugging(Debug::PARSER))
-               lex.printTable(lyxerr);
-
-       while (lex.isOK()) {
-               switch (lex.lex()) {
-               case ui_include: {
-                       lex.next(true);
-                       string const file = lex.getString();
-                       if (!readUIFile(file, true))
-                               return false;
-                       break;
-               }
-               case ui_menuset:
-                       theApp()->menuBackend().read(lex);
-                       break;
-
-               case ui_toolbarset:
-                       toolbarbackend.readToolbars(lex);
-                       break;
-
-               case ui_toolbars:
-                       toolbarbackend.readToolbarSettings(lex);
-                       break;
-
-               default:
-                       if (!rtrim(lex.getString()).empty())
-                               lex.printError("LyX::ReadUIFile: "
-                                              "Unknown menu tag: `$$Token'");
-                       break;
-               }
-       }
-       return true;
-}
-
-
 // Read the languages file `name'
 bool LyX::readLanguagesFile(string const & name)
 {
@@ -1148,12 +945,10 @@ bool LyX::readEncodingsFile(string const & enc_name,
 
 namespace {
 
-string batch;
-
 /// return the the number of arguments consumed
-typedef boost::function<int(string const &, string const &)> cmd_helper;
+typedef boost::function<int(string const &, string const &, string &)> cmd_helper;
 
-int parse_dbg(string const & arg, string const &)
+int parse_dbg(string const & arg, string const &, string &)
 {
        if (arg.empty()) {
                lyxerr << to_utf8(_("List of supported debug flags:")) << endl;
@@ -1168,7 +963,7 @@ int parse_dbg(string const & arg, string const &)
 }
 
 
-int parse_help(string const &, string const &)
+int parse_help(string const &, string const &, string &)
 {
        lyxerr <<
                to_utf8(_("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
@@ -1186,9 +981,11 @@ int parse_help(string const &, string const &)
                  "                  where fmt is the export format of choice.\n"
                  "                  Look on Tools->Preferences->File formats->Format\n"
                  "                  to get an idea which parameters should be passed.\n"
+                 "                  Note that the order of -e and -x switches matters."
                  "\t-i [--import] fmt file.xxx\n"
                  "                  where fmt is the import format of choice\n"
                  "                  and file.xxx is the file to be imported.\n"
+                 "\t--batch         execute commands and exit\n"
                  "\t-version        summarize version and build info\n"
                               "Check the LyX man page for more details.")) << endl;
        exit(0);
@@ -1196,7 +993,7 @@ int parse_help(string const &, string const &)
 }
 
 
-int parse_version(string const &, string const &)
+int parse_version(string const &, string const &, string &)
 {
        lyxerr << "LyX " << lyx_version
               << " (" << lyx_release_date << ")" << endl;
@@ -1208,7 +1005,7 @@ int parse_version(string const &, string const &)
 }
 
 
-int parse_sysdir(string const & arg, string const &)
+int parse_sysdir(string const & arg, string const &, string &)
 {
        if (arg.empty()) {
                Alert::error(_("No system directory"),
@@ -1220,7 +1017,7 @@ int parse_sysdir(string const & arg, string const &)
 }
 
 
-int parse_userdir(string const & arg, string const &)
+int parse_userdir(string const & arg, string const &, string &)
 {
        if (arg.empty()) {
                Alert::error(_("No user directory"),
@@ -1232,7 +1029,7 @@ int parse_userdir(string const & arg, string const &)
 }
 
 
-int parse_execute(string const & arg, string const &)
+int parse_execute(string const & arg, string const &, string & batch)
 {
        if (arg.empty()) {
                Alert::error(_("Incomplete command"),
@@ -1244,7 +1041,7 @@ int parse_execute(string const & arg, string const &)
 }
 
 
-int parse_export(string const & type, string const &)
+int parse_export(string const & type, string const &, string & batch)
 {
        if (type.empty()) {
                lyxerr << to_utf8(_("Missing file type [eg latex, ps...] after "
@@ -1257,7 +1054,7 @@ int parse_export(string const & type, string const &)
 }
 
 
-int parse_import(string const & type, string const & file)
+int parse_import(string const & type, string const & file, string & batch)
 {
        if (type.empty()) {
                lyxerr << to_utf8(_("Missing file type [eg latex, ps...] after "
@@ -1274,16 +1071,19 @@ int parse_import(string const & type, string const & file)
 }
 
 
-int parse_geometry(string const & arg1, string const &)
+int parse_geometry(string const & arg1, string const &, string &)
 {
        geometryArg = arg1;
-#if defined(_WIN32) || (defined(__CYGWIN__) && defined(X_DISPLAY_MISSING))
-       // remove also the arg
-       return 1;
-#else
-       // don't remove "-geometry"
+       // don't remove "-geometry", it will be pruned out later in the
+       // frontend if need be.
        return -1;
-#endif
+}
+
+
+int parse_batch(string const &, string const &, string &) 
+{
+       use_gui = false;
+       return 0;
 }
 
 
@@ -1308,6 +1108,7 @@ void LyX::easyParse(int & argc, char * argv[])
        cmdmap["-i"] = parse_import;
        cmdmap["--import"] = parse_import;
        cmdmap["-geometry"] = parse_geometry;
+       cmdmap["--batch"] = parse_batch;
 
        for (int i = 1; i < argc; ++i) {
                map<string, cmd_helper>::const_iterator it
@@ -1322,7 +1123,10 @@ void LyX::easyParse(int & argc, char * argv[])
                string const arg2 =
                        (i + 2 < argc) ? to_utf8(from_local8bit(argv[i + 2])) : string();
 
-               int const remove = 1 + it->second(arg, arg2);
+               string batch;
+               int const remove = 1 + it->second(arg, arg2, batch);
+               if (!batch.empty())
+                       pimpl_->batch_commands.push_back(batch);
 
                // Now, remove used arguments by shifting
                // the following ones remove places down.
@@ -1333,102 +1137,142 @@ void LyX::easyParse(int & argc, char * argv[])
                        --i;
                }
        }
-
-       pimpl_->batch_command = batch;
 }
 
 
 FuncStatus getStatus(FuncRequest const & action)
 {
-       return LyX::ref().lyxFunc().getStatus(action);
+       LASSERT(singleton_, /**/);
+       return singleton_->pimpl_->lyxfunc_.getStatus(action);
 }
 
 
 void dispatch(FuncRequest const & action)
 {
-       LyX::ref().lyxFunc().dispatch(action);
+       LASSERT(singleton_, /**/);
+       singleton_->pimpl_->lyxfunc_.dispatch(action);
 }
 
 
 BufferList & theBufferList()
 {
-       return LyX::ref().bufferList();
+       LASSERT(singleton_, /**/);
+       return singleton_->pimpl_->buffer_list_;
 }
 
 
 LyXFunc & theLyXFunc()
 {
-       return LyX::ref().lyxFunc();
+       LASSERT(singleton_, /**/);
+       return singleton_->pimpl_->lyxfunc_;
 }
 
 
 Server & theServer()
 {
        // FIXME: this should not be use_gui dependent
-       BOOST_ASSERT(use_gui);
-       return LyX::ref().server();
+       LASSERT(use_gui, /**/);
+       LASSERT(singleton_, /**/);
+       return *singleton_->pimpl_->lyx_server_.get();
 }
 
 
 ServerSocket & theServerSocket()
 {
        // FIXME: this should not be use_gui dependent
-       BOOST_ASSERT(use_gui);
-       return LyX::ref().socket();
+       LASSERT(use_gui, /**/);
+       LASSERT(singleton_, /**/);
+       return *singleton_->pimpl_->lyx_socket_.get();
 }
 
 
 KeyMap & theTopLevelKeymap()
 {
-       return LyX::ref().topLevelKeymap();
+       LASSERT(singleton_, /**/);
+       return singleton_->pimpl_->toplevel_keymap_;
 }
 
 
 Converters & theConverters()
 {
-       return  LyX::ref().converters();
+       LASSERT(singleton_, /**/);
+       return  singleton_->pimpl_->converters_;
 }
 
 
 Converters & theSystemConverters()
 {
-       return  LyX::ref().systemConverters();
+       LASSERT(singleton_, /**/);
+       return  singleton_->pimpl_->system_converters_;
 }
 
 
 Movers & theMovers()
 {
-       return  LyX::ref().pimpl_->movers_;
+       LASSERT(singleton_, /**/);
+       return singleton_->pimpl_->movers_;
 }
 
 
 Mover const & getMover(string  const & fmt)
 {
-       return  LyX::ref().pimpl_->movers_(fmt);
+       LASSERT(singleton_, /**/);
+       return singleton_->pimpl_->movers_(fmt);
 }
 
 
 void setMover(string const & fmt, string const & command)
 {
-       LyX::ref().pimpl_->movers_.set(fmt, command);
+       LASSERT(singleton_, /**/);
+       singleton_->pimpl_->movers_.set(fmt, command);
 }
 
 
 Movers & theSystemMovers()
 {
-       return  LyX::ref().pimpl_->system_movers_;
+       LASSERT(singleton_, /**/);
+       return singleton_->pimpl_->system_movers_;
 }
 
 
 Messages & getMessages(string const & language)
 {
-       return LyX::ref().getMessages(language);
+       LASSERT(singleton_, /**/);
+       return singleton_->messages(language);
 }
 
 
 Messages & getGuiMessages()
 {
-       return LyX::ref().getGuiMessages();
+       LASSERT(singleton_, /**/);
+       return singleton_->pimpl_->messages_["GUI"];
+}
+
+
+graphics::Previews & thePreviews()
+{
+       LASSERT(singleton_, /**/);
+       return singleton_->pimpl_->preview_;
+}
+
+
+Session & theSession()
+{
+       LASSERT(singleton_, /**/);
+       return *singleton_->pimpl_->session_.get();
+}
+
+
+CmdDef & theTopLevelCmdDef()
+{
+       LASSERT(singleton_, /**/);
+       return singleton_->pimpl_->toplevel_cmddef_;
+}
+
+
+SpellChecker * theSpellChecker()
+{
+       return singleton_->pimpl_->spell_checker_;
 }
 
 } // namespace lyx