]> git.lyx.org Git - lyx.git/blob - src/lyx_main.C
fix bug with ever-growing bst files list (from herbert)
[lyx.git] / src / lyx_main.C
1 /**
2  * \file lyx_main.C
3  * Copyright 1995-2002 the LyX Team
4  * Read the file COPYING
5  *
6  * \author unknown
7  */
8
9 #include <config.h>
10 #include <version.h>
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #endif
15
16 #include "lyx_main.h"
17
18 #include "support/filetools.h"
19 #include "support/lyxlib.h"
20 #include "support/os.h"
21 #include "support/FileInfo.h"
22 #include "support/path.h"
23 #include "debug.h"
24 #include "gettext.h"
25 #include "lyxlex.h"
26
27 #include "bufferlist.h"
28 #include "lyxserver.h"
29 #include "kbmap.h"
30 #include "lyxfunc.h"
31 #include "ToolbarDefaults.h"
32 #include "MenuBackend.h"
33 #include "language.h"
34 #include "lastfiles.h"
35 #include "encoding.h"
36 #include "converter.h"
37 #include "lyxtextclasslist.h"
38
39 #include "frontends/Alert.h"
40 #include "frontends/lyx_gui.h"
41
42 #include <cstdlib>
43 #include <csignal>
44
45 using std::vector;
46 using std::endl;
47
48 #ifndef CXX_GLOBAL_CSTD
49 using std::exit;
50 using std::signal;
51 using std::system;
52 #endif
53
54 extern void LoadLyXFile(string const &);
55 extern void QuitLyX();
56
57 extern LyXServer * lyxserver;
58
59 string system_lyxdir;
60 string build_lyxdir;
61 string system_tempdir;
62 string user_lyxdir;
63
64 DebugStream lyxerr;
65
66 boost::scoped_ptr<LastFiles> lastfiles;
67
68 // This is the global bufferlist object
69 BufferList bufferlist;
70
71 // convenient to have it here.
72 boost::scoped_ptr<kb_keymap> toplevel_keymap;
73
74
75 LyX::LyX(int & argc, char * argv[])
76 {
77         // Here we need to parse the command line. At least
78         // we need to parse for "-dbg" and "-help"
79         bool const want_gui = easyParse(argc, argv);
80
81         // Global bindings (this must be done as early as possible.) (Lgb)
82         toplevel_keymap.reset(new kb_keymap);
83         defaultKeyBindings(toplevel_keymap.get());
84
85         if (want_gui) {
86                 lyx_gui::parse_init(argc, argv);
87         }
88
89         // check for any spurious extra arguments
90         // other than documents
91         for (int argi = 1; argi < argc ; ++argi) {
92                 if (argv[argi][0] == '-') {
93                         lyxerr << _("Wrong command line option `")
94                                << argv[argi]
95                                << _("'. Exiting.") << endl;
96                         exit(1);
97                 }
98         }
99
100         // Initialization of LyX (reads lyxrc and more)
101         lyxerr[Debug::INIT] << "Initializing LyX::init..." << endl;
102         init(want_gui);
103         lyxerr[Debug::INIT] << "Initializing LyX::init...done" << endl;
104
105         if (want_gui) {
106                 lyx_gui::parse_lyxrc();
107         }
108
109         vector<string> files;
110
111         for (int argi = argc - 1; argi >= 1; --argi) {
112                 files.push_back(argv[argi]);
113         }
114
115         if (first_start) {
116                 files.push_back(i18nLibFileSearch("examples", "splash.lyx"));
117         }
118
119 #if 0 // FIXME: GUII
120         // Execute batch commands if available
121         if (!batch_command.empty()) {
122                 lyxerr[Debug::INIT] << "About to handle -x '"
123                        << batch_command << "'" << endl;
124
125                 // no buffer loaded, create one
126                 if (!last_loaded)
127                         last_loaded = bufferlist.newFile("tmpfile", string());
128
129                 bool success = false;
130
131                 // try to dispatch to last loaded buffer first
132                 bool const dispatched = last_loaded->dispatch(batch_command, &success);
133
134                 // if this was successful, finish
135                 if (dispatched) {
136                         QuitLyX();
137                         exit(!success);
138                 }
139         }
140 #endif
141
142         lyx_gui::start(batch_command, files);
143 }
144
145
146 extern "C" {
147
148 static
149 void error_handler(int err_sig)
150 {
151         switch (err_sig) {
152         case SIGHUP:
153                 lyxerr << "\nlyx: SIGHUP signal caught" << endl;
154                 break;
155         case SIGINT:
156                 // no comments
157                 break;
158         case SIGFPE:
159                 lyxerr << "\nlyx: SIGFPE signal caught" << endl;
160                 break;
161         case SIGSEGV:
162                 lyxerr << "\nlyx: SIGSEGV signal caught" << endl;
163                 lyxerr <<
164                         "Sorry, you have found a bug in LyX. "
165                         "Please read the bug-reporting instructions "
166                         "in Help->Introduction and send us a bug report, "
167                         "if necessary. Thanks !" << endl;
168                 break;
169         case SIGTERM:
170                 // no comments
171                 break;
172         }
173
174         // Deinstall the signal handlers
175         signal(SIGHUP, SIG_DFL);
176         signal(SIGINT, SIG_DFL);
177         signal(SIGFPE, SIG_DFL);
178         signal(SIGSEGV, SIG_DFL);
179         signal(SIGTERM, SIG_DFL);
180
181         LyX::emergencyCleanup();
182
183         lyxerr << "Bye." << endl;
184         if (err_sig!= SIGHUP &&
185            (!GetEnv("LYXDEBUG").empty() || err_sig == SIGSEGV))
186                 lyx::abort();
187         exit(0);
188 }
189
190 }
191
192
193 void LyX::init(bool gui)
194 {
195         // Install the signal handlers
196         signal(SIGHUP, error_handler);
197         signal(SIGFPE, error_handler);
198         signal(SIGSEGV, error_handler);
199         signal(SIGINT, error_handler);
200         signal(SIGTERM, error_handler);
201
202         //
203         // Determine path of binary
204         //
205
206         string binpath = os::binpath();
207         string binname = os::binname();
208         string fullbinname = MakeAbsPath(binname, binpath);
209
210         if (binpath.empty()) {
211                 lyxerr << _("Warning: could not determine path of binary.")
212                        << "\n"
213                        << _("If you have problems, try starting LyX with an absolute path.")
214                        << endl;
215         }
216         lyxerr[Debug::INIT] << "Name of binary: " << binname << endl;
217         lyxerr[Debug::INIT] << "Path of binary: " << binpath << endl;
218
219         //
220         // Determine system directory.
221         //
222
223         // Directories are searched in this order:
224         // 1) -sysdir command line parameter
225         // 2) LYX_DIR_13x environment variable
226         // 3) Maybe <path of binary>/TOP_SRCDIR/lib
227         // 4) <path of binary>/../share/<name of binary>/
228         // 4a) repeat 4 after following the Symlink if <path of
229         //     binary> is a symbolic link.
230         // 5) hardcoded lyx_dir
231         // The directory is checked for the presence of the file
232         // "chkconfig.ltx", and if that is present, the directory
233         // is accepted as the system directory.
234         // If no chkconfig.ltx file is found, a warning is given,
235         // and the hardcoded lyx_dir is used.
236
237         // If we had a command line switch, system_lyxdir is already set
238         string searchpath;
239         if (!system_lyxdir.empty())
240                 searchpath = MakeAbsPath(system_lyxdir) + ';';
241
242         // LYX_DIR_13x environment variable
243         string const lyxdir = GetEnvPath("LYX_DIR_13x");
244
245         if (!lyxdir.empty()) {
246                 lyxerr[Debug::INIT] << "LYX_DIR_13x: " << lyxdir << endl;
247                 searchpath += lyxdir + ';';
248         }
249
250         string fullbinpath = binpath;
251         FileInfo file(fullbinname, true);
252         if (file.isLink()) {
253                 lyxerr[Debug::INIT] << "binary is a link" << endl;
254                 string link;
255                 if (LyXReadLink(fullbinname, link, true)) {
256                         // Path of binary/../share/name of binary/
257                         searchpath += NormalizePath(AddPath(binpath,
258                                                             "../share/")
259                                                     + OnlyFilename(binname));
260                         searchpath += ';';
261                         fullbinpath = link;
262                         binpath = MakeAbsPath(OnlyPath(fullbinpath));
263                 }
264         }
265
266         bool followlink;
267         do {
268                 // Path of binary/../share/name of binary/
269                 searchpath += NormalizePath(AddPath(binpath, "../share/") +
270                       OnlyFilename(binname)) + ';';
271
272                 // Follow Symlinks
273                 FileInfo file(fullbinpath, true);
274                 followlink = file.isLink();
275                 if (followlink) {
276                         lyxerr << " directory " << fullbinpath
277                                << " is a link" << endl;
278                         string link;
279                         if (LyXReadLink(fullbinpath, link, true)) {
280                                 fullbinpath = link;
281                                 binpath = MakeAbsPath(OnlyPath(fullbinpath));
282                         }
283                         else {
284                                 followlink = false;
285                         }
286                 }
287         } while (followlink);
288
289         // <path of binary>/TOP_SRCDIR/lib
290         build_lyxdir = MakeAbsPath("../lib", binpath);
291         if (!FileSearch(build_lyxdir, "lyxrc.defaults").empty()) {
292                 searchpath += MakeAbsPath(AddPath(TOP_SRCDIR, "lib"),
293                                           binpath) + ';';
294                 lyxerr[Debug::INIT] << "Checking whether LyX is run in "
295                         "place... yes" << endl;
296         } else {
297                 lyxerr[Debug::INIT]
298                         << "Checking whether LyX is run in place... no"
299                         << endl;
300                 build_lyxdir.erase();
301         }
302
303         // Hardcoded dir
304         searchpath += LYX_DIR;
305
306         // If debugging, show complete search path
307         lyxerr[Debug::INIT] << "System directory search path: "
308                             << searchpath << endl;
309
310         string const filename = "chkconfig.ltx";
311         string const temp = FileOpenSearch(searchpath, filename, string());
312         system_lyxdir = OnlyPath(temp);
313
314         // Reduce "path/../path" stuff out of system directory
315         system_lyxdir = NormalizePath(system_lyxdir);
316
317         bool path_shown = false;
318
319         // Warn if environment variable is set, but unusable
320         if (!lyxdir.empty()) {
321                 if (system_lyxdir != NormalizePath(lyxdir)) {
322                         lyxerr <<_("LYX_DIR_13x environment variable no good.")
323                                << '\n'
324                                << _("System directory set to: ")
325                                << system_lyxdir << endl;
326                         path_shown = true;
327                 }
328         }
329
330         // Warn the user if we couldn't find "chkconfig.ltx"
331         if (system_lyxdir == "./") {
332                 lyxerr <<_("LyX Warning! Couldn't determine system directory. ")
333                        <<_("Try the '-sysdir' command line parameter or ")
334                        <<_("set the environment variable LYX_DIR_13x to the "
335                            "LyX system directory ")
336                        << _("containing the file `chkconfig.ltx'.") << endl;
337                 if (!path_shown) {
338                         FileInfo fi(LYX_DIR);
339                         if (!fi.exist()) {
340                                 lyxerr << "Couldn't even find the default LYX_DIR." << endl
341                                         << "Giving up." << endl;
342                                 exit(1);
343                         }
344                         lyxerr << _("Using built-in default ")
345                                << LYX_DIR << _(" but expect problems.")
346                                << endl;
347                 } else {
348                         lyxerr << _("Expect problems.") << endl;
349                 }
350                 system_lyxdir = LYX_DIR;
351                 path_shown = true;
352         }
353         // Report the system directory if debugging is on
354         if (!path_shown)
355                 lyxerr[Debug::INIT] << "System directory: '"
356                                     << system_lyxdir << '\'' << endl;
357
358         //
359         // Determine user lyx-dir
360         //
361
362         // Directories are searched in this order:
363         // 1) -userdir command line parameter
364         // 2) LYX_USERDIR_13x environment variable
365         // 3) $HOME/.<name of binary>
366
367         // If we had a command line switch, user_lyxdir is already set
368         bool explicit_userdir = true;
369         if (user_lyxdir.empty()) {
370
371                 // LYX_USERDIR_13x environment variable
372                 user_lyxdir = GetEnvPath("LYX_USERDIR_13x");
373
374                 // default behaviour
375                 if (user_lyxdir.empty())
376                         user_lyxdir = AddPath(GetEnvPath("HOME"),
377                                                         string(".") + PACKAGE);
378                         explicit_userdir = false;
379         }
380
381         lyxerr[Debug::INIT] << "User LyX directory: '"
382                             <<  user_lyxdir << '\'' << endl;
383
384         // Check that user LyX directory is ok. We don't do that if
385         // running in batch mode.
386         if (gui) {
387                 queryUserLyXDir(explicit_userdir);
388         } else {
389                 first_start = false;
390         }
391
392         //
393         // Shine up lyxrc defaults
394         //
395
396         // Default template path: system_dir/templates
397         if (lyxrc.template_path.empty()) {
398                 lyxrc.template_path = AddPath(system_lyxdir, "templates");
399         }
400
401         // Default lastfiles file: $HOME/.lyx/lastfiles
402         if (lyxrc.lastfiles.empty()) {
403                 lyxrc.lastfiles = AddName(user_lyxdir, "lastfiles");
404         }
405
406         // Disable gui when either lyxrc or easyparse says so
407         if (!gui)
408                 lyxrc.use_gui = false;
409
410         //
411         // Read configuration files
412         //
413
414         readRcFile("lyxrc.defaults");
415         system_lyxrc = lyxrc;
416         system_formats = formats;
417         system_converters = converters;
418         system_lcolor = lcolor;
419
420         // If there is a preferences file we read that instead
421         // of the old lyxrc file.
422         if (!readRcFile("preferences"))
423             readRcFile("lyxrc");
424
425         // Read encodings
426         readEncodingsFile("encodings");
427         // Read languages
428         readLanguagesFile("languages");
429
430         // Load the layouts
431         lyxerr[Debug::INIT] << "Reading layouts..." << endl;
432         LyXSetStyle();
433
434         // Ensure that we have really read a bind file, so that LyX is
435         // usable.
436         lyxrc.readBindFileIfNeeded();
437
438         // Read menus
439         readUIFile(lyxrc.ui_file);
440
441         // Bind the X dead keys to the corresponding LyX functions if
442         // necessary.
443         if (lyxrc.override_x_deadkeys)
444                 deadKeyBindings(toplevel_keymap.get());
445
446         if (lyxerr.debugging(Debug::LYXRC)) {
447                 lyxrc.print();
448         }
449
450         // Create temp directory
451         os::setTmpDir(CreateLyXTmpDir(lyxrc.tempdir_path));
452         system_tempdir = os::getTmpDir();
453         if (lyxerr.debugging(Debug::INIT)) {
454                 lyxerr << "LyX tmp dir: `" << system_tempdir << '\'' << endl;
455         }
456
457         // load the lastfiles mini-database
458         lyxerr[Debug::INIT] << "Reading lastfiles `"
459                             << lyxrc.lastfiles << "'..." << endl;
460         lastfiles.reset(new LastFiles(lyxrc.lastfiles,
461                                       lyxrc.check_lastfiles,
462                                       lyxrc.num_lastfiles));
463 }
464
465
466 // These are the default bindings known to LyX
467 void LyX::defaultKeyBindings(kb_keymap  * kbmap)
468 {
469         kbmap->bind("Right", LFUN_RIGHT);
470         kbmap->bind("Left", LFUN_LEFT);
471         kbmap->bind("Up", LFUN_UP);
472         kbmap->bind("Down", LFUN_DOWN);
473
474         kbmap->bind("Tab", LFUN_TAB);
475         kbmap->bind("ISO_Left_Tab", LFUN_TAB); // jbl 2001-23-02
476
477         kbmap->bind("Home", LFUN_HOME);
478         kbmap->bind("End", LFUN_END);
479         kbmap->bind("Prior", LFUN_PRIOR);
480         kbmap->bind("Next", LFUN_NEXT);
481
482         kbmap->bind("Return", LFUN_BREAKPARAGRAPH);
483         //kbmap->bind("~C-~S-~M-nobreakspace", LFUN_PROTECTEDSPACE);
484
485         kbmap->bind("Delete", LFUN_DELETE);
486         kbmap->bind("BackSpace", LFUN_BACKSPACE);
487
488         // sub- and superscript -MV
489         kbmap->bind("~S-underscore", LFUN_SUBSCRIPT);
490         kbmap->bind("~S-asciicircum", LFUN_SUPERSCRIPT);
491
492         // kbmap->bindings to enable the use of the numeric keypad
493         // e.g. Num Lock set
494         //kbmap->bind("KP_0", LFUN_SELFINSERT);
495         //kbmap->bind("KP_Decimal", LFUN_SELFINSERT);
496         kbmap->bind("KP_Enter", LFUN_BREAKPARAGRAPH);
497         //kbmap->bind("KP_1", LFUN_SELFINSERT);
498         //kbmap->bind("KP_2", LFUN_SELFINSERT);
499         //kbmap->bind("KP_3", LFUN_SELFINSERT);
500         //kbmap->bind("KP_4", LFUN_SELFINSERT);
501         //kbmap->bind("KP_5", LFUN_SELFINSERT);
502         //kbmap->bind("KP_6", LFUN_SELFINSERT);
503         //kbmap->bind("KP_Add", LFUN_SELFINSERT);
504         //kbmap->bind("KP_7", LFUN_SELFINSERT);
505         //kbmap->bind("KP_8", LFUN_SELFINSERT);
506         //kbmap->bind("KP_9", LFUN_SELFINSERT);
507         //kbmap->bind("KP_Divide", LFUN_SELFINSERT);
508         //kbmap->bind("KP_Multiply", LFUN_SELFINSERT);
509         //kbmap->bind("KP_Subtract", LFUN_SELFINSERT);
510         kbmap->bind("KP_Right", LFUN_RIGHT);
511         kbmap->bind("KP_Left", LFUN_LEFT);
512         kbmap->bind("KP_Up", LFUN_UP);
513         kbmap->bind("KP_Down", LFUN_DOWN);
514         kbmap->bind("KP_Home", LFUN_HOME);
515         kbmap->bind("KP_End", LFUN_END);
516         kbmap->bind("KP_Prior", LFUN_PRIOR);
517         kbmap->bind("KP_Next", LFUN_NEXT);
518
519         kbmap->bind("C-Tab", LFUN_TABINSERT);  // ale970515
520         kbmap->bind("S-Tab", LFUN_SHIFT_TAB);  // jug20000522
521         kbmap->bind("S-ISO_Left_Tab", LFUN_SHIFT_TAB); // jbl 2001-23-02
522 }
523
524
525 void LyX::emergencyCleanup()
526 {
527         // what to do about tmpfiles is non-obvious. we would
528         // like to delete any we find, but our lyxdir might
529         // contain documents etc. which might be helpful on
530         // a crash
531
532         bufferlist.emergencyWriteAll();
533         if (lyxserver)
534                 lyxserver->emergencyCleanup();
535 }
536
537
538 // LyX can optionally take over the handling of deadkeys
539 void LyX::deadKeyBindings(kb_keymap * kbmap)
540 {
541         // bindKeyings for transparent handling of deadkeys
542         // The keysyms are gotten from XFree86 X11R6
543         kbmap->bind("~C-~S-~M-dead_acute", LFUN_ACUTE);
544         kbmap->bind("~C-~S-~M-dead_breve", LFUN_BREVE);
545         kbmap->bind("~C-~S-~M-dead_caron", LFUN_CARON);
546         kbmap->bind("~C-~S-~M-dead_cedilla", LFUN_CEDILLA);
547         kbmap->bind("~C-~S-~M-dead_abovering", LFUN_CIRCLE);
548         kbmap->bind("~C-~S-~M-dead_circumflex", LFUN_CIRCUMFLEX);
549         kbmap->bind("~C-~S-~M-dead_abovedot", LFUN_DOT);
550         kbmap->bind("~C-~S-~M-dead_grave", LFUN_GRAVE);
551         kbmap->bind("~C-~S-~M-dead_doubleacute", LFUN_HUNG_UMLAUT);
552         kbmap->bind("~C-~S-~M-dead_macron", LFUN_MACRON);
553         // nothing with this name
554         // kbmap->bind("~C-~S-~M-dead_special_caron", LFUN_SPECIAL_CARON);
555         kbmap->bind("~C-~S-~M-dead_tilde", LFUN_TILDE);
556         kbmap->bind("~C-~S-~M-dead_diaeresis", LFUN_UMLAUT);
557         // nothing with this name either...
558         //kbmap->bind("~C-~S-~M-dead_underbar", LFUN_UNDERBAR);
559         kbmap->bind("~C-~S-~M-dead_belowdot", LFUN_UNDERDOT);
560         kbmap->bind("~C-~S-~M-dead_tie", LFUN_TIE);
561         kbmap->bind("~C-~S-~M-dead_ogonek", LFUN_OGONEK);
562 }
563
564
565 // This one is not allowed to use anything on the main form, since that
566 // one does not exist yet. (Asger)
567 void LyX::queryUserLyXDir(bool explicit_userdir)
568 {
569         // Does user directory exist?
570         FileInfo fileInfo(user_lyxdir);
571         if (fileInfo.isOK() && fileInfo.isDir()) {
572                 first_start = false;
573                 return;
574         } else {
575                 first_start = !explicit_userdir;
576         }
577
578         // If the user specified explicitely a directory, ask whether
579         // to create it (otherwise, always create it)
580         if (explicit_userdir &&
581             !Alert::askQuestion(_("You have specified an invalid LyX directory."),
582                          _("It is needed to keep your own configuration."),
583                          _("Should I try to set it up for you (recommended)?"))) {
584                 lyxerr << _("Running without personal LyX directory.") << endl;
585                 // No, let's use $HOME instead.
586                 user_lyxdir = GetEnvPath("HOME");
587                 return;
588         }
589
590         // Tell the user what is going on
591         lyxerr << _("LyX: Creating directory ") << user_lyxdir
592                << _(" and running configure...") << endl;
593
594         // Create directory structure
595         if (!createDirectory(user_lyxdir, 0755)) {
596                 // Failed, let's use $HOME instead.
597                 user_lyxdir = GetEnvPath("HOME");
598                 lyxerr << _("Failed. Will use ") << user_lyxdir
599                        << _(" instead.") << endl;
600                 return;
601         }
602
603         // Run configure in user lyx directory
604         Path p(user_lyxdir);
605         ::system(AddName(system_lyxdir, "configure").c_str());
606         lyxerr << "LyX: " << _("Done!") << endl;
607 }
608
609
610 // Read the rc file `name'
611 bool LyX::readRcFile(string const & name)
612 {
613         lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
614
615         string const lyxrc_path = LibFileSearch(string(), name);
616         if (!lyxrc_path.empty()) {
617                 lyxerr[Debug::INIT] << "Found " << name
618                                     << " in " << lyxrc_path << endl;
619                 if (lyxrc.read(lyxrc_path) < 0) {
620                         Alert::alert(_("LyX Warning!"),
621                                    _("Error while reading ") + lyxrc_path + ".",
622                                    _("Using built-in defaults."));
623                         return false;
624                 }
625                 return true;
626         } else {
627                 lyxerr[Debug::INIT] << "Could not find " << name << endl;
628         }
629
630         return false;
631 }
632
633
634 // Read the ui file `name'
635 void LyX::readUIFile(string const & name)
636 {
637         enum Uitags {
638                 ui_menuset = 1,
639                 ui_toolbar,
640                 ui_last
641         };
642
643         struct keyword_item uitags[ui_last-1] = {
644                 { "menuset", ui_menuset },
645                 { "toolbar", ui_toolbar }
646         };
647
648         lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
649
650         string const ui_path = LibFileSearch("ui", name, "ui");
651
652         if (ui_path.empty()) {
653                 lyxerr[Debug::INIT] << "Could not find " << name << endl;
654                 menubackend.defaults();
655                 return;
656         }
657
658         lyxerr[Debug::INIT] << "Found " << name
659                             << " in " << ui_path << endl;
660         LyXLex lex(uitags, ui_last - 1);
661         lex.setFile(ui_path);
662         if (!lex.isOK()) {
663                 lyxerr << "Unable to set LyXLeX for ui file: " << ui_path
664                        << endl;
665         }
666
667         if (lyxerr.debugging(Debug::PARSER))
668                 lex.printTable(lyxerr);
669
670         while (lex.isOK()) {
671                 switch (lex.lex()) {
672                 case ui_menuset:
673                         menubackend.read(lex);
674                         break;
675
676                 case ui_toolbar:
677                         toolbardefaults.read(lex);
678                         break;
679
680                 default:
681                         if (!strip(lex.getString()).empty())
682                                 lex.printError("LyX::ReadUIFile: "
683                                                "Unknown menu tag: `$$Token'");
684                         break;
685                 }
686         }
687 }
688
689
690 // Read the languages file `name'
691 void LyX::readLanguagesFile(string const & name)
692 {
693         lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
694
695         string const lang_path = LibFileSearch(string(), name);
696         if (lang_path.empty()) {
697                 lyxerr[Debug::INIT] << "Could not find " << name << endl;
698                 languages.setDefaults();
699                 return;
700         }
701         languages.read(lang_path);
702 }
703
704
705 // Read the encodings file `name'
706 void LyX::readEncodingsFile(string const & name)
707 {
708         lyxerr[Debug::INIT] << "About to read " << name << "..." << endl;
709
710         string const enc_path = LibFileSearch(string(), name);
711         if (enc_path.empty()) {
712                 lyxerr[Debug::INIT] << "Could not find " << name << endl;
713                 return;
714         }
715         encodings.read(enc_path);
716 }
717
718
719 namespace {
720
721 // Set debugging level and report result to user
722 void setDebuggingLevel(string const & dbgLevel)
723 {
724         lyxerr << _("Setting debug level to ") <<  dbgLevel << endl;
725         lyxerr.level(Debug::value(dbgLevel));
726         Debug::showLevel(lyxerr, lyxerr.level());
727 }
728
729
730 // Give command line help
731 void commandLineHelp()
732 {
733         lyxerr <<
734                 _("Usage: lyx [ command line switches ] [ name.lyx ... ]\n"
735                   "Command line switches (case sensitive):\n"
736                   "\t-help              summarize LyX usage\n"
737                   "\t-userdir dir       try to set user directory to dir\n"
738                   "\t-sysdir dir        try to set system directory to dir\n"
739                   "\t-geometry WxH+X+Y  set geometry of the main window\n"
740                   "\t-dbg feature[,feature]...\n"
741                   "                  select the features to debug.\n"
742                   "                  Type `lyx -dbg' to see the list of features\n"
743                   "\t-x [--execute] command\n"
744                   "                  where command is a lyx command.\n"
745                   "\t-e [--export] fmt\n"
746                   "                  where fmt is the export format of choice.\n"
747                   "\t-i [--import] fmt file.xxx\n"
748                   "                  where fmt is the import format of choice\n"
749                   "                  and file.xxx is the file to be imported.\n"
750                   "\t-version        summarize version and build info\n"
751                   "Check the LyX man page for more details.") << endl;
752 }
753
754 // Give command line version information
755 void commandLineVersionInfo()
756 {
757         lyxerr << "LyX " << lyx_version
758                << " of " << lyx_release_date << endl;
759         lyxerr << "Built on " << __DATE__ << ", " << __TIME__ << endl;
760
761         lyxerr << lyx_version_info << endl;
762 }
763
764
765 } // namespace anon
766
767
768 bool LyX::easyParse(int & argc, char * argv[])
769 {
770         bool gui = true;
771         int removeargs = 0; // used when options are read
772         for (int i = 1; i < argc; ++i) {
773                 string arg = argv[i];
774
775                 // Check for -dbg int
776                 if (arg == "-dbg") {
777                         if (i + 1 < argc) {
778                                 setDebuggingLevel(argv[i + 1]);
779                                 removeargs = 2;
780                         } else {
781                                 lyxerr << _("List of supported debug flags:")
782                                        << endl;
783                                 Debug::showTags(lyxerr);
784                                 exit(1);
785                         }
786                 }
787                 // Check for "-sysdir"
788                 else if (arg == "-sysdir") {
789                         if (i + 1 < argc) {
790                                 system_lyxdir = argv[i + 1];
791                                 removeargs = 2;
792                         } else {
793                                 lyxerr << _("Missing directory for -sysdir switch!")
794                                        << endl;
795                                 exit(1);
796                         }
797                 }
798                 // Check for "-userdir"
799                 else if (arg == "-userdir") {
800                         if (i + 1 < argc) {
801                                 user_lyxdir = argv[i + 1];
802                                 removeargs = 2;
803                         } else {
804                                 lyxerr << _("Missing directory for -userdir switch!")
805                                        << endl;
806                                 exit(1);
807                         }
808                 }
809                 // Check for --help or -help
810                 else if (arg == "--help" || arg == "-help") {
811                         commandLineHelp();
812                         exit(0);
813                 }
814                 // Check for --version or -version
815                 else if (arg == "--version" || arg == "-version") {
816                         commandLineVersionInfo();
817                         exit(0);
818                 }
819                 // FIXME: why is this commented out ?
820                 // Check for "-nw": No XWindows as for emacs this should
821                 // give a LyX that could be used in a terminal window.
822                 //else if (arg == "-nw") {
823                 //      gui = false;
824                 //}
825
826                 // Check for "-x": Execute commands
827                 else if (arg == "-x" || arg == "--execute") {
828                         if (i + 1 < argc) {
829                                 batch_command = string(argv[i + 1]);
830                                 removeargs = 2;
831                         }
832                         else
833                                 lyxerr << _("Missing command string after  -x switch!") << endl;
834
835                         // Argh. Setting gui to false segfaults..
836                         // FIXME: when ? how ?
837                         // gui = false;
838                 }
839
840                 else if (arg == "-e" || arg == "--export") {
841                         if (i + 1 < argc) {
842                                 string type(argv[i+1]);
843                                 removeargs = 2;
844                                 batch_command = "buffer-export " + type;
845                                 gui = false;
846                         } else {
847                                 lyxerr << _("Missing file type [eg latex, "
848                                             "ps...] after ")
849                                        << arg << _(" switch!") << endl;
850                                 exit(1);
851                         }
852                 }
853                 else if (arg == "-i" || arg == "--import") {
854                         if (i + 1 < argc) {
855                                 if (!argv[i+2]) {
856                                         lyxerr << _("Missing filename for --import") << endl;
857                                         exit(1);
858                                 }
859
860                                 string const file(argv[i+2]);
861                                 string const type(argv[i+1]);
862                                 removeargs = 3;
863
864                                 batch_command = "buffer-import " + type + " " + file;
865                                 lyxerr << "batch_command: "
866                                        << batch_command << endl;
867
868                         } else {
869                                 lyxerr << _("Missing type [eg latex, "
870                                             "ps...] after ")
871                                        << arg << _(" switch!") << endl;
872                                 exit(1);
873                         }
874                 }
875
876                 if (removeargs > 0) {
877                         // Now, remove used arguments by shifting
878                         // the following ones removeargs places down.
879                         argc -= removeargs;
880                         for (int j = i; j < argc; ++j)
881                                 argv[j] = argv[j + removeargs];
882                         --i; // After shift, check this number again.
883                         removeargs = 0;
884                 }
885
886         }
887
888         return gui;
889 }