} // namespace anon
-void lyx_gui::parse_init(int & argc, char * argv[])
+void lyx_gui::exec(int & argc, char * argv[])
{
new Gtk::Main(argc, argv);
// must do this /before/ lyxrc gets read
lyxrc.dpi = getDPI();
+
+ LyX::ref().exec2(argc, argv);
}
}
-void lyx_gui::exit()
+void lyx_gui::exit(int /*status*/)
{
+ // FIXME: Don't ignore status
Gtk::Main::quit();
}
/// return a suitable monospaced font name (called from non-gui context too !)
std::string const typewriter_font_name();
-/// parse command line and do basic initialisation
-void parse_init(int & argc, char * argv[]);
-
/**
* set up GUI parameters. At this point lyxrc may
* be used.
* batch commands, and loading the given documents
*/
void start(std::string const & batch, std::vector<std::string> const & files,
- unsigned int width, unsigned int height, int posx, int posy);
+ unsigned int width, unsigned int height, int posx, int posy);
+
+/**
+ * Enter the main event loop (\sa LyX::exec2)
+ */
+void exec(int & argc, char * argv[]);
/**
* Synchronise all pending events.
/**
* quit running LyX
*/
-void exit();
+void exit(int);
/**
* return the status flag for a given action. This can be used to tell
extern BufferList bufferlist;
+// FIXME: wrong place !
+LyXServer * lyxserver;
+LyXServerSocket * lyxsocket;
+
namespace {
int getDPI()
map<int, shared_ptr<socket_callback> > socket_callbacks;
-} // namespace anon
+void cleanup()
+{
+ delete lyxsocket;
+ lyxsocket = 0;
+ delete lyxserver;
+ lyxserver = 0;
+}
-// FIXME: wrong place !
-LyXServer * lyxserver;
-LyXServerSocket * lyxsocket;
+} // namespace anon
// in QLyXKeySym.C
extern void initEncodings();
#endif
#ifdef Q_WS_MACX
-extern bool macEventFilter(EventRef event);
extern pascal OSErr
handleOpenDocuments(const AppleEvent* inEvent, AppleEvent* /*reply*/,
long /*refCon*/);
bool use_gui = true;
-void parse_init(int & argc, char * argv[])
+
+void exec(int & argc, char * argv[])
{
// Force adding of font path _before_ QApplication is initialized
FontLoader::initFontPath();
- static LQApplication app(argc, argv);
+ LQApplication app(argc, argv);
#if QT_VERSION >= 0x030200
// install translation file for Qt built-in dialogs
// These are only installed since Qt 3.2.x
- static QTranslator qt_trans(0);
+ QTranslator qt_trans(0);
if (qt_trans.load(QString("qt_") + QTextCodec::locale(),
qInstallPathTranslations())) {
- app.installTranslator(&qt_trans);
+ qApp->installTranslator(&qt_trans);
// even if the language calls for RtL, don't do that
- app.setReverseLayout(false);
+ qApp->setReverseLayout(false);
lyxerr[Debug::GUI]
<< "Successfully installed Qt translations for locale "
<< QTextCodec::locale() << std::endl;
// These translations are meant to break Qt/Mac menu merging
// algorithm on some entries. It lists the menu names that
// should not be moved to the LyX menu
- static QTranslator aqua_trans(0);
+ QTranslator aqua_trans(0);
aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setting", 0,
"do_not_merge_me"));
aqua_trans.insert(QTranslatorMessage("QMenuBar", "Config", 0,
aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setup", 0,
"do_not_merge_me"));
- app.installTranslator(&aqua_trans);
+ qApp->installTranslator(&aqua_trans);
#endif
using namespace lyx::graphics;
lyxrc.dpi = getDPI();
LoaderQueue::setPriority(10,100);
+
+ LyX::ref().exec2(argc, argv);
}
qApp->exec();
// FIXME
- delete lyxsocket;
- delete lyxserver;
- lyxserver = 0;
+ cleanup();
}
}
-void exit()
+void exit(int status)
{
- delete lyxsocket;
- delete lyxserver;
- lyxserver = 0;
+ cleanup();
- // we cannot call qApp->exit(0) - that could return us
+ // we cannot call QApplication::exit(status) - that could return us
// into a static dialog return in the lyx code (for example,
// load autosave file QMessageBox. We have to just get the hell
// out.
- ::exit(0);
+ ::exit(status);
}
extern BufferList bufferlist;
+// FIXME: wrong place !
+LyXServer * lyxserver;
+LyXServerSocket * lyxsocket;
+
namespace {
int getDPI()
map<int, shared_ptr<socket_callback> > socket_callbacks;
-} // namespace anon
+void cleanup()
+{
+ delete lyxsocket;
+ lyxsocket = 0;
+ delete lyxserver;
+ lyxserver = 0;
+}
-// FIXME: wrong place !
-LyXServer * lyxserver;
-LyXServerSocket * lyxsocket;
+} // namespace anon
// in QLyXKeySym.C
extern void initEncodings();
#endif
-namespace {
-
-LQApplication * app = 0;
-
-}
-
-
namespace lyx_gui {
bool use_gui = true;
-void parse_init(int & argc, char * argv[])
-{
- /*
- FIXME : Abdel 29/05/2006 (younes.a@free.fr)
- reorganize this code. In particular make sure that this
- advise from Qt documentation is respected:
-
- Since the QApplication object does so much initialization, it
- must be created before any other objects related to the user
- interface are created.
-
- Right now this is not the case. For example, the call to
- "FontLoader::initFontPath()" below is doned before the QApplication
- creation. Moreover, I suspect that a number of global variables
- contains Qt object that are initialized before the passage through
- parse_init(). This might also explain the message displayed by Qt
- that caused the hanging:
-
- QObject::killTimer: timers cannot be stopped from another thread
- */
+void exec(int & argc, char * argv[])
+{
// Force adding of font path _before_ QApplication is initialized
FontLoader::initFontPath();
-#ifdef Q_WS_WIN
- static QApplication win_app(argc, argv);
-#else
- app = new LQApplication(argc, argv);
-#endif
+ LQApplication app(argc, argv);
// install translation file for Qt built-in dialogs
// These are only installed since Qt 3.2.x
- static QTranslator qt_trans(0);
+ QTranslator qt_trans(0);
if (qt_trans.load(QString("qt_") + QTextCodec::locale(),
qInstallPathTranslations())) {
qApp->installTranslator(&qt_trans);
// These translations are meant to break Qt/Mac menu merging
// algorithm on some entries. It lists the menu names that
// should not be moved to the LyX menu
- static QTranslator aqua_trans(0);
+ QTranslator aqua_trans(0);
aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setting", 0,
"do_not_merge_me"));
aqua_trans.insert(QTranslatorMessage("QMenuBar", "Config", 0,
lyxrc.dpi = getDPI();
LoaderQueue::setPriority(10,100);
+
+ LyX::ref().exec2(argc, argv);
}
qApp->exec();
// FIXME
- delete lyxsocket;
- delete lyxserver;
- lyxserver = 0;
- delete app;
+ cleanup();
}
}
-void exit()
+void exit(int status)
{
- delete lyxsocket;
- delete lyxserver;
- lyxserver = 0;
+ cleanup();
- // we cannot call qApp->exit(0) - that could return us
+ // we cannot call QApplication::exit(status) - that could return us
// into a static dialog return in the lyx code (for example,
// load autosave file QMessageBox. We have to just get the hell
// out.
- ::exit(0);
+ ::exit(status);
}
/// quit lyx
bool finished = false;
+int exit_status = 0;
/// estimate DPI from X server
int getDPI()
bool use_gui = true;
-void parse_init(int & argc, char * argv[])
+void exec(int & argc, char * argv[])
{
setDefaults();
lyxrc.dpi = getDPI();
LoaderQueue::setPriority(10,100);
+
+ LyX::ref().exec2(argc, argv);
}
// FIXME: breaks emergencyCleanup
delete lyxsocket;
delete lyxserver;
+ ::exit(exit_status);
}
-void exit()
+void exit(int status)
{
finished = true;
+ exit_status = status;
}
Alert::warning(_("Unable to remove temporary directory"), msg);
}
- lyx_gui::exit();
+ lyx_gui::exit(0);
}
string cl_user_support;
+void lyx_exit(int status)
+{
+ // FIXME: We should not directly call exit(), since it only
+ // guarantees a return to the system, no application cleanup.
+ // This may cause troubles with not executed destructors.
+ if (lyx_gui::use_gui)
+ lyx_gui::exit(status);
+ exit(status);
+}
+
+
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);
+ lyx_exit(EXIT_FAILURE);
}
{
// 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);
+ lyx_gui::use_gui = easyParse(argc, argv);
lyx::support::init_package(argv[0], cl_system_support, cl_user_support,
lyx::support::top_build_dir_is_one_level_up);
- if (want_gui)
- lyx_gui::parse_init(argc, argv);
+ // Start the real execution loop.
+ if (lyx_gui::use_gui)
+ lyx_gui::exec(argc, argv);
+ else
+ exec2(argc, argv);
+}
+
+void LyX::exec2(int & argc, char * argv[])
+{
// check for any spurious extra arguments
// other than documents
for (int argi = 1; argi < argc ; ++argi) {
// Initialization of LyX (reads lyxrc and more)
lyxerr[Debug::INIT] << "Initializing LyX::init..." << endl;
- init(want_gui);
+ init();
lyxerr[Debug::INIT] << "Initializing LyX::init...done" << endl;
- if (want_gui)
+ if (lyx_gui::use_gui)
lyx_gui::parse_lyxrc();
vector<string> files;
bool success = false;
if (last_loaded->dispatch(batch_command, &success)) {
quitLyX(false);
- exit(!success);
+ lyx_exit(!success);
}
}
files.clear(); // the files are already loaded
}
- if (want_gui) {
+ if (lyx_gui::use_gui) {
// determine windows size and position, from lyxrc and/or session
// initial geometry
unsigned int width = 690;
}
// if lyxrc returns (0,0), then use session info
else {
- string val = LyX::ref().session().loadSessionInfo("WindowWidth");
+ string val = session().loadSessionInfo("WindowWidth");
if (!val.empty())
width = convert<unsigned int>(val);
- val = LyX::ref().session().loadSessionInfo("WindowHeight");
+ val = session().loadSessionInfo("WindowHeight");
if (!val.empty())
height = convert<unsigned int>(val);
}
int posx = -1;
int posy = -1;
if (lyxrc.geometry_xysaved) {
- string val = LyX::ref().session().loadSessionInfo("WindowPosX");
+ string val = session().loadSessionInfo("WindowPosX");
if (!val.empty())
posx = convert<int>(val);
- val = LyX::ref().session().loadSessionInfo("WindowPosY");
+ val = session().loadSessionInfo("WindowPosY");
if (!val.empty())
posy = convert<int>(val);
}
} else {
// Something went wrong above
quitLyX(false);
- exit(EXIT_FAILURE);
+ lyx_exit(EXIT_FAILURE);
}
}
}
-void LyX::init(bool gui)
+void LyX::init()
{
#ifdef SIGHUP
signal(SIGHUP, error_handler);
signal(SIGTERM, error_handler);
// SIGPIPE can be safely ignored.
- // Disable gui when easyparse says so
- lyx_gui::use_gui = gui;
-
lyxrc.tempdir_path = package().temp_dir();
lyxrc.document_path = package().document_dir();
// Check that user LyX directory is ok. We don't do that if
// running in batch mode.
- if (gui) {
+ if (lyx_gui::use_gui) {
if (queryUserLyXDir(package().explicit_user_support()))
reconfigureUserLyXDir();
} else {
lyxerr[Debug::INIT] << "Reading layouts..." << endl;
LyXSetStyle();
- if (gui) {
+ if (lyx_gui::use_gui) {
// Set up bindings
toplevel_keymap.reset(new kb_keymap);
defaultKeyBindings(toplevel_keymap.get());
// 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);
+ lyx_exit(EXIT_FAILURE);
}
if (lyxerr.debugging(Debug::INIT)) {
_("&Create directory"),
_("&Exit LyX"))) {
lyxerr << _("No user LyX directory. Exiting.") << endl;
- exit(1);
+ lyx_exit(EXIT_FAILURE);
}
lyxerr << bformat(_("LyX: Creating directory %1$s"),
// Failed, so let's exit.
lyxerr << _("Failed to create directory. Exiting.")
<< endl;
- exit(1);
+ lyx_exit(EXIT_FAILURE);
}
return true;
/// initial startup
class LyX : boost::noncopyable {
public:
+ /**
+ * Execute LyX. The startup sequence is as follows:
+ * -# LyX::exec()
+ * -# LyX::priv_exec()
+ * -# lyx_gui::exec()
+ * -# LyX::exec2()
+ * Step 3 is omitted if no gui is wanted. We need lyx_gui::exec()
+ * only to create the QApplication object in the qt frontend. All
+ * attempts with static and dynamically allocated QApplication
+ * objects lead either to harmless error messages on exit
+ * ("Mutex destroy failure") or crashes (OS X).
+ */
static void exec(int & argc, char * argv[]);
+ /// Execute LyX (inner execution loop, \sa exec)
+ void exec2(int & argc, char * argv[]);
static LyX & ref();
static LyX const & cref();
void priv_exec(int & argc, char * argv[]);
/// initial LyX set up
- void init(bool);
+ void init();
/// set up the default key bindings
void defaultKeyBindings(kb_keymap * kbmap);
/// set up the default dead key bindings if requested