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"
22 #include "output_latex.h"
23 #include "ParagraphList.h"
25 #include "frontends/alert.h"
27 #include "support/filetools.h"
28 #include "support/Package.h"
30 #include <boost/bind.hpp>
45 using std::back_inserter;
51 using support::addName;
52 using support::bformat;
53 using support::FileName;
54 using support::makeDisplayPath;
55 using support::onlyFilename;
56 using support::removeAutosaveFile;
57 using support::package;
58 using support::prefixIs;
60 namespace Alert = lyx::frontend::Alert;
63 BufferList::BufferList()
67 bool BufferList::empty() const
69 return bstore.empty();
73 BufferList::iterator BufferList::begin()
75 return bstore.begin();
79 BufferList::const_iterator BufferList::begin() const
81 return bstore.begin();
85 BufferList::iterator BufferList::end()
91 BufferList::const_iterator BufferList::end() const
97 bool BufferList::quitWriteBuffer(Buffer * buf)
102 if (buf->isUnnamed())
103 file = from_utf8(onlyFilename(buf->fileName()));
105 file = makeDisplayPath(buf->fileName(), 30);
107 docstring const text =
108 bformat(_("The document %1$s has unsaved changes.\n\n"
109 "Do you want to save the document or discard the changes?"),
111 int const ret = Alert::prompt(_("Save changed document?"),
112 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
115 // FIXME: WriteAs can be asynch !
116 // but not right now...maybe we should remove that
120 if (buf->isUnnamed())
121 succeeded = buf->writeAs();
123 succeeded = buf->menuWrite();
127 } else if (ret == 1) {
128 // if we crash after this we could
129 // have no autosave file but I guess
130 // this is really inprobable (Jug)
131 if (buf->isUnnamed())
132 removeAutosaveFile(buf->fileName());
142 bool BufferList::quitWriteAll()
144 BufferStorage::iterator it = bstore.begin();
145 BufferStorage::iterator end = bstore.end();
146 for (; it != end; ++it) {
147 if ((*it)->isClean())
150 if (!quitWriteBuffer(*it))
153 // now, all buffers have been written sucessfully
154 // save file names to .lyx/session
156 for (; it != end; ++it) {
157 // if master/slave are both open, do not save slave since it
158 // will be automatically loaded when the master is loaded
159 if ((*it)->getMasterBuffer() == (*it))
160 LyX::ref().session().lastOpened().add(FileName((*it)->fileName()));
167 void BufferList::release(Buffer * buf)
170 BufferStorage::iterator const it =
171 find(bstore.begin(), bstore.end(), buf);
172 if (it != bstore.end()) {
173 Buffer * tmp = (*it);
181 Buffer * BufferList::newBuffer(string const & s, bool const ronly)
183 auto_ptr<Buffer> tmpbuf(new Buffer(s, ronly));
184 tmpbuf->params().useClassDefaults();
185 LYXERR(Debug::INFO) << "Assigning to buffer "
186 << bstore.size() << endl;
187 bstore.push_back(tmpbuf.get());
188 return tmpbuf.release();
192 void BufferList::closeAll()
194 while (!bstore.empty()) {
195 close(bstore.front(), false);
200 bool BufferList::close(Buffer * buf, bool const ask)
204 if (!ask || buf->isClean() || buf->paragraphs().empty()) {
210 if (buf->isUnnamed())
211 fname = from_utf8(onlyFilename(buf->fileName()));
213 fname = makeDisplayPath(buf->fileName(), 30);
215 docstring const text =
216 bformat(_("The document %1$s has unsaved changes.\n\n"
217 "Do you want to save the document or discard the changes?"),
219 int const ret = Alert::prompt(_("Save changed document?"),
220 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
223 if (buf->isUnnamed()) {
226 } else if (!buf->menuWrite())
231 removeAutosaveFile(buf->fileName());
238 vector<string> const BufferList::getFileNames() const
241 transform(bstore.begin(), bstore.end(),
243 boost::bind(&Buffer::fileName, _1));
248 Buffer * BufferList::first()
252 return bstore.front();
256 Buffer * BufferList::last()
260 return bstore.back();
264 Buffer * BufferList::getBuffer(unsigned int choice)
266 if (choice >= bstore.size())
268 return bstore[choice];
272 Buffer * BufferList::next(Buffer const * buf) const
278 BufferStorage::const_iterator it = find(bstore.begin(),
280 BOOST_ASSERT(it != bstore.end());
282 if (it == bstore.end())
283 return bstore.front();
289 Buffer * BufferList::previous(Buffer const * buf) const
295 BufferStorage::const_iterator it = find(bstore.begin(),
297 BOOST_ASSERT(it != bstore.end());
298 if (it == bstore.begin())
299 return bstore.back();
305 void BufferList::updateIncludedTeXfiles(string const & mastertmpdir,
306 OutputParams const & runparams)
308 BufferStorage::iterator it = bstore.begin();
309 BufferStorage::iterator end = bstore.end();
310 for (; it != end; ++it) {
311 if (!(*it)->isDepClean(mastertmpdir)) {
312 string writefile = addName(mastertmpdir, (*it)->getLatexName());
313 (*it)->makeLaTeXFile(FileName(writefile), mastertmpdir,
315 (*it)->markDepClean(mastertmpdir);
321 void BufferList::emergencyWriteAll()
323 for_each(bstore.begin(), bstore.end(),
324 bind(&BufferList::emergencyWrite, this, _1));
328 void BufferList::emergencyWrite(Buffer * buf)
330 // Use ::assert to avoid a loop, BOOST_ASSERT ends up calling ::assert
331 // compare with 0 to avoid pointer/interger comparison
332 // ::assert(buf != 0);
336 // No need to save if the buffer has not changed.
340 string const doc = buf->isUnnamed()
341 ? onlyFilename(buf->fileName()) : buf->fileName();
344 bformat(_("LyX: Attempting to save document %1$s"), from_utf8(doc)))
347 // We try to save three places:
348 // 1) Same place as document. Unless it is an unnamed doc.
349 if (!buf->isUnnamed()) {
350 string s = buf->fileName();
352 lyxerr << " " << s << endl;
353 if (buf->writeFile(FileName(s))) {
355 lyxerr << to_utf8(_(" Save seems successful. Phew.")) << endl;
358 lyxerr << to_utf8(_(" Save failed! Trying...")) << endl;
362 // 2) In HOME directory.
363 string s = addName(package().home_dir().absFilename(), buf->fileName());
365 lyxerr << ' ' << s << endl;
366 if (buf->writeFile(FileName(s))) {
368 lyxerr << to_utf8(_(" Save seems successful. Phew.")) << endl;
372 lyxerr << to_utf8(_(" Save failed! Trying...")) << endl;
374 // 3) In "/tmp" directory.
375 // MakeAbsPath to prepend the current
376 // drive letter on OS/2
377 s = addName(package().temp_dir().absFilename(), buf->fileName());
379 lyxerr << ' ' << s << endl;
380 if (buf->writeFile(FileName(s))) {
382 lyxerr << to_utf8(_(" Save seems successful. Phew.")) << endl;
385 lyxerr << to_utf8(_(" Save failed! Bummer. Document is lost.")) << endl;
389 bool BufferList::exists(string const & s) const
391 return find_if(bstore.begin(), bstore.end(),
392 bind(equal_to<string>(),
393 bind(&Buffer::fileName, _1),
399 bool BufferList::isLoaded(Buffer const * b) const
402 BufferStorage::const_iterator cit =
403 find(bstore.begin(), bstore.end(), b);
404 return cit != bstore.end();
408 Buffer * BufferList::getBuffer(string const & s)
410 BufferStorage::iterator it =
411 find_if(bstore.begin(), bstore.end(),
412 bind(equal_to<string>(),
413 bind(&Buffer::fileName, _1),
416 return it != bstore.end() ? (*it) : 0;
420 Buffer * BufferList::getBufferFromTmp(string const & s)
422 BufferStorage::iterator it = bstore.begin();
423 BufferStorage::iterator end = bstore.end();
424 for (; it < end; ++it)
425 if (prefixIs(s, (*it)->temppath()))
431 void BufferList::setCurrentAuthor(docstring const & name, docstring const & email)
433 BufferStorage::iterator it = bstore.begin();
434 BufferStorage::iterator end = bstore.end();
435 for (; it != end; ++it) {
436 (*it)->params().authors().record(0, Author(name, email));