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.
21 #include "buffer_funcs.h"
22 #include "bufferlist.h"
23 #include "converter.h"
26 #include "errorlist.h"
37 #include "lyxtextclasslist.h"
38 #include "lyxserver.h"
39 #include "MenuBackend.h"
41 #include "ToolbarBackend.h"
43 #include "mathed/math_inset.h"
45 #include "frontends/Alert.h"
46 #include "frontends/lyx_gui.h"
47 #include "frontends/LyXView.h"
49 #include "support/environment.h"
50 #include "support/filetools.h"
51 #include "support/lyxlib.h"
52 #include "support/os.h"
53 #include "support/package.h"
54 #include "support/path.h"
56 #include <boost/bind.hpp>
57 #include <boost/filesystem/operations.hpp>
62 using lyx::support::addName;
63 using lyx::support::addPath;
64 using lyx::support::bformat;
65 using lyx::support::createDirectory;
66 using lyx::support::createLyXTmpDir;
67 using lyx::support::fileSearch;
68 using lyx::support::getEnv;
69 using lyx::support::i18nLibFileSearch;
70 using lyx::support::libFileSearch;
71 using lyx::support::package;
72 using lyx::support::Path;
73 using lyx::support::prependEnvPath;
74 using lyx::support::quoteName;
75 using lyx::support::rtrim;
77 namespace os = lyx::support::os;
78 namespace fs = boost::filesystem;
84 #ifndef CXX_GLOBAL_CSTD
91 extern LyXServer * lyxserver;
93 // This is the global bufferlist object
94 BufferList bufferlist;
96 // convenient to have it here.
97 boost::scoped_ptr<kb_keymap> toplevel_keymap;
101 // Filled with the command line arguments "foo" of "-sysdir foo" or
103 string cl_system_support;
104 string cl_user_support;
107 void showFileError(string const & error)
109 Alert::warning(_("Could not read configuration file"),
110 bformat(_("Error while reading the configuration file\n%1$s.\n"
111 "Please check your installation."), error));
116 void reconfigureUserLyXDir()
118 string const configure_command = package().configure_command();
120 lyxerr << _("LyX: reconfiguring user directory") << endl;
121 Path p(package().user_support());
122 ::system(configure_command.c_str());
123 lyxerr << "LyX: " << _("Done!") << endl;
129 boost::scoped_ptr<LyX> LyX::singleton_;
131 void LyX::exec(int & argc, char * argv[])
133 BOOST_ASSERT(!singleton_.get());
134 // We must return from this before launching the gui so that
135 // other parts of the code can access singleton_ through
136 // LyX::ref and LyX::cref.
137 singleton_.reset(new LyX);
138 // Start the real execution loop.
139 singleton_->priv_exec(argc, argv);
145 BOOST_ASSERT(singleton_.get());
146 return *singleton_.get();
150 LyX const & LyX::cref()
152 BOOST_ASSERT(singleton_.get());
153 return *singleton_.get();
162 lyx::Session & LyX::session()
164 BOOST_ASSERT(session_.get());
165 return *session_.get();
169 lyx::Session const & LyX::session() const
171 BOOST_ASSERT(session_.get());
172 return *session_.get();
176 void LyX::addLyXView(boost::shared_ptr<LyXView> const & lyxview)
178 views_.push_back(lyxview);
182 Buffer const * const LyX::updateInset(InsetBase const * inset) const
187 Buffer const * buffer_ptr = 0;
188 ViewList::const_iterator it = views_.begin();
189 ViewList::const_iterator const end = views_.end();
190 for (; it != end; ++it) {
191 Buffer const * ptr = (*it)->updateInset(inset);
199 void LyX::priv_exec(int & argc, char * argv[])
201 // Here we need to parse the command line. At least
202 // we need to parse for "-dbg" and "-help"
203 bool const want_gui = easyParse(argc, argv);
205 lyx::support::init_package(argv[0], cl_system_support, cl_user_support,
206 lyx::support::top_build_dir_is_one_level_up);
209 lyx_gui::parse_init(argc, argv);
211 // check for any spurious extra arguments
212 // other than documents
213 for (int argi = 1; argi < argc ; ++argi) {
214 if (argv[argi][0] == '-') {
215 lyxerr << bformat(_("Wrong command line option `%1$s'. Exiting."),
221 // Initialization of LyX (reads lyxrc and more)
222 lyxerr[Debug::INIT] << "Initializing LyX::init..." << endl;
224 lyxerr[Debug::INIT] << "Initializing LyX::init...done" << endl;
227 lyx_gui::parse_lyxrc();
229 vector<string> files;
231 for (int argi = argc - 1; argi >= 1; --argi)
232 files.push_back(os::internal_path(argv[argi]));
235 files.push_back(i18nLibFileSearch("examples", "splash.lyx"));
237 // if a file is specified, I assume that user wants to edit *that* file
238 if (files.empty() && lyxrc.load_session) {
239 vector<string> const & lastopened = session_->lastOpenedFiles();
240 files.insert(files.end(), lastopened.begin(), lastopened.end() );
242 // clear this list to save a few bytes of RAM
243 session_->clearLastOpenedFiles();
245 // Execute batch commands if available
246 if (!batch_command.empty()) {
248 lyxerr[Debug::INIT] << "About to handle -x '"
249 << batch_command << '\'' << endl;
251 Buffer * last_loaded = 0;
253 vector<string>::const_iterator it = files.begin();
254 vector<string>::const_iterator end = files.end();
256 for (; it != end; ++it) {
257 // get absolute path of file and add ".lyx" to
258 // the filename if necessary
259 string s = fileSearch(string(), *it, "lyx");
261 last_loaded = newFile(*it, string(), true);
263 Buffer * buf = bufferlist.newBuffer(s, false);
264 buf->error.connect(boost::bind(&LyX::printError, this, _1));
265 if (loadLyXFile(buf, s))
268 bufferlist.release(buf);
272 // try to dispatch to last loaded buffer first
274 bool success = false;
275 if (last_loaded->dispatch(batch_command, &success)) {
280 files.clear(); // the files are already loaded
284 lyx_gui::start(batch_command, files);
286 // Something went wrong above
296 The SIGHUP signal does not exist on Windows and does not need to be handled.
298 Windows handles SIGFPE and SIGSEGV signals as expected.
300 Cntl+C interrupts (mapped to SIGINT by Windows' POSIX compatability layer)
301 cause a new thread to be spawned. This may well result in unexpected
302 behaviour by the single-threaded LyX.
304 SIGTERM signals will come only from another process actually sending
305 that signal using 'raise' in Windows' POSIX compatability layer. It will
306 not come from the general "terminate process" methods that everyone
307 actually uses (and which can't be trapped). Killing an app 'politely' on
308 Windows involves first sending a WM_CLOSE message, something that is
309 caught already by the Qt frontend.
311 For more information see:
313 http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/2034055
314 ...signals are mostly useless on Windows for a variety of reasons that are
317 'UNIX Application Migration Guide, Chapter 9'
318 http://msdn.microsoft.com/library/en-us/dnucmg/html/UCMGch09.asp
320 'How To Terminate an Application "Cleanly" in Win32'
321 http://support.microsoft.com/default.aspx?scid=kb;en-us;178893
325 static void error_handler(int err_sig)
327 // Throw away any signals other than the first one received.
328 static sig_atomic_t handling_error = false;
331 handling_error = true;
333 // We have received a signal indicating a fatal error, so
334 // try and save the data ASAP.
335 LyX::cref().emergencyCleanup();
337 // These lyxerr calls may or may not work:
339 // Signals are asynchronous, so the main program may be in a very
340 // fragile state when a signal is processed and thus while a signal
341 // handler function executes.
342 // In general, therefore, we should avoid performing any
343 // I/O operations or calling most library and system functions from
346 // This shouldn't matter here, however, as we've already invoked
351 lyxerr << "\nlyx: SIGHUP signal caught\nBye." << endl;
355 lyxerr << "\nlyx: SIGFPE signal caught\nBye." << endl;
358 lyxerr << "\nlyx: SIGSEGV signal caught\n"
359 "Sorry, you have found a bug in LyX. "
360 "Please read the bug-reporting instructions "
361 "in Help->Introduction and send us a bug report, "
362 "if necessary. Thanks !\nBye." << endl;
370 // Deinstall the signal handlers
372 signal(SIGHUP, SIG_DFL);
374 signal(SIGINT, SIG_DFL);
375 signal(SIGFPE, SIG_DFL);
376 signal(SIGSEGV, SIG_DFL);
377 signal(SIGTERM, SIG_DFL);
380 if (err_sig == SIGSEGV ||
381 (err_sig != SIGHUP && !getEnv("LYXDEBUG").empty()))
383 if (err_sig == SIGSEGV || !getEnv("LYXDEBUG").empty())
385 lyx::support::abort();
392 void LyX::printError(ErrorItem const & ei)
394 std::cerr << _("LyX: ") << ei.error
395 << ':' << ei.description << std::endl;
400 void LyX::init(bool gui)
403 signal(SIGHUP, error_handler);
405 signal(SIGFPE, error_handler);
406 signal(SIGSEGV, error_handler);
407 signal(SIGINT, error_handler);
408 signal(SIGTERM, error_handler);
409 // SIGPIPE can be safely ignored.
411 // Check that user LyX directory is ok. We don't do that if
412 // running in batch mode.
413 bool reconfigure = false;
416 queryUserLyXDir(package().explicit_user_support());
421 // Disable gui when easyparse says so
422 lyx_gui::use_gui = gui;
424 lyxrc.tempdir_path = package().temp_dir();
425 lyxrc.document_path = package().document_dir();
427 if (lyxrc.template_path.empty()) {
428 lyxrc.template_path = addPath(package().system_support(),
432 if (lyxrc.roman_font_name.empty())
433 lyxrc.roman_font_name = lyx_gui::roman_font_name();
434 if (lyxrc.sans_font_name.empty())
435 lyxrc.sans_font_name = lyx_gui::sans_font_name();
436 if (lyxrc.typewriter_font_name.empty())
437 lyxrc.typewriter_font_name = lyx_gui::typewriter_font_name();
440 // Read configuration files
443 // This one may have been distributed along with LyX.
444 readRcFile("lyxrc.dist");
445 // This one is generated in user_support directory by lib/configure.py.
446 readRcFile("lyxrc.defaults");
448 system_lyxrc = lyxrc;
449 system_formats = formats;
450 system_converters = converters;
451 system_movers = movers;
452 system_lcolor = lcolor;
454 // This one is edited through the preferences dialog.
455 readRcFile("preferences");
457 readEncodingsFile("encodings");
458 readLanguagesFile("languages");
461 lyxerr[Debug::INIT] << "Reading layouts..." << endl;
466 toplevel_keymap.reset(new kb_keymap);
467 defaultKeyBindings(toplevel_keymap.get());
468 toplevel_keymap->read(lyxrc.bind_file);
471 readUIFile(lyxrc.ui_file);
474 if (lyxerr.debugging(Debug::LYXRC))
477 os::cygwin_path_fix(lyxrc.cygwin_path_fix);
478 if (!lyxrc.path_prefix.empty())
479 prependEnvPath("PATH", lyxrc.path_prefix);
481 #if !defined (USE_POSIX_PACKAGING)
482 // Add the directory containing the LyX executable to the path
483 // so that LyX can find things like tex2lyx.
484 if (package().build_support().empty())
485 prependEnvPath("PATH", package().binary_dir());
488 // Having reset the PATH we're now in a position to run configure
491 reconfigureUserLyXDir();
493 if (fs::exists(lyxrc.document_path) &&
494 fs::is_directory(lyxrc.document_path))
495 package().document_dir() = lyxrc.document_path;
497 package().temp_dir() = createLyXTmpDir(lyxrc.tempdir_path);
498 if (package().temp_dir().empty()) {
499 Alert::error(_("Could not create temporary directory"),
500 bformat(_("Could not create a temporary directory in\n"
501 "%1$s. Make sure that this\n"
502 "path exists and is writable and try again."),
503 lyxrc.tempdir_path));
504 // createLyXTmpDir() tries sufficiently hard to create a
505 // usable temp dir, so the probability to come here is
506 // close to zero. We therefore don't try to overcome this
507 // problem with e.g. asking the user for a new path and
508 // trying again but simply exit.
512 if (lyxerr.debugging(Debug::INIT)) {
513 lyxerr << "LyX tmp dir: `" << package().temp_dir() << '\'' << endl;
516 lyxerr[Debug::INIT] << "Reading session information '.lyx/session'..." << endl;
517 session_.reset(new lyx::Session(lyxrc.num_lastfiles));
521 void LyX::defaultKeyBindings(kb_keymap * kbmap)
523 kbmap->bind("Right", FuncRequest(LFUN_CHAR_FORWARD));
524 kbmap->bind("Left", FuncRequest(LFUN_CHAR_BACKWARD));
525 kbmap->bind("Up", FuncRequest(LFUN_UP));
526 kbmap->bind("Down", FuncRequest(LFUN_DOWN));
528 kbmap->bind("Tab", FuncRequest(LFUN_CELL_FORWARD));
529 kbmap->bind("C-Tab", FuncRequest(LFUN_CELL_SPLIT));
530 kbmap->bind("~S-ISO_Left_Tab", FuncRequest(LFUN_CELL_BACKWARD));
531 kbmap->bind("~S-BackTab", FuncRequest(LFUN_CELL_BACKWARD));
533 kbmap->bind("Home", FuncRequest(LFUN_LINE_BEGIN));
534 kbmap->bind("End", FuncRequest(LFUN_LINE_END));
535 kbmap->bind("Prior", FuncRequest(LFUN_SCREEN_UP));
536 kbmap->bind("Next", FuncRequest(LFUN_SCREEN_DOWN));
538 kbmap->bind("Return", FuncRequest(LFUN_BREAK_PARAGRAPH));
539 //kbmap->bind("~C-~S-~M-nobreakspace", FuncRequest(LFUN_PROTECTEDSPACE));
541 kbmap->bind("Delete", FuncRequest(LFUN_DELETE_FORWARD));
542 kbmap->bind("BackSpace", FuncRequest(LFUN_DELETE_FORWARD_BACKWARD));
544 // kbmap->bindings to enable the use of the numeric keypad
546 //kbmap->bind("KP_0", FuncRequest(LFUN_SELF_INSERT));
547 //kbmap->bind("KP_Decimal", FuncRequest(LFUN_SELF_INSERT));
548 kbmap->bind("KP_Enter", FuncRequest(LFUN_BREAK_PARAGRAPH));
549 //kbmap->bind("KP_1", FuncRequest(LFUN_SELF_INSERT));
550 //kbmap->bind("KP_2", FuncRequest(LFUN_SELF_INSERT));
551 //kbmap->bind("KP_3", FuncRequest(LFUN_SELF_INSERT));
552 //kbmap->bind("KP_4", FuncRequest(LFUN_SELF_INSERT));
553 //kbmap->bind("KP_5", FuncRequest(LFUN_SELF_INSERT));
554 //kbmap->bind("KP_6", FuncRequest(LFUN_SELF_INSERT));
555 //kbmap->bind("KP_Add", FuncRequest(LFUN_SELF_INSERT));
556 //kbmap->bind("KP_7", FuncRequest(LFUN_SELF_INSERT));
557 //kbmap->bind("KP_8", FuncRequest(LFUN_SELF_INSERT));
558 //kbmap->bind("KP_9", FuncRequest(LFUN_SELF_INSERT));
559 //kbmap->bind("KP_Divide", FuncRequest(LFUN_SELF_INSERT));
560 //kbmap->bind("KP_Multiply", FuncRequest(LFUN_SELF_INSERT));
561 //kbmap->bind("KP_Subtract", FuncRequest(LFUN_SELF_INSERT));
562 kbmap->bind("KP_Right", FuncRequest(LFUN_CHAR_FORWARD));
563 kbmap->bind("KP_Left", FuncRequest(LFUN_CHAR_BACKWARD));
564 kbmap->bind("KP_Up", FuncRequest(LFUN_UP));
565 kbmap->bind("KP_Down", FuncRequest(LFUN_DOWN));
566 kbmap->bind("KP_Home", FuncRequest(LFUN_LINE_BEGIN));
567 kbmap->bind("KP_End", FuncRequest(LFUN_LINE_END));
568 kbmap->bind("KP_Prior", FuncRequest(LFUN_SCREEN_UP));
569 kbmap->bind("KP_Next", FuncRequest(LFUN_SCREEN_DOWN));
573 void LyX::emergencyCleanup() const
575 // what to do about tmpfiles is non-obvious. we would
576 // like to delete any we find, but our lyxdir might
577 // contain documents etc. which might be helpful on
580 bufferlist.emergencyWriteAll();
582 lyxserver->emergencyCleanup();
586 void LyX::deadKeyBindings(kb_keymap * kbmap)
588 // bindKeyings for transparent handling of deadkeys
589 // The keysyms are gotten from XFree86 X11R6
590 kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACCENT_ACUTE));
591 kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_ACCENT_BREVE));
592 kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_ACCENT_CARON));
593 kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_ACCENT_CEDILLA));
594 kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_ACCENT_CIRCLE));
595 kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_ACCENT_CIRCUMFLEX));
596 kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_ACCENT_DOT));
597 kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_ACCENT_GRAVE));
598 kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_ACCENT_HUNGARIAN_UMLAUT));
599 kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_ACCENT_MACRON));
600 // nothing with this name
601 // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_ACCENT_SPECIAL_CARON);
602 kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_ACCENT_TILDE));
603 kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_ACCENT_UMLAUT));
604 // nothing with this name either...
605 //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_ACCENT_UNDERBAR));
606 kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_ACCENT_UNDERDOT));
607 kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_ACCENT_TIE));
608 kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_ACCENT_OGONEK));
612 bool LyX::queryUserLyXDir(bool explicit_userdir)
614 bool reconfigure = false;
616 // Does user directory exist?
617 if (fs::exists(package().user_support()) &&
618 fs::is_directory(package().user_support())) {
620 string const configure_script =
621 addName(package().system_support(), "configure.py");
622 string const userDefaults =
623 addName(package().user_support(), "lyxrc.defaults");
624 if (fs::exists(configure_script) &&
625 fs::exists(userDefaults) &&
626 fs::last_write_time(configure_script)
627 > fs::last_write_time(userDefaults)) {
633 first_start = !explicit_userdir;
635 // If the user specified explicitly a directory, ask whether
636 // to create it. If the user says "no", then exit.
637 if (explicit_userdir &&
639 _("Missing user LyX directory"),
640 bformat(_("You have specified a non-existent user "
641 "LyX directory, %1$s.\n"
642 "It is needed to keep your own configuration."),
643 package().user_support()),
645 _("&Create directory"),
647 lyxerr << _("No user LyX directory. Exiting.") << endl;
651 lyxerr << bformat(_("LyX: Creating directory %1$s"),
652 package().user_support())
656 if (!createDirectory(package().user_support(), 0755)) {
657 // Failed, so let's exit.
658 lyxerr << _("Failed to create directory. Exiting.")
667 void LyX::readRcFile(string const & name)
669 lyxerr[Debug::INIT] << "About to read " << name << "... ";
671 string const lyxrc_path = libFileSearch(string(), name);
672 if (!lyxrc_path.empty()) {
674 lyxerr[Debug::INIT] << "Found in " << lyxrc_path << endl;
676 if (lyxrc.read(lyxrc_path) < 0)
679 lyxerr[Debug::INIT] << "Not found." << lyxrc_path << endl;
684 // Read the ui file `name'
685 void LyX::readUIFile(string const & name)
695 struct keyword_item uitags[ui_last - 1] = {
696 { "include", ui_include },
697 { "menuset", ui_menuset },
698 { "toolbar", ui_toolbar },
699 { "toolbars", ui_toolbars }
702 // Ensure that a file is read only once (prevents include loops)
703 static std::list<string> uifiles;
704 std::list<string>::const_iterator it = uifiles.begin();
705 std::list<string>::const_iterator end = uifiles.end();
706 it = std::find(it, end, name);
708 lyxerr[Debug::INIT] << "UI file '" << name
709 << "' has been read already. "
710 << "Is this an include loop?"
715 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
717 string const ui_path = libFileSearch("ui", name, "ui");
719 if (ui_path.empty()) {
720 lyxerr[Debug::INIT] << "Could not find " << name << endl;
724 uifiles.push_back(name);
726 lyxerr[Debug::INIT] << "Found " << name
727 << " in " << ui_path << endl;
728 LyXLex lex(uitags, ui_last - 1);
729 lex.setFile(ui_path);
731 lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
735 if (lyxerr.debugging(Debug::PARSER))
736 lex.printTable(lyxerr);
742 string const file = lex.getString();
747 menubackend.read(lex);
751 toolbarbackend.read(lex);
755 toolbarbackend.readToolbars(lex);
759 if (!rtrim(lex.getString()).empty())
760 lex.printError("LyX::ReadUIFile: "
761 "Unknown menu tag: `$$Token'");
768 // Read the languages file `name'
769 void LyX::readLanguagesFile(string const & name)
771 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
773 string const lang_path = libFileSearch(string(), name);
774 if (lang_path.empty()) {
778 languages.read(lang_path);
782 // Read the encodings file `name'
783 void LyX::readEncodingsFile(string const & name)
785 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
787 string const enc_path = libFileSearch(string(), name);
788 if (enc_path.empty()) {
792 encodings.read(enc_path);
801 /// return the the number of arguments consumed
802 typedef boost::function<int(string const &, string const &)> cmd_helper;
804 int parse_dbg(string const & arg, string const &)
807 lyxerr << _("List of supported debug flags:") << endl;
808 Debug::showTags(lyxerr);
811 lyxerr << bformat(_("Setting debug level to %1$s"), arg) << endl;
813 lyxerr.level(Debug::value(arg));
814 Debug::showLevel(lyxerr, lyxerr.level());
819 int parse_help(string const &, string const &)
822 _("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
823 "Command line switches (case sensitive):\n"
824 "\t-help summarize LyX usage\n"
825 "\t-userdir dir set user directory to dir\n"
826 "\t-sysdir dir set system directory to dir\n"
827 "\t-geometry WxH+X+Y set geometry of the main window\n"
828 "\t-dbg feature[,feature]...\n"
829 " select the features to debug.\n"
830 " Type `lyx -dbg' to see the list of features\n"
831 "\t-x [--execute] command\n"
832 " where command is a lyx command.\n"
833 "\t-e [--export] fmt\n"
834 " where fmt is the export format of choice.\n"
835 "\t-i [--import] fmt file.xxx\n"
836 " where fmt is the import format of choice\n"
837 " and file.xxx is the file to be imported.\n"
838 "\t-version summarize version and build info\n"
839 "Check the LyX man page for more details.") << endl;
844 int parse_version(string const &, string const &)
846 lyxerr << "LyX " << lyx_version
847 << " of " << lyx_release_date << endl;
848 lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
850 lyxerr << lyx_version_info << endl;
855 int parse_sysdir(string const & arg, string const &)
858 lyxerr << _("Missing directory for -sysdir switch") << endl;
861 cl_system_support = arg;
865 int parse_userdir(string const & arg, string const &)
868 lyxerr << _("Missing directory for -userdir switch") << endl;
871 cl_user_support = arg;
875 int parse_execute(string const & arg, string const &)
878 lyxerr << _("Missing command string after --execute switch") << endl;
885 int parse_export(string const & type, string const &)
888 lyxerr << _("Missing file type [eg latex, ps...] after "
889 "--export switch") << endl;
892 batch = "buffer-export " + type;
897 int parse_import(string const & type, string const & file)
900 lyxerr << _("Missing file type [eg latex, ps...] after "
901 "--import switch") << endl;
905 lyxerr << _("Missing filename for --import") << endl;
909 batch = "buffer-import " + type + ' ' + file;
916 bool LyX::easyParse(int & argc, char * argv[])
918 std::map<string, cmd_helper> cmdmap;
920 cmdmap["-dbg"] = parse_dbg;
921 cmdmap["-help"] = parse_help;
922 cmdmap["--help"] = parse_help;
923 cmdmap["-version"] = parse_version;
924 cmdmap["--version"] = parse_version;
925 cmdmap["-sysdir"] = parse_sysdir;
926 cmdmap["-userdir"] = parse_userdir;
927 cmdmap["-x"] = parse_execute;
928 cmdmap["--execute"] = parse_execute;
929 cmdmap["-e"] = parse_export;
930 cmdmap["--export"] = parse_export;
931 cmdmap["-i"] = parse_import;
932 cmdmap["--import"] = parse_import;
934 for (int i = 1; i < argc; ++i) {
935 std::map<string, cmd_helper>::const_iterator it
936 = cmdmap.find(argv[i]);
938 // don't complain if not found - may be parsed later
939 if (it == cmdmap.end())
942 string arg((i + 1 < argc) ? argv[i + 1] : "");
943 string arg2((i + 2 < argc) ? argv[i + 2] : "");
945 int const remove = 1 + it->second(arg, arg2);
947 // Now, remove used arguments by shifting
948 // the following ones remove places down.
950 for (int j = i; j < argc; ++j)
951 argv[j] = argv[j + remove];
955 batch_command = batch;