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/filetools.h"
49 #include "support/lyxlib.h"
50 #include "support/os.h"
51 #include "support/package.h"
52 #include "support/path.h"
54 #include <boost/bind.hpp>
55 #include <boost/filesystem/operations.hpp>
60 using lyx::support::AddName;
61 using lyx::support::AddPath;
62 using lyx::support::bformat;
63 using lyx::support::createDirectory;
64 using lyx::support::createLyXTmpDir;
65 using lyx::support::FileSearch;
66 using lyx::support::GetEnv;
67 using lyx::support::i18nLibFileSearch;
68 using lyx::support::LibFileSearch;
69 using lyx::support::package;
70 using lyx::support::Path;
71 using lyx::support::prependEnvPath;
72 using lyx::support::QuoteName;
73 using lyx::support::rtrim;
75 namespace os = lyx::support::os;
76 namespace fs = boost::filesystem;
82 #ifndef CXX_GLOBAL_CSTD
89 extern void QuitLyX();
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_script =
119 AddName(package().system_support(), "configure");
120 string const configure_command =
121 "sh " + QuoteName(configure_script);
123 lyxerr << _("LyX: reconfiguring user directory") << endl;
124 Path p(package().user_support());
125 ::system(configure_command.c_str());
126 lyxerr << "LyX: " << _("Done!") << endl;
132 boost::scoped_ptr<LyX> LyX::singleton_;
134 void LyX::exec(int & argc, char * argv[])
136 BOOST_ASSERT(!singleton_.get());
137 // We must return from this before launching the gui so that
138 // other parts of the code can access singleton_ through
139 // LyX::ref and LyX::cref.
140 singleton_.reset(new LyX);
141 // Start the real execution loop.
142 singleton_->priv_exec(argc, argv);
148 BOOST_ASSERT(singleton_.get());
149 return *singleton_.get();
153 LyX const & LyX::cref()
155 BOOST_ASSERT(singleton_.get());
156 return *singleton_.get();
165 LastFiles & LyX::lastfiles()
167 BOOST_ASSERT(lastfiles_.get());
168 return *lastfiles_.get();
172 LastFiles const & LyX::lastfiles() const
174 BOOST_ASSERT(lastfiles_.get());
175 return *lastfiles_.get();
179 void LyX::addLyXView(boost::shared_ptr<LyXView> const & lyxview)
181 views_.push_back(lyxview);
185 Buffer const * const LyX::updateInset(InsetBase const * inset) const
190 Buffer const * buffer_ptr = 0;
191 ViewList::const_iterator it = views_.begin();
192 ViewList::const_iterator const end = views_.end();
193 for (; it != end; ++it) {
194 Buffer const * ptr = (*it)->updateInset(inset);
202 void LyX::priv_exec(int & argc, char * argv[])
204 // Here we need to parse the command line. At least
205 // we need to parse for "-dbg" and "-help"
206 bool const want_gui = easyParse(argc, argv);
208 lyx::support::init_package(argv[0], cl_system_support, cl_user_support,
209 lyx::support::top_build_dir_is_one_level_up);
212 lyx_gui::parse_init(argc, argv);
214 // check for any spurious extra arguments
215 // other than documents
216 for (int argi = 1; argi < argc ; ++argi) {
217 if (argv[argi][0] == '-') {
218 lyxerr << bformat(_("Wrong command line option `%1$s'. Exiting."),
224 // Initialization of LyX (reads lyxrc and more)
225 lyxerr[Debug::INIT] << "Initializing LyX::init..." << endl;
227 lyxerr[Debug::INIT] << "Initializing LyX::init...done" << endl;
230 lyx_gui::parse_lyxrc();
234 vector<string> files;
236 for (int argi = argc - 1; argi >= 1; --argi)
237 files.push_back(argv[argi]);
240 files.push_back(i18nLibFileSearch("examples", "splash.lyx"));
242 // Execute batch commands if available
243 if (!batch_command.empty()) {
245 lyxerr[Debug::INIT] << "About to handle -x '"
246 << batch_command << '\'' << endl;
248 Buffer * last_loaded = 0;
250 vector<string>::const_iterator it = files.begin();
251 vector<string>::const_iterator end = files.end();
253 for (; it != end; ++it) {
254 // get absolute path of file and add ".lyx" to
255 // the filename if necessary
256 string s = FileSearch(string(), *it, "lyx");
258 last_loaded = newFile(*it, string(), true);
260 Buffer * buf = bufferlist.newBuffer(s, false);
261 buf->error.connect(boost::bind(&LyX::printError, this, _1));
262 if (loadLyXFile(buf, s))
265 bufferlist.release(buf);
269 // try to dispatch to last loaded buffer first
271 bool success = false;
272 if (last_loaded->dispatch(batch_command, &success)) {
277 files.clear(); // the files are already loaded
280 lyx_gui::start(batch_command, files);
287 The SIGHUP signal does not exist on Windows and does not need to be handled.
289 Windows handles SIGFPE and SIGSEGV signals as expected.
291 Cntl+C interrupts (mapped to SIGINT by Windows' POSIX compatability layer)
292 cause a new thread to be spawned. This may well result in unexpected
293 behaviour by the single-threaded LyX.
295 SIGTERM signals will come only from another process actually sending
296 that signal using 'raise' in Windows' POSIX compatability layer. It will
297 not come from the general "terminate process" methods that everyone
298 actually uses (and which can't be trapped). Killing an app 'politely' on
299 Windows involves first sending a WM_CLOSE message, something that is
300 caught already by the Qt frontend.
302 For more information see:
304 http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/2034055
305 ...signals are mostly useless on Windows for a variety of reasons that are
308 'UNIX Application Migration Guide, Chapter 9'
309 http://msdn.microsoft.com/library/en-us/dnucmg/html/UCMGch09.asp
311 'How To Terminate an Application "Cleanly" in Win32'
312 http://support.microsoft.com/default.aspx?scid=kb;en-us;178893
316 static void error_handler(int err_sig)
318 // Throw away any signals other than the first one received.
319 static sig_atomic_t handling_error = false;
322 handling_error = true;
324 // We have received a signal indicating a fatal error, so
325 // try and save the data ASAP.
326 LyX::cref().emergencyCleanup();
328 // These lyxerr calls may or may not work:
330 // Signals are asynchronous, so the main program may be in a very
331 // fragile state when a signal is processed and thus while a signal
332 // handler function executes.
333 // In general, therefore, we should avoid performing any
334 // I/O operations or calling most library and system functions from
337 // This shouldn't matter here, however, as we've already invoked
342 lyxerr << "\nlyx: SIGHUP signal caught\nBye." << endl;
346 lyxerr << "\nlyx: SIGFPE signal caught\nBye." << endl;
349 lyxerr << "\nlyx: SIGSEGV signal caught\n"
350 "Sorry, you have found a bug in LyX. "
351 "Please read the bug-reporting instructions "
352 "in Help->Introduction and send us a bug report, "
353 "if necessary. Thanks !\nBye." << endl;
361 // Deinstall the signal handlers
363 signal(SIGHUP, SIG_DFL);
365 signal(SIGINT, SIG_DFL);
366 signal(SIGFPE, SIG_DFL);
367 signal(SIGSEGV, SIG_DFL);
368 signal(SIGTERM, SIG_DFL);
371 if (err_sig == SIGSEGV ||
372 (err_sig != SIGHUP && !GetEnv("LYXDEBUG").empty()))
374 if (err_sig == SIGSEGV || !GetEnv("LYXDEBUG").empty())
376 lyx::support::abort();
383 void LyX::printError(ErrorItem const & ei)
385 std::cerr << _("LyX: ") << ei.error
386 << ':' << ei.description << std::endl;
391 void LyX::init(bool gui)
394 signal(SIGHUP, error_handler);
396 signal(SIGFPE, error_handler);
397 signal(SIGSEGV, error_handler);
398 signal(SIGINT, error_handler);
399 signal(SIGTERM, error_handler);
400 // SIGPIPE can be safely ignored.
402 #if !defined (USE_POSIX_PACKAGING)
403 // Add the directory containing the LyX executable to the path
404 // so that LyX can find things like reLyX.
405 if (package().build_support().empty())
406 prependEnvPath("PATH", package().binary_dir());
409 // Check that user LyX directory is ok. We don't do that if
410 // running in batch mode.
411 bool reconfigure = false;
414 queryUserLyXDir(package().explicit_user_support());
419 // Disable gui when easyparse says so
420 lyx_gui::use_gui = gui;
422 lyxrc.tempdir_path = package().temp_dir();
423 lyxrc.document_path = package().document_dir();
425 if (lyxrc.template_path.empty()) {
426 lyxrc.template_path = AddPath(package().system_support(),
430 if (lyxrc.lastfiles.empty()) {
431 lyxrc.lastfiles = AddName(package().user_support(), "lastfiles");
434 if (lyxrc.roman_font_name.empty())
435 lyxrc.roman_font_name = lyx_gui::roman_font_name();
436 if (lyxrc.sans_font_name.empty())
437 lyxrc.sans_font_name = lyx_gui::sans_font_name();
438 if (lyxrc.typewriter_font_name.empty())
439 lyxrc.typewriter_font_name = lyx_gui::typewriter_font_name();
442 // Read configuration files
445 readRcFile("lyxrc.defaults");
446 system_lyxrc = lyxrc;
447 system_formats = formats;
448 system_converters = converters;
449 system_movers = movers;
450 system_lcolor = lcolor;
452 string prefsfile = "preferences";
453 // back compatibility to lyxs < 1.1.6
454 if (LibFileSearch(string(), prefsfile).empty())
456 if (!LibFileSearch(string(), prefsfile).empty())
457 readRcFile(prefsfile);
459 readEncodingsFile("encodings");
460 readLanguagesFile("languages");
463 lyxerr[Debug::INIT] << "Reading layouts..." << endl;
468 toplevel_keymap.reset(new kb_keymap);
469 defaultKeyBindings(toplevel_keymap.get());
470 toplevel_keymap->read(lyxrc.bind_file);
473 readUIFile(lyxrc.ui_file);
476 if (lyxerr.debugging(Debug::LYXRC))
479 os::cygwin_path_fix(lyxrc.cygwin_path_fix);
480 prependEnvPath("PATH", lyxrc.path_prefix);
482 // Having reset the PATH we're now in a position to run configure
485 reconfigureUserLyXDir();
487 if (fs::exists(lyxrc.document_path) &&
488 fs::is_directory(lyxrc.document_path))
489 package().document_dir() = lyxrc.document_path;
491 package().temp_dir() = createLyXTmpDir(lyxrc.tempdir_path);
492 if (package().temp_dir().empty()) {
493 Alert::error(_("Could not create temporary directory"),
494 bformat(_("Could not create a temporary directory in\n"
495 "%1$s. Make sure that this\n"
496 "path exists and is writable and try again."),
497 lyxrc.tempdir_path));
498 // createLyXTmpDir() tries sufficiently hard to create a
499 // usable temp dir, so the probability to come here is
500 // close to zero. We therefore don't try to overcome this
501 // problem with e.g. asking the user for a new path and
502 // trying again but simply exit.
506 if (lyxerr.debugging(Debug::INIT)) {
507 lyxerr << "LyX tmp dir: `" << package().temp_dir() << '\'' << endl;
510 lyxerr[Debug::INIT] << "Reading lastfiles `"
511 << lyxrc.lastfiles << "'..." << endl;
512 lastfiles_.reset(new LastFiles(lyxrc.lastfiles,
513 lyxrc.check_lastfiles,
514 lyxrc.num_lastfiles));
518 void LyX::defaultKeyBindings(kb_keymap * kbmap)
520 kbmap->bind("Right", FuncRequest(LFUN_RIGHT));
521 kbmap->bind("Left", FuncRequest(LFUN_LEFT));
522 kbmap->bind("Up", FuncRequest(LFUN_UP));
523 kbmap->bind("Down", FuncRequest(LFUN_DOWN));
525 kbmap->bind("Tab", FuncRequest(LFUN_CELL_FORWARD));
526 kbmap->bind("ISO_Left_Tab", FuncRequest(LFUN_CELL_FORWARD));
528 kbmap->bind("Home", FuncRequest(LFUN_HOME));
529 kbmap->bind("End", FuncRequest(LFUN_END));
530 kbmap->bind("Prior", FuncRequest(LFUN_PRIOR));
531 kbmap->bind("Next", FuncRequest(LFUN_NEXT));
533 kbmap->bind("Return", FuncRequest(LFUN_BREAKPARAGRAPH));
534 //kbmap->bind("~C-~S-~M-nobreakspace", FuncRequest(LFUN_PROTECTEDSPACE));
536 kbmap->bind("Delete", FuncRequest(LFUN_DELETE));
537 kbmap->bind("BackSpace", FuncRequest(LFUN_BACKSPACE));
539 // kbmap->bindings to enable the use of the numeric keypad
541 //kbmap->bind("KP_0", FuncRequest(LFUN_SELFINSERT));
542 //kbmap->bind("KP_Decimal", FuncRequest(LFUN_SELFINSERT));
543 kbmap->bind("KP_Enter", FuncRequest(LFUN_BREAKPARAGRAPH));
544 //kbmap->bind("KP_1", FuncRequest(LFUN_SELFINSERT));
545 //kbmap->bind("KP_2", FuncRequest(LFUN_SELFINSERT));
546 //kbmap->bind("KP_3", FuncRequest(LFUN_SELFINSERT));
547 //kbmap->bind("KP_4", FuncRequest(LFUN_SELFINSERT));
548 //kbmap->bind("KP_5", FuncRequest(LFUN_SELFINSERT));
549 //kbmap->bind("KP_6", FuncRequest(LFUN_SELFINSERT));
550 //kbmap->bind("KP_Add", FuncRequest(LFUN_SELFINSERT));
551 //kbmap->bind("KP_7", FuncRequest(LFUN_SELFINSERT));
552 //kbmap->bind("KP_8", FuncRequest(LFUN_SELFINSERT));
553 //kbmap->bind("KP_9", FuncRequest(LFUN_SELFINSERT));
554 //kbmap->bind("KP_Divide", FuncRequest(LFUN_SELFINSERT));
555 //kbmap->bind("KP_Multiply", FuncRequest(LFUN_SELFINSERT));
556 //kbmap->bind("KP_Subtract", FuncRequest(LFUN_SELFINSERT));
557 kbmap->bind("KP_Right", FuncRequest(LFUN_RIGHT));
558 kbmap->bind("KP_Left", FuncRequest(LFUN_LEFT));
559 kbmap->bind("KP_Up", FuncRequest(LFUN_UP));
560 kbmap->bind("KP_Down", FuncRequest(LFUN_DOWN));
561 kbmap->bind("KP_Home", FuncRequest(LFUN_HOME));
562 kbmap->bind("KP_End", FuncRequest(LFUN_END));
563 kbmap->bind("KP_Prior", FuncRequest(LFUN_PRIOR));
564 kbmap->bind("KP_Next", FuncRequest(LFUN_NEXT));
566 kbmap->bind("C-Tab", FuncRequest(LFUN_CELL_SPLIT));
567 kbmap->bind("S-Tab", FuncRequest(LFUN_CELL_BACKWARD));
568 kbmap->bind("S-ISO_Left_Tab", FuncRequest(LFUN_CELL_BACKWARD));
572 void LyX::emergencyCleanup() const
574 // what to do about tmpfiles is non-obvious. we would
575 // like to delete any we find, but our lyxdir might
576 // contain documents etc. which might be helpful on
579 bufferlist.emergencyWriteAll();
581 lyxserver->emergencyCleanup();
585 void LyX::deadKeyBindings(kb_keymap * kbmap)
587 // bindKeyings for transparent handling of deadkeys
588 // The keysyms are gotten from XFree86 X11R6
589 kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACUTE));
590 kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_BREVE));
591 kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_CARON));
592 kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_CEDILLA));
593 kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_CIRCLE));
594 kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_CIRCUMFLEX));
595 kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_DOT));
596 kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_GRAVE));
597 kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_HUNG_UMLAUT));
598 kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_MACRON));
599 // nothing with this name
600 // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_SPECIAL_CARON);
601 kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_TILDE));
602 kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_UMLAUT));
603 // nothing with this name either...
604 //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_UNDERBAR));
605 kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_UNDERDOT));
606 kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_TIE));
607 kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_OGONEK));
611 bool LyX::queryUserLyXDir(bool explicit_userdir)
613 bool reconfigure = false;
615 // Does user directory exist?
616 if (fs::exists(package().user_support()) &&
617 fs::is_directory(package().user_support())) {
619 string const configure_script =
620 AddName(package().system_support(), "configure");
621 string const userDefaults =
622 AddName(package().user_support(), "lyxrc.defaults");
623 if (fs::exists(configure_script) &&
624 fs::exists(userDefaults) &&
625 fs::last_write_time(configure_script)
626 < fs::last_write_time(userDefaults)) {
632 first_start = !explicit_userdir;
634 // If the user specified explicitly a directory, ask whether
635 // to create it. If the user says "no", then exit.
636 if (explicit_userdir &&
638 _("Missing LyX support directory"),
639 bformat(_("You have specified a non-existent user "
640 "LyX directory, %1$s.\n"
641 "It is needed to keep your own configuration."),
642 package().user_support()),
644 _("&Create directory."),
646 lyxerr << _("No user LyX directory. Exiting.") << endl;
650 lyxerr << bformat(_("LyX: Creating directory %1$s"),
651 package().user_support())
655 if (!createDirectory(package().user_support(), 0755)) {
656 // Failed, so let's exit.
657 lyxerr << _("Failed to create directory. Exiting.")
666 void LyX::readRcFile(string const & name)
668 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
670 string const lyxrc_path = LibFileSearch(string(), name);
671 if (!lyxrc_path.empty()) {
673 lyxerr[Debug::INIT] << "Found " << name
674 << " in " << lyxrc_path << endl;
676 if (lyxrc.read(lyxrc_path) >= 0)
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 try to set user directory to dir\n"
826 "\t-sysdir dir try to 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;
882 // Argh. Setting gui to false segfaults..
883 // FIXME: when ? how ?
888 int parse_export(string const & type, string const &)
891 lyxerr << _("Missing file type [eg latex, ps...] after "
892 "--export switch") << endl;
895 batch = "buffer-export " + type;
900 int parse_import(string const & type, string const & file)
903 lyxerr << _("Missing file type [eg latex, ps...] after "
904 "--import switch") << endl;
908 lyxerr << _("Missing filename for --import") << endl;
912 batch = "buffer-import " + type + ' ' + file;
919 bool LyX::easyParse(int & argc, char * argv[])
921 std::map<string, cmd_helper> cmdmap;
923 cmdmap["-dbg"] = parse_dbg;
924 cmdmap["-help"] = parse_help;
925 cmdmap["--help"] = parse_help;
926 cmdmap["-version"] = parse_version;
927 cmdmap["--version"] = parse_version;
928 cmdmap["-sysdir"] = parse_sysdir;
929 cmdmap["-userdir"] = parse_userdir;
930 cmdmap["-x"] = parse_execute;
931 cmdmap["--execute"] = parse_execute;
932 cmdmap["-e"] = parse_export;
933 cmdmap["--export"] = parse_export;
934 cmdmap["-i"] = parse_import;
935 cmdmap["--import"] = parse_import;
937 for (int i = 1; i < argc; ++i) {
938 std::map<string, cmd_helper>::const_iterator it
939 = cmdmap.find(argv[i]);
941 // don't complain if not found - may be parsed later
942 if (it == cmdmap.end())
945 string arg((i + 1 < argc) ? argv[i + 1] : "");
946 string arg2((i + 2 < argc) ? argv[i + 2] : "");
948 int const remove = 1 + it->second(arg, arg2);
950 // Now, remove used arguments by shifting
951 // the following ones remove places down.
953 for (int j = i; j < argc; ++j)
954 argv[j] = argv[j + remove];
958 batch_command = batch;