]> git.lyx.org Git - lyx.git/blobdiff - src/LyX.cpp
version.h: tex2lyx can have the same actual fileformat
[lyx.git] / src / LyX.cpp
index 4038eae82d43d16aac99e3ff0db6d165e2fdac24..e678e98932154af0909028024a632847145cedd0 100644 (file)
@@ -4,10 +4,10 @@
  * Licence details can be found in the file COPYING.
  *
  * \author Alfredo Braunstein
  * 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 Jean-Marc Lasgouttes
  * \author John Levon
- * \author André Pönitz
+ * \author André Pönitz
  *
  * Full author contact details are available in file CREDITS.
  */
  *
  * Full author contact details are available in file CREDITS.
  */
 
 #include "LyX.h"
 
 
 #include "LyX.h"
 
-#include "LayoutFile.h"
+#include "AppleSpellChecker.h"
+#include "AspellChecker.h"
 #include "Buffer.h"
 #include "BufferList.h"
 #include "CmdDef.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 "ConverterCache.h"
 #include "Converter.h"
 #include "CutAndPaste.h"
+#include "EnchantChecker.h"
 #include "Encoding.h"
 #include "ErrorList.h"
 #include "Format.h"
 #include "FuncStatus.h"
 #include "Encoding.h"
 #include "ErrorList.h"
 #include "Format.h"
 #include "FuncStatus.h"
+#include "HunspellChecker.h"
 #include "KeyMap.h"
 #include "Language.h"
 #include "KeyMap.h"
 #include "Language.h"
+#include "LaTeXFonts.h"
+#include "LayoutFile.h"
 #include "Lexer.h"
 #include "Lexer.h"
+#include "LyX.h"
 #include "LyXAction.h"
 #include "LyXAction.h"
-#include "LyXFunc.h"
 #include "LyXRC.h"
 #include "ModuleList.h"
 #include "Mover.h"
 #include "Server.h"
 #include "ServerSocket.h"
 #include "Session.h"
 #include "LyXRC.h"
 #include "ModuleList.h"
 #include "Mover.h"
 #include "Server.h"
 #include "ServerSocket.h"
 #include "Session.h"
+#include "WordList.h"
 
 #include "frontends/alert.h"
 #include "frontends/Application.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/lassert.h"
 #include "support/debug.h"
 #include "support/environment.h"
 #include "support/Messages.h"
 #include "support/os.h"
 #include "support/Package.h"
 #include "support/Messages.h"
 #include "support/os.h"
 #include "support/Package.h"
-#include "support/Path.h"
+#include "support/PathChanger.h"
 #include "support/Systemcall.h"
 
 #include "support/Systemcall.h"
 
-#include <boost/bind.hpp>
+#include "support/bind.h"
 #include <boost/scoped_ptr.hpp>
 
 #include <algorithm>
 #include <boost/scoped_ptr.hpp>
 
 #include <algorithm>
@@ -85,6 +89,22 @@ namespace os = support::os;
 
 bool use_gui = true;
 
 
 bool use_gui = true;
 
+
+// We default to open documents in an already running instance, provided that
+// the lyxpipe has been setup. This can be overridden either on the command
+// line or through preference settings.
+
+RunMode run_mode = PREFERRED;
+
+
+// Tell what files can be silently overwritten during batch export.
+// Possible values are: NO_FILES, MAIN_FILE, ALL_FILES, UNSPECIFIED.
+// Unless specified on command line (through the -f switch) or through the
+// environment variable LYX_FORCE_OVERWRITE, the default will be MAIN_FILE.
+
+OverwriteFiles force_overwrite = UNSPECIFIED;
+
+
 namespace {
 
 // Filled with the command line arguments "foo" of "-sysdir foo" or
 namespace {
 
 // Filled with the command line arguments "foo" of "-sysdir foo" or
@@ -117,19 +137,21 @@ void reconfigureUserLyXDir()
 
 } // namespace anon
 
 
 } // namespace anon
 
-
 /// The main application class private implementation.
 /// The main application class private implementation.
-struct LyX::Impl
-{
+struct LyX::Impl {
        Impl()
        Impl()
+               : latexfonts_(0), spell_checker_(0), apple_spell_checker_(0), aspell_checker_(0), enchant_checker_(0), hunspell_checker_(0)
+       {}
+
+       ~Impl()
        {
        {
-               // Set the default User Interface language as soon as possible.
-               // The language used will be derived from the environment
-               // variables.
-               messages_["GUI"] = Messages();
+               delete latexfonts_;
+               delete apple_spell_checker_;
+               delete aspell_checker_;
+               delete enchant_checker_;
+               delete hunspell_checker_;
        }
        }
-       /// our function handler
-       LyXFunc lyxfunc_;
+
        ///
        BufferList buffer_list_;
        ///
        ///
        BufferList buffer_list_;
        ///
@@ -166,11 +188,23 @@ struct LyX::Impl
        bool first_start;
        /// the parsed command line batch command if any
        vector<string> batch_commands;
        bool first_start;
        /// the parsed command line batch command if any
        vector<string> batch_commands;
+       
+       ///
+       LaTeXFonts * latexfonts_;
 
        ///
 
        ///
-       graphics::Previews preview_;
+       SpellChecker * spell_checker_;
+       ///
+       SpellChecker * apple_spell_checker_;
+       ///
+       SpellChecker * aspell_checker_;
+       ///
+       SpellChecker * enchant_checker_;
+       ///
+       SpellChecker * hunspell_checker_;
 };
 
 };
 
+
 ///
 frontend::Application * theApp()
 {
 ///
 frontend::Application * theApp()
 {
@@ -183,8 +217,9 @@ frontend::Application * theApp()
 
 LyX::~LyX()
 {
 
 LyX::~LyX()
 {
-       singleton_ = 0;
        delete pimpl_;
        delete pimpl_;
+       singleton_ = 0;
+       WordList::cleanupWordLists();
 }
 
 
 }
 
 
@@ -226,37 +261,28 @@ Messages & LyX::messages(string const & language)
        pair<map<string, Messages>::iterator, bool> result =
                        pimpl_->messages_.insert(make_pair(language, Messages(language)));
 
        pair<map<string, Messages>::iterator, bool> result =
                        pimpl_->messages_.insert(make_pair(language, Messages(language)));
 
-       LASSERT(result.second, /**/);
+       LATTEST(result.second);
        return result.first->second;
 }
 
 
        return result.first->second;
 }
 
 
-void setRcGuiLanguage()
-{
-       LASSERT(singleton_, "");
-       if (lyxrc.gui_language == "auto")
-               return;
-       Language const * language = languages.getLanguage(lyxrc.gui_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!");
-       singleton_->pimpl_->messages_["GUI"] = Messages();
-}
-
-
 int LyX::exec(int & argc, char * argv[])
 {
 int LyX::exec(int & argc, char * argv[])
 {
+       // Minimal setting of locale before parsing command line
+       try {
+               init_package(os::utf8_argv(0), string(), string());
+               // we do not get to this point when init_package throws an exception
+               locale_init();
+       } catch (ExceptionMessage const & message) {
+               LYXERR(Debug::LOCALE, message.title_ + ", " + message.details_);
+       }
+
        // Here we need to parse the command line. At least
        // we need to parse for "-dbg" and "-help"
        easyParse(argc, argv);
 
        try {
        // Here we need to parse the command line. At least
        // we need to parse for "-dbg" and "-help"
        easyParse(argc, argv);
 
        try {
-               init_package(to_utf8(from_local8bit(argv[0])),
-                             cl_system_support, cl_user_support,
-                             top_build_dir_is_one_level_up);
+               init_package(os::utf8_argv(0), cl_system_support, cl_user_support);
        } catch (ExceptionMessage const & message) {
                if (message.type_ == ErrorException) {
                        Alert::error(message.title_, message.details_);
        } catch (ExceptionMessage const & message) {
                if (message.type_ == ErrorException) {
                        Alert::error(message.title_, message.details_);
@@ -293,12 +319,13 @@ int LyX::exec(int & argc, char * argv[])
                        Buffer * buf = *I;
                        if (buf != buf->masterBuffer())
                                continue;
                        Buffer * buf = *I;
                        if (buf != buf->masterBuffer())
                                continue;
-                       bool success = false;
                        vector<string>::const_iterator bcit  = pimpl_->batch_commands.begin();
                        vector<string>::const_iterator bcend = pimpl_->batch_commands.end();
                        vector<string>::const_iterator bcit  = pimpl_->batch_commands.begin();
                        vector<string>::const_iterator bcend = pimpl_->batch_commands.end();
-                       for (; bcit != bcend; bcit++) {
-                               buf->dispatch(*bcit, &success);
-                               final_success |= success;
+                       DispatchResult dr;
+                       for (; bcit != bcend; ++bcit) {
+                               LYXERR(Debug::ACTION, "Buffer::dispatch: cmd: " << *bcit);
+                               buf->dispatch(*bcit, dr);
+                               final_success |= !dr.error();
                        }
                }
                prepareExit();
                        }
                }
                prepareExit();
@@ -322,22 +349,37 @@ int LyX::exec(int & argc, char * argv[])
                prepareExit();
                return exit_status;
        }
                prepareExit();
                return exit_status;
        }
+
+       // If not otherwise specified by a command line option or
+       // by preferences, we default to reuse a running instance.
+       if (run_mode == PREFERRED)
+               run_mode = USE_REMOTE;
+
        // FIXME
        /* Create a CoreApplication class that will provide the main event loop
        * and the socket callback registering. With Qt4, only QtCore
        * library would be needed.
        * When this is done, a server_mode could be created and the following two
        * line would be moved out from here.
        // FIXME
        /* Create a CoreApplication class that will provide the main event loop
        * and the socket callback registering. With Qt4, only QtCore
        * library would be needed.
        * When this is done, a server_mode could be created and the following two
        * line would be moved out from here.
+       * However, note that the first of the two lines below triggers the
+       * "single instance" behavior, which should occur right at this point.
        */
        // Note: socket callback must be registered after init(argc, argv)
        // such that package().temp_dir() is properly initialized.
        */
        // Note: socket callback must be registered after init(argc, argv)
        // such that package().temp_dir() is properly initialized.
-       pimpl_->lyx_server_.reset(new Server(&pimpl_->lyxfunc_, lyxrc.lyxpipes));
-       pimpl_->lyx_socket_.reset(new ServerSocket(&pimpl_->lyxfunc_,
-                       FileName(package().temp_dir().absFilename() + "/lyxsocket")));
+       pimpl_->lyx_server_.reset(new Server(lyxrc.lyxpipes));
+       pimpl_->lyx_socket_.reset(new ServerSocket(
+                       FileName(package().temp_dir().absFileName() + "/lyxsocket")));
 
        // Start the real execution loop.
 
        // Start the real execution loop.
-       exit_status = pimpl_->application_->exec();
+       if (!theServer().deferredLoadingToOtherInstance())
+               exit_status = pimpl_->application_->exec();
+       else if (!pimpl_->files_to_load_.empty()) {
+               vector<string>::const_iterator it = pimpl_->files_to_load_.begin();
+               vector<string>::const_iterator end = pimpl_->files_to_load_.end();
+               lyxerr << _("The following files could not be loaded:") << endl;
+               for (; it != end; ++it)
+                       lyxerr << *it << endl;
+       }
 
        prepareExit();
 
 
        prepareExit();
 
@@ -351,6 +393,9 @@ void LyX::prepareExit()
        cap::clearCutStack();
        cap::clearSelection();
 
        cap::clearCutStack();
        cap::clearSelection();
 
+       // Write the index file of the converter cache
+       ConverterCache::get().writeIndex();
+
        // close buffers first
        pimpl_->buffer_list_.closeAll();
 
        // close buffers first
        pimpl_->buffer_list_.closeAll();
 
@@ -365,19 +410,19 @@ void LyX::prepareExit()
 
        // do any other cleanup procedures now
        if (package().temp_dir() != package().system_temp_dir()) {
 
        // do any other cleanup procedures now
        if (package().temp_dir() != package().system_temp_dir()) {
-               string const abs_tmpdir = package().temp_dir().absFilename();
-               if (!contains(package().temp_dir().absFilename(), "lyx_tmpdir")) {
+               string const abs_tmpdir = package().temp_dir().absFileName();
+               if (!contains(package().temp_dir().absFileName(), "lyx_tmpdir")) {
                        docstring const 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 "
                        docstring const 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());
+                               << package().temp_dir().absFileName());
                        if (!package().temp_dir().destroyDirectory()) {
                                docstring const msg =
                                        bformat(_("Unable to remove the temporary directory %1$s"),
                        if (!package().temp_dir().destroyDirectory()) {
                                docstring const msg =
                                        bformat(_("Unable to remove the temporary directory %1$s"),
-                                       from_utf8(package().temp_dir().absFilename()));
+                                       from_utf8(package().temp_dir().absFileName()));
                                Alert::warning(_("Unable to remove temporary directory"), msg);
                        }
                }
                                Alert::warning(_("Unable to remove temporary directory"), msg);
                        }
                }
@@ -385,14 +430,13 @@ void LyX::prepareExit()
 
        // Kill the application object before exiting. This avoids crashes
        // when exiting on Linux.
 
        // Kill the application object before exiting. This avoids crashes
        // when exiting on Linux.
-       if (pimpl_->application_)
-               pimpl_->application_.reset();
+       pimpl_->application_.reset();
 }
 
 
 void LyX::earlyExit(int status)
 {
 }
 
 
 void LyX::earlyExit(int status)
 {
-       LASSERT(pimpl_->application_.get(), /**/);
+       LATTEST(pimpl_->application_.get());
        // LyX::pimpl_::application_ is not initialised at this
        // point so it's safe to just exit after some cleanup.
        prepareExit();
        // LyX::pimpl_::application_ is not initialised at this
        // point so it's safe to just exit after some cleanup.
        prepareExit();
@@ -408,7 +452,7 @@ int LyX::init(int & argc, char * argv[])
                if (argv[argi][0] == '-') {
                        lyxerr << to_utf8(
                                bformat(_("Wrong command line option `%1$s'. Exiting."),
                if (argv[argi][0] == '-') {
                        lyxerr << to_utf8(
                                bformat(_("Wrong command line option `%1$s'. Exiting."),
-                               from_utf8(argv[argi]))) << endl;
+                               from_utf8(os::utf8_argv(argi)))) << endl;
                        return EXIT_FAILURE;
                }
        }
                        return EXIT_FAILURE;
                }
        }
@@ -421,12 +465,17 @@ int LyX::init(int & argc, char * argv[])
                return EXIT_FAILURE;
 
        // Remaining arguments are assumed to be files to load.
                return EXIT_FAILURE;
 
        // Remaining arguments are assumed to be files to load.
-       for (int argi = argc - 1; argi >= 1; --argi)
-               pimpl_->files_to_load_.push_back(to_utf8(from_local8bit(argv[argi])));
+       for (int argi = 1; argi < argc; ++argi)
+               pimpl_->files_to_load_.push_back(os::utf8_argv(argi));
+
+       if (!use_gui && pimpl_->files_to_load_.empty()) {
+               lyxerr << to_utf8(_("Missing filename for this operation.")) << endl;
+               return EXIT_FAILURE;
+       }
 
        if (first_start) {
                pimpl_->files_to_load_.push_back(
 
        if (first_start) {
                pimpl_->files_to_load_.push_back(
-                       i18nLibFileSearch("examples", "splash.lyx").absFilename());
+                       i18nLibFileSearch("examples", "splash.lyx").absFileName());
        }
 
        return EXIT_SUCCESS;
        }
 
        return EXIT_SUCCESS;
@@ -435,7 +484,7 @@ int LyX::init(int & argc, char * argv[])
 
 bool LyX::loadFiles()
 {
 
 bool LyX::loadFiles()
 {
-       LASSERT(!use_gui, /**/);
+       LATTEST(!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();
        bool success = true;
        vector<string>::const_iterator it = pimpl_->files_to_load_.begin();
        vector<string>::const_iterator end = pimpl_->files_to_load_.end();
@@ -449,15 +498,19 @@ bool LyX::loadFiles()
                if (fname.empty())
                        continue;
 
                if (fname.empty())
                        continue;
 
-               Buffer * buf = pimpl_->buffer_list_.newBuffer(fname.absFilename(), false);
-               if (buf->loadLyXFile(fname)) {
+               Buffer * buf = pimpl_->buffer_list_.newBuffer(fname.absFileName());
+               if (buf->loadLyXFile() == Buffer::ReadSuccess) {
                        ErrorList const & el = buf->errorList("Parse");
                        if (!el.empty())
                                for_each(el.begin(), el.end(),
                        ErrorList const & el = buf->errorList("Parse");
                        if (!el.empty())
                                for_each(el.begin(), el.end(),
-                               boost::bind(&LyX::printError, this, _1));
+                               bind(&LyX::printError, this, _1));
                }
                else {
                        pimpl_->buffer_list_.release(buf);
                }
                else {
                        pimpl_->buffer_list_.release(buf);
+                       docstring const error_message =
+                               bformat(_("LyX failed to load the following file: %1$s"),
+                               from_utf8(fname.absFileName()));
+                       lyxerr << to_utf8(error_message) << endl;
                        success = false;
                }
        }
                        success = false;
                }
        }
@@ -467,7 +520,7 @@ bool LyX::loadFiles()
 
 void execBatchCommands()
 {
 
 void execBatchCommands()
 {
-       LASSERT(singleton_, /**/);
+       LAPPERR(singleton_);
        singleton_->execCommands();
 }
 
        singleton_->execCommands();
 }
 
@@ -479,46 +532,44 @@ void LyX::execCommands()
        // aknowledged.
 
        // if reconfiguration is needed.
        // aknowledged.
 
        // if reconfiguration is needed.
-       while (LayoutFileList::get().empty()) {
+       if (LayoutFileList::get().empty()) {
                switch (Alert::prompt(
                        _("No textclass is found"),
                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."),
+                       _("LyX will only have minimal functionality because no textclasses "
+                               "have been found. You can either try to reconfigure LyX normally, "
+                               "try to reconfigure without checking your LaTeX installation, or continue."),
                        0, 2,
                        _("&Reconfigure"),
                        0, 2,
                        _("&Reconfigure"),
-                       _("&Use Default"),
-                       _("&Exit LyX")))
+                       _("&Without LaTeX"),
+                       _("&Continue")))
                {
                case 0:
                        // regular reconfigure
                {
                case 0:
                        // regular reconfigure
-                       pimpl_->lyxfunc_.dispatch(FuncRequest(LFUN_RECONFIGURE, ""));
+                       lyx::dispatch(FuncRequest(LFUN_RECONFIGURE, ""));
                        break;
                case 1:
                        // reconfigure --without-latex-config
                        break;
                case 1:
                        // reconfigure --without-latex-config
-                       pimpl_->lyxfunc_.dispatch(FuncRequest(LFUN_RECONFIGURE,
+                       lyx::dispatch(FuncRequest(LFUN_RECONFIGURE,
                                " --without-latex-config"));
                        break;
                default:
                                " --without-latex-config"));
                        break;
                default:
-                       pimpl_->lyxfunc_.dispatch(FuncRequest(LFUN_LYX_QUIT));
-                       return;
+                       break;
                }
        }
                }
        }
-       
+
        // create the first main window
        // create the first main window
-       pimpl_->lyxfunc_.dispatch(FuncRequest(LFUN_WINDOW_NEW, geometryArg));
+       lyx::dispatch(FuncRequest(LFUN_WINDOW_NEW, geometryArg));
 
        if (!pimpl_->files_to_load_.empty()) {
                // if some files were specified at command-line we assume that the
                // user wants to edit *these* files and not to restore the session.
                for (size_t i = 0; i != pimpl_->files_to_load_.size(); ++i) {
 
        if (!pimpl_->files_to_load_.empty()) {
                // if some files were specified at command-line we assume that the
                // user wants to edit *these* files and not to restore the session.
                for (size_t i = 0; i != pimpl_->files_to_load_.size(); ++i) {
-                       pimpl_->lyxfunc_.dispatch(
+                       lyx::dispatch(
                                FuncRequest(LFUN_FILE_OPEN, pimpl_->files_to_load_[i]));
                }
                // clear this list to save a few bytes of RAM
                pimpl_->files_to_load_.clear();
                                FuncRequest(LFUN_FILE_OPEN, pimpl_->files_to_load_[i]));
                }
                // 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
                pimpl_->application_->restoreGuiSession();
 
        // Execute batch commands if available
@@ -527,9 +578,9 @@ void LyX::execCommands()
 
        vector<string>::const_iterator bcit  = pimpl_->batch_commands.begin();
        vector<string>::const_iterator bcend = pimpl_->batch_commands.end();
 
        vector<string>::const_iterator bcit  = pimpl_->batch_commands.begin();
        vector<string>::const_iterator bcend = pimpl_->batch_commands.end();
-       for (; bcit != bcend; bcit++) {
+       for (; bcit != bcend; ++bcit) {
                LYXERR(Debug::INIT, "About to handle -x '" << *bcit << '\'');
                LYXERR(Debug::INIT, "About to handle -x '" << *bcit << '\'');
-               pimpl_->lyxfunc_.dispatch(lyxaction.lookupFunc(*bcit));
+               lyx::dispatch(lyxaction.lookupFunc(*bcit));
        }
 }
 
        }
 }
 
@@ -541,7 +592,7 @@ The SIGHUP signal does not exist on Windows and does not need to be handled.
 
 Windows handles SIGFPE and SIGSEGV signals as expected.
 
 
 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.
 
 cause a new thread to be spawned. This may well result in unexpected
 behaviour by the single-threaded LyX.
 
@@ -589,21 +640,23 @@ static void error_handler(int err_sig)
 
        // This shouldn't matter here, however, as we've already invoked
        // emergencyCleanup.
 
        // This shouldn't matter here, however, as we've already invoked
        // emergencyCleanup.
+       docstring msg;
        switch (err_sig) {
 #ifdef SIGHUP
        case SIGHUP:
        switch (err_sig) {
 #ifdef SIGHUP
        case SIGHUP:
-               lyxerr << "\nlyx: SIGHUP signal caught\nBye." << endl;
+               msg = _("SIGHUP signal caught!\nBye.");
                break;
 #endif
        case SIGFPE:
                break;
 #endif
        case SIGFPE:
-               lyxerr << "\nlyx: SIGFPE signal caught\nBye." << endl;
+               msg = _("SIGFPE signal caught!\nBye.");
                break;
        case SIGSEGV:
                break;
        case SIGSEGV:
-               lyxerr << "\nlyx: SIGSEGV signal caught\n"
-                         "Sorry, you have found a bug in LyX. "
+               msg = _("SIGSEGV signal caught!\n"
+                         "Sorry, you have found a bug in LyX, "
+                         "hope you have not lost any data.\n"
                          "Please read the bug-reporting instructions "
                          "Please read the bug-reporting instructions "
-                         "in Help->Introduction and send us a bug report, "
-                         "if necessary. Thanks !\nBye." << endl;
+                         "in 'Help->Introduction' and send us a bug report, "
+                         "if necessary. Thanks!\nBye.");
                break;
        case SIGINT:
        case SIGTERM:
                break;
        case SIGINT:
        case SIGTERM:
@@ -611,6 +664,12 @@ static void error_handler(int err_sig)
                break;
        }
 
                break;
        }
 
+       if (!msg.empty()) {
+               lyxerr << "\nlyx: " << msg << endl;
+               // try to make a GUI message
+               Alert::error(_("LyX crashed!"), msg);
+       }
+
        // Deinstall the signal handlers
 #ifdef SIGHUP
        signal(SIGHUP, SIG_DFL);
        // Deinstall the signal handlers
 #ifdef SIGHUP
        signal(SIGHUP, SIG_DFL);
@@ -622,11 +681,18 @@ static void error_handler(int err_sig)
 
 #ifdef SIGHUP
        if (err_sig == SIGSEGV ||
 
 #ifdef SIGHUP
        if (err_sig == SIGSEGV ||
-           (err_sig != SIGHUP && !getEnv("LYXDEBUG").empty()))
+               (err_sig != SIGHUP && !getEnv("LYXDEBUG").empty())) {
 #else
 #else
-       if (err_sig == SIGSEGV || !getEnv("LYXDEBUG").empty())
+       if (err_sig == SIGSEGV || !getEnv("LYXDEBUG").empty()) {
 #endif
 #endif
+#ifdef _MSC_VER
+               // with abort() it crashes again.
+               exit(err_sig);
+#else
                abort();
                abort();
+#endif
+       }
+
        exit(0);
 }
 
        exit(0);
 }
 
@@ -652,18 +718,24 @@ bool LyX::init()
        signal(SIGTERM, error_handler);
        // SIGPIPE can be safely ignored.
 
        signal(SIGTERM, error_handler);
        // SIGPIPE can be safely ignored.
 
-       lyxrc.tempdir_path = package().temp_dir().absFilename();
-       lyxrc.document_path = package().document_dir().absFilename();
+       lyxrc.tempdir_path = package().temp_dir().absFileName();
+       lyxrc.document_path = package().document_dir().absFileName();
 
        if (lyxrc.example_path.empty()) {
 
        if (lyxrc.example_path.empty()) {
-               lyxrc.example_path = addPath(package().system_support().absFilename(),
+               lyxrc.example_path = addPath(package().system_support().absFileName(),
                                              "examples");
        }
        if (lyxrc.template_path.empty()) {
                                              "examples");
        }
        if (lyxrc.template_path.empty()) {
-               lyxrc.template_path = addPath(package().system_support().absFilename(),
+               lyxrc.template_path = addPath(package().system_support().absFileName(),
                                              "templates");
        }
 
                                              "templates");
        }
 
+       // init LyXDir environment variable
+       string const lyx_dir = package().lyx_dir().absFileName();
+       LYXERR(Debug::INIT, "Setting LyXDir... to \"" << lyx_dir << "\"");
+       if (!setEnv("LyXDir", lyx_dir))
+               LYXERR(Debug::INIT, "\t... failed!");
+
        //
        // Read configuration files
        //
        //
        // Read configuration files
        //
@@ -672,26 +744,34 @@ bool LyX::init()
        if (!readRcFile("lyxrc.dist"))
                return false;
 
        if (!readRcFile("lyxrc.dist"))
                return false;
 
-       // Set the language defined by the distributor.
-       setRcGuiLanguage();
-
        // Set the PATH correctly.
 #if !defined (USE_POSIX_PACKAGING)
        // Add the directory containing the LyX executable to the path
        // so that LyX can find things like tex2lyx.
        if (package().build_support().empty())
        // Set the PATH correctly.
 #if !defined (USE_POSIX_PACKAGING)
        // Add the directory containing the LyX executable to the path
        // so that LyX can find things like tex2lyx.
        if (package().build_support().empty())
-               prependEnvPath("PATH", package().binary_dir().absFilename());
+               prependEnvPath("PATH", package().binary_dir().absFileName());
 #endif
        if (!lyxrc.path_prefix.empty())
 #endif
        if (!lyxrc.path_prefix.empty())
-               prependEnvPath("PATH", lyxrc.path_prefix);
+               prependEnvPath("PATH", replaceEnvironmentPath(lyxrc.path_prefix));
 
        // Check that user LyX directory is ok.
        if (queryUserLyXDir(package().explicit_user_support()))
                reconfigureUserLyXDir();
 
 
        // Check that user LyX directory is ok.
        if (queryUserLyXDir(package().explicit_user_support()))
                reconfigureUserLyXDir();
 
-       // no need for a splash when there is no GUI
        if (!use_gui) {
        if (!use_gui) {
+               // No need for a splash when there is no GUI
                first_start = false;
                first_start = false;
+               // Default is to overwrite the main file during export, unless
+               // the -f switch was specified or LYX_FORCE_OVERWRITE was set
+               if (force_overwrite == UNSPECIFIED) {
+                       string const what = getEnv("LYX_FORCE_OVERWRITE");
+                       if (what == "all")
+                               force_overwrite = ALL_FILES;
+                       else if (what == "none")
+                               force_overwrite = NO_FILES;
+                       else
+                               force_overwrite = MAIN_FILE;
+               }
        }
 
        // This one is generated in user_support directory by lib/configure.py.
        }
 
        // This one is generated in user_support directory by lib/configure.py.
@@ -704,9 +784,6 @@ bool LyX::init()
        // Read lyxrc.dist again to be able to override viewer auto-detection.
        readRcFile("lyxrc.dist");
 
        // 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_;
        system_lyxrc = lyxrc;
        system_formats = formats;
        pimpl_->system_converters_ = pimpl_->converters_;
@@ -714,7 +791,7 @@ bool LyX::init()
        system_lcolor = lcolor;
 
        // This one is edited through the preferences dialog.
        system_lcolor = lcolor;
 
        // This one is edited through the preferences dialog.
-       if (!readRcFile("preferences"))
+       if (!readRcFile("preferences", true))
                return false;
 
        if (!readEncodingsFile("encodings", "unicodesymbols"))
                return false;
 
        if (!readEncodingsFile("encodings", "unicodesymbols"))
@@ -722,15 +799,11 @@ bool LyX::init()
        if (!readLanguagesFile("languages"))
                return false;
 
        if (!readLanguagesFile("languages"))
                return false;
 
-       // Set the language defined by the user.
-       setRcGuiLanguage();
-
-       // Load the layouts
        LYXERR(Debug::INIT, "Reading layouts...");
        LYXERR(Debug::INIT, "Reading layouts...");
-       if (!LyXSetStyle())
-               return false;
+       // Load the layouts
+       LayoutFileList::get().read();
        //...and the modules
        //...and the modules
-       moduleList.load();
+       theModuleList.read();
 
        // read keymap and ui files in batch mode as well
        // because InsetInfo needs to know these to produce
 
        // read keymap and ui files in batch mode as well
        // because InsetInfo needs to know these to produce
@@ -739,20 +812,19 @@ bool LyX::init()
        // Set up command definitions
        pimpl_->toplevel_cmddef_.read(lyxrc.def_file);
 
        // Set up command definitions
        pimpl_->toplevel_cmddef_.read(lyxrc.def_file);
 
+       // FIXME
        // Set up bindings
        pimpl_->toplevel_keymap_.read("site");
        pimpl_->toplevel_keymap_.read(lyxrc.bind_file);
        // load user bind file user.bind
        // Set up bindings
        pimpl_->toplevel_keymap_.read("site");
        pimpl_->toplevel_keymap_.read(lyxrc.bind_file);
        // load user bind file user.bind
-       pimpl_->toplevel_keymap_.read("user");
-
-       pimpl_->lyxfunc_.initKeySequences(&pimpl_->toplevel_keymap_);
+       pimpl_->toplevel_keymap_.read("user", 0, KeyMap::MissingOK);
 
        if (lyxerr.debugging(Debug::LYXRC))
                lyxrc.print();
 
        os::windows_style_tex_paths(lyxrc.windows_style_tex_paths);
        if (!lyxrc.path_prefix.empty())
 
        if (lyxerr.debugging(Debug::LYXRC))
                lyxrc.print();
 
        os::windows_style_tex_paths(lyxrc.windows_style_tex_paths);
        if (!lyxrc.path_prefix.empty())
-               prependEnvPath("PATH", lyxrc.path_prefix);
+               prependEnvPath("PATH", replaceEnvironmentPath(lyxrc.path_prefix));
 
        FileName const document_path(lyxrc.document_path);
        if (document_path.exists() && document_path.isDirectory())
 
        FileName const document_path(lyxrc.document_path);
        if (document_path.exists() && document_path.isDirectory())
@@ -774,7 +846,7 @@ bool LyX::init()
        }
 
        LYXERR(Debug::INIT, "LyX tmp dir: `"
        }
 
        LYXERR(Debug::INIT, "LyX tmp dir: `"
-                           << package().temp_dir().absFilename() << '\'');
+                           << package().temp_dir().absFileName() << '\'');
 
        LYXERR(Debug::INIT, "Reading session information '.lyx/session'...");
        pimpl_->session_.reset(new Session(lyxrc.num_lastfiles));
 
        LYXERR(Debug::INIT, "Reading session information '.lyx/session'...");
        pimpl_->session_.reset(new Session(lyxrc.num_lastfiles));
@@ -782,7 +854,7 @@ 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();
        // 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;
 }
 
        return true;
 }
 
@@ -808,18 +880,18 @@ void emergencyCleanup()
 static bool needsUpdate(string const & file)
 {
        // We cannot initialize configure_script directly because the package
 static bool needsUpdate(string const & file)
 {
        // We cannot initialize configure_script directly because the package
-       // is not initialized yet when  static objects are constructed.
+       // is not initialized yet when static objects are constructed.
        static FileName configure_script;
        static bool firstrun = true;
        if (firstrun) {
                configure_script =
        static FileName configure_script;
        static bool firstrun = true;
        if (firstrun) {
                configure_script =
-                       FileName(addName(package().system_support().absFilename(),
+                       FileName(addName(package().system_support().absFileName(),
                                "configure.py"));
                firstrun = false;
        }
 
                                "configure.py"));
                firstrun = false;
        }
 
-       FileName absfile = 
-               FileName(addName(package().user_support().absFilename(), file));
+       FileName absfile =
+               FileName(addName(package().user_support().absFileName(), file));
        return !absfile.exists()
                || configure_script.lastModified() > absfile.lastModified();
 }
        return !absfile.exists()
                || configure_script.lastModified() > absfile.lastModified();
 }
@@ -848,7 +920,7 @@ bool LyX::queryUserLyXDir(bool explicit_userdir)
                    bformat(_("You have specified a non-existent user "
                                           "LyX directory, %1$s.\n"
                                           "It is needed to keep your own configuration."),
                    bformat(_("You have specified a non-existent user "
                                           "LyX directory, %1$s.\n"
                                           "It is needed to keep your own configuration."),
-                           from_utf8(package().user_support().absFilename())),
+                           from_utf8(package().user_support().absFileName())),
                    1, 0,
                    _("&Create directory"),
                    _("&Exit LyX"))) {
                    1, 0,
                    _("&Create directory"),
                    _("&Exit LyX"))) {
@@ -857,7 +929,7 @@ bool LyX::queryUserLyXDir(bool explicit_userdir)
        }
 
        lyxerr << to_utf8(bformat(_("LyX: Creating directory %1$s"),
        }
 
        lyxerr << to_utf8(bformat(_("LyX: Creating directory %1$s"),
-                         from_utf8(sup.absFilename()))) << endl;
+                         from_utf8(sup.absFileName()))) << endl;
 
        if (!sup.createDirectory(0755)) {
                // Failed, so let's exit.
 
        if (!sup.createDirectory(0755)) {
                // Failed, so let's exit.
@@ -870,21 +942,22 @@ bool LyX::queryUserLyXDir(bool explicit_userdir)
 }
 
 
 }
 
 
-bool LyX::readRcFile(string const & name)
+bool LyX::readRcFile(string const & name, bool check_format)
 {
        LYXERR(Debug::INIT, "About to read " << name << "... ");
 
        FileName const lyxrc_path = libFileSearch(string(), name);
 {
        LYXERR(Debug::INIT, "About to read " << name << "... ");
 
        FileName const lyxrc_path = libFileSearch(string(), name);
-       if (!lyxrc_path.empty()) {
-               LYXERR(Debug::INIT, "Found in " << lyxrc_path);
-               if (lyxrc.read(lyxrc_path) < 0) {
-                       showFileError(name);
-                       return false;
-               }
-       } else {
+       if (lyxrc_path.empty()) {
                LYXERR(Debug::INIT, "Not found." << lyxrc_path);
                LYXERR(Debug::INIT, "Not found." << lyxrc_path);
+               // FIXME
+               // This was the previous logic, but can it be right??
+               return true;
        }
        }
-       return true;
+       LYXERR(Debug::INIT, "Found in " << lyxrc_path);
+       bool const success = lyxrc.read(lyxrc_path, check_format);
+       if (!success)
+               showFileError(name);
+       return success;
 }
 
 // Read the languages file `name'
 }
 
 // Read the languages file `name'
@@ -933,13 +1006,13 @@ typedef boost::function<int(string const &, string const &, string &)> cmd_helpe
 int parse_dbg(string const & arg, string const &, string &)
 {
        if (arg.empty()) {
 int parse_dbg(string const & arg, string const &, string &)
 {
        if (arg.empty()) {
-               lyxerr << to_utf8(_("List of supported debug flags:")) << endl;
-               Debug::showTags(lyxerr);
+               cout << to_utf8(_("List of supported debug flags:")) << endl;
+               Debug::showTags(cout);
                exit(0);
        }
        lyxerr << to_utf8(bformat(_("Setting debug level to %1$s"), from_utf8(arg))) << endl;
 
                exit(0);
        }
        lyxerr << to_utf8(bformat(_("Setting debug level to %1$s"), from_utf8(arg))) << endl;
 
-       lyxerr.level(Debug::value(arg));
+       lyxerr.setLevel(Debug::value(arg));
        Debug::showLevel(lyxerr, lyxerr.level());
        return 1;
 }
        Debug::showLevel(lyxerr, lyxerr.level());
        return 1;
 }
@@ -947,7 +1020,7 @@ int parse_dbg(string const & arg, string const &, string &)
 
 int parse_help(string const &, string const &, string &)
 {
 
 int parse_help(string const &, string const &, string &)
 {
-       lyxerr <<
+       cout <<
                to_utf8(_("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
                  "Command line switches (case sensitive):\n"
                  "\t-help              summarize LyX usage\n"
                to_utf8(_("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
                  "Command line switches (case sensitive):\n"
                  "\t-help              summarize LyX usage\n"
@@ -960,13 +1033,29 @@ int parse_help(string const &, string const &, string &)
                  "\t-x [--execute] command\n"
                  "                  where command is a lyx command.\n"
                  "\t-e [--export] fmt\n"
                  "\t-x [--execute] command\n"
                  "                  where command is a lyx command.\n"
                  "\t-e [--export] fmt\n"
-                 "                  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"
+                 "                  where fmt is the export format of choice. Look in\n"
+                 "                  Tools->Preferences->File Handling->File Formats->Short Name\n"
+                 "                  to see which parameter (which differs from the format name\n"
+                 "                  in the File->Export menu) should be passed.\n"
+                 "                  Note that the order of -e and -x switches matters.\n"
+                 "\t-E [--export-to] fmt filename\n"
+                 "                  where fmt is the export format of choice (see --export),\n"
+                 "                  and filename is the destination filename.\n"
                  "\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-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-version        summarize version and build info\n"
+                 "\t-f [--force-overwrite] what\n"
+                 "                  where what is either `all', `main' or `none',\n"
+                 "                  specifying whether all files, main file only, or no files,\n"
+                 "                  respectively, are to be overwritten during a batch export.\n"
+                 "                  Anything else is equivalent to `all', but is not consumed.\n"
+                 "\t-n [--no-remote]\n"
+                 "                  open documents in a new instance\n"
+                 "\t-r [--remote]\n"
+                 "                  open documents in an already running instance\n"
+                 "                  (a working lyxpipe is needed)\n"
+                 "\t-batch    execute commands without launching GUI and exit.\n"
+                 "\t-version  summarize version and build info\n"
                               "Check the LyX man page for more details.")) << endl;
        exit(0);
        return 0;
                               "Check the LyX man page for more details.")) << endl;
        exit(0);
        return 0;
@@ -975,11 +1064,12 @@ int parse_help(string const &, string const &, string &)
 
 int parse_version(string const &, string const &, string &)
 {
 
 int parse_version(string const &, string const &, string &)
 {
-       lyxerr << "LyX " << lyx_version
+       cout << "LyX " << lyx_version
               << " (" << lyx_release_date << ")" << endl;
               << " (" << lyx_release_date << ")" << endl;
-       lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
+       cout << to_utf8(bformat(_("Built on %1$s[[date]], %2$s[[time]]"),
+               from_ascii(__DATE__), from_ascii(__TIME__))) << endl;
 
 
-       lyxerr << lyx_version_info << endl;
+       cout << lyx_version_info << endl;
        exit(0);
        return 0;
 }
        exit(0);
        return 0;
 }
@@ -1021,6 +1111,24 @@ int parse_execute(string const & arg, string const &, string & batch)
 }
 
 
 }
 
 
+int parse_export_to(string const & type, string const & output_file, string & batch)
+{
+       if (type.empty()) {
+               lyxerr << to_utf8(_("Missing file type [eg latex, ps...] after "
+                                        "--export-to switch")) << endl;
+               exit(1);
+       }
+       if (output_file.empty()) {
+               lyxerr << to_utf8(_("Missing destination filename after "
+                                        "--export-to switch")) << endl;
+               exit(1);
+       }
+       batch = "buffer-export " + type + " " + output_file;
+       use_gui = false;
+       return 2;
+}
+
+
 int parse_export(string const & type, string const &, string & batch)
 {
        if (type.empty()) {
 int parse_export(string const & type, string const &, string & batch)
 {
        if (type.empty()) {
@@ -1045,7 +1153,6 @@ int parse_import(string const & type, string const & file, string & batch)
                lyxerr << to_utf8(_("Missing filename for --import")) << endl;
                exit(1);
        }
                lyxerr << to_utf8(_("Missing filename for --import")) << endl;
                exit(1);
        }
-
        batch = "buffer-import " + type + ' ' + file;
        return 2;
 }
        batch = "buffer-import " + type + ' ' + file;
        return 2;
 }
@@ -1054,13 +1161,47 @@ int parse_import(string const & type, string const & file, string & batch)
 int parse_geometry(string const & arg1, string const &, string &)
 {
        geometryArg = arg1;
 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;
        return -1;
-#endif
+}
+
+
+int parse_batch(string const &, string const &, string &)
+{
+       use_gui = false;
+       return 0;
+}
+
+
+int parse_noremote(string const &, string const &, string &)
+{
+       run_mode = NEW_INSTANCE;
+       return 0;
+}
+
+
+int parse_remote(string const &, string const &, string &)
+{
+       run_mode = USE_REMOTE;
+       return 0;
+}
+
+
+int parse_force(string const & arg, string const &, string &)
+{
+       if (arg == "all") {
+               force_overwrite = ALL_FILES;
+               return 1;
+       } else if (arg == "main") {
+               force_overwrite = MAIN_FILE;
+               return 1;
+       } else if (arg == "none") {
+               force_overwrite = NO_FILES;
+               return 1;
+       }
+       force_overwrite = ALL_FILES;
+       return 0;
 }
 
 
 }
 
 
@@ -1080,11 +1221,20 @@ void LyX::easyParse(int & argc, char * argv[])
        cmdmap["-userdir"] = parse_userdir;
        cmdmap["-x"] = parse_execute;
        cmdmap["--execute"] = parse_execute;
        cmdmap["-userdir"] = parse_userdir;
        cmdmap["-x"] = parse_execute;
        cmdmap["--execute"] = parse_execute;
-       cmdmap["-e"] = parse_export;
+       cmdmap["-e"] = parse_export;
        cmdmap["--export"] = parse_export;
        cmdmap["--export"] = parse_export;
+       cmdmap["-E"] = parse_export_to;
+       cmdmap["--export-to"] = parse_export_to;
        cmdmap["-i"] = parse_import;
        cmdmap["--import"] = parse_import;
        cmdmap["-geometry"] = parse_geometry;
        cmdmap["-i"] = parse_import;
        cmdmap["--import"] = parse_import;
        cmdmap["-geometry"] = parse_geometry;
+       cmdmap["-batch"] = parse_batch;
+       cmdmap["-f"] = parse_force;
+       cmdmap["--force-overwrite"] = parse_force;
+       cmdmap["-n"] = parse_noremote;
+       cmdmap["--no-remote"] = parse_noremote;
+       cmdmap["-r"] = parse_remote;
+       cmdmap["--remote"] = parse_remote;
 
        for (int i = 1; i < argc; ++i) {
                map<string, cmd_helper>::const_iterator it
 
        for (int i = 1; i < argc; ++i) {
                map<string, cmd_helper>::const_iterator it
@@ -1095,9 +1245,9 @@ void LyX::easyParse(int & argc, char * argv[])
                        continue;
 
                string const arg =
                        continue;
 
                string const arg =
-                       (i + 1 < argc) ? to_utf8(from_local8bit(argv[i + 1])) : string();
+                       (i + 1 < argc) ? os::utf8_argv(i + 1) : string();
                string const arg2 =
                string const arg2 =
-                       (i + 2 < argc) ? to_utf8(from_local8bit(argv[i + 2])) : string();
+                       (i + 2 < argc) ? os::utf8_argv(i + 2) : string();
 
                string batch;
                int const remove = 1 + it->second(arg, arg2, batch);
 
                string batch;
                int const remove = 1 + it->second(arg, arg2, batch);
@@ -1107,6 +1257,7 @@ void LyX::easyParse(int & argc, char * argv[])
                // Now, remove used arguments by shifting
                // the following ones remove places down.
                if (remove > 0) {
                // Now, remove used arguments by shifting
                // the following ones remove places down.
                if (remove > 0) {
+                       os::remove_internal_args(i, remove);
                        argc -= remove;
                        for (int j = i; j < argc; ++j)
                                argv[j] = argv[j + remove];
                        argc -= remove;
                        for (int j = i; j < argc; ++j)
                                argv[j] = argv[j + remove];
@@ -1118,37 +1269,44 @@ void LyX::easyParse(int & argc, char * argv[])
 
 FuncStatus getStatus(FuncRequest const & action)
 {
 
 FuncStatus getStatus(FuncRequest const & action)
 {
-       LASSERT(singleton_, /**/);
-       return singleton_->pimpl_->lyxfunc_.getStatus(action);
+       LAPPERR(theApp());
+       return theApp()->getStatus(action);
 }
 
 
 void dispatch(FuncRequest const & action)
 {
 }
 
 
 void dispatch(FuncRequest const & action)
 {
-       LASSERT(singleton_, /**/);
-       singleton_->pimpl_->lyxfunc_.dispatch(action);
+       LAPPERR(theApp());
+       return theApp()->dispatch(action);
 }
 
 
 }
 
 
-BufferList & theBufferList()
+void dispatch(FuncRequest const & action, DispatchResult & dr)
 {
 {
-       LASSERT(singleton_, /**/);
-       return singleton_->pimpl_->buffer_list_;
+       LAPPERR(theApp());
+       return theApp()->dispatch(action, dr);
 }
 
 
 }
 
 
-LyXFunc & theLyXFunc()
+vector<string> & theFilesToLoad()
 {
 {
-       LASSERT(singleton_, /**/);
-       return singleton_->pimpl_->lyxfunc_;
+       LAPPERR(singleton_);
+       return singleton_->pimpl_->files_to_load_;
+}
+
+
+BufferList & theBufferList()
+{
+       LAPPERR(singleton_);
+       return singleton_->pimpl_->buffer_list_;
 }
 
 
 Server & theServer()
 {
        // FIXME: this should not be use_gui dependent
 }
 
 
 Server & theServer()
 {
        // FIXME: this should not be use_gui dependent
-       LASSERT(use_gui, /**/);
-       LASSERT(singleton_, /**/);
+       LWARNIF(use_gui);
+       LAPPERR(singleton_);
        return *singleton_->pimpl_->lyx_server_.get();
 }
 
        return *singleton_->pimpl_->lyx_server_.get();
 }
 
@@ -1156,93 +1314,162 @@ Server & theServer()
 ServerSocket & theServerSocket()
 {
        // FIXME: this should not be use_gui dependent
 ServerSocket & theServerSocket()
 {
        // FIXME: this should not be use_gui dependent
-       LASSERT(use_gui, /**/);
-       LASSERT(singleton_, /**/);
+       LWARNIF(use_gui);
+       LAPPERR(singleton_);
        return *singleton_->pimpl_->lyx_socket_.get();
 }
 
 
 KeyMap & theTopLevelKeymap()
 {
        return *singleton_->pimpl_->lyx_socket_.get();
 }
 
 
 KeyMap & theTopLevelKeymap()
 {
-       LASSERT(singleton_, /**/);
+       LAPPERR(singleton_);
        return singleton_->pimpl_->toplevel_keymap_;
 }
 
 
 Converters & theConverters()
 {
        return singleton_->pimpl_->toplevel_keymap_;
 }
 
 
 Converters & theConverters()
 {
-       LASSERT(singleton_, /**/);
+       LAPPERR(singleton_);
        return  singleton_->pimpl_->converters_;
 }
 
 
 Converters & theSystemConverters()
 {
        return  singleton_->pimpl_->converters_;
 }
 
 
 Converters & theSystemConverters()
 {
-       LASSERT(singleton_, /**/);
+       LAPPERR(singleton_);
        return  singleton_->pimpl_->system_converters_;
 }
 
 
 Movers & theMovers()
 {
        return  singleton_->pimpl_->system_converters_;
 }
 
 
 Movers & theMovers()
 {
-       LASSERT(singleton_, /**/);
+       LAPPERR(singleton_);
        return singleton_->pimpl_->movers_;
 }
 
 
 Mover const & getMover(string  const & fmt)
 {
        return singleton_->pimpl_->movers_;
 }
 
 
 Mover const & getMover(string  const & fmt)
 {
-       LASSERT(singleton_, /**/);
+       LAPPERR(singleton_);
        return singleton_->pimpl_->movers_(fmt);
 }
 
 
 void setMover(string const & fmt, string const & command)
 {
        return singleton_->pimpl_->movers_(fmt);
 }
 
 
 void setMover(string const & fmt, string const & command)
 {
-       LASSERT(singleton_, /**/);
+       LAPPERR(singleton_);
        singleton_->pimpl_->movers_.set(fmt, command);
 }
 
 
 Movers & theSystemMovers()
 {
        singleton_->pimpl_->movers_.set(fmt, command);
 }
 
 
 Movers & theSystemMovers()
 {
-       LASSERT(singleton_, /**/);
+       LAPPERR(singleton_);
        return singleton_->pimpl_->system_movers_;
 }
 
 
        return singleton_->pimpl_->system_movers_;
 }
 
 
-Messages & getMessages(string const & language)
+Messages const & getMessages(string const & language)
 {
 {
-       LASSERT(singleton_, /**/);
+       LAPPERR(singleton_);
        return singleton_->messages(language);
 }
 
 
        return singleton_->messages(language);
 }
 
 
-Messages & getGuiMessages()
+Messages const & getGuiMessages()
 {
 {
-       LASSERT(singleton_, /**/);
-       return singleton_->pimpl_->messages_["GUI"];
+       LAPPERR(singleton_);
+       // A cache to translate full language name to language code
+       static string last_language = "auto";
+       static string code;
+       if (lyxrc.gui_language != last_language) {
+               if (lyxrc.gui_language == "auto")
+                       code.clear();
+               else {
+                       Language const * l = languages.getLanguage(lyxrc.gui_language);
+                       code = l ? l->code() : string();
+               }
+               last_language = lyxrc.gui_language;
+       }
+       return singleton_->messages(code);
 }
 
 
 }
 
 
-graphics::Previews & thePreviews()
+Session & theSession()
 {
 {
-       LASSERT(singleton_, /**/);
-       return singleton_->pimpl_->preview_;
+       LAPPERR(singleton_);
+       return *singleton_->pimpl_->session_.get();
 }
 
 
 }
 
 
-Session & theSession()
+LaTeXFonts & theLaTeXFonts()
 {
 {
-       LASSERT(singleton_, /**/);
-       return *singleton_->pimpl_->session_.get();
+       LAPPERR(singleton_);
+       if (!singleton_->pimpl_->latexfonts_)
+               singleton_->pimpl_->latexfonts_ = new LaTeXFonts;
+       return *singleton_->pimpl_->latexfonts_;
 }
 
 
 CmdDef & theTopLevelCmdDef()
 {
 }
 
 
 CmdDef & theTopLevelCmdDef()
 {
-       LASSERT(singleton_, /**/);
+       LAPPERR(singleton_);
        return singleton_->pimpl_->toplevel_cmddef_;
 }
 
        return singleton_->pimpl_->toplevel_cmddef_;
 }
 
+
+SpellChecker * theSpellChecker()
+{
+       if (!singleton_->pimpl_->spell_checker_)
+               setSpellChecker();
+       return singleton_->pimpl_->spell_checker_;
+}
+
+
+void setSpellChecker()
+{
+       SpellChecker::ChangeNumber speller_change_number =singleton_->pimpl_->spell_checker_ ?
+               singleton_->pimpl_->spell_checker_->changeNumber() : 0;
+
+       if (lyxrc.spellchecker == "native") {
+#if defined(USE_MACOSX_PACKAGING)
+               if (!singleton_->pimpl_->apple_spell_checker_)
+                       singleton_->pimpl_->apple_spell_checker_ = new AppleSpellChecker;
+               singleton_->pimpl_->spell_checker_ = singleton_->pimpl_->apple_spell_checker_;
+#else
+               singleton_->pimpl_->spell_checker_ = 0;
+#endif
+       } else if (lyxrc.spellchecker == "aspell") {
+#if defined(USE_ASPELL)
+               if (!singleton_->pimpl_->aspell_checker_)
+                       singleton_->pimpl_->aspell_checker_ = new AspellChecker;
+               singleton_->pimpl_->spell_checker_ = singleton_->pimpl_->aspell_checker_;
+#else
+               singleton_->pimpl_->spell_checker_ = 0;
+#endif
+       } else if (lyxrc.spellchecker == "enchant") {
+#if defined(USE_ENCHANT)
+               if (!singleton_->pimpl_->enchant_checker_)
+                       singleton_->pimpl_->enchant_checker_ = new EnchantChecker;
+               singleton_->pimpl_->spell_checker_ = singleton_->pimpl_->enchant_checker_;
+#else
+               singleton_->pimpl_->spell_checker_ = 0;
+#endif
+       } else if (lyxrc.spellchecker == "hunspell") {
+#if defined(USE_HUNSPELL)
+               if (!singleton_->pimpl_->hunspell_checker_)
+                       singleton_->pimpl_->hunspell_checker_ = new HunspellChecker;
+               singleton_->pimpl_->spell_checker_ = singleton_->pimpl_->hunspell_checker_;
+#else
+               singleton_->pimpl_->spell_checker_ = 0;
+#endif
+       } else {
+               singleton_->pimpl_->spell_checker_ = 0;
+       }
+       if (singleton_->pimpl_->spell_checker_) {
+               singleton_->pimpl_->spell_checker_->changeNumber(speller_change_number);
+               singleton_->pimpl_->spell_checker_->advanceChangeNumber();
+       }
+}
+
 } // namespace lyx
 } // namespace lyx