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"
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 lyx::Session & LyX::session()
168 BOOST_ASSERT(session_.get());
169 return *session_.get();
173 lyx::Session const & LyX::session() const
175 BOOST_ASSERT(session_.get());
176 return *session_.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 // if a file is specified, I assume that user wants to edit *that* file
242 if (files.empty() && lyxrc.load_session) {
243 vector<string> const & lastopened = session_->lastOpenedFiles();
244 files.insert(files.end(), lastopened.begin(), lastopened.end() );
245 // clear this list to save a few bytes of RAM
246 session_->clearLastOpenedFiles();
249 // Execute batch commands if available
250 if (!batch_command.empty()) {
252 lyxerr[Debug::INIT] << "About to handle -x '"
253 << batch_command << '\'' << endl;
255 Buffer * last_loaded = 0;
257 vector<string>::const_iterator it = files.begin();
258 vector<string>::const_iterator end = files.end();
260 for (; it != end; ++it) {
261 // get absolute path of file and add ".lyx" to
262 // the filename if necessary
263 string s = FileSearch(string(), *it, "lyx");
265 last_loaded = newFile(*it, string(), true);
267 Buffer * buf = bufferlist.newBuffer(s, false);
268 buf->error.connect(boost::bind(&LyX::printError, this, _1));
269 if (loadLyXFile(buf, s))
272 bufferlist.release(buf);
276 // try to dispatch to last loaded buffer first
278 bool success = false;
279 if (last_loaded->dispatch(batch_command, &success)) {
284 files.clear(); // the files are already loaded
288 lyx_gui::start(batch_command, files);
290 // Something went wrong above
300 The SIGHUP signal does not exist on Windows and does not need to be handled.
302 Windows handles SIGFPE and SIGSEGV signals as expected.
304 Cntl+C interrupts (mapped to SIGINT by Windows' POSIX compatability layer)
305 cause a new thread to be spawned. This may well result in unexpected
306 behaviour by the single-threaded LyX.
308 SIGTERM signals will come only from another process actually sending
309 that signal using 'raise' in Windows' POSIX compatability layer. It will
310 not come from the general "terminate process" methods that everyone
311 actually uses (and which can't be trapped). Killing an app 'politely' on
312 Windows involves first sending a WM_CLOSE message, something that is
313 caught already by the Qt frontend.
315 For more information see:
317 http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/2034055
318 ...signals are mostly useless on Windows for a variety of reasons that are
321 'UNIX Application Migration Guide, Chapter 9'
322 http://msdn.microsoft.com/library/en-us/dnucmg/html/UCMGch09.asp
324 'How To Terminate an Application "Cleanly" in Win32'
325 http://support.microsoft.com/default.aspx?scid=kb;en-us;178893
329 static void error_handler(int err_sig)
331 // Throw away any signals other than the first one received.
332 static sig_atomic_t handling_error = false;
335 handling_error = true;
337 // We have received a signal indicating a fatal error, so
338 // try and save the data ASAP.
339 LyX::cref().emergencyCleanup();
341 // These lyxerr calls may or may not work:
343 // Signals are asynchronous, so the main program may be in a very
344 // fragile state when a signal is processed and thus while a signal
345 // handler function executes.
346 // In general, therefore, we should avoid performing any
347 // I/O operations or calling most library and system functions from
350 // This shouldn't matter here, however, as we've already invoked
355 lyxerr << "\nlyx: SIGHUP signal caught\nBye." << endl;
359 lyxerr << "\nlyx: SIGFPE signal caught\nBye." << endl;
362 lyxerr << "\nlyx: SIGSEGV signal caught\n"
363 "Sorry, you have found a bug in LyX. "
364 "Please read the bug-reporting instructions "
365 "in Help->Introduction and send us a bug report, "
366 "if necessary. Thanks !\nBye." << endl;
374 // Deinstall the signal handlers
376 signal(SIGHUP, SIG_DFL);
378 signal(SIGINT, SIG_DFL);
379 signal(SIGFPE, SIG_DFL);
380 signal(SIGSEGV, SIG_DFL);
381 signal(SIGTERM, SIG_DFL);
384 if (err_sig == SIGSEGV ||
385 (err_sig != SIGHUP && !getEnv("LYXDEBUG").empty()))
387 if (err_sig == SIGSEGV || !getEnv("LYXDEBUG").empty())
389 lyx::support::abort();
396 void LyX::printError(ErrorItem const & ei)
398 std::cerr << _("LyX: ") << ei.error
399 << ':' << ei.description << std::endl;
404 void LyX::init(bool gui)
407 signal(SIGHUP, error_handler);
409 signal(SIGFPE, error_handler);
410 signal(SIGSEGV, error_handler);
411 signal(SIGINT, error_handler);
412 signal(SIGTERM, error_handler);
413 // SIGPIPE can be safely ignored.
415 // Check that user LyX directory is ok. We don't do that if
416 // running in batch mode.
417 bool reconfigure = false;
420 queryUserLyXDir(package().explicit_user_support());
425 // Disable gui when easyparse says so
426 lyx_gui::use_gui = gui;
428 lyxrc.tempdir_path = package().temp_dir();
429 lyxrc.document_path = package().document_dir();
431 if (lyxrc.template_path.empty()) {
432 lyxrc.template_path = AddPath(package().system_support(),
436 if (lyxrc.roman_font_name.empty())
437 lyxrc.roman_font_name = lyx_gui::roman_font_name();
438 if (lyxrc.sans_font_name.empty())
439 lyxrc.sans_font_name = lyx_gui::sans_font_name();
440 if (lyxrc.typewriter_font_name.empty())
441 lyxrc.typewriter_font_name = lyx_gui::typewriter_font_name();
444 // Read configuration files
447 readRcFile("lyxrc.defaults");
448 system_lyxrc = lyxrc;
449 system_formats = formats;
450 system_converters = converters;
451 system_movers = movers;
452 system_lcolor = lcolor;
454 string prefsfile = "preferences";
455 // back compatibility to lyxs < 1.1.6
456 if (LibFileSearch(string(), prefsfile).empty())
458 if (!LibFileSearch(string(), prefsfile).empty())
459 readRcFile(prefsfile);
461 readEncodingsFile("encodings");
462 readLanguagesFile("languages");
465 lyxerr[Debug::INIT] << "Reading layouts..." << endl;
470 toplevel_keymap.reset(new kb_keymap);
471 defaultKeyBindings(toplevel_keymap.get());
472 toplevel_keymap->read(lyxrc.bind_file);
475 readUIFile(lyxrc.ui_file);
478 if (lyxerr.debugging(Debug::LYXRC))
481 os::cygwin_path_fix(lyxrc.cygwin_path_fix);
482 if (!lyxrc.path_prefix.empty())
483 prependEnvPath("PATH", lyxrc.path_prefix);
485 #if !defined (USE_POSIX_PACKAGING)
486 // Add the directory containing the LyX executable to the path
487 // so that LyX can find things like tex2lyx.
488 if (package().build_support().empty())
489 prependEnvPath("PATH", package().binary_dir());
492 // Having reset the PATH we're now in a position to run configure
495 reconfigureUserLyXDir();
497 if (fs::exists(lyxrc.document_path) &&
498 fs::is_directory(lyxrc.document_path))
499 package().document_dir() = lyxrc.document_path;
501 package().temp_dir() = createLyXTmpDir(lyxrc.tempdir_path);
502 if (package().temp_dir().empty()) {
503 Alert::error(_("Could not create temporary directory"),
504 bformat(_("Could not create a temporary directory in\n"
505 "%1$s. Make sure that this\n"
506 "path exists and is writable and try again."),
507 lyxrc.tempdir_path));
508 // createLyXTmpDir() tries sufficiently hard to create a
509 // usable temp dir, so the probability to come here is
510 // close to zero. We therefore don't try to overcome this
511 // problem with e.g. asking the user for a new path and
512 // trying again but simply exit.
516 if (lyxerr.debugging(Debug::INIT)) {
517 lyxerr << "LyX tmp dir: `" << package().temp_dir() << '\'' << endl;
520 lyxerr[Debug::INIT] << "Reading session information '.lyx/session'..." << endl;
521 session_.reset(new lyx::Session(lyxrc.num_lastfiles));
525 void LyX::defaultKeyBindings(kb_keymap * kbmap)
527 kbmap->bind("Right", FuncRequest(LFUN_RIGHT));
528 kbmap->bind("Left", FuncRequest(LFUN_LEFT));
529 kbmap->bind("Up", FuncRequest(LFUN_UP));
530 kbmap->bind("Down", FuncRequest(LFUN_DOWN));
532 kbmap->bind("Tab", FuncRequest(LFUN_CELL_FORWARD));
533 kbmap->bind("C-Tab", FuncRequest(LFUN_CELL_SPLIT));
534 kbmap->bind("~S-ISO_Left_Tab", FuncRequest(LFUN_CELL_BACKWARD));
535 kbmap->bind("~S-BackTab", FuncRequest(LFUN_CELL_BACKWARD));
537 kbmap->bind("Home", FuncRequest(LFUN_HOME));
538 kbmap->bind("End", FuncRequest(LFUN_END));
539 kbmap->bind("Prior", FuncRequest(LFUN_PRIOR));
540 kbmap->bind("Next", FuncRequest(LFUN_NEXT));
542 kbmap->bind("Return", FuncRequest(LFUN_BREAKPARAGRAPH));
543 //kbmap->bind("~C-~S-~M-nobreakspace", FuncRequest(LFUN_PROTECTEDSPACE));
545 kbmap->bind("Delete", FuncRequest(LFUN_DELETE));
546 kbmap->bind("BackSpace", FuncRequest(LFUN_BACKSPACE));
548 // kbmap->bindings to enable the use of the numeric keypad
550 //kbmap->bind("KP_0", FuncRequest(LFUN_SELFINSERT));
551 //kbmap->bind("KP_Decimal", FuncRequest(LFUN_SELFINSERT));
552 kbmap->bind("KP_Enter", FuncRequest(LFUN_BREAKPARAGRAPH));
553 //kbmap->bind("KP_1", FuncRequest(LFUN_SELFINSERT));
554 //kbmap->bind("KP_2", FuncRequest(LFUN_SELFINSERT));
555 //kbmap->bind("KP_3", FuncRequest(LFUN_SELFINSERT));
556 //kbmap->bind("KP_4", FuncRequest(LFUN_SELFINSERT));
557 //kbmap->bind("KP_5", FuncRequest(LFUN_SELFINSERT));
558 //kbmap->bind("KP_6", FuncRequest(LFUN_SELFINSERT));
559 //kbmap->bind("KP_Add", FuncRequest(LFUN_SELFINSERT));
560 //kbmap->bind("KP_7", FuncRequest(LFUN_SELFINSERT));
561 //kbmap->bind("KP_8", FuncRequest(LFUN_SELFINSERT));
562 //kbmap->bind("KP_9", FuncRequest(LFUN_SELFINSERT));
563 //kbmap->bind("KP_Divide", FuncRequest(LFUN_SELFINSERT));
564 //kbmap->bind("KP_Multiply", FuncRequest(LFUN_SELFINSERT));
565 //kbmap->bind("KP_Subtract", FuncRequest(LFUN_SELFINSERT));
566 kbmap->bind("KP_Right", FuncRequest(LFUN_RIGHT));
567 kbmap->bind("KP_Left", FuncRequest(LFUN_LEFT));
568 kbmap->bind("KP_Up", FuncRequest(LFUN_UP));
569 kbmap->bind("KP_Down", FuncRequest(LFUN_DOWN));
570 kbmap->bind("KP_Home", FuncRequest(LFUN_HOME));
571 kbmap->bind("KP_End", FuncRequest(LFUN_END));
572 kbmap->bind("KP_Prior", FuncRequest(LFUN_PRIOR));
573 kbmap->bind("KP_Next", FuncRequest(LFUN_NEXT));
577 void LyX::emergencyCleanup() const
579 // what to do about tmpfiles is non-obvious. we would
580 // like to delete any we find, but our lyxdir might
581 // contain documents etc. which might be helpful on
584 bufferlist.emergencyWriteAll();
586 lyxserver->emergencyCleanup();
590 void LyX::deadKeyBindings(kb_keymap * kbmap)
592 // bindKeyings for transparent handling of deadkeys
593 // The keysyms are gotten from XFree86 X11R6
594 kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACUTE));
595 kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_BREVE));
596 kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_CARON));
597 kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_CEDILLA));
598 kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_CIRCLE));
599 kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_CIRCUMFLEX));
600 kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_DOT));
601 kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_GRAVE));
602 kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_HUNG_UMLAUT));
603 kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_MACRON));
604 // nothing with this name
605 // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_SPECIAL_CARON);
606 kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_TILDE));
607 kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_UMLAUT));
608 // nothing with this name either...
609 //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_UNDERBAR));
610 kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_UNDERDOT));
611 kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_TIE));
612 kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_OGONEK));
616 bool LyX::queryUserLyXDir(bool explicit_userdir)
618 bool reconfigure = false;
620 // Does user directory exist?
621 if (fs::exists(package().user_support()) &&
622 fs::is_directory(package().user_support())) {
624 string const configure_script =
625 AddName(package().system_support(), "configure.py");
626 string const userDefaults =
627 AddName(package().user_support(), "lyxrc.defaults");
628 if (fs::exists(configure_script) &&
629 fs::exists(userDefaults) &&
630 fs::last_write_time(configure_script)
631 > fs::last_write_time(userDefaults)) {
637 first_start = !explicit_userdir;
639 // If the user specified explicitly a directory, ask whether
640 // to create it. If the user says "no", then exit.
641 if (explicit_userdir &&
643 _("Missing user LyX directory"),
644 bformat(_("You have specified a non-existent user "
645 "LyX directory, %1$s.\n"
646 "It is needed to keep your own configuration."),
647 package().user_support()),
649 _("&Create directory"),
651 lyxerr << _("No user LyX directory. Exiting.") << endl;
655 lyxerr << bformat(_("LyX: Creating directory %1$s"),
656 package().user_support())
660 if (!createDirectory(package().user_support(), 0755)) {
661 // Failed, so let's exit.
662 lyxerr << _("Failed to create directory. Exiting.")
671 void LyX::readRcFile(string const & name)
673 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
675 string const lyxrc_path = LibFileSearch(string(), name);
676 if (!lyxrc_path.empty()) {
678 lyxerr[Debug::INIT] << "Found " << name
679 << " in " << lyxrc_path << endl;
681 if (lyxrc.read(lyxrc_path) >= 0)
689 // Read the ui file `name'
690 void LyX::readUIFile(string const & name)
700 struct keyword_item uitags[ui_last - 1] = {
701 { "include", ui_include },
702 { "menuset", ui_menuset },
703 { "toolbar", ui_toolbar },
704 { "toolbars", ui_toolbars }
707 // Ensure that a file is read only once (prevents include loops)
708 static std::list<string> uifiles;
709 std::list<string>::const_iterator it = uifiles.begin();
710 std::list<string>::const_iterator end = uifiles.end();
711 it = std::find(it, end, name);
713 lyxerr[Debug::INIT] << "UI file '" << name
714 << "' has been read already. "
715 << "Is this an include loop?"
720 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
722 string const ui_path = LibFileSearch("ui", name, "ui");
724 if (ui_path.empty()) {
725 lyxerr[Debug::INIT] << "Could not find " << name << endl;
729 uifiles.push_back(name);
731 lyxerr[Debug::INIT] << "Found " << name
732 << " in " << ui_path << endl;
733 LyXLex lex(uitags, ui_last - 1);
734 lex.setFile(ui_path);
736 lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
740 if (lyxerr.debugging(Debug::PARSER))
741 lex.printTable(lyxerr);
747 string const file = lex.getString();
752 menubackend.read(lex);
756 toolbarbackend.read(lex);
760 toolbarbackend.readToolbars(lex);
764 if (!rtrim(lex.getString()).empty())
765 lex.printError("LyX::ReadUIFile: "
766 "Unknown menu tag: `$$Token'");
773 // Read the languages file `name'
774 void LyX::readLanguagesFile(string const & name)
776 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
778 string const lang_path = LibFileSearch(string(), name);
779 if (lang_path.empty()) {
783 languages.read(lang_path);
787 // Read the encodings file `name'
788 void LyX::readEncodingsFile(string const & name)
790 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
792 string const enc_path = LibFileSearch(string(), name);
793 if (enc_path.empty()) {
797 encodings.read(enc_path);
806 /// return the the number of arguments consumed
807 typedef boost::function<int(string const &, string const &)> cmd_helper;
809 int parse_dbg(string const & arg, string const &)
812 lyxerr << _("List of supported debug flags:") << endl;
813 Debug::showTags(lyxerr);
816 lyxerr << bformat(_("Setting debug level to %1$s"), arg) << endl;
818 lyxerr.level(Debug::value(arg));
819 Debug::showLevel(lyxerr, lyxerr.level());
824 int parse_help(string const &, string const &)
827 _("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
828 "Command line switches (case sensitive):\n"
829 "\t-help summarize LyX usage\n"
830 "\t-userdir dir set user directory to dir\n"
831 "\t-sysdir dir set system directory to dir\n"
832 "\t-geometry WxH+X+Y set geometry of the main window\n"
833 "\t-dbg feature[,feature]...\n"
834 " select the features to debug.\n"
835 " Type `lyx -dbg' to see the list of features\n"
836 "\t-x [--execute] command\n"
837 " where command is a lyx command.\n"
838 "\t-e [--export] fmt\n"
839 " where fmt is the export format of choice.\n"
840 "\t-i [--import] fmt file.xxx\n"
841 " where fmt is the import format of choice\n"
842 " and file.xxx is the file to be imported.\n"
843 "\t-version summarize version and build info\n"
844 "Check the LyX man page for more details.") << endl;
849 int parse_version(string const &, string const &)
851 lyxerr << "LyX " << lyx_version
852 << " of " << lyx_release_date << endl;
853 lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
855 lyxerr << lyx_version_info << endl;
860 int parse_sysdir(string const & arg, string const &)
863 lyxerr << _("Missing directory for -sysdir switch") << endl;
866 cl_system_support = arg;
870 int parse_userdir(string const & arg, string const &)
873 lyxerr << _("Missing directory for -userdir switch") << endl;
876 cl_user_support = arg;
880 int parse_execute(string const & arg, string const &)
883 lyxerr << _("Missing command string after --execute switch") << endl;
890 int parse_export(string const & type, string const &)
893 lyxerr << _("Missing file type [eg latex, ps...] after "
894 "--export switch") << endl;
897 batch = "buffer-export " + type;
902 int parse_import(string const & type, string const & file)
905 lyxerr << _("Missing file type [eg latex, ps...] after "
906 "--import switch") << endl;
910 lyxerr << _("Missing filename for --import") << endl;
914 batch = "buffer-import " + type + ' ' + file;
921 bool LyX::easyParse(int & argc, char * argv[])
923 std::map<string, cmd_helper> cmdmap;
925 cmdmap["-dbg"] = parse_dbg;
926 cmdmap["-help"] = parse_help;
927 cmdmap["--help"] = parse_help;
928 cmdmap["-version"] = parse_version;
929 cmdmap["--version"] = parse_version;
930 cmdmap["-sysdir"] = parse_sysdir;
931 cmdmap["-userdir"] = parse_userdir;
932 cmdmap["-x"] = parse_execute;
933 cmdmap["--execute"] = parse_execute;
934 cmdmap["-e"] = parse_export;
935 cmdmap["--export"] = parse_export;
936 cmdmap["-i"] = parse_import;
937 cmdmap["--import"] = parse_import;
939 for (int i = 1; i < argc; ++i) {
940 std::map<string, cmd_helper>::const_iterator it
941 = cmdmap.find(argv[i]);
943 // don't complain if not found - may be parsed later
944 if (it == cmdmap.end())
947 string arg((i + 1 < argc) ? argv[i + 1] : "");
948 string arg2((i + 2 < argc) ? argv[i + 2] : "");
950 int const remove = 1 + it->second(arg, arg2);
952 // Now, remove used arguments by shifting
953 // the following ones remove places down.
955 for (int j = i; j < argc; ++j)
956 argv[j] = argv[j + remove];
960 batch_command = batch;