X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FLyX.cpp;h=706950fe9fa317b09a0d8fbbe503e6c92ff84a0f;hb=449c766e03d94ddf6c823cfcae845f76f83c0e1c;hp=7e56d550eefbc42f1ae6e2ce825c149d075d9b55;hpb=79716cbcd0ce92126fb200785b54077d8e31fc18;p=lyx.git diff --git a/src/LyX.cpp b/src/LyX.cpp index 7e56d550ee..706950fe9f 100644 --- a/src/LyX.cpp +++ b/src/LyX.cpp @@ -34,6 +34,7 @@ #include "HunspellChecker.h" #include "KeyMap.h" #include "Language.h" +#include "LaTeXFonts.h" #include "LayoutFile.h" #include "Lexer.h" #include "LyX.h" @@ -59,7 +60,7 @@ #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/bind.h" @@ -76,6 +77,10 @@ using namespace std; using namespace lyx::support; +#if defined (USE_MACOSX_PACKAGING) +#include +#endif + namespace lyx { namespace Alert = frontend::Alert; @@ -137,18 +142,14 @@ void reconfigureUserLyXDir() } // namespace anon /// The main application class private implementation. -struct LyX::Impl -{ - Impl() : spell_checker_(0), apple_spell_checker_(0), aspell_checker_(0), enchant_checker_(0), hunspell_checker_(0) - { - // Set the default User Interface language as soon as possible. - // The language used will be derived from the environment - // variables. - messages_["GUI"] = Messages(); - } +struct LyX::Impl { + Impl() + : latexfonts_(0), spell_checker_(0), apple_spell_checker_(0), aspell_checker_(0), enchant_checker_(0), hunspell_checker_(0) + {} ~Impl() { + delete latexfonts_; delete apple_spell_checker_; delete aspell_checker_; delete enchant_checker_; @@ -192,6 +193,9 @@ struct LyX::Impl /// the parsed command line batch command if any vector batch_commands; + /// + LaTeXFonts * latexfonts_; + /// SpellChecker * spell_checker_; /// @@ -204,6 +208,7 @@ struct LyX::Impl SpellChecker * hunspell_checker_; }; + /// frontend::Application * theApp() { @@ -260,37 +265,18 @@ Messages & LyX::messages(string const & language) pair::iterator, bool> result = pimpl_->messages_.insert(make_pair(language, Messages(language))); - LASSERT(result.second, /**/); + LATTEST(result.second); return result.first->second; } -void setRcGuiLanguage() -{ - 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(); -} - - 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(); + setLocale(); } catch (ExceptionMessage const & message) { LYXERR(Debug::LOCALE, message.title_ + ", " + message.details_); } @@ -312,7 +298,7 @@ int LyX::exec(int & argc, char * argv[]) // Reinit the messages machinery in case package() knows // something interesting about the locale directory. - Messages::init(); + setLocale(); if (!use_gui) { // FIXME: create a ConsoleApplication @@ -340,7 +326,7 @@ int LyX::exec(int & argc, char * argv[]) vector::const_iterator bcit = pimpl_->batch_commands.begin(); vector::const_iterator bcend = pimpl_->batch_commands.end(); DispatchResult dr; - for (; bcit != bcend; bcit++) { + for (; bcit != bcend; ++bcit) { LYXERR(Debug::ACTION, "Buffer::dispatch: cmd: " << *bcit); buf->dispatch(*bcit, dr); final_success |= !dr.error(); @@ -355,7 +341,7 @@ int LyX::exec(int & argc, char * argv[]) // Reestablish our defaults, as Qt overwrites them // after createApplication() - locale_init(); + setLocale();//??? // Parse and remove all known arguments in the LyX singleton // Give an error for all remaining ones. @@ -375,7 +361,7 @@ int LyX::exec(int & argc, char * argv[]) // FIXME /* Create a CoreApplication class that will provide the main event loop - * and the socket callback registering. With Qt4, only QtCore + * and the socket callback registering. With Qt, 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. @@ -454,7 +440,7 @@ void LyX::prepareExit() 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(); @@ -486,6 +472,11 @@ int LyX::init(int & argc, char * argv[]) 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( i18nLibFileSearch("examples", "splash.lyx").absFileName()); @@ -497,7 +488,7 @@ int LyX::init(int & argc, char * argv[]) bool LyX::loadFiles() { - LASSERT(!use_gui, /**/); + LATTEST(!use_gui); bool success = true; vector::const_iterator it = pimpl_->files_to_load_.begin(); vector::const_iterator end = pimpl_->files_to_load_.end(); @@ -511,7 +502,7 @@ bool LyX::loadFiles() if (fname.empty()) continue; - Buffer * buf = pimpl_->buffer_list_.newBuffer(fname.absFileName(), false); + Buffer * buf = pimpl_->buffer_list_.newBuffer(fname.absFileName()); if (buf->loadLyXFile() == Buffer::ReadSuccess) { ErrorList const & el = buf->errorList("Parse"); if (!el.empty()) @@ -520,6 +511,10 @@ bool LyX::loadFiles() } 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; } } @@ -529,7 +524,7 @@ bool LyX::loadFiles() void execBatchCommands() { - LASSERT(singleton_, /**/); + LAPPERR(singleton_); singleton_->execCommands(); } @@ -587,7 +582,7 @@ void LyX::execCommands() vector::const_iterator bcit = pimpl_->batch_commands.begin(); vector::const_iterator bcend = pimpl_->batch_commands.end(); - for (; bcit != bcend; bcit++) { + for (; bcit != bcend; ++bcit) { LYXERR(Debug::INIT, "About to handle -x '" << *bcit << '\''); lyx::dispatch(lyxaction.lookupFunc(*bcit)); } @@ -676,7 +671,7 @@ static void error_handler(int err_sig) if (!msg.empty()) { lyxerr << "\nlyx: " << msg << endl; // try to make a GUI message - Alert::error(_("LyX crashed!"), msg); + Alert::error(_("LyX crashed!"), msg, true); } // Deinstall the signal handlers @@ -715,6 +710,55 @@ void LyX::printError(ErrorItem const & ei) cerr << to_utf8(tmp) << endl; } +#if defined (USE_MACOSX_PACKAGING) +namespace { + // Unexposed--extract an environment variable name from its NAME=VALUE + // representation + std::string varname(const char* line) + { + size_t nameLen = strcspn(line, "="); + if (nameLen == strlen(line)) { + return std::string(); + } else { + return std::string(line, nameLen); + } + } +} + +void cleanDuplicateEnvVars() +{ + std::set seen; + std::set dupes; + + // Create a list of the environment variables that appear more than once + for (char **read = *_NSGetEnviron(); *read; read++) { + std::string name = varname(*read); + if (name.size() == 0) { + continue; + } + if (seen.find(name) != seen.end()) { + dupes.insert(name); + } else { + seen.insert(name); + } + } + + // Loop over the list of duplicated variables + for (std::set::iterator dupe = dupes.begin(); dupe != dupes.end(); dupe++) { + const char *name = (*dupe).c_str(); + char *val = getenv(name); + if (val != NULL) { + LYXERR(Debug::INIT, "Duplicate environment variable: " << name); + // unsetenv removes *all* instances of the variable from the environment + unsetenv(name); + + // replace with the value from getenv (in practice appears to be the + // first value in the list) + setenv(name, val, 0); + } + } +} +#endif bool LyX::init() { @@ -727,6 +771,10 @@ bool LyX::init() signal(SIGTERM, error_handler); // SIGPIPE can be safely ignored. +#if defined (USE_MACOSX_PACKAGING) + cleanDuplicateEnvVars(); +#endif + lyxrc.tempdir_path = package().temp_dir().absFileName(); lyxrc.document_path = package().document_dir().absFileName(); @@ -745,6 +793,18 @@ bool LyX::init() if (!setEnv("LyXDir", lyx_dir)) LYXERR(Debug::INIT, "\t... failed!"); + if (package().explicit_user_support() && getEnv(LYX_USERDIR_VER).empty()) { + // -userdir was given on the command line. + // Make it available to child processes, otherwise tex2lyx + // would not find all layout files, and other converters might + // use it as well. + string const user_dir = package().user_support().absFileName(); + LYXERR(Debug::INIT, "Setting " LYX_USERDIR_VER "... to \"" + << user_dir << '"'); + if (!setEnv(LYX_USERDIR_VER, user_dir)) + LYXERR(Debug::INIT, "\t... failed!"); + } + // // Read configuration files // @@ -753,9 +813,6 @@ bool LyX::init() 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 @@ -767,8 +824,15 @@ bool LyX::init() prependEnvPath("PATH", replaceEnvironmentPath(lyxrc.path_prefix)); // Check that user LyX directory is ok. - if (queryUserLyXDir(package().explicit_user_support())) - reconfigureUserLyXDir(); + { + string const lock_file = package().user_support().absFileName() + ".lyx_configure_lock"; + int fd = fileLock(lock_file.c_str()); + + if (queryUserLyXDir(package().explicit_user_support())) { + reconfigureUserLyXDir(); + } + fileUnlock(fd, lock_file.c_str()); + } if (!use_gui) { // No need for a splash when there is no GUI @@ -796,9 +860,6 @@ 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_; @@ -809,14 +870,14 @@ bool LyX::init() if (!readRcFile("preferences", true)) return false; + // The language may have been set to someting useful through prefs + setLocale(); + if (!readEncodingsFile("encodings", "unicodesymbols")) return false; if (!readLanguagesFile("languages")) return false; - // Set the language defined by the user. - setRcGuiLanguage(); - LYXERR(Debug::INIT, "Reading layouts..."); // Load the layouts LayoutFileList::get().read(); @@ -841,6 +902,7 @@ bool LyX::init() lyxrc.print(); os::windows_style_tex_paths(lyxrc.windows_style_tex_paths); + // Prepend path prefix a second time to take the user preferences into a account if (!lyxrc.path_prefix.empty()) prependEnvPath("PATH", replaceEnvironmentPath(lyxrc.path_prefix)); @@ -898,7 +960,7 @@ void emergencyCleanup() 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) { @@ -1024,8 +1086,8 @@ typedef boost::function cmd_helpe 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; @@ -1038,7 +1100,7 @@ int parse_dbg(string const & arg, 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" @@ -1051,9 +1113,10 @@ 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" - " 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" @@ -1081,11 +1144,14 @@ int parse_help(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; - lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl; - - lyxerr << lyx_version_info << endl; + if (string(lyx_git_commit_hash) != "none") + cout << to_utf8(_(" Git commit hash ")) + << string(lyx_git_commit_hash).substr(0,8) << endl; + cout << to_utf8(bformat(_("Built on %1$s[[date]], %2$s[[time]]"), + from_ascii(lyx_build_date), from_ascii(lyx_build_time))) << endl; + cout << lyx_version_info << endl; exit(0); return 0; } @@ -1169,7 +1235,6 @@ int parse_import(string const & type, string const & file, string & batch) lyxerr << to_utf8(_("Missing filename for --import")) << endl; exit(1); } - batch = "buffer-import " + type + ' ' + file; return 2; } @@ -1286,35 +1351,35 @@ void LyX::easyParse(int & argc, char * argv[]) FuncStatus getStatus(FuncRequest const & action) { - LASSERT(theApp(), /**/); + LAPPERR(theApp()); return theApp()->getStatus(action); } void dispatch(FuncRequest const & action) { - LASSERT(theApp(), /**/); + LAPPERR(theApp()); return theApp()->dispatch(action); } void dispatch(FuncRequest const & action, DispatchResult & dr) { - LASSERT(theApp(), /**/); + LAPPERR(theApp()); return theApp()->dispatch(action, dr); } vector & theFilesToLoad() { - LASSERT(singleton_, /**/); + LAPPERR(singleton_); return singleton_->pimpl_->files_to_load_; } BufferList & theBufferList() { - LASSERT(singleton_, /**/); + LAPPERR(singleton_); return singleton_->pimpl_->buffer_list_; } @@ -1322,8 +1387,8 @@ BufferList & theBufferList() 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(); } @@ -1331,85 +1396,94 @@ Server & theServer() 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() { - LASSERT(singleton_, /**/); + LAPPERR(singleton_); return singleton_->pimpl_->toplevel_keymap_; } Converters & theConverters() { - LASSERT(singleton_, /**/); + LAPPERR(singleton_); return singleton_->pimpl_->converters_; } Converters & theSystemConverters() { - LASSERT(singleton_, /**/); + LAPPERR(singleton_); return singleton_->pimpl_->system_converters_; } Movers & theMovers() { - LASSERT(singleton_, /**/); + LAPPERR(singleton_); 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) { - LASSERT(singleton_, /**/); + LAPPERR(singleton_); singleton_->pimpl_->movers_.set(fmt, command); } Movers & theSystemMovers() { - LASSERT(singleton_, /**/); + LAPPERR(singleton_); return singleton_->pimpl_->system_movers_; } Messages const & getMessages(string const & language) { - LASSERT(singleton_, /**/); + LAPPERR(singleton_); return singleton_->messages(language); } Messages const & getGuiMessages() { - LASSERT(singleton_, /**/); - return singleton_->pimpl_->messages_["GUI"]; + LAPPERR(singleton_); + return singleton_->messages(Messages::guiLanguage()); } Session & theSession() { - LASSERT(singleton_, /**/); + LAPPERR(singleton_); return *singleton_->pimpl_->session_.get(); } +LaTeXFonts & theLaTeXFonts() +{ + LAPPERR(singleton_); + if (!singleton_->pimpl_->latexfonts_) + singleton_->pimpl_->latexfonts_ = new LaTeXFonts; + return *singleton_->pimpl_->latexfonts_; +} + + CmdDef & theTopLevelCmdDef() { - LASSERT(singleton_, /**/); + LAPPERR(singleton_); return singleton_->pimpl_->toplevel_cmddef_; } @@ -1430,7 +1504,7 @@ void setSpellChecker() if (lyxrc.spellchecker == "native") { #if defined(USE_MACOSX_PACKAGING) if (!singleton_->pimpl_->apple_spell_checker_) - singleton_->pimpl_->apple_spell_checker_ = new AppleSpellChecker(); + singleton_->pimpl_->apple_spell_checker_ = new AppleSpellChecker; singleton_->pimpl_->spell_checker_ = singleton_->pimpl_->apple_spell_checker_; #else singleton_->pimpl_->spell_checker_ = 0; @@ -1438,7 +1512,7 @@ void setSpellChecker() } else if (lyxrc.spellchecker == "aspell") { #if defined(USE_ASPELL) if (!singleton_->pimpl_->aspell_checker_) - singleton_->pimpl_->aspell_checker_ = new AspellChecker(); + singleton_->pimpl_->aspell_checker_ = new AspellChecker; singleton_->pimpl_->spell_checker_ = singleton_->pimpl_->aspell_checker_; #else singleton_->pimpl_->spell_checker_ = 0; @@ -1446,7 +1520,7 @@ void setSpellChecker() } else if (lyxrc.spellchecker == "enchant") { #if defined(USE_ENCHANT) if (!singleton_->pimpl_->enchant_checker_) - singleton_->pimpl_->enchant_checker_ = new EnchantChecker(); + singleton_->pimpl_->enchant_checker_ = new EnchantChecker; singleton_->pimpl_->spell_checker_ = singleton_->pimpl_->enchant_checker_; #else singleton_->pimpl_->spell_checker_ = 0; @@ -1454,7 +1528,7 @@ void setSpellChecker() } else if (lyxrc.spellchecker == "hunspell") { #if defined(USE_HUNSPELL) if (!singleton_->pimpl_->hunspell_checker_) - singleton_->pimpl_->hunspell_checker_ = new HunspellChecker(); + singleton_->pimpl_->hunspell_checker_ = new HunspellChecker; singleton_->pimpl_->spell_checker_ = singleton_->pimpl_->hunspell_checker_; #else singleton_->pimpl_->spell_checker_ = 0;