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::is_directory(lyxrc.document_path))
488 package().document_dir() = lyxrc.document_path;
490 package().temp_dir() = createLyXTmpDir(lyxrc.tempdir_path);
491 if (package().temp_dir().empty()) {
492 Alert::error(_("Could not create temporary directory"),
493 bformat(_("Could not create a temporary directory in\n"
494 "%1$s. Make sure that this\n"
495 "path exists and is writable and try again."),
496 lyxrc.tempdir_path));
497 // createLyXTmpDir() tries sufficiently hard to create a
498 // usable temp dir, so the probability to come here is
499 // close to zero. We therefore don't try to overcome this
500 // problem with e.g. asking the user for a new path and
501 // trying again but simply exit.
505 if (lyxerr.debugging(Debug::INIT)) {
506 lyxerr << "LyX tmp dir: `" << package().temp_dir() << '\'' << endl;
509 lyxerr[Debug::INIT] << "Reading lastfiles `"
510 << lyxrc.lastfiles << "'..." << endl;
511 lastfiles_.reset(new LastFiles(lyxrc.lastfiles,
512 lyxrc.check_lastfiles,
513 lyxrc.num_lastfiles));
517 void LyX::defaultKeyBindings(kb_keymap * kbmap)
519 kbmap->bind("Right", FuncRequest(LFUN_RIGHT));
520 kbmap->bind("Left", FuncRequest(LFUN_LEFT));
521 kbmap->bind("Up", FuncRequest(LFUN_UP));
522 kbmap->bind("Down", FuncRequest(LFUN_DOWN));
524 kbmap->bind("Tab", FuncRequest(LFUN_CELL_FORWARD));
525 kbmap->bind("ISO_Left_Tab", FuncRequest(LFUN_CELL_FORWARD));
527 kbmap->bind("Home", FuncRequest(LFUN_HOME));
528 kbmap->bind("End", FuncRequest(LFUN_END));
529 kbmap->bind("Prior", FuncRequest(LFUN_PRIOR));
530 kbmap->bind("Next", FuncRequest(LFUN_NEXT));
532 kbmap->bind("Return", FuncRequest(LFUN_BREAKPARAGRAPH));
533 //kbmap->bind("~C-~S-~M-nobreakspace", FuncRequest(LFUN_PROTECTEDSPACE));
535 kbmap->bind("Delete", FuncRequest(LFUN_DELETE));
536 kbmap->bind("BackSpace", FuncRequest(LFUN_BACKSPACE));
538 // kbmap->bindings to enable the use of the numeric keypad
540 //kbmap->bind("KP_0", FuncRequest(LFUN_SELFINSERT));
541 //kbmap->bind("KP_Decimal", FuncRequest(LFUN_SELFINSERT));
542 kbmap->bind("KP_Enter", FuncRequest(LFUN_BREAKPARAGRAPH));
543 //kbmap->bind("KP_1", FuncRequest(LFUN_SELFINSERT));
544 //kbmap->bind("KP_2", FuncRequest(LFUN_SELFINSERT));
545 //kbmap->bind("KP_3", FuncRequest(LFUN_SELFINSERT));
546 //kbmap->bind("KP_4", FuncRequest(LFUN_SELFINSERT));
547 //kbmap->bind("KP_5", FuncRequest(LFUN_SELFINSERT));
548 //kbmap->bind("KP_6", FuncRequest(LFUN_SELFINSERT));
549 //kbmap->bind("KP_Add", FuncRequest(LFUN_SELFINSERT));
550 //kbmap->bind("KP_7", FuncRequest(LFUN_SELFINSERT));
551 //kbmap->bind("KP_8", FuncRequest(LFUN_SELFINSERT));
552 //kbmap->bind("KP_9", FuncRequest(LFUN_SELFINSERT));
553 //kbmap->bind("KP_Divide", FuncRequest(LFUN_SELFINSERT));
554 //kbmap->bind("KP_Multiply", FuncRequest(LFUN_SELFINSERT));
555 //kbmap->bind("KP_Subtract", FuncRequest(LFUN_SELFINSERT));
556 kbmap->bind("KP_Right", FuncRequest(LFUN_RIGHT));
557 kbmap->bind("KP_Left", FuncRequest(LFUN_LEFT));
558 kbmap->bind("KP_Up", FuncRequest(LFUN_UP));
559 kbmap->bind("KP_Down", FuncRequest(LFUN_DOWN));
560 kbmap->bind("KP_Home", FuncRequest(LFUN_HOME));
561 kbmap->bind("KP_End", FuncRequest(LFUN_END));
562 kbmap->bind("KP_Prior", FuncRequest(LFUN_PRIOR));
563 kbmap->bind("KP_Next", FuncRequest(LFUN_NEXT));
565 kbmap->bind("C-Tab", FuncRequest(LFUN_CELL_SPLIT));
566 kbmap->bind("S-Tab", FuncRequest(LFUN_CELL_BACKWARD));
567 kbmap->bind("S-ISO_Left_Tab", FuncRequest(LFUN_CELL_BACKWARD));
571 void LyX::emergencyCleanup() const
573 // what to do about tmpfiles is non-obvious. we would
574 // like to delete any we find, but our lyxdir might
575 // contain documents etc. which might be helpful on
578 bufferlist.emergencyWriteAll();
580 lyxserver->emergencyCleanup();
584 void LyX::deadKeyBindings(kb_keymap * kbmap)
586 // bindKeyings for transparent handling of deadkeys
587 // The keysyms are gotten from XFree86 X11R6
588 kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACUTE));
589 kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_BREVE));
590 kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_CARON));
591 kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_CEDILLA));
592 kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_CIRCLE));
593 kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_CIRCUMFLEX));
594 kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_DOT));
595 kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_GRAVE));
596 kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_HUNG_UMLAUT));
597 kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_MACRON));
598 // nothing with this name
599 // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_SPECIAL_CARON);
600 kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_TILDE));
601 kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_UMLAUT));
602 // nothing with this name either...
603 //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_UNDERBAR));
604 kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_UNDERDOT));
605 kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_TIE));
606 kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_OGONEK));
610 bool LyX::queryUserLyXDir(bool explicit_userdir)
612 bool reconfigure = false;
614 // Does user directory exist?
615 if (fs::is_directory(package().user_support())) {
617 string const configure_script =
618 AddName(package().system_support(), "configure");
619 string const userDefaults =
620 AddName(package().user_support(), "lyxrc.defaults");
621 if (fs::exists(configure_script) &&
622 fs::exists(userDefaults) &&
623 fs::last_write_time(configure_script)
624 < fs::last_write_time(userDefaults)) {
630 first_start = !explicit_userdir;
632 // If the user specified explicitly a directory, ask whether
633 // to create it. If the user says "no", then exit.
634 if (explicit_userdir &&
636 _("Missing LyX support directory"),
637 bformat(_("You have specified a non-existent user "
638 "LyX directory, %1$s.\n"
639 "It is needed to keep your own configuration."),
640 package().user_support()),
642 _("&Create directory."),
644 lyxerr << _("No user LyX directory. Exiting.") << endl;
648 lyxerr << bformat(_("LyX: Creating directory %1$s"),
649 package().user_support())
653 if (!createDirectory(package().user_support(), 0755)) {
654 // Failed, so let's exit.
655 lyxerr << _("Failed to create directory. Exiting.")
664 void LyX::readRcFile(string const & name)
666 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
668 string const lyxrc_path = LibFileSearch(string(), name);
669 if (!lyxrc_path.empty()) {
671 lyxerr[Debug::INIT] << "Found " << name
672 << " in " << lyxrc_path << endl;
674 if (lyxrc.read(lyxrc_path) >= 0)
682 // Read the ui file `name'
683 void LyX::readUIFile(string const & name)
693 struct keyword_item uitags[ui_last - 1] = {
694 { "include", ui_include },
695 { "menuset", ui_menuset },
696 { "toolbar", ui_toolbar },
697 { "toolbars", ui_toolbars }
700 // Ensure that a file is read only once (prevents include loops)
701 static std::list<string> uifiles;
702 std::list<string>::const_iterator it = uifiles.begin();
703 std::list<string>::const_iterator end = uifiles.end();
704 it = std::find(it, end, name);
706 lyxerr[Debug::INIT] << "UI file '" << name
707 << "' has been read already. "
708 << "Is this an include loop?"
713 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
715 string const ui_path = LibFileSearch("ui", name, "ui");
717 if (ui_path.empty()) {
718 lyxerr[Debug::INIT] << "Could not find " << name << endl;
722 uifiles.push_back(name);
724 lyxerr[Debug::INIT] << "Found " << name
725 << " in " << ui_path << endl;
726 LyXLex lex(uitags, ui_last - 1);
727 lex.setFile(ui_path);
729 lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
733 if (lyxerr.debugging(Debug::PARSER))
734 lex.printTable(lyxerr);
740 string const file = lex.getString();
745 menubackend.read(lex);
749 toolbarbackend.read(lex);
753 toolbarbackend.readToolbars(lex);
757 if (!rtrim(lex.getString()).empty())
758 lex.printError("LyX::ReadUIFile: "
759 "Unknown menu tag: `$$Token'");
766 // Read the languages file `name'
767 void LyX::readLanguagesFile(string const & name)
769 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
771 string const lang_path = LibFileSearch(string(), name);
772 if (lang_path.empty()) {
776 languages.read(lang_path);
780 // Read the encodings file `name'
781 void LyX::readEncodingsFile(string const & name)
783 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
785 string const enc_path = LibFileSearch(string(), name);
786 if (enc_path.empty()) {
790 encodings.read(enc_path);
799 /// return the the number of arguments consumed
800 typedef boost::function<int(string const &, string const &)> cmd_helper;
802 int parse_dbg(string const & arg, string const &)
805 lyxerr << _("List of supported debug flags:") << endl;
806 Debug::showTags(lyxerr);
809 lyxerr << bformat(_("Setting debug level to %1$s"), arg) << endl;
811 lyxerr.level(Debug::value(arg));
812 Debug::showLevel(lyxerr, lyxerr.level());
817 int parse_help(string const &, string const &)
820 _("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
821 "Command line switches (case sensitive):\n"
822 "\t-help summarize LyX usage\n"
823 "\t-userdir dir try to set user directory to dir\n"
824 "\t-sysdir dir try to set system directory to dir\n"
825 "\t-geometry WxH+X+Y set geometry of the main window\n"
826 "\t-dbg feature[,feature]...\n"
827 " select the features to debug.\n"
828 " Type `lyx -dbg' to see the list of features\n"
829 "\t-x [--execute] command\n"
830 " where command is a lyx command.\n"
831 "\t-e [--export] fmt\n"
832 " where fmt is the export format of choice.\n"
833 "\t-i [--import] fmt file.xxx\n"
834 " where fmt is the import format of choice\n"
835 " and file.xxx is the file to be imported.\n"
836 "\t-version summarize version and build info\n"
837 "Check the LyX man page for more details.") << endl;
842 int parse_version(string const &, string const &)
844 lyxerr << "LyX " << lyx_version
845 << " of " << lyx_release_date << endl;
846 lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
848 lyxerr << lyx_version_info << endl;
853 int parse_sysdir(string const & arg, string const &)
856 lyxerr << _("Missing directory for -sysdir switch") << endl;
859 cl_system_support = arg;
863 int parse_userdir(string const & arg, string const &)
866 lyxerr << _("Missing directory for -userdir switch") << endl;
869 cl_user_support = arg;
873 int parse_execute(string const & arg, string const &)
876 lyxerr << _("Missing command string after --execute switch") << endl;
880 // Argh. Setting gui to false segfaults..
881 // FIXME: when ? how ?
886 int parse_export(string const & type, string const &)
889 lyxerr << _("Missing file type [eg latex, ps...] after "
890 "--export switch") << endl;
893 batch = "buffer-export " + type;
898 int parse_import(string const & type, string const & file)
901 lyxerr << _("Missing file type [eg latex, ps...] after "
902 "--import switch") << endl;
906 lyxerr << _("Missing filename for --import") << endl;
910 batch = "buffer-import " + type + ' ' + file;
917 bool LyX::easyParse(int & argc, char * argv[])
919 std::map<string, cmd_helper> cmdmap;
921 cmdmap["-dbg"] = parse_dbg;
922 cmdmap["-help"] = parse_help;
923 cmdmap["--help"] = parse_help;
924 cmdmap["-version"] = parse_version;
925 cmdmap["--version"] = parse_version;
926 cmdmap["-sysdir"] = parse_sysdir;
927 cmdmap["-userdir"] = parse_userdir;
928 cmdmap["-x"] = parse_execute;
929 cmdmap["--execute"] = parse_execute;
930 cmdmap["-e"] = parse_export;
931 cmdmap["--export"] = parse_export;
932 cmdmap["-i"] = parse_import;
933 cmdmap["--import"] = parse_import;
935 for (int i = 1; i < argc; ++i) {
936 std::map<string, cmd_helper>::const_iterator it
937 = cmdmap.find(argv[i]);
939 // don't complain if not found - may be parsed later
940 if (it == cmdmap.end())
943 string arg((i + 1 < argc) ? argv[i + 1] : "");
944 string arg2((i + 2 < argc) ? argv[i + 2] : "");
946 int const remove = 1 + it->second(arg, arg2);
948 // Now, remove used arguments by shifting
949 // the following ones remove places down.
951 for (int j = i; j < argc; ++j)
952 argv[j] = argv[j + remove];
956 batch_command = batch;