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 if (!lyxrc.path_prefix.empty())
481 prependEnvPath("PATH", lyxrc.path_prefix);
483 // Having reset the PATH we're now in a position to run configure
486 reconfigureUserLyXDir();
488 if (fs::exists(lyxrc.document_path) &&
489 fs::is_directory(lyxrc.document_path))
490 package().document_dir() = lyxrc.document_path;
492 package().temp_dir() = createLyXTmpDir(lyxrc.tempdir_path);
493 if (package().temp_dir().empty()) {
494 Alert::error(_("Could not create temporary directory"),
495 bformat(_("Could not create a temporary directory in\n"
496 "%1$s. Make sure that this\n"
497 "path exists and is writable and try again."),
498 lyxrc.tempdir_path));
499 // createLyXTmpDir() tries sufficiently hard to create a
500 // usable temp dir, so the probability to come here is
501 // close to zero. We therefore don't try to overcome this
502 // problem with e.g. asking the user for a new path and
503 // trying again but simply exit.
507 if (lyxerr.debugging(Debug::INIT)) {
508 lyxerr << "LyX tmp dir: `" << package().temp_dir() << '\'' << endl;
511 lyxerr[Debug::INIT] << "Reading lastfiles `"
512 << lyxrc.lastfiles << "'..." << endl;
513 lastfiles_.reset(new LastFiles(lyxrc.lastfiles,
514 lyxrc.check_lastfiles,
515 lyxrc.num_lastfiles));
519 void LyX::defaultKeyBindings(kb_keymap * kbmap)
521 kbmap->bind("Right", FuncRequest(LFUN_RIGHT));
522 kbmap->bind("Left", FuncRequest(LFUN_LEFT));
523 kbmap->bind("Up", FuncRequest(LFUN_UP));
524 kbmap->bind("Down", FuncRequest(LFUN_DOWN));
526 kbmap->bind("Tab", FuncRequest(LFUN_CELL_FORWARD));
527 kbmap->bind("ISO_Left_Tab", FuncRequest(LFUN_CELL_FORWARD));
529 kbmap->bind("Home", FuncRequest(LFUN_HOME));
530 kbmap->bind("End", FuncRequest(LFUN_END));
531 kbmap->bind("Prior", FuncRequest(LFUN_PRIOR));
532 kbmap->bind("Next", FuncRequest(LFUN_NEXT));
534 kbmap->bind("Return", FuncRequest(LFUN_BREAKPARAGRAPH));
535 //kbmap->bind("~C-~S-~M-nobreakspace", FuncRequest(LFUN_PROTECTEDSPACE));
537 kbmap->bind("Delete", FuncRequest(LFUN_DELETE));
538 kbmap->bind("BackSpace", FuncRequest(LFUN_BACKSPACE));
540 // kbmap->bindings to enable the use of the numeric keypad
542 //kbmap->bind("KP_0", FuncRequest(LFUN_SELFINSERT));
543 //kbmap->bind("KP_Decimal", FuncRequest(LFUN_SELFINSERT));
544 kbmap->bind("KP_Enter", FuncRequest(LFUN_BREAKPARAGRAPH));
545 //kbmap->bind("KP_1", FuncRequest(LFUN_SELFINSERT));
546 //kbmap->bind("KP_2", FuncRequest(LFUN_SELFINSERT));
547 //kbmap->bind("KP_3", FuncRequest(LFUN_SELFINSERT));
548 //kbmap->bind("KP_4", FuncRequest(LFUN_SELFINSERT));
549 //kbmap->bind("KP_5", FuncRequest(LFUN_SELFINSERT));
550 //kbmap->bind("KP_6", FuncRequest(LFUN_SELFINSERT));
551 //kbmap->bind("KP_Add", FuncRequest(LFUN_SELFINSERT));
552 //kbmap->bind("KP_7", FuncRequest(LFUN_SELFINSERT));
553 //kbmap->bind("KP_8", FuncRequest(LFUN_SELFINSERT));
554 //kbmap->bind("KP_9", FuncRequest(LFUN_SELFINSERT));
555 //kbmap->bind("KP_Divide", FuncRequest(LFUN_SELFINSERT));
556 //kbmap->bind("KP_Multiply", FuncRequest(LFUN_SELFINSERT));
557 //kbmap->bind("KP_Subtract", FuncRequest(LFUN_SELFINSERT));
558 kbmap->bind("KP_Right", FuncRequest(LFUN_RIGHT));
559 kbmap->bind("KP_Left", FuncRequest(LFUN_LEFT));
560 kbmap->bind("KP_Up", FuncRequest(LFUN_UP));
561 kbmap->bind("KP_Down", FuncRequest(LFUN_DOWN));
562 kbmap->bind("KP_Home", FuncRequest(LFUN_HOME));
563 kbmap->bind("KP_End", FuncRequest(LFUN_END));
564 kbmap->bind("KP_Prior", FuncRequest(LFUN_PRIOR));
565 kbmap->bind("KP_Next", FuncRequest(LFUN_NEXT));
567 kbmap->bind("C-Tab", FuncRequest(LFUN_CELL_SPLIT));
568 kbmap->bind("S-Tab", FuncRequest(LFUN_CELL_BACKWARD));
569 kbmap->bind("S-ISO_Left_Tab", FuncRequest(LFUN_CELL_BACKWARD));
573 void LyX::emergencyCleanup() const
575 // what to do about tmpfiles is non-obvious. we would
576 // like to delete any we find, but our lyxdir might
577 // contain documents etc. which might be helpful on
580 bufferlist.emergencyWriteAll();
582 lyxserver->emergencyCleanup();
586 void LyX::deadKeyBindings(kb_keymap * kbmap)
588 // bindKeyings for transparent handling of deadkeys
589 // The keysyms are gotten from XFree86 X11R6
590 kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACUTE));
591 kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_BREVE));
592 kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_CARON));
593 kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_CEDILLA));
594 kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_CIRCLE));
595 kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_CIRCUMFLEX));
596 kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_DOT));
597 kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_GRAVE));
598 kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_HUNG_UMLAUT));
599 kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_MACRON));
600 // nothing with this name
601 // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_SPECIAL_CARON);
602 kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_TILDE));
603 kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_UMLAUT));
604 // nothing with this name either...
605 //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_UNDERBAR));
606 kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_UNDERDOT));
607 kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_TIE));
608 kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_OGONEK));
612 bool LyX::queryUserLyXDir(bool explicit_userdir)
614 bool reconfigure = false;
616 // Does user directory exist?
617 if (fs::exists(package().user_support()) &&
618 fs::is_directory(package().user_support())) {
620 string const configure_script =
621 AddName(package().system_support(), "configure");
622 string const userDefaults =
623 AddName(package().user_support(), "lyxrc.defaults");
624 if (fs::exists(configure_script) &&
625 fs::exists(userDefaults) &&
626 fs::last_write_time(configure_script)
627 < fs::last_write_time(userDefaults)) {
633 first_start = !explicit_userdir;
635 // If the user specified explicitly a directory, ask whether
636 // to create it. If the user says "no", then exit.
637 if (explicit_userdir &&
639 _("Missing LyX support directory"),
640 bformat(_("You have specified a non-existent user "
641 "LyX directory, %1$s.\n"
642 "It is needed to keep your own configuration."),
643 package().user_support()),
645 _("&Create directory."),
647 lyxerr << _("No user LyX directory. Exiting.") << endl;
651 lyxerr << bformat(_("LyX: Creating directory %1$s"),
652 package().user_support())
656 if (!createDirectory(package().user_support(), 0755)) {
657 // Failed, so let's exit.
658 lyxerr << _("Failed to create directory. Exiting.")
667 void LyX::readRcFile(string const & name)
669 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
671 string const lyxrc_path = LibFileSearch(string(), name);
672 if (!lyxrc_path.empty()) {
674 lyxerr[Debug::INIT] << "Found " << name
675 << " in " << lyxrc_path << endl;
677 if (lyxrc.read(lyxrc_path) >= 0)
685 // Read the ui file `name'
686 void LyX::readUIFile(string const & name)
696 struct keyword_item uitags[ui_last - 1] = {
697 { "include", ui_include },
698 { "menuset", ui_menuset },
699 { "toolbar", ui_toolbar },
700 { "toolbars", ui_toolbars }
703 // Ensure that a file is read only once (prevents include loops)
704 static std::list<string> uifiles;
705 std::list<string>::const_iterator it = uifiles.begin();
706 std::list<string>::const_iterator end = uifiles.end();
707 it = std::find(it, end, name);
709 lyxerr[Debug::INIT] << "UI file '" << name
710 << "' has been read already. "
711 << "Is this an include loop?"
716 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
718 string const ui_path = LibFileSearch("ui", name, "ui");
720 if (ui_path.empty()) {
721 lyxerr[Debug::INIT] << "Could not find " << name << endl;
725 uifiles.push_back(name);
727 lyxerr[Debug::INIT] << "Found " << name
728 << " in " << ui_path << endl;
729 LyXLex lex(uitags, ui_last - 1);
730 lex.setFile(ui_path);
732 lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
736 if (lyxerr.debugging(Debug::PARSER))
737 lex.printTable(lyxerr);
743 string const file = lex.getString();
748 menubackend.read(lex);
752 toolbarbackend.read(lex);
756 toolbarbackend.readToolbars(lex);
760 if (!rtrim(lex.getString()).empty())
761 lex.printError("LyX::ReadUIFile: "
762 "Unknown menu tag: `$$Token'");
769 // Read the languages file `name'
770 void LyX::readLanguagesFile(string const & name)
772 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
774 string const lang_path = LibFileSearch(string(), name);
775 if (lang_path.empty()) {
779 languages.read(lang_path);
783 // Read the encodings file `name'
784 void LyX::readEncodingsFile(string const & name)
786 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
788 string const enc_path = LibFileSearch(string(), name);
789 if (enc_path.empty()) {
793 encodings.read(enc_path);
802 /// return the the number of arguments consumed
803 typedef boost::function<int(string const &, string const &)> cmd_helper;
805 int parse_dbg(string const & arg, string const &)
808 lyxerr << _("List of supported debug flags:") << endl;
809 Debug::showTags(lyxerr);
812 lyxerr << bformat(_("Setting debug level to %1$s"), arg) << endl;
814 lyxerr.level(Debug::value(arg));
815 Debug::showLevel(lyxerr, lyxerr.level());
820 int parse_help(string const &, string const &)
823 _("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
824 "Command line switches (case sensitive):\n"
825 "\t-help summarize LyX usage\n"
826 "\t-userdir dir try to set user directory to dir\n"
827 "\t-sysdir dir try to set system directory to dir\n"
828 "\t-geometry WxH+X+Y set geometry of the main window\n"
829 "\t-dbg feature[,feature]...\n"
830 " select the features to debug.\n"
831 " Type `lyx -dbg' to see the list of features\n"
832 "\t-x [--execute] command\n"
833 " where command is a lyx command.\n"
834 "\t-e [--export] fmt\n"
835 " where fmt is the export format of choice.\n"
836 "\t-i [--import] fmt file.xxx\n"
837 " where fmt is the import format of choice\n"
838 " and file.xxx is the file to be imported.\n"
839 "\t-version summarize version and build info\n"
840 "Check the LyX man page for more details.") << endl;
845 int parse_version(string const &, string const &)
847 lyxerr << "LyX " << lyx_version
848 << " of " << lyx_release_date << endl;
849 lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
851 lyxerr << lyx_version_info << endl;
856 int parse_sysdir(string const & arg, string const &)
859 lyxerr << _("Missing directory for -sysdir switch") << endl;
862 cl_system_support = arg;
866 int parse_userdir(string const & arg, string const &)
869 lyxerr << _("Missing directory for -userdir switch") << endl;
872 cl_user_support = arg;
876 int parse_execute(string const & arg, string const &)
879 lyxerr << _("Missing command string after --execute switch") << endl;
883 // Argh. Setting gui to false segfaults..
884 // FIXME: when ? how ?
889 int parse_export(string const & type, string const &)
892 lyxerr << _("Missing file type [eg latex, ps...] after "
893 "--export switch") << endl;
896 batch = "buffer-export " + type;
901 int parse_import(string const & type, string const & file)
904 lyxerr << _("Missing file type [eg latex, ps...] after "
905 "--import switch") << endl;
909 lyxerr << _("Missing filename for --import") << endl;
913 batch = "buffer-import " + type + ' ' + file;
920 bool LyX::easyParse(int & argc, char * argv[])
922 std::map<string, cmd_helper> cmdmap;
924 cmdmap["-dbg"] = parse_dbg;
925 cmdmap["-help"] = parse_help;
926 cmdmap["--help"] = parse_help;
927 cmdmap["-version"] = parse_version;
928 cmdmap["--version"] = parse_version;
929 cmdmap["-sysdir"] = parse_sysdir;
930 cmdmap["-userdir"] = parse_userdir;
931 cmdmap["-x"] = parse_execute;
932 cmdmap["--execute"] = parse_execute;
933 cmdmap["-e"] = parse_export;
934 cmdmap["--export"] = parse_export;
935 cmdmap["-i"] = parse_import;
936 cmdmap["--import"] = parse_import;
938 for (int i = 1; i < argc; ++i) {
939 std::map<string, cmd_helper>::const_iterator it
940 = cmdmap.find(argv[i]);
942 // don't complain if not found - may be parsed later
943 if (it == cmdmap.end())
946 string arg((i + 1 < argc) ? argv[i + 1] : "");
947 string arg2((i + 2 < argc) ? argv[i + 2] : "");
949 int const remove = 1 + it->second(arg, arg2);
951 // Now, remove used arguments by shifting
952 // the following ones remove places down.
954 for (int j = i; j < argc; ++j)
955 argv[j] = argv[j + remove];
959 batch_command = batch;