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"
19 #include "frontends/alert.h"
21 #include "support/ExceptionMessage.h"
22 #include "support/debug.h"
23 #include "support/FileName.h"
24 #include "support/FileNameList.h"
25 #include "support/filetools.h"
26 #include "support/lstrings.h"
28 #include "support/lassert.h"
35 using namespace lyx::support;
39 namespace Alert = lyx::frontend::Alert;
42 BufferList::BufferList()
46 BufferList::~BufferList()
48 for (Buffer * buf : binternal)
53 bool BufferList::empty() const
55 return bstore.empty();
59 BufferList::iterator BufferList::begin()
61 return bstore.begin();
65 BufferList::const_iterator BufferList::begin() const
67 return bstore.begin();
71 BufferList::iterator BufferList::end()
77 BufferList::const_iterator BufferList::end() const
83 void BufferList::release(Buffer * buf)
85 // We may leak here, but we probably do not need to
88 BufferStorage::iterator const it =
89 find(bstore.begin(), bstore.end(), buf);
90 if (it != bstore.end()) {
91 Buffer const * parent = buf->parent();
97 // If this was a child, update the parent's buffer
98 // to avoid crashes due to dangling pointers (bug 9979)
99 parent->updateBuffer();
104 Buffer * BufferList::newInternalBuffer(string const & s)
106 Buffer * const buf = createNewBuffer(s);
108 buf->setInternal(true);
109 binternal.push_back(buf);
115 Buffer * BufferList::newBuffer(string const & s)
117 Buffer * const buf = createNewBuffer(s);
119 LYXERR(Debug::INFO, "Assigning to buffer " << bstore.size());
120 bstore.push_back(buf);
126 Buffer * BufferList::createNewBuffer(string const & s)
128 unique_ptr<Buffer> tmpbuf;
130 tmpbuf = make_unique<Buffer>(s);
131 } catch (ExceptionMessage const & message) {
132 if (message.type_ == ErrorException) {
133 Alert::error(message.title_, message.details_);
135 } else if (message.type_ == WarningException) {
136 Alert::warning(message.title_, message.details_);
140 tmpbuf->params().useClassDefaults();
141 return tmpbuf.release();
145 void BufferList::closeAll()
147 while (!bstore.empty())
148 release(bstore.front());
152 FileNameList BufferList::fileNames() const
155 for (Buffer const * buf : bstore)
156 nvec.push_back(buf->fileName());
161 Buffer * BufferList::first()
165 return bstore.front();
169 Buffer * BufferList::last()
173 return bstore.back();
177 Buffer * BufferList::getBuffer(unsigned int choice)
179 if (choice >= bstore.size())
181 return bstore[choice];
185 Buffer * BufferList::next(Buffer const * buf) const
187 // Something is wrong, but we can probably survive it.
188 LASSERT(buf, return nullptr);
192 BufferStorage::const_iterator it =
193 find(bstore.begin(), bstore.end(), buf);
194 LASSERT(it != bstore.end(), return nullptr);
196 Buffer * nextbuf = (it == bstore.end()) ? bstore.front() : *it;
201 Buffer * BufferList::previous(Buffer const * buf) const
203 // Something is wrong, but we can probably survive it.
204 LASSERT(buf, return nullptr);
208 BufferStorage::const_iterator it =
209 find(bstore.begin(), bstore.end(), buf);
210 LASSERT(it != bstore.end(), return nullptr);
212 Buffer * previousbuf = (it == bstore.begin()) ? bstore.back() : *(it - 1);
217 void BufferList::updateIncludedTeXfiles(string const & masterTmpDir,
218 OutputParams const & runparams_in)
220 OutputParams runparams = runparams_in;
221 runparams.is_child = true;
222 for (Buffer * buf : bstore) {
223 if (!buf->isDepClean(masterTmpDir)) {
224 string writefile = addName(masterTmpDir, buf->latexName());
225 buf->makeLaTeXFile(FileName(writefile), masterTmpDir,
226 runparams, Buffer::OnlyBody);
227 buf->markDepClean(masterTmpDir);
233 void BufferList::emergencyWriteAll()
235 for (Buffer * buf : bstore)
236 buf->emergencyWrite();
240 void BufferList::invalidateConverterCache() const
242 for (Buffer const * buf : bstore)
243 buf->params().invalidateConverterCache();
247 bool BufferList::exists(FileName const & fname) const
249 return getBuffer(fname) != nullptr;
253 bool BufferList::isLoaded(Buffer const * b) const
257 BufferStorage::const_iterator cit =
258 find(bstore.begin(), bstore.end(), b);
259 return cit != bstore.end();
263 bool BufferList::isInternal(Buffer const * b) const
267 BufferStorage::const_iterator cit =
268 find(binternal.begin(), binternal.end(), b);
269 return cit != binternal.end();
273 bool BufferList::isOthersChild(Buffer * parent, Buffer * child) const
275 LASSERT(parent, return false);
276 LASSERT(child, return false);
277 LASSERT(parent->isChild(child), return false);
279 // Does child document have a different parent?
280 Buffer const * parent_ = child->parent();
281 if (parent_ && parent_ != parent)
284 for(Buffer const * buf : bstore)
285 if (buf != parent && buf->isChild(child))
291 Buffer * BufferList::getBuffer(support::FileName const & fname, bool internal) const
293 // 1) cheap test, using string comparison of file names
294 for (Buffer * b : bstore)
295 if (b->fileName() == fname)
297 // 2) possibly expensive test, using equivalence test of file names
298 for (Buffer * b : bstore)
299 if (equivalent(b->fileName(), fname))
302 // 1) cheap test, using string comparison of file names
303 for (Buffer * b : binternal)
304 if (b->fileName() == fname)
306 // 2) possibly expensive test, using equivalence test of file names
307 for (Buffer * b : binternal)
308 if (equivalent(b->fileName(), fname))
315 Buffer * BufferList::getBufferFromTmp(string const & path, bool realpath)
317 for (Buffer * buf : bstore) {
318 string const temppath = realpath ? FileName(buf->temppath()).realPath() : buf->temppath();
319 if (prefixIs(path, temppath)) {
320 // check whether the filename matches the master
321 string const master_name = buf->latexName();
322 if (suffixIs(path, master_name))
324 // if not, try with the children
325 for (Buffer * child : buf->getDescendants()) {
326 string const mangled_child_name = DocFileName(
327 changeExtension(child->absFileName(),
328 ".tex")).mangledFileName();
329 if (suffixIs(path, mangled_child_name))
338 void BufferList::recordCurrentAuthor(Author const & author)
340 for (Buffer * buf : bstore)
341 buf->params().authors().recordCurrentAuthor(author);
345 void BufferList::updatePreviews()
347 for (Buffer * buf : bstore)
348 buf->updatePreviews();
352 int BufferList::bufferNum(FileName const & fname) const
354 FileNameList const buffers(fileNames());
355 FileNameList::const_iterator cit =
356 find(buffers.begin(), buffers.end(), fname);
357 if (cit == buffers.end())
359 return int(cit - buffers.begin());
363 void BufferList::changed(bool update_metrics) const
365 for (Buffer const * buf : bstore)
366 buf->changed(update_metrics);
367 for (Buffer const * buf : binternal)
368 buf->changed(update_metrics);