]> git.lyx.org Git - lyx.git/blob - src/BufferList.cpp
a650ba62dc32d7a7c67a89463dc983c59932f176
[lyx.git] / src / BufferList.cpp
1 /**
2  * \file BufferList.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "BufferList.h"
14
15 #include "Author.h"
16 #include "Buffer.h"
17 #include "BufferParams.h"
18 #include "Session.h"
19 #include "LyX.h"
20 #include "output_latex.h"
21 #include "ParagraphList.h"
22
23 #include "frontends/alert.h"
24
25 #include "support/debug.h"
26 #include "support/filetools.h"
27 #include "support/gettext.h"
28 #include "support/lstrings.h"
29 #include "support/Package.h"
30
31 #include <boost/bind.hpp>
32
33 #include <algorithm>
34 #include <functional>
35
36 using boost::bind;
37
38 using namespace std;
39
40 namespace lyx {
41
42 using support::addName;
43 using support::bformat;
44 using support::FileName;
45 using support::makeDisplayPath;
46 using support::onlyFilename;
47 using support::removeAutosaveFile;
48 using support::package;
49 using support::prefixIs;
50
51 namespace Alert = lyx::frontend::Alert;
52
53
54 BufferList::BufferList()
55 {}
56
57
58 bool BufferList::empty() const
59 {
60         return bstore.empty();
61 }
62
63
64 BufferList::iterator BufferList::begin()
65 {
66         return bstore.begin();
67 }
68
69
70 BufferList::const_iterator BufferList::begin() const
71 {
72         return bstore.begin();
73 }
74
75
76 BufferList::iterator BufferList::end()
77 {
78         return bstore.end();
79 }
80
81
82 BufferList::const_iterator BufferList::end() const
83 {
84         return bstore.end();
85 }
86
87
88 void BufferList::release(Buffer * buf)
89 {
90         BOOST_ASSERT(buf);
91         BufferStorage::iterator const it =
92                 find(bstore.begin(), bstore.end(), buf);
93         if (it != bstore.end()) {
94                 Buffer * tmp = (*it);
95                 BOOST_ASSERT(tmp);
96                 bstore.erase(it);
97                 delete tmp;
98         }
99 }
100
101
102 Buffer * BufferList::newBuffer(string const & s, bool const ronly)
103 {
104         auto_ptr<Buffer> tmpbuf(new Buffer(s, ronly));
105         tmpbuf->params().useClassDefaults();
106         LYXERR(Debug::INFO, "Assigning to buffer " << bstore.size());
107         bstore.push_back(tmpbuf.get());
108         return tmpbuf.release();
109 }
110
111
112 void BufferList::closeAll()
113 {
114         while (!bstore.empty())
115                 release(bstore.front());
116 }
117
118
119 vector<string> const BufferList::getFileNames() const
120 {
121         vector<string> nvec;
122         transform(bstore.begin(), bstore.end(),
123                   back_inserter(nvec),
124                   boost::bind(&Buffer::absFileName, _1));
125         return nvec;
126 }
127
128
129 Buffer * BufferList::first()
130 {
131         if (bstore.empty())
132                 return 0;
133         return bstore.front();
134 }
135
136
137 Buffer * BufferList::last()
138 {
139         if (bstore.empty())
140                 return 0;
141         return bstore.back();
142 }
143
144
145 Buffer * BufferList::getBuffer(unsigned int choice)
146 {
147         if (choice >= bstore.size())
148                 return 0;
149         return bstore[choice];
150 }
151
152
153 Buffer * BufferList::next(Buffer const * buf) const
154 {
155         BOOST_ASSERT(buf);
156
157         if (bstore.empty())
158                 return 0;
159         BufferStorage::const_iterator it = find(bstore.begin(),
160                                                 bstore.end(), buf);
161         BOOST_ASSERT(it != bstore.end());
162         ++it;
163         if (it == bstore.end())
164                 return bstore.front();
165         else
166                 return *it;
167 }
168
169
170 Buffer * BufferList::previous(Buffer const * buf) const
171 {
172         BOOST_ASSERT(buf);
173
174         if (bstore.empty())
175                 return 0;
176         BufferStorage::const_iterator it = find(bstore.begin(),
177                                                 bstore.end(), buf);
178         BOOST_ASSERT(it != bstore.end());
179         if (it == bstore.begin())
180                 return bstore.back();
181         else
182                 return *(it - 1);
183 }
184
185
186 void BufferList::updateIncludedTeXfiles(string const & masterTmpDir,
187                                         OutputParams const & runparams)
188 {
189         BufferStorage::iterator it = bstore.begin();
190         BufferStorage::iterator end = bstore.end();
191         for (; it != end; ++it) {
192                 if (!(*it)->isDepClean(masterTmpDir)) {
193                         string writefile = addName(masterTmpDir, (*it)->latexName());
194                         (*it)->makeLaTeXFile(FileName(writefile), masterTmpDir,
195                                              runparams, false);
196                         (*it)->markDepClean(masterTmpDir);
197                 }
198         }
199 }
200
201
202 void BufferList::emergencyWriteAll()
203 {
204         for_each(bstore.begin(), bstore.end(),
205                  bind(&BufferList::emergencyWrite, this, _1));
206 }
207
208
209 void BufferList::emergencyWrite(Buffer * buf)
210 {
211         // Use ::assert to avoid a loop, BOOST_ASSERT ends up calling ::assert
212         // compare with 0 to avoid pointer/interger comparison
213         // ::assert(buf != 0);
214         if (!buf)
215                 return;
216
217         // No need to save if the buffer has not changed.
218         if (buf->isClean())
219                 return;
220
221         string const doc = buf->isUnnamed()
222                 ? onlyFilename(buf->absFileName()) : buf->absFileName();
223
224         lyxerr << to_utf8(
225                 bformat(_("LyX: Attempting to save document %1$s"), from_utf8(doc)))
226                 << endl;
227
228         // We try to save three places:
229         // 1) Same place as document. Unless it is an unnamed doc.
230         if (!buf->isUnnamed()) {
231                 string s = buf->absFileName();
232                 s += ".emergency";
233                 lyxerr << "  " << s << endl;
234                 if (buf->writeFile(FileName(s))) {
235                         buf->markClean();
236                         lyxerr << to_utf8(_("  Save seems successful. Phew.")) << endl;
237                         return;
238                 } else {
239                         lyxerr << to_utf8(_("  Save failed! Trying...")) << endl;
240                 }
241         }
242
243         // 2) In HOME directory.
244         string s = addName(package().home_dir().absFilename(), buf->absFileName());
245         s += ".emergency";
246         lyxerr << ' ' << s << endl;
247         if (buf->writeFile(FileName(s))) {
248                 buf->markClean();
249                 lyxerr << to_utf8(_("  Save seems successful. Phew.")) << endl;
250                 return;
251         }
252
253         lyxerr << to_utf8(_("  Save failed! Trying...")) << endl;
254
255         // 3) In "/tmp" directory.
256         // MakeAbsPath to prepend the current
257         // drive letter on OS/2
258         s = addName(package().temp_dir().absFilename(), buf->absFileName());
259         s += ".emergency";
260         lyxerr << ' ' << s << endl;
261         if (buf->writeFile(FileName(s))) {
262                 buf->markClean();
263                 lyxerr << to_utf8(_("  Save seems successful. Phew.")) << endl;
264                 return;
265         }
266         lyxerr << to_utf8(_("  Save failed! Bummer. Document is lost.")) << endl;
267 }
268
269
270 bool BufferList::exists(string const & s) const
271 {
272         return find_if(bstore.begin(), bstore.end(),
273                        bind(equal_to<string>(),
274                             bind(&Buffer::absFileName, _1),
275                             s))
276                 != bstore.end();
277 }
278
279
280 bool BufferList::isLoaded(Buffer const * b) const
281 {
282         BOOST_ASSERT(b);
283         BufferStorage::const_iterator cit =
284                 find(bstore.begin(), bstore.end(), b);
285         return cit != bstore.end();
286 }
287
288
289 Buffer * BufferList::getBuffer(string const & s)
290 {
291         BufferStorage::iterator it =
292                 find_if(bstore.begin(), bstore.end(),
293                         bind(equal_to<string>(),
294                              bind(&Buffer::absFileName, _1),
295                              s));
296
297         return it != bstore.end() ? (*it) : 0;
298 }
299
300
301 Buffer * BufferList::getBufferFromTmp(string const & s)
302 {
303         BufferStorage::iterator it = bstore.begin();
304         BufferStorage::iterator end = bstore.end();
305         for (; it < end; ++it)
306                 if (prefixIs(s, (*it)->temppath()))
307                         return *it;
308         return 0;
309 }
310
311
312 void BufferList::setCurrentAuthor(docstring const & name, docstring const & email)
313 {
314         BufferStorage::iterator it = bstore.begin();
315         BufferStorage::iterator end = bstore.end();
316         for (; it != end; ++it)
317                 (*it)->params().authors().record(0, Author(name, email));
318 }
319
320
321 int BufferList::bufferNum(std::string const & name) const
322 {
323         vector<string> buffers = getFileNames();
324         vector<string>::const_iterator cit =
325                 std::find(buffers.begin(), buffers.end(), name);
326         if (cit == buffers.end())
327                 return 0;
328         return int(cit - buffers.begin());
329 }
330
331
332 } // namespace lyx