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