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/FileInfo.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>
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::FileInfo;
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;
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);
211 lyx_gui::parse_init(argc, argv);
213 // check for any spurious extra arguments
214 // other than documents
215 for (int argi = 1; argi < argc ; ++argi) {
216 if (argv[argi][0] == '-') {
217 lyxerr << bformat(_("Wrong command line option `%1$s'. Exiting."),
223 // Initialization of LyX (reads lyxrc and more)
224 lyxerr[Debug::INIT] << "Initializing LyX::init..." << endl;
226 lyxerr[Debug::INIT] << "Initializing LyX::init...done" << endl;
229 lyx_gui::parse_lyxrc();
233 vector<string> files;
235 for (int argi = argc - 1; argi >= 1; --argi)
236 files.push_back(argv[argi]);
239 files.push_back(i18nLibFileSearch("examples", "splash.lyx"));
241 // Execute batch commands if available
242 if (!batch_command.empty()) {
244 lyxerr[Debug::INIT] << "About to handle -x '"
245 << batch_command << '\'' << endl;
247 Buffer * last_loaded = 0;
249 vector<string>::const_iterator it = files.begin();
250 vector<string>::const_iterator end = files.end();
252 for (; it != end; ++it) {
253 // get absolute path of file and add ".lyx" to
254 // the filename if necessary
255 string s = FileSearch(string(), *it, "lyx");
257 last_loaded = newFile(*it, string(), true);
259 Buffer * buf = bufferlist.newBuffer(s, false);
260 buf->error.connect(boost::bind(&LyX::printError, this, _1));
261 if (loadLyXFile(buf, s))
264 bufferlist.release(buf);
268 // try to dispatch to last loaded buffer first
270 bool success = false;
271 if (last_loaded->dispatch(batch_command, &success)) {
276 files.clear(); // the files are already loaded
279 lyx_gui::start(batch_command, files);
286 The SIGHUP signal does not exist on Windows and does not need to be handled.
288 Windows handles SIGFPE and SIGSEGV signals as expected.
290 Cntl+C interrupts (mapped to SIGINT by Windows' POSIX compatability layer)
291 cause a new thread to be spawned. This may well result in unexpected
292 behaviour by the single-threaded LyX.
294 SIGTERM signals will come only from another process actually sending
295 that signal using 'raise' in Windows' POSIX compatability layer. It will
296 not come from the general "terminate process" methods that everyone
297 actually uses (and which can't be trapped). Killing an app 'politely' on
298 Windows involves first sending a WM_CLOSE message, something that is
299 caught already by the Qt frontend.
301 For more information see:
303 http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/2034055
304 ...signals are mostly useless on Windows for a variety of reasons that are
307 'UNIX Application Migration Guide, Chapter 9'
308 http://msdn.microsoft.com/library/en-us/dnucmg/html/UCMGch09.asp
310 'How To Terminate an Application "Cleanly" in Win32'
311 http://support.microsoft.com/default.aspx?scid=kb;en-us;178893
315 static void error_handler(int err_sig)
317 // Throw away any signals other than the first one received.
318 static sig_atomic_t handling_error = false;
321 handling_error = true;
323 // We have received a signal indicating a fatal error, so
324 // try and save the data ASAP.
325 LyX::cref().emergencyCleanup();
327 // These lyxerr calls may or may not work:
329 // Signals are asynchronous, so the main program may be in a very
330 // fragile state when a signal is processed and thus while a signal
331 // handler function executes.
332 // In general, therefore, we should avoid performing any
333 // I/O operations or calling most library and system functions from
336 // This shouldn't matter here, however, as we've already invoked
341 lyxerr << "\nlyx: SIGHUP signal caught\nBye." << endl;
345 lyxerr << "\nlyx: SIGFPE signal caught\nBye." << endl;
348 lyxerr << "\nlyx: SIGSEGV signal caught\n"
349 "Sorry, you have found a bug in LyX. "
350 "Please read the bug-reporting instructions "
351 "in Help->Introduction and send us a bug report, "
352 "if necessary. Thanks !\nBye." << endl;
360 // Deinstall the signal handlers
362 signal(SIGHUP, SIG_DFL);
364 signal(SIGINT, SIG_DFL);
365 signal(SIGFPE, SIG_DFL);
366 signal(SIGSEGV, SIG_DFL);
367 signal(SIGTERM, SIG_DFL);
370 if (err_sig == SIGSEGV ||
371 (err_sig != SIGHUP && !GetEnv("LYXDEBUG").empty()))
373 if (err_sig == SIGSEGV || !GetEnv("LYXDEBUG").empty())
375 lyx::support::abort();
382 void LyX::printError(ErrorItem const & ei)
384 std::cerr << _("LyX: ") << ei.error
385 << ':' << ei.description << std::endl;
390 void LyX::init(bool gui)
393 signal(SIGHUP, error_handler);
395 signal(SIGFPE, error_handler);
396 signal(SIGSEGV, error_handler);
397 signal(SIGINT, error_handler);
398 signal(SIGTERM, error_handler);
399 // SIGPIPE can be safely ignored.
401 #if !defined (USE_POSIX_PACKAGING)
402 // Add the directory containing the LyX executable to the path
403 // so that LyX can find things like reLyX.
404 if (package.build_support().empty())
405 prependEnvPath("PATH", package.binary_dir());
408 // Check that user LyX directory is ok. We don't do that if
409 // running in batch mode.
410 bool reconfigure = false;
413 queryUserLyXDir(package().explicit_user_support());
418 // Disable gui when easyparse says so
419 lyx_gui::use_gui = gui;
421 lyxrc.tempdir_path = package().temp_dir();
422 lyxrc.document_path = package().document_dir();
424 if (lyxrc.template_path.empty()) {
425 lyxrc.template_path = AddPath(package().system_support(),
429 if (lyxrc.lastfiles.empty()) {
430 lyxrc.lastfiles = AddName(package().user_support(), "lastfiles");
433 if (lyxrc.roman_font_name.empty())
434 lyxrc.roman_font_name = lyx_gui::roman_font_name();
435 if (lyxrc.sans_font_name.empty())
436 lyxrc.sans_font_name = lyx_gui::sans_font_name();
437 if (lyxrc.typewriter_font_name.empty())
438 lyxrc.typewriter_font_name = lyx_gui::typewriter_font_name();
441 // Read configuration files
444 readRcFile("lyxrc.defaults");
445 system_lyxrc = lyxrc;
446 system_formats = formats;
447 system_converters = converters;
448 system_movers = movers;
449 system_lcolor = lcolor;
451 string prefsfile = "preferences";
452 // back compatibility to lyxs < 1.1.6
453 if (LibFileSearch(string(), prefsfile).empty())
455 if (!LibFileSearch(string(), prefsfile).empty())
456 readRcFile(prefsfile);
458 readEncodingsFile("encodings");
459 readLanguagesFile("languages");
462 lyxerr[Debug::INIT] << "Reading layouts..." << endl;
467 toplevel_keymap.reset(new kb_keymap);
468 defaultKeyBindings(toplevel_keymap.get());
469 toplevel_keymap->read(lyxrc.bind_file);
472 readUIFile(lyxrc.ui_file);
475 if (lyxerr.debugging(Debug::LYXRC))
478 os::cygwin_path_fix(lyxrc.cygwin_path_fix);
479 prependEnvPath("PATH", lyxrc.path_prefix);
481 // Having reset the PATH we're now in a position to run configure
484 reconfigureUserLyXDir();
486 FileInfo fi(lyxrc.document_path);
487 if (fi.isOK() && fi.isDir())
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 FileInfo fileInfo(package().user_support());
616 if (fileInfo.isOK() && fileInfo.isDir()) {
618 string const configure_script =
619 AddName(package().system_support(), "configure");
620 FileInfo script(configure_script);
621 FileInfo defaults(AddName(package().user_support(), "lyxrc.defaults"));
622 if (defaults.isOK() && script.isOK()
623 && defaults.getModificationTime() < script.getModificationTime()) {
629 first_start = !explicit_userdir;
631 // If the user specified explicitly a directory, ask whether
632 // to create it. If the user says "no", then exit.
633 if (explicit_userdir &&
635 _("Missing LyX support directory"),
636 bformat(_("You have specified a non-existent user "
637 "LyX directory, %1$s.\n"
638 "It is needed to keep your own configuration."),
639 package().user_support()),
641 _("&Create directory."),
643 lyxerr << _("No user LyX directory. Exiting.") << endl;
647 lyxerr << bformat(_("LyX: Creating directory %1$s"),
648 package().user_support())
652 if (!createDirectory(package().user_support(), 0755)) {
653 // Failed, so let's exit.
654 lyxerr << _("Failed to create directory. Exiting.")
663 void LyX::readRcFile(string const & name)
665 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
667 string const lyxrc_path = LibFileSearch(string(), name);
668 if (!lyxrc_path.empty()) {
670 lyxerr[Debug::INIT] << "Found " << name
671 << " in " << lyxrc_path << endl;
673 if (lyxrc.read(lyxrc_path) >= 0)
681 // Read the ui file `name'
682 void LyX::readUIFile(string const & name)
692 struct keyword_item uitags[ui_last - 1] = {
693 { "include", ui_include },
694 { "menuset", ui_menuset },
695 { "toolbar", ui_toolbar },
696 { "toolbars", ui_toolbars }
699 // Ensure that a file is read only once (prevents include loops)
700 static std::list<string> uifiles;
701 std::list<string>::const_iterator it = uifiles.begin();
702 std::list<string>::const_iterator end = uifiles.end();
703 it = std::find(it, end, name);
705 lyxerr[Debug::INIT] << "UI file '" << name
706 << "' has been read already. "
707 << "Is this an include loop?"
712 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
714 string const ui_path = LibFileSearch("ui", name, "ui");
716 if (ui_path.empty()) {
717 lyxerr[Debug::INIT] << "Could not find " << name << endl;
721 uifiles.push_back(name);
723 lyxerr[Debug::INIT] << "Found " << name
724 << " in " << ui_path << endl;
725 LyXLex lex(uitags, ui_last - 1);
726 lex.setFile(ui_path);
728 lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
732 if (lyxerr.debugging(Debug::PARSER))
733 lex.printTable(lyxerr);
739 string const file = lex.getString();
744 menubackend.read(lex);
748 toolbarbackend.read(lex);
752 toolbarbackend.readToolbars(lex);
756 if (!rtrim(lex.getString()).empty())
757 lex.printError("LyX::ReadUIFile: "
758 "Unknown menu tag: `$$Token'");
765 // Read the languages file `name'
766 void LyX::readLanguagesFile(string const & name)
768 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
770 string const lang_path = LibFileSearch(string(), name);
771 if (lang_path.empty()) {
775 languages.read(lang_path);
779 // Read the encodings file `name'
780 void LyX::readEncodingsFile(string const & name)
782 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
784 string const enc_path = LibFileSearch(string(), name);
785 if (enc_path.empty()) {
789 encodings.read(enc_path);
798 /// return the the number of arguments consumed
799 typedef boost::function<int(string const &, string const &)> cmd_helper;
801 int parse_dbg(string const & arg, string const &)
804 lyxerr << _("List of supported debug flags:") << endl;
805 Debug::showTags(lyxerr);
808 lyxerr << bformat(_("Setting debug level to %1$s"), arg) << endl;
810 lyxerr.level(Debug::value(arg));
811 Debug::showLevel(lyxerr, lyxerr.level());
816 int parse_help(string const &, string const &)
819 _("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
820 "Command line switches (case sensitive):\n"
821 "\t-help summarize LyX usage\n"
822 "\t-userdir dir try to set user directory to dir\n"
823 "\t-sysdir dir try to set system directory to dir\n"
824 "\t-geometry WxH+X+Y set geometry of the main window\n"
825 "\t-dbg feature[,feature]...\n"
826 " select the features to debug.\n"
827 " Type `lyx -dbg' to see the list of features\n"
828 "\t-x [--execute] command\n"
829 " where command is a lyx command.\n"
830 "\t-e [--export] fmt\n"
831 " where fmt is the export format of choice.\n"
832 "\t-i [--import] fmt file.xxx\n"
833 " where fmt is the import format of choice\n"
834 " and file.xxx is the file to be imported.\n"
835 "\t-version summarize version and build info\n"
836 "Check the LyX man page for more details.") << endl;
841 int parse_version(string const &, string const &)
843 lyxerr << "LyX " << lyx_version
844 << " of " << lyx_release_date << endl;
845 lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
847 lyxerr << lyx_version_info << endl;
852 int parse_sysdir(string const & arg, string const &)
855 lyxerr << _("Missing directory for -sysdir switch") << endl;
858 cl_system_support = arg;
862 int parse_userdir(string const & arg, string const &)
865 lyxerr << _("Missing directory for -userdir switch") << endl;
868 cl_user_support = arg;
872 int parse_execute(string const & arg, string const &)
875 lyxerr << _("Missing command string after --execute switch") << endl;
879 // Argh. Setting gui to false segfaults..
880 // FIXME: when ? how ?
885 int parse_export(string const & type, string const &)
888 lyxerr << _("Missing file type [eg latex, ps...] after "
889 "--export switch") << endl;
892 batch = "buffer-export " + type;
897 int parse_import(string const & type, string const & file)
900 lyxerr << _("Missing file type [eg latex, ps...] after "
901 "--import switch") << endl;
905 lyxerr << _("Missing filename for --import") << endl;
909 batch = "buffer-import " + type + ' ' + file;
916 bool LyX::easyParse(int & argc, char * argv[])
918 std::map<string, cmd_helper> cmdmap;
920 cmdmap["-dbg"] = parse_dbg;
921 cmdmap["-help"] = parse_help;
922 cmdmap["--help"] = parse_help;
923 cmdmap["-version"] = parse_version;
924 cmdmap["--version"] = parse_version;
925 cmdmap["-sysdir"] = parse_sysdir;
926 cmdmap["-userdir"] = parse_userdir;
927 cmdmap["-x"] = parse_execute;
928 cmdmap["--execute"] = parse_execute;
929 cmdmap["-e"] = parse_export;
930 cmdmap["--export"] = parse_export;
931 cmdmap["-i"] = parse_import;
932 cmdmap["--import"] = parse_import;
934 for (int i = 1; i < argc; ++i) {
935 std::map<string, cmd_helper>::const_iterator it
936 = cmdmap.find(argv[i]);
938 // don't complain if not found - may be parsed later
939 if (it == cmdmap.end())
942 string arg((i + 1 < argc) ? argv[i + 1] : "");
943 string arg2((i + 2 < argc) ? argv[i + 2] : "");
945 int const remove = 1 + it->second(arg, arg2);
947 // Now, remove used arguments by shifting
948 // the following ones remove places down.
950 for (int j = i; j < argc; ++j)
951 argv[j] = argv[j + remove];
955 batch_command = batch;