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