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