2 filetools.C (former paths.C) - part of LyX project
3 General path-mangling functions
4 Copyright 1996 Ivan Schreter
5 Parts Copyright 1996 Dirk Niggemann
6 Parts Copyright 1985, 1990, 1993 Free Software Foundation, Inc.
7 Parts Copyright 1996 Asger Alstrup
11 lyx-filetool.C : tools functions for file/path handling
12 this file is part of LyX, the High Level Word Processor
13 Copyright 1995-1996, Matthias Ettrich and the LyX Team
27 #pragma implementation "filetools.h"
30 #include "filetools.h"
31 #include "LSubstring.h"
32 #include "lyx_gui_misc.h"
34 #include "support/path.h" // I know it's OS/2 specific (SMiyata)
35 #include "support/syscall.h"
39 // Which part of this is still necessary? (JMarc).
42 # define NAMLEN(dirent) strlen((dirent)->d_name)
44 # define dirent direct
45 # define NAMLEN(dirent) (dirent)->d_namlen
47 # include <sys/ndir.h>
70 extern string system_lyxdir;
71 extern string build_lyxdir;
72 extern string user_lyxdir;
73 extern string system_tempdir;
76 bool IsLyXFilename(string const & filename)
78 return contains(filename, ".lyx");
82 bool IsSGMLFilename(string const & filename)
84 return contains(filename, ".sgml");
88 // Substitutes spaces with underscores in filename (and path)
89 string const MakeLatexName(string const & file)
91 string name = OnlyFilename(file);
92 string const path = OnlyPath(file);
94 for (string::size_type i = 0; i < name.length(); ++i) {
95 name[i] &= 0x7f; // set 8th bit to 0
98 // ok so we scan through the string twice, but who cares.
99 string const keep("abcdefghijklmnopqrstuvwxyz"
100 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
101 "@!\"'()*+,-./0123456789:;<=>?[]`|");
103 string::size_type pos = 0;
104 while ((pos = name.find_first_not_of(keep, pos)) != string::npos) {
107 return AddName(path, name);
111 // Substitutes spaces with underscores in filename (and path)
112 string const QuoteName(string const & name)
114 // CHECK Add proper emx support here!
116 return "\'" + name + "\'";
123 // Is a file readable ?
124 bool IsFileReadable (string const & path)
127 if (file.isOK() && file.isRegular() && file.readable())
134 // Is a file read_only?
135 // return 1 read-write
137 // -1 error (doesn't exist, no access, anything else)
138 int IsFileWriteable (string const & path)
141 if (fi.access(FileInfo::wperm|FileInfo::rperm)) // read-write
143 if (fi.readable()) // read-only
145 return -1; // everything else.
149 //returns 1: dir writeable
151 // -1: error- couldn't find out
152 int IsDirWriteable (string const & path)
154 string const tmpfl(lyx::tempName(path)); //TmpFileName(path));
157 WriteFSAlert(_("LyX Internal Error!"),
158 _("Could not test if directory is writeable"));
162 if (fi.writable()) return 1;
168 // Uses a string of paths separated by ";"s to find a file to open.
169 // Can't cope with pathnames with a ';' in them. Returns full path to file.
170 // If path entry begins with $$LyX/, use system_lyxdir
171 // If path entry begins with $$User/, use user_lyxdir
172 // Example: "$$User/doc;$$LyX/doc"
173 string const FileOpenSearch (string const & path, string const & name,
176 string real_file, path_element;
177 bool notfound = true;
178 string tmppath = split(path, path_element, ';');
180 while (notfound && !path_element.empty()) {
181 path_element = CleanupPath(path_element);
182 if (!suffixIs(path_element, '/'))
184 path_element = subst(path_element, "$$LyX", system_lyxdir);
185 path_element = subst(path_element, "$$User", user_lyxdir);
187 real_file = FileSearch(path_element, name, ext);
189 if (real_file.empty()) {
191 tmppath = split(tmppath, path_element, ';');
192 } while(!tmppath.empty() && path_element.empty());
198 if (ext.empty() && notfound) {
199 real_file = FileOpenSearch(path, name, "exe");
200 if (notfound) real_file = FileOpenSearch(path, name, "cmd");
207 /// Returns a vector of all files in directory dir having extension ext.
208 vector<string> const DirList(string const & dir, string const & ext)
210 // This is a non-error checking C/system implementation
211 string extension(ext);
212 if (extension[0] != '.')
213 extension.insert(0, ".");
214 vector<string> dirlist;
215 DIR * dirp = ::opendir(dir.c_str());
217 while ((dire = ::readdir(dirp))) {
218 string const fil = dire->d_name;
219 if (prefixIs(fil, extension)) {
220 dirlist.push_back(fil);
225 /* I would have prefered to take a vector<string>& as parameter so
226 that we could avoid the copy of the vector when returning.
228 dirlist.swap(argvec);
229 to avoid the copy. (Lgb)
231 /* A C++ implementaion will look like this:
232 string extension(ext);
233 if (extension[0] != '.') extension.insert(0, ".");
234 vector<string> dirlist;
235 directory_iterator dit("dir");
236 while (dit != directory_iterator()) {
237 string fil = (*dit).filename;
238 if (prefixIs(fil, extension)) {
239 dirlist.push_back(fil);
243 dirlist.swap(argvec);
249 // Returns the real name of file name in directory path, with optional
251 string const FileSearch(string const & path, string const & name,
254 // if `name' is an absolute path, we ignore the setting of `path'
255 // Expand Environmentvariables in 'name'
256 string const tmpname = ReplaceEnvironmentPath(name);
257 string fullname = MakeAbsPath(tmpname, path);
259 // search first without extension, then with it.
260 if (IsFileReadable(fullname))
262 else if (ext.empty())
264 else { // Is it not more reasonable to use ChangeExtension()? (SMiyata)
267 if (IsFileReadable(fullname))
275 // Search the file name.ext in the subdirectory dir of
277 // 2) build_lyxdir (if not empty)
279 string const LibFileSearch(string const & dir, string const & name,
282 string fullname = FileSearch(AddPath(user_lyxdir, dir),
284 if (!fullname.empty())
287 if (!build_lyxdir.empty())
288 fullname = FileSearch(AddPath(build_lyxdir, dir),
290 if (!fullname.empty())
293 return FileSearch(AddPath(system_lyxdir, dir), name, ext);
298 i18nLibFileSearch(string const & dir, string const & name,
301 string const lang = token(string(GetEnv("LANG")), '_', 0);
303 if (lang.empty() || lang == "C")
304 return LibFileSearch(dir, name, ext);
306 string const tmp = LibFileSearch(dir, lang + '_' + name,
311 return LibFileSearch(dir, name, ext);
316 string const GetEnv(string const & envname)
318 // f.ex. what about error checking?
319 char const * const ch = getenv(envname.c_str());
320 string const envstr = !ch ? "" : ch;
325 string const GetEnvPath(string const & name)
328 string const pathlist = subst(GetEnv(name), ':', ';');
330 string const pathlist = subst(GetEnv(name), '\\', '/');
332 return strip(pathlist, ';');
336 bool PutEnv(string const & envstr)
338 // CHECK Look at and fix this.
339 // f.ex. what about error checking?
342 // this leaks, but what can we do about it?
343 // Is doing a getenv() and a free() of the older value
344 // a good idea? (JMarc)
345 // Actually we don't have to leak...calling putenv like this
346 // should be enough: ... and this is obviously not enough if putenv
347 // does not make a copy of the string. It is also not very wise to
348 // put a string on the free store. If we have to leak we should do it
350 char * leaker = new char[envstr.length() + 1];
351 envstr.copy(leaker, envstr.length());
352 leaker[envstr.length()] = '\0';
353 int const retval = lyx::putenv(leaker);
355 // If putenv does not make a copy of the char const * this
356 // is very dangerous. OTOH if it does take a copy this is the
358 // The only implementation of putenv that I have seen does not
359 // allocate memory. _And_ after testing the putenv in glibc it
360 // seems that we need to make a copy of the string contents.
361 // I will enable the above.
362 //int retval = lyx::putenv(envstr.c_str());
366 string const str = envstr.split(varname,'=');
367 int const retval = ::setenv(varname.c_str(), str.c_str(), true);
369 // No environment setting function. Can this happen?
370 int const retval = 1; //return an error condition.
377 bool PutEnvPath(string const & envstr)
379 return PutEnv(envstr);
384 int DeleteAllFilesInDir (string const & path)
386 // I have decided that we will be using parts from the boost
387 // library. Check out http://www.boost.org/
388 // For directory access we will then use the directory_iterator.
389 // Then the code will be something like:
390 // directory_iterator dit(path);
391 // directory_iterator dend;
392 // if (dit == dend) {
393 // WriteFSAlert(_("Error! Cannot open directory:"), path);
396 // for (; dit != dend; ++dit) {
397 // string filename(*dit);
398 // if (filename == "." || filename == "..")
400 // string unlinkpath(AddName(path, filename));
401 // if (lyx::unlink(unlinkpath))
402 // WriteFSAlert(_("Error! Could not remove file:"),
406 DIR * dir = ::opendir(path.c_str());
408 WriteFSAlert (_("Error! Cannot open directory:"), path);
412 int return_value = 0;
413 while ((de = readdir(dir))) {
414 string const temp = de->d_name;
415 if (temp == "." || temp == "..")
417 string const unlinkpath = AddName (path, temp);
419 lyxerr.debug() << "Deleting file: " << unlinkpath << endl;
422 if (FileInfo(unlinkpath).isDir())
423 deleted = (DeleteAllFilesInDir(unlinkpath) == 0);
424 deleted &= (lyx::unlink(unlinkpath) == 0);
426 WriteFSAlert (_("Error! Could not remove file:"),
437 string const CreateTmpDir(string const & tempdir, string const & mask)
440 << "CreateTmpDir: tempdir=`" << tempdir << "'\n"
441 << "CreateTmpDir: mask=`" << mask << "'" << endl;
443 string const tmpfl(lyx::tempName(tempdir, mask));
444 // lyx::tempName actually creates a file to make sure that it
445 // stays unique. So we have to delete it before we can create
446 // a dir with the same name. Note also that we are not thread
447 // safe because of the gap between unlink and mkdir. (Lgb)
448 lyx::unlink(tmpfl.c_str());
450 if (tmpfl.empty() || lyx::mkdir(tmpfl, 0777)) {
451 WriteFSAlert(_("Error! Couldn't create temporary directory:"),
455 return MakeAbsPath(tmpfl);
460 int DestroyTmpDir(string const & tmpdir, bool Allfiles)
465 if (Allfiles && DeleteAllFilesInDir(tmpdir)) return -1;
466 if (lyx::rmdir(tmpdir)) {
467 WriteFSAlert(_("Error! Couldn't delete temporary directory:"),
475 string const CreateBufferTmpDir(string const & pathfor)
477 return CreateTmpDir(pathfor, "lyx_tmpbuf");
481 int DestroyBufferTmpDir(string const & tmpdir)
483 return DestroyTmpDir(tmpdir, true);
487 string const CreateLyXTmpDir(string const & deflt)
489 if ((!deflt.empty()) && (deflt != "/tmp")) {
490 if (lyx::mkdir(deflt, 0777)) {
494 string const t(CreateTmpDir(deflt, "lyx_tmpdir"));
502 string const t(CreateTmpDir("/tmp", "lyx_tmpdir"));
508 int DestroyLyXTmpDir(string const & tmpdir)
510 return DestroyTmpDir (tmpdir, false); // Why false?
514 // Creates directory. Returns true if succesfull
515 bool createDirectory(string const & path, int permission)
517 string temp(strip(CleanupPath(path), '/'));
520 WriteAlert(_("Internal error!"),
521 _("Call to createDirectory with invalid name"));
525 if (lyx::mkdir(temp, permission)) {
526 WriteFSAlert (_("Error! Couldn't create directory:"), temp);
533 // Strip filename from path name
534 string const OnlyPath(string const & Filename)
536 // If empty filename, return empty
537 if (Filename.empty()) return Filename;
539 // Find last / or start of filename
540 string::size_type j = Filename.rfind('/');
541 if (j == string::npos)
543 return Filename.substr(0, j + 1);
547 // Convert relative path into absolute path based on a basepath.
548 // If relpath is absolute, just use that.
549 // If basepath is empty, use CWD as base.
550 string const MakeAbsPath(string const & RelPath, string const & BasePath)
552 // checks for already absolute path
553 if (AbsolutePath(RelPath))
555 if (RelPath[0]!= '/' && RelPath[0]!= '\\')
559 // Copies given paths
560 string TempRel(CleanupPath(RelPath));
564 if (!BasePath.empty()) {
568 char * with_drive = new char[_MAX_PATH];
569 _abspath(with_drive, BasePath.c_str(), _MAX_PATH);
570 TempBase = with_drive;
574 TempBase = lyx::getcwd(); //GetCWD();
576 if (AbsolutePath(TempRel))
577 return TempBase.substr(0, 2) + TempRel;
580 // Handle /./ at the end of the path
581 while(suffixIs(TempBase, "/./"))
582 TempBase.erase(TempBase.length() - 2);
584 // processes relative path
585 string RTemp(TempRel);
588 while (!RTemp.empty()) {
590 RTemp = split(RTemp, Temp, '/');
592 if (Temp == ".") continue;
594 // Remove one level of TempBase
595 string::difference_type i = TempBase.length() - 2;
598 while (i > 0 && TempBase[i] != '/') --i;
602 while (i > 2 && TempBase[i] != '/') --i;
605 TempBase.erase(i, string::npos);
609 // Add this piece to TempBase
610 if (!suffixIs(TempBase, '/'))
616 // returns absolute path
621 // Correctly append filename to the pathname.
622 // If pathname is '.', then don't use pathname.
623 // Chops any path of filename.
624 string const AddName(string const & path, string const & fname)
627 string const basename(OnlyFilename(fname));
631 if (path != "." && path != "./" && !path.empty()) {
632 buf = CleanupPath(path);
633 if (!suffixIs(path, '/'))
637 return buf + basename;
641 // Strips path from filename
642 string const OnlyFilename(string const & fname)
647 string::size_type j = fname.rfind('/');
648 if (j == string::npos) // no '/' in fname
652 return fname.substr(j + 1);
656 // Strips filename from path
657 string const BasePath(string const & fname)
662 string::size_type j = fname.rfind('/');
663 if (j == string::npos) // no '/' in fname
667 return fname.substr(0,j + 1);
671 // Is a filename/path absolute?
672 bool AbsolutePath(string const & path)
675 return (!path.empty() && path[0] == '/');
677 return (!path.empty() && (path[0] == '/' || (isalpha(static_cast<unsigned char>(path[0])) && path.length()>1 && path[1] == ':')));
682 // Create absolute path. If impossible, don't do anything
683 // Supports ./ and ~/. Later we can add support for ~logname/. (Asger)
684 string const ExpandPath(string const & path)
686 // checks for already absolute path
687 string RTemp(ReplaceEnvironmentPath(path));
688 if (AbsolutePath(RTemp))
692 string const copy(RTemp);
695 RTemp = split(RTemp, Temp, '/');
698 return lyx::getcwd() /*GetCWD()*/ + '/' + RTemp;
699 } else if (Temp == "~") {
700 return GetEnvPath("HOME") + '/' + RTemp;
701 } else if (Temp == "..") {
702 return MakeAbsPath(copy);
704 // Don't know how to handle this
710 // Constracts path/../path
711 // Can't handle "../../" or "/../" (Asger)
712 string const NormalizePath(string const & path)
718 if (AbsolutePath(path))
721 // Make implicit current directory explicit
724 while (!RTemp.empty()) {
726 RTemp = split(RTemp, Temp, '/');
730 } else if (Temp == "..") {
731 // Remove one level of TempBase
732 string::difference_type i = TempBase.length() - 2;
733 while (i > 0 && TempBase[i] != '/')
735 if (i >= 0 && TempBase[i] == '/')
736 TempBase.erase(i + 1, string::npos);
740 TempBase += Temp + '/';
744 // returns absolute path
749 string const CleanupPath(string const & path)
751 #ifdef __EMX__ /* SMiyata: This should fix searchpath bug. */
752 string temppath = subst(path, '\\', '/');
753 temppath = subst(temppath, "//", "/");
754 return lowercase(temppath);
755 #else // On unix, nothing to do
761 string const GetFileContents(string const & fname)
763 FileInfo finfo(fname);
765 ifstream ifs(fname.c_str());
766 std::ostringstream ofs;
770 return ofs.str().c_str();
773 lyxerr << "LyX was not able to read file '" << fname << "'" << endl;
779 // Search ${...} as Variable-Name inside the string and replace it with
780 // the denoted environmentvariable
781 // Allow Variables according to
782 // variable := '$' '{' [A-Za-z_]{[A-Za-z_0-9]*} '}'
785 string const ReplaceEnvironmentPath(string const & path)
788 // CompareChar: Environmentvariables starts with this character
789 // PathChar: Next path component start with this character
790 // while CompareChar found do:
791 // Split String with PathChar
792 // Search Environmentvariable
793 // if found: Replace Strings
795 char const CompareChar = '$';
796 char const FirstChar = '{';
797 char const EndChar = '}';
798 char const UnderscoreChar = '_';
799 string EndString; EndString += EndChar;
800 string FirstString; FirstString += FirstChar;
801 string CompareString; CompareString += CompareChar;
802 string const RegExp("*}*"); // Exist EndChar inside a String?
804 // first: Search for a '$' - Sign.
806 string result1; //(copy); // for split-calls
807 string result0 = split(path, result1, CompareChar);
808 while (!result0.empty()) {
809 string copy1(result0); // contains String after $
811 // Check, if there is an EndChar inside original String.
813 if (!regexMatch(copy1, RegExp)) {
814 // No EndChar inside. So we are finished
815 result1 += CompareString + result0;
821 string res0 = split(copy1, res1, EndChar);
822 // Now res1 holds the environmentvariable
823 // First, check, if Contents is ok.
824 if (res1.empty()) { // No environmentvariable. Continue Loop.
825 result1 += CompareString + FirstString;
829 // check contents of res1
830 char const * res1_contents = res1.c_str();
831 if (*res1_contents != FirstChar) {
832 // Again No Environmentvariable
833 result1 += CompareString;
837 // Check for variable names
838 // Situation ${} is detected as "No Environmentvariable"
839 char const * cp1 = res1_contents + 1;
840 bool result = isalpha(*cp1) || (*cp1 == UnderscoreChar);
842 while (*cp1 && result) {
843 result = isalnum(*cp1) ||
844 (*cp1 == UnderscoreChar);
849 // no correct variable name
850 result1 += CompareString + res1 + EndString;
851 result0 = split(res0, res1, CompareChar);
856 string env(GetEnv(res1_contents + 1));
858 // Congratulations. Environmentvariable found
861 result1 += CompareString + res1 + EndString;
864 result0 = split(res0, res1, CompareChar);
868 } // ReplaceEnvironmentPath
871 // Make relative path out of two absolute paths
872 string const MakeRelPath(string const & abspath0, string const & basepath0)
873 // Makes relative path out of absolute path. If it is deeper than basepath,
874 // it's easy. If basepath and abspath share something (they are all deeper
875 // than some directory), it'll be rendered using ..'s. If they are completely
876 // different, then the absolute path will be used as relative path.
878 // This is a hack. It should probaly be done in another way. Lgb.
879 string const abspath = CleanupPath(abspath0);
880 string const basepath = CleanupPath(basepath0);
882 return "<unknown_path>";
884 string::size_type const abslen = abspath.length();
885 string::size_type const baselen = basepath.length();
887 // Find first different character
888 string::size_type i = 0;
889 while (i < abslen && i < baselen && abspath[i] == basepath[i]) ++i;
892 if (i < abslen && i < baselen
893 || (i < abslen && abspath[i] != '/' && i == baselen)
894 || (i < baselen && basepath[i] != '/' && i == abslen))
896 if (i) --i; // here was the last match
897 while (i && abspath[i] != '/') --i;
901 // actually no match - cannot make it relative
905 // Count how many dirs there are in basepath above match
906 // and append as many '..''s into relpath
908 string::size_type j = i;
909 while (j < baselen) {
910 if (basepath[j] == '/') {
911 if (j + 1 == baselen) break;
917 // Append relative stuff from common directory to abspath
918 if (abspath[i] == '/') ++i;
919 for (; i < abslen; ++i)
922 if (suffixIs(buf, '/'))
923 buf.erase(buf.length() - 1);
924 // Substitute empty with .
931 // Append sub-directory(ies) to a path in an intelligent way
932 string const AddPath(string const & path, string const & path_2)
935 string const path2 = CleanupPath(path_2);
937 if (!path.empty() && path != "." && path != "./") {
938 buf = CleanupPath(path);
939 if (path[path.length() - 1] != '/')
943 if (!path2.empty()) {
944 string::size_type const p2start = path2.find_first_not_of('/');
945 string::size_type const p2end = path2.find_last_not_of('/');
946 string const tmp = path2.substr(p2start, p2end - p2start + 1);
954 Change extension of oldname to extension.
955 Strips path off if no_path == true.
956 If no extension on oldname, just appends.
959 ChangeExtension(string const & oldname, string const & extension)
961 string::size_type const last_slash = oldname.rfind('/');
962 string::size_type last_dot = oldname.rfind('.');
963 if (last_dot < last_slash && last_slash != string::npos)
964 last_dot = string::npos;
967 // Make sure the extension starts with a dot
968 if (!extension.empty() && extension[0] != '.')
969 ext= "." + extension;
973 return CleanupPath(oldname.substr(0, last_dot) + ext);
977 /// Return the extension of the file (not including the .)
978 string const GetExtension(string const & name)
980 string::size_type const last_slash = name.rfind('/');
981 string::size_type const last_dot = name.rfind('.');
982 if (last_dot != string::npos &&
983 (last_slash == string::npos || last_dot > last_slash))
984 return name.substr(last_dot + 1,
985 name.length() - (last_dot + 1));
991 // Creates a nice compact path for displaying
993 MakeDisplayPath (string const & path, unsigned int threshold)
995 string::size_type const l1 = path.length();
997 // First, we try a relative path compared to home
998 string const home(GetEnvPath("HOME"));
999 string relhome = MakeRelPath(path, home);
1001 string::size_type l2 = relhome.length();
1005 // If we backup from home or don't have a relative path,
1006 // this try is no good
1007 if (prefixIs(relhome, "../") || AbsolutePath(relhome)) {
1008 // relative path was no good, just use the original path
1015 // Is the path too long?
1016 if (l2 > threshold) {
1022 while (relhome.length() > threshold)
1023 relhome = split(relhome, temp, '/');
1025 // Did we shortend everything away?
1026 if (relhome.empty()) {
1027 // Yes, filename in itself is too long.
1028 // Pick the start and the end of the filename.
1029 relhome = OnlyFilename(path);
1030 string const head = relhome.substr(0, threshold/2 - 3);
1032 l2 = relhome.length();
1034 relhome.substr(l2 - threshold/2 - 2, l2 - 1);
1035 relhome = head + "..." + tail;
1038 return prefix + relhome;
1042 bool LyXReadLink(string const & File, string & Link)
1044 char LinkBuffer[512];
1045 // Should be PATH_MAX but that needs autconf support
1046 int const nRead = ::readlink(File.c_str(),
1047 LinkBuffer, sizeof(LinkBuffer) - 1);
1050 LinkBuffer[nRead] = '\0'; // terminator
1056 typedef pair<int, string> cmdret;
1058 cmdret const do_popen(string const & cmd)
1060 // One question is if we should use popen or
1061 // create our own popen based on fork, exec, pipe
1062 // of course the best would be to have a
1063 // pstream (process stream), with the
1064 // variants ipstream, opstream
1065 FILE * inf = ::popen(cmd.c_str(), "r");
1069 ret += static_cast<char>(c);
1072 int const pret = pclose(inf);
1073 return make_pair(pret, ret);
1078 findtexfile(string const & fil, string const & /*format*/)
1080 /* There is no problem to extend this function too use other
1081 methods to look for files. It could be setup to look
1082 in environment paths and also if wanted as a last resort
1083 to a recursive find. One of the easier extensions would
1084 perhaps be to use the LyX file lookup methods. But! I am
1085 going to implement this until I see some demand for it.
1089 // If the file can be found directly, we just return a
1090 // absolute path version of it.
1091 if (FileInfo(fil).exist())
1092 return MakeAbsPath(fil);
1094 // No we try to find it using kpsewhich.
1095 // It seems from the kpsewhich manual page that it is safe to use
1096 // kpsewhich without --format: "When the --format option is not
1097 // given, the search path used when looking for a file is inferred
1098 // from the name given, by looking for a known extension. If no
1099 // known extension is found, the search path for TeX source files
1101 // However, we want to take advantage of the format sine almost all
1102 // the different formats has environment variables that can be used
1103 // to controll which paths to search. f.ex. bib looks in
1104 // BIBINPUTS and TEXBIB. Small list follows:
1105 // bib - BIBINPUTS, TEXBIB
1107 // graphic/figure - TEXPICTS, TEXINPUTS
1108 // ist - TEXINDEXSTYLE, INDEXSTYLE
1109 // pk - PROGRAMFONTS, PKFONTS, TEXPKS, GLYPHFONTS, TEXFONTS
1111 // tfm - TFMFONTS, TEXFONTS
1112 // This means that to use kpsewhich in the best possible way we
1113 // should help it by setting additional path in the approp. envir.var.
1114 string const kpsecmd = "kpsewhich " + fil;
1116 cmdret const c = do_popen(kpsecmd);
1118 lyxerr[Debug::LATEX] << "kpse status = " << c.first << "\n"
1119 << "kpse result = `" << strip(c.second, '\n')
1121 return c.first != -1 ? strip(c.second, '\n') : string();
1125 void removeAutosaveFile(string const & filename)
1127 string a = OnlyPath(filename);
1129 a += OnlyFilename(filename);
1131 FileInfo const fileinfo(a);
1132 if (fileinfo.exist()) {
1133 if (lyx::unlink(a) != 0) {
1134 WriteFSAlert(_("Could not delete auto-save file!"), a);