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::makeAbsPath;
43 using support::makeDisplayPath;
44 using support::onlyFilename;
45 using support::removeAutosaveFile;
46 using support::package;
47 using support::prefixIs;
59 using std::back_inserter;
62 namespace Alert = lyx::frontend::Alert;
65 BufferList::BufferList()
69 bool BufferList::empty() const
71 return bstore.empty();
75 BufferList::iterator BufferList::begin()
77 return bstore.begin();
81 BufferList::const_iterator BufferList::begin() const
83 return bstore.begin();
87 BufferList::iterator BufferList::end()
93 BufferList::const_iterator BufferList::end() const
99 bool BufferList::quitWriteBuffer(Buffer * buf)
104 if (buf->isUnnamed())
105 file = from_utf8(onlyFilename(buf->fileName()));
107 file = makeDisplayPath(buf->fileName(), 30);
109 docstring const text =
110 bformat(_("The document %1$s has unsaved changes.\n\n"
111 "Do you want to save the document or discard the changes?"),
113 int const ret = Alert::prompt(_("Save changed document?"),
114 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
117 // FIXME: WriteAs can be asynch !
118 // but not right now...maybe we should remove that
122 if (buf->isUnnamed())
123 succeeded = writeAs(buf);
125 succeeded = menuWrite(buf);
129 } else if (ret == 1) {
130 // if we crash after this we could
131 // have no autosave file but I guess
132 // this is really inprobable (Jug)
133 if (buf->isUnnamed())
134 removeAutosaveFile(buf->fileName());
144 bool BufferList::quitWriteAll()
146 BufferStorage::iterator it = bstore.begin();
147 BufferStorage::iterator end = bstore.end();
148 for (; it != end; ++it) {
149 if ((*it)->isClean())
152 if (!quitWriteBuffer(*it))
155 // now, all buffers have been written sucessfully
156 // save file names to .lyx/session
158 for (; it != end; ++it) {
159 // if master/slave are both open, do not save slave since it
160 // will be automatically loaded when the master is loaded
161 if ((*it)->getMasterBuffer() == (*it))
162 LyX::ref().session().lastOpened().add((*it)->fileName());
169 void BufferList::release(Buffer * buf)
172 BufferStorage::iterator const it =
173 find(bstore.begin(), bstore.end(), buf);
174 if (it != bstore.end()) {
175 Buffer * tmp = (*it);
183 Buffer * BufferList::newBuffer(string const & s, bool const ronly)
185 auto_ptr<Buffer> tmpbuf(new Buffer(s, ronly));
186 tmpbuf->params().useClassDefaults();
187 lyxerr[Debug::INFO] << "Assigning to buffer "
188 << bstore.size() << endl;
189 bstore.push_back(tmpbuf.get());
190 return tmpbuf.release();
194 void BufferList::closeAll()
196 while (!bstore.empty()) {
197 close(bstore.front(), false);
202 bool BufferList::close(Buffer * buf, bool const ask)
206 if (!ask || buf->isClean() || buf->paragraphs().empty()) {
212 if (buf->isUnnamed())
213 fname = from_utf8(onlyFilename(buf->fileName()));
215 fname = makeDisplayPath(buf->fileName(), 30);
217 docstring const text =
218 bformat(_("The document %1$s has unsaved changes.\n\n"
219 "Do you want to save the document or discard the changes?"),
221 int const ret = Alert::prompt(_("Save changed document?"),
222 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
225 if (buf->isUnnamed()) {
228 } else if (!menuWrite(buf))
235 if (buf->isUnnamed()) {
236 removeAutosaveFile(buf->fileName());
244 vector<string> const BufferList::getFileNames() const
247 transform(bstore.begin(), bstore.end(),
249 boost::bind(&Buffer::fileName, _1));
254 Buffer * BufferList::first()
258 return bstore.front();
262 Buffer * BufferList::last()
266 return bstore.back();
270 Buffer * BufferList::getBuffer(unsigned int const choice)
272 if (choice >= bstore.size())
274 return bstore[choice];
278 Buffer * BufferList::next(Buffer const * buf) const
284 BufferStorage::const_iterator it = find(bstore.begin(),
286 BOOST_ASSERT(it != bstore.end());
288 if (it == bstore.end())
289 return bstore.front();
295 Buffer * BufferList::previous(Buffer const * buf) const
301 BufferStorage::const_iterator it = find(bstore.begin(),
303 BOOST_ASSERT(it != bstore.end());
304 if (it == bstore.begin())
305 return bstore.back();
311 void BufferList::updateIncludedTeXfiles(string const & mastertmpdir,
312 OutputParams const & runparams)
314 BufferStorage::iterator it = bstore.begin();
315 BufferStorage::iterator end = bstore.end();
316 for (; it != end; ++it) {
317 if (!(*it)->isDepClean(mastertmpdir)) {
318 string writefile = mastertmpdir;
320 writefile += (*it)->getLatexName();
321 (*it)->makeLaTeXFile(writefile, mastertmpdir,
323 (*it)->markDepClean(mastertmpdir);
329 void BufferList::emergencyWriteAll()
331 for_each(bstore.begin(), bstore.end(),
332 bind(&BufferList::emergencyWrite, this, _1));
336 void BufferList::emergencyWrite(Buffer * buf)
338 // Use ::assert to avoid a loop, BOOST_ASSERT ends up calling ::assert
339 // compare with 0 to avoid pointer/interger comparison
342 // No need to save if the buffer has not changed.
346 string const doc = buf->isUnnamed()
347 ? onlyFilename(buf->fileName()) : buf->fileName();
350 bformat(_("LyX: Attempting to save document %1$s"), from_utf8(doc)))
353 // We try to save three places:
354 // 1) Same place as document. Unless it is an unnamed doc.
355 if (!buf->isUnnamed()) {
356 string s = buf->fileName();
358 lyxerr << " " << s << endl;
359 if (buf->writeFile(s)) {
361 lyxerr << to_utf8(_(" Save seems successful. Phew.")) << endl;
364 lyxerr << to_utf8(_(" Save failed! Trying...")) << endl;
368 // 2) In HOME directory.
369 string s = addName(package().home_dir(), buf->fileName());
371 lyxerr << ' ' << s << endl;
372 if (buf->writeFile(s)) {
374 lyxerr << to_utf8(_(" Save seems successful. Phew.")) << endl;
378 lyxerr << to_utf8(_(" Save failed! Trying...")) << endl;
380 // 3) In "/tmp" directory.
381 // MakeAbsPath to prepend the current
382 // drive letter on OS/2
383 s = addName(package().temp_dir(), buf->fileName());
385 lyxerr << ' ' << s << endl;
386 if (buf->writeFile(s)) {
388 lyxerr << to_utf8(_(" Save seems successful. Phew.")) << endl;
391 lyxerr << to_utf8(_(" Save failed! Bummer. Document is lost.")) << endl;
395 bool BufferList::exists(string const & s) const
397 return find_if(bstore.begin(), bstore.end(),
398 bind(equal_to<string>(),
399 bind(&Buffer::fileName, _1),
405 bool BufferList::isLoaded(Buffer const * b) const
408 BufferStorage::const_iterator cit =
409 find(bstore.begin(), bstore.end(), b);
410 return cit != bstore.end();
414 Buffer * BufferList::getBuffer(string const & s)
416 BufferStorage::iterator it =
417 find_if(bstore.begin(), bstore.end(),
418 bind(equal_to<string>(),
419 bind(&Buffer::fileName, _1),
422 return it != bstore.end() ? (*it) : 0;
426 Buffer * BufferList::getBufferFromTmp(string const & s)
428 BufferStorage::iterator it = bstore.begin();
429 BufferStorage::iterator end = bstore.end();
430 for (; it < end; ++it)
431 if (prefixIs(s, (*it)->temppath()))
437 void BufferList::setCurrentAuthor(string const & name, string const & email)
439 BufferStorage::iterator it = bstore.begin();
440 BufferStorage::iterator end = bstore.end();
441 for (; it != end; ++it) {
442 (*it)->params().authors().record(0, Author(name, email));