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"
31 #include "lastfiles.h"
36 #include "lyxtextclasslist.h"
37 #include "lyxserver.h"
38 #include "MenuBackend.h"
40 #include "ToolbarBackend.h"
42 #include "mathed/math_inset.h"
44 #include "frontends/Alert.h"
45 #include "frontends/lyx_gui.h"
46 #include "frontends/LyXView.h"
48 #include "support/environment.h"
49 #include "support/filetools.h"
50 #include "support/lyxlib.h"
51 #include "support/os.h"
52 #include "support/package.h"
53 #include "support/path.h"
55 #include <boost/bind.hpp>
56 #include <boost/filesystem/operations.hpp>
61 using lyx::support::AddName;
62 using lyx::support::AddPath;
63 using lyx::support::bformat;
64 using lyx::support::createDirectory;
65 using lyx::support::createLyXTmpDir;
66 using lyx::support::FileSearch;
67 using lyx::support::getEnv;
68 using lyx::support::i18nLibFileSearch;
69 using lyx::support::LibFileSearch;
70 using lyx::support::package;
71 using lyx::support::Path;
72 using lyx::support::prependEnvPath;
73 using lyx::support::QuoteName;
74 using lyx::support::rtrim;
76 namespace os = lyx::support::os;
77 namespace fs = boost::filesystem;
83 #ifndef CXX_GLOBAL_CSTD
90 extern void QuitLyX(bool);
92 extern LyXServer * lyxserver;
94 // This is the global bufferlist object
95 BufferList bufferlist;
97 // convenient to have it here.
98 boost::scoped_ptr<kb_keymap> toplevel_keymap;
102 // Filled with the command line arguments "foo" of "-sysdir foo" or
104 string cl_system_support;
105 string cl_user_support;
108 void showFileError(string const & error)
110 Alert::warning(_("Could not read configuration file"),
111 bformat(_("Error while reading the configuration file\n%1$s.\n"
112 "Please check your installation."), error));
117 void reconfigureUserLyXDir()
119 string const configure_script =
120 AddName(package().system_support(), "configure.py");
121 string const configure_command =
122 "python " + QuoteName(configure_script);
124 lyxerr << _("LyX: reconfiguring user directory") << endl;
125 Path p(package().user_support());
126 ::system(configure_command.c_str());
127 lyxerr << "LyX: " << _("Done!") << endl;
133 boost::scoped_ptr<LyX> LyX::singleton_;
135 void LyX::exec(int & argc, char * argv[])
137 BOOST_ASSERT(!singleton_.get());
138 // We must return from this before launching the gui so that
139 // other parts of the code can access singleton_ through
140 // LyX::ref and LyX::cref.
141 singleton_.reset(new LyX);
142 // Start the real execution loop.
143 singleton_->priv_exec(argc, argv);
149 BOOST_ASSERT(singleton_.get());
150 return *singleton_.get();
154 LyX const & LyX::cref()
156 BOOST_ASSERT(singleton_.get());
157 return *singleton_.get();
166 LastFiles & LyX::lastfiles()
168 BOOST_ASSERT(lastfiles_.get());
169 return *lastfiles_.get();
173 LastFiles const & LyX::lastfiles() const
175 BOOST_ASSERT(lastfiles_.get());
176 return *lastfiles_.get();
180 void LyX::addLyXView(boost::shared_ptr<LyXView> const & lyxview)
182 views_.push_back(lyxview);
186 Buffer const * const LyX::updateInset(InsetBase const * inset) const
191 Buffer const * buffer_ptr = 0;
192 ViewList::const_iterator it = views_.begin();
193 ViewList::const_iterator const end = views_.end();
194 for (; it != end; ++it) {
195 Buffer const * ptr = (*it)->updateInset(inset);
203 void LyX::priv_exec(int & argc, char * argv[])
205 // Here we need to parse the command line. At least
206 // we need to parse for "-dbg" and "-help"
207 bool const want_gui = easyParse(argc, argv);
209 lyx::support::init_package(argv[0], cl_system_support, cl_user_support,
210 lyx::support::top_build_dir_is_one_level_up);
213 lyx_gui::parse_init(argc, argv);
215 // check for any spurious extra arguments
216 // other than documents
217 for (int argi = 1; argi < argc ; ++argi) {
218 if (argv[argi][0] == '-') {
219 lyxerr << bformat(_("Wrong command line option `%1$s'. Exiting."),
225 // Initialization of LyX (reads lyxrc and more)
226 lyxerr[Debug::INIT] << "Initializing LyX::init..." << endl;
228 lyxerr[Debug::INIT] << "Initializing LyX::init...done" << endl;
231 lyx_gui::parse_lyxrc();
233 vector<string> files;
235 for (int argi = argc - 1; argi >= 1; --argi)
236 files.push_back(os::internal_path(argv[argi]));
239 files.push_back(i18nLibFileSearch("examples", "splash.lyx"));
241 // Execute batch commands if available
242 if (!batch_command.empty()) {
244 lyxerr[Debug::INIT] << "About to handle -x '"
245 << batch_command << '\'' << endl;
247 Buffer * last_loaded = 0;
249 vector<string>::const_iterator it = files.begin();
250 vector<string>::const_iterator end = files.end();
252 for (; it != end; ++it) {
253 // get absolute path of file and add ".lyx" to
254 // the filename if necessary
255 string s = FileSearch(string(), *it, "lyx");
257 last_loaded = newFile(*it, string(), true);
259 Buffer * buf = bufferlist.newBuffer(s, false);
260 buf->error.connect(boost::bind(&LyX::printError, this, _1));
261 if (loadLyXFile(buf, s))
264 bufferlist.release(buf);
268 // try to dispatch to last loaded buffer first
270 bool success = false;
271 if (last_loaded->dispatch(batch_command, &success)) {
276 files.clear(); // the files are already loaded
280 lyx_gui::start(batch_command, files);
282 // Something went wrong above
292 The SIGHUP signal does not exist on Windows and does not need to be handled.
294 Windows handles SIGFPE and SIGSEGV signals as expected.
296 Cntl+C interrupts (mapped to SIGINT by Windows' POSIX compatability layer)
297 cause a new thread to be spawned. This may well result in unexpected
298 behaviour by the single-threaded LyX.
300 SIGTERM signals will come only from another process actually sending
301 that signal using 'raise' in Windows' POSIX compatability layer. It will
302 not come from the general "terminate process" methods that everyone
303 actually uses (and which can't be trapped). Killing an app 'politely' on
304 Windows involves first sending a WM_CLOSE message, something that is
305 caught already by the Qt frontend.
307 For more information see:
309 http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/2034055
310 ...signals are mostly useless on Windows for a variety of reasons that are
313 'UNIX Application Migration Guide, Chapter 9'
314 http://msdn.microsoft.com/library/en-us/dnucmg/html/UCMGch09.asp
316 'How To Terminate an Application "Cleanly" in Win32'
317 http://support.microsoft.com/default.aspx?scid=kb;en-us;178893
321 static void error_handler(int err_sig)
323 // Throw away any signals other than the first one received.
324 static sig_atomic_t handling_error = false;
327 handling_error = true;
329 // We have received a signal indicating a fatal error, so
330 // try and save the data ASAP.
331 LyX::cref().emergencyCleanup();
333 // These lyxerr calls may or may not work:
335 // Signals are asynchronous, so the main program may be in a very
336 // fragile state when a signal is processed and thus while a signal
337 // handler function executes.
338 // In general, therefore, we should avoid performing any
339 // I/O operations or calling most library and system functions from
342 // This shouldn't matter here, however, as we've already invoked
347 lyxerr << "\nlyx: SIGHUP signal caught\nBye." << endl;
351 lyxerr << "\nlyx: SIGFPE signal caught\nBye." << endl;
354 lyxerr << "\nlyx: SIGSEGV signal caught\n"
355 "Sorry, you have found a bug in LyX. "
356 "Please read the bug-reporting instructions "
357 "in Help->Introduction and send us a bug report, "
358 "if necessary. Thanks !\nBye." << endl;
366 // Deinstall the signal handlers
368 signal(SIGHUP, SIG_DFL);
370 signal(SIGINT, SIG_DFL);
371 signal(SIGFPE, SIG_DFL);
372 signal(SIGSEGV, SIG_DFL);
373 signal(SIGTERM, SIG_DFL);
376 if (err_sig == SIGSEGV ||
377 (err_sig != SIGHUP && !getEnv("LYXDEBUG").empty()))
379 if (err_sig == SIGSEGV || !getEnv("LYXDEBUG").empty())
381 lyx::support::abort();
388 void LyX::printError(ErrorItem const & ei)
390 std::cerr << _("LyX: ") << ei.error
391 << ':' << ei.description << std::endl;
396 void LyX::init(bool gui)
399 signal(SIGHUP, error_handler);
401 signal(SIGFPE, error_handler);
402 signal(SIGSEGV, error_handler);
403 signal(SIGINT, error_handler);
404 signal(SIGTERM, error_handler);
405 // SIGPIPE can be safely ignored.
407 // Check that user LyX directory is ok. We don't do that if
408 // running in batch mode.
409 bool reconfigure = false;
412 queryUserLyXDir(package().explicit_user_support());
417 // Disable gui when easyparse says so
418 lyx_gui::use_gui = gui;
420 lyxrc.tempdir_path = package().temp_dir();
421 lyxrc.document_path = package().document_dir();
423 if (lyxrc.template_path.empty()) {
424 lyxrc.template_path = AddPath(package().system_support(),
428 if (lyxrc.lastfiles.empty()) {
429 lyxrc.lastfiles = AddName(package().user_support(), "lastfiles");
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 readRcFile("lyxrc.defaults");
444 system_lyxrc = lyxrc;
445 system_formats = formats;
446 system_converters = converters;
447 system_movers = movers;
448 system_lcolor = lcolor;
450 string prefsfile = "preferences";
451 // back compatibility to lyxs < 1.1.6
452 if (LibFileSearch(string(), prefsfile).empty())
454 if (!LibFileSearch(string(), prefsfile).empty())
455 readRcFile(prefsfile);
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 lastfiles `"
517 << lyxrc.lastfiles << "'..." << endl;
518 lastfiles_.reset(new LastFiles(lyxrc.lastfiles,
519 lyxrc.check_lastfiles,
520 lyxrc.num_lastfiles));
524 void LyX::defaultKeyBindings(kb_keymap * kbmap)
526 kbmap->bind("Right", FuncRequest(LFUN_RIGHT));
527 kbmap->bind("Left", FuncRequest(LFUN_LEFT));
528 kbmap->bind("Up", FuncRequest(LFUN_UP));
529 kbmap->bind("Down", FuncRequest(LFUN_DOWN));
531 kbmap->bind("Tab", FuncRequest(LFUN_CELL_FORWARD));
532 kbmap->bind("C-Tab", FuncRequest(LFUN_CELL_SPLIT));
533 kbmap->bind("~S-ISO_Left_Tab", FuncRequest(LFUN_CELL_BACKWARD));
534 kbmap->bind("~S-BackTab", FuncRequest(LFUN_CELL_BACKWARD));
536 kbmap->bind("Home", FuncRequest(LFUN_HOME));
537 kbmap->bind("End", FuncRequest(LFUN_END));
538 kbmap->bind("Prior", FuncRequest(LFUN_PRIOR));
539 kbmap->bind("Next", FuncRequest(LFUN_NEXT));
541 kbmap->bind("Return", FuncRequest(LFUN_BREAKPARAGRAPH));
542 //kbmap->bind("~C-~S-~M-nobreakspace", FuncRequest(LFUN_PROTECTEDSPACE));
544 kbmap->bind("Delete", FuncRequest(LFUN_DELETE));
545 kbmap->bind("BackSpace", FuncRequest(LFUN_BACKSPACE));
547 // kbmap->bindings to enable the use of the numeric keypad
549 //kbmap->bind("KP_0", FuncRequest(LFUN_SELFINSERT));
550 //kbmap->bind("KP_Decimal", FuncRequest(LFUN_SELFINSERT));
551 kbmap->bind("KP_Enter", FuncRequest(LFUN_BREAKPARAGRAPH));
552 //kbmap->bind("KP_1", FuncRequest(LFUN_SELFINSERT));
553 //kbmap->bind("KP_2", FuncRequest(LFUN_SELFINSERT));
554 //kbmap->bind("KP_3", FuncRequest(LFUN_SELFINSERT));
555 //kbmap->bind("KP_4", FuncRequest(LFUN_SELFINSERT));
556 //kbmap->bind("KP_5", FuncRequest(LFUN_SELFINSERT));
557 //kbmap->bind("KP_6", FuncRequest(LFUN_SELFINSERT));
558 //kbmap->bind("KP_Add", FuncRequest(LFUN_SELFINSERT));
559 //kbmap->bind("KP_7", FuncRequest(LFUN_SELFINSERT));
560 //kbmap->bind("KP_8", FuncRequest(LFUN_SELFINSERT));
561 //kbmap->bind("KP_9", FuncRequest(LFUN_SELFINSERT));
562 //kbmap->bind("KP_Divide", FuncRequest(LFUN_SELFINSERT));
563 //kbmap->bind("KP_Multiply", FuncRequest(LFUN_SELFINSERT));
564 //kbmap->bind("KP_Subtract", FuncRequest(LFUN_SELFINSERT));
565 kbmap->bind("KP_Right", FuncRequest(LFUN_RIGHT));
566 kbmap->bind("KP_Left", FuncRequest(LFUN_LEFT));
567 kbmap->bind("KP_Up", FuncRequest(LFUN_UP));
568 kbmap->bind("KP_Down", FuncRequest(LFUN_DOWN));
569 kbmap->bind("KP_Home", FuncRequest(LFUN_HOME));
570 kbmap->bind("KP_End", FuncRequest(LFUN_END));
571 kbmap->bind("KP_Prior", FuncRequest(LFUN_PRIOR));
572 kbmap->bind("KP_Next", FuncRequest(LFUN_NEXT));
576 void LyX::emergencyCleanup() const
578 // what to do about tmpfiles is non-obvious. we would
579 // like to delete any we find, but our lyxdir might
580 // contain documents etc. which might be helpful on
583 bufferlist.emergencyWriteAll();
585 lyxserver->emergencyCleanup();
589 void LyX::deadKeyBindings(kb_keymap * kbmap)
591 // bindKeyings for transparent handling of deadkeys
592 // The keysyms are gotten from XFree86 X11R6
593 kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACUTE));
594 kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_BREVE));
595 kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_CARON));
596 kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_CEDILLA));
597 kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_CIRCLE));
598 kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_CIRCUMFLEX));
599 kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_DOT));
600 kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_GRAVE));
601 kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_HUNG_UMLAUT));
602 kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_MACRON));
603 // nothing with this name
604 // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_SPECIAL_CARON);
605 kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_TILDE));
606 kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_UMLAUT));
607 // nothing with this name either...
608 //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_UNDERBAR));
609 kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_UNDERDOT));
610 kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_TIE));
611 kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_OGONEK));
615 bool LyX::queryUserLyXDir(bool explicit_userdir)
617 bool reconfigure = false;
619 // Does user directory exist?
620 if (fs::exists(package().user_support()) &&
621 fs::is_directory(package().user_support())) {
623 string const configure_script =
624 AddName(package().system_support(), "configure.py");
625 string const userDefaults =
626 AddName(package().user_support(), "lyxrc.defaults");
627 if (fs::exists(configure_script) &&
628 fs::exists(userDefaults) &&
629 fs::last_write_time(configure_script)
630 > fs::last_write_time(userDefaults)) {
636 first_start = !explicit_userdir;
638 // If the user specified explicitly a directory, ask whether
639 // to create it. If the user says "no", then exit.
640 if (explicit_userdir &&
642 _("Missing user LyX directory"),
643 bformat(_("You have specified a non-existent user "
644 "LyX directory, %1$s.\n"
645 "It is needed to keep your own configuration."),
646 package().user_support()),
648 _("&Create directory."),
650 lyxerr << _("No user LyX directory. Exiting.") << endl;
654 lyxerr << bformat(_("LyX: Creating directory %1$s"),
655 package().user_support())
659 if (!createDirectory(package().user_support(), 0755)) {
660 // Failed, so let's exit.
661 lyxerr << _("Failed to create directory. Exiting.")
670 void LyX::readRcFile(string const & name)
672 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
674 string const lyxrc_path = LibFileSearch(string(), name);
675 if (!lyxrc_path.empty()) {
677 lyxerr[Debug::INIT] << "Found " << name
678 << " in " << lyxrc_path << endl;
680 if (lyxrc.read(lyxrc_path) >= 0)
688 // Read the ui file `name'
689 void LyX::readUIFile(string const & name)
699 struct keyword_item uitags[ui_last - 1] = {
700 { "include", ui_include },
701 { "menuset", ui_menuset },
702 { "toolbar", ui_toolbar },
703 { "toolbars", ui_toolbars }
706 // Ensure that a file is read only once (prevents include loops)
707 static std::list<string> uifiles;
708 std::list<string>::const_iterator it = uifiles.begin();
709 std::list<string>::const_iterator end = uifiles.end();
710 it = std::find(it, end, name);
712 lyxerr[Debug::INIT] << "UI file '" << name
713 << "' has been read already. "
714 << "Is this an include loop?"
719 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
721 string const ui_path = LibFileSearch("ui", name, "ui");
723 if (ui_path.empty()) {
724 lyxerr[Debug::INIT] << "Could not find " << name << endl;
728 uifiles.push_back(name);
730 lyxerr[Debug::INIT] << "Found " << name
731 << " in " << ui_path << endl;
732 LyXLex lex(uitags, ui_last - 1);
733 lex.setFile(ui_path);
735 lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
739 if (lyxerr.debugging(Debug::PARSER))
740 lex.printTable(lyxerr);
746 string const file = lex.getString();
751 menubackend.read(lex);
755 toolbarbackend.read(lex);
759 toolbarbackend.readToolbars(lex);
763 if (!rtrim(lex.getString()).empty())
764 lex.printError("LyX::ReadUIFile: "
765 "Unknown menu tag: `$$Token'");
772 // Read the languages file `name'
773 void LyX::readLanguagesFile(string const & name)
775 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
777 string const lang_path = LibFileSearch(string(), name);
778 if (lang_path.empty()) {
782 languages.read(lang_path);
786 // Read the encodings file `name'
787 void LyX::readEncodingsFile(string const & name)
789 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
791 string const enc_path = LibFileSearch(string(), name);
792 if (enc_path.empty()) {
796 encodings.read(enc_path);
805 /// return the the number of arguments consumed
806 typedef boost::function<int(string const &, string const &)> cmd_helper;
808 int parse_dbg(string const & arg, string const &)
811 lyxerr << _("List of supported debug flags:") << endl;
812 Debug::showTags(lyxerr);
815 lyxerr << bformat(_("Setting debug level to %1$s"), arg) << endl;
817 lyxerr.level(Debug::value(arg));
818 Debug::showLevel(lyxerr, lyxerr.level());
823 int parse_help(string const &, string const &)
826 _("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
827 "Command line switches (case sensitive):\n"
828 "\t-help summarize LyX usage\n"
829 "\t-userdir dir try to set user directory to dir\n"
830 "\t-sysdir dir try to set system directory to dir\n"
831 "\t-geometry WxH+X+Y set geometry of the main window\n"
832 "\t-dbg feature[,feature]...\n"
833 " select the features to debug.\n"
834 " Type `lyx -dbg' to see the list of features\n"
835 "\t-x [--execute] command\n"
836 " where command is a lyx command.\n"
837 "\t-e [--export] fmt\n"
838 " where fmt is the export format of choice.\n"
839 "\t-i [--import] fmt file.xxx\n"
840 " where fmt is the import format of choice\n"
841 " and file.xxx is the file to be imported.\n"
842 "\t-version summarize version and build info\n"
843 "Check the LyX man page for more details.") << endl;
848 int parse_version(string const &, string const &)
850 lyxerr << "LyX " << lyx_version
851 << " of " << lyx_release_date << endl;
852 lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
854 lyxerr << lyx_version_info << endl;
859 int parse_sysdir(string const & arg, string const &)
862 lyxerr << _("Missing directory for -sysdir switch") << endl;
865 cl_system_support = arg;
869 int parse_userdir(string const & arg, string const &)
872 lyxerr << _("Missing directory for -userdir switch") << endl;
875 cl_user_support = arg;
879 int parse_execute(string const & arg, string const &)
882 lyxerr << _("Missing command string after --execute switch") << endl;
889 int parse_export(string const & type, string const &)
892 lyxerr << _("Missing file type [eg latex, ps...] after "
893 "--export switch") << endl;
896 batch = "buffer-export " + type;
901 int parse_import(string const & type, string const & file)
904 lyxerr << _("Missing file type [eg latex, ps...] after "
905 "--import switch") << endl;
909 lyxerr << _("Missing filename for --import") << endl;
913 batch = "buffer-import " + type + ' ' + file;
920 bool LyX::easyParse(int & argc, char * argv[])
922 std::map<string, cmd_helper> cmdmap;
924 cmdmap["-dbg"] = parse_dbg;
925 cmdmap["-help"] = parse_help;
926 cmdmap["--help"] = parse_help;
927 cmdmap["-version"] = parse_version;
928 cmdmap["--version"] = parse_version;
929 cmdmap["-sysdir"] = parse_sysdir;
930 cmdmap["-userdir"] = parse_userdir;
931 cmdmap["-x"] = parse_execute;
932 cmdmap["--execute"] = parse_execute;
933 cmdmap["-e"] = parse_export;
934 cmdmap["--export"] = parse_export;
935 cmdmap["-i"] = parse_import;
936 cmdmap["--import"] = parse_import;
938 for (int i = 1; i < argc; ++i) {
939 std::map<string, cmd_helper>::const_iterator it
940 = cmdmap.find(argv[i]);
942 // don't complain if not found - may be parsed later
943 if (it == cmdmap.end())
946 string arg((i + 1 < argc) ? argv[i + 1] : "");
947 string arg2((i + 2 < argc) ? argv[i + 2] : "");
949 int const remove = 1 + it->second(arg, arg2);
951 // Now, remove used arguments by shifting
952 // the following ones remove places down.
954 for (int j = i; j < argc; ++j)
955 argv[j] = argv[j + remove];
959 batch_command = batch;