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"
23 #include "output_latex.h"
24 #include "paragraph.h"
25 #include "ParagraphList.h"
27 #include "frontends/Alert.h"
29 #include "support/filetools.h"
30 #include "support/package.h"
32 #include <boost/bind.hpp>
40 using support::addName;
41 using support::bformat;
42 using support::FileName;
43 using support::makeAbsPath;
44 using support::makeDisplayPath;
45 using support::onlyFilename;
46 using support::removeAutosaveFile;
47 using support::package;
48 using support::prefixIs;
60 using std::back_inserter;
63 namespace Alert = lyx::frontend::Alert;
66 BufferList::BufferList()
70 bool BufferList::empty() const
72 return bstore.empty();
76 BufferList::iterator BufferList::begin()
78 return bstore.begin();
82 BufferList::const_iterator BufferList::begin() const
84 return bstore.begin();
88 BufferList::iterator BufferList::end()
94 BufferList::const_iterator BufferList::end() const
100 bool BufferList::quitWriteBuffer(Buffer * buf)
105 if (buf->isUnnamed())
106 file = from_utf8(onlyFilename(buf->fileName()));
108 file = makeDisplayPath(buf->fileName(), 30);
110 docstring const text =
111 bformat(_("The document %1$s has unsaved changes.\n\n"
112 "Do you want to save the document or discard the changes?"),
114 int const ret = Alert::prompt(_("Save changed document?"),
115 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
118 // FIXME: WriteAs can be asynch !
119 // but not right now...maybe we should remove that
123 if (buf->isUnnamed())
124 succeeded = writeAs(buf);
126 succeeded = menuWrite(buf);
130 } else if (ret == 1) {
131 // if we crash after this we could
132 // have no autosave file but I guess
133 // this is really inprobable (Jug)
134 if (buf->isUnnamed())
135 removeAutosaveFile(buf->fileName());
145 bool BufferList::quitWriteAll()
147 BufferStorage::iterator it = bstore.begin();
148 BufferStorage::iterator end = bstore.end();
149 for (; it != end; ++it) {
150 if ((*it)->isClean())
153 if (!quitWriteBuffer(*it))
156 // now, all buffers have been written sucessfully
157 // save file names to .lyx/session
159 for (; it != end; ++it) {
160 // if master/slave are both open, do not save slave since it
161 // will be automatically loaded when the master is loaded
162 if ((*it)->getMasterBuffer() == (*it))
163 LyX::ref().session().lastOpened().add(FileName((*it)->fileName()));
170 void BufferList::release(Buffer * buf)
173 BufferStorage::iterator const it =
174 find(bstore.begin(), bstore.end(), buf);
175 if (it != bstore.end()) {
176 Buffer * tmp = (*it);
184 Buffer * BufferList::newBuffer(string const & s, bool const ronly)
186 auto_ptr<Buffer> tmpbuf(new Buffer(s, ronly));
187 tmpbuf->params().useClassDefaults();
188 lyxerr[Debug::INFO] << "Assigning to buffer "
189 << bstore.size() << endl;
190 bstore.push_back(tmpbuf.get());
191 return tmpbuf.release();
195 void BufferList::closeAll()
197 while (!bstore.empty()) {
198 close(bstore.front(), false);
203 bool BufferList::close(Buffer * buf, bool const ask)
207 if (!ask || buf->isClean() || buf->paragraphs().empty()) {
213 if (buf->isUnnamed())
214 fname = from_utf8(onlyFilename(buf->fileName()));
216 fname = makeDisplayPath(buf->fileName(), 30);
218 docstring const text =
219 bformat(_("The document %1$s has unsaved changes.\n\n"
220 "Do you want to save the document or discard the changes?"),
222 int const ret = Alert::prompt(_("Save changed document?"),
223 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
226 if (buf->isUnnamed()) {
229 } else if (!menuWrite(buf))
236 if (buf->isUnnamed()) {
237 removeAutosaveFile(buf->fileName());
245 vector<string> const BufferList::getFileNames() const
248 transform(bstore.begin(), bstore.end(),
250 boost::bind(&Buffer::fileName, _1));
255 Buffer * BufferList::first()
259 return bstore.front();
263 Buffer * BufferList::last()
267 return bstore.back();
271 Buffer * BufferList::getBuffer(unsigned int const choice)
273 if (choice >= bstore.size())
275 return bstore[choice];
279 Buffer * BufferList::next(Buffer const * buf) const
285 BufferStorage::const_iterator it = find(bstore.begin(),
287 BOOST_ASSERT(it != bstore.end());
289 if (it == bstore.end())
290 return bstore.front();
296 Buffer * BufferList::previous(Buffer const * buf) const
302 BufferStorage::const_iterator it = find(bstore.begin(),
304 BOOST_ASSERT(it != bstore.end());
305 if (it == bstore.begin())
306 return bstore.back();
312 void BufferList::updateIncludedTeXfiles(string const & mastertmpdir,
313 OutputParams const & runparams)
315 BufferStorage::iterator it = bstore.begin();
316 BufferStorage::iterator end = bstore.end();
317 for (; it != end; ++it) {
318 if (!(*it)->isDepClean(mastertmpdir)) {
319 string writefile = mastertmpdir;
321 writefile += (*it)->getLatexName();
322 (*it)->makeLaTeXFile(FileName(writefile), mastertmpdir,
324 (*it)->markDepClean(mastertmpdir);
330 void BufferList::emergencyWriteAll()
332 for_each(bstore.begin(), bstore.end(),
333 bind(&BufferList::emergencyWrite, this, _1));
337 void BufferList::emergencyWrite(Buffer * buf)
339 // Use ::assert to avoid a loop, BOOST_ASSERT ends up calling ::assert
340 // compare with 0 to avoid pointer/interger comparison
343 // No need to save if the buffer has not changed.
347 string const doc = buf->isUnnamed()
348 ? onlyFilename(buf->fileName()) : buf->fileName();
351 bformat(_("LyX: Attempting to save document %1$s"), from_utf8(doc)))
354 // We try to save three places:
355 // 1) Same place as document. Unless it is an unnamed doc.
356 if (!buf->isUnnamed()) {
357 string s = buf->fileName();
359 lyxerr << " " << s << endl;
360 if (buf->writeFile(FileName(s))) {
362 lyxerr << to_utf8(_(" Save seems successful. Phew.")) << endl;
365 lyxerr << to_utf8(_(" Save failed! Trying...")) << endl;
369 // 2) In HOME directory.
370 string s = addName(package().home_dir(), buf->fileName());
372 lyxerr << ' ' << s << endl;
373 if (buf->writeFile(FileName(s))) {
375 lyxerr << to_utf8(_(" Save seems successful. Phew.")) << endl;
379 lyxerr << to_utf8(_(" Save failed! Trying...")) << endl;
381 // 3) In "/tmp" directory.
382 // MakeAbsPath to prepend the current
383 // drive letter on OS/2
384 s = addName(package().temp_dir(), buf->fileName());
386 lyxerr << ' ' << s << endl;
387 if (buf->writeFile(FileName(s))) {
389 lyxerr << to_utf8(_(" Save seems successful. Phew.")) << endl;
392 lyxerr << to_utf8(_(" Save failed! Bummer. Document is lost.")) << endl;
396 bool BufferList::exists(string const & s) const
398 return find_if(bstore.begin(), bstore.end(),
399 bind(equal_to<string>(),
400 bind(&Buffer::fileName, _1),
406 bool BufferList::isLoaded(Buffer const * b) const
409 BufferStorage::const_iterator cit =
410 find(bstore.begin(), bstore.end(), b);
411 return cit != bstore.end();
415 Buffer * BufferList::getBuffer(string const & s)
417 BufferStorage::iterator it =
418 find_if(bstore.begin(), bstore.end(),
419 bind(equal_to<string>(),
420 bind(&Buffer::fileName, _1),
423 return it != bstore.end() ? (*it) : 0;
427 Buffer * BufferList::getBufferFromTmp(string const & s)
429 BufferStorage::iterator it = bstore.begin();
430 BufferStorage::iterator end = bstore.end();
431 for (; it < end; ++it)
432 if (prefixIs(s, (*it)->temppath()))
438 void BufferList::setCurrentAuthor(string const & name, string const & email)
440 BufferStorage::iterator it = bstore.begin();
441 BufferStorage::iterator end = bstore.end();
442 for (; it != end; ++it) {
443 (*it)->params().authors().record(0, Author(name, email));