]> git.lyx.org Git - lyx.git/blobdiff - src/support/filetools.C
fix typo that put too many include paths for most people
[lyx.git] / src / support / filetools.C
index 340da1cfa73b8494b47300f956492014129a5ae8..746a141da98427050f71f0f14fb5208fda23079a 100644 (file)
@@ -1,12 +1,12 @@
 /*
        filetools.C (former paths.C) - part of LyX project
-       General path-mangling functions 
+       General path-mangling functions
        Copyright 1996 Ivan Schreter
        Parts Copyright 1996 Dirk Niggemann
-        Parts Copyright 1985, 1990, 1993 Free Software Foundation, Inc.
+       Parts Copyright 1985, 1990, 1993 Free Software Foundation, Inc.
        Parts Copyright 1996 Asger Alstrup
-       
-       See also filetools.H.
+
+       See also filetools.h.
 
        lyx-filetool.C : tools functions for file/path handling
        this file is part of LyX, the High Level Word Processor
 #include <cctype>
 
 #include <utility>
-using std::make_pair;
-using std::pair;
+#include <fstream>
+
+#include "Lsstream.h"
 
 #ifdef __GNUG__
 #pragma implementation "filetools.h"
 #endif
 
+#include <cstdlib>
+#include <cstdio>
+#include <fcntl.h>
+#include <cerrno>
+#include "debug.h"
+#include "support/lstrings.h"
+#include "support/systemcall.h"
+
 #include "filetools.h"
 #include "LSubstring.h"
-#include "lyx_gui_misc.h"
+#include "frontends/Alert.h"
 #include "FileInfo.h"
 #include "support/path.h"        // I know it's OS/2 specific (SMiyata)
 #include "gettext.h"
 #include "lyxlib.h"
+#include "os.h"
 
 // Which part of this is still necessary? (JMarc).
 #if HAVE_DIRENT_H
@@ -52,39 +62,46 @@ using std::pair;
 # endif
 #endif
 
+using std::make_pair;
+using std::pair;
+using std::endl;
+using std::ifstream;
+using std::vector;
+
 extern string system_lyxdir;
 extern string build_lyxdir;
 extern string user_lyxdir;
 extern string system_tempdir;
+extern string system_packageList;
 
 
 bool IsLyXFilename(string const & filename)
 {
-       return contains(filename, ".lyx");
+       return suffixIs(lowercase(filename), ".lyx");
 }
 
 
 bool IsSGMLFilename(string const & filename)
 {
-       return contains(filename, ".sgml");
+       return suffixIs(lowercase(filename), ".sgml");
 }
 
 
 // Substitutes spaces with underscores in filename (and path)
-string MakeLatexName(string const & file)
+string const MakeLatexName(string const & file)
 {
        string name = OnlyFilename(file);
-       string path = OnlyPath(file);
-       
+       string const path = OnlyPath(file);
+
        for (string::size_type i = 0; i < name.length(); ++i) {
                name[i] &= 0x7f; // set 8th bit to 0
        };
 
        // ok so we scan through the string twice, but who cares.
-       string keep("abcdefghijklmnopqrstuvwxyz"
+       string const keep("abcdefghijklmnopqrstuvwxyz"
                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                "@!\"'()*+,-./0123456789:;<=>?[]`|");
-       
+
        string::size_type pos = 0;
        while ((pos = name.find_first_not_of(keep, pos)) != string::npos) {
                name[pos++] = '_';
@@ -92,48 +109,13 @@ string MakeLatexName(string const & file)
        return AddName(path, name);
 }
 
+
 // Substitutes spaces with underscores in filename (and path)
-string QuoteName(string const & name)
+string const QuoteName(string const & name)
 {
-#ifdef WITH_WARNINGS
-#warning Add proper emx support here!
-#endif
-#ifndef __EMX__
-       return '\'' + name + '\'';
-#else
-       return name; 
-#endif
-}
-
-
-/// Returns an unique name to be used as a temporary file. 
-string TmpFileName(string const & dir, string const & mask)
-{// With all these temporary variables, it should be safe enough :-) (JMarc)
-       string tmpdir;  
-       if (dir.empty())
-               tmpdir = system_tempdir;
-       else
-               tmpdir = dir;
-       string tmpfl = AddName(tmpdir, mask);
-
-       // find a uniq postfix for the filename...
-       // using the pid, and...
-       tmpfl += tostr(getpid());
-       // a short string...
-       string ret;
-       FileInfo fnfo;
-       for (int a = 'a'; a <= 'z'; ++a)
-               for (int b = 'a'; b <= 'z'; ++b)
-                       for (int c = 'a'; c <= 'z'; ++c) {
-                               // if this is not enough I have no idea what
-                               // to do.
-                               ret = tmpfl + char(a) + char(b) + char(c);
-                               // check if the file exist
-                               if (!fnfo.newFile(ret).exist())
-                                       return ret;
-                       }
-       lyxerr << "Not able to find a uniq tmpfile name." << endl;
-       return string();
+       return (os::shell() == os::UNIX) ?
+               "\'" + name + "\'":
+               "\"" + name + "\"";
 }
 
 
@@ -151,10 +133,11 @@ bool IsFileReadable (string const & path)
 // Is a file read_only?
 // return 1 read-write
 //       0 read_only
-//      -1 error (doesn't exist, no access, anything else) 
+//      -1 error (doesn't exist, no access, anything else)
 int IsFileWriteable (string const & path)
 {
        FileInfo fi(path);
+
        if (fi.access(FileInfo::wperm|FileInfo::rperm)) // read-write
                return 1;
        if (fi.readable()) // read-only
@@ -163,22 +146,19 @@ int IsFileWriteable (string const & path)
 }
 
 
-//returns 1: dir writeable
-//       0: not writeable
-//      -1: error- couldn't find out
-int IsDirWriteable (string const & path)
+//returns true: dir writeable
+//       false: not writeable
+bool IsDirWriteable (string const & path)
 {
-        string tmpfl = TmpFileName(path);
+       lyxerr[Debug::FILES] << "IsDirWriteable: " << path << endl;
 
-       if (tmpfl.empty()) {
-               WriteFSAlert(_("LyX Internal Error!"), 
-                            _("Could not test if directory is writeable"));
-               return -1;
-       } else {
-               FileInfo fi(path);
-               if (fi.writable()) return 1;
-               return 0;
-       }
+       string const tmpfl(lyx::tempName(path, "lyxwritetest"));
+
+       if (tmpfl.empty())
+               return false;
+
+       lyx::unlink(tmpfl);
+       return true;
 }
 
 
@@ -187,28 +167,28 @@ int IsDirWriteable (string const & path)
 // If path entry begins with $$LyX/, use system_lyxdir
 // If path entry begins with $$User/, use user_lyxdir
 // Example: "$$User/doc;$$LyX/doc"
-string FileOpenSearch (string const & path, string const & name, 
-                       string const & ext)
+string const FileOpenSearch (string const & path, string const & name,
+                            string const & ext)
 {
        string real_file, path_element;
        bool notfound = true;
        string tmppath = split(path, path_element, ';');
-       
+
        while (notfound && !path_element.empty()) {
-               path_element = CleanupPath(path_element);
+               path_element = os::slashify_path(path_element);
                if (!suffixIs(path_element, '/'))
                        path_element+= '/';
                path_element = subst(path_element, "$$LyX", system_lyxdir);
                path_element = subst(path_element, "$$User", user_lyxdir);
-               
+
                real_file = FileSearch(path_element, name, ext);
 
                if (real_file.empty()) {
-                 do {
-                   tmppath = split(tmppath, path_element, ';');
-                 } while(!tmppath.empty() && path_element.empty());
+                       do {
+                               tmppath = split(tmppath, path_element, ';');
+                       } while (!tmppath.empty() && path_element.empty());
                } else {
-                 notfound = false;
+                       notfound = false;
                }
        }
 #ifdef __EMX__
@@ -221,27 +201,75 @@ string FileOpenSearch (string const & path, string const & name,
 }
 
 
+/// Returns a vector of all files in directory dir having extension ext.
+vector<string> const DirList(string const & dir, string const & ext)
+{
+       // This is a non-error checking C/system implementation
+       string extension(ext);
+       if (!extension.empty() && extension[0] != '.')
+               extension.insert(0, ".");
+       vector<string> dirlist;
+       DIR * dirp = ::opendir(dir.c_str());
+       if (!dirp) {
+               lyxerr[Debug::FILES]
+                       << "Directory \"" << dir
+                       << "\" does not exist to DirList." << endl;
+               return dirlist;
+       }
+
+       dirent * dire;
+       while ((dire = ::readdir(dirp))) {
+               string const fil = dire->d_name;
+               if (suffixIs(fil, extension)) {
+                       dirlist.push_back(fil);
+               }
+       }
+       ::closedir(dirp);
+       return dirlist;
+       /* I would have prefered to take a vector<string>& as parameter so
+          that we could avoid the copy of the vector when returning.
+          Then we would use:
+          dirlist.swap(argvec);
+          to avoid the copy. (Lgb)
+       */
+       /* A C++ implementaion will look like this:
+          string extension(ext);
+          if (extension[0] != '.') extension.insert(0, ".");
+          vector<string> dirlist;
+          directory_iterator dit("dir");
+          while (dit != directory_iterator()) {
+                  string fil = dit->filename;
+                  if (prefixIs(fil, extension)) {
+                          dirlist.push_back(fil);
+                  }
+                  ++dit;
+          }
+          dirlist.swap(argvec);
+          return;
+       */
+}
+
+
 // Returns the real name of file name in directory path, with optional
-// extension ext.  
-string FileSearch(string const & path, string const & name, 
-                 string const & ext)
+// extension ext.
+string const FileSearch(string const & path, string const & name,
+                       string const & ext)
 {
        // if `name' is an absolute path, we ignore the setting of `path'
        // Expand Environmentvariables in 'name'
-       string tmpname = ReplaceEnvironmentPath(name);
+       string const tmpname = ReplaceEnvironmentPath(name);
        string fullname = MakeAbsPath(tmpname, path);
-       
        // search first without extension, then with it.
        if (IsFileReadable(fullname))
                return fullname;
-       else if (ext.empty()) 
+       else if (ext.empty())
                return string();
        else { // Is it not more reasonable to use ChangeExtension()? (SMiyata)
                fullname += '.';
                fullname += ext;
                if (IsFileReadable(fullname))
                        return fullname;
-               else 
+               else
                        return string();
        }
 }
@@ -251,17 +279,15 @@ string FileSearch(string const & path, string const & name,
 //   1) user_lyxdir
 //   2) build_lyxdir (if not empty)
 //   3) system_lyxdir
-string LibFileSearch(string const & dir, string const & name, 
-                    string const & ext)
+string const LibFileSearch(string const & dir, string const & name,
+                          string const & ext)
 {
-        string fullname = FileSearch(AddPath(user_lyxdir, dir),
-                                    name, ext); 
+       string fullname = FileSearch(AddPath(user_lyxdir, dir), name, ext);
        if (!fullname.empty())
                return fullname;
 
-       if (!build_lyxdir.empty()) 
-               fullname = FileSearch(AddPath(build_lyxdir, dir), 
-                                     name, ext);
+       if (!build_lyxdir.empty())
+               fullname = FileSearch(AddPath(build_lyxdir, dir), name, ext);
        if (!fullname.empty())
                return fullname;
 
@@ -269,16 +295,32 @@ string LibFileSearch(string const & dir, string const & name,
 }
 
 
-string i18nLibFileSearch(string const & dir, string const & name, 
-                        string const & ext)
+string const
+i18nLibFileSearch(string const & dir, string const & name,
+                 string const & ext)
 {
-       string lang = token(string(GetEnv("LANG")), '_', 0);
+       // this comment is from intl/dcigettext.c. We try to mimick this
+       // behaviour here.
+       /* The highest priority value is the `LANGUAGE' environment
+          variable. But we don't use the value if the currently
+          selected locale is the C locale. This is a GNU extension. */
+
+       string const lc_all = GetEnv("LC_ALL");
+       string lang = GetEnv("LANGUAGE");
+       if (lang.empty() || lc_all == "C") {
+               lang = lc_all;
+               if (lang.empty()) {
+                       lang = GetEnv("LANG");
+               }
+       }
+
+       lang = token(lang, '_', 0);
 
        if (lang.empty() || lang == "C")
                return LibFileSearch(dir, name, ext);
        else {
-               string tmp = LibFileSearch(dir, lang + '_' + name,
-                                           ext);
+               string const tmp = LibFileSearch(dir, lang + '_' + name,
+                                                ext);
                if (!tmp.empty())
                        return tmp;
                else
@@ -287,102 +329,159 @@ string i18nLibFileSearch(string const & dir, string const & name,
 }
 
 
-string GetEnv(string const & envname)
+string const LibScriptSearch(string const & command)
+{
+       string script;
+       string args = command;
+       split(args, script, ' ');
+       script = LibFileSearch("scripts", script);
+       if (script.empty())
+               return command;
+       else if (args.empty())
+               return script;
+       else
+               return script + ' ' + args;
+}
+
+
+string const GetEnv(string const & envname)
 {
-        // f.ex. what about error checking?
-        char const * const ch = getenv(envname.c_str());
-        string envstr = !ch ? "" : ch;
-        return envstr;
+       // f.ex. what about error checking?
+       char const * const ch = getenv(envname.c_str());
+       string const envstr = !ch ? "" : ch;
+       return envstr;
 }
 
 
-string GetEnvPath(string const & name)
+string const GetEnvPath(string const & name)
 {
 #ifndef __EMX__
-        string pathlist = subst(GetEnv(name), ':', ';');
+       string const pathlist = subst(GetEnv(name), ':', ';');
 #else
-        string pathlist = subst(GetEnv(name), '\\', '/');
+       string const pathlist = os::slashify_path(GetEnv(name));
 #endif
-        return strip(pathlist, ';');
+       return strip(pathlist, ';');
 }
 
 
 bool PutEnv(string const & envstr)
 {
-#ifdef WITH_WARNINGS
-#warning Look at and fix this.
-#endif
-        // f.ex. what about error checking?
+       // CHECK Look at and fix this.
+       // f.ex. what about error checking?
+
 #if HAVE_PUTENV
-        // this leaks, but what can we do about it?
-        //   Is doing a getenv() and a free() of the older value 
-        //   a good idea? (JMarc)
+       // this leaks, but what can we do about it?
+       //   Is doing a getenv() and a free() of the older value
+       //   a good idea? (JMarc)
        // Actually we don't have to leak...calling putenv like this
        // should be enough: ... and this is obviously not enough if putenv
        // does not make a copy of the string. It is also not very wise to
        // put a string on the free store. If we have to leak we should do it
        // like this:
-       /*
        char * leaker = new char[envstr.length() + 1];
        envstr.copy(leaker, envstr.length());
        leaker[envstr.length()] = '\0';
-       int retval = putenv(const_cast<PUTENV_TYPE_ARG>(leaker));
-       */
+       int const retval = lyx::putenv(leaker);
 
        // If putenv does not make a copy of the char const * this
        // is very dangerous. OTOH if it does take a copy this is the
        // best solution.
-       int retval = putenv(const_cast<PUTENV_TYPE_ARG>(envstr.c_str()));
+       // The  only implementation of putenv that I have seen does not
+       // allocate memory. _And_ after testing the putenv in glibc it
+       // seems that we need to make a copy of the string contents.
+       // I will enable the above.
+       //int retval = lyx::putenv(envstr.c_str());
 #else
-#ifdef HAVE_SETENV 
-        string varname;
-        string str = envstr.split(varname,'=');
-        int retval = setenv(varname.c_str(), str.c_str(), true);
+#ifdef HAVE_SETENV
+       string varname;
+       string const str = envstr.split(varname,'=');
+       int const retval = ::setenv(varname.c_str(), str.c_str(), true);
+#else
+       // No environment setting function. Can this happen?
+       int const retval = 1; //return an error condition.
 #endif
 #endif
-        return retval == 0;
+       return retval == 0;
 }
 
 
 bool PutEnvPath(string const & envstr)
 {
-        return PutEnv(envstr);
+       return PutEnv(envstr);
 }
 
 
-static
+namespace {
+
 int DeleteAllFilesInDir (string const & path)
 {
-       DIR * dir = opendir(path.c_str());
+       // I have decided that we will be using parts from the boost
+       // library. Check out http://www.boost.org/
+       // For directory access we will then use the directory_iterator.
+       // Then the code will be something like:
+       // directory_iterator dit(path);
+       // directory_iterator dend;
+       // if (dit == dend) {
+       //         Alert::err_alert(_("Error! Cannot open directory:"), path);
+       //         return -1;
+       // }
+       // for (; dit != dend; ++dit) {
+       //         string filename(*dit);
+       //         if (filename == "." || filename == "..")
+       //                 continue;
+       //         string unlinkpath(AddName(path, filename));
+       //         if (lyx::unlink(unlinkpath))
+       //                 Alert::err_alert(_("Error! Could not remove file:"),
+       //                              unlinkpath);
+       // }
+       // return 0;
+       DIR * dir = ::opendir(path.c_str());
        if (!dir) {
-               WriteFSAlert (_("Error! Cannot open directory:"), path);
+               Alert::err_alert (_("Error! Cannot open directory:"), path);
                return -1;
        }
        struct dirent * de;
+       int return_value = 0;
        while ((de = readdir(dir))) {
-               string temp = de->d_name;
-               if (temp == "." || temp == "..") 
+               string const temp = de->d_name;
+               if (temp == "." || temp == "..")
                        continue;
-               string unlinkpath = AddName (path, temp);
-
-               lyxerr.debug() << "Deleting file: " << unlinkpath << endl;
-
-               if (remove(unlinkpath.c_str()))
-                       WriteFSAlert (_("Error! Could not remove file:"), 
-                                     unlinkpath);
-        }
+               string const unlinkpath = AddName (path, temp);
+
+               lyxerr[Debug::FILES] << "Deleting file: " << unlinkpath
+                                    << endl;
+
+               bool deleted = true;
+               FileInfo fi(unlinkpath);
+               if (fi.isOK() && fi.isDir())
+                       deleted = (DeleteAllFilesInDir(unlinkpath) == 0);
+               deleted &= (lyx::unlink(unlinkpath) == 0);
+               if (!deleted) {
+                       Alert::err_alert(_("Error! Could not remove file:"),
+                               unlinkpath);
+                       return_value = -1;
+               }
+       }
        closedir(dir);
-       return 0;
+       return return_value;
 }
 
 
-static
-string CreateTmpDir (string const & tempdir, string const & mask)
+string const CreateTmpDir(string const & tempdir, string const & mask)
 {
-       string tmpfl = TmpFileName(tempdir, mask);
-       
-       if ((tmpfl.empty()) || mkdir (tmpfl.c_str(), 0777)) {
-               WriteFSAlert(_("Error! Couldn't create temporary directory:"),
+       lyxerr[Debug::FILES]
+               << "CreateTmpDir: tempdir=`" << tempdir << "'\n"
+               << "CreateTmpDir:    mask=`" << mask << "'" << endl;
+
+       string const tmpfl(lyx::tempName(tempdir, mask));
+       // lyx::tempName actually creates a file to make sure that it
+       // stays unique. So we have to delete it before we can create
+       // a dir with the same name. Note also that we are not thread
+       // safe because of the gap between unlink and mkdir. (Lgb)
+       lyx::unlink(tmpfl.c_str());
+
+       if (tmpfl.empty() || lyx::mkdir(tmpfl, 0700)) {
+               Alert::err_alert(_("Error! Couldn't create temporary directory:"),
                             tempdir);
                return string();
        }
@@ -390,104 +489,94 @@ string CreateTmpDir (string const & tempdir, string const & mask)
 }
 
 
-static
-int DestroyTmpDir (string const & tmpdir, bool Allfiles)
+int DestroyTmpDir(string const & tmpdir, bool Allfiles)
 {
 #ifdef __EMX__
        Path p(user_lyxdir);
 #endif
-       if (Allfiles && DeleteAllFilesInDir(tmpdir)) return -1;
-       if (rmdir(tmpdir.c_str())) { 
-               WriteFSAlert(_("Error! Couldn't delete temporary directory:"), 
+       if (Allfiles && DeleteAllFilesInDir(tmpdir)) {
+               return -1;
+       }
+       if (lyx::rmdir(tmpdir)) {
+               Alert::err_alert(_("Error! Couldn't delete temporary directory:"),
                             tmpdir);
                return -1;
        }
-       return 0; 
-} 
+       return 0;
+}
 
+} // namespace anon
 
-string CreateBufferTmpDir (string const & pathfor)
+
+string const CreateBufferTmpDir(string const & pathfor)
 {
-       return CreateTmpDir(pathfor, "lyx_bufrtmp");
+       static int count;
+       static string const tmpdir(pathfor.empty() ? os::getTmpDir() : pathfor);
+       // We are in our own directory.  Why bother to mangle name?
+       // In fact I wrote this code to circumvent a problematic behaviour (bug?)
+       // of EMX mkstemp().
+       string const tmpfl = tmpdir + "/lyx_tmpbuf" + tostr(count++);
+       if (lyx::mkdir(tmpfl, 0777)) {
+               Alert::err_alert(_("Error! Couldn't create temporary directory:"),
+                            tmpdir);
+               return string();
+       }
+       return tmpfl;
 }
 
 
-int DestroyBufferTmpDir (string const & tmpdir)
+int DestroyBufferTmpDir(string const & tmpdir)
 {
        return DestroyTmpDir(tmpdir, true);
 }
 
 
-string CreateLyXTmpDir (string const & deflt)
+string const CreateLyXTmpDir(string const & deflt)
 {
        if ((!deflt.empty()) && (deflt  != "/tmp")) {
-               if (mkdir(deflt.c_str(), 0777)) {
+               if (lyx::mkdir(deflt, 0777)) {
 #ifdef __EMX__
-                        Path p(user_lyxdir);
+               Path p(user_lyxdir);
 #endif
-                       string t = CreateTmpDir (deflt.c_str(), "lyx_tmp");
-                        return t;
+                       return CreateTmpDir(deflt, "lyx_tmpdir");
                } else
-                        return deflt;
+                       return deflt;
        } else {
 #ifdef __EMX__
                Path p(user_lyxdir);
 #endif
-               string t = CreateTmpDir ("/tmp", "lyx_tmp");
-               return t;
+               return CreateTmpDir("/tmp", "lyx_tmpdir");
        }
 }
 
 
-int DestroyLyXTmpDir (string const & tmpdir)
+int DestroyLyXTmpDir(string const & tmpdir)
 {
-       return DestroyTmpDir (tmpdir, false); // Why false?
+       return DestroyTmpDir (tmpdir, false); // Why false?
 }
 
 
 // Creates directory. Returns true if succesfull
 bool createDirectory(string const & path, int permission)
 {
-       string temp = strip(CleanupPath(path), '/');
+       string temp(strip(os::slashify_path(path), '/'));
 
        if (temp.empty()) {
-               WriteAlert(_("Internal error!"),
+               Alert::alert(_("Internal error!"),
                           _("Call to createDirectory with invalid name"));
                return false;
        }
 
-       if (mkdir(temp.c_str(), permission)) {
-               WriteFSAlert (_("Error! Couldn't create directory:"), temp);
+       if (lyx::mkdir(temp, permission)) {
+               Alert::err_alert (_("Error! Couldn't create directory:"), temp);
                return false;
        }
        return true;
 }
 
 
-// Returns current working directory
-string GetCWD ()
-{
-       int n = 256;    // Assume path is less than 256 chars
-       char * err;
-       char * tbuf = new char[n];
-       
-       // Safe. Hopefully all getcwds behave this way!
-       while (((err = lyx::getcwd (tbuf, n)) == 0) && (errno == ERANGE)) {
-               // Buffer too small, double the buffersize and try again
-               delete[] tbuf;
-               n = 2 * n;
-               tbuf = new char[n];
-       }
-
-       string result;
-       if (err) result = tbuf;
-       delete[] tbuf;
-       return result;
-}
-
-
 // Strip filename from path name
-string OnlyPath(string const & Filename)
+string const OnlyPath(string const & Filename)
 {
        // If empty filename, return empty
        if (Filename.empty()) return Filename;
@@ -503,52 +592,40 @@ string OnlyPath(string const & Filename)
 // Convert relative path into absolute path based on a basepath.
 // If relpath is absolute, just use that.
 // If basepath is empty, use CWD as base.
-string MakeAbsPath(string const & RelPath, string const & BasePath)
+string const MakeAbsPath(string const & RelPath, string const & BasePath)
 {
        // checks for already absolute path
-       if (AbsolutePath(RelPath))
-#ifdef __EMX__
-               if(RelPath[0]!= '/' && RelPath[0]!= '\\')
-#endif
+       if (os::is_absolute_path(RelPath))
                return RelPath;
 
        // Copies given paths
-       string TempRel = CleanupPath(RelPath);
+       string TempRel(os::slashify_path(RelPath));
+       // Since TempRel is NOT absolute, we can safely replace "//" with "/"
+       TempRel = subst(TempRel, "//", "/");
 
        string TempBase;
 
-       if (!BasePath.empty()) {
-#ifndef __EMX__
+       if (os::is_absolute_path(BasePath))
                TempBase = BasePath;
-#else
-               char * with_drive = new char[_MAX_PATH];
-               _abspath(with_drive, BasePath.c_str(), _MAX_PATH);
-               TempBase = with_drive;
-               delete[] with_drive;
-#endif
-       } else
-               TempBase = GetCWD();
-#ifdef __EMX__
-       if (AbsolutePath(TempRel))
-               return TempBase.substr(0, 2) + TempRel;
-#endif
+       else
+               TempBase = AddPath(lyx::getcwd(), BasePath);
 
        // Handle /./ at the end of the path
-       while(suffixIs(TempBase, "/./"))
+       while (suffixIs(TempBase, "/./"))
                TempBase.erase(TempBase.length() - 2);
 
        // processes relative path
-       string RTemp = TempRel;
+       string RTemp(TempRel);
        string Temp;
 
        while (!RTemp.empty()) {
                // Split by next /
                RTemp = split(RTemp, Temp, '/');
-               
+
                if (Temp == ".") continue;
                if (Temp == "..") {
                        // Remove one level of TempBase
-                       int i = TempBase.length() - 2;
+                       string::difference_type i = TempBase.length() - 2;
 #ifndef __EMX__
                        if (i < 0) i = 0;
                        while (i > 0 && TempBase[i] != '/') --i;
@@ -561,6 +638,9 @@ string MakeAbsPath(string const & RelPath, string const & BasePath)
                                TempBase.erase(i, string::npos);
                        else
                                TempBase += '/';
+               } else if (Temp.empty() && !RTemp.empty()) {
+                               TempBase = os::current_root() + RTemp;
+                               RTemp.erase();
                } else {
                        // Add this piece to TempBase
                        if (!suffixIs(TempBase, '/'))
@@ -570,22 +650,22 @@ string MakeAbsPath(string const & RelPath, string const & BasePath)
        }
 
        // returns absolute path
-       return TempBase;
+       return os::slashify_path(TempBase);
 }
 
 
 // Correctly append filename to the pathname.
 // If pathname is '.', then don't use pathname.
 // Chops any path of filename.
-string AddName(string const & path, string const & fname)
+string const AddName(string const & path, string const & fname)
 {
        // Get basename
-       string basename = OnlyFilename(fname);
+       string const basename(OnlyFilename(fname));
 
        string buf;
 
        if (path != "." && path != "./" && !path.empty()) {
-               buf = CleanupPath(path);
+               buf = os::slashify_path(path);
                if (!suffixIs(path, '/'))
                        buf += '/';
        }
@@ -595,7 +675,7 @@ string AddName(string const & path, string const & fname)
 
 
 // Strips path from filename
-string OnlyFilename(string const & fname)
+string const OnlyFilename(string const & fname)
 {
        if (fname.empty())
                return fname;
@@ -609,54 +689,53 @@ string OnlyFilename(string const & fname)
 }
 
 
-// Is a filename/path absolute?
+/// Returns true is path is absolute
 bool AbsolutePath(string const & path)
 {
-#ifndef __EMX__
-       return (!path.empty() && path[0] == '/');
-#else
-       return (!path.empty() && (path[0] == '/' || (isalpha(static_cast<unsigned char>(path[0])) && path.length()>1 && path[1] == ':')));
-#endif
+       return os::is_absolute_path(path);
 }
 
 
+
 // Create absolute path. If impossible, don't do anything
 // Supports ./ and ~/. Later we can add support for ~logname/. (Asger)
-string ExpandPath(string const & path)
+string const ExpandPath(string const & path)
 {
        // checks for already absolute path
-       string RTemp = ReplaceEnvironmentPath(path);
-       if (AbsolutePath(RTemp))
+       string RTemp(ReplaceEnvironmentPath(path));
+       if (os::is_absolute_path(RTemp))
                return RTemp;
 
        string Temp;
-       string copy(RTemp);
+       string const copy(RTemp);
 
        // Split by next /
-       RTemp= split(RTemp, Temp, '/');
+       RTemp = split(RTemp, Temp, '/');
 
        if (Temp == ".") {
-               return GetCWD() + '/' + RTemp;
-       } else if (Temp == "~") {
+               return lyx::getcwd() /*GetCWD()*/ + '/' + RTemp;
+       }
+       if (Temp == "~") {
                return GetEnvPath("HOME") + '/' + RTemp;
-       } else if (Temp == "..") {
+       }
+       if (Temp == "..") {
                return MakeAbsPath(copy);
-       } else
-               // Don't know how to handle this
-               return copy;
+       }
+       // Don't know how to handle this
+       return copy;
 }
 
 
 // Normalize a path
 // Constracts path/../path
 // Can't handle "../../" or "/../" (Asger)
-string NormalizePath(string const & path)
+string const NormalizePath(string const & path)
 {
        string TempBase;
        string RTemp;
        string Temp;
 
-       if (AbsolutePath(path))
+       if (os::is_absolute_path(path))
                RTemp = path;
        else
                // Make implicit current directory explicit
@@ -665,12 +744,12 @@ string NormalizePath(string const & path)
        while (!RTemp.empty()) {
                // Split by next /
                RTemp = split(RTemp, Temp, '/');
-               
+
                if (Temp == ".") {
                        TempBase = "./";
                } else if (Temp == "..") {
                        // Remove one level of TempBase
-                       int i = TempBase.length() - 2;
+                       string::difference_type i = TempBase.length() - 2;
                        while (i > 0 && TempBase[i] != '/')
                                --i;
                        if (i >= 0 && TempBase[i] == '/')
@@ -683,42 +762,48 @@ string NormalizePath(string const & path)
        }
 
        // returns absolute path
-       return TempBase;        
+       return TempBase;
 }
 
-string CleanupPath(string const & path) 
+
+string const GetFileContents(string const & fname)
 {
-#ifdef __EMX__   /* SMiyata: This should fix searchpath bug. */
-       string temppath = subst(path, '\\', '/');
-       temppath = subst(temppath, "//", "/");
-       return lowercase(temppath);
-#else // On unix, nothing to do
-       return path;
-#endif
+       FileInfo finfo(fname);
+       if (finfo.exist()) {
+               ifstream ifs(fname.c_str());
+               ostringstream ofs;
+               if (ifs && ofs) {
+                       ofs << ifs.rdbuf();
+                       ifs.close();
+                       return ofs.str().c_str();
+               }
+       }
+       lyxerr << "LyX was not able to read file '" << fname << "'" << endl;
+       return string();
 }
 
 
 //
 // Search ${...} as Variable-Name inside the string and replace it with
 // the denoted environmentvariable
-// Allow Variables according to 
+// Allow Variables according to
 //  variable :=  '$' '{' [A-Za-z_]{[A-Za-z_0-9]*} '}'
 //
 
-string ReplaceEnvironmentPath(string const & path)
+string const ReplaceEnvironmentPath(string const & path)
 {
-// 
+//
 // CompareChar: Environmentvariables starts with this character
 // PathChar:    Next path component start with this character
 // while CompareChar found do:
 //       Split String with PathChar
-//      Search Environmentvariable
+//      Search Environmentvariable
 //      if found: Replace Strings
 //
        char const CompareChar = '$';
-       char const FirstChar = '{'; 
-       char const EndChar = '}'; 
-       char const UnderscoreChar = '_'; 
+       char const FirstChar = '{';
+       char const EndChar = '}';
+       char const UnderscoreChar = '_';
        string EndString; EndString += EndChar;
        string FirstString; FirstString += FirstChar;
        string CompareString; CompareString += CompareChar;
@@ -730,13 +815,13 @@ string ReplaceEnvironmentPath(string const & path)
        string result0 = split(path, result1, CompareChar);
        while (!result0.empty()) {
                string copy1(result0); // contains String after $
-               
+
                // Check, if there is an EndChar inside original String.
-               
+
                if (!regexMatch(copy1, RegExp)) {
                        // No EndChar inside. So we are finished
                        result1 += CompareString + result0;
-                       result0.clear();
+                       result0.erase();
                        continue;
                }
 
@@ -763,8 +848,8 @@ string ReplaceEnvironmentPath(string const & path)
                bool result = isalpha(*cp1) || (*cp1 == UnderscoreChar);
                ++cp1;
                while (*cp1 && result) {
-                       result = isalnum(*cp1) || 
-                               (*cp1 == UnderscoreChar); 
+                       result = isalnum(*cp1) ||
+                               (*cp1 == UnderscoreChar);
                        ++cp1;
                }
 
@@ -775,8 +860,8 @@ string ReplaceEnvironmentPath(string const & path)
                        result1 += res1;
                        continue;
                }
-            
-               string env = GetEnv(res1_contents+1);
+
+               string env(GetEnv(res1_contents + 1));
                if (!env.empty()) {
                        // Congratulations. Environmentvariable found
                        result1 += env;
@@ -786,39 +871,22 @@ string ReplaceEnvironmentPath(string const & path)
                // Next $-Sign?
                result0  = split(res0, res1, CompareChar);
                result1 += res1;
-       } 
+       }
        return result1;
 }  // ReplaceEnvironmentPath
 
 
 // Make relative path out of two absolute paths
-string MakeRelPath(string const & abspath0, string const & basepath0)
+string const MakeRelPath(string const & abspath, string const & basepath)
 // Makes relative path out of absolute path. If it is deeper than basepath,
 // it's easy. If basepath and abspath share something (they are all deeper
 // than some directory), it'll be rendered using ..'s. If they are completely
 // different, then the absolute path will be used as relative path.
 {
-       // This is a hack. It should probaly be done in another way. Lgb.
-       string abspath = CleanupPath(abspath0);
-       string basepath = CleanupPath(basepath0);
-       if (abspath.empty())
-               return "<unknown_path>";
-
-       const int abslen = abspath.length();
-       const int baselen = basepath.length();
-       
-       // Find first different character
-       int i = 0;
-       while (i < abslen && i < baselen && abspath[i] == basepath[i]) ++i;
+       string::size_type const abslen = abspath.length();
+       string::size_type const baselen = basepath.length();
 
-       // Go back to last /
-       if (i < abslen && i < baselen
-           || (i<abslen && abspath[i] != '/' && i == baselen)
-           || (i<baselen && basepath[i] != '/' && i == abslen))
-       {
-               if (i) --i;     // here was the last match
-               while (i && abspath[i] != '/') --i;
-       }
+       string::size_type i = os::common_path(abspath, basepath);
 
        if (i == 0) {
                // actually no match - cannot make it relative
@@ -828,17 +896,19 @@ string MakeRelPath(string const & abspath0, string const & basepath0)
        // Count how many dirs there are in basepath above match
        // and append as many '..''s into relpath
        string buf;
-       int j = i;
+       string::size_type j = i;
        while (j < baselen) {
                if (basepath[j] == '/') {
-                       if (j+1 == baselen) break;
+                       if (j + 1 == baselen)
+                               break;
                        buf += "../";
                }
                ++j;
        }
 
        // Append relative stuff from common directory to abspath
-       if (abspath[i] == '/') ++i;
+       if (abspath[i] == '/')
+               ++i;
        for (; i < abslen; ++i)
                buf += abspath[i];
        // Remove trailing /
@@ -852,77 +922,284 @@ string MakeRelPath(string const & abspath0, string const & basepath0)
 
 
 // Append sub-directory(ies) to a path in an intelligent way
-string AddPath(string const & path, string const & path_2)
+string const AddPath(string const & path, string const & path_2)
 {
        string buf;
-       string path2 = CleanupPath(path_2);
+       string const path2 = os::slashify_path(path_2);
 
        if (!path.empty() && path != "." && path != "./") {
-               buf = CleanupPath(path);
+               buf = os::slashify_path(path);
                if (path[path.length() - 1] != '/')
                        buf += '/';
        }
 
-       if (!path2.empty()){
-               int p2start = path2.find_first_not_of('/');
-
-               int p2end = path2.find_last_not_of('/');
-
-               string tmp = path2.substr(p2start, p2end - p2start + 1);
+       if (!path2.empty()) {
+               string::size_type const p2start = path2.find_first_not_of('/');
+               string::size_type const p2end = path2.find_last_not_of('/');
+               string const tmp = path2.substr(p2start, p2end - p2start + 1);
                buf += tmp + '/';
        }
        return buf;
 }
 
 
-/* 
+/*
  Change extension of oldname to extension.
  Strips path off if no_path == true.
  If no extension on oldname, just appends.
  */
-string ChangeExtension(string const & oldname, string const & extension, 
-                       bool no_path) 
+string const ChangeExtension(string const & oldname, string const & extension)
 {
-       string::size_type last_slash = oldname.rfind('/');
-       string::size_type last_dot;
-       if (last_slash != string::npos)
-               last_dot = oldname.find('.', last_slash);
-       else
-               last_dot = oldname.rfind('.');
+       string::size_type const last_slash = oldname.rfind('/');
+       string::size_type last_dot = oldname.rfind('.');
+       if (last_dot < last_slash && last_slash != string::npos)
+               last_dot = string::npos;
 
        string ext;
        // Make sure the extension starts with a dot
        if (!extension.empty() && extension[0] != '.')
-               ext= '.' + extension;
+               ext= "." + extension;
        else
                ext = extension;
-       string ret_str;
-       if (no_path && last_slash != string::npos) {
-               ++last_slash; // step it
-               ret_str = oldname.substr(last_slash,
-                                        last_dot - last_slash) + ext;
-       } else
-               ret_str = oldname.substr(0, last_dot) + ext;
-       return CleanupPath(ret_str);
+
+       return os::slashify_path(oldname.substr(0, last_dot) + ext);
+}
+
+
+/// Return the extension of the file (not including the .)
+string const GetExtension(string const & name)
+{
+       string::size_type const last_slash = name.rfind('/');
+       string::size_type const last_dot = name.rfind('.');
+       if (last_dot != string::npos &&
+           (last_slash == string::npos || last_dot > last_slash))
+               return name.substr(last_dot + 1,
+                                  name.length() - (last_dot + 1));
+       else
+               return string();
+}
+
+// the different filetypes and what they contain in one of the first lines
+// (dots are any characters).          (Herbert 20020131)
+// AGR Grace...
+// BMP BM...
+// EPS %!PS-Adobe-3.0 EPSF...
+// FITS ...BITPIX...
+// GIF GIF...
+// JPG JFIF
+// PDF %PDF-...
+// PNG .PNG...
+// PBM P1... or P4     (B/W)
+// PGM P2... or P5     (Grayscale)
+// PPM P3... or P6     (color)
+// PS  %!PS-Adobe-2.0 or 1.0,  no "EPSF"!
+// SGI \001\332...     (decimal 474)
+// TGIF        %TGIF...
+// TIFF        II... or MM...
+// XBM ..._bits[]...
+// XPM /* XPM */
+// XWD \000\000\000\151        (0x00006900) decimal 105
+//
+// GZIP        \037\213\010\010...     http://www.ietf.org/rfc/rfc1952.txt
+// ZIP PK...                   http://www.halyava.ru/document/ind_arch.htm
+// Z   \037\177                UNIX compress
+
+/// return the "extension" which belongs to the contents.
+/// for no knowing contents return the extension. Without
+/// an extension and unknown contents we return "user"
+string const getExtFromContents(string const & filename) {
+       if (filename.empty() || !IsFileReadable(filename))
+               // paranoia check
+               return string();
+
+       ifstream ifs(filename.c_str());
+       if (!ifs)
+               // Couldn't open file...
+               return string();
+
+       // gnuzip
+       string const gzipStamp = "\037\213\010\010";
+
+       // PKZIP
+       string const zipStamp = "PK";
+
+       // compress
+       string const compressStamp = "\037\177";
+
+       // Maximum strings to read
+       int const max_count = 50;
+       int count = 0;
+
+       string str, format;
+       bool firstLine = true;
+       while ((count++ < max_count) && format.empty()) {
+               if (ifs.eof()) {
+                       lyxerr[Debug::GRAPHICS]
+                               << "filetools(getExtFromContents)\n"
+                               << "\tFile type not recognised before EOF!"
+                               << endl;
+                       break;
+               }
+
+               ifs >> str;
+               lyxerr[Debug::GRAPHICS]
+                   << "Scanstring: " << str << endl;
+               string const stamp = str.substr(0,2);
+               if (firstLine && str.size() >= 2) {
+                       // at first we check for a zipped file, because this
+                       // information is saved in the first bytes of the file!
+                       // also some graphic formats which save the information
+                       // in the first line, too.
+                       if (prefixIs(str, gzipStamp))
+                               format =  "gzip";
+
+                       else if (stamp == zipStamp)
+                               format =  "zip";
+
+                       else if (stamp == compressStamp)
+                               format =  "compress";
+
+                       // the graphics part
+                       else if (stamp == "BM")
+                               format =  "bmp";
+
+                       else if (stamp == "\001\332")
+                               format =  "sgi";
+                       // PBM family
+                       // Don't need to use str.at(0), str.at(1) because
+                       // we already know that str.size() >= 2
+                       else if (str[0] == 'P') {
+                               switch (str[1]) {
+                               case '1':
+                               case '4':
+                                       format =  "pbm";
+                                   break;
+                               case '2':
+                               case '5':
+                                       format =  "pgm";
+                                   break;
+                               case '3':
+                               case '6':
+                                       format =  "ppm";
+                               }
+                               break;
+                       }
+                       if (stamp == "\001\332")
+                           format =  "sgi";
+                       else if ((stamp == "II") || (stamp == "MM"))
+                           format =  "tiff";
+                       else if (str == "%TGIF")
+                           format =  "tgif";
+                       else if (prefixIs(str,"GIF"))
+                           format =  "gif";
+                       else if (str.size() > 3)        // get long
+                           if (((str[0] << 24) + (str[1] << 16) +
+                               (str[2] << 8) + str[3]) == 105)
+                               format =  "xwd";
+                       firstLine = false;
+               }
+               if (!format.empty())
+                   break;
+               else if (contains(str,"EPSF"))
+                       // dummy, if we have wrong file description like
+                       // description like "%!PS-Adobe-2.0EPSF"
+                       format =  "eps";
+
+               else if (contains(str,"Grace"))
+                       format =  "agr";
+
+               else if (contains(str,"JFIF"))
+                       format =  "jpg";
+
+               else if (contains(str,"%PDF"))
+                       format =  "pdf";
+
+               else if (contains(str,"PNG"))
+                       format =  "png";
+
+               else if (contains(str,"%!PS-Adobe")) {
+                       // eps or ps
+                       ifs >> str;
+                       if (contains(str,"EPSF"))
+                               format = "eps";
+                       else
+                           format = "ps";
+               }
+
+               else if (contains(str,"_bits[]"))
+                       format = "xbm";
+
+               else if (contains(str,"XPM"))
+                       format = "xpm";
+
+               else if (contains(str,"BITPIX"))
+                       format = "fits";
+       }
+
+       if (!format.empty()) {
+           lyxerr[Debug::GRAPHICS]
+               << "Recognised Fileformat: " << format << endl;
+           return format;
+       }
+
+       string const ext(GetExtension(filename));
+       lyxerr[Debug::GRAPHICS]
+               << "filetools(getExtFromContents)\n"
+               << "\tCouldn't find a known Type!\n";
+       if (!ext.empty()) {
+           lyxerr[Debug::GRAPHICS]
+               << "\twill take the file extension -> "
+               << ext << endl;
+               return ext;
+       } else {
+           lyxerr[Debug::GRAPHICS]
+               << "\twill use ext or a \"user\" defined format" << endl;
+           return "user";
+       }
+}
+
+
+/// check for zipped file
+bool zippedFile(string const & name)
+{
+       string const type = getExtFromContents(name);
+       if (contains("gzip zip compress", type) && !type.empty())
+               return true;
+       return false;
+}
+
+
+string const unzipFile(string const & zipped_file)
+{
+       string const file = ChangeExtension(zipped_file, string());
+       string  const tempfile = lyx::tempName(string(), file);
+       // Run gunzip
+       string const command = "gunzip -c " + zipped_file + " > " + tempfile;
+       Systemcall one;
+       one.startscript(Systemcall::Wait, command);
+       // test that command was executed successfully (anon)
+       // yes, please do. (Lgb)
+       return tempfile;
 }
 
 
 // Creates a nice compact path for displaying
-string MakeDisplayPath (string const & path, unsigned int threshold)
+string const
+MakeDisplayPath (string const & path, unsigned int threshold)
 {
-       const int l1 = path.length();
+       string::size_type const l1 = path.length();
 
        // First, we try a relative path compared to home
-       string home = GetEnvPath("HOME");
+       string const home(GetEnvPath("HOME"));
        string relhome = MakeRelPath(path, home);
 
-       unsigned int l2 = relhome.length();
+       string::size_type l2 = relhome.length();
 
        string prefix;
 
        // If we backup from home or don't have a relative path,
        // this try is no good
-       if (prefixIs(relhome, "../") || AbsolutePath(relhome)) {
+       if (prefixIs(relhome, "../") || os::is_absolute_path(relhome)) {
                // relative path was no good, just use the original path
                relhome = path;
                l2 = l1;
@@ -934,9 +1211,9 @@ string MakeDisplayPath (string const & path, unsigned int threshold)
        if (l2 > threshold) {
                // Yes, shortend it
                prefix += ".../";
-               
+
                string temp;
-               
+
                while (relhome.length() > threshold)
                        relhome = split(relhome, temp, '/');
 
@@ -945,10 +1222,10 @@ string MakeDisplayPath (string const & path, unsigned int threshold)
                        // Yes, filename in itself is too long.
                        // Pick the start and the end of the filename.
                        relhome = OnlyFilename(path);
-                       string head = relhome.substr(0, threshold/2 - 3);
+                       string const head = relhome.substr(0, threshold/2 - 3);
 
                        l2 = relhome.length();
-                       string tail =
+                       string const tail =
                                relhome.substr(l2 - threshold/2 - 2, l2 - 1);
                        relhome = head + "..." + tail;
                }
@@ -961,36 +1238,48 @@ bool LyXReadLink(string const & File, string & Link)
 {
        char LinkBuffer[512];
        // Should be PATH_MAX but that needs autconf support
-       int nRead = readlink(File.c_str(), LinkBuffer, sizeof(LinkBuffer)-1);
+       int const nRead = ::readlink(File.c_str(),
+                                    LinkBuffer, sizeof(LinkBuffer) - 1);
        if (nRead <= 0)
                return false;
-       LinkBuffer[nRead] = 0;
+       LinkBuffer[nRead] = '\0'; // terminator
        Link = LinkBuffer;
        return true;
 }
 
 
+namespace {
+
 typedef pair<int, string> cmdret;
-static cmdret do_popen(string const & cmd)
+
+cmdret const do_popen(string const & cmd)
 {
        // One question is if we should use popen or
        // create our own popen based on fork, exec, pipe
        // of course the best would be to have a
        // pstream (process stream), with the
        // variants ipstream, opstream
-       FILE * inf = popen(cmd.c_str(), "r");
+
+       FILE * inf = ::popen(cmd.c_str(), os::read_mode());
+
+       // (Claus Hentschel) Check if popen was succesful ;-)
+       if (!inf)
+               return make_pair(-1, string());
+
        string ret;
        int c = fgetc(inf);
        while (c != EOF) {
                ret += static_cast<char>(c);
                c = fgetc(inf);
        }
-       int pret = pclose(inf);
+       int const pret = pclose(inf);
        return make_pair(pret, ret);
 }
 
+} // namespace anon
+
 
-string findtexfile(string const & fil, string const & format)
+string const findtexfile(string const & fil, string const & /*format*/)
 {
        /* There is no problem to extend this function too use other
           methods to look for files. It could be setup to look
@@ -1000,21 +1289,56 @@ string findtexfile(string const & fil, string const & format)
           going to implement this until I see some demand for it.
           Lgb
        */
-       
-        // If fil is a file with absolute path we just return it
-        if (AbsolutePath(fil)) return fil;
-       
-        // Check in the current dir.
-        if (FileInfo(OnlyFilename(fil)).exist())
-               return OnlyFilename(fil);
-       
-        // No we try to find it using kpsewhich.
-        string kpsecmd = "kpsewhich --format=" + format + " " + OnlyFilename(fil);
-
-        cmdret c = do_popen(kpsecmd);
-       
-        lyxerr[Debug::LATEX] << "kpse status = " << c.first << "\n"
-                            << "kpse result = `" << strip(c.second, '\n') 
-                            << "'" << endl;
-        return c.first != -1 ? strip(c.second, '\n') : string();
+
+       // If the file can be found directly, we just return a
+       // absolute path version of it.
+       if (FileInfo(fil).exist())
+               return MakeAbsPath(fil);
+
+       // No we try to find it using kpsewhich.
+       // It seems from the kpsewhich manual page that it is safe to use
+       // kpsewhich without --format: "When the --format option is not
+       // given, the search path used when looking for a file is inferred
+       // from the name given, by looking for a known extension. If no
+       // known extension is found, the search path for TeX source files
+       // is used."
+       // However, we want to take advantage of the format sine almost all
+       // the different formats has environment variables that can be used
+       // to controll which paths to search. f.ex. bib looks in
+       // BIBINPUTS and TEXBIB. Small list follows:
+       // bib - BIBINPUTS, TEXBIB
+       // bst - BSTINPUTS
+       // graphic/figure - TEXPICTS, TEXINPUTS
+       // ist - TEXINDEXSTYLE, INDEXSTYLE
+       // pk - PROGRAMFONTS, PKFONTS, TEXPKS, GLYPHFONTS, TEXFONTS
+       // tex - TEXINPUTS
+       // tfm - TFMFONTS, TEXFONTS
+       // This means that to use kpsewhich in the best possible way we
+       // should help it by setting additional path in the approp. envir.var.
+       string const kpsecmd = "kpsewhich " + fil;
+
+       cmdret const c = do_popen(kpsecmd);
+
+       lyxerr[Debug::LATEX] << "kpse status = " << c.first << "\n"
+                << "kpse result = `" << strip(c.second, '\n')
+                << "'" << endl;
+       if (c.first != -1)
+               return os::internal_path(strip(strip(c.second, '\n'), '\r'));
+       else
+               return string();
+}
+
+
+void removeAutosaveFile(string const & filename)
+{
+       string a = OnlyPath(filename);
+       a += '#';
+       a += OnlyFilename(filename);
+       a += '#';
+       FileInfo const fileinfo(a);
+       if (fileinfo.exist()) {
+               if (lyx::unlink(a) != 0) {
+                       Alert::err_alert(_("Could not delete auto-save file!"), a);
+               }
+       }
 }