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