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();
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");
121 string const configure_command =
122 "sh " + 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();
235 vector<string> files;
237 for (int argi = argc - 1; argi >= 1; --argi)
238 files.push_back(argv[argi]);
241 files.push_back(i18nLibFileSearch("examples", "splash.lyx"));
243 // Execute batch commands if available
244 if (!batch_command.empty()) {
246 lyxerr[Debug::INIT] << "About to handle -x '"
247 << batch_command << '\'' << endl;
249 Buffer * last_loaded = 0;
251 vector<string>::const_iterator it = files.begin();
252 vector<string>::const_iterator end = files.end();
254 for (; it != end; ++it) {
255 // get absolute path of file and add ".lyx" to
256 // the filename if necessary
257 string s = FileSearch(string(), *it, "lyx");
259 last_loaded = newFile(*it, string(), true);
261 Buffer * buf = bufferlist.newBuffer(s, false);
262 buf->error.connect(boost::bind(&LyX::printError, this, _1));
263 if (loadLyXFile(buf, s))
266 bufferlist.release(buf);
270 // try to dispatch to last loaded buffer first
272 bool success = false;
273 if (last_loaded->dispatch(batch_command, &success)) {
278 files.clear(); // the files are already loaded
281 lyx_gui::start(batch_command, files);
288 The SIGHUP signal does not exist on Windows and does not need to be handled.
290 Windows handles SIGFPE and SIGSEGV signals as expected.
292 Cntl+C interrupts (mapped to SIGINT by Windows' POSIX compatability layer)
293 cause a new thread to be spawned. This may well result in unexpected
294 behaviour by the single-threaded LyX.
296 SIGTERM signals will come only from another process actually sending
297 that signal using 'raise' in Windows' POSIX compatability layer. It will
298 not come from the general "terminate process" methods that everyone
299 actually uses (and which can't be trapped). Killing an app 'politely' on
300 Windows involves first sending a WM_CLOSE message, something that is
301 caught already by the Qt frontend.
303 For more information see:
305 http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/2034055
306 ...signals are mostly useless on Windows for a variety of reasons that are
309 'UNIX Application Migration Guide, Chapter 9'
310 http://msdn.microsoft.com/library/en-us/dnucmg/html/UCMGch09.asp
312 'How To Terminate an Application "Cleanly" in Win32'
313 http://support.microsoft.com/default.aspx?scid=kb;en-us;178893
317 static void error_handler(int err_sig)
319 // Throw away any signals other than the first one received.
320 static sig_atomic_t handling_error = false;
323 handling_error = true;
325 // We have received a signal indicating a fatal error, so
326 // try and save the data ASAP.
327 LyX::cref().emergencyCleanup();
329 // These lyxerr calls may or may not work:
331 // Signals are asynchronous, so the main program may be in a very
332 // fragile state when a signal is processed and thus while a signal
333 // handler function executes.
334 // In general, therefore, we should avoid performing any
335 // I/O operations or calling most library and system functions from
338 // This shouldn't matter here, however, as we've already invoked
343 lyxerr << "\nlyx: SIGHUP signal caught\nBye." << endl;
347 lyxerr << "\nlyx: SIGFPE signal caught\nBye." << endl;
350 lyxerr << "\nlyx: SIGSEGV signal caught\n"
351 "Sorry, you have found a bug in LyX. "
352 "Please read the bug-reporting instructions "
353 "in Help->Introduction and send us a bug report, "
354 "if necessary. Thanks !\nBye." << endl;
362 // Deinstall the signal handlers
364 signal(SIGHUP, SIG_DFL);
366 signal(SIGINT, SIG_DFL);
367 signal(SIGFPE, SIG_DFL);
368 signal(SIGSEGV, SIG_DFL);
369 signal(SIGTERM, SIG_DFL);
372 if (err_sig == SIGSEGV ||
373 (err_sig != SIGHUP && !getEnv("LYXDEBUG").empty()))
375 if (err_sig == SIGSEGV || !getEnv("LYXDEBUG").empty())
377 lyx::support::abort();
384 void LyX::printError(ErrorItem const & ei)
386 std::cerr << _("LyX: ") << ei.error
387 << ':' << ei.description << std::endl;
392 void LyX::init(bool gui)
395 signal(SIGHUP, error_handler);
397 signal(SIGFPE, error_handler);
398 signal(SIGSEGV, error_handler);
399 signal(SIGINT, error_handler);
400 signal(SIGTERM, error_handler);
401 // SIGPIPE can be safely ignored.
403 #if !defined (USE_POSIX_PACKAGING)
404 // Add the directory containing the LyX executable to the path
405 // so that LyX can find things like reLyX.
406 if (package().build_support().empty())
407 prependEnvPath("PATH", package().binary_dir());
410 // Check that user LyX directory is ok. We don't do that if
411 // running in batch mode.
412 bool reconfigure = false;
415 queryUserLyXDir(package().explicit_user_support());
420 // Disable gui when easyparse says so
421 lyx_gui::use_gui = gui;
423 lyxrc.tempdir_path = package().temp_dir();
424 lyxrc.document_path = package().document_dir();
426 if (lyxrc.template_path.empty()) {
427 lyxrc.template_path = AddPath(package().system_support(),
431 if (lyxrc.lastfiles.empty()) {
432 lyxrc.lastfiles = AddName(package().user_support(), "lastfiles");
435 if (lyxrc.roman_font_name.empty())
436 lyxrc.roman_font_name = lyx_gui::roman_font_name();
437 if (lyxrc.sans_font_name.empty())
438 lyxrc.sans_font_name = lyx_gui::sans_font_name();
439 if (lyxrc.typewriter_font_name.empty())
440 lyxrc.typewriter_font_name = lyx_gui::typewriter_font_name();
443 // Read configuration files
446 readRcFile("lyxrc.defaults");
447 system_lyxrc = lyxrc;
448 system_formats = formats;
449 system_converters = converters;
450 system_movers = movers;
451 system_lcolor = lcolor;
453 string prefsfile = "preferences";
454 // back compatibility to lyxs < 1.1.6
455 if (LibFileSearch(string(), prefsfile).empty())
457 if (!LibFileSearch(string(), prefsfile).empty())
458 readRcFile(prefsfile);
460 readEncodingsFile("encodings");
461 readLanguagesFile("languages");
464 lyxerr[Debug::INIT] << "Reading layouts..." << endl;
469 toplevel_keymap.reset(new kb_keymap);
470 defaultKeyBindings(toplevel_keymap.get());
471 toplevel_keymap->read(lyxrc.bind_file);
474 readUIFile(lyxrc.ui_file);
477 if (lyxerr.debugging(Debug::LYXRC))
480 os::cygwin_path_fix(lyxrc.cygwin_path_fix);
481 if (!lyxrc.path_prefix.empty())
482 prependEnvPath("PATH", lyxrc.path_prefix);
484 // Having reset the PATH we're now in a position to run configure
487 reconfigureUserLyXDir();
489 if (fs::exists(lyxrc.document_path) &&
490 fs::is_directory(lyxrc.document_path))
491 package().document_dir() = lyxrc.document_path;
493 package().temp_dir() = createLyXTmpDir(lyxrc.tempdir_path);
494 if (package().temp_dir().empty()) {
495 Alert::error(_("Could not create temporary directory"),
496 bformat(_("Could not create a temporary directory in\n"
497 "%1$s. Make sure that this\n"
498 "path exists and is writable and try again."),
499 lyxrc.tempdir_path));
500 // createLyXTmpDir() tries sufficiently hard to create a
501 // usable temp dir, so the probability to come here is
502 // close to zero. We therefore don't try to overcome this
503 // problem with e.g. asking the user for a new path and
504 // trying again but simply exit.
508 if (lyxerr.debugging(Debug::INIT)) {
509 lyxerr << "LyX tmp dir: `" << package().temp_dir() << '\'' << endl;
512 lyxerr[Debug::INIT] << "Reading lastfiles `"
513 << lyxrc.lastfiles << "'..." << endl;
514 lastfiles_.reset(new LastFiles(lyxrc.lastfiles,
515 lyxrc.check_lastfiles,
516 lyxrc.num_lastfiles));
520 void LyX::defaultKeyBindings(kb_keymap * kbmap)
522 kbmap->bind("Right", FuncRequest(LFUN_RIGHT));
523 kbmap->bind("Left", FuncRequest(LFUN_LEFT));
524 kbmap->bind("Up", FuncRequest(LFUN_UP));
525 kbmap->bind("Down", FuncRequest(LFUN_DOWN));
527 kbmap->bind("Tab", FuncRequest(LFUN_CELL_FORWARD));
528 kbmap->bind("ISO_Left_Tab", FuncRequest(LFUN_CELL_FORWARD));
530 kbmap->bind("Home", FuncRequest(LFUN_HOME));
531 kbmap->bind("End", FuncRequest(LFUN_END));
532 kbmap->bind("Prior", FuncRequest(LFUN_PRIOR));
533 kbmap->bind("Next", FuncRequest(LFUN_NEXT));
535 kbmap->bind("Return", FuncRequest(LFUN_BREAKPARAGRAPH));
536 //kbmap->bind("~C-~S-~M-nobreakspace", FuncRequest(LFUN_PROTECTEDSPACE));
538 kbmap->bind("Delete", FuncRequest(LFUN_DELETE));
539 kbmap->bind("BackSpace", FuncRequest(LFUN_BACKSPACE));
541 // kbmap->bindings to enable the use of the numeric keypad
543 //kbmap->bind("KP_0", FuncRequest(LFUN_SELFINSERT));
544 //kbmap->bind("KP_Decimal", FuncRequest(LFUN_SELFINSERT));
545 kbmap->bind("KP_Enter", FuncRequest(LFUN_BREAKPARAGRAPH));
546 //kbmap->bind("KP_1", FuncRequest(LFUN_SELFINSERT));
547 //kbmap->bind("KP_2", FuncRequest(LFUN_SELFINSERT));
548 //kbmap->bind("KP_3", FuncRequest(LFUN_SELFINSERT));
549 //kbmap->bind("KP_4", FuncRequest(LFUN_SELFINSERT));
550 //kbmap->bind("KP_5", FuncRequest(LFUN_SELFINSERT));
551 //kbmap->bind("KP_6", FuncRequest(LFUN_SELFINSERT));
552 //kbmap->bind("KP_Add", FuncRequest(LFUN_SELFINSERT));
553 //kbmap->bind("KP_7", FuncRequest(LFUN_SELFINSERT));
554 //kbmap->bind("KP_8", FuncRequest(LFUN_SELFINSERT));
555 //kbmap->bind("KP_9", FuncRequest(LFUN_SELFINSERT));
556 //kbmap->bind("KP_Divide", FuncRequest(LFUN_SELFINSERT));
557 //kbmap->bind("KP_Multiply", FuncRequest(LFUN_SELFINSERT));
558 //kbmap->bind("KP_Subtract", FuncRequest(LFUN_SELFINSERT));
559 kbmap->bind("KP_Right", FuncRequest(LFUN_RIGHT));
560 kbmap->bind("KP_Left", FuncRequest(LFUN_LEFT));
561 kbmap->bind("KP_Up", FuncRequest(LFUN_UP));
562 kbmap->bind("KP_Down", FuncRequest(LFUN_DOWN));
563 kbmap->bind("KP_Home", FuncRequest(LFUN_HOME));
564 kbmap->bind("KP_End", FuncRequest(LFUN_END));
565 kbmap->bind("KP_Prior", FuncRequest(LFUN_PRIOR));
566 kbmap->bind("KP_Next", FuncRequest(LFUN_NEXT));
568 kbmap->bind("C-Tab", FuncRequest(LFUN_CELL_SPLIT));
569 kbmap->bind("S-Tab", FuncRequest(LFUN_CELL_BACKWARD));
570 kbmap->bind("S-ISO_Left_Tab", FuncRequest(LFUN_CELL_BACKWARD));
574 void LyX::emergencyCleanup() const
576 // what to do about tmpfiles is non-obvious. we would
577 // like to delete any we find, but our lyxdir might
578 // contain documents etc. which might be helpful on
581 bufferlist.emergencyWriteAll();
583 lyxserver->emergencyCleanup();
587 void LyX::deadKeyBindings(kb_keymap * kbmap)
589 // bindKeyings for transparent handling of deadkeys
590 // The keysyms are gotten from XFree86 X11R6
591 kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACUTE));
592 kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_BREVE));
593 kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_CARON));
594 kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_CEDILLA));
595 kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_CIRCLE));
596 kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_CIRCUMFLEX));
597 kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_DOT));
598 kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_GRAVE));
599 kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_HUNG_UMLAUT));
600 kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_MACRON));
601 // nothing with this name
602 // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_SPECIAL_CARON);
603 kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_TILDE));
604 kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_UMLAUT));
605 // nothing with this name either...
606 //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_UNDERBAR));
607 kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_UNDERDOT));
608 kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_TIE));
609 kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_OGONEK));
613 bool LyX::queryUserLyXDir(bool explicit_userdir)
615 bool reconfigure = false;
617 // Does user directory exist?
618 if (fs::exists(package().user_support()) &&
619 fs::is_directory(package().user_support())) {
621 string const configure_script =
622 AddName(package().system_support(), "configure");
623 string const userDefaults =
624 AddName(package().user_support(), "lyxrc.defaults");
625 if (fs::exists(configure_script) &&
626 fs::exists(userDefaults) &&
627 fs::last_write_time(configure_script)
628 < fs::last_write_time(userDefaults)) {
634 first_start = !explicit_userdir;
636 // If the user specified explicitly a directory, ask whether
637 // to create it. If the user says "no", then exit.
638 if (explicit_userdir &&
640 _("Missing LyX support directory"),
641 bformat(_("You have specified a non-existent user "
642 "LyX directory, %1$s.\n"
643 "It is needed to keep your own configuration."),
644 package().user_support()),
646 _("&Create directory."),
648 lyxerr << _("No user LyX directory. Exiting.") << endl;
652 lyxerr << bformat(_("LyX: Creating directory %1$s"),
653 package().user_support())
657 if (!createDirectory(package().user_support(), 0755)) {
658 // Failed, so let's exit.
659 lyxerr << _("Failed to create directory. Exiting.")
668 void LyX::readRcFile(string const & name)
670 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
672 string const lyxrc_path = LibFileSearch(string(), name);
673 if (!lyxrc_path.empty()) {
675 lyxerr[Debug::INIT] << "Found " << name
676 << " in " << lyxrc_path << endl;
678 if (lyxrc.read(lyxrc_path) >= 0)
686 // Read the ui file `name'
687 void LyX::readUIFile(string const & name)
697 struct keyword_item uitags[ui_last - 1] = {
698 { "include", ui_include },
699 { "menuset", ui_menuset },
700 { "toolbar", ui_toolbar },
701 { "toolbars", ui_toolbars }
704 // Ensure that a file is read only once (prevents include loops)
705 static std::list<string> uifiles;
706 std::list<string>::const_iterator it = uifiles.begin();
707 std::list<string>::const_iterator end = uifiles.end();
708 it = std::find(it, end, name);
710 lyxerr[Debug::INIT] << "UI file '" << name
711 << "' has been read already. "
712 << "Is this an include loop?"
717 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
719 string const ui_path = LibFileSearch("ui", name, "ui");
721 if (ui_path.empty()) {
722 lyxerr[Debug::INIT] << "Could not find " << name << endl;
726 uifiles.push_back(name);
728 lyxerr[Debug::INIT] << "Found " << name
729 << " in " << ui_path << endl;
730 LyXLex lex(uitags, ui_last - 1);
731 lex.setFile(ui_path);
733 lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
737 if (lyxerr.debugging(Debug::PARSER))
738 lex.printTable(lyxerr);
744 string const file = lex.getString();
749 menubackend.read(lex);
753 toolbarbackend.read(lex);
757 toolbarbackend.readToolbars(lex);
761 if (!rtrim(lex.getString()).empty())
762 lex.printError("LyX::ReadUIFile: "
763 "Unknown menu tag: `$$Token'");
770 // Read the languages file `name'
771 void LyX::readLanguagesFile(string const & name)
773 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
775 string const lang_path = LibFileSearch(string(), name);
776 if (lang_path.empty()) {
780 languages.read(lang_path);
784 // Read the encodings file `name'
785 void LyX::readEncodingsFile(string const & name)
787 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
789 string const enc_path = LibFileSearch(string(), name);
790 if (enc_path.empty()) {
794 encodings.read(enc_path);
803 /// return the the number of arguments consumed
804 typedef boost::function<int(string const &, string const &)> cmd_helper;
806 int parse_dbg(string const & arg, string const &)
809 lyxerr << _("List of supported debug flags:") << endl;
810 Debug::showTags(lyxerr);
813 lyxerr << bformat(_("Setting debug level to %1$s"), arg) << endl;
815 lyxerr.level(Debug::value(arg));
816 Debug::showLevel(lyxerr, lyxerr.level());
821 int parse_help(string const &, string const &)
824 _("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
825 "Command line switches (case sensitive):\n"
826 "\t-help summarize LyX usage\n"
827 "\t-userdir dir try to set user directory to dir\n"
828 "\t-sysdir dir try to set system directory to dir\n"
829 "\t-geometry WxH+X+Y set geometry of the main window\n"
830 "\t-dbg feature[,feature]...\n"
831 " select the features to debug.\n"
832 " Type `lyx -dbg' to see the list of features\n"
833 "\t-x [--execute] command\n"
834 " where command is a lyx command.\n"
835 "\t-e [--export] fmt\n"
836 " where fmt is the export format of choice.\n"
837 "\t-i [--import] fmt file.xxx\n"
838 " where fmt is the import format of choice\n"
839 " and file.xxx is the file to be imported.\n"
840 "\t-version summarize version and build info\n"
841 "Check the LyX man page for more details.") << endl;
846 int parse_version(string const &, string const &)
848 lyxerr << "LyX " << lyx_version
849 << " of " << lyx_release_date << endl;
850 lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
852 lyxerr << lyx_version_info << endl;
857 int parse_sysdir(string const & arg, string const &)
860 lyxerr << _("Missing directory for -sysdir switch") << endl;
863 cl_system_support = arg;
867 int parse_userdir(string const & arg, string const &)
870 lyxerr << _("Missing directory for -userdir switch") << endl;
873 cl_user_support = arg;
877 int parse_execute(string const & arg, string const &)
880 lyxerr << _("Missing command string after --execute switch") << endl;
884 // Argh. Setting gui to false segfaults..
885 // FIXME: when ? how ?
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;