X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Flyx_main.C;h=cc856fb70a4e3a8aaca7f0a644e1d1af14e227e5;hb=3815df7705b09920f9bb60c6fd9ee0576fe0a834;hp=56bb85136d0d901c73daa3738bd3dd6036b87c75;hpb=fb1ffecd0c3b07939dcb8af50af71ef3ba0b1d02;p=lyx.git diff --git a/src/lyx_main.C b/src/lyx_main.C index 56bb85136d..cc856fb70a 100644 --- a/src/lyx_main.C +++ b/src/lyx_main.C @@ -31,10 +31,12 @@ #include "session.h" #include "LColor.h" #include "lyx_cb.h" +#include "LyXAction.h" #include "lyxfunc.h" #include "lyxlex.h" #include "lyxrc.h" #include "lyxserver.h" +#include "lyxsocket.h" #include "lyxtextclasslist.h" #include "MenuBackend.h" #include "mover.h" @@ -42,6 +44,7 @@ #include "frontends/Alert.h" #include "frontends/Application.h" +#include "frontends/Gui.h" #include "frontends/LyXView.h" #include "support/environment.h" @@ -60,25 +63,26 @@ #include #include -using lyx::support::addName; -using lyx::support::addPath; -using lyx::support::bformat; -using lyx::support::createDirectory; -using lyx::support::createLyXTmpDir; -using lyx::support::destroyDir; -using lyx::support::fileSearch; -using lyx::support::getEnv; -using lyx::support::i18nLibFileSearch; -using lyx::support::libFileSearch; -using lyx::support::package; -using lyx::support::prependEnvPath; -using lyx::support::rtrim; -using lyx::support::Systemcall; - -using lyx::docstring; - -namespace Alert = lyx::frontend::Alert; -namespace os = lyx::support::os; + +namespace lyx { + +using support::addName; +using support::addPath; +using support::bformat; +using support::createDirectory; +using support::createLyXTmpDir; +using support::destroyDir; +using support::fileSearch; +using support::getEnv; +using support::i18nLibFileSearch; +using support::libFileSearch; +using support::package; +using support::prependEnvPath; +using support::rtrim; +using support::Systemcall; + +namespace Alert = frontend::Alert; +namespace os = support::os; namespace fs = boost::filesystem; using std::endl; @@ -92,14 +96,8 @@ using std::signal; using std::system; #endif - -/// convenient to have it here. -boost::scoped_ptr toplevel_keymap; - /// -lyx::frontend::Application * theApp = 0; - -namespace lyx { +frontend::Application * theApp = 0; /// are we using the GUI at all? /** @@ -107,7 +105,6 @@ namespace lyx { */ bool use_gui = true; -} namespace { @@ -121,7 +118,7 @@ void showFileError(string const & error) { Alert::warning(_("Could not read configuration file"), bformat(_("Error while reading the configuration file\n%1$s.\n" - "Please check your installation."), lyx::from_utf8(error))); + "Please check your installation."), from_utf8(error))); } @@ -129,18 +126,39 @@ void reconfigureUserLyXDir() { string const configure_command = package().configure_command(); - lyxerr << lyx::to_utf8(_("LyX: reconfiguring user directory")) << endl; - lyx::support::Path p(package().user_support()); + lyxerr << to_utf8(_("LyX: reconfiguring user directory")) << endl; + support::Path p(package().user_support()); Systemcall one; one.startscript(Systemcall::Wait, configure_command); - lyxerr << "LyX: " << lyx::to_utf8(_("Done!")) << endl; + lyxerr << "LyX: " << to_utf8(_("Done!")) << endl; } } // namespace anon +/// The main application class private implementation. +struct LyX::Singletons +{ + /// our function handler + LyXFunc lyxfunc_; + /// + BufferList buffer_list_; + /// + boost::scoped_ptr toplevel_keymap_; + /// + boost::scoped_ptr lyx_server_; + /// + boost::scoped_ptr lyx_socket_; + /// + boost::scoped_ptr application_; + /// lyx session, containing lastfiles, lastfilepos, and lastopened + boost::scoped_ptr session_; +}; + + boost::scoped_ptr LyX::singleton_; + int LyX::exec(int & argc, char * argv[]) { BOOST_ASSERT(!singleton_.get()); @@ -167,48 +185,104 @@ LyX const & LyX::cref() } -BufferList & theBufferList() -{ - return LyX::ref().bufferList(); -} - - LyX::LyX() : first_start(false), geometryOption_(false) { - buffer_list_.reset(new BufferList); + pimpl_.reset(new Singletons); } BufferList & LyX::bufferList() { - return *buffer_list_.get(); + return pimpl_->buffer_list_; } BufferList const & LyX::bufferList() const { - return *buffer_list_.get(); + return pimpl_->buffer_list_; +} + + +Session & LyX::session() +{ + BOOST_ASSERT(pimpl_->session_.get()); + return *pimpl_->session_.get(); +} + + +Session const & LyX::session() const +{ + BOOST_ASSERT(pimpl_->session_.get()); + return *pimpl_->session_.get(); +} + + +LyXFunc & LyX::lyxFunc() +{ + return pimpl_->lyxfunc_; } -lyx::Session & LyX::session() +LyXFunc const & LyX::lyxFunc() const { - BOOST_ASSERT(session_.get()); - return *session_.get(); + return pimpl_->lyxfunc_; } -lyx::Session const & LyX::session() const +LyXServer & LyX::server() { - BOOST_ASSERT(session_.get()); - return *session_.get(); + BOOST_ASSERT(pimpl_->lyx_server_.get()); + return *pimpl_->lyx_server_.get(); } -void LyX::addLyXView(LyXView * lyxview) +LyXServer const & LyX::server() const { - views_.push_back(lyxview); + BOOST_ASSERT(pimpl_->lyx_server_.get()); + return *pimpl_->lyx_server_.get(); +} + + +LyXServerSocket & LyX::socket() +{ + BOOST_ASSERT(pimpl_->lyx_socket_.get()); + return *pimpl_->lyx_socket_.get(); +} + + +LyXServerSocket const & LyX::socket() const +{ + BOOST_ASSERT(pimpl_->lyx_socket_.get()); + return *pimpl_->lyx_socket_.get(); +} + + +frontend::Application & LyX::application() +{ + BOOST_ASSERT(pimpl_->application_.get()); + return *pimpl_->application_.get(); +} + + +frontend::Application const & LyX::application() const +{ + BOOST_ASSERT(pimpl_->application_.get()); + return *pimpl_->application_.get(); +} + + +kb_keymap & LyX::topLevelKeymap() +{ + BOOST_ASSERT(pimpl_->toplevel_keymap_.get()); + return *pimpl_->toplevel_keymap_.get(); +} + + +kb_keymap const & LyX::topLevelKeymap() const +{ + BOOST_ASSERT(pimpl_->toplevel_keymap_.get()); + return *pimpl_->toplevel_keymap_.get(); } @@ -218,10 +292,12 @@ Buffer const * const LyX::updateInset(InsetBase const * inset) const return 0; Buffer const * buffer_ptr = 0; - ViewList::const_iterator it = views_.begin(); - ViewList::const_iterator const end = views_.end(); + vector const & view_ids = pimpl_->application_->gui().viewIds(); + vector::const_iterator it = view_ids.begin(); + vector::const_iterator const end = view_ids.end(); for (; it != end; ++it) { - Buffer const * ptr = (*it)->updateInset(inset); + Buffer const * ptr = + pimpl_->application_->gui().view(*it).updateInset(inset); if (ptr) buffer_ptr = ptr; } @@ -235,30 +311,47 @@ int LyX::priv_exec(int & argc, char * argv[]) // we need to parse for "-dbg" and "-help" easyParse(argc, argv); - lyx::support::init_package(argv[0], cl_system_support, cl_user_support, - lyx::support::top_build_dir_is_one_level_up); + support::init_package(argv[0], cl_system_support, cl_user_support, + support::top_build_dir_is_one_level_up); vector files; int exit_status = execBatchCommands(argc, argv, files); if (exit_status) return exit_status; - - if (lyx::use_gui) { + + if (use_gui) { // Force adding of font path _before_ Application is initialized - lyx::support::addFontResources(); - application_.reset(lyx::createApplication(argc, argv)); + support::addFontResources(); + pimpl_->application_.reset(createApplication(argc, argv)); initGuiFont(); // FIXME: this global pointer should probably go. - theApp = application_.get(); + theApp = pimpl_->application_.get(); restoreGuiSession(files); // Start the real execution loop. - exit_status = application_->start(batch_command); + + // FIXME + /* Create a CoreApplication class that will provide the main event loop + * and the socket callback registering. With Qt4, only QtCore + * library would be needed. + * When this is done, a server_mode could be created and the following two + * line would be moved out from here. + */ + pimpl_->lyx_server_.reset(new LyXServer(&pimpl_->lyxfunc_, lyxrc.lyxpipes)); + pimpl_->lyx_socket_.reset(new LyXServerSocket(&pimpl_->lyxfunc_, + support::os::internal_path(package().temp_dir() + "/lyxsocket"))); + + // handle the batch commands the user asked for + if (!batch_command.empty()) { + pimpl_->lyxfunc_.dispatch(lyxaction.lookupFunc(batch_command)); + } + + exit_status = pimpl_->application_->start(batch_command); // Kill the application object before exiting. This avoid crash // on exit on Linux. - application_.reset(); + pimpl_->application_.reset(); // Restore original font resources after Application is destroyed. - lyx::support::restoreFontResources(); + support::restoreFontResources(); } else { // FIXME: create a ConsoleApplication @@ -276,7 +369,7 @@ void LyX::prepareExit() quitting = true; // close buffers first - buffer_list_->closeAll(); + pimpl_->buffer_list_.closeAll(); // do any other cleanup procedures now lyxerr[Debug::INFO] << "Deleting tmp dir " << package().temp_dir() << endl; @@ -284,7 +377,7 @@ void LyX::prepareExit() if (!destroyDir(package().temp_dir())) { docstring const msg = bformat(_("Unable to remove the temporary directory %1$s"), - lyx::from_utf8(package().temp_dir())); + from_utf8(package().temp_dir())); Alert::warning(_("Unable to remove temporary directory"), msg); } } @@ -292,29 +385,25 @@ void LyX::prepareExit() void LyX::earlyExit(int status) { - BOOST_ASSERT(application_.get()); - // LyX::application_ is not initialised at this + BOOST_ASSERT(pimpl_->application_.get()); + // LyX::pimpl_::application_ is not initialised at this // point so it's safe to just exit after some cleanup. prepareExit(); exit(status); } -void LyX::quit(bool noask) +void LyX::quit() { lyxerr[Debug::INFO] << "Running QuitLyX." << endl; - if (lyx::use_gui) { - if (!noask && !buffer_list_->quitWriteAll()) - return; - - session_->writeFile(); - } - prepareExit(); - if (lyx::use_gui) { - application_->exit(0); + if (use_gui) { + pimpl_->session_->writeFile(); + pimpl_->lyx_server_.reset(); + pimpl_->lyx_socket_.reset(); + pimpl_->application_->exit(0); } } @@ -326,9 +415,9 @@ int LyX::execBatchCommands(int & argc, char * argv[], // other than documents for (int argi = 1; argi < argc ; ++argi) { if (argv[argi][0] == '-') { - lyxerr << lyx::to_utf8( + lyxerr << to_utf8( bformat(_("Wrong command line option `%1$s'. Exiting."), - lyx::from_utf8(argv[argi]))) << endl; + from_utf8(argv[argi]))) << endl; return EXIT_FAILURE; } } @@ -366,7 +455,7 @@ int LyX::execBatchCommands(int & argc, char * argv[], if (b) last_loaded = b; } else { - Buffer * buf = buffer_list_->newBuffer(s, false); + Buffer * buf = pimpl_->buffer_list_.newBuffer(s, false); if (loadLyXFile(buf, s)) { last_loaded = buf; ErrorList const & el = buf->errorList("Parse"); @@ -375,7 +464,7 @@ int LyX::execBatchCommands(int & argc, char * argv[], boost::bind(&LyX::printError, this, _1)); } else - buffer_list_->release(buf); + pimpl_->buffer_list_.release(buf); } } @@ -396,6 +485,31 @@ int LyX::execBatchCommands(int & argc, char * argv[], void LyX::restoreGuiSession(vector const & files) { + LyXView * view = newLyXView(); + + // load files + for_each(files.begin(), files.end(), + bind(&LyXView::loadLyXFile, view, _1, true)); + + // if a file is specified, I assume that user wants to edit *that* file + if (files.empty() && lyxrc.load_session) { + vector const & lastopened = pimpl_->session_->lastOpened().getfiles(); + // do not add to the lastfile list since these files are restored from + // last seesion, and should be already there (regular files), or should + // not be added at all (help files). + for_each(lastopened.begin(), lastopened.end(), + bind(&LyXView::loadLyXFile, view, _1, false)); + } + // clear this list to save a few bytes of RAM + pimpl_->session_->lastOpened().clear(); +} + + +LyXView * LyX::newLyXView() +{ + if (!lyx::use_gui) + return 0; + // determine windows size and position, from lyxrc and/or session // initial geometry unsigned int width = 690; @@ -408,23 +522,24 @@ void LyX::restoreGuiSession(vector const & files) } // if lyxrc returns (0,0), then use session info else { - string val = session().loadSessionInfo("WindowWidth"); + string val = session().sessionInfo().load("WindowWidth"); if (!val.empty()) width = convert(val); - val = session().loadSessionInfo("WindowHeight"); + val = session().sessionInfo().load("WindowHeight"); if (!val.empty()) height = convert(val); - if (session().loadSessionInfo("WindowIsMaximized") == "yes") + if (session().sessionInfo().load("WindowIsMaximized") == "yes") maximize = true; } + // if user wants to restore window position int posx = -1; int posy = -1; if (lyxrc.geometry_xysaved) { - string val = session().loadSessionInfo("WindowPosX"); + string val = session().sessionInfo().load("WindowPosX"); if (!val.empty()) posx = convert(val); - val = session().loadSessionInfo("WindowPosY"); + val = session().sessionInfo().load("WindowPosY"); if (!val.empty()) posy = convert(val); } @@ -434,27 +549,11 @@ void LyX::restoreGuiSession(vector const & files) height = 0; } // create the main window - LyXView * view = &application_->createView(width, height, posx, posy, maximize); - ref().addLyXView(view); + LyXView * view = &pimpl_->application_->createView(width, height, posx, posy, maximize); - // load files - for_each(files.begin(), files.end(), - bind(&LyXView::loadLyXFile, view, _1, true)); - - // if a file is specified, I assume that user wants to edit *that* file - if (files.empty() && lyxrc.load_session) { - vector const & lastopened = session_->lastOpenedFiles(); - // do not add to the lastfile list since these files are restored from - // last seesion, and should be already there (regular files), or should - // not be added at all (help files). - for_each(lastopened.begin(), lastopened.end(), - bind(&LyXView::loadLyXFile, view, _1, false)); - } - // clear this list to save a few bytes of RAM - session_->clearLastOpenedFiles(); + return view; } - /* Signals and Windows =================== @@ -547,7 +646,7 @@ static void error_handler(int err_sig) #else if (err_sig == SIGSEGV || !getEnv("LYXDEBUG").empty()) #endif - lyx::support::abort(); + support::abort(); exit(0); } @@ -556,23 +655,23 @@ static void error_handler(int err_sig) void LyX::printError(ErrorItem const & ei) { - docstring tmp = _("LyX: ") + ei.error + lyx::char_type(':') + docstring tmp = _("LyX: ") + ei.error + char_type(':') + ei.description; - std::cerr << lyx::to_utf8(tmp) << std::endl; + std::cerr << to_utf8(tmp) << std::endl; } void LyX::initGuiFont() { if (lyxrc.roman_font_name.empty()) - lyxrc.roman_font_name = application_->romanFontName(); + lyxrc.roman_font_name = pimpl_->application_->romanFontName(); if (lyxrc.sans_font_name.empty()) - lyxrc.sans_font_name = application_->sansFontName(); + lyxrc.sans_font_name = pimpl_->application_->sansFontName(); if (lyxrc.typewriter_font_name.empty()) lyxrc.typewriter_font_name - = application_->typewriterFontName(); + = pimpl_->application_->typewriterFontName(); } @@ -618,7 +717,7 @@ bool LyX::init() reconfigureUserLyXDir(); // no need for a splash when there is no GUI - if (!lyx::use_gui) { + if (!use_gui) { first_start = false; } @@ -629,6 +728,9 @@ bool LyX::init() // Query the OS to know what formats are viewed natively formats.setAutoOpen(); + // Read lyxrc.dist again to be able to override viewer auto-detection. + readRcFile("lyxrc.dist"); + system_lyxrc = lyxrc; system_formats = formats; system_converters = converters; @@ -649,11 +751,13 @@ bool LyX::init() if (!LyXSetStyle()) return false; - if (lyx::use_gui) { + if (use_gui) { // Set up bindings - toplevel_keymap.reset(new kb_keymap); - defaultKeyBindings(toplevel_keymap.get()); - toplevel_keymap->read(lyxrc.bind_file); + pimpl_->toplevel_keymap_.reset(new kb_keymap); + defaultKeyBindings(pimpl_->toplevel_keymap_.get()); + pimpl_->toplevel_keymap_->read(lyxrc.bind_file); + + pimpl_->lyxfunc_.initKeySequences(pimpl_->toplevel_keymap_.get()); // Read menus if (!readUIFile(lyxrc.ui_file)) @@ -677,7 +781,7 @@ bool LyX::init() bformat(_("Could not create a temporary directory in\n" "%1$s. Make sure that this\n" "path exists and is writable and try again."), - lyx::from_utf8(lyxrc.tempdir_path))); + from_utf8(lyxrc.tempdir_path))); // createLyXTmpDir() tries sufficiently hard to create a // usable temp dir, so the probability to come here is // close to zero. We therefore don't try to overcome this @@ -691,7 +795,7 @@ bool LyX::init() } lyxerr[Debug::INIT] << "Reading session information '.lyx/session'..." << endl; - session_.reset(new lyx::Session(lyxrc.num_lastfiles)); + pimpl_->session_.reset(new Session(lyxrc.num_lastfiles)); return true; } @@ -755,8 +859,12 @@ void LyX::emergencyCleanup() const // contain documents etc. which might be helpful on // a crash - buffer_list_->emergencyWriteAll(); - application_->server().emergencyCleanup(); + pimpl_->buffer_list_.emergencyWriteAll(); + if (use_gui) { + pimpl_->lyx_server_->emergencyCleanup(); + pimpl_->lyx_server_.reset(); + pimpl_->lyx_socket_.reset(); + } } @@ -826,21 +934,21 @@ bool LyX::queryUserLyXDir(bool explicit_userdir) bformat(_("You have specified a non-existent user " "LyX directory, %1$s.\n" "It is needed to keep your own configuration."), - lyx::from_utf8(package().user_support())), + from_utf8(package().user_support())), 1, 0, _("&Create directory"), _("&Exit LyX"))) { - lyxerr << lyx::to_utf8(_("No user LyX directory. Exiting.")) << endl; + lyxerr << to_utf8(_("No user LyX directory. Exiting.")) << endl; earlyExit(EXIT_FAILURE); } - lyxerr << lyx::to_utf8(bformat(_("LyX: Creating directory %1$s"), - lyx::from_utf8(package().user_support()))) + lyxerr << to_utf8(bformat(_("LyX: Creating directory %1$s"), + from_utf8(package().user_support()))) << endl; if (!createDirectory(package().user_support(), 0755)) { // Failed, so let's exit. - lyxerr << lyx::to_utf8(_("Failed to create directory. Exiting.")) + lyxerr << to_utf8(_("Failed to create directory. Exiting.")) << endl; earlyExit(EXIT_FAILURE); } @@ -995,11 +1103,11 @@ typedef boost::function cmd_helper; int parse_dbg(string const & arg, string const &) { if (arg.empty()) { - lyxerr << lyx::to_utf8(_("List of supported debug flags:")) << endl; + lyxerr << to_utf8(_("List of supported debug flags:")) << endl; Debug::showTags(lyxerr); exit(0); } - lyxerr << lyx::to_utf8(bformat(_("Setting debug level to %1$s"), lyx::from_utf8(arg))) << endl; + lyxerr << to_utf8(bformat(_("Setting debug level to %1$s"), from_utf8(arg))) << endl; lyxerr.level(Debug::value(arg)); Debug::showLevel(lyxerr, lyxerr.level()); @@ -1010,7 +1118,7 @@ int parse_dbg(string const & arg, string const &) int parse_help(string const &, string const &) { lyxerr << - lyx::to_utf8(_("Usage: lyx [ command line switches ] [ name.lyx ... ]\n" + to_utf8(_("Usage: lyx [ command line switches ] [ name.lyx ... ]\n" "Command line switches (case sensitive):\n" "\t-help summarize LyX usage\n" "\t-userdir dir set user directory to dir\n" @@ -1046,7 +1154,7 @@ int parse_version(string const &, string const &) int parse_sysdir(string const & arg, string const &) { if (arg.empty()) { - lyxerr << lyx::to_utf8(_("Missing directory for -sysdir switch")) << endl; + lyxerr << to_utf8(_("Missing directory for -sysdir switch")) << endl; exit(1); } cl_system_support = arg; @@ -1056,7 +1164,7 @@ int parse_sysdir(string const & arg, string const &) int parse_userdir(string const & arg, string const &) { if (arg.empty()) { - lyxerr << lyx::to_utf8(_("Missing directory for -userdir switch")) << endl; + lyxerr << to_utf8(_("Missing directory for -userdir switch")) << endl; exit(1); } cl_user_support = arg; @@ -1066,7 +1174,7 @@ int parse_userdir(string const & arg, string const &) int parse_execute(string const & arg, string const &) { if (arg.empty()) { - lyxerr << lyx::to_utf8(_("Missing command string after --execute switch")) << endl; + lyxerr << to_utf8(_("Missing command string after --execute switch")) << endl; exit(1); } batch = arg; @@ -1076,24 +1184,24 @@ int parse_execute(string const & arg, string const &) int parse_export(string const & type, string const &) { if (type.empty()) { - lyxerr << lyx::to_utf8(_("Missing file type [eg latex, ps...] after " + lyxerr << to_utf8(_("Missing file type [eg latex, ps...] after " "--export switch")) << endl; exit(1); } batch = "buffer-export " + type; - lyx::use_gui = false; + use_gui = false; return 1; } int parse_import(string const & type, string const & file) { if (type.empty()) { - lyxerr << lyx::to_utf8(_("Missing file type [eg latex, ps...] after " + lyxerr << to_utf8(_("Missing file type [eg latex, ps...] after " "--import switch")) << endl; exit(1); } if (file.empty()) { - lyxerr << lyx::to_utf8(_("Missing filename for --import")) << endl; + lyxerr << to_utf8(_("Missing filename for --import")) << endl; exit(1); } @@ -1127,7 +1235,7 @@ void LyX::easyParse(int & argc, char * argv[]) = cmdmap.find(argv[i]); // check for X11 -geometry option - if (lyx::support::compare(argv[i], "-geometry") == 0) + if (support::compare(argv[i], "-geometry") == 0) geometryOption_ = true; // don't complain if not found - may be parsed later @@ -1149,3 +1257,52 @@ void LyX::easyParse(int & argc, char * argv[]) batch_command = batch; } + + +FuncStatus getStatus(FuncRequest const & action) +{ + return LyX::ref().lyxFunc().getStatus(action); +} + + +void dispatch(FuncRequest const & action) +{ + LyX::ref().lyxFunc().dispatch(action); +} + + +BufferList & theBufferList() +{ + return LyX::ref().bufferList(); +} + + +LyXFunc & theLyXFunc() +{ + return LyX::ref().lyxFunc(); +} + + +LyXServer & theLyXServer() +{ + // FIXME: this should not be use_gui dependent + BOOST_ASSERT(use_gui); + return LyX::ref().server(); +} + + +LyXServerSocket & theLyXServerSocket() +{ + // FIXME: this should not be use_gui dependent + BOOST_ASSERT(use_gui); + return LyX::ref().socket(); +} + + +kb_keymap & theTopLevelKeymap() +{ + BOOST_ASSERT(use_gui); + return LyX::ref().topLevelKeymap(); +} + +} // namespace lyx