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