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 "ParagraphList.h"
26 #include "frontends/alert.h"
28 #include "support/filetools.h"
29 #include "support/Package.h"
31 #include <boost/bind.hpp>
46 using std::back_inserter
;
52 using support::addName
;
53 using support::bformat
;
54 using support::FileName
;
55 using support::makeDisplayPath
;
56 using support::onlyFilename
;
57 using support::removeAutosaveFile
;
58 using support::package
;
59 using support::prefixIs
;
61 namespace Alert
= lyx::frontend::Alert
;
64 BufferList::BufferList()
68 bool BufferList::empty() const
70 return bstore
.empty();
74 BufferList::iterator
BufferList::begin()
76 return bstore
.begin();
80 BufferList::const_iterator
BufferList::begin() const
82 return bstore
.begin();
86 BufferList::iterator
BufferList::end()
92 BufferList::const_iterator
BufferList::end() const
98 bool BufferList::quitWriteBuffer(Buffer
* buf
)
103 if (buf
->isUnnamed())
104 file
= from_utf8(onlyFilename(buf
->fileName()));
106 file
= makeDisplayPath(buf
->fileName(), 30);
108 docstring
const text
=
109 bformat(_("The document %1$s has unsaved changes.\n\n"
110 "Do you want to save the document or discard the changes?"),
112 int const ret
= Alert::prompt(_("Save changed document?"),
113 text
, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
116 // FIXME: WriteAs can be asynch !
117 // but not right now...maybe we should remove that
121 if (buf
->isUnnamed())
122 succeeded
= writeAs(buf
);
124 succeeded
= menuWrite(buf
);
128 } else if (ret
== 1) {
129 // if we crash after this we could
130 // have no autosave file but I guess
131 // this is really inprobable (Jug)
132 if (buf
->isUnnamed())
133 removeAutosaveFile(buf
->fileName());
143 bool BufferList::quitWriteAll()
145 BufferStorage::iterator it
= bstore
.begin();
146 BufferStorage::iterator end
= bstore
.end();
147 for (; it
!= end
; ++it
) {
148 if ((*it
)->isClean())
151 if (!quitWriteBuffer(*it
))
154 // now, all buffers have been written sucessfully
155 // save file names to .lyx/session
157 for (; it
!= end
; ++it
) {
158 // if master/slave are both open, do not save slave since it
159 // will be automatically loaded when the master is loaded
160 if ((*it
)->getMasterBuffer() == (*it
))
161 LyX::ref().session().lastOpened().add(FileName((*it
)->fileName()));
168 void BufferList::release(Buffer
* buf
)
171 BufferStorage::iterator
const it
=
172 find(bstore
.begin(), bstore
.end(), buf
);
173 if (it
!= bstore
.end()) {
174 Buffer
* tmp
= (*it
);
182 Buffer
* BufferList::newBuffer(string
const & s
, bool const ronly
)
184 auto_ptr
<Buffer
> tmpbuf(new Buffer(s
, ronly
));
185 tmpbuf
->params().useClassDefaults();
186 LYXERR(Debug::INFO
) << "Assigning to buffer "
187 << bstore
.size() << endl
;
188 bstore
.push_back(tmpbuf
.get());
189 return tmpbuf
.release();
193 void BufferList::closeAll()
195 while (!bstore
.empty()) {
196 close(bstore
.front(), false);
201 bool BufferList::close(Buffer
* buf
, bool const ask
)
205 if (!ask
|| buf
->isClean() || buf
->paragraphs().empty()) {
211 if (buf
->isUnnamed())
212 fname
= from_utf8(onlyFilename(buf
->fileName()));
214 fname
= makeDisplayPath(buf
->fileName(), 30);
216 docstring
const text
=
217 bformat(_("The document %1$s has unsaved changes.\n\n"
218 "Do you want to save the document or discard the changes?"),
220 int const ret
= Alert::prompt(_("Save changed document?"),
221 text
, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
224 if (buf
->isUnnamed()) {
227 } else if (!menuWrite(buf
))
234 if (buf
->isUnnamed()) {
235 removeAutosaveFile(buf
->fileName());
243 vector
<string
> const BufferList::getFileNames() const
246 transform(bstore
.begin(), bstore
.end(),
248 boost::bind(&Buffer::fileName
, _1
));
253 Buffer
* BufferList::first()
257 return bstore
.front();
261 Buffer
* BufferList::last()
265 return bstore
.back();
269 Buffer
* BufferList::getBuffer(unsigned int const choice
)
271 if (choice
>= bstore
.size())
273 return bstore
[choice
];
277 Buffer
* BufferList::next(Buffer
const * buf
) const
283 BufferStorage::const_iterator it
= find(bstore
.begin(),
285 BOOST_ASSERT(it
!= bstore
.end());
287 if (it
== bstore
.end())
288 return bstore
.front();
294 Buffer
* BufferList::previous(Buffer
const * buf
) const
300 BufferStorage::const_iterator it
= find(bstore
.begin(),
302 BOOST_ASSERT(it
!= bstore
.end());
303 if (it
== bstore
.begin())
304 return bstore
.back();
310 void BufferList::updateIncludedTeXfiles(string
const & mastertmpdir
,
311 OutputParams
const & runparams
)
313 BufferStorage::iterator it
= bstore
.begin();
314 BufferStorage::iterator end
= bstore
.end();
315 for (; it
!= end
; ++it
) {
316 if (!(*it
)->isDepClean(mastertmpdir
)) {
317 string writefile
= addName(mastertmpdir
, (*it
)->getLatexName());
318 (*it
)->makeLaTeXFile(FileName(writefile
), mastertmpdir
,
320 (*it
)->markDepClean(mastertmpdir
);
326 void BufferList::emergencyWriteAll()
328 for_each(bstore
.begin(), bstore
.end(),
329 bind(&BufferList::emergencyWrite
, this, _1
));
333 void BufferList::emergencyWrite(Buffer
* buf
)
335 // Use ::assert to avoid a loop, BOOST_ASSERT ends up calling ::assert
336 // compare with 0 to avoid pointer/interger comparison
339 // No need to save if the buffer has not changed.
343 string
const doc
= buf
->isUnnamed()
344 ? onlyFilename(buf
->fileName()) : buf
->fileName();
347 bformat(_("LyX: Attempting to save document %1$s"), from_utf8(doc
)))
350 // We try to save three places:
351 // 1) Same place as document. Unless it is an unnamed doc.
352 if (!buf
->isUnnamed()) {
353 string s
= buf
->fileName();
355 lyxerr
<< " " << s
<< endl
;
356 if (buf
->writeFile(FileName(s
))) {
358 lyxerr
<< to_utf8(_(" Save seems successful. Phew.")) << endl
;
361 lyxerr
<< to_utf8(_(" Save failed! Trying...")) << endl
;
365 // 2) In HOME directory.
366 string s
= addName(package().home_dir().absFilename(), buf
->fileName());
368 lyxerr
<< ' ' << s
<< endl
;
369 if (buf
->writeFile(FileName(s
))) {
371 lyxerr
<< to_utf8(_(" Save seems successful. Phew.")) << endl
;
375 lyxerr
<< to_utf8(_(" Save failed! Trying...")) << endl
;
377 // 3) In "/tmp" directory.
378 // MakeAbsPath to prepend the current
379 // drive letter on OS/2
380 s
= addName(package().temp_dir().absFilename(), buf
->fileName());
382 lyxerr
<< ' ' << s
<< endl
;
383 if (buf
->writeFile(FileName(s
))) {
385 lyxerr
<< to_utf8(_(" Save seems successful. Phew.")) << endl
;
388 lyxerr
<< to_utf8(_(" Save failed! Bummer. Document is lost.")) << endl
;
392 bool BufferList::exists(string
const & s
) const
394 return find_if(bstore
.begin(), bstore
.end(),
395 bind(equal_to
<string
>(),
396 bind(&Buffer::fileName
, _1
),
402 bool BufferList::isLoaded(Buffer
const * b
) const
405 BufferStorage::const_iterator cit
=
406 find(bstore
.begin(), bstore
.end(), b
);
407 return cit
!= bstore
.end();
411 Buffer
* BufferList::getBuffer(string
const & s
)
413 BufferStorage::iterator it
=
414 find_if(bstore
.begin(), bstore
.end(),
415 bind(equal_to
<string
>(),
416 bind(&Buffer::fileName
, _1
),
419 return it
!= bstore
.end() ? (*it
) : 0;
423 Buffer
* BufferList::getBufferFromTmp(string
const & s
)
425 BufferStorage::iterator it
= bstore
.begin();
426 BufferStorage::iterator end
= bstore
.end();
427 for (; it
< end
; ++it
)
428 if (prefixIs(s
, (*it
)->temppath()))
434 void BufferList::setCurrentAuthor(docstring
const & name
, docstring
const & email
)
436 BufferStorage::iterator it
= bstore
.begin();
437 BufferStorage::iterator end
= bstore
.end();
438 for (; it
!= end
; ++it
) {
439 (*it
)->params().authors().record(0, Author(name
, email
));