]> git.lyx.org Git - lyx.git/blob - src/support/filename.C
layout file converter for layout files in old format
[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
18 #include <boost/assert.hpp>
19
20 #include <map>
21 #include <sstream>
22
23
24 using std::map;
25 using std::string;
26
27
28 namespace lyx {
29 namespace support {
30
31
32 FileName::FileName()
33         : save_abs_path_(true)
34 {}
35
36
37 FileName::FileName(string const & abs_filename, bool save_abs)
38         : name_(abs_filename), save_abs_path_(save_abs)
39 {
40         BOOST_ASSERT(AbsolutePath(name_));
41 }
42
43
44 void FileName::set(string const & name, string const & buffer_path)
45 {
46         save_abs_path_ = AbsolutePath(name);
47         name_ = save_abs_path_ ? name : MakeAbsPath(name, buffer_path);
48 }
49
50
51 void FileName::erase()
52 {
53         name_.erase();
54 }
55
56
57 string const FileName::relFilename(string const & path) const
58 {
59         return MakeRelPath(name_, path);
60 }
61
62
63 string const FileName::outputFilename(string const & path) const
64 {
65         return save_abs_path_ ? name_ : MakeRelPath(name_, path);
66 }
67
68
69 string const FileName::mangledFilename(std::string const & dir) const
70 {
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())
77                 return (*it).second;
78
79         // Now the real work
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_));
93
94         // Prepend a counter to the filename. This is necessary to make
95         // the mangled name unique.
96         static int counter = 0;
97         std::ostringstream s;
98         s << counter++ << mname;
99         mname = s.str();
100
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;
112
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
115                 // of the counter.
116                 if (mname.size() > max_length) {
117                         int const half = (int(max_length) / 2) - 2;
118                         if (half > 0) {
119                                 mname = mname.substr(0, half) + "___" +
120                                         mname.substr(mname.size() - half);
121                         }
122                 }
123         }
124
125         mangledNames[name_] = mname;
126         return mname;
127 }
128
129
130 bool FileName::isZipped() const
131 {
132         return zippedFile(name_);
133 }
134
135
136 string const FileName::unzippedFilename() const
137 {
138         return unzippedFileName(name_);
139 }
140
141
142 bool operator==(FileName const & lhs, FileName const & rhs)
143 {
144         return lhs.absFilename() == rhs.absFilename() &&
145                 lhs.saveAbsPath() == rhs.saveAbsPath();
146 }
147
148
149 bool operator!=(FileName const & lhs, FileName const & rhs)
150 {
151         return !(lhs == rhs);
152 }
153
154 } // namespace support
155 } // namespace lyx