3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
8 * Full author contact details are available in file CREDITS.
13 #include "BufferList.h"
17 #include "BufferParams.h"
20 #include "output_latex.h"
21 #include "ParagraphList.h"
23 #include "frontends/alert.h"
25 #include "support/ExceptionMessage.h"
26 #include "support/debug.h"
27 #include "support/FileName.h"
28 #include "support/FileNameList.h"
29 #include "support/filetools.h"
30 #include "support/gettext.h"
31 #include "support/lstrings.h"
32 #include "support/Package.h"
34 #include "support/lassert.h"
35 #include <boost/bind.hpp>
43 using namespace lyx::support;
47 namespace Alert = lyx::frontend::Alert;
50 BufferList::BufferList()
54 bool BufferList::empty() const
56 return bstore.empty();
60 BufferList::iterator BufferList::begin()
62 return bstore.begin();
66 BufferList::const_iterator BufferList::begin() const
68 return bstore.begin();
72 BufferList::iterator BufferList::end()
78 BufferList::const_iterator BufferList::end() const
84 void BufferList::release(Buffer * buf)
87 BufferStorage::iterator const it =
88 find(bstore.begin(), bstore.end(), buf);
89 if (it != bstore.end()) {
98 Buffer * BufferList::newBuffer(string const & s, bool const ronly)
100 auto_ptr<Buffer> tmpbuf;
102 tmpbuf.reset(new Buffer(s, ronly));
103 } catch (ExceptionMessage const & message) {
104 if (message.type_ == ErrorException) {
105 Alert::error(message.title_, message.details_);
107 } else if (message.type_ == WarningException) {
108 Alert::warning(message.title_, message.details_);
112 tmpbuf->params().useClassDefaults();
113 LYXERR(Debug::INFO, "Assigning to buffer " << bstore.size());
114 bstore.push_back(tmpbuf.get());
115 return tmpbuf.release();
119 void BufferList::closeAll()
121 while (!bstore.empty())
122 release(bstore.front());
126 FileNameList const & BufferList::fileNames() const
128 static FileNameList nvec;
130 transform(bstore.begin(), bstore.end(),
132 boost::bind(&Buffer::fileName, _1));
137 Buffer * BufferList::first()
141 return bstore.front();
145 Buffer * BufferList::last()
149 return bstore.back();
153 Buffer * BufferList::getBuffer(unsigned int choice)
155 if (choice >= bstore.size())
157 return bstore[choice];
161 Buffer * BufferList::next(Buffer const * buf) const
167 BufferStorage::const_iterator it = find(bstore.begin(),
169 LASSERT(it != bstore.end(), /**/);
171 Buffer * nextbuf = (it == bstore.end()) ? bstore.front() : *it;
172 if (nextbuf->fileName().extension() == "internal")
173 return next(nextbuf);
178 Buffer * BufferList::previous(Buffer const * buf) const
184 BufferStorage::const_iterator it = find(bstore.begin(),
186 LASSERT(it != bstore.end(), /**/);
188 Buffer * previousbuf = (it == bstore.begin()) ? bstore.back() : *(it - 1);
189 if (previousbuf->fileName().extension() == "internal")
190 return previous(previousbuf);
195 void BufferList::updateIncludedTeXfiles(string const & masterTmpDir,
196 OutputParams const & runparams)
198 BufferStorage::iterator it = bstore.begin();
199 BufferStorage::iterator end = bstore.end();
200 for (; it != end; ++it) {
201 if (!(*it)->isDepClean(masterTmpDir)) {
202 string writefile = addName(masterTmpDir, (*it)->latexName());
203 (*it)->makeLaTeXFile(FileName(writefile), masterTmpDir,
205 (*it)->markDepClean(masterTmpDir);
211 void BufferList::emergencyWriteAll()
213 for_each(bstore.begin(), bstore.end(),
214 bind(&BufferList::emergencyWrite, this, _1));
218 docstring BufferList::emergencyWrite(Buffer * buf)
220 // Use ::assert to avoid a loop, BOOST_ASSERT ends up calling ::assert
221 // compare with 0 to avoid pointer/interger comparison
222 // ::assert(buf != 0);
224 return _("No file open!");
226 // No need to save if the buffer has not changed.
230 string const doc = buf->isUnnamed()
231 ? onlyFilename(buf->absFileName()) : buf->absFileName();
233 docstring user_message = bformat(
234 _("LyX: Attempting to save document %1$s\n"), from_utf8(doc));
236 // We try to save three places:
237 // 1) Same place as document. Unless it is an unnamed doc.
238 if (!buf->isUnnamed()) {
239 string s = buf->absFileName();
241 lyxerr << " " << s << endl;
242 if (buf->writeFile(FileName(s))) {
244 user_message += _(" Save seems successful. Phew.\n");
247 user_message += _(" Save failed! Trying...\n");
251 // 2) In HOME directory.
252 string s = addName(package().home_dir().absFilename(), buf->absFileName());
254 lyxerr << ' ' << s << endl;
255 if (buf->writeFile(FileName(s))) {
257 user_message += _(" Save seems successful. Phew.\n");
261 user_message += _(" Save failed! Trying...\n");
263 // 3) In "/tmp" directory.
264 // MakeAbsPath to prepend the current
265 // drive letter on OS/2
266 s = addName(package().temp_dir().absFilename(), buf->absFileName());
268 lyxerr << ' ' << s << endl;
269 if (buf->writeFile(FileName(s))) {
271 user_message += _(" Save seems successful. Phew.\n");
275 user_message += _(" Save failed! Bummer. Document is lost.");
280 bool BufferList::exists(FileName const & fname) const
282 return getBuffer(fname) != 0;
286 bool BufferList::isLoaded(Buffer const * b) const
289 BufferStorage::const_iterator cit =
290 find(bstore.begin(), bstore.end(), b);
291 return cit != bstore.end();
295 Buffer * BufferList::getBuffer(support::FileName const & fname) const
297 BufferStorage::const_iterator it = find_if(bstore.begin(), bstore.end(),
298 bind(equal_to<FileName>(), bind(&Buffer::fileName, _1), fname));
299 return it != bstore.end() ? (*it) : 0;
303 Buffer * BufferList::getBufferFromTmp(string const & s)
305 BufferStorage::iterator it = bstore.begin();
306 BufferStorage::iterator end = bstore.end();
307 for (; it < end; ++it)
308 if (prefixIs(s, (*it)->temppath()))
314 void BufferList::setCurrentAuthor(docstring const & name, docstring const & email)
316 BufferStorage::iterator it = bstore.begin();
317 BufferStorage::iterator end = bstore.end();
318 for (; it != end; ++it)
319 (*it)->params().authors().record(0, Author(name, email));
323 int BufferList::bufferNum(FileName const & fname) const
325 FileNameList const & buffers = fileNames();
326 FileNameList::const_iterator cit =
327 find(buffers.begin(), buffers.end(), fname);
328 if (cit == buffers.end())
330 return int(cit - buffers.begin());
334 bool BufferList::releaseChild(Buffer * parent, Buffer * child)
336 LASSERT(parent, return false);
337 LASSERT(child, return false);
338 LASSERT(parent->isChild(child), return false);
340 // Child document has a different parent, don't close it.
341 if (child->parent() != parent)
344 BufferStorage::iterator it = bstore.begin();
345 BufferStorage::iterator end = bstore.end();
346 for (; it != end; ++it) {
348 if (buf != parent && buf->isChild(child)) {