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(os::internal_path(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
282 lyx_gui::start(batch_command, files);
284 // Something went wrong above
294 The SIGHUP signal does not exist on Windows and does not need to be handled.
296 Windows handles SIGFPE and SIGSEGV signals as expected.
298 Cntl+C interrupts (mapped to SIGINT by Windows' POSIX compatability layer)
299 cause a new thread to be spawned. This may well result in unexpected
300 behaviour by the single-threaded LyX.
302 SIGTERM signals will come only from another process actually sending
303 that signal using 'raise' in Windows' POSIX compatability layer. It will
304 not come from the general "terminate process" methods that everyone
305 actually uses (and which can't be trapped). Killing an app 'politely' on
306 Windows involves first sending a WM_CLOSE message, something that is
307 caught already by the Qt frontend.
309 For more information see:
311 http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/2034055
312 ...signals are mostly useless on Windows for a variety of reasons that are
315 'UNIX Application Migration Guide, Chapter 9'
316 http://msdn.microsoft.com/library/en-us/dnucmg/html/UCMGch09.asp
318 'How To Terminate an Application "Cleanly" in Win32'
319 http://support.microsoft.com/default.aspx?scid=kb;en-us;178893
323 static void error_handler(int err_sig)
325 // Throw away any signals other than the first one received.
326 static sig_atomic_t handling_error = false;
329 handling_error = true;
331 // We have received a signal indicating a fatal error, so
332 // try and save the data ASAP.
333 LyX::cref().emergencyCleanup();
335 // These lyxerr calls may or may not work:
337 // Signals are asynchronous, so the main program may be in a very
338 // fragile state when a signal is processed and thus while a signal
339 // handler function executes.
340 // In general, therefore, we should avoid performing any
341 // I/O operations or calling most library and system functions from
344 // This shouldn't matter here, however, as we've already invoked
349 lyxerr << "\nlyx: SIGHUP signal caught\nBye." << endl;
353 lyxerr << "\nlyx: SIGFPE signal caught\nBye." << endl;
356 lyxerr << "\nlyx: SIGSEGV signal caught\n"
357 "Sorry, you have found a bug in LyX. "
358 "Please read the bug-reporting instructions "
359 "in Help->Introduction and send us a bug report, "
360 "if necessary. Thanks !\nBye." << endl;
368 // Deinstall the signal handlers
370 signal(SIGHUP, SIG_DFL);
372 signal(SIGINT, SIG_DFL);
373 signal(SIGFPE, SIG_DFL);
374 signal(SIGSEGV, SIG_DFL);
375 signal(SIGTERM, SIG_DFL);
378 if (err_sig == SIGSEGV ||
379 (err_sig != SIGHUP && !getEnv("LYXDEBUG").empty()))
381 if (err_sig == SIGSEGV || !getEnv("LYXDEBUG").empty())
383 lyx::support::abort();
390 void LyX::printError(ErrorItem const & ei)
392 std::cerr << _("LyX: ") << ei.error
393 << ':' << ei.description << std::endl;
398 void LyX::init(bool gui)
401 signal(SIGHUP, error_handler);
403 signal(SIGFPE, error_handler);
404 signal(SIGSEGV, error_handler);
405 signal(SIGINT, error_handler);
406 signal(SIGTERM, error_handler);
407 // SIGPIPE can be safely ignored.
409 #if !defined (USE_POSIX_PACKAGING)
410 // Add the directory containing the LyX executable to the path
411 // so that LyX can find things like reLyX.
412 if (package().build_support().empty())
413 prependEnvPath("PATH", package().binary_dir());
416 // Check that user LyX directory is ok. We don't do that if
417 // running in batch mode.
418 bool reconfigure = false;
421 queryUserLyXDir(package().explicit_user_support());
426 // Disable gui when easyparse says so
427 lyx_gui::use_gui = gui;
429 lyxrc.tempdir_path = package().temp_dir();
430 lyxrc.document_path = package().document_dir();
432 if (lyxrc.template_path.empty()) {
433 lyxrc.template_path = AddPath(package().system_support(),
437 if (lyxrc.lastfiles.empty()) {
438 lyxrc.lastfiles = AddName(package().user_support(), "lastfiles");
441 if (lyxrc.roman_font_name.empty())
442 lyxrc.roman_font_name = lyx_gui::roman_font_name();
443 if (lyxrc.sans_font_name.empty())
444 lyxrc.sans_font_name = lyx_gui::sans_font_name();
445 if (lyxrc.typewriter_font_name.empty())
446 lyxrc.typewriter_font_name = lyx_gui::typewriter_font_name();
449 // Read configuration files
452 readRcFile("lyxrc.defaults");
453 system_lyxrc = lyxrc;
454 system_formats = formats;
455 system_converters = converters;
456 system_movers = movers;
457 system_lcolor = lcolor;
459 string prefsfile = "preferences";
460 // back compatibility to lyxs < 1.1.6
461 if (LibFileSearch(string(), prefsfile).empty())
463 if (!LibFileSearch(string(), prefsfile).empty())
464 readRcFile(prefsfile);
466 readEncodingsFile("encodings");
467 readLanguagesFile("languages");
470 lyxerr[Debug::INIT] << "Reading layouts..." << endl;
475 toplevel_keymap.reset(new kb_keymap);
476 defaultKeyBindings(toplevel_keymap.get());
477 toplevel_keymap->read(lyxrc.bind_file);
480 readUIFile(lyxrc.ui_file);
483 if (lyxerr.debugging(Debug::LYXRC))
486 os::cygwin_path_fix(lyxrc.cygwin_path_fix);
487 if (!lyxrc.path_prefix.empty())
488 prependEnvPath("PATH", lyxrc.path_prefix);
490 // Having reset the PATH we're now in a position to run configure
493 reconfigureUserLyXDir();
495 if (fs::exists(lyxrc.document_path) &&
496 fs::is_directory(lyxrc.document_path))
497 package().document_dir() = lyxrc.document_path;
499 package().temp_dir() = createLyXTmpDir(lyxrc.tempdir_path);
500 if (package().temp_dir().empty()) {
501 Alert::error(_("Could not create temporary directory"),
502 bformat(_("Could not create a temporary directory in\n"
503 "%1$s. Make sure that this\n"
504 "path exists and is writable and try again."),
505 lyxrc.tempdir_path));
506 // createLyXTmpDir() tries sufficiently hard to create a
507 // usable temp dir, so the probability to come here is
508 // close to zero. We therefore don't try to overcome this
509 // problem with e.g. asking the user for a new path and
510 // trying again but simply exit.
514 if (lyxerr.debugging(Debug::INIT)) {
515 lyxerr << "LyX tmp dir: `" << package().temp_dir() << '\'' << endl;
518 lyxerr[Debug::INIT] << "Reading lastfiles `"
519 << lyxrc.lastfiles << "'..." << endl;
520 lastfiles_.reset(new LastFiles(lyxrc.lastfiles,
521 lyxrc.check_lastfiles,
522 lyxrc.num_lastfiles));
526 void LyX::defaultKeyBindings(kb_keymap * kbmap)
528 kbmap->bind("Right", FuncRequest(LFUN_RIGHT));
529 kbmap->bind("Left", FuncRequest(LFUN_LEFT));
530 kbmap->bind("Up", FuncRequest(LFUN_UP));
531 kbmap->bind("Down", FuncRequest(LFUN_DOWN));
533 kbmap->bind("Tab", FuncRequest(LFUN_CELL_FORWARD));
534 kbmap->bind("C-Tab", FuncRequest(LFUN_CELL_SPLIT));
535 kbmap->bind("~S-ISO_Left_Tab", FuncRequest(LFUN_CELL_BACKWARD));
536 kbmap->bind("~S-BackTab", FuncRequest(LFUN_CELL_BACKWARD));
538 kbmap->bind("Home", FuncRequest(LFUN_HOME));
539 kbmap->bind("End", FuncRequest(LFUN_END));
540 kbmap->bind("Prior", FuncRequest(LFUN_PRIOR));
541 kbmap->bind("Next", FuncRequest(LFUN_NEXT));
543 kbmap->bind("Return", FuncRequest(LFUN_BREAKPARAGRAPH));
544 //kbmap->bind("~C-~S-~M-nobreakspace", FuncRequest(LFUN_PROTECTEDSPACE));
546 kbmap->bind("Delete", FuncRequest(LFUN_DELETE));
547 kbmap->bind("BackSpace", FuncRequest(LFUN_BACKSPACE));
549 // kbmap->bindings to enable the use of the numeric keypad
551 //kbmap->bind("KP_0", FuncRequest(LFUN_SELFINSERT));
552 //kbmap->bind("KP_Decimal", FuncRequest(LFUN_SELFINSERT));
553 kbmap->bind("KP_Enter", FuncRequest(LFUN_BREAKPARAGRAPH));
554 //kbmap->bind("KP_1", FuncRequest(LFUN_SELFINSERT));
555 //kbmap->bind("KP_2", FuncRequest(LFUN_SELFINSERT));
556 //kbmap->bind("KP_3", FuncRequest(LFUN_SELFINSERT));
557 //kbmap->bind("KP_4", FuncRequest(LFUN_SELFINSERT));
558 //kbmap->bind("KP_5", FuncRequest(LFUN_SELFINSERT));
559 //kbmap->bind("KP_6", FuncRequest(LFUN_SELFINSERT));
560 //kbmap->bind("KP_Add", FuncRequest(LFUN_SELFINSERT));
561 //kbmap->bind("KP_7", FuncRequest(LFUN_SELFINSERT));
562 //kbmap->bind("KP_8", FuncRequest(LFUN_SELFINSERT));
563 //kbmap->bind("KP_9", FuncRequest(LFUN_SELFINSERT));
564 //kbmap->bind("KP_Divide", FuncRequest(LFUN_SELFINSERT));
565 //kbmap->bind("KP_Multiply", FuncRequest(LFUN_SELFINSERT));
566 //kbmap->bind("KP_Subtract", FuncRequest(LFUN_SELFINSERT));
567 kbmap->bind("KP_Right", FuncRequest(LFUN_RIGHT));
568 kbmap->bind("KP_Left", FuncRequest(LFUN_LEFT));
569 kbmap->bind("KP_Up", FuncRequest(LFUN_UP));
570 kbmap->bind("KP_Down", FuncRequest(LFUN_DOWN));
571 kbmap->bind("KP_Home", FuncRequest(LFUN_HOME));
572 kbmap->bind("KP_End", FuncRequest(LFUN_END));
573 kbmap->bind("KP_Prior", FuncRequest(LFUN_PRIOR));
574 kbmap->bind("KP_Next", FuncRequest(LFUN_NEXT));
578 void LyX::emergencyCleanup() const
580 // what to do about tmpfiles is non-obvious. we would
581 // like to delete any we find, but our lyxdir might
582 // contain documents etc. which might be helpful on
585 bufferlist.emergencyWriteAll();
587 lyxserver->emergencyCleanup();
591 void LyX::deadKeyBindings(kb_keymap * kbmap)
593 // bindKeyings for transparent handling of deadkeys
594 // The keysyms are gotten from XFree86 X11R6
595 kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACUTE));
596 kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_BREVE));
597 kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_CARON));
598 kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_CEDILLA));
599 kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_CIRCLE));
600 kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_CIRCUMFLEX));
601 kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_DOT));
602 kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_GRAVE));
603 kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_HUNG_UMLAUT));
604 kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_MACRON));
605 // nothing with this name
606 // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_SPECIAL_CARON);
607 kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_TILDE));
608 kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_UMLAUT));
609 // nothing with this name either...
610 //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_UNDERBAR));
611 kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_UNDERDOT));
612 kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_TIE));
613 kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_OGONEK));
617 bool LyX::queryUserLyXDir(bool explicit_userdir)
619 bool reconfigure = false;
621 // Does user directory exist?
622 if (fs::exists(package().user_support()) &&
623 fs::is_directory(package().user_support())) {
625 string const configure_script =
626 AddName(package().system_support(), "configure");
627 string const userDefaults =
628 AddName(package().user_support(), "lyxrc.defaults");
629 if (fs::exists(configure_script) &&
630 fs::exists(userDefaults) &&
631 fs::last_write_time(configure_script)
632 > fs::last_write_time(userDefaults)) {
638 first_start = !explicit_userdir;
640 // If the user specified explicitly a directory, ask whether
641 // to create it. If the user says "no", then exit.
642 if (explicit_userdir &&
644 _("Missing LyX support directory"),
645 bformat(_("You have specified a non-existent user "
646 "LyX directory, %1$s.\n"
647 "It is needed to keep your own configuration."),
648 package().user_support()),
650 _("&Create directory."),
652 lyxerr << _("No user LyX directory. Exiting.") << endl;
656 lyxerr << bformat(_("LyX: Creating directory %1$s"),
657 package().user_support())
661 if (!createDirectory(package().user_support(), 0755)) {
662 // Failed, so let's exit.
663 lyxerr << _("Failed to create directory. Exiting.")
672 void LyX::readRcFile(string const & name)
674 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
676 string const lyxrc_path = LibFileSearch(string(), name);
677 if (!lyxrc_path.empty()) {
679 lyxerr[Debug::INIT] << "Found " << name
680 << " in " << lyxrc_path << endl;
682 if (lyxrc.read(lyxrc_path) >= 0)
690 // Read the ui file `name'
691 void LyX::readUIFile(string const & name)
701 struct keyword_item uitags[ui_last - 1] = {
702 { "include", ui_include },
703 { "menuset", ui_menuset },
704 { "toolbar", ui_toolbar },
705 { "toolbars", ui_toolbars }
708 // Ensure that a file is read only once (prevents include loops)
709 static std::list<string> uifiles;
710 std::list<string>::const_iterator it = uifiles.begin();
711 std::list<string>::const_iterator end = uifiles.end();
712 it = std::find(it, end, name);
714 lyxerr[Debug::INIT] << "UI file '" << name
715 << "' has been read already. "
716 << "Is this an include loop?"
721 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
723 string const ui_path = LibFileSearch("ui", name, "ui");
725 if (ui_path.empty()) {
726 lyxerr[Debug::INIT] << "Could not find " << name << endl;
730 uifiles.push_back(name);
732 lyxerr[Debug::INIT] << "Found " << name
733 << " in " << ui_path << endl;
734 LyXLex lex(uitags, ui_last - 1);
735 lex.setFile(ui_path);
737 lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
741 if (lyxerr.debugging(Debug::PARSER))
742 lex.printTable(lyxerr);
748 string const file = lex.getString();
753 menubackend.read(lex);
757 toolbarbackend.read(lex);
761 toolbarbackend.readToolbars(lex);
765 if (!rtrim(lex.getString()).empty())
766 lex.printError("LyX::ReadUIFile: "
767 "Unknown menu tag: `$$Token'");
774 // Read the languages file `name'
775 void LyX::readLanguagesFile(string const & name)
777 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
779 string const lang_path = LibFileSearch(string(), name);
780 if (lang_path.empty()) {
784 languages.read(lang_path);
788 // Read the encodings file `name'
789 void LyX::readEncodingsFile(string const & name)
791 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
793 string const enc_path = LibFileSearch(string(), name);
794 if (enc_path.empty()) {
798 encodings.read(enc_path);
807 /// return the the number of arguments consumed
808 typedef boost::function<int(string const &, string const &)> cmd_helper;
810 int parse_dbg(string const & arg, string const &)
813 lyxerr << _("List of supported debug flags:") << endl;
814 Debug::showTags(lyxerr);
817 lyxerr << bformat(_("Setting debug level to %1$s"), arg) << endl;
819 lyxerr.level(Debug::value(arg));
820 Debug::showLevel(lyxerr, lyxerr.level());
825 int parse_help(string const &, string const &)
828 _("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
829 "Command line switches (case sensitive):\n"
830 "\t-help summarize LyX usage\n"
831 "\t-userdir dir try to set user directory to dir\n"
832 "\t-sysdir dir try to set system directory to dir\n"
833 "\t-geometry WxH+X+Y set geometry of the main window\n"
834 "\t-dbg feature[,feature]...\n"
835 " select the features to debug.\n"
836 " Type `lyx -dbg' to see the list of features\n"
837 "\t-x [--execute] command\n"
838 " where command is a lyx command.\n"
839 "\t-e [--export] fmt\n"
840 " where fmt is the export format of choice.\n"
841 "\t-i [--import] fmt file.xxx\n"
842 " where fmt is the import format of choice\n"
843 " and file.xxx is the file to be imported.\n"
844 "\t-version summarize version and build info\n"
845 "Check the LyX man page for more details.") << endl;
850 int parse_version(string const &, string const &)
852 lyxerr << "LyX " << lyx_version
853 << " of " << lyx_release_date << endl;
854 lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
856 lyxerr << lyx_version_info << endl;
861 int parse_sysdir(string const & arg, string const &)
864 lyxerr << _("Missing directory for -sysdir switch") << endl;
867 cl_system_support = arg;
871 int parse_userdir(string const & arg, string const &)
874 lyxerr << _("Missing directory for -userdir switch") << endl;
877 cl_user_support = arg;
881 int parse_execute(string const & arg, string const &)
884 lyxerr << _("Missing command string after --execute switch") << endl;
892 int parse_export(string const & type, string const &)
895 lyxerr << _("Missing file type [eg latex, ps...] after "
896 "--export switch") << endl;
899 batch = "buffer-export " + type;
904 int parse_import(string const & type, string const & file)
907 lyxerr << _("Missing file type [eg latex, ps...] after "
908 "--import switch") << endl;
912 lyxerr << _("Missing filename for --import") << endl;
916 batch = "buffer-import " + type + ' ' + file;
923 bool LyX::easyParse(int & argc, char * argv[])
925 std::map<string, cmd_helper> cmdmap;
927 cmdmap["-dbg"] = parse_dbg;
928 cmdmap["-help"] = parse_help;
929 cmdmap["--help"] = parse_help;
930 cmdmap["-version"] = parse_version;
931 cmdmap["--version"] = parse_version;
932 cmdmap["-sysdir"] = parse_sysdir;
933 cmdmap["-userdir"] = parse_userdir;
934 cmdmap["-x"] = parse_execute;
935 cmdmap["--execute"] = parse_execute;
936 cmdmap["-e"] = parse_export;
937 cmdmap["--export"] = parse_export;
938 cmdmap["-i"] = parse_import;
939 cmdmap["--import"] = parse_import;
941 for (int i = 1; i < argc; ++i) {
942 std::map<string, cmd_helper>::const_iterator it
943 = cmdmap.find(argv[i]);
945 // don't complain if not found - may be parsed later
946 if (it == cmdmap.end())
949 string arg((i + 1 < argc) ? argv[i + 1] : "");
950 string arg2((i + 2 < argc) ? argv[i + 2] : "");
952 int const remove = 1 + it->second(arg, arg2);
954 // Now, remove used arguments by shifting
955 // the following ones remove places down.
957 for (int j = i; j < argc; ++j)
958 argv[j] = argv[j + remove];
962 batch_command = batch;