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