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