3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
12 * Full author contact details are available in file CREDITS.
20 #include "LayoutFile.h"
22 #include "BufferList.h"
25 #include "ConverterCache.h"
26 #include "Converter.h"
27 #include "CutAndPaste.h"
29 #include "ErrorList.h"
31 #include "FuncStatus.h"
35 #include "LyXAction.h"
38 #include "ModuleList.h"
41 #include "ServerSocket.h"
44 #include "frontends/alert.h"
45 #include "frontends/Application.h"
47 #include "support/lassert.h"
48 #include "support/debug.h"
49 #include "support/environment.h"
50 #include "support/ExceptionMessage.h"
51 #include "support/filetools.h"
52 #include "support/gettext.h"
53 #include "support/lstrings.h"
54 #include "support/Messages.h"
55 #include "support/os.h"
56 #include "support/Package.h"
57 #include "support/Path.h"
58 #include "support/Systemcall.h"
60 #include <boost/bind.hpp>
61 #include <boost/scoped_ptr.hpp>
72 using namespace lyx::support;
76 namespace Alert = frontend::Alert;
77 namespace os = support::os;
81 // Are we using the GUI at all? We default to true and this is changed
82 // to false when the export feature is used.
88 // Filled with the command line arguments "foo" of "-sysdir foo" or
90 string cl_system_support;
91 string cl_user_support;
97 void showFileError(string const & error)
99 Alert::warning(_("Could not read configuration file"),
100 bformat(_("Error while reading the configuration file\n%1$s.\n"
101 "Please check your installation."), from_utf8(error)));
105 void reconfigureUserLyXDir()
107 string const configure_command = package().configure_command();
109 lyxerr << to_utf8(_("LyX: reconfiguring user directory")) << endl;
110 PathChanger p(package().user_support());
112 one.startscript(Systemcall::Wait, configure_command);
113 lyxerr << "LyX: " << to_utf8(_("Done!")) << endl;
119 /// The main application class private implementation.
124 // Set the default User Interface language as soon as possible.
125 // The language used will be derived from the environment
127 messages_["GUI"] = Messages();
129 /// our function handler
132 BufferList buffer_list_;
134 KeyMap toplevel_keymap_;
136 CmdDef toplevel_cmddef_;
138 boost::scoped_ptr<Server> lyx_server_;
140 boost::scoped_ptr<ServerSocket> lyx_socket_;
142 boost::scoped_ptr<frontend::Application> application_;
143 /// lyx session, containing lastfiles, lastfilepos, and lastopened
144 boost::scoped_ptr<Session> session_;
146 /// Files to load at start.
147 vector<string> files_to_load_;
149 /// The messages translators.
150 map<string, Messages> messages_;
152 /// The file converters.
153 Converters converters_;
155 // The system converters copy after reading lyxrc.defaults.
156 Converters system_converters_;
161 Movers system_movers_;
163 /// has this user started lyx for the first time?
165 /// the parsed command line batch command if any
166 string batch_command;
170 frontend::Application * theApp()
173 return singleton_->pimpl_->application_.get();
185 void LyX::exit(int exit_code) const
188 // Something wrong happened so better save everything, just in
193 // Properly crash in debug mode in order to get a useful backtrace.
197 // In release mode, try to exit gracefully.
199 theApp()->exit(exit_code);
207 LASSERT(singleton_, /**/);
212 LyX const & LyX::cref()
214 LASSERT(singleton_, /**/);
227 BufferList & LyX::bufferList()
229 return pimpl_->buffer_list_;
233 BufferList const & LyX::bufferList() const
235 return pimpl_->buffer_list_;
239 Session & LyX::session()
241 LASSERT(pimpl_->session_.get(), /**/);
242 return *pimpl_->session_.get();
246 Session const & LyX::session() const
248 LASSERT(pimpl_->session_.get(), /**/);
249 return *pimpl_->session_.get();
253 LyXFunc & LyX::lyxFunc()
255 return pimpl_->lyxfunc_;
259 LyXFunc const & LyX::lyxFunc() const
261 return pimpl_->lyxfunc_;
265 Server & LyX::server()
267 LASSERT(pimpl_->lyx_server_.get(), /**/);
268 return *pimpl_->lyx_server_.get();
272 Server const & LyX::server() const
274 LASSERT(pimpl_->lyx_server_.get(), /**/);
275 return *pimpl_->lyx_server_.get();
279 ServerSocket & LyX::socket()
281 LASSERT(pimpl_->lyx_socket_.get(), /**/);
282 return *pimpl_->lyx_socket_.get();
286 ServerSocket const & LyX::socket() const
288 LASSERT(pimpl_->lyx_socket_.get(), /**/);
289 return *pimpl_->lyx_socket_.get();
293 frontend::Application & LyX::application()
295 LASSERT(pimpl_->application_.get(), /**/);
296 return *pimpl_->application_.get();
300 frontend::Application const & LyX::application() const
302 LASSERT(pimpl_->application_.get(), /**/);
303 return *pimpl_->application_.get();
307 CmdDef & LyX::topLevelCmdDef()
309 return pimpl_->toplevel_cmddef_;
313 Converters & LyX::converters()
315 return pimpl_->converters_;
319 Converters & LyX::systemConverters()
321 return pimpl_->system_converters_;
325 Messages & LyX::getMessages(string const & language)
327 map<string, Messages>::iterator it = pimpl_->messages_.find(language);
329 if (it != pimpl_->messages_.end())
332 pair<map<string, Messages>::iterator, bool> result =
333 pimpl_->messages_.insert(make_pair(language, Messages(language)));
335 LASSERT(result.second, /**/);
336 return result.first->second;
340 Messages & LyX::getGuiMessages()
342 return pimpl_->messages_["GUI"];
346 void LyX::setGuiLanguage(string const & language)
348 pimpl_->messages_["GUI"] = Messages(language);
352 int LyX::exec(int & argc, char * argv[])
354 // Here we need to parse the command line. At least
355 // we need to parse for "-dbg" and "-help"
356 easyParse(argc, argv);
359 init_package(to_utf8(from_local8bit(argv[0])),
360 cl_system_support, cl_user_support,
361 top_build_dir_is_one_level_up);
362 } catch (ExceptionMessage const & message) {
363 if (message.type_ == ErrorException) {
364 Alert::error(message.title_, message.details_);
366 } else if (message.type_ == WarningException) {
367 Alert::warning(message.title_, message.details_);
371 // Reinit the messages machinery in case package() knows
372 // something interesting about the locale directory.
376 // FIXME: create a ConsoleApplication
377 int exit_status = init(argc, argv);
383 // this is correct, since return values are inverted.
384 exit_status = !loadFiles();
386 if (pimpl_->batch_command.empty() || pimpl_->buffer_list_.empty()) {
391 BufferList::iterator begin = pimpl_->buffer_list_.begin();
393 bool final_success = false;
394 for (BufferList::iterator I = begin; I != pimpl_->buffer_list_.end(); ++I) {
396 if (buf != buf->masterBuffer())
398 bool success = false;
399 buf->dispatch(pimpl_->batch_command, &success);
400 final_success |= success;
403 return !final_success;
406 // Let the frontend parse and remove all arguments that it knows
407 pimpl_->application_.reset(createApplication(argc, argv));
409 // Parse and remove all known arguments in the LyX singleton
410 // Give an error for all remaining ones.
411 int exit_status = init(argc, argv);
413 // Kill the application object before exiting.
414 pimpl_->application_.reset();
421 /* Create a CoreApplication class that will provide the main event loop
422 * and the socket callback registering. With Qt4, only QtCore
423 * library would be needed.
424 * When this is done, a server_mode could be created and the following two
425 * line would be moved out from here.
427 // Note: socket callback must be registered after init(argc, argv)
428 // such that package().temp_dir() is properly initialized.
429 pimpl_->lyx_server_.reset(new Server(&pimpl_->lyxfunc_, lyxrc.lyxpipes));
430 pimpl_->lyx_socket_.reset(new ServerSocket(&pimpl_->lyxfunc_,
431 FileName(package().temp_dir().absFilename() + "/lyxsocket")));
433 // Start the real execution loop.
434 exit_status = pimpl_->application_->exec();
442 void LyX::prepareExit()
444 // Clear the clipboard and selection stack:
445 cap::clearCutStack();
446 cap::clearSelection();
448 // close buffers first
449 pimpl_->buffer_list_.closeAll();
451 // register session changes and shutdown server and socket
453 if (pimpl_->session_)
454 pimpl_->session_->writeFile();
455 pimpl_->session_.reset();
456 pimpl_->lyx_server_.reset();
457 pimpl_->lyx_socket_.reset();
460 // do any other cleanup procedures now
461 if (package().temp_dir() != package().system_temp_dir()) {
462 LYXERR(Debug::INFO, "Deleting tmp dir "
463 << package().temp_dir().absFilename());
465 if (!package().temp_dir().destroyDirectory()) {
466 docstring const msg =
467 bformat(_("Unable to remove the temporary directory %1$s"),
468 from_utf8(package().temp_dir().absFilename()));
469 Alert::warning(_("Unable to remove temporary directory"), msg);
473 // Kill the application object before exiting. This avoids crashes
474 // when exiting on Linux.
475 if (pimpl_->application_)
476 pimpl_->application_.reset();
480 void LyX::earlyExit(int status)
482 LASSERT(pimpl_->application_.get(), /**/);
483 // LyX::pimpl_::application_ is not initialised at this
484 // point so it's safe to just exit after some cleanup.
490 int LyX::init(int & argc, char * argv[])
492 // check for any spurious extra arguments
493 // other than documents
494 for (int argi = 1; argi < argc ; ++argi) {
495 if (argv[argi][0] == '-') {
497 bformat(_("Wrong command line option `%1$s'. Exiting."),
498 from_utf8(argv[argi]))) << endl;
503 // Initialization of LyX (reads lyxrc and more)
504 LYXERR(Debug::INIT, "Initializing LyX::init...");
505 bool success = init();
506 LYXERR(Debug::INIT, "Initializing LyX::init...done");
510 // Remaining arguments are assumed to be files to load.
511 for (int argi = argc - 1; argi >= 1; --argi)
512 pimpl_->files_to_load_.push_back(to_utf8(from_local8bit(argv[argi])));
515 pimpl_->files_to_load_.push_back(
516 i18nLibFileSearch("examples", "splash.lyx").absFilename());
523 void LyX::addFileToLoad(string const & fname)
525 vector<string>::const_iterator cit = find(
526 pimpl_->files_to_load_.begin(), pimpl_->files_to_load_.end(),
529 if (cit == pimpl_->files_to_load_.end())
530 pimpl_->files_to_load_.push_back(fname);
534 bool LyX::loadFiles()
536 LASSERT(!use_gui, /**/);
538 vector<string>::const_iterator it = pimpl_->files_to_load_.begin();
539 vector<string>::const_iterator end = pimpl_->files_to_load_.end();
541 for (; it != end; ++it) {
542 // get absolute path of file and add ".lyx" to
543 // the filename if necessary
544 FileName fname = fileSearch(string(), os::internal_path(*it), "lyx",
550 Buffer * buf = pimpl_->buffer_list_.newBuffer(fname.absFilename(), false);
551 if (buf->loadLyXFile(fname)) {
552 ErrorList const & el = buf->errorList("Parse");
554 for_each(el.begin(), el.end(),
555 boost::bind(&LyX::printError, this, _1));
558 pimpl_->buffer_list_.release(buf);
566 void LyX::execBatchCommands()
568 // The advantage of doing this here is that the event loop
569 // is already started. So any need for interaction will be
572 // if reconfiguration is needed.
573 while (LayoutFileList::get().empty()) {
574 switch (Alert::prompt(
575 _("No textclass is found"),
576 _("LyX cannot continue because no textclass is found. "
577 "You can either reconfigure normally, or reconfigure using "
578 "default textclasses, or quit LyX."),
585 // regular reconfigure
586 pimpl_->lyxfunc_.dispatch(FuncRequest(LFUN_RECONFIGURE, ""));
589 // reconfigure --without-latex-config
590 pimpl_->lyxfunc_.dispatch(FuncRequest(LFUN_RECONFIGURE,
591 " --without-latex-config"));
594 pimpl_->lyxfunc_.dispatch(FuncRequest(LFUN_LYX_QUIT));
599 // create the first main window
600 pimpl_->lyxfunc_.dispatch(FuncRequest(LFUN_WINDOW_NEW, geometryArg));
602 if (!pimpl_->files_to_load_.empty()) {
603 // if some files were specified at command-line we assume that the
604 // user wants to edit *these* files and not to restore the session.
605 for (size_t i = 0; i != pimpl_->files_to_load_.size(); ++i) {
606 pimpl_->lyxfunc_.dispatch(
607 FuncRequest(LFUN_FILE_OPEN, pimpl_->files_to_load_[i]));
609 // clear this list to save a few bytes of RAM
610 pimpl_->files_to_load_.clear();
613 pimpl_->application_->restoreGuiSession();
615 // Execute batch commands if available
616 if (pimpl_->batch_command.empty())
619 LYXERR(Debug::INIT, "About to handle -x '" << pimpl_->batch_command << '\'');
621 pimpl_->lyxfunc_.dispatch(lyxaction.lookupFunc(pimpl_->batch_command));
628 The SIGHUP signal does not exist on Windows and does not need to be handled.
630 Windows handles SIGFPE and SIGSEGV signals as expected.
632 Cntl+C interrupts (mapped to SIGINT by Windows' POSIX compatability layer)
633 cause a new thread to be spawned. This may well result in unexpected
634 behaviour by the single-threaded LyX.
636 SIGTERM signals will come only from another process actually sending
637 that signal using 'raise' in Windows' POSIX compatability layer. It will
638 not come from the general "terminate process" methods that everyone
639 actually uses (and which can't be trapped). Killing an app 'politely' on
640 Windows involves first sending a WM_CLOSE message, something that is
641 caught already by the Qt frontend.
643 For more information see:
645 http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/2034055
646 ...signals are mostly useless on Windows for a variety of reasons that are
649 'UNIX Application Migration Guide, Chapter 9'
650 http://msdn.microsoft.com/library/en-us/dnucmg/html/UCMGch09.asp
652 'How To Terminate an Application "Cleanly" in Win32'
653 http://support.microsoft.com/default.aspx?scid=kb;en-us;178893
657 static void error_handler(int err_sig)
659 // Throw away any signals other than the first one received.
660 static sig_atomic_t handling_error = false;
663 handling_error = true;
665 // We have received a signal indicating a fatal error, so
666 // try and save the data ASAP.
667 LyX::cref().emergencyCleanup();
669 // These lyxerr calls may or may not work:
671 // Signals are asynchronous, so the main program may be in a very
672 // fragile state when a signal is processed and thus while a signal
673 // handler function executes.
674 // In general, therefore, we should avoid performing any
675 // I/O operations or calling most library and system functions from
678 // This shouldn't matter here, however, as we've already invoked
683 lyxerr << "\nlyx: SIGHUP signal caught\nBye." << endl;
687 lyxerr << "\nlyx: SIGFPE signal caught\nBye." << endl;
690 lyxerr << "\nlyx: SIGSEGV signal caught\n"
691 "Sorry, you have found a bug in LyX. "
692 "Please read the bug-reporting instructions "
693 "in Help->Introduction and send us a bug report, "
694 "if necessary. Thanks !\nBye." << endl;
702 // Deinstall the signal handlers
704 signal(SIGHUP, SIG_DFL);
706 signal(SIGINT, SIG_DFL);
707 signal(SIGFPE, SIG_DFL);
708 signal(SIGSEGV, SIG_DFL);
709 signal(SIGTERM, SIG_DFL);
712 if (err_sig == SIGSEGV ||
713 (err_sig != SIGHUP && !getEnv("LYXDEBUG").empty()))
715 if (err_sig == SIGSEGV || !getEnv("LYXDEBUG").empty())
724 void LyX::printError(ErrorItem const & ei)
726 docstring tmp = _("LyX: ") + ei.error + char_type(':')
728 cerr << to_utf8(tmp) << endl;
735 signal(SIGHUP, error_handler);
737 signal(SIGFPE, error_handler);
738 signal(SIGSEGV, error_handler);
739 signal(SIGINT, error_handler);
740 signal(SIGTERM, error_handler);
741 // SIGPIPE can be safely ignored.
743 lyxrc.tempdir_path = package().temp_dir().absFilename();
744 lyxrc.document_path = package().document_dir().absFilename();
746 if (lyxrc.example_path.empty()) {
747 lyxrc.example_path = addPath(package().system_support().absFilename(),
750 if (lyxrc.template_path.empty()) {
751 lyxrc.template_path = addPath(package().system_support().absFilename(),
756 // Read configuration files
759 // This one may have been distributed along with LyX.
760 if (!readRcFile("lyxrc.dist"))
763 // Set the language defined by the distributor.
764 //setGuiLanguage(lyxrc.gui_language);
766 // Set the PATH correctly.
767 #if !defined (USE_POSIX_PACKAGING)
768 // Add the directory containing the LyX executable to the path
769 // so that LyX can find things like tex2lyx.
770 if (package().build_support().empty())
771 prependEnvPath("PATH", package().binary_dir().absFilename());
773 if (!lyxrc.path_prefix.empty())
774 prependEnvPath("PATH", lyxrc.path_prefix);
776 // Check that user LyX directory is ok.
777 if (queryUserLyXDir(package().explicit_user_support()))
778 reconfigureUserLyXDir();
780 // no need for a splash when there is no GUI
785 // This one is generated in user_support directory by lib/configure.py.
786 if (!readRcFile("lyxrc.defaults"))
789 // Query the OS to know what formats are viewed natively
790 formats.setAutoOpen();
792 // Read lyxrc.dist again to be able to override viewer auto-detection.
793 readRcFile("lyxrc.dist");
795 system_lyxrc = lyxrc;
796 system_formats = formats;
797 pimpl_->system_converters_ = pimpl_->converters_;
798 pimpl_->system_movers_ = pimpl_->movers_;
799 system_lcolor = lcolor;
801 // This one is edited through the preferences dialog.
802 if (!readRcFile("preferences"))
805 if (!readEncodingsFile("encodings", "unicodesymbols"))
807 if (!readLanguagesFile("languages"))
811 LYXERR(Debug::INIT, "Reading layouts...");
817 // read keymap and ui files in batch mode as well
818 // because InsetInfo needs to know these to produce
819 // the correct output
821 // Set the language defined by the user.
822 //setGuiLanguage(lyxrc.gui_language);
824 // Set up command definitions
825 pimpl_->toplevel_cmddef_.read(lyxrc.def_file);
828 pimpl_->toplevel_keymap_.read("site");
829 pimpl_->toplevel_keymap_.read(lyxrc.bind_file);
830 // load user bind file user.bind
831 pimpl_->toplevel_keymap_.read("user");
833 pimpl_->lyxfunc_.initKeySequences(&pimpl_->toplevel_keymap_);
835 if (lyxerr.debugging(Debug::LYXRC))
838 os::windows_style_tex_paths(lyxrc.windows_style_tex_paths);
839 if (!lyxrc.path_prefix.empty())
840 prependEnvPath("PATH", lyxrc.path_prefix);
842 FileName const document_path(lyxrc.document_path);
843 if (document_path.exists() && document_path.isDirectory())
844 package().document_dir() = document_path;
846 package().temp_dir() = createLyXTmpDir(FileName(lyxrc.tempdir_path));
847 if (package().temp_dir().empty()) {
848 Alert::error(_("Could not create temporary directory"),
849 bformat(_("Could not create a temporary directory in\n"
850 "%1$s. Make sure that this\n"
851 "path exists and is writable and try again."),
852 from_utf8(lyxrc.tempdir_path)));
853 // createLyXTmpDir() tries sufficiently hard to create a
854 // usable temp dir, so the probability to come here is
855 // close to zero. We therefore don't try to overcome this
856 // problem with e.g. asking the user for a new path and
857 // trying again but simply exit.
861 LYXERR(Debug::INIT, "LyX tmp dir: `"
862 << package().temp_dir().absFilename() << '\'');
864 LYXERR(Debug::INIT, "Reading session information '.lyx/session'...");
865 pimpl_->session_.reset(new Session(lyxrc.num_lastfiles));
867 // This must happen after package initialization and after lyxrc is
868 // read, therefore it can't be done by a static object.
869 ConverterCache::init();
875 void LyX::emergencyCleanup() const
877 // what to do about tmpfiles is non-obvious. we would
878 // like to delete any we find, but our lyxdir might
879 // contain documents etc. which might be helpful on
882 pimpl_->buffer_list_.emergencyWriteAll();
884 if (pimpl_->lyx_server_)
885 pimpl_->lyx_server_->emergencyCleanup();
886 pimpl_->lyx_server_.reset();
887 pimpl_->lyx_socket_.reset();
892 // return true if file does not exist or is older than configure.py.
893 static bool needsUpdate(string const & file)
895 // We cannot initialize configure_script directly because the package
896 // is not initialized yet when static objects are constructed.
897 static FileName configure_script;
898 static bool firstrun = true;
901 FileName(addName(package().system_support().absFilename(),
907 FileName(addName(package().user_support().absFilename(), file));
908 return !absfile.exists()
909 || configure_script.lastModified() > absfile.lastModified();
913 bool LyX::queryUserLyXDir(bool explicit_userdir)
915 // Does user directory exist?
916 FileName const sup = package().user_support();
917 if (sup.exists() && sup.isDirectory()) {
920 return needsUpdate("lyxrc.defaults")
921 || needsUpdate("lyxmodules.lst")
922 || needsUpdate("textclass.lst")
923 || needsUpdate("packages.lst");
926 first_start = !explicit_userdir;
928 // If the user specified explicitly a directory, ask whether
929 // to create it. If the user says "no", then exit.
930 if (explicit_userdir &&
932 _("Missing user LyX directory"),
933 bformat(_("You have specified a non-existent user "
934 "LyX directory, %1$s.\n"
935 "It is needed to keep your own configuration."),
936 from_utf8(package().user_support().absFilename())),
938 _("&Create directory"),
940 lyxerr << to_utf8(_("No user LyX directory. Exiting.")) << endl;
941 earlyExit(EXIT_FAILURE);
944 lyxerr << to_utf8(bformat(_("LyX: Creating directory %1$s"),
945 from_utf8(sup.absFilename()))) << endl;
947 if (!sup.createDirectory(0755)) {
948 // Failed, so let's exit.
949 lyxerr << to_utf8(_("Failed to create directory. Exiting."))
951 earlyExit(EXIT_FAILURE);
958 bool LyX::readRcFile(string const & name)
960 LYXERR(Debug::INIT, "About to read " << name << "... ");
962 FileName const lyxrc_path = libFileSearch(string(), name);
963 if (!lyxrc_path.empty()) {
964 LYXERR(Debug::INIT, "Found in " << lyxrc_path);
965 if (lyxrc.read(lyxrc_path) < 0) {
970 LYXERR(Debug::INIT, "Not found." << lyxrc_path);
975 // Read the languages file `name'
976 bool LyX::readLanguagesFile(string const & name)
978 LYXERR(Debug::INIT, "About to read " << name << "...");
980 FileName const lang_path = libFileSearch(string(), name);
981 if (lang_path.empty()) {
985 languages.read(lang_path);
990 // Read the encodings file `name'
991 bool LyX::readEncodingsFile(string const & enc_name,
992 string const & symbols_name)
994 LYXERR(Debug::INIT, "About to read " << enc_name << " and "
995 << symbols_name << "...");
997 FileName const symbols_path = libFileSearch(string(), symbols_name);
998 if (symbols_path.empty()) {
999 showFileError(symbols_name);
1003 FileName const enc_path = libFileSearch(string(), enc_name);
1004 if (enc_path.empty()) {
1005 showFileError(enc_name);
1008 encodings.read(enc_path, symbols_path);
1017 /// return the the number of arguments consumed
1018 typedef boost::function<int(string const &, string const &)> cmd_helper;
1020 int parse_dbg(string const & arg, string const &)
1023 lyxerr << to_utf8(_("List of supported debug flags:")) << endl;
1024 Debug::showTags(lyxerr);
1027 lyxerr << to_utf8(bformat(_("Setting debug level to %1$s"), from_utf8(arg))) << endl;
1029 lyxerr.level(Debug::value(arg));
1030 Debug::showLevel(lyxerr, lyxerr.level());
1035 int parse_help(string const &, string const &)
1038 to_utf8(_("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
1039 "Command line switches (case sensitive):\n"
1040 "\t-help summarize LyX usage\n"
1041 "\t-userdir dir set user directory to dir\n"
1042 "\t-sysdir dir set system directory to dir\n"
1043 "\t-geometry WxH+X+Y set geometry of the main window\n"
1044 "\t-dbg feature[,feature]...\n"
1045 " select the features to debug.\n"
1046 " Type `lyx -dbg' to see the list of features\n"
1047 "\t-x [--execute] command\n"
1048 " where command is a lyx command.\n"
1049 "\t-e [--export] fmt\n"
1050 " where fmt is the export format of choice.\n"
1051 " Look on Tools->Preferences->File formats->Format\n"
1052 " to get an idea which parameters should be passed.\n"
1053 "\t-i [--import] fmt file.xxx\n"
1054 " where fmt is the import format of choice\n"
1055 " and file.xxx is the file to be imported.\n"
1056 "\t-version summarize version and build info\n"
1057 "Check the LyX man page for more details.")) << endl;
1063 int parse_version(string const &, string const &)
1065 lyxerr << "LyX " << lyx_version
1066 << " (" << lyx_release_date << ")" << endl;
1067 lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
1069 lyxerr << lyx_version_info << endl;
1075 int parse_sysdir(string const & arg, string const &)
1078 Alert::error(_("No system directory"),
1079 _("Missing directory for -sysdir switch"));
1082 cl_system_support = arg;
1087 int parse_userdir(string const & arg, string const &)
1090 Alert::error(_("No user directory"),
1091 _("Missing directory for -userdir switch"));
1094 cl_user_support = arg;
1099 int parse_execute(string const & arg, string const &)
1102 Alert::error(_("Incomplete command"),
1103 _("Missing command string after --execute switch"));
1111 int parse_export(string const & type, string const &)
1114 lyxerr << to_utf8(_("Missing file type [eg latex, ps...] after "
1115 "--export switch")) << endl;
1118 batch = "buffer-export " + type;
1124 int parse_import(string const & type, string const & file)
1127 lyxerr << to_utf8(_("Missing file type [eg latex, ps...] after "
1128 "--import switch")) << endl;
1132 lyxerr << to_utf8(_("Missing filename for --import")) << endl;
1136 batch = "buffer-import " + type + ' ' + file;
1141 int parse_geometry(string const & arg1, string const &)
1144 #if defined(_WIN32) || (defined(__CYGWIN__) && defined(X_DISPLAY_MISSING))
1145 // remove also the arg
1148 // don't remove "-geometry"
1157 void LyX::easyParse(int & argc, char * argv[])
1159 map<string, cmd_helper> cmdmap;
1161 cmdmap["-dbg"] = parse_dbg;
1162 cmdmap["-help"] = parse_help;
1163 cmdmap["--help"] = parse_help;
1164 cmdmap["-version"] = parse_version;
1165 cmdmap["--version"] = parse_version;
1166 cmdmap["-sysdir"] = parse_sysdir;
1167 cmdmap["-userdir"] = parse_userdir;
1168 cmdmap["-x"] = parse_execute;
1169 cmdmap["--execute"] = parse_execute;
1170 cmdmap["-e"] = parse_export;
1171 cmdmap["--export"] = parse_export;
1172 cmdmap["-i"] = parse_import;
1173 cmdmap["--import"] = parse_import;
1174 cmdmap["-geometry"] = parse_geometry;
1176 for (int i = 1; i < argc; ++i) {
1177 map<string, cmd_helper>::const_iterator it
1178 = cmdmap.find(argv[i]);
1180 // don't complain if not found - may be parsed later
1181 if (it == cmdmap.end())
1185 (i + 1 < argc) ? to_utf8(from_local8bit(argv[i + 1])) : string();
1187 (i + 2 < argc) ? to_utf8(from_local8bit(argv[i + 2])) : string();
1189 int const remove = 1 + it->second(arg, arg2);
1191 // Now, remove used arguments by shifting
1192 // the following ones remove places down.
1195 for (int j = i; j < argc; ++j)
1196 argv[j] = argv[j + remove];
1201 pimpl_->batch_command = batch;
1205 FuncStatus getStatus(FuncRequest const & action)
1207 return LyX::ref().lyxFunc().getStatus(action);
1211 void dispatch(FuncRequest const & action)
1213 LyX::ref().lyxFunc().dispatch(action);
1217 BufferList & theBufferList()
1219 return LyX::ref().bufferList();
1223 LyXFunc & theLyXFunc()
1225 return LyX::ref().lyxFunc();
1229 Server & theServer()
1231 // FIXME: this should not be use_gui dependent
1232 LASSERT(use_gui, /**/);
1233 return LyX::ref().server();
1237 ServerSocket & theServerSocket()
1239 // FIXME: this should not be use_gui dependent
1240 LASSERT(use_gui, /**/);
1241 return LyX::ref().socket();
1245 KeyMap & theTopLevelKeymap()
1247 return LyX::ref().pimpl_->toplevel_keymap_;
1251 Converters & theConverters()
1253 return LyX::ref().converters();
1257 Converters & theSystemConverters()
1259 return LyX::ref().systemConverters();
1263 Movers & theMovers()
1265 return LyX::ref().pimpl_->movers_;
1269 Mover const & getMover(string const & fmt)
1271 return LyX::ref().pimpl_->movers_(fmt);
1275 void setMover(string const & fmt, string const & command)
1277 LyX::ref().pimpl_->movers_.set(fmt, command);
1281 Movers & theSystemMovers()
1283 return LyX::ref().pimpl_->system_movers_;
1287 Messages & getMessages(string const & language)
1289 return LyX::ref().getMessages(language);
1293 Messages & getGuiMessages()
1295 return LyX::ref().getGuiMessages();