X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Flyx_main.C;h=cc856fb70a4e3a8aaca7f0a644e1d1af14e227e5;hb=3815df7705b09920f9bb60c6fd9ee0576fe0a834;hp=5fe670ca1eeecfeacf0fbf5ffb0a4194cbe52f6c;hpb=8c93f63b48a1b15d4f3e163b7305213f2f73879e;p=lyx.git diff --git a/src/lyx_main.C b/src/lyx_main.C index 5fe670ca1e..cc856fb70a 100644 --- a/src/lyx_main.C +++ b/src/lyx_main.C @@ -30,27 +30,32 @@ #include "language.h" #include "session.h" #include "LColor.h" +#include "lyx_cb.h" +#include "LyXAction.h" #include "lyxfunc.h" #include "lyxlex.h" #include "lyxrc.h" -#include "lyxtextclasslist.h" #include "lyxserver.h" +#include "lyxsocket.h" +#include "lyxtextclasslist.h" #include "MenuBackend.h" #include "mover.h" #include "ToolbarBackend.h" -#include "mathed/math_inset.h" - #include "frontends/Alert.h" -#include "frontends/lyx_gui.h" +#include "frontends/Application.h" +#include "frontends/Gui.h" #include "frontends/LyXView.h" #include "support/environment.h" #include "support/filetools.h" +#include "support/fontutils.h" #include "support/lyxlib.h" +#include "support/convert.h" #include "support/os.h" #include "support/package.h" #include "support/path.h" +#include "support/systemcall.h" #include #include @@ -58,27 +63,32 @@ #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::fileSearch; -using lyx::support::getEnv; -using lyx::support::i18nLibFileSearch; -using lyx::support::libFileSearch; -using lyx::support::package; -using lyx::support::Path; -using lyx::support::prependEnvPath; -using lyx::support::quoteName; -using lyx::support::rtrim; - -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; using std::string; using std::vector; +using std::for_each; #ifndef CXX_GLOBAL_CSTD using std::exit; @@ -86,16 +96,15 @@ using std::signal; using std::system; #endif +/// +frontend::Application * theApp = 0; -extern void QuitLyX(bool); - -extern LyXServer * lyxserver; - -// This is the global bufferlist object -BufferList bufferlist; +/// are we using the GUI at all? +/** +* We default to true and this is changed to false when the export feature is used. +*/ +bool use_gui = true; -// convenient to have it here. -boost::scoped_ptr toplevel_keymap; namespace { @@ -108,31 +117,49 @@ string cl_user_support; 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."), error)); - exit(EXIT_FAILURE); + bformat(_("Error while reading the configuration file\n%1$s.\n" + "Please check your installation."), from_utf8(error))); } void reconfigureUserLyXDir() { - string const configure_script = - addName(package().system_support(), "configure.py"); - string const configure_command = - "python " + quoteName(configure_script); + string const configure_command = package().configure_command(); - lyxerr << _("LyX: reconfiguring user directory") << endl; - Path p(package().user_support()); - ::system(configure_command.c_str()); - lyxerr << "LyX: " << _("Done!") << endl; + lyxerr << to_utf8(_("LyX: reconfiguring user directory")) << endl; + support::Path p(package().user_support()); + Systemcall one; + one.startscript(Systemcall::Wait, configure_command); + 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_; -void LyX::exec(int & argc, char * argv[]) + +int LyX::exec(int & argc, char * argv[]) { BOOST_ASSERT(!singleton_.get()); // We must return from this before launching the gui so that @@ -140,7 +167,7 @@ void LyX::exec(int & argc, char * argv[]) // LyX::ref and LyX::cref. singleton_.reset(new LyX); // Start the real execution loop. - singleton_->priv_exec(argc, argv); + return singleton_->priv_exec(argc, argv); } @@ -159,27 +186,103 @@ LyX const & LyX::cref() LyX::LyX() - : first_start(false) -{} + : first_start(false), geometryOption_(false) +{ + pimpl_.reset(new Singletons); +} + + +BufferList & LyX::bufferList() +{ + return pimpl_->buffer_list_; +} + + +BufferList const & LyX::bufferList() const +{ + 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_; +} + + +LyXFunc const & LyX::lyxFunc() const +{ + return pimpl_->lyxfunc_; +} + + +LyXServer & LyX::server() +{ + BOOST_ASSERT(pimpl_->lyx_server_.get()); + return *pimpl_->lyx_server_.get(); +} + + +LyXServer const & LyX::server() const +{ + 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(); +} -lyx::Session & LyX::session() +frontend::Application & LyX::application() { - BOOST_ASSERT(session_.get()); - return *session_.get(); + BOOST_ASSERT(pimpl_->application_.get()); + return *pimpl_->application_.get(); } -lyx::Session const & LyX::session() const +frontend::Application const & LyX::application() const { - BOOST_ASSERT(session_.get()); - return *session_.get(); + BOOST_ASSERT(pimpl_->application_.get()); + return *pimpl_->application_.get(); } -void LyX::addLyXView(boost::shared_ptr const & lyxview) +kb_keymap & LyX::topLevelKeymap() { - views_.push_back(lyxview); + 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(); } @@ -189,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; } @@ -200,37 +305,129 @@ Buffer const * const LyX::updateInset(InsetBase const * inset) const } -void LyX::priv_exec(int & argc, char * argv[]) +int LyX::priv_exec(int & argc, char * argv[]) { // Here we need to parse the command line. At least // we need to parse for "-dbg" and "-help" - bool const want_gui = easyParse(argc, argv); + easyParse(argc, argv); + + 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 (use_gui) { + // Force adding of font path _before_ Application is initialized + support::addFontResources(); + pimpl_->application_.reset(createApplication(argc, argv)); + initGuiFont(); + // FIXME: this global pointer should probably go. + theApp = pimpl_->application_.get(); + restoreGuiSession(files); + // Start the real execution loop. + + // 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)); + } - lyx::support::init_package(argv[0], cl_system_support, cl_user_support, - lyx::support::top_build_dir_is_one_level_up); + exit_status = pimpl_->application_->start(batch_command); + // Kill the application object before exiting. This avoid crash + // on exit on Linux. + pimpl_->application_.reset(); + // Restore original font resources after Application is destroyed. + support::restoreFontResources(); + } + else { + // FIXME: create a ConsoleApplication + theApp = 0; + } + + return exit_status; +} - if (want_gui) - lyx_gui::parse_init(argc, argv); +void LyX::prepareExit() +{ + // Set a flag that we do quitting from the program, + // so no refreshes are necessary. + quitting = true; + + // close buffers first + pimpl_->buffer_list_.closeAll(); + + // do any other cleanup procedures now + lyxerr[Debug::INFO] << "Deleting tmp dir " << package().temp_dir() << endl; + + if (!destroyDir(package().temp_dir())) { + docstring const msg = + bformat(_("Unable to remove the temporary directory %1$s"), + from_utf8(package().temp_dir())); + Alert::warning(_("Unable to remove temporary directory"), msg); + } +} + + +void LyX::earlyExit(int status) +{ + 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() +{ + lyxerr[Debug::INFO] << "Running QuitLyX." << endl; + + prepareExit(); + + if (use_gui) { + pimpl_->session_->writeFile(); + pimpl_->lyx_server_.reset(); + pimpl_->lyx_socket_.reset(); + pimpl_->application_->exit(0); + } +} + + +int LyX::execBatchCommands(int & argc, char * argv[], + vector & files) +{ // check for any spurious extra arguments // other than documents for (int argi = 1; argi < argc ; ++argi) { if (argv[argi][0] == '-') { - lyxerr << bformat(_("Wrong command line option `%1$s'. Exiting."), - argv[argi]) << endl; - exit(1); + lyxerr << to_utf8( + bformat(_("Wrong command line option `%1$s'. Exiting."), + from_utf8(argv[argi]))) << endl; + return EXIT_FAILURE; } } // Initialization of LyX (reads lyxrc and more) lyxerr[Debug::INIT] << "Initializing LyX::init..." << endl; - init(want_gui); + bool success = init(); lyxerr[Debug::INIT] << "Initializing LyX::init...done" << endl; - - if (want_gui) - lyx_gui::parse_lyxrc(); - - vector files; + if (!success) + return EXIT_FAILURE; for (int argi = argc - 1; argi >= 1; --argi) files.push_back(os::internal_path(argv[argi])); @@ -238,14 +435,6 @@ void LyX::priv_exec(int & argc, char * argv[]) if (first_start) files.push_back(i18nLibFileSearch("examples", "splash.lyx")); - // 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(); - files.insert(files.end(), lastopened.begin(), lastopened.end() ); - // clear this list to save a few bytes of RAM - session_->clearLastOpenedFiles(); - } - // Execute batch commands if available if (!batch_command.empty()) { @@ -262,38 +451,109 @@ void LyX::priv_exec(int & argc, char * argv[]) // the filename if necessary string s = fileSearch(string(), *it, "lyx"); if (s.empty()) { - last_loaded = newFile(*it, string(), true); + Buffer * const b = newFile(*it, string(), true); + if (b) + last_loaded = b; } else { - Buffer * buf = bufferlist.newBuffer(s, false); - buf->error.connect(boost::bind(&LyX::printError, this, _1)); - if (loadLyXFile(buf, s)) + Buffer * buf = pimpl_->buffer_list_.newBuffer(s, false); + if (loadLyXFile(buf, s)) { last_loaded = buf; + ErrorList const & el = buf->errorList("Parse"); + if (!el.empty()) + for_each(el.begin(), el.end(), + boost::bind(&LyX::printError, this, _1)); + } else - bufferlist.release(buf); + pimpl_->buffer_list_.release(buf); } } // try to dispatch to last loaded buffer first if (last_loaded) { - bool success = false; + success = false; if (last_loaded->dispatch(batch_command, &success)) { - QuitLyX(false); - exit(!success); + prepareExit(); + return !success; } } files.clear(); // the files are already loaded } - if (want_gui) - lyx_gui::start(batch_command, files); - else { - // Something went wrong above - QuitLyX(false); - exit(EXIT_FAILURE); + return EXIT_SUCCESS; +} + + +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; + unsigned int height = 510; + bool maximize = false; + // first try lyxrc + if (lyxrc.geometry_width != 0 && lyxrc.geometry_height != 0 ) { + width = lyxrc.geometry_width; + height = lyxrc.geometry_height; + } + // if lyxrc returns (0,0), then use session info + else { + string val = session().sessionInfo().load("WindowWidth"); + if (!val.empty()) + width = convert(val); + val = session().sessionInfo().load("WindowHeight"); + if (!val.empty()) + height = convert(val); + 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().sessionInfo().load("WindowPosX"); + if (!val.empty()) + posx = convert(val); + val = session().sessionInfo().load("WindowPosY"); + if (!val.empty()) + posy = convert(val); + } + + if (geometryOption_) { + width = 0; + height = 0; + } + // create the main window + LyXView * view = &pimpl_->application_->createView(width, height, posx, posy, maximize); + + return view; +} + /* Signals and Windows =================== @@ -386,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); } @@ -395,13 +655,27 @@ static void error_handler(int err_sig) void LyX::printError(ErrorItem const & ei) { - std::cerr << _("LyX: ") << ei.error - << ':' << ei.description << std::endl; + docstring tmp = _("LyX: ") + ei.error + char_type(':') + + ei.description; + std::cerr << to_utf8(tmp) << std::endl; +} + +void LyX::initGuiFont() +{ + if (lyxrc.roman_font_name.empty()) + lyxrc.roman_font_name = pimpl_->application_->romanFontName(); + + if (lyxrc.sans_font_name.empty()) + lyxrc.sans_font_name = pimpl_->application_->sansFontName(); + + if (lyxrc.typewriter_font_name.empty()) + lyxrc.typewriter_font_name + = pimpl_->application_->typewriterFontName(); } -void LyX::init(bool gui) +bool LyX::init() { #ifdef SIGHUP signal(SIGHUP, error_handler); @@ -412,19 +686,6 @@ void LyX::init(bool gui) signal(SIGTERM, error_handler); // SIGPIPE can be safely ignored. - // Check that user LyX directory is ok. We don't do that if - // running in batch mode. - bool reconfigure = false; - if (gui) { - reconfigure = - queryUserLyXDir(package().explicit_user_support()); - } else { - first_start = false; - } - - // Disable gui when easyparse says so - lyx_gui::use_gui = gui; - lyxrc.tempdir_path = package().temp_dir(); lyxrc.document_path = package().document_dir(); @@ -433,67 +694,83 @@ void LyX::init(bool gui) "templates"); } - if (lyxrc.roman_font_name.empty()) - lyxrc.roman_font_name = lyx_gui::roman_font_name(); - if (lyxrc.sans_font_name.empty()) - lyxrc.sans_font_name = lyx_gui::sans_font_name(); - if (lyxrc.typewriter_font_name.empty()) - lyxrc.typewriter_font_name = lyx_gui::typewriter_font_name(); - // // Read configuration files // - readRcFile("lyxrc.defaults"); + // This one may have been distributed along with LyX. + if (!readRcFile("lyxrc.dist")) + return false; + + // Set the PATH correctly. +#if !defined (USE_POSIX_PACKAGING) + // Add the directory containing the LyX executable to the path + // so that LyX can find things like tex2lyx. + if (package().build_support().empty()) + prependEnvPath("PATH", package().binary_dir()); +#endif + if (!lyxrc.path_prefix.empty()) + prependEnvPath("PATH", lyxrc.path_prefix); + + // Check that user LyX directory is ok. + if (queryUserLyXDir(package().explicit_user_support())) + reconfigureUserLyXDir(); + + // no need for a splash when there is no GUI + if (!use_gui) { + first_start = false; + } + + // This one is generated in user_support directory by lib/configure.py. + if (!readRcFile("lyxrc.defaults")) + return false; + + // 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; system_movers = movers; system_lcolor = lcolor; - string prefsfile = "preferences"; - // back compatibility to lyxs < 1.1.6 - if (libFileSearch(string(), prefsfile).empty()) - prefsfile = "lyxrc"; - if (!libFileSearch(string(), prefsfile).empty()) - readRcFile(prefsfile); + // This one is edited through the preferences dialog. + if (!readRcFile("preferences")) + return false; - readEncodingsFile("encodings"); - readLanguagesFile("languages"); + if (!readEncodingsFile("encodings")) + return false; + if (!readLanguagesFile("languages")) + return false; // Load the layouts lyxerr[Debug::INIT] << "Reading layouts..." << endl; - LyXSetStyle(); + if (!LyXSetStyle()) + return false; - if (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 - readUIFile(lyxrc.ui_file); + if (!readUIFile(lyxrc.ui_file)) + return false; } if (lyxerr.debugging(Debug::LYXRC)) lyxrc.print(); - os::cygwin_path_fix(lyxrc.cygwin_path_fix); + os::windows_style_tex_paths(lyxrc.windows_style_tex_paths); if (!lyxrc.path_prefix.empty()) prependEnvPath("PATH", lyxrc.path_prefix); -#if !defined (USE_POSIX_PACKAGING) - // Add the directory containing the LyX executable to the path - // so that LyX can find things like tex2lyx. - if (package().build_support().empty()) - prependEnvPath("PATH", package().binary_dir()); -#endif - - // Having reset the PATH we're now in a position to run configure - // if necessary. - if (reconfigure) - reconfigureUserLyXDir(); - if (fs::exists(lyxrc.document_path) && fs::is_directory(lyxrc.document_path)) package().document_dir() = lyxrc.document_path; @@ -502,15 +779,15 @@ void LyX::init(bool gui) if (package().temp_dir().empty()) { Alert::error(_("Could not create temporary directory"), bformat(_("Could not create a temporary directory in\n" - "%1$s. Make sure that this\n" - "path exists and is writable and try again."), - lyxrc.tempdir_path)); + "%1$s. Make sure that this\n" + "path exists and is writable and try again."), + 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 // problem with e.g. asking the user for a new path and // trying again but simply exit. - exit(EXIT_FAILURE); + return false; } if (lyxerr.debugging(Debug::INIT)) { @@ -518,14 +795,15 @@ void LyX::init(bool gui) } 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; } void LyX::defaultKeyBindings(kb_keymap * kbmap) { - kbmap->bind("Right", FuncRequest(LFUN_RIGHT)); - kbmap->bind("Left", FuncRequest(LFUN_LEFT)); + kbmap->bind("Right", FuncRequest(LFUN_CHAR_FORWARD)); + kbmap->bind("Left", FuncRequest(LFUN_CHAR_BACKWARD)); kbmap->bind("Up", FuncRequest(LFUN_UP)); kbmap->bind("Down", FuncRequest(LFUN_DOWN)); @@ -534,43 +812,43 @@ void LyX::defaultKeyBindings(kb_keymap * kbmap) kbmap->bind("~S-ISO_Left_Tab", FuncRequest(LFUN_CELL_BACKWARD)); kbmap->bind("~S-BackTab", FuncRequest(LFUN_CELL_BACKWARD)); - kbmap->bind("Home", FuncRequest(LFUN_HOME)); - kbmap->bind("End", FuncRequest(LFUN_END)); - kbmap->bind("Prior", FuncRequest(LFUN_PRIOR)); - kbmap->bind("Next", FuncRequest(LFUN_NEXT)); + kbmap->bind("Home", FuncRequest(LFUN_LINE_BEGIN)); + kbmap->bind("End", FuncRequest(LFUN_LINE_END)); + kbmap->bind("Prior", FuncRequest(LFUN_SCREEN_UP)); + kbmap->bind("Next", FuncRequest(LFUN_SCREEN_DOWN)); - kbmap->bind("Return", FuncRequest(LFUN_BREAKPARAGRAPH)); + kbmap->bind("Return", FuncRequest(LFUN_BREAK_PARAGRAPH)); //kbmap->bind("~C-~S-~M-nobreakspace", FuncRequest(LFUN_PROTECTEDSPACE)); - kbmap->bind("Delete", FuncRequest(LFUN_DELETE)); - kbmap->bind("BackSpace", FuncRequest(LFUN_BACKSPACE)); + kbmap->bind("Delete", FuncRequest(LFUN_CHAR_DELETE_FORWARD)); + kbmap->bind("BackSpace", FuncRequest(LFUN_CHAR_DELETE_BACKWARD)); // kbmap->bindings to enable the use of the numeric keypad // e.g. Num Lock set - //kbmap->bind("KP_0", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_Decimal", FuncRequest(LFUN_SELFINSERT)); - kbmap->bind("KP_Enter", FuncRequest(LFUN_BREAKPARAGRAPH)); - //kbmap->bind("KP_1", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_2", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_3", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_4", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_5", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_6", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_Add", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_7", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_8", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_9", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_Divide", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_Multiply", FuncRequest(LFUN_SELFINSERT)); - //kbmap->bind("KP_Subtract", FuncRequest(LFUN_SELFINSERT)); - kbmap->bind("KP_Right", FuncRequest(LFUN_RIGHT)); - kbmap->bind("KP_Left", FuncRequest(LFUN_LEFT)); + //kbmap->bind("KP_0", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_Decimal", FuncRequest(LFUN_SELF_INSERT)); + kbmap->bind("KP_Enter", FuncRequest(LFUN_BREAK_PARAGRAPH)); + //kbmap->bind("KP_1", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_2", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_3", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_4", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_5", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_6", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_Add", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_7", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_8", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_9", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_Divide", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_Multiply", FuncRequest(LFUN_SELF_INSERT)); + //kbmap->bind("KP_Subtract", FuncRequest(LFUN_SELF_INSERT)); + kbmap->bind("KP_Right", FuncRequest(LFUN_CHAR_FORWARD)); + kbmap->bind("KP_Left", FuncRequest(LFUN_CHAR_BACKWARD)); kbmap->bind("KP_Up", FuncRequest(LFUN_UP)); kbmap->bind("KP_Down", FuncRequest(LFUN_DOWN)); - kbmap->bind("KP_Home", FuncRequest(LFUN_HOME)); - kbmap->bind("KP_End", FuncRequest(LFUN_END)); - kbmap->bind("KP_Prior", FuncRequest(LFUN_PRIOR)); - kbmap->bind("KP_Next", FuncRequest(LFUN_NEXT)); + kbmap->bind("KP_Home", FuncRequest(LFUN_LINE_BEGIN)); + kbmap->bind("KP_End", FuncRequest(LFUN_LINE_END)); + kbmap->bind("KP_Prior", FuncRequest(LFUN_SCREEN_UP)); + kbmap->bind("KP_Next", FuncRequest(LFUN_SCREEN_DOWN)); } @@ -581,9 +859,12 @@ void LyX::emergencyCleanup() const // contain documents etc. which might be helpful on // a crash - bufferlist.emergencyWriteAll(); - if (lyxserver) - lyxserver->emergencyCleanup(); + pimpl_->buffer_list_.emergencyWriteAll(); + if (use_gui) { + pimpl_->lyx_server_->emergencyCleanup(); + pimpl_->lyx_server_.reset(); + pimpl_->lyx_socket_.reset(); + } } @@ -591,47 +872,56 @@ void LyX::deadKeyBindings(kb_keymap * kbmap) { // bindKeyings for transparent handling of deadkeys // The keysyms are gotten from XFree86 X11R6 - kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACUTE)); - kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_BREVE)); - kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_CARON)); - kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_CEDILLA)); - kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_CIRCLE)); - kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_CIRCUMFLEX)); - kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_DOT)); - kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_GRAVE)); - kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_HUNG_UMLAUT)); - kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_MACRON)); + kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACCENT_ACUTE)); + kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_ACCENT_BREVE)); + kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_ACCENT_CARON)); + kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_ACCENT_CEDILLA)); + kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_ACCENT_CIRCLE)); + kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_ACCENT_CIRCUMFLEX)); + kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_ACCENT_DOT)); + kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_ACCENT_GRAVE)); + kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_ACCENT_HUNGARIAN_UMLAUT)); + kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_ACCENT_MACRON)); // nothing with this name - // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_SPECIAL_CARON); - kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_TILDE)); - kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_UMLAUT)); + // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_ACCENT_SPECIAL_CARON); + kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_ACCENT_TILDE)); + kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_ACCENT_UMLAUT)); // nothing with this name either... - //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_UNDERBAR)); - kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_UNDERDOT)); - kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_TIE)); - kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_OGONEK)); + //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_ACCENT_UNDERBAR)); + kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_ACCENT_UNDERDOT)); + kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_ACCENT_TIE)); + kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_ACCENT_OGONEK)); } -bool LyX::queryUserLyXDir(bool explicit_userdir) +namespace { + +// return true if file does not exist or is older than configure.py. +bool needsUpdate(string const & file) { - bool reconfigure = false; + static string const configure_script = + addName(package().system_support(), "configure.py"); + string const absfile = + addName(package().user_support(), file); + + return (! fs::exists(absfile)) + || (fs::last_write_time(configure_script) + > fs::last_write_time(absfile)); +} + +} + +bool LyX::queryUserLyXDir(bool explicit_userdir) +{ // Does user directory exist? if (fs::exists(package().user_support()) && fs::is_directory(package().user_support())) { first_start = false; - string const configure_script = - addName(package().system_support(), "configure.py"); - string const userDefaults = - addName(package().user_support(), "lyxrc.defaults"); - if (fs::exists(configure_script) && - fs::exists(userDefaults) && - fs::last_write_time(configure_script) - > fs::last_write_time(userDefaults)) { - reconfigure = true; - } - return reconfigure; + + return needsUpdate("lyxrc.defaults") + || needsUpdate("textclass.lst") + || needsUpdate("packages.lst"); } first_start = !explicit_userdir; @@ -642,52 +932,53 @@ bool LyX::queryUserLyXDir(bool explicit_userdir) Alert::prompt( _("Missing user LyX directory"), bformat(_("You have specified a non-existent user " - "LyX directory, %1$s.\n" - "It is needed to keep your own configuration."), - package().user_support()), + "LyX directory, %1$s.\n" + "It is needed to keep your own configuration."), + from_utf8(package().user_support())), 1, 0, _("&Create directory"), _("&Exit LyX"))) { - lyxerr << _("No user LyX directory. Exiting.") << endl; - exit(1); + lyxerr << to_utf8(_("No user LyX directory. Exiting.")) << endl; + earlyExit(EXIT_FAILURE); } - lyxerr << bformat(_("LyX: Creating directory %1$s"), - package().user_support()) + lyxerr << to_utf8(bformat(_("LyX: Creating directory %1$s"), + from_utf8(package().user_support()))) << endl; - reconfigure = true; if (!createDirectory(package().user_support(), 0755)) { // Failed, so let's exit. - lyxerr << _("Failed to create directory. Exiting.") + lyxerr << to_utf8(_("Failed to create directory. Exiting.")) << endl; - exit(1); + earlyExit(EXIT_FAILURE); } - return reconfigure; + return true; } -void LyX::readRcFile(string const & name) +bool LyX::readRcFile(string const & name) { - lyxerr[Debug::INIT] << "About to read " << name << "..." << endl; + lyxerr[Debug::INIT] << "About to read " << name << "... "; string const lyxrc_path = libFileSearch(string(), name); if (!lyxrc_path.empty()) { - lyxerr[Debug::INIT] << "Found " << name - << " in " << lyxrc_path << endl; + lyxerr[Debug::INIT] << "Found in " << lyxrc_path << endl; - if (lyxrc.read(lyxrc_path) >= 0) - return; - } + if (lyxrc.read(lyxrc_path) < 0) { + showFileError(name); + return false; + } + } else + lyxerr[Debug::INIT] << "Not found." << lyxrc_path << endl; + return true; - showFileError(name); } // Read the ui file `name' -void LyX::readUIFile(string const & name) +bool LyX::readUIFile(string const & name) { enum Uitags { ui_menuset = 1, @@ -714,7 +1005,7 @@ void LyX::readUIFile(string const & name) << "' has been read already. " << "Is this an include loop?" << endl; - return; + return false; } lyxerr[Debug::INIT] << "About to read " << name << "..." << endl; @@ -724,7 +1015,7 @@ void LyX::readUIFile(string const & name) if (ui_path.empty()) { lyxerr[Debug::INIT] << "Could not find " << name << endl; showFileError(name); - return; + return false; } uifiles.push_back(name); @@ -745,7 +1036,8 @@ void LyX::readUIFile(string const & name) case ui_include: { lex.next(true); string const file = lex.getString(); - readUIFile(file); + if (!readUIFile(file)) + return false; break; } case ui_menuset: @@ -767,40 +1059,42 @@ void LyX::readUIFile(string const & name) break; } } + return true; } // Read the languages file `name' -void LyX::readLanguagesFile(string const & name) +bool LyX::readLanguagesFile(string const & name) { lyxerr[Debug::INIT] << "About to read " << name << "..." << endl; string const lang_path = libFileSearch(string(), name); if (lang_path.empty()) { showFileError(name); - return; + return false; } languages.read(lang_path); + return true; } // Read the encodings file `name' -void LyX::readEncodingsFile(string const & name) +bool LyX::readEncodingsFile(string const & name) { lyxerr[Debug::INIT] << "About to read " << name << "..." << endl; string const enc_path = libFileSearch(string(), name); if (enc_path.empty()) { showFileError(name); - return; + return false; } encodings.read(enc_path); + return true; } namespace { -bool is_gui = true; string batch; /// return the the number of arguments consumed @@ -809,11 +1103,11 @@ typedef boost::function cmd_helper; int parse_dbg(string const & arg, string const &) { if (arg.empty()) { - lyxerr << _("List of supported debug flags:") << endl; + lyxerr << to_utf8(_("List of supported debug flags:")) << endl; Debug::showTags(lyxerr); exit(0); } - lyxerr << bformat(_("Setting debug level to %1$s"), 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()); @@ -824,7 +1118,7 @@ int parse_dbg(string const & arg, string const &) int parse_help(string const &, string const &) { lyxerr << - _("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" @@ -841,7 +1135,7 @@ int parse_help(string const &, string const &) " where fmt is the import format of choice\n" " and file.xxx is the file to be imported.\n" "\t-version summarize version and build info\n" - "Check the LyX man page for more details.") << endl; + "Check the LyX man page for more details.")) << endl; exit(0); return 0; } @@ -849,7 +1143,7 @@ int parse_help(string const &, string const &) int parse_version(string const &, string const &) { lyxerr << "LyX " << lyx_version - << " of " << lyx_release_date << endl; + << " (" << lyx_release_date << ")" << endl; lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl; lyxerr << lyx_version_info << endl; @@ -860,7 +1154,7 @@ int parse_version(string const &, string const &) int parse_sysdir(string const & arg, string const &) { if (arg.empty()) { - lyxerr << _("Missing directory for -sysdir switch") << endl; + lyxerr << to_utf8(_("Missing directory for -sysdir switch")) << endl; exit(1); } cl_system_support = arg; @@ -870,7 +1164,7 @@ int parse_sysdir(string const & arg, string const &) int parse_userdir(string const & arg, string const &) { if (arg.empty()) { - lyxerr << _("Missing directory for -userdir switch") << endl; + lyxerr << to_utf8(_("Missing directory for -userdir switch")) << endl; exit(1); } cl_user_support = arg; @@ -880,7 +1174,7 @@ int parse_userdir(string const & arg, string const &) int parse_execute(string const & arg, string const &) { if (arg.empty()) { - lyxerr << _("Missing command string after --execute switch") << endl; + lyxerr << to_utf8(_("Missing command string after --execute switch")) << endl; exit(1); } batch = arg; @@ -890,24 +1184,24 @@ int parse_execute(string const & arg, string const &) int parse_export(string const & type, string const &) { if (type.empty()) { - lyxerr << _("Missing file type [eg latex, ps...] after " - "--export switch") << endl; + lyxerr << to_utf8(_("Missing file type [eg latex, ps...] after " + "--export switch")) << endl; exit(1); } batch = "buffer-export " + type; - is_gui = false; + use_gui = false; return 1; } int parse_import(string const & type, string const & file) { if (type.empty()) { - lyxerr << _("Missing file type [eg latex, ps...] after " - "--import switch") << endl; + lyxerr << to_utf8(_("Missing file type [eg latex, ps...] after " + "--import switch")) << endl; exit(1); } if (file.empty()) { - lyxerr << _("Missing filename for --import") << endl; + lyxerr << to_utf8(_("Missing filename for --import")) << endl; exit(1); } @@ -918,7 +1212,7 @@ int parse_import(string const & type, string const & file) } // namespace anon -bool LyX::easyParse(int & argc, char * argv[]) +void LyX::easyParse(int & argc, char * argv[]) { std::map cmdmap; @@ -940,6 +1234,10 @@ bool LyX::easyParse(int & argc, char * argv[]) std::map::const_iterator it = cmdmap.find(argv[i]); + // check for X11 -geometry option + if (support::compare(argv[i], "-geometry") == 0) + geometryOption_ = true; + // don't complain if not found - may be parsed later if (it == cmdmap.end()) continue; @@ -958,6 +1256,53 @@ bool LyX::easyParse(int & argc, char * argv[]) } batch_command = batch; +} + - return is_gui; +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