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"
41 using namespace lyx::support;
45 namespace Alert = lyx::frontend::Alert;
48 BufferList::BufferList()
52 BufferList::~BufferList()
54 for (Buffer * buf : binternal)
59 bool BufferList::empty() const
61 return bstore.empty();
65 BufferList::iterator BufferList::begin()
67 return bstore.begin();
71 BufferList::const_iterator BufferList::begin() const
73 return bstore.begin();
77 BufferList::iterator BufferList::end()
83 BufferList::const_iterator BufferList::end() const
89 void BufferList::release(Buffer * buf)
91 // We may leak here, but we probably do not need to
94 BufferStorage::iterator const it =
95 find(bstore.begin(), bstore.end(), buf);
96 if (it != bstore.end()) {
97 Buffer const * parent = buf->parent();
100 LASSERT(tmp, return);
103 // If this was a child, update the parent's buffer
104 // to avoid crashes due to dangling pointers (bug 9979)
105 parent->updateBuffer();
110 Buffer * BufferList::newInternalBuffer(string const & s)
112 Buffer * const buf = createNewBuffer(s);
114 buf->setInternal(true);
115 binternal.push_back(buf);
121 Buffer * BufferList::newBuffer(string const & s)
123 Buffer * const buf = createNewBuffer(s);
125 LYXERR(Debug::INFO, "Assigning to buffer " << bstore.size());
126 bstore.push_back(buf);
132 Buffer * BufferList::createNewBuffer(string const & s)
134 unique_ptr<Buffer> tmpbuf;
136 tmpbuf = make_unique<Buffer>(s);
137 } catch (ExceptionMessage const & message) {
138 if (message.type_ == ErrorException) {
139 Alert::error(message.title_, message.details_);
141 } else if (message.type_ == WarningException) {
142 Alert::warning(message.title_, message.details_);
146 tmpbuf->params().useClassDefaults();
147 return tmpbuf.release();
151 void BufferList::closeAll()
153 while (!bstore.empty())
154 release(bstore.front());
158 FileNameList BufferList::fileNames() const
161 for (Buffer const * buf : bstore)
162 nvec.push_back(buf->fileName());
167 Buffer * BufferList::first()
171 return bstore.front();
175 Buffer * BufferList::last()
179 return bstore.back();
183 Buffer * BufferList::getBuffer(unsigned int choice)
185 if (choice >= bstore.size())
187 return bstore[choice];
191 Buffer * BufferList::next(Buffer const * buf) const
193 // Something is wrong, but we can probably survive it.
194 LASSERT(buf, return 0);
198 BufferStorage::const_iterator it =
199 find(bstore.begin(), bstore.end(), buf);
200 LASSERT(it != bstore.end(), return 0);
202 Buffer * nextbuf = (it == bstore.end()) ? bstore.front() : *it;
207 Buffer * BufferList::previous(Buffer const * buf) const
209 // Something is wrong, but we can probably survive it.
210 LASSERT(buf, return 0);
214 BufferStorage::const_iterator it =
215 find(bstore.begin(), bstore.end(), buf);
216 LASSERT(it != bstore.end(), return 0);
218 Buffer * previousbuf = (it == bstore.begin()) ? bstore.back() : *(it - 1);
223 void BufferList::updateIncludedTeXfiles(string const & masterTmpDir,
224 OutputParams const & runparams_in)
226 OutputParams runparams = runparams_in;
227 runparams.is_child = true;
228 for (Buffer * buf : bstore) {
229 if (!buf->isDepClean(masterTmpDir)) {
230 string writefile = addName(masterTmpDir, buf->latexName());
231 buf->makeLaTeXFile(FileName(writefile), masterTmpDir,
232 runparams, Buffer::OnlyBody);
233 buf->markDepClean(masterTmpDir);
239 void BufferList::emergencyWriteAll()
241 for (Buffer * buf : bstore)
242 buf->emergencyWrite();
246 void BufferList::invalidateConverterCache() const
248 for (Buffer const * buf : bstore)
249 buf->params().invalidateConverterCache();
253 bool BufferList::exists(FileName const & fname) const
255 return getBuffer(fname) != 0;
259 bool BufferList::isLoaded(Buffer const * b) const
263 BufferStorage::const_iterator cit =
264 find(bstore.begin(), bstore.end(), b);
265 return cit != bstore.end();
269 bool BufferList::isInternal(Buffer const * b) const
273 BufferStorage::const_iterator cit =
274 find(binternal.begin(), binternal.end(), b);
275 return cit != binternal.end();
279 bool BufferList::isOthersChild(Buffer * parent, Buffer * child) const
281 LASSERT(parent, return false);
282 LASSERT(child, return false);
283 LASSERT(parent->isChild(child), return false);
285 // Does child document have a different parent?
286 Buffer const * parent_ = child->parent();
287 if (parent_ && parent_ != parent)
290 for(Buffer const * buf : bstore)
291 if (buf != parent && buf->isChild(child))
297 Buffer * BufferList::getBuffer(support::FileName const & fname, bool internal) const
299 // 1) cheap test, using string comparison of file names
300 for (Buffer * b : bstore)
301 if (b->fileName() == fname)
303 // 2) possibly expensive test, using equivalence test of file names
304 for (Buffer * b : bstore)
305 if (equivalent(b->fileName(), fname))
308 // 1) cheap test, using string comparison of file names
309 for (Buffer * b : binternal)
310 if (b->fileName() == fname)
312 // 2) possibly expensive test, using equivalence test of file names
313 for (Buffer * b : binternal)
314 if (equivalent(b->fileName(), fname))
321 Buffer * BufferList::getBufferFromTmp(string const & s)
323 for (Buffer * buf : bstore) {
324 if (prefixIs(s, buf->temppath())) {
325 // check whether the filename matches the master
326 string const master_name = buf->latexName();
327 if (suffixIs(s, master_name))
329 // if not, try with the children
330 for (Buffer * child : buf->getDescendents()) {
331 string const mangled_child_name = DocFileName(
332 changeExtension(child->absFileName(),
333 ".tex")).mangledFileName();
334 if (suffixIs(s, mangled_child_name))
343 void BufferList::recordCurrentAuthor(Author const & author)
345 for (Buffer * buf : bstore)
346 buf->params().authors().recordCurrentAuthor(author);
350 void BufferList::updatePreviews()
352 for (Buffer * buf : bstore)
353 buf->updatePreviews();
357 int BufferList::bufferNum(FileName const & fname) const
359 FileNameList const buffers(fileNames());
360 FileNameList::const_iterator cit =
361 find(buffers.begin(), buffers.end(), fname);
362 if (cit == buffers.end())
364 return int(cit - buffers.begin());
368 void BufferList::changed(bool update_metrics) const
370 for (Buffer const * buf : bstore)
371 buf->changed(update_metrics);
372 for (Buffer const * buf : binternal)
373 buf->changed(update_metrics);