]> git.lyx.org Git - lyx.git/blob - src/LyX.cpp
Use home made code for the bool facet.
[lyx.git] / src / LyX.cpp
1 /**
2  * \file LyX.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alfredo Braunstein
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author John Levon
10  * \author André Pönitz
11  *
12  * Full author contact details are available in file CREDITS.
13  */
14
15 #include <config.h>
16 #include <version.h>
17
18 #include "LyX.h"
19
20 #include "ConverterCache.h"
21 #include "Buffer.h"
22 #include "buffer_funcs.h"
23 #include "BufferList.h"
24 #include "Converter.h"
25 #include "debug.h"
26 #include "Encoding.h"
27 #include "ErrorList.h"
28 #include "Format.h"
29 #include "gettext.h"
30 #include "KeyMap.h"
31 #include "Language.h"
32 #include "Session.h"
33 #include "Color.h"
34 #include "callback.h"
35 #include "LyXAction.h"
36 #include "LyXFunc.h"
37 #include "Lexer.h"
38 #include "LyXRC.h"
39 #include "Server.h"
40 #include "ServerSocket.h"
41 #include "TextClassList.h"
42 #include "MenuBackend.h"
43 #include "Messages.h"
44 #include "Mover.h"
45 #include "ToolbarBackend.h"
46
47 #include "frontends/alert.h"
48 #include "frontends/Application.h"
49 #include "frontends/Dialogs.h"
50 #include "frontends/Gui.h"
51 #include "frontends/LyXView.h"
52
53 #include "support/environment.h"
54 #include "support/filetools.h"
55 #include "support/lyxlib.h"
56 #include "support/convert.h"
57 #include "support/ExceptionMessage.h"
58 #include "support/os.h"
59 #include "support/Package.h"
60 #include "support/Path.h"
61 #include "support/Systemcall.h"
62
63 #include <boost/bind.hpp>
64 #include <boost/filesystem/operations.hpp>
65
66 #include <algorithm>
67 #include <iostream>
68 #include <csignal>
69 #include <map>
70 #include <string>
71 #include <vector>
72
73
74 namespace lyx {
75
76 using support::addName;
77 using support::addPath;
78 using support::bformat;
79 using support::changeExtension;
80 using support::createDirectory;
81 using support::createLyXTmpDir;
82 using support::destroyDir;
83 using support::FileName;
84 using support::fileSearch;
85 using support::getEnv;
86 using support::i18nLibFileSearch;
87 using support::libFileSearch;
88 using support::package;
89 using support::prependEnvPath;
90 using support::rtrim;
91 using support::Systemcall;
92
93 namespace Alert = frontend::Alert;
94 namespace os = support::os;
95 namespace fs = boost::filesystem;
96
97 using std::endl;
98 using std::for_each;
99 using std::map;
100 using std::make_pair;
101 using std::string;
102 using std::vector;
103
104 #ifndef CXX_GLOBAL_CSTD
105 using std::exit;
106 using std::signal;
107 using std::system;
108 #endif
109
110
111 /// are we using the GUI at all?
112 /**
113 * We default to true and this is changed to false when the export feature is used.
114 */
115 bool use_gui = true;
116
117
118 namespace {
119
120 // Filled with the command line arguments "foo" of "-sysdir foo" or
121 // "-userdir foo".
122 string cl_system_support;
123 string cl_user_support;
124
125 std::string geometryArg;
126
127 LyX * singleton_ = 0;
128
129 void showFileError(string const & error)
130 {
131         Alert::warning(_("Could not read configuration file"),
132                        bformat(_("Error while reading the configuration file\n%1$s.\n"
133                            "Please check your installation."), from_utf8(error)));
134 }
135
136
137 void reconfigureUserLyXDir()
138 {
139         string const configure_command = package().configure_command();
140
141         lyxerr << to_utf8(_("LyX: reconfiguring user directory")) << endl;
142         support::Path p(package().user_support());
143         Systemcall one;
144         one.startscript(Systemcall::Wait, configure_command);
145         lyxerr << "LyX: " << to_utf8(_("Done!")) << endl;
146 }
147
148 } // namespace anon
149
150
151 /// The main application class private implementation.
152 struct LyX::Singletons
153 {
154         Singletons()
155         {
156                 // Set the default User Interface language as soon as possible.
157                 // The language used will be derived from the environment
158                 // variables.
159                 messages_["GUI"] = Messages();
160         }
161         /// our function handler
162         LyXFunc lyxfunc_;
163         ///
164         BufferList buffer_list_;
165         ///
166         boost::scoped_ptr<KeyMap> toplevel_keymap_;
167         ///
168         boost::scoped_ptr<Server> lyx_server_;
169         ///
170         boost::scoped_ptr<ServerSocket> lyx_socket_;
171         ///
172         boost::scoped_ptr<frontend::Application> application_;
173         /// lyx session, containing lastfiles, lastfilepos, and lastopened
174         boost::scoped_ptr<Session> session_;
175
176         /// Files to load at start.
177         vector<FileName> files_to_load_;
178
179         /// The messages translators.
180         map<string, Messages> messages_;
181
182         /// The file converters.
183         Converters converters_;
184
185         // The system converters copy after reading lyxrc.defaults.
186         Converters system_converters_;
187
188         ///
189         Movers movers_;
190
191         ///
192         Movers system_movers_;
193 };
194
195 ///
196 frontend::Application * theApp()
197 {
198         if (singleton_)
199                 return singleton_->pimpl_->application_.get();
200         else
201                 return 0;
202 }
203
204
205 LyX::~LyX()
206 {
207 }
208
209
210 LyX & LyX::ref()
211 {
212         BOOST_ASSERT(singleton_);
213         return *singleton_;
214 }
215
216
217 LyX const & LyX::cref()
218 {
219         BOOST_ASSERT(singleton_);
220         return *singleton_;
221 }
222
223
224 LyX::LyX()
225         : first_start(false)
226 {
227         singleton_ = this;
228         pimpl_.reset(new Singletons);
229 }
230
231
232 BufferList & LyX::bufferList()
233 {
234         return pimpl_->buffer_list_;
235 }
236
237
238 BufferList const & LyX::bufferList() const
239 {
240         return pimpl_->buffer_list_;
241 }
242
243
244 Session & LyX::session()
245 {
246         BOOST_ASSERT(pimpl_->session_.get());
247         return *pimpl_->session_.get();
248 }
249
250
251 Session const & LyX::session() const
252 {
253         BOOST_ASSERT(pimpl_->session_.get());
254         return *pimpl_->session_.get();
255 }
256
257
258 LyXFunc & LyX::lyxFunc()
259 {
260         return pimpl_->lyxfunc_;
261 }
262
263
264 LyXFunc const & LyX::lyxFunc() const
265 {
266         return pimpl_->lyxfunc_;
267 }
268
269
270 Server & LyX::server()
271 {
272         BOOST_ASSERT(pimpl_->lyx_server_.get());
273         return *pimpl_->lyx_server_.get();
274 }
275
276
277 Server const & LyX::server() const
278 {
279         BOOST_ASSERT(pimpl_->lyx_server_.get());
280         return *pimpl_->lyx_server_.get();
281 }
282
283
284 ServerSocket & LyX::socket()
285 {
286         BOOST_ASSERT(pimpl_->lyx_socket_.get());
287         return *pimpl_->lyx_socket_.get();
288 }
289
290
291 ServerSocket const & LyX::socket() const
292 {
293         BOOST_ASSERT(pimpl_->lyx_socket_.get());
294         return *pimpl_->lyx_socket_.get();
295 }
296
297
298 frontend::Application & LyX::application()
299 {
300         BOOST_ASSERT(pimpl_->application_.get());
301         return *pimpl_->application_.get();
302 }
303
304
305 frontend::Application const & LyX::application() const
306 {
307         BOOST_ASSERT(pimpl_->application_.get());
308         return *pimpl_->application_.get();
309 }
310
311
312 KeyMap & LyX::topLevelKeymap()
313 {
314         BOOST_ASSERT(pimpl_->toplevel_keymap_.get());
315         return *pimpl_->toplevel_keymap_.get();
316 }
317
318
319 Converters & LyX::converters()
320 {
321         return pimpl_->converters_;
322 }
323
324
325 Converters & LyX::systemConverters()
326 {
327         return pimpl_->system_converters_;
328 }
329
330
331 KeyMap const & LyX::topLevelKeymap() const
332 {
333         BOOST_ASSERT(pimpl_->toplevel_keymap_.get());
334         return *pimpl_->toplevel_keymap_.get();
335 }
336
337
338 Messages & LyX::getMessages(std::string const & language)
339 {
340         map<string, Messages>::iterator it = pimpl_->messages_.find(language);
341
342         if (it != pimpl_->messages_.end())
343                 return it->second;
344
345         std::pair<map<string, Messages>::iterator, bool> result =
346                         pimpl_->messages_.insert(std::make_pair(language, Messages(language)));
347
348         BOOST_ASSERT(result.second);
349         return result.first->second;
350 }
351
352
353 Messages & LyX::getGuiMessages()
354 {
355         return pimpl_->messages_["GUI"];
356 }
357
358
359 void LyX::setGuiLanguage(std::string const & language)
360 {
361         pimpl_->messages_["GUI"] = Messages(language);
362 }
363
364
365 Buffer const * const LyX::updateInset(Inset const * inset) const
366 {
367         if (quitting || !inset)
368                 return 0;
369
370         Buffer const * buffer_ptr = 0;
371         vector<int> const & view_ids = pimpl_->application_->gui().viewIds();
372         vector<int>::const_iterator it = view_ids.begin();
373         vector<int>::const_iterator const end = view_ids.end();
374         for (; it != end; ++it) {
375                 Buffer const * ptr =
376                         pimpl_->application_->gui().view(*it).updateInset(inset);
377                 if (ptr)
378                         buffer_ptr = ptr;
379         }
380         return buffer_ptr;
381 }
382
383
384 void LyX::hideDialogs(std::string const & name, Inset * inset) const
385 {
386         if (quitting)
387                 return;
388
389         vector<int> const & view_ids = pimpl_->application_->gui().viewIds();
390         vector<int>::const_iterator it = view_ids.begin();
391         vector<int>::const_iterator const end = view_ids.end();
392         for (; it != end; ++it)
393                 pimpl_->application_->gui().view(*it).getDialogs().
394                         hide(name, inset);
395 }
396
397
398 int LyX::exec(int & argc, char * argv[])
399 {
400         // Here we need to parse the command line. At least
401         // we need to parse for "-dbg" and "-help"
402         easyParse(argc, argv);
403
404         try { support::init_package(to_utf8(from_local8bit(argv[0])),
405                               cl_system_support, cl_user_support,
406                               support::top_build_dir_is_one_level_up);
407         } catch (support::ExceptionMessage const & message) {
408                 if (message.type_ == support::ErrorException) {
409                         Alert::error(message.title_, message.details_);
410                         exit(1);
411                 } else if (message.type_ == support::WarningException) {
412                         Alert::warning(message.title_, message.details_);
413                 }
414         }
415
416         if (!use_gui) {
417                 // FIXME: create a ConsoleApplication
418                 int exit_status = init(argc, argv);
419                 if (exit_status) {
420                         prepareExit();
421                         return exit_status;
422                 }
423
424                 loadFiles();
425
426                 if (batch_command.empty() || pimpl_->buffer_list_.empty()) {
427                         prepareExit();
428                         return EXIT_SUCCESS;
429                 }
430
431                 BufferList::iterator begin = pimpl_->buffer_list_.begin();
432                 BufferList::iterator end = pimpl_->buffer_list_.end();
433
434                 bool final_success = false;
435                 for (BufferList::iterator I = begin; I != end; ++I) {
436                         Buffer * buf = *I;
437                         bool success = false;
438                         buf->dispatch(batch_command, &success);
439                         final_success |= success;
440                 }
441                 prepareExit();
442                 return !final_success;
443         }
444
445         // Force adding of font path _before_ Application is initialized
446         support::os::addFontResources();
447
448         // Let the frontend parse and remove all arguments that it knows
449         pimpl_->application_.reset(createApplication(argc, argv));
450
451         initGuiFont();
452
453         // Parse and remove all known arguments in the LyX singleton
454         // Give an error for all remaining ones.
455         int exit_status = init(argc, argv);
456         if (exit_status) {
457                 // Kill the application object before exiting.
458                 pimpl_->application_.reset();
459                 use_gui = false;
460                 prepareExit();
461                 return exit_status;
462         }
463
464         // FIXME
465         /* Create a CoreApplication class that will provide the main event loop
466         * and the socket callback registering. With Qt4, only QtCore
467         * library would be needed.
468         * When this is done, a server_mode could be created and the following two
469         * line would be moved out from here.
470         */
471         // Note: socket callback must be registered after init(argc, argv)
472         // such that package().temp_dir() is properly initialized.
473         pimpl_->lyx_server_.reset(new Server(&pimpl_->lyxfunc_, lyxrc.lyxpipes));
474         pimpl_->lyx_socket_.reset(new ServerSocket(&pimpl_->lyxfunc_,
475                         FileName(package().temp_dir().absFilename() + "/lyxsocket")));
476
477         // Start the real execution loop.
478         exit_status = pimpl_->application_->exec();
479
480         prepareExit();
481
482         // Restore original font resources after Application is destroyed.
483         support::os::restoreFontResources();
484
485         return exit_status;
486 }
487
488
489 void LyX::prepareExit()
490 {
491         // Set a flag that we do quitting from the program,
492         // so no refreshes are necessary.
493         quitting = true;
494
495         // close buffers first
496         pimpl_->buffer_list_.closeAll();
497
498         // do any other cleanup procedures now
499         if (package().temp_dir() != package().system_temp_dir()) {
500                 LYXERR(Debug::INFO) << "Deleting tmp dir "
501                                     << package().temp_dir().absFilename() << endl;
502
503                 if (!destroyDir(package().temp_dir())) {
504                         docstring const msg =
505                                 bformat(_("Unable to remove the temporary directory %1$s"),
506                                 from_utf8(package().temp_dir().absFilename()));
507                         Alert::warning(_("Unable to remove temporary directory"), msg);
508                 }
509         }
510
511         if (use_gui) {
512                 if (pimpl_->session_)
513                         pimpl_->session_->writeFile();
514                 pimpl_->session_.reset();
515                 pimpl_->lyx_server_.reset();
516                 pimpl_->lyx_socket_.reset();
517         }
518
519         // Kill the application object before exiting. This avoids crashes
520         // when exiting on Linux.
521         if (pimpl_->application_)
522                 pimpl_->application_.reset();
523 }
524
525
526 void LyX::earlyExit(int status)
527 {
528         BOOST_ASSERT(pimpl_->application_.get());
529         // LyX::pimpl_::application_ is not initialised at this
530         // point so it's safe to just exit after some cleanup.
531         prepareExit();
532         exit(status);
533 }
534
535
536 int LyX::init(int & argc, char * argv[])
537 {
538         // check for any spurious extra arguments
539         // other than documents
540         for (int argi = 1; argi < argc ; ++argi) {
541                 if (argv[argi][0] == '-') {
542                         lyxerr << to_utf8(
543                                 bformat(_("Wrong command line option `%1$s'. Exiting."),
544                                 from_utf8(argv[argi]))) << endl;
545                         return EXIT_FAILURE;
546                 }
547         }
548
549         // Initialization of LyX (reads lyxrc and more)
550         LYXERR(Debug::INIT) << "Initializing LyX::init..." << endl;
551         bool success = init();
552         LYXERR(Debug::INIT) << "Initializing LyX::init...done" << endl;
553         if (!success)
554                 return EXIT_FAILURE;
555
556         for (int argi = argc - 1; argi >= 1; --argi) {
557                 // get absolute path of file and add ".lyx" to
558                 // the filename if necessary
559                 pimpl_->files_to_load_.push_back(fileSearch(string(),
560                         os::internal_path(to_utf8(from_local8bit(argv[argi]))),
561                         "lyx", support::allow_unreadable));
562         }
563
564         if (first_start)
565                 pimpl_->files_to_load_.push_back(i18nLibFileSearch("examples", "splash.lyx"));
566
567         return EXIT_SUCCESS;
568 }
569
570
571 void LyX::addFileToLoad(FileName const & fname)
572 {
573         vector<FileName>::const_iterator cit = std::find(
574                 pimpl_->files_to_load_.begin(), pimpl_->files_to_load_.end(),
575                 fname);
576
577         if (cit == pimpl_->files_to_load_.end())
578                 pimpl_->files_to_load_.push_back(fname);
579 }
580
581
582 void LyX::loadFiles()
583 {
584         vector<FileName>::const_iterator it = pimpl_->files_to_load_.begin();
585         vector<FileName>::const_iterator end = pimpl_->files_to_load_.end();
586
587         for (; it != end; ++it) {
588                 if (it->empty())
589                         continue;
590
591                 Buffer * buf = pimpl_->buffer_list_.newBuffer(it->absFilename(), false);
592                 if (loadLyXFile(buf, *it)) {
593                         ErrorList const & el = buf->errorList("Parse");
594                         if (!el.empty())
595                                 for_each(el.begin(), el.end(),
596                                 boost::bind(&LyX::printError, this, _1));
597                 }
598                 else
599                         pimpl_->buffer_list_.release(buf);
600         }
601 }
602
603
604 void LyX::execBatchCommands()
605 {
606         // The advantage of doing this here is that the event loop
607         // is already started. So any need for interaction will be
608         // aknowledged.
609         restoreGuiSession();
610
611         // Execute batch commands if available
612         if (batch_command.empty())
613                 return;
614
615         LYXERR(Debug::INIT) << "About to handle -x '"
616                 << batch_command << '\'' << endl;
617
618         pimpl_->lyxfunc_.dispatch(lyxaction.lookupFunc(batch_command));
619 }
620
621
622 void LyX::restoreGuiSession()
623 {
624         LyXView * view = newLyXView();
625
626         // if some files were specified at command-line we assume that the
627         // user wants to edit *these* files and not to restore the session.
628         if (!pimpl_->files_to_load_.empty()) {
629                 for_each(pimpl_->files_to_load_.begin(),
630                         pimpl_->files_to_load_.end(),
631                         bind(&LyXView::loadLyXFile, view, _1, true, false, false));
632                 // clear this list to save a few bytes of RAM
633                 pimpl_->files_to_load_.clear();
634                 pimpl_->session_->lastOpened().clear();
635                 return;
636         }
637
638         if (!lyxrc.load_session)
639                 return;
640
641         vector<FileName> const & lastopened = pimpl_->session_->lastOpened().getfiles();
642         // do not add to the lastfile list since these files are restored from
643         // last session, and should be already there (regular files), or should
644         // not be added at all (help files).
645         for_each(lastopened.begin(), lastopened.end(),
646                 bind(&LyXView::loadLyXFile, view, _1, false, false, false));
647
648         // clear this list to save a few bytes of RAM
649         pimpl_->session_->lastOpened().clear();
650 }
651
652
653 LyXView * LyX::newLyXView()
654 {
655         if (!lyx::use_gui)
656                 return 0;
657
658         // determine windows size and position, from lyxrc and/or session
659         // initial geometry
660         unsigned int width = 690;
661         unsigned int height = 510;
662         // default icon size, will be overwritten by  stored session value
663         unsigned int iconSizeXY = 0;
664         int maximized = LyXView::NotMaximized;
665         // first try lyxrc
666         if (lyxrc.geometry_width != 0 && lyxrc.geometry_height != 0 ) {
667                 width = lyxrc.geometry_width;
668                 height = lyxrc.geometry_height;
669         }
670         // if lyxrc returns (0,0), then use session info
671         else {
672                 string val = session().sessionInfo().load("WindowWidth");
673                 if (!val.empty())
674                         width = convert<unsigned int>(val);
675                 val = session().sessionInfo().load("WindowHeight");
676                 if (!val.empty())
677                         height = convert<unsigned int>(val);
678                 val = session().sessionInfo().load("WindowMaximized");
679                 if (!val.empty())
680                         maximized = convert<int>(val);
681                 val = session().sessionInfo().load("IconSizeXY");
682                 if (!val.empty())
683                         iconSizeXY = convert<unsigned int>(val);
684         }
685
686         // if user wants to restore window position
687         int posx = -1;
688         int posy = -1;
689         if (lyxrc.geometry_xysaved) {
690                 string val = session().sessionInfo().load("WindowPosX");
691                 if (!val.empty())
692                         posx = convert<int>(val);
693                 val = session().sessionInfo().load("WindowPosY");
694                 if (!val.empty())
695                         posy = convert<int>(val);
696         }
697
698         if (!geometryArg.empty())
699         {
700                 width = 0;
701                 height = 0;
702         }
703
704         // create the main window
705         LyXView * view = &pimpl_->application_->createView(width, height, posx, posy, maximized, iconSizeXY, geometryArg);
706
707         return view;
708 }
709
710 /*
711 Signals and Windows
712 ===================
713 The SIGHUP signal does not exist on Windows and does not need to be handled.
714
715 Windows handles SIGFPE and SIGSEGV signals as expected.
716
717 Cntl+C interrupts (mapped to SIGINT by Windows' POSIX compatability layer)
718 cause a new thread to be spawned. This may well result in unexpected
719 behaviour by the single-threaded LyX.
720
721 SIGTERM signals will come only from another process actually sending
722 that signal using 'raise' in Windows' POSIX compatability layer. It will
723 not come from the general "terminate process" methods that everyone
724 actually uses (and which can't be trapped). Killing an app 'politely' on
725 Windows involves first sending a WM_CLOSE message, something that is
726 caught already by the Qt frontend.
727
728 For more information see:
729
730 http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/2034055
731 ...signals are mostly useless on Windows for a variety of reasons that are
732 Windows specific...
733
734 'UNIX Application Migration Guide, Chapter 9'
735 http://msdn.microsoft.com/library/en-us/dnucmg/html/UCMGch09.asp
736
737 'How To Terminate an Application "Cleanly" in Win32'
738 http://support.microsoft.com/default.aspx?scid=kb;en-us;178893
739 */
740 extern "C" {
741
742 static void error_handler(int err_sig)
743 {
744         // Throw away any signals other than the first one received.
745         static sig_atomic_t handling_error = false;
746         if (handling_error)
747                 return;
748         handling_error = true;
749
750         // We have received a signal indicating a fatal error, so
751         // try and save the data ASAP.
752         LyX::cref().emergencyCleanup();
753
754         // These lyxerr calls may or may not work:
755
756         // Signals are asynchronous, so the main program may be in a very
757         // fragile state when a signal is processed and thus while a signal
758         // handler function executes.
759         // In general, therefore, we should avoid performing any
760         // I/O operations or calling most library and system functions from
761         // signal handlers.
762
763         // This shouldn't matter here, however, as we've already invoked
764         // emergencyCleanup.
765         switch (err_sig) {
766 #ifdef SIGHUP
767         case SIGHUP:
768                 lyxerr << "\nlyx: SIGHUP signal caught\nBye." << endl;
769                 break;
770 #endif
771         case SIGFPE:
772                 lyxerr << "\nlyx: SIGFPE signal caught\nBye." << endl;
773                 break;
774         case SIGSEGV:
775                 lyxerr << "\nlyx: SIGSEGV signal caught\n"
776                           "Sorry, you have found a bug in LyX. "
777                           "Please read the bug-reporting instructions "
778                           "in Help->Introduction and send us a bug report, "
779                           "if necessary. Thanks !\nBye." << endl;
780                 break;
781         case SIGINT:
782         case SIGTERM:
783                 // no comments
784                 break;
785         }
786
787         // Deinstall the signal handlers
788 #ifdef SIGHUP
789         signal(SIGHUP, SIG_DFL);
790 #endif
791         signal(SIGINT, SIG_DFL);
792         signal(SIGFPE, SIG_DFL);
793         signal(SIGSEGV, SIG_DFL);
794         signal(SIGTERM, SIG_DFL);
795
796 #ifdef SIGHUP
797         if (err_sig == SIGSEGV ||
798             (err_sig != SIGHUP && !getEnv("LYXDEBUG").empty()))
799 #else
800         if (err_sig == SIGSEGV || !getEnv("LYXDEBUG").empty())
801 #endif
802                 support::abort();
803         exit(0);
804 }
805
806 }
807
808
809 void LyX::printError(ErrorItem const & ei)
810 {
811         docstring tmp = _("LyX: ") + ei.error + char_type(':')
812                 + ei.description;
813         std::cerr << to_utf8(tmp) << std::endl;
814 }
815
816
817 void LyX::initGuiFont()
818 {
819         if (lyxrc.roman_font_name.empty())
820                 lyxrc.roman_font_name = pimpl_->application_->romanFontName();
821
822         if (lyxrc.sans_font_name.empty())
823                 lyxrc.sans_font_name = pimpl_->application_->sansFontName();
824
825         if (lyxrc.typewriter_font_name.empty())
826                 lyxrc.typewriter_font_name
827                         = pimpl_->application_->typewriterFontName();
828 }
829
830
831 bool LyX::init()
832 {
833 #ifdef SIGHUP
834         signal(SIGHUP, error_handler);
835 #endif
836         signal(SIGFPE, error_handler);
837         signal(SIGSEGV, error_handler);
838         signal(SIGINT, error_handler);
839         signal(SIGTERM, error_handler);
840         // SIGPIPE can be safely ignored.
841
842         lyxrc.tempdir_path = package().temp_dir().absFilename();
843         lyxrc.document_path = package().document_dir().absFilename();
844
845         if (lyxrc.template_path.empty()) {
846                 lyxrc.template_path = addPath(package().system_support().absFilename(),
847                                               "templates");
848         }
849
850         //
851         // Read configuration files
852         //
853
854         // This one may have been distributed along with LyX.
855         if (!readRcFile("lyxrc.dist"))
856                 return false;
857
858         // Set the language defined by the distributor.
859         //setGuiLanguage(lyxrc.gui_language);
860
861         // Set the PATH correctly.
862 #if !defined (USE_POSIX_PACKAGING)
863         // Add the directory containing the LyX executable to the path
864         // so that LyX can find things like tex2lyx.
865         if (package().build_support().empty())
866                 prependEnvPath("PATH", package().binary_dir().absFilename());
867 #endif
868         if (!lyxrc.path_prefix.empty())
869                 prependEnvPath("PATH", lyxrc.path_prefix);
870
871         // Check that user LyX directory is ok.
872         if (queryUserLyXDir(package().explicit_user_support()))
873                 reconfigureUserLyXDir();
874
875         // no need for a splash when there is no GUI
876         if (!use_gui) {
877                 first_start = false;
878         }
879
880         // This one is generated in user_support directory by lib/configure.py.
881         if (!readRcFile("lyxrc.defaults"))
882                 return false;
883
884         // Query the OS to know what formats are viewed natively
885         formats.setAutoOpen();
886
887         // Read lyxrc.dist again to be able to override viewer auto-detection.
888         readRcFile("lyxrc.dist");
889
890         system_lyxrc = lyxrc;
891         system_formats = formats;
892         pimpl_->system_converters_ = pimpl_->converters_;
893         pimpl_->system_movers_ = pimpl_->movers_;
894         system_lcolor = lcolor;
895
896         // This one is edited through the preferences dialog.
897         if (!readRcFile("preferences"))
898                 return false;
899
900         if (!readEncodingsFile("encodings", "unicodesymbols"))
901                 return false;
902         if (!readLanguagesFile("languages"))
903                 return false;
904
905         // Load the layouts
906         LYXERR(Debug::INIT) << "Reading layouts..." << endl;
907         if (!LyXSetStyle())
908                 return false;
909
910         if (use_gui) {
911                 // Set the language defined by the user.
912                 //setGuiLanguage(lyxrc.gui_language);
913
914                 // Set up bindings
915                 pimpl_->toplevel_keymap_.reset(new KeyMap);
916                 defaultKeyBindings(pimpl_->toplevel_keymap_.get());
917                 pimpl_->toplevel_keymap_->read(lyxrc.bind_file);
918
919                 pimpl_->lyxfunc_.initKeySequences(pimpl_->toplevel_keymap_.get());
920
921                 // Read menus
922                 if (!readUIFile(lyxrc.ui_file))
923                         return false;
924         }
925
926         if (lyxerr.debugging(Debug::LYXRC))
927                 lyxrc.print();
928
929         os::windows_style_tex_paths(lyxrc.windows_style_tex_paths);
930         if (!lyxrc.path_prefix.empty())
931                 prependEnvPath("PATH", lyxrc.path_prefix);
932
933         FileName const document_path(lyxrc.document_path);
934         if (fs::exists(document_path.toFilesystemEncoding()) &&
935             fs::is_directory(document_path.toFilesystemEncoding()))
936                 package().document_dir() = document_path;
937
938         package().temp_dir() = createLyXTmpDir(FileName(lyxrc.tempdir_path));
939         if (package().temp_dir().empty()) {
940                 Alert::error(_("Could not create temporary directory"),
941                              bformat(_("Could not create a temporary directory in\n"
942                                                     "%1$s. Make sure that this\n"
943                                                     "path exists and is writable and try again."),
944                                      from_utf8(lyxrc.tempdir_path)));
945                 // createLyXTmpDir() tries sufficiently hard to create a
946                 // usable temp dir, so the probability to come here is
947                 // close to zero. We therefore don't try to overcome this
948                 // problem with e.g. asking the user for a new path and
949                 // trying again but simply exit.
950                 return false;
951         }
952
953         LYXERR(Debug::INIT) << "LyX tmp dir: `"
954                             << package().temp_dir().absFilename()
955                             << '\'' << endl;
956
957         LYXERR(Debug::INIT) << "Reading session information '.lyx/session'..." << endl;
958         pimpl_->session_.reset(new Session(lyxrc.num_lastfiles));
959
960         // This must happen after package initialization and after lyxrc is
961         // read, therefore it can't be done by a static object.
962         ConverterCache::init();
963
964         return true;
965 }
966
967
968 void LyX::defaultKeyBindings(KeyMap  * kbmap)
969 {
970         kbmap->bind("Right", FuncRequest(LFUN_CHAR_FORWARD));
971         kbmap->bind("Left", FuncRequest(LFUN_CHAR_BACKWARD));
972         kbmap->bind("Up", FuncRequest(LFUN_UP));
973         kbmap->bind("Down", FuncRequest(LFUN_DOWN));
974
975         kbmap->bind("Tab", FuncRequest(LFUN_CELL_FORWARD));
976         kbmap->bind("C-Tab", FuncRequest(LFUN_CELL_SPLIT));
977         kbmap->bind("~S-ISO_Left_Tab", FuncRequest(LFUN_CELL_BACKWARD));
978         kbmap->bind("~S-BackTab", FuncRequest(LFUN_CELL_BACKWARD));
979
980         kbmap->bind("Home", FuncRequest(LFUN_LINE_BEGIN));
981         kbmap->bind("End", FuncRequest(LFUN_LINE_END));
982         kbmap->bind("Prior", FuncRequest(LFUN_SCREEN_UP));
983         kbmap->bind("Next", FuncRequest(LFUN_SCREEN_DOWN));
984
985         kbmap->bind("Return", FuncRequest(LFUN_BREAK_PARAGRAPH));
986         //kbmap->bind("~C-~S-~M-nobreakspace", FuncRequest(LFUN_PROTECTEDSPACE));
987
988         kbmap->bind("Delete", FuncRequest(LFUN_CHAR_DELETE_FORWARD));
989         kbmap->bind("BackSpace", FuncRequest(LFUN_CHAR_DELETE_BACKWARD));
990
991         // kbmap->bindings to enable the use of the numeric keypad
992         // e.g. Num Lock set
993         //kbmap->bind("KP_0", FuncRequest(LFUN_SELF_INSERT));
994         //kbmap->bind("KP_Decimal", FuncRequest(LFUN_SELF_INSERT));
995         kbmap->bind("KP_Enter", FuncRequest(LFUN_BREAK_PARAGRAPH));
996         //kbmap->bind("KP_1", FuncRequest(LFUN_SELF_INSERT));
997         //kbmap->bind("KP_2", FuncRequest(LFUN_SELF_INSERT));
998         //kbmap->bind("KP_3", FuncRequest(LFUN_SELF_INSERT));
999         //kbmap->bind("KP_4", FuncRequest(LFUN_SELF_INSERT));
1000         //kbmap->bind("KP_5", FuncRequest(LFUN_SELF_INSERT));
1001         //kbmap->bind("KP_6", FuncRequest(LFUN_SELF_INSERT));
1002         //kbmap->bind("KP_Add", FuncRequest(LFUN_SELF_INSERT));
1003         //kbmap->bind("KP_7", FuncRequest(LFUN_SELF_INSERT));
1004         //kbmap->bind("KP_8", FuncRequest(LFUN_SELF_INSERT));
1005         //kbmap->bind("KP_9", FuncRequest(LFUN_SELF_INSERT));
1006         //kbmap->bind("KP_Divide", FuncRequest(LFUN_SELF_INSERT));
1007         //kbmap->bind("KP_Multiply", FuncRequest(LFUN_SELF_INSERT));
1008         //kbmap->bind("KP_Subtract", FuncRequest(LFUN_SELF_INSERT));
1009         kbmap->bind("KP_Right", FuncRequest(LFUN_CHAR_FORWARD));
1010         kbmap->bind("KP_Left", FuncRequest(LFUN_CHAR_BACKWARD));
1011         kbmap->bind("KP_Up", FuncRequest(LFUN_UP));
1012         kbmap->bind("KP_Down", FuncRequest(LFUN_DOWN));
1013         kbmap->bind("KP_Home", FuncRequest(LFUN_LINE_BEGIN));
1014         kbmap->bind("KP_End", FuncRequest(LFUN_LINE_END));
1015         kbmap->bind("KP_Prior", FuncRequest(LFUN_SCREEN_UP));
1016         kbmap->bind("KP_Next", FuncRequest(LFUN_SCREEN_DOWN));
1017 }
1018
1019
1020 void LyX::emergencyCleanup() const
1021 {
1022         // what to do about tmpfiles is non-obvious. we would
1023         // like to delete any we find, but our lyxdir might
1024         // contain documents etc. which might be helpful on
1025         // a crash
1026
1027         pimpl_->buffer_list_.emergencyWriteAll();
1028         if (use_gui) {
1029                 if (pimpl_->lyx_server_)
1030                         pimpl_->lyx_server_->emergencyCleanup();
1031                 pimpl_->lyx_server_.reset();
1032                 pimpl_->lyx_socket_.reset();
1033         }
1034 }
1035
1036
1037 void LyX::deadKeyBindings(KeyMap * kbmap)
1038 {
1039         // bindKeyings for transparent handling of deadkeys
1040         // The keysyms are gotten from XFree86 X11R6
1041         kbmap->bind("~C-~S-~M-dead_acute", FuncRequest(LFUN_ACCENT_ACUTE));
1042         kbmap->bind("~C-~S-~M-dead_breve", FuncRequest(LFUN_ACCENT_BREVE));
1043         kbmap->bind("~C-~S-~M-dead_caron", FuncRequest(LFUN_ACCENT_CARON));
1044         kbmap->bind("~C-~S-~M-dead_cedilla", FuncRequest(LFUN_ACCENT_CEDILLA));
1045         kbmap->bind("~C-~S-~M-dead_abovering", FuncRequest(LFUN_ACCENT_CIRCLE));
1046         kbmap->bind("~C-~S-~M-dead_circumflex", FuncRequest(LFUN_ACCENT_CIRCUMFLEX));
1047         kbmap->bind("~C-~S-~M-dead_abovedot", FuncRequest(LFUN_ACCENT_DOT));
1048         kbmap->bind("~C-~S-~M-dead_grave", FuncRequest(LFUN_ACCENT_GRAVE));
1049         kbmap->bind("~C-~S-~M-dead_doubleacute", FuncRequest(LFUN_ACCENT_HUNGARIAN_UMLAUT));
1050         kbmap->bind("~C-~S-~M-dead_macron", FuncRequest(LFUN_ACCENT_MACRON));
1051         // nothing with this name
1052         // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_ACCENT_SPECIAL_CARON);
1053         kbmap->bind("~C-~S-~M-dead_tilde", FuncRequest(LFUN_ACCENT_TILDE));
1054         kbmap->bind("~C-~S-~M-dead_diaeresis", FuncRequest(LFUN_ACCENT_UMLAUT));
1055         // nothing with this name either...
1056         //kbmap->bind("~C-~S-~M-dead_underbar", FuncRequest(LFUN_ACCENT_UNDERBAR));
1057         kbmap->bind("~C-~S-~M-dead_belowdot", FuncRequest(LFUN_ACCENT_UNDERDOT));
1058         kbmap->bind("~C-~S-~M-dead_tie", FuncRequest(LFUN_ACCENT_TIE));
1059         kbmap->bind("~C-~S-~M-dead_ogonek",FuncRequest(LFUN_ACCENT_OGONEK));
1060 }
1061
1062
1063 namespace {
1064
1065 // return true if file does not exist or is older than configure.py.
1066 bool needsUpdate(string const & file)
1067 {
1068         // We cannot initialize configure_script directly because the package
1069         // is not initialized yet when  static objects are constructed.
1070         static string configure_script;
1071         static bool firstrun = true;
1072         if (firstrun) {
1073                 configure_script = FileName(addName(
1074                                 package().system_support().absFilename(),
1075                                 "configure.py")).toFilesystemEncoding();
1076                 firstrun = false;
1077         }
1078
1079         string const absfile = FileName(addName(
1080                 package().user_support().absFilename(), file)).toFilesystemEncoding();
1081         return (! fs::exists(absfile))
1082                 || (fs::last_write_time(configure_script)
1083                     > fs::last_write_time(absfile));
1084 }
1085
1086 }
1087
1088
1089 bool LyX::queryUserLyXDir(bool explicit_userdir)
1090 {
1091         // Does user directory exist?
1092         string const user_support =
1093                 package().user_support().toFilesystemEncoding();
1094         if (fs::exists(user_support) && fs::is_directory(user_support)) {
1095                 first_start = false;
1096
1097                 return needsUpdate("lyxrc.defaults")
1098                         || needsUpdate("textclass.lst")
1099                         || needsUpdate("packages.lst");
1100         }
1101
1102         first_start = !explicit_userdir;
1103
1104         // If the user specified explicitly a directory, ask whether
1105         // to create it. If the user says "no", then exit.
1106         if (explicit_userdir &&
1107             Alert::prompt(
1108                     _("Missing user LyX directory"),
1109                     bformat(_("You have specified a non-existent user "
1110                                            "LyX directory, %1$s.\n"
1111                                            "It is needed to keep your own configuration."),
1112                             from_utf8(package().user_support().absFilename())),
1113                     1, 0,
1114                     _("&Create directory"),
1115                     _("&Exit LyX"))) {
1116                 lyxerr << to_utf8(_("No user LyX directory. Exiting.")) << endl;
1117                 earlyExit(EXIT_FAILURE);
1118         }
1119
1120         lyxerr << to_utf8(bformat(_("LyX: Creating directory %1$s"),
1121                           from_utf8(package().user_support().absFilename())))
1122                << endl;
1123
1124         if (!createDirectory(package().user_support(), 0755)) {
1125                 // Failed, so let's exit.
1126                 lyxerr << to_utf8(_("Failed to create directory. Exiting."))
1127                        << endl;
1128                 earlyExit(EXIT_FAILURE);
1129         }
1130
1131         return true;
1132 }
1133
1134
1135 bool LyX::readRcFile(string const & name)
1136 {
1137         LYXERR(Debug::INIT) << "About to read " << name << "... ";
1138
1139         FileName const lyxrc_path = libFileSearch(string(), name);
1140         if (!lyxrc_path.empty()) {
1141
1142                 LYXERR(Debug::INIT) << "Found in " << lyxrc_path << endl;
1143
1144                 if (lyxrc.read(lyxrc_path) < 0) {
1145                         showFileError(name);
1146                         return false;
1147                 }
1148         } else
1149                 LYXERR(Debug::INIT) << "Not found." << lyxrc_path << endl;
1150         return true;
1151
1152 }
1153
1154
1155 // Read the ui file `name'
1156 bool LyX::readUIFile(string const & name, bool include)
1157 {
1158         enum Uitags {
1159                 ui_menuset = 1,
1160                 ui_toolbars,
1161                 ui_toolbarset,
1162                 ui_include,
1163                 ui_last
1164         };
1165
1166         struct keyword_item uitags[ui_last - 1] = {
1167                 { "include", ui_include },
1168                 { "menuset", ui_menuset },
1169                 { "toolbars", ui_toolbars },
1170                 { "toolbarset", ui_toolbarset }
1171         };
1172
1173         // Ensure that a file is read only once (prevents include loops)
1174         static std::list<string> uifiles;
1175         std::list<string>::const_iterator it  = uifiles.begin();
1176         std::list<string>::const_iterator end = uifiles.end();
1177         it = std::find(it, end, name);
1178         if (it != end) {
1179                 LYXERR(Debug::INIT) << "UI file '" << name
1180                                     << "' has been read already. "
1181                                     << "Is this an include loop?"
1182                                     << endl;
1183                 return false;
1184         }
1185
1186         LYXERR(Debug::INIT) << "About to read " << name << "..." << endl;
1187
1188
1189         FileName ui_path;
1190         if (include) {
1191                 ui_path = libFileSearch("ui", name, "inc");
1192                 if (ui_path.empty())
1193                         ui_path = libFileSearch("ui",
1194                                                 changeExtension(name, "inc"));
1195         }
1196         else
1197                 ui_path = libFileSearch("ui", name, "ui");
1198
1199         if (ui_path.empty()) {
1200                 LYXERR(Debug::INIT) << "Could not find " << name << endl;
1201                 showFileError(name);
1202                 return false;
1203         }
1204
1205         uifiles.push_back(name);
1206
1207         LYXERR(Debug::INIT) << "Found " << name
1208                             << " in " << ui_path << endl;
1209         Lexer lex(uitags, ui_last - 1);
1210         lex.setFile(ui_path);
1211         if (!lex.isOK()) {
1212                 lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
1213                        << endl;
1214         }
1215
1216         if (lyxerr.debugging(Debug::PARSER))
1217                 lex.printTable(lyxerr);
1218
1219         while (lex.isOK()) {
1220                 switch (lex.lex()) {
1221                 case ui_include: {
1222                         lex.next(true);
1223                         string const file = lex.getString();
1224                         if (!readUIFile(file, true))
1225                                 return false;
1226                         break;
1227                 }
1228                 case ui_menuset:
1229                         menubackend.read(lex);
1230                         break;
1231
1232                 case ui_toolbarset:
1233                         toolbarbackend.readToolbars(lex);
1234                         break;
1235
1236                 case ui_toolbars:
1237                         toolbarbackend.readToolbarSettings(lex);
1238                         break;
1239
1240                 default:
1241                         if (!rtrim(lex.getString()).empty())
1242                                 lex.printError("LyX::ReadUIFile: "
1243                                                "Unknown menu tag: `$$Token'");
1244                         break;
1245                 }
1246         }
1247         return true;
1248 }
1249
1250
1251 // Read the languages file `name'
1252 bool LyX::readLanguagesFile(string const & name)
1253 {
1254         LYXERR(Debug::INIT) << "About to read " << name << "..." << endl;
1255
1256         FileName const lang_path = libFileSearch(string(), name);
1257         if (lang_path.empty()) {
1258                 showFileError(name);
1259                 return false;
1260         }
1261         languages.read(lang_path);
1262         return true;
1263 }
1264
1265
1266 // Read the encodings file `name'
1267 bool LyX::readEncodingsFile(string const & enc_name,
1268                             string const & symbols_name)
1269 {
1270         LYXERR(Debug::INIT) << "About to read " << enc_name << " and "
1271                             << symbols_name << "..." << endl;
1272
1273         FileName const symbols_path = libFileSearch(string(), symbols_name);
1274         if (symbols_path.empty()) {
1275                 showFileError(symbols_name);
1276                 return false;
1277         }
1278
1279         FileName const enc_path = libFileSearch(string(), enc_name);
1280         if (enc_path.empty()) {
1281                 showFileError(enc_name);
1282                 return false;
1283         }
1284         encodings.read(enc_path, symbols_path);
1285         return true;
1286 }
1287
1288
1289 namespace {
1290
1291 string batch;
1292
1293 /// return the the number of arguments consumed
1294 typedef boost::function<int(string const &, string const &)> cmd_helper;
1295
1296 int parse_dbg(string const & arg, string const &)
1297 {
1298         if (arg.empty()) {
1299                 lyxerr << to_utf8(_("List of supported debug flags:")) << endl;
1300                 Debug::showTags(lyxerr);
1301                 exit(0);
1302         }
1303         lyxerr << to_utf8(bformat(_("Setting debug level to %1$s"), from_utf8(arg))) << endl;
1304
1305         lyxerr.level(Debug::value(arg));
1306         Debug::showLevel(lyxerr, lyxerr.level());
1307         return 1;
1308 }
1309
1310
1311 int parse_help(string const &, string const &)
1312 {
1313         lyxerr <<
1314                 to_utf8(_("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
1315                   "Command line switches (case sensitive):\n"
1316                   "\t-help              summarize LyX usage\n"
1317                   "\t-userdir dir       set user directory to dir\n"
1318                   "\t-sysdir dir        set system directory to dir\n"
1319                   "\t-geometry WxH+X+Y  set geometry of the main window\n"
1320                   "\t-dbg feature[,feature]...\n"
1321                   "                  select the features to debug.\n"
1322                   "                  Type `lyx -dbg' to see the list of features\n"
1323                   "\t-x [--execute] command\n"
1324                   "                  where command is a lyx command.\n"
1325                   "\t-e [--export] fmt\n"
1326                   "                  where fmt is the export format of choice.\n"
1327                   "\t-i [--import] fmt file.xxx\n"
1328                   "                  where fmt is the import format of choice\n"
1329                   "                  and file.xxx is the file to be imported.\n"
1330                   "\t-version        summarize version and build info\n"
1331                                "Check the LyX man page for more details.")) << endl;
1332         exit(0);
1333         return 0;
1334 }
1335
1336 int parse_version(string const &, string const &)
1337 {
1338         lyxerr << "LyX " << lyx_version
1339                << " (" << lyx_release_date << ")" << endl;
1340         lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
1341
1342         lyxerr << lyx_version_info << endl;
1343         exit(0);
1344         return 0;
1345 }
1346
1347 int parse_sysdir(string const & arg, string const &)
1348 {
1349         if (arg.empty()) {
1350                 Alert::error(_("No system directory"),
1351                         _("Missing directory for -sysdir switch"));
1352                 exit(1);
1353         }
1354         cl_system_support = arg;
1355         return 1;
1356 }
1357
1358 int parse_userdir(string const & arg, string const &)
1359 {
1360         if (arg.empty()) {
1361                 Alert::error(_("No user directory"),
1362                         _("Missing directory for -userdir switch"));
1363                 exit(1);
1364         }
1365         cl_user_support = arg;
1366         return 1;
1367 }
1368
1369 int parse_execute(string const & arg, string const &)
1370 {
1371         if (arg.empty()) {
1372                 Alert::error(_("Incomplete command"),
1373                         _("Missing command string after --execute switch"));
1374                 exit(1);
1375         }
1376         batch = arg;
1377         return 1;
1378 }
1379
1380 int parse_export(string const & type, string const &)
1381 {
1382         if (type.empty()) {
1383                 lyxerr << to_utf8(_("Missing file type [eg latex, ps...] after "
1384                                          "--export switch")) << endl;
1385                 exit(1);
1386         }
1387         batch = "buffer-export " + type;
1388         use_gui = false;
1389         return 1;
1390 }
1391
1392 int parse_import(string const & type, string const & file)
1393 {
1394         if (type.empty()) {
1395                 lyxerr << to_utf8(_("Missing file type [eg latex, ps...] after "
1396                                          "--import switch")) << endl;
1397                 exit(1);
1398         }
1399         if (file.empty()) {
1400                 lyxerr << to_utf8(_("Missing filename for --import")) << endl;
1401                 exit(1);
1402         }
1403
1404         batch = "buffer-import " + type + ' ' + file;
1405         return 2;
1406 }
1407
1408 int parse_geometry(string const & arg1, string const &)
1409 {
1410         geometryArg = arg1;
1411 #if defined(_WIN32) || (defined(__CYGWIN__) && defined(X_DISPLAY_MISSING))
1412         // remove also the arg
1413         return 1;
1414 #else
1415         // don't remove "-geometry"
1416         return -1;
1417 #endif
1418 }
1419
1420
1421 } // namespace anon
1422
1423
1424 void LyX::easyParse(int & argc, char * argv[])
1425 {
1426         std::map<string, cmd_helper> cmdmap;
1427
1428         cmdmap["-dbg"] = parse_dbg;
1429         cmdmap["-help"] = parse_help;
1430         cmdmap["--help"] = parse_help;
1431         cmdmap["-version"] = parse_version;
1432         cmdmap["--version"] = parse_version;
1433         cmdmap["-sysdir"] = parse_sysdir;
1434         cmdmap["-userdir"] = parse_userdir;
1435         cmdmap["-x"] = parse_execute;
1436         cmdmap["--execute"] = parse_execute;
1437         cmdmap["-e"] = parse_export;
1438         cmdmap["--export"] = parse_export;
1439         cmdmap["-i"] = parse_import;
1440         cmdmap["--import"] = parse_import;
1441         cmdmap["-geometry"] = parse_geometry;
1442
1443         for (int i = 1; i < argc; ++i) {
1444                 std::map<string, cmd_helper>::const_iterator it
1445                         = cmdmap.find(argv[i]);
1446
1447                 // don't complain if not found - may be parsed later
1448                 if (it == cmdmap.end())
1449                         continue;
1450
1451                 string const arg((i + 1 < argc) ? to_utf8(from_local8bit(argv[i + 1])) : string());
1452                 string const arg2((i + 2 < argc) ? to_utf8(from_local8bit(argv[i + 2])) : string());
1453
1454                 int const remove = 1 + it->second(arg, arg2);
1455
1456                 // Now, remove used arguments by shifting
1457                 // the following ones remove places down.
1458                 if (remove > 0) {
1459                         argc -= remove;
1460                         for (int j = i; j < argc; ++j)
1461                                 argv[j] = argv[j + remove];
1462                         --i;
1463                 }
1464         }
1465
1466         batch_command = batch;
1467 }
1468
1469
1470 FuncStatus getStatus(FuncRequest const & action)
1471 {
1472         return LyX::ref().lyxFunc().getStatus(action);
1473 }
1474
1475
1476 void dispatch(FuncRequest const & action)
1477 {
1478         LyX::ref().lyxFunc().dispatch(action);
1479 }
1480
1481
1482 BufferList & theBufferList()
1483 {
1484         return LyX::ref().bufferList();
1485 }
1486
1487
1488 LyXFunc & theLyXFunc()
1489 {
1490         return LyX::ref().lyxFunc();
1491 }
1492
1493
1494 Server & theServer()
1495 {
1496         // FIXME: this should not be use_gui dependent
1497         BOOST_ASSERT(use_gui);
1498         return LyX::ref().server();
1499 }
1500
1501
1502 ServerSocket & theServerSocket()
1503 {
1504         // FIXME: this should not be use_gui dependent
1505         BOOST_ASSERT(use_gui);
1506         return LyX::ref().socket();
1507 }
1508
1509
1510 KeyMap & theTopLevelKeymap()
1511 {
1512         BOOST_ASSERT(use_gui);
1513         return LyX::ref().topLevelKeymap();
1514 }
1515
1516
1517 Converters & theConverters()
1518 {
1519         return  LyX::ref().converters();
1520 }
1521
1522
1523 Converters & theSystemConverters()
1524 {
1525         return  LyX::ref().systemConverters();
1526 }
1527
1528
1529 Movers & theMovers()
1530 {
1531         return  LyX::ref().pimpl_->movers_;
1532 }
1533
1534
1535 Mover const & getMover(std::string  const & fmt)
1536 {
1537         return  LyX::ref().pimpl_->movers_(fmt);
1538 }
1539
1540
1541 void setMover(std::string const & fmt, std::string const & command)
1542 {
1543         LyX::ref().pimpl_->movers_.set(fmt, command);
1544 }
1545
1546
1547 Movers & theSystemMovers()
1548 {
1549         return  LyX::ref().pimpl_->system_movers_;
1550 }
1551
1552
1553 Messages & getMessages(std::string const & language)
1554 {
1555         return LyX::ref().getMessages(language);
1556 }
1557
1558
1559 Messages & getGuiMessages()
1560 {
1561         return LyX::ref().getGuiMessages();
1562 }
1563
1564 } // namespace lyx