]> git.lyx.org Git - lyx.git/blob - src/support/Package.cpp
Update shortcuts in fr.po
[lyx.git] / src / support / Package.cpp
1 // -*- C++ -*-
2 /**
3  * \file package.cpp
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Angus Leeming
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "support/Package.h"
15
16 #include "support/debug.h"
17 #include "support/environment.h"
18 #include "support/ExceptionMessage.h"
19 #include "support/filetools.h"
20 #include "support/gettext.h"
21 #include "support/lassert.h"
22 #include "support/lstrings.h"
23 #include "support/os.h"
24 #include "support/PathChanger.h"
25 #include "support/Systemcall.h"
26
27 #if defined (USE_WINDOWS_PACKAGING)
28 # include "support/os_win32.h"
29 #endif
30
31
32 #include <iostream>
33 #include <list>
34
35 #if !defined (USE_WINDOWS_PACKAGING) && \
36     !defined (USE_MACOSX_PACKAGING) && \
37     !defined (USE_HAIKU_PACKAGING) && \
38     !defined (USE_POSIX_PACKAGING)
39 #error USE_FOO_PACKAGING must be defined for FOO = WINDOWS, MACOSX, HAIKU or POSIX.
40 #endif
41
42 #if defined (USE_MACOSX_PACKAGING)
43 # include "support/qstring_helpers.h"
44 # include <QDir>
45 # include <QDesktopServices>
46 #endif
47
48 using namespace std;
49
50 namespace lyx {
51 namespace support {
52
53 namespace {
54
55 Package package_;
56 bool initialised_ = false;
57
58 } // namespace
59
60
61 void init_package(string const & command_line_arg0,
62                   string const & command_line_system_support_dir,
63                   string const & command_line_user_support_dir)
64 {
65         package_ = Package(command_line_arg0,
66                            command_line_system_support_dir,
67                            command_line_user_support_dir);
68         initialised_ = true;
69 }
70
71
72 Package const & package()
73 {
74         LAPPERR(initialised_);
75         return package_;
76 }
77
78
79 namespace {
80
81 FileName const abs_path_from_binary_name(string const & exe);
82
83
84 bool inBuildDir(FileName const & abs_binary, FileName &, FileName &);
85
86 FileName findLyxBinary(FileName const & abs_binary);
87
88 FileName const get_document_dir(FileName const & home_dir);
89
90 FileName const get_locale_dir(FileName const & system_support_dir);
91
92 FileName const get_system_support_dir(FileName const & abs_binary,
93                                     string const & command_line_system_support_dir);
94
95 FileName const get_default_user_support_dir(FileName const & home_dir);
96
97 bool userSupportDir(FileName const & default_user_support_dir,
98                      string const & command_line_user_support_dir, FileName & result);
99
100 string const & with_version_suffix();
101
102 string const fix_dir_name(string const & name);
103
104 } // namespace
105
106
107 Package::Package(string const & command_line_arg0,
108                  string const & command_line_system_support_dir,
109                  string const & command_line_user_support_dir)
110         : explicit_user_support_dir_(false)
111 {
112         // Specification of temp_dir_ may be reset by LyXRC,
113         // but the default is fixed for a given OS.
114         system_temp_dir_ = FileName::tempPath();
115         temp_dir_ = system_temp_dir_;
116         document_dir_ = get_document_dir(get_home_dir());
117
118         FileName const abs_binary = abs_path_from_binary_name(command_line_arg0);
119         binary_dir_ = FileName(onlyPath(abs_binary.absFileName()));
120
121         // the LyX package directory
122         lyx_dir_ = FileName(addPath(binary_dir_.absFileName(), "../"));
123         lyx_dir_ = FileName(lyx_dir_.realPath());
124
125         // Is LyX being run in-place from the build tree?
126         in_build_dir_ = inBuildDir(abs_binary, build_support_dir_, system_support_dir_);
127
128         if (!in_build_dir_) {
129                 system_support_dir_ =
130                         get_system_support_dir(abs_binary,
131                                                command_line_system_support_dir);
132         }
133
134         // Find the LyX executable
135         lyx_binary_ = findLyxBinary(abs_binary);
136
137         locale_dir_ = get_locale_dir(system_support_dir_);
138
139         FileName const default_user_support_dir =
140                 get_default_user_support_dir(get_home_dir());
141
142         explicit_user_support_dir_ = userSupportDir(default_user_support_dir,
143                                      command_line_user_support_dir, user_support_dir_);
144
145
146         LYXERR(Debug::INIT, "<package>\n"
147                 << "\tbinary_dir " << binary_dir().absFileName() << '\n'
148                 << "\tsystem_support " << system_support().absFileName() << '\n'
149                 << "\tbuild_support " << build_support().absFileName() << '\n'
150                 << "\tuser_support " << user_support().absFileName() << '\n'
151                 << "\tlocale_dir " << locale_dir().absFileName() << '\n'
152                 << "\tdocument_dir " << document_dir().absFileName() << '\n'
153                 << "\ttemp_dir " << temp_dir().absFileName() << '\n'
154                 << "\thome_dir " << get_home_dir().absFileName() << '\n'
155                 << "</package>\n");
156 }
157
158
159 int Package::reconfigureUserLyXDir(string const & option) const
160 {
161         if (configure_command_.empty()) {
162                 FileName const configure_script(addName(system_support().absFileName(), "configure.py"));
163                 configure_command_ = os::python() + ' ' +
164                         quoteName(configure_script.toFilesystemEncoding()) +
165                         with_version_suffix() + " --binary-dir=" +
166                         quoteName(FileName(binary_dir().absFileName()).toFilesystemEncoding());
167         }
168
169         lyxerr << to_utf8(_("LyX: reconfiguring user directory")) << endl;
170         PathChanger p(user_support());
171         Systemcall one;
172         int const ret = one.startscript(Systemcall::Wait, configure_command_ + option);
173         lyxerr << "LyX: " << to_utf8(_("Done!")) << endl;
174         return ret;
175 }
176
177
178 string Package::getConfigureLockName() const
179 {
180         return addName(user_support().absFileName(), ".lyx_configure_lock");
181 }
182
183
184 void Package::set_temp_dir(FileName const & temp_dir) const
185 {
186         if (temp_dir.empty())
187                 temp_dir_ = system_temp_dir_;
188         else
189                 temp_dir_ = temp_dir;
190 }
191
192
193 FileName Package::messages_file(string const & c) const
194 {
195         if (in_build_dir_) {
196                 FileName res = FileName(lyx_dir().absFileName() + "/po/" + c + ".gmo");
197                 if (!res.isReadableFile())
198                         res = FileName(lyx_dir().absFileName() + "../po/" + c + ".gmo");
199                 if (!res.isReadableFile())
200                         res = FileName(top_srcdir().absFileName() + "/po/" + c + ".gmo");
201                 return res;
202         } else
203                 return FileName(locale_dir_.absFileName() + "/" + c
204                         + "/LC_MESSAGES/" PACKAGE ".mo");
205 }
206
207
208 // The specification of home_dir_ is fixed for a given OS.
209 // A typical example on Windows: "C:/Documents and Settings/USERNAME"
210 // and on a Posix-like machine: "/home/USERNAME".
211 FileName const & Package::get_home_dir()
212 {
213 #if defined (USE_WINDOWS_PACKAGING)
214         static FileName const home_dir(getEnv("USERPROFILE"));
215 #elif defined (USE_MACOSX_PACKAGING)
216         static FileName const home_dir(fromqstr(QDir::homePath()));
217 #else // Posix-like.
218         static FileName const home_dir(getEnv("HOME"));
219 #endif
220         return home_dir;
221 }
222
223
224 namespace {
225
226 // These next functions contain the stuff that is substituted at
227 // configuration-time.
228 FileName const hardcoded_localedir()
229 {
230         // FIXME UNICODE
231         // The build system needs to make sure that this is in utf8 encoding.
232         return FileName(LYX_ABS_INSTALLED_LOCALEDIR);
233 }
234
235
236 FileName const hardcoded_system_support_dir()
237 {
238         // FIXME UNICODE
239         // The build system needs to make sure that this is in utf8 encoding.
240         return FileName(LYX_ABS_INSTALLED_DATADIR);
241 }
242
243
244 string const & with_version_suffix()
245 {
246         static string const program_suffix = PROGRAM_SUFFIX;
247         static string const with_version_suffix =
248                 " --with-version-suffix=" PROGRAM_SUFFIX;
249         return program_suffix.empty() ? program_suffix : with_version_suffix;
250 }
251
252 } // namespace
253
254
255 FileName const & Package::top_srcdir()
256 {
257         // FIXME UNICODE
258         // The build system needs to make sure that this is in utf8 encoding.
259         static FileName const dir(LYX_ABS_TOP_SRCDIR);
260         return dir;
261 }
262
263
264 namespace {
265
266 bool check_command_line_dir(string const & dir,
267                             string const & file,
268                             string const & command_line_switch);
269
270 FileName const extract_env_var_dir(string const & env_var);
271
272 bool check_env_var_dir(FileName const & dir,
273                        string const & env_var);
274
275 bool check_env_var_dir(FileName const & dir,
276                        string const & file,
277                        string const & env_var);
278
279 string const relative_locale_dir();
280
281 string const relative_system_support_dir();
282
283
284 /**
285  * Convert \p name to internal path and strip a trailing slash, since it
286  * comes from user input (commandline or environment).
287  * \p name is encoded in utf8.
288  */
289 string const fix_dir_name(string const & name)
290 {
291         return rtrim(os::internal_path(name), "/");
292 }
293
294
295
296 bool isBuildDir(FileName const & abs_binary, string const & dir_location,
297         FileName & build_support_dir)
298 {
299     string search_dir = onlyPath(abs_binary.absFileName()) + dir_location;
300
301     // Makefile by automake
302     build_support_dir = FileName(addPath(search_dir, "lib"));
303     if (!fileSearch(build_support_dir.absFileName(), "Makefile").empty()) {
304         return true;
305     }
306     //  cmake file, no Makefile in lib
307     FileName build_src_dir = FileName(addPath(search_dir, "src"));
308     if (!fileSearch(build_src_dir.absFileName(), "cmake_install.cmake").empty()) {
309         return true;
310     }
311
312     return false;
313 }
314
315 bool inBuildDir(FileName const & abs_binary,
316         FileName & build_support_dir, FileName & system_support_dir)
317 {
318         string const check_text = "Checking whether LyX is run in place...";
319
320         // We're looking for "Makefile" in a directory
321         //   binary_dir/../lib
322         // We're also looking for "chkconfig.ltx" in a directory
323         //   top_srcdir()/lib
324         // If both are found, then we're running LyX in-place.
325
326         // Note that the name of the lyx binary may be a symbolic link.
327         // If that is the case, then we follow the links too.
328     FileName binary = abs_binary;
329         while (true) {
330                 // Try and find "lyxrc.defaults".
331                 if( isBuildDir(binary, "../", build_support_dir) ||
332             isBuildDir(binary, "../../", build_support_dir))
333         {
334                         // Try and find "chkconfig.ltx".
335                         system_support_dir =
336                                 FileName(addPath(Package::top_srcdir().absFileName(), "lib"));
337
338                         if (!fileSearch(system_support_dir.absFileName(), "chkconfig.ltx").empty()) {
339                                 LYXERR(Debug::INIT, check_text << " yes");
340                                 return true;
341                         }
342                 }
343
344                 // Check whether binary is a symbolic link.
345                 // If so, resolve it and repeat the exercise.
346                 if (!binary.isSymLink())
347                         break;
348
349                 FileName link;
350                 if (readLink(binary, link)) {
351                         binary = link;
352                 } else {
353                         // Unable to resolve the link.
354                         break;
355                 }
356         }
357
358         LYXERR(Debug::INIT, check_text << " no");
359         system_support_dir = FileName();
360         build_support_dir = FileName();
361
362     return false;
363 }
364
365
366 bool doesFileExist(FileName & result, string const & search_dir, string const & name)
367 {
368     result = fileSearch(search_dir, name);
369     if (!result.empty()) {
370         return true;
371     }
372     return false;
373 }
374
375
376 bool lyxBinaryPath(FileName & lyx_binary, string const & search_dir, string const & ext)
377 {
378     lyx_binary = FileName();
379     if(false) {
380     } else if (doesFileExist(lyx_binary, search_dir, "lyx" + ext)) {
381     } else if (doesFileExist(lyx_binary, search_dir, "LyX" + ext)) {
382     } else if (doesFileExist(lyx_binary, search_dir, "lyx" + string(PROGRAM_SUFFIX) + ext)) {
383     } else if (doesFileExist(lyx_binary, search_dir, "LyX" + string(PROGRAM_SUFFIX) + ext)){
384     }
385     return !lyx_binary.empty() ? true : false;
386 }
387
388
389 FileName findLyxBinary(FileName const & abs_binary)
390 {
391     string ext;
392     string checkname = abs_binary.toFilesystemEncoding();
393     int check_len = checkname.length();
394     int prgsuffixlen = string(PROGRAM_SUFFIX).length();
395     if ((prgsuffixlen > 0) && (check_len > prgsuffixlen) &&
396        (checkname.substr(check_len-prgsuffixlen) == string(PROGRAM_SUFFIX))) {
397         ext = "";
398     }
399     else if (!abs_binary.extension().empty()) {
400         ext = "." + abs_binary.extension();
401     }
402
403     string binary_dir = onlyPath(abs_binary.absFileName());
404
405     FileName lyx_binary;
406     if (lyxBinaryPath(lyx_binary, binary_dir, ext))
407         return lyx_binary;
408
409     string search_dir = onlyPath(FileName(addPath(binary_dir, "/../")).absFileName());
410     if (lyxBinaryPath(lyx_binary, search_dir, ext))
411         return lyx_binary;
412
413     return FileName();
414 }
415
416
417 // Specification of document_dir_ may be reset by LyXRC,
418 // but the default is fixed for a given OS.
419 FileName const get_document_dir(FileName const & home_dir)
420 {
421 #if defined (USE_WINDOWS_PACKAGING)
422         (void)home_dir; // Silence warning about unused variable.
423         os::GetFolderPath win32_folder_path;
424         return FileName(win32_folder_path(os::GetFolderPath::PERSONAL));
425 #elif defined (USE_MACOSX_PACKAGING) && (QT_VERSION >= 0x050000)
426         (void)home_dir; // Silence warning about unused variable.
427         return FileName(fromqstr(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)));
428 #elif defined (USE_MACOSX_PACKAGING)
429         (void)home_dir; // Silence warning about unused variable.
430         return FileName(fromqstr(QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation)));
431 #else // Posix-like.
432         return home_dir;
433 #endif
434 }
435
436
437
438 // Several sources are probed to ascertain the locale directory.
439 // The only requirement is that the result is indeed a directory.
440 FileName const get_locale_dir(FileName const & system_support_dir)
441 {
442         // 1. Use the "LYX_LOCALEDIR" environment variable.
443         FileName const path_env = extract_env_var_dir("LYX_LOCALEDIR");
444         if (!path_env.empty() && check_env_var_dir(path_env, "LYX_LOCALEDIR"))
445                 return path_env;
446
447         // 2. Search for system_support_dir / <relative locale dir>
448         // The <relative locale dir> is OS-dependent. (On Unix, it will
449         // be "../locale/".)
450         FileName path(addPath(system_support_dir.absFileName(),
451                 relative_locale_dir()));
452
453         if (path.exists() && path.isDirectory())
454                 return path;
455
456         // 3. Fall back to the hard-coded LOCALEDIR.
457         path = hardcoded_localedir();
458         if (path.exists() && path.isDirectory())
459                 return path;
460
461         return FileName();
462 }
463
464
465 // Extracts the absolute path from the foo of "-sysdir foo" or "-userdir foo"
466 FileName const abs_path_from_command_line(string const & command_line)
467 {
468         if (command_line.empty())
469                 return FileName();
470
471         string const str_path = fix_dir_name(command_line);
472         return makeAbsPath(str_path);
473 }
474
475
476 // Does the grunt work for abs_path_from_binary_name()
477 FileName const get_binary_path(string const & exe)
478 {
479 #if defined (USE_WINDOWS_PACKAGING)
480         // The executable may have been invoked either with or
481         // without the .exe extension.
482         // Ensure that it is present.
483         string const as_internal_path = os::internal_path(exe);
484         string const exe_path = suffixIs(as_internal_path, ".exe") ?
485                 as_internal_path : as_internal_path + ".exe";
486 #else
487         string const exe_path = os::internal_path(exe);
488 #endif
489         if (FileName::isAbsolute(exe_path))
490                 return FileName(exe_path);
491
492         // Two possibilities present themselves.
493         // 1. The binary is relative to the CWD.
494         FileName const abs_exe_path = makeAbsPath(exe_path);
495         if (abs_exe_path.exists())
496                 return abs_exe_path;
497
498         // 2. exe must be the name of the binary only and it
499         // can be found on the PATH.
500         string const exe_name = onlyFileName(exe_path);
501         if (exe_name != exe_path)
502                 return FileName();
503
504         vector<string> const path = getEnvPath("PATH");
505         vector<string>::const_iterator it = path.begin();
506         vector<string>::const_iterator const end = path.end();
507         for (; it != end; ++it) {
508                 // This will do nothing if *it is already absolute.
509                 string const exe_dir = makeAbsPath(*it).absFileName();
510
511                 FileName const exe_path(addName(exe_dir, exe_name));
512                 if (exe_path.exists())
513                         return exe_path;
514         }
515
516         // Didn't find anything.
517         return FileName();
518 }
519
520
521 // Extracts the absolute path to the binary name received as argv[0].
522 FileName const abs_path_from_binary_name(string const & exe)
523 {
524         FileName const abs_binary = get_binary_path(exe);
525         if (abs_binary.empty()) {
526                 // FIXME UNICODE
527                 throw ExceptionMessage(ErrorException,
528                         _("LyX binary not found"),
529                         bformat(_("Unable to determine the path to the LyX binary from the command line %1$s"),
530                                 from_utf8(exe)));
531         }
532         return abs_binary;
533 }
534
535
536 // A plethora of directories is searched to ascertain the system
537 // lyxdir which is defined as the first directory to contain
538 // "chkconfig.ltx".
539 FileName const
540 get_system_support_dir(FileName const & abs_binary,
541                   string const & command_line_system_support_dir)
542 {
543         string const chkconfig_ltx = "chkconfig.ltx";
544
545         // searched_dirs is used for diagnostic purposes only in the case
546         // that "chkconfig.ltx" is not found.
547         list<FileName> searched_dirs;
548
549         // 1. Use the -sysdir command line parameter.
550         FileName path = abs_path_from_command_line(command_line_system_support_dir);
551         if (!path.empty()) {
552                 searched_dirs.push_back(path);
553                 if (check_command_line_dir(path.absFileName(), chkconfig_ltx, "-sysdir"))
554                         return path;
555         }
556
557         // 2. Use the "LYX_DIR_${major}${minor}x" environment variable.
558         path = extract_env_var_dir(LYX_DIR_VER);
559         if (!path.empty()) {
560                 searched_dirs.push_back(path);
561                 if (check_env_var_dir(path, chkconfig_ltx, LYX_DIR_VER))
562                         return path;
563         }
564
565         // 3. Search relative to the lyx binary.
566         // We're looking for "chkconfig.ltx" in a directory
567         //   OnlyPath(abs_binary) / <relative dir> / PACKAGE /
568         // PACKAGE is hardcoded in config.h. Eg "lyx" or "lyx-1.3.6cvs".
569         // <relative dir> is OS-dependent; on Unix, it will be "../share/".
570         string const relative_lyxdir = relative_system_support_dir();
571
572         // One subtlety to be aware of. The name of the lyx binary may be
573         // a symbolic link. If that is the case, then we follow the links too.
574         FileName binary = abs_binary;
575         while (true) {
576                 // Try and find "chkconfig.ltx".
577                 string const binary_dir = onlyPath(binary.absFileName());
578
579                 FileName const lyxdir(addPath(binary_dir, relative_lyxdir));
580                 searched_dirs.push_back(lyxdir);
581
582                 if (!fileSearch(lyxdir.absFileName(), chkconfig_ltx).empty()) {
583                         // Success! "chkconfig.ltx" has been found.
584                         return lyxdir;
585                 }
586
587                 // Check whether binary is a symbolic link.
588                 // If so, resolve it and repeat the exercise.
589                 if (!binary.isSymLink())
590                         break;
591
592                 FileName link;
593                 if (readLink(binary, link)) {
594                         binary = link;
595                 } else {
596                         // Unable to resolve the link.
597                         break;
598                 }
599         }
600
601         // 4. Repeat the exercise on the directory itself.
602         FileName binary_dir(onlyPath(abs_binary.absFileName()));
603         while (true) {
604                 // This time test whether the directory is a symbolic link
605                 // *before* looking for "chkconfig.ltx".
606                 // (We've looked relative to the original already.)
607                 if (!binary.isSymLink())
608                         break;
609
610                 FileName link;
611                 if (readLink(binary_dir, link)) {
612                         binary_dir = link;
613                 } else {
614                         // Unable to resolve the link.
615                         break;
616                 }
617
618                 // Try and find "chkconfig.ltx".
619                 FileName const lyxdir(addPath(binary_dir.absFileName(),
620                         relative_lyxdir));
621                 searched_dirs.push_back(lyxdir);
622
623                 if (!fileSearch(lyxdir.absFileName(), chkconfig_ltx).empty()) {
624                         // Success! "chkconfig.ltx" has been found.
625                         return lyxdir;
626                 }
627         }
628
629         // 5. In desparation, try the hard-coded system support dir.
630         path = hardcoded_system_support_dir();
631         if (!fileSearch(path.absFileName(), chkconfig_ltx).empty())
632                 return path;
633
634         // Everything has failed :-(
635         // So inform the user and exit.
636         string searched_dirs_str;
637         typedef list<FileName>::const_iterator iterator;
638         iterator const begin = searched_dirs.begin();
639         iterator const end = searched_dirs.end();
640         for (iterator it = begin; it != end; ++it) {
641                 if (it != begin)
642                         searched_dirs_str += "\n\t";
643                 searched_dirs_str += it->absFileName();
644         }
645
646         // FIXME UNICODE
647         throw ExceptionMessage(ErrorException, _("No system directory"),
648                 bformat(_("Unable to determine the system directory "
649                                 "having searched\n"
650                                 "\t%1$s\n"
651                                 "Use the '-sysdir' command line parameter or "
652                                 "set the environment variable\n%2$s "
653                                 "to the LyX system directory containing the "
654                                 "file `chkconfig.ltx'."),
655                           from_utf8(searched_dirs_str), from_ascii(LYX_DIR_VER)));
656 }
657
658
659 // Returns the absolute path to the user lyxdir, together with a flag
660 // indicating whether this directory was specified explicitly (as -userdir
661 // or through an environment variable) or whether it was deduced.
662 bool userSupportDir(FileName const & default_user_support_dir,
663         string const & command_line_user_support_dir, FileName & result)
664 {
665         // 1. Use the -userdir command line parameter.
666         result = abs_path_from_command_line(command_line_user_support_dir);
667         if (!result.empty())
668                 return true;
669
670         // 2. Use the LYX_USERDIR_${major}${minor}x environment variable.
671         result = extract_env_var_dir(LYX_USERDIR_VER);
672         if (!result.empty())
673                 return true;
674
675         // 3. Use the OS-dependent default_user_support_dir
676         result = default_user_support_dir;
677         return false;
678 }
679
680
681 // $HOME/.lyx on POSIX but on Win32 it will be something like
682 // "C:/Documents and Settings/USERNAME/Application Data/LyX"
683 FileName const get_default_user_support_dir(FileName const & home_dir)
684 {
685 #if defined (USE_WINDOWS_PACKAGING)
686         (void)home_dir; // Silence warning about unused variable.
687
688         os::GetFolderPath win32_folder_path;
689         return FileName(addPath(win32_folder_path(os::GetFolderPath::APPDATA), PACKAGE));
690
691 #elif defined (USE_MACOSX_PACKAGING) && (QT_VERSION >= 0x050000)
692         (void)home_dir; // Silence warning about unused variable.
693         return FileName(addPath(fromqstr(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)), PACKAGE));
694
695 #elif defined (USE_MACOSX_PACKAGING)
696         (void)home_dir; // Silence warning about unused variable.
697         return FileName(addPath(fromqstr(QDesktopServices::storageLocation(QDesktopServices::DataLocation)), PACKAGE));
698
699 #elif defined (USE_HAIKU_PACKAGING)
700         return FileName(addPath(home_dir.absFileName(), string("/config/settings/") + PACKAGE));
701
702 #else // USE_POSIX_PACKAGING
703         return FileName(addPath(home_dir.absFileName(), string(".") + PACKAGE));
704 #endif
705 }
706
707
708 // Check that directory @c dir contains @c file.
709 // Else emit an error message about an invalid @c command_line_switch.
710 bool check_command_line_dir(string const & dir,
711                             string const & file,
712                             string const & command_line_switch)
713 {
714         FileName const abs_path = fileSearch(dir, file);
715         if (abs_path.empty()) {
716                 // FIXME UNICODE
717                 throw ExceptionMessage(ErrorException, _("File not found"), bformat(
718                         _("Invalid %1$s switch.\nDirectory %2$s does not contain %3$s."),
719                         from_utf8(command_line_switch), from_utf8(dir),
720                         from_utf8(file)));
721         }
722
723         return !abs_path.empty();
724 }
725
726
727 // The environment variable @c env_var expands to a (single) file path.
728 FileName const extract_env_var_dir(string const & env_var)
729 {
730         string const dir = fix_dir_name(getEnv(env_var));
731         return dir.empty() ? FileName() : makeAbsPath(dir);
732 }
733
734
735 // Check that directory @c dir contains @c file.
736 // Else emit a warning about an invalid @c env_var.
737 bool check_env_var_dir(FileName const & dir,
738                        string const & file,
739                        string const & env_var)
740 {
741         FileName const abs_path = fileSearch(dir.absFileName(), file);
742         if (abs_path.empty()) {
743                 // FIXME UNICODE
744                 throw ExceptionMessage(WarningException, _("File not found"), bformat(
745                         _("Invalid %1$s environment variable.\n"
746                                 "Directory %2$s does not contain %3$s."),
747                         from_utf8(env_var), from_utf8(dir.absFileName()),
748                         from_utf8(file)));
749         }
750
751         return !abs_path.empty();
752 }
753
754
755 // Check that directory @c dir is indeed a directory.
756 // Else emit a warning about an invalid @c env_var.
757 bool check_env_var_dir(FileName const & dir,
758                        string const & env_var)
759 {
760         bool const success = dir.exists() && dir.isDirectory();
761
762         if (!success) {
763                 // Put this string on a single line so that the gettext
764                 // search mechanism in po/Makefile.in.in will register
765                 // Package.cpp.in as a file containing strings that need
766                 // translation.
767                 // FIXME UNICODE
768                 docstring const fmt =
769                         _("Invalid %1$s environment variable.\n%2$s is not a directory.");
770
771                 throw ExceptionMessage(WarningException, _("Directory not found"), bformat(
772                         fmt, from_utf8(env_var), from_utf8(dir.absFileName())));
773         }
774
775         return success;
776 }
777
778
779 // The locale directory relative to the LyX system directory.
780 string const relative_locale_dir()
781 {
782 #if defined (USE_WINDOWS_PACKAGING) || defined (USE_MACOSX_PACKAGING)
783         return "locale/";
784 #else
785         return "../locale/";
786 #endif
787 }
788
789
790 // The system lyxdir is relative to the directory containing the LyX binary.
791 string const relative_system_support_dir()
792 {
793         string result;
794
795 #if defined (USE_WINDOWS_PACKAGING) || defined (USE_MACOSX_PACKAGING)
796         result = "../Resources/";
797 #else // Posix-like.
798         result = addPath("../share/", PACKAGE);
799 #endif
800
801         return result;
802 }
803
804 } // namespace
805
806 } // namespace support
807 } // namespace lyx