3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
8 * Full author contact details are available in file CREDITS.
13 #include "support/filename.h"
14 #include "support/filetools.h"
15 #include "support/lstrings.h"
16 #include "support/os.h"
18 #include <boost/assert.hpp>
33 : save_abs_path_(true)
37 FileName::FileName(string const & abs_filename, bool save_abs)
38 : name_(abs_filename), save_abs_path_(save_abs)
40 BOOST_ASSERT(AbsolutePath(name_));
44 void FileName::set(string const & name, string const & buffer_path)
46 save_abs_path_ = AbsolutePath(name);
47 name_ = save_abs_path_ ? name : MakeAbsPath(name, buffer_path);
51 void FileName::erase()
57 string const FileName::relFilename(string const & path) const
59 return MakeRelPath(name_, path);
63 string const FileName::outputFilename(string const & path) const
65 return save_abs_path_ ? name_ : MakeRelPath(name_, path);
69 string const FileName::mangledFilename(std::string const & dir) const
71 // We need to make sure that every FileName instance for a given
72 // filename returns the same mangled name.
73 typedef map<string, string> MangledMap;
74 static MangledMap mangledNames;
75 MangledMap::const_iterator const it = mangledNames.find(name_);
76 if (it != mangledNames.end())
80 string mname = os::internal_path(name_);
81 // Remove the extension.
82 mname = ChangeExtension(name_, string());
83 // Replace '/' in the file name with '_'
84 mname = subst(mname, "/", "_");
85 // Replace '.' in the file name with '_'
86 mname = subst(mname, ".", "_");
87 // Replace ' ' in the file name with '_'
88 mname = subst(mname, " ", "_");
89 // Replace ':' in the file name with '_'
90 mname = subst(mname, ":", "_");
91 // Add the extension back on
92 mname = ChangeExtension(mname, GetExtension(name_));
94 // Prepend a counter to the filename. This is necessary to make
95 // the mangled name unique.
96 static int counter = 0;
98 s << counter++ << mname;
101 // Experiments show that MiKTeX's YAP (version 2.4.1803)
102 // will crash if the string referencing the file name in
103 // the .dvi file is longer than 220 characters.
104 // This string contains about 50 chars-worth of other data,
105 // leaving us, say, 160 characters for the file name itself.
106 // (Erring on the side of caution.)
107 string::size_type max_length = 160;
108 if (dir.size() - 1 < max_length) {
109 // If dir.size() > max_length, all bets are off anyway.
110 // "+ 1" for the directory separator.
111 max_length -= dir.size() + 1;
113 // If the mangled file name is too long, hack it to fit.
114 // We know we're guaranteed to have a unique file name because
116 if (mname.size() > max_length) {
117 int const half = (int(max_length) / 2) - 2;
119 mname = mname.substr(0, half) + "___" +
120 mname.substr(mname.size() - half);
125 mangledNames[name_] = mname;
130 bool FileName::isZipped() const
132 return zippedFile(name_);
136 string const FileName::unzippedFilename() const
138 return unzippedFileName(name_);
142 bool operator==(FileName const & lhs, FileName const & rhs)
144 return lhs.absFilename() == rhs.absFilename() &&
145 lhs.saveAbsPath() == rhs.saveAbsPath();
149 bool operator!=(FileName const & lhs, FileName const & rhs)
151 return !(lhs == rhs);
154 } // namespace support