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"
37 #include "lyxtextclasslist.h"
38 #include "lyxserver.h"
39 #include "MenuBackend.h"
41 #include "ToolbarBackend.h"
43 #include "mathed/math_inset.h"
45 #include "frontends/Alert.h"
46 #include "frontends/lyx_gui.h"
47 #include "frontends/LyXView.h"
49 #include "support/environment.h"
50 #include "support/filetools.h"
51 #include "support/lyxlib.h"
52 #include "support/convert.h"
53 #include "support/os.h"
54 #include "support/package.h"
55 #include "support/path.h"
56 #include "support/systemcall.h"
58 #include <boost/bind.hpp>
59 #include <boost/filesystem/operations.hpp>
64 using lyx::support::addName;
65 using lyx::support::addPath;
66 using lyx::support::bformat;
67 using lyx::support::createDirectory;
68 using lyx::support::createLyXTmpDir;
69 using lyx::support::fileSearch;
70 using lyx::support::getEnv;
71 using lyx::support::i18nLibFileSearch;
72 using lyx::support::libFileSearch;
73 using lyx::support::package;
74 using lyx::support::Path;
75 using lyx::support::prependEnvPath;
76 using lyx::support::quoteName;
77 using lyx::support::rtrim;
78 using lyx::support::Systemcall;
80 namespace os = lyx::support::os;
81 namespace fs = boost::filesystem;
87 #ifndef CXX_GLOBAL_CSTD
94 extern LyXServer * lyxserver;
96 // This is the global bufferlist object
97 BufferList bufferlist;
99 // convenient to have it here.
100 boost::scoped_ptr<kb_keymap> toplevel_keymap;
104 // Filled with the command line arguments "foo" of "-sysdir foo" or
106 string cl_system_support;
107 string cl_user_support;
110 void lyx_exit(int status)
112 // FIXME: We should not directly call exit(), since it only
113 // guarantees a return to the system, no application cleanup.
114 // This may cause troubles with not executed destructors.
115 if (lyx_gui::use_gui)
116 lyx_gui::exit(status);
121 void showFileError(string const & error)
123 Alert::warning(_("Could not read configuration file"),
124 bformat(_("Error while reading the configuration file\n%1$s.\n"
125 "Please check your installation."), error));
126 lyx_exit(EXIT_FAILURE);
130 void reconfigureUserLyXDir()
132 string const configure_command = package().configure_command();
134 lyxerr << _("LyX: reconfiguring user directory") << endl;
135 Path p(package().user_support());
137 one.startscript(Systemcall::Wait, configure_command);
138 lyxerr << "LyX: " << _("Done!") << endl;
144 boost::scoped_ptr<LyX> LyX::singleton_;
146 void LyX::exec(int & argc, char * argv[])
148 BOOST_ASSERT(!singleton_.get());
149 // We must return from this before launching the gui so that
150 // other parts of the code can access singleton_ through
151 // LyX::ref and LyX::cref.
152 singleton_.reset(new LyX);
153 // Start the real execution loop.
154 singleton_->priv_exec(argc, argv);
160 BOOST_ASSERT(singleton_.get());
161 return *singleton_.get();
165 LyX const & LyX::cref()
167 BOOST_ASSERT(singleton_.get());
168 return *singleton_.get();
173 : first_start(false), geometryOption_(false)
177 lyx::Session & LyX::session()
179 BOOST_ASSERT(session_.get());
180 return *session_.get();
184 lyx::Session const & LyX::session() const
186 BOOST_ASSERT(session_.get());
187 return *session_.get();
191 void LyX::addLyXView(boost::shared_ptr<LyXView> const & lyxview)
193 views_.push_back(lyxview);
197 Buffer const * const LyX::updateInset(InsetBase const * inset) const
202 Buffer const * buffer_ptr = 0;
203 ViewList::const_iterator it = views_.begin();
204 ViewList::const_iterator const end = views_.end();
205 for (; it != end; ++it) {
206 Buffer const * ptr = (*it)->updateInset(inset);
214 void LyX::priv_exec(int & argc, char * argv[])
216 // Here we need to parse the command line. At least
217 // we need to parse for "-dbg" and "-help"
218 lyx_gui::use_gui = easyParse(argc, argv);
220 lyx::support::init_package(argv[0], cl_system_support, cl_user_support,
221 lyx::support::top_build_dir_is_one_level_up);
223 // Start the real execution loop.
224 if (lyx_gui::use_gui)
225 lyx_gui::exec(argc, argv);
231 void LyX::exec2(int & argc, char * argv[])
233 // check for any spurious extra arguments
234 // other than documents
235 for (int argi = 1; argi < argc ; ++argi) {
236 if (argv[argi][0] == '-') {
237 lyxerr << bformat(_("Wrong command line option `%1$s'. Exiting."),
243 // Initialization of LyX (reads lyxrc and more)
244 lyxerr[Debug::INIT] << "Initializing LyX::init..." << endl;
246 lyxerr[Debug::INIT] << "Initializing LyX::init...done" << endl;
248 if (lyx_gui::use_gui)
249 lyx_gui::parse_lyxrc();
251 vector<string> files;
253 for (int argi = argc - 1; argi >= 1; --argi)
254 files.push_back(os::internal_path(argv[argi]));
257 files.push_back(i18nLibFileSearch("examples", "splash.lyx"));
259 // if a file is specified, I assume that user wants to edit *that* file
260 if (files.empty() && lyxrc.load_session) {
261 vector<string> const & lastopened = session_->lastOpenedFiles();
262 files.insert(files.end(), lastopened.begin(), lastopened.end() );
264 // clear this list to save a few bytes of RAM
265 session_->clearLastOpenedFiles();
267 // Execute batch commands if available
268 if (!batch_command.empty()) {
270 lyxerr[Debug::INIT] << "About to handle -x '"
271 << batch_command << '\'' << endl;
273 Buffer * last_loaded = 0;
275 vector<string>::const_iterator it = files.begin();
276 vector<string>::const_iterator end = files.end();
278 for (; it != end; ++it) {
279 // get absolute path of file and add ".lyx" to
280 // the filename if necessary
281 string s = fileSearch(string(), *it, "lyx");
283 last_loaded = newFile(*it, string(), true);
285 Buffer * buf = bufferlist.newBuffer(s, false);
286 buf->error.connect(boost::bind(&LyX::printError, this, _1));
287 if (loadLyXFile(buf, s))
290 bufferlist.release(buf);
294 // try to dispatch to last loaded buffer first
296 bool success = false;
297 if (last_loaded->dispatch(batch_command, &success)) {
302 files.clear(); // the files are already loaded
305 if (lyx_gui::use_gui) {
306 // determine windows size and position, from lyxrc and/or session
308 unsigned int width = 690;
309 unsigned int height = 510;
310 bool maximize = false;
312 if (lyxrc.geometry_width != 0 && lyxrc.geometry_height != 0 ) {
313 width = lyxrc.geometry_width;
314 height = lyxrc.geometry_height;
316 // if lyxrc returns (0,0), then use session info
318 string val = session().loadSessionInfo("WindowWidth");
320 width = convert<unsigned int>(val);
321 val = session().loadSessionInfo("WindowHeight");
323 height = convert<unsigned int>(val);
324 if (session().loadSessionInfo("WindowIsMaximized") == "yes")
327 // if user wants to restore window position
330 if (lyxrc.geometry_xysaved) {
331 string val = session().loadSessionInfo("WindowPosX");
333 posx = convert<int>(val);
334 val = session().loadSessionInfo("WindowPosY");
336 posy = convert<int>(val);
339 if (geometryOption_) {
344 lyx_gui::start(batch_command, files, width, height, posx, posy, maximize);
347 // Something went wrong above
349 lyx_exit(EXIT_FAILURE);
357 The SIGHUP signal does not exist on Windows and does not need to be handled.
359 Windows handles SIGFPE and SIGSEGV signals as expected.
361 Cntl+C interrupts (mapped to SIGINT by Windows' POSIX compatability layer)
362 cause a new thread to be spawned. This may well result in unexpected
363 behaviour by the single-threaded LyX.
365 SIGTERM signals will come only from another process actually sending
366 that signal using 'raise' in Windows' POSIX compatability layer. It will
367 not come from the general "terminate process" methods that everyone
368 actually uses (and which can't be trapped). Killing an app 'politely' on
369 Windows involves first sending a WM_CLOSE message, something that is
370 caught already by the Qt frontend.
372 For more information see:
374 http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/2034055
375 ...signals are mostly useless on Windows for a variety of reasons that are
378 'UNIX Application Migration Guide, Chapter 9'
379 http://msdn.microsoft.com/library/en-us/dnucmg/html/UCMGch09.asp
381 'How To Terminate an Application "Cleanly" in Win32'
382 http://support.microsoft.com/default.aspx?scid=kb;en-us;178893
386 static void error_handler(int err_sig)
388 // Throw away any signals other than the first one received.
389 static sig_atomic_t handling_error = false;
392 handling_error = true;
394 // We have received a signal indicating a fatal error, so
395 // try and save the data ASAP.
396 LyX::cref().emergencyCleanup();
398 // These lyxerr calls may or may not work:
400 // Signals are asynchronous, so the main program may be in a very
401 // fragile state when a signal is processed and thus while a signal
402 // handler function executes.
403 // In general, therefore, we should avoid performing any
404 // I/O operations or calling most library and system functions from
407 // This shouldn't matter here, however, as we've already invoked
412 lyxerr << "\nlyx: SIGHUP signal caught\nBye." << endl;
416 lyxerr << "\nlyx: SIGFPE signal caught\nBye." << endl;
419 lyxerr << "\nlyx: SIGSEGV signal caught\n"
420 "Sorry, you have found a bug in LyX. "
421 "Please read the bug-reporting instructions "
422 "in Help->Introduction and send us a bug report, "
423 "if necessary. Thanks !\nBye." << endl;
431 // Deinstall the signal handlers
433 signal(SIGHUP, SIG_DFL);
435 signal(SIGINT, SIG_DFL);
436 signal(SIGFPE, SIG_DFL);
437 signal(SIGSEGV, SIG_DFL);
438 signal(SIGTERM, SIG_DFL);
441 if (err_sig == SIGSEGV ||
442 (err_sig != SIGHUP && !getEnv("LYXDEBUG").empty()))
444 if (err_sig == SIGSEGV || !getEnv("LYXDEBUG").empty())
446 lyx::support::abort();
453 void LyX::printError(ErrorItem const & ei)
455 std::cerr << _("LyX: ") << ei.error
456 << ':' << ei.description << std::endl;
464 signal(SIGHUP, error_handler);
466 signal(SIGFPE, error_handler);
467 signal(SIGSEGV, error_handler);
468 signal(SIGINT, error_handler);
469 signal(SIGTERM, error_handler);
470 // SIGPIPE can be safely ignored.
472 lyxrc.tempdir_path = package().temp_dir();
473 lyxrc.document_path = package().document_dir();
475 if (lyxrc.template_path.empty()) {
476 lyxrc.template_path = addPath(package().system_support(),
480 if (lyxrc.roman_font_name.empty())
481 lyxrc.roman_font_name = lyx_gui::roman_font_name();
482 if (lyxrc.sans_font_name.empty())
483 lyxrc.sans_font_name = lyx_gui::sans_font_name();
484 if (lyxrc.typewriter_font_name.empty())
485 lyxrc.typewriter_font_name = lyx_gui::typewriter_font_name();
488 // Read configuration files
491 // This one may have been distributed along with LyX.
492 readRcFile("lyxrc.dist");
494 // Set the PATH correctly.
495 #if !defined (USE_POSIX_PACKAGING)
496 // Add the directory containing the LyX executable to the path
497 // so that LyX can find things like tex2lyx.
498 if (package().build_support().empty())
499 prependEnvPath("PATH", package().binary_dir());
501 if (!lyxrc.path_prefix.empty())
502 prependEnvPath("PATH", lyxrc.path_prefix);
504 // Check that user LyX directory is ok. We don't do that if
505 // running in batch mode.
506 if (lyx_gui::use_gui) {
507 if (queryUserLyXDir(package().explicit_user_support()))
508 reconfigureUserLyXDir();
513 // This one is generated in user_support directory by lib/configure.py.
514 readRcFile("lyxrc.defaults");
516 // Query the OS to know what formats are viewed natively
517 formats.setAutoOpen();
519 system_lyxrc = lyxrc;
520 system_formats = formats;
521 system_converters = converters;
522 system_movers = movers;
523 system_lcolor = lcolor;
525 // This one is edited through the preferences dialog.
526 readRcFile("preferences");
528 readEncodingsFile("encodings");
529 readLanguagesFile("languages");
532 lyxerr[Debug::INIT] << "Reading layouts..." << endl;
535 if (lyx_gui::use_gui) {
537 toplevel_keymap.reset(new kb_keymap);
538 defaultKeyBindings(toplevel_keymap.get());
539 toplevel_keymap->read(lyxrc.bind_file);
542 readUIFile(lyxrc.ui_file);
545 if (lyxerr.debugging(Debug::LYXRC))
548 os::cygwin_path_fix(lyxrc.cygwin_path_fix);
549 if (!lyxrc.path_prefix.empty())
550 prependEnvPath("PATH", lyxrc.path_prefix);
552 if (fs::exists(lyxrc.document_path) &&
553 fs::is_directory(lyxrc.document_path))
554 package().document_dir() = lyxrc.document_path;
556 package().temp_dir() = createLyXTmpDir(lyxrc.tempdir_path);
557 if (package().temp_dir().empty()) {
558 Alert::error(_("Could not create temporary directory"),
559 bformat(_("Could not create a temporary directory in\n"
560 "%1$s. Make sure that this\n"
561 "path exists and is writable and try again."),
562 lyxrc.tempdir_path));
563 // createLyXTmpDir() tries sufficiently hard to create a
564 // usable temp dir, so the probability to come here is
565 // close to zero. We therefore don't try to overcome this
566 // problem with e.g. asking the user for a new path and
567 // trying again but simply exit.
568 lyx_exit(EXIT_FAILURE);
571 if (lyxerr.debugging(Debug::INIT)) {
572 lyxerr << "LyX tmp dir: `" << package().temp_dir() << '\'' << endl;
575 lyxerr[Debug::INIT] << "Reading session information '.lyx/session'..." << endl;
576 session_.reset(new lyx::Session(lyxrc.num_lastfiles));
580 void LyX::defaultKeyBindings(kb_keymap * kbmap)
582 kbmap->bind("Right", FuncRequest(LFUN_CHAR_FORWARD));
583 kbmap->bind("Left", FuncRequest(LFUN_CHAR_BACKWARD));
584 kbmap->bind("Up", FuncRequest(LFUN_UP));
585 kbmap->bind("Down", FuncRequest(LFUN_DOWN));
587 kbmap->bind("Tab", FuncRequest(LFUN_CELL_FORWARD));
588 kbmap->bind("C-Tab", FuncRequest(LFUN_CELL_SPLIT));
589 kbmap->bind("~S-ISO_Left_Tab", FuncRequest(LFUN_CELL_BACKWARD));
590 kbmap->bind("~S-BackTab", FuncRequest(LFUN_CELL_BACKWARD));
592 kbmap->bind("Home", FuncRequest(LFUN_LINE_BEGIN));
593 kbmap->bind("End", FuncRequest(LFUN_LINE_END));
594 kbmap->bind("Prior", FuncRequest(LFUN_SCREEN_UP));
595 kbmap->bind("Next", FuncRequest(LFUN_SCREEN_DOWN));
597 kbmap->bind("Return", FuncRequest(LFUN_BREAK_PARAGRAPH));
598 //kbmap->bind("~C-~S-~M-nobreakspace", FuncRequest(LFUN_PROTECTEDSPACE));
600 kbmap->bind("Delete", FuncRequest(LFUN_CHAR_DELETE_FORWARD));
601 kbmap->bind("BackSpace", FuncRequest(LFUN_CHAR_DELETE_BACKWARD));
603 // kbmap->bindings to enable the use of the numeric keypad
605 //kbmap->bind("KP_0", FuncRequest(LFUN_SELF_INSERT));
606 //kbmap->bind("KP_Decimal", FuncRequest(LFUN_SELF_INSERT));
607 kbmap->bind("KP_Enter", FuncRequest(LFUN_BREAK_PARAGRAPH));
608 //kbmap->bind("KP_1", FuncRequest(LFUN_SELF_INSERT));
609 //kbmap->bind("KP_2", FuncRequest(LFUN_SELF_INSERT));
610 //kbmap->bind("KP_3", FuncRequest(LFUN_SELF_INSERT));
611 //kbmap->bind("KP_4", FuncRequest(LFUN_SELF_INSERT));
612 //kbmap->bind("KP_5", FuncRequest(LFUN_SELF_INSERT));
613 //kbmap->bind("KP_6", FuncRequest(LFUN_SELF_INSERT));
614 //kbmap->bind("KP_Add", FuncRequest(LFUN_SELF_INSERT));
615 //kbmap->bind("KP_7", FuncRequest(LFUN_SELF_INSERT));
616 //kbmap->bind("KP_8", FuncRequest(LFUN_SELF_INSERT));
617 //kbmap->bind("KP_9", FuncRequest(LFUN_SELF_INSERT));
618 //kbmap->bind("KP_Divide", FuncRequest(LFUN_SELF_INSERT));
619 //kbmap->bind("KP_Multiply", FuncRequest(LFUN_SELF_INSERT));
620 //kbmap->bind("KP_Subtract", FuncRequest(LFUN_SELF_INSERT));
621 kbmap->bind("KP_Right", FuncRequest(LFUN_CHAR_FORWARD));
622 kbmap->bind("KP_Left", FuncRequest(LFUN_CHAR_BACKWARD));
623 kbmap->bind("KP_Up", FuncRequest(LFUN_UP));
624 kbmap->bind("KP_Down", FuncRequest(LFUN_DOWN));
625 kbmap->bind("KP_Home", FuncRequest(LFUN_LINE_BEGIN));
626 kbmap->bind("KP_End", FuncRequest(LFUN_LINE_END));
627 kbmap->bind("KP_Prior", FuncRequest(LFUN_SCREEN_UP));
628 kbmap->bind("KP_Next", FuncRequest(LFUN_SCREEN_DOWN));
632 void LyX::emergencyCleanup() const
634 // what to do about tmpfiles is non-obvious. we would
635 // like to delete any we find, but our lyxdir might
636 // contain documents etc. which might be helpful on
639 bufferlist.emergencyWriteAll();
641 lyxserver->emergencyCleanup();
645 void LyX::deadKeyBindings(kb_keymap * kbmap)
647 // bindKeyings for transparent handling of deadkeys
648 // The keysyms are gotten from XFree86 X11R6
649 kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACCENT_ACUTE));
650 kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_ACCENT_BREVE));
651 kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_ACCENT_CARON));
652 kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_ACCENT_CEDILLA));
653 kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_ACCENT_CIRCLE));
654 kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_ACCENT_CIRCUMFLEX));
655 kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_ACCENT_DOT));
656 kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_ACCENT_GRAVE));
657 kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_ACCENT_HUNGARIAN_UMLAUT));
658 kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_ACCENT_MACRON));
659 // nothing with this name
660 // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_ACCENT_SPECIAL_CARON);
661 kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_ACCENT_TILDE));
662 kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_ACCENT_UMLAUT));
663 // nothing with this name either...
664 //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_ACCENT_UNDERBAR));
665 kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_ACCENT_UNDERDOT));
666 kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_ACCENT_TIE));
667 kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_ACCENT_OGONEK));
673 // return true if file does not exist or is older than configure.py.
674 bool needsUpdate(string const & file)
676 static string const configure_script =
677 addName(package().system_support(), "configure.py");
678 string const absfile =
679 addName(package().user_support(), file);
681 return (! fs::exists(absfile))
682 || (fs::last_write_time(configure_script)
683 > fs::last_write_time(absfile));
689 bool LyX::queryUserLyXDir(bool explicit_userdir)
691 // Does user directory exist?
692 if (fs::exists(package().user_support()) &&
693 fs::is_directory(package().user_support())) {
696 return needsUpdate("lyxrc.defaults")
697 || needsUpdate("textclass.lst")
698 || needsUpdate("packages.lst");
701 first_start = !explicit_userdir;
703 // If the user specified explicitly a directory, ask whether
704 // to create it. If the user says "no", then exit.
705 if (explicit_userdir &&
707 _("Missing user LyX directory"),
708 bformat(_("You have specified a non-existent user "
709 "LyX directory, %1$s.\n"
710 "It is needed to keep your own configuration."),
711 package().user_support()),
713 _("&Create directory"),
715 lyxerr << _("No user LyX directory. Exiting.") << endl;
716 lyx_exit(EXIT_FAILURE);
719 lyxerr << bformat(_("LyX: Creating directory %1$s"),
720 package().user_support())
723 if (!createDirectory(package().user_support(), 0755)) {
724 // Failed, so let's exit.
725 lyxerr << _("Failed to create directory. Exiting.")
727 lyx_exit(EXIT_FAILURE);
734 void LyX::readRcFile(string const & name)
736 lyxerr[Debug::INIT] << "About to read " << name << "... ";
738 string const lyxrc_path = libFileSearch(string(), name);
739 if (!lyxrc_path.empty()) {
741 lyxerr[Debug::INIT] << "Found in " << lyxrc_path << endl;
743 if (lyxrc.read(lyxrc_path) < 0)
746 lyxerr[Debug::INIT] << "Not found." << lyxrc_path << endl;
751 // Read the ui file `name'
752 void LyX::readUIFile(string const & name)
762 struct keyword_item uitags[ui_last - 1] = {
763 { "include", ui_include },
764 { "menuset", ui_menuset },
765 { "toolbar", ui_toolbar },
766 { "toolbars", ui_toolbars }
769 // Ensure that a file is read only once (prevents include loops)
770 static std::list<string> uifiles;
771 std::list<string>::const_iterator it = uifiles.begin();
772 std::list<string>::const_iterator end = uifiles.end();
773 it = std::find(it, end, name);
775 lyxerr[Debug::INIT] << "UI file '" << name
776 << "' has been read already. "
777 << "Is this an include loop?"
782 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
784 string const ui_path = libFileSearch("ui", name, "ui");
786 if (ui_path.empty()) {
787 lyxerr[Debug::INIT] << "Could not find " << name << endl;
791 uifiles.push_back(name);
793 lyxerr[Debug::INIT] << "Found " << name
794 << " in " << ui_path << endl;
795 LyXLex lex(uitags, ui_last - 1);
796 lex.setFile(ui_path);
798 lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
802 if (lyxerr.debugging(Debug::PARSER))
803 lex.printTable(lyxerr);
809 string const file = lex.getString();
814 menubackend.read(lex);
818 toolbarbackend.read(lex);
822 toolbarbackend.readToolbars(lex);
826 if (!rtrim(lex.getString()).empty())
827 lex.printError("LyX::ReadUIFile: "
828 "Unknown menu tag: `$$Token'");
835 // Read the languages file `name'
836 void LyX::readLanguagesFile(string const & name)
838 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
840 string const lang_path = libFileSearch(string(), name);
841 if (lang_path.empty()) {
845 languages.read(lang_path);
849 // Read the encodings file `name'
850 void LyX::readEncodingsFile(string const & name)
852 lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
854 string const enc_path = libFileSearch(string(), name);
855 if (enc_path.empty()) {
859 encodings.read(enc_path);
868 /// return the the number of arguments consumed
869 typedef boost::function<int(string const &, string const &)> cmd_helper;
871 int parse_dbg(string const & arg, string const &)
874 lyxerr << _("List of supported debug flags:") << endl;
875 Debug::showTags(lyxerr);
878 lyxerr << bformat(_("Setting debug level to %1$s"), arg) << endl;
880 lyxerr.level(Debug::value(arg));
881 Debug::showLevel(lyxerr, lyxerr.level());
886 int parse_help(string const &, string const &)
889 _("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
890 "Command line switches (case sensitive):\n"
891 "\t-help summarize LyX usage\n"
892 "\t-userdir dir set user directory to dir\n"
893 "\t-sysdir dir set system directory to dir\n"
894 "\t-geometry WxH+X+Y set geometry of the main window\n"
895 "\t-dbg feature[,feature]...\n"
896 " select the features to debug.\n"
897 " Type `lyx -dbg' to see the list of features\n"
898 "\t-x [--execute] command\n"
899 " where command is a lyx command.\n"
900 "\t-e [--export] fmt\n"
901 " where fmt is the export format of choice.\n"
902 "\t-i [--import] fmt file.xxx\n"
903 " where fmt is the import format of choice\n"
904 " and file.xxx is the file to be imported.\n"
905 "\t-version summarize version and build info\n"
906 "Check the LyX man page for more details.") << endl;
911 int parse_version(string const &, string const &)
913 lyxerr << "LyX " << lyx_version
914 << " of " << lyx_release_date << endl;
915 lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
917 lyxerr << lyx_version_info << endl;
922 int parse_sysdir(string const & arg, string const &)
925 lyxerr << _("Missing directory for -sysdir switch") << endl;
928 cl_system_support = arg;
932 int parse_userdir(string const & arg, string const &)
935 lyxerr << _("Missing directory for -userdir switch") << endl;
938 cl_user_support = arg;
942 int parse_execute(string const & arg, string const &)
945 lyxerr << _("Missing command string after --execute switch") << endl;
952 int parse_export(string const & type, string const &)
955 lyxerr << _("Missing file type [eg latex, ps...] after "
956 "--export switch") << endl;
959 batch = "buffer-export " + type;
964 int parse_import(string const & type, string const & file)
967 lyxerr << _("Missing file type [eg latex, ps...] after "
968 "--import switch") << endl;
972 lyxerr << _("Missing filename for --import") << endl;
976 batch = "buffer-import " + type + ' ' + file;
983 bool LyX::easyParse(int & argc, char * argv[])
985 std::map<string, cmd_helper> cmdmap;
987 cmdmap["-dbg"] = parse_dbg;
988 cmdmap["-help"] = parse_help;
989 cmdmap["--help"] = parse_help;
990 cmdmap["-version"] = parse_version;
991 cmdmap["--version"] = parse_version;
992 cmdmap["-sysdir"] = parse_sysdir;
993 cmdmap["-userdir"] = parse_userdir;
994 cmdmap["-x"] = parse_execute;
995 cmdmap["--execute"] = parse_execute;
996 cmdmap["-e"] = parse_export;
997 cmdmap["--export"] = parse_export;
998 cmdmap["-i"] = parse_import;
999 cmdmap["--import"] = parse_import;
1001 for (int i = 1; i < argc; ++i) {
1002 std::map<string, cmd_helper>::const_iterator it
1003 = cmdmap.find(argv[i]);
1005 // check for X11 -geometry option
1006 if (lyx::support::compare(argv[i], "-geometry") == 0)
1007 geometryOption_ = true;
1009 // don't complain if not found - may be parsed later
1010 if (it == cmdmap.end())
1013 string arg((i + 1 < argc) ? argv[i + 1] : "");
1014 string arg2((i + 2 < argc) ? argv[i + 2] : "");
1016 int const remove = 1 + it->second(arg, arg2);
1018 // Now, remove used arguments by shifting
1019 // the following ones remove places down.
1021 for (int j = i; j < argc; ++j)
1022 argv[j] = argv[j + remove];
1026 batch_command = batch;