]> git.lyx.org Git - lyx.git/blob - src/support/filename.C
Provide do_put methods for inserting all remaining basic type values
[lyx.git] / src / support / filename.C
1 /**
2  * \file filename.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "support/filename.h"
14 #include "support/filetools.h"
15 #include "support/lstrings.h"
16 #include "support/os.h"
17 #include "support/qstring_helpers.h"
18
19 #include <QFile>
20
21 #include <boost/assert.hpp>
22
23 #include <map>
24 #include <sstream>
25 #include <algorithm>
26
27
28 using std::map;
29 using std::string;
30
31
32 namespace lyx {
33 namespace support {
34
35
36 FileName::FileName()
37 {}
38
39
40 FileName::~FileName()
41 {}
42
43
44 FileName::FileName(string const & abs_filename)
45         : name_(abs_filename)
46 {
47         BOOST_ASSERT(empty() || absolutePath(name_));
48         BOOST_ASSERT(!contains(name_, '\\'));
49 }
50
51
52 void FileName::set(string const & name)
53 {
54         name_ = name;
55         BOOST_ASSERT(absolutePath(name_));
56         BOOST_ASSERT(!contains(name_, '\\'));
57 }
58
59
60 void FileName::erase()
61 {
62         name_.erase();
63 }
64
65
66 string const FileName::toFilesystemEncoding() const
67 {
68         QByteArray const encoded = QFile::encodeName(toqstr(name_));
69         return string(encoded.begin(), encoded.end());
70 }
71
72
73 bool operator==(FileName const & lhs, FileName const & rhs)
74 {
75         return lhs.absFilename() == rhs.absFilename();
76 }
77
78
79 bool operator!=(FileName const & lhs, FileName const & rhs)
80 {
81         return lhs.absFilename() != rhs.absFilename();
82 }
83
84
85 bool operator<(FileName const & lhs, FileName const & rhs)
86 {
87         return lhs.absFilename() < rhs.absFilename();
88 }
89
90
91 bool operator>(FileName const & lhs, FileName const & rhs)
92 {
93         return lhs.absFilename() > rhs.absFilename();
94 }
95
96
97 std::ostream & operator<<(std::ostream & os, FileName const & filename)
98 {
99         return os << filename.absFilename();
100 }
101
102
103 DocFileName::DocFileName()
104         : save_abs_path_(true)
105 {}
106
107
108 DocFileName::DocFileName(string const & abs_filename, bool save_abs)
109         : FileName(abs_filename), save_abs_path_(save_abs), zipped_valid_(false)
110 {}
111
112
113 void DocFileName::set(string const & name, string const & buffer_path)
114 {
115         save_abs_path_ = absolutePath(name);
116         name_ = save_abs_path_ ? name : makeAbsPath(name, buffer_path);
117         zipped_valid_ = false;
118 }
119
120
121 void DocFileName::erase()
122 {
123         name_.erase();
124         zipped_valid_ = false;
125 }
126
127
128 string const DocFileName::relFilename(string const & path) const
129 {
130         return makeRelPath(name_, path);
131 }
132
133
134 string const DocFileName::outputFilename(string const & path) const
135 {
136         return save_abs_path_ ? name_ : makeRelPath(name_, path);
137 }
138
139
140 string const DocFileName::mangledFilename(std::string const & dir) const
141 {
142         // We need to make sure that every DocFileName instance for a given
143         // filename returns the same mangled name.
144         typedef map<string, string> MangledMap;
145         static MangledMap mangledNames;
146         MangledMap::const_iterator const it = mangledNames.find(name_);
147         if (it != mangledNames.end())
148                 return (*it).second;
149
150         // Now the real work
151         string mname = os::internal_path(name_);
152         // Remove the extension.
153         mname = changeExtension(name_, string());
154         // Replace '/' in the file name with '_'
155         mname = subst(mname, "/", "_");
156         // Replace '.' in the file name with '_'
157         mname = subst(mname, ".", "_");
158         // Replace ' ' in the file name with '_'
159         mname = subst(mname, " ", "_");
160         // Replace ':' in the file name with '_'
161         mname = subst(mname, ":", "_");
162         // Add the extension back on
163         mname = changeExtension(mname, getExtension(name_));
164
165         // Prepend a counter to the filename. This is necessary to make
166         // the mangled name unique.
167         static int counter = 0;
168         std::ostringstream s;
169         s << counter++ << mname;
170         mname = s.str();
171
172         // MiKTeX's YAP (version 2.4.1803) crashes if the file name
173         // is longer than about 160 characters. MiKTeX's pdflatex
174         // is even pickier. A maximum length of 100 has been proven to work.
175         // If dir.size() > max length, all bets are off for YAP. We truncate
176         // the filename nevertheless, keeping a minimum of 10 chars.
177
178         string::size_type max_length = std::max(100 - ((int)dir.size() + 1), 10);
179
180         // If the mangled file name is too long, hack it to fit.
181         // We know we're guaranteed to have a unique file name because
182         // of the counter.
183         if (mname.size() > max_length) {
184                 int const half = (int(max_length) / 2) - 2;
185                 if (half > 0) {
186                         mname = mname.substr(0, half) + "___" +
187                                 mname.substr(mname.size() - half);
188                 }
189         }
190
191         mangledNames[name_] = mname;
192         return mname;
193 }
194
195
196 bool DocFileName::isZipped() const
197 {
198         if (!zipped_valid_) {
199                 zipped_ = zippedFile(*this);
200                 zipped_valid_ = true;
201         }
202         return zipped_;
203 }
204
205
206 string const DocFileName::unzippedFilename() const
207 {
208         return unzippedFileName(name_);
209 }
210
211
212 bool operator==(DocFileName const & lhs, DocFileName const & rhs)
213 {
214         return lhs.absFilename() == rhs.absFilename() &&
215                 lhs.saveAbsPath() == rhs.saveAbsPath();
216 }
217
218
219 bool operator!=(DocFileName const & lhs, DocFileName const & rhs)
220 {
221         return !(lhs == rhs);
222 }
223
224 } // namespace support
225 } // namespace lyx