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 BufferStorage::iterator it = binternal.begin();
55 BufferStorage::iterator end = binternal.end();
56 for (; it != end; ++it)
61 bool BufferList::empty() const
63 return bstore.empty();
67 BufferList::iterator BufferList::begin()
69 return bstore.begin();
73 BufferList::const_iterator BufferList::begin() const
75 return bstore.begin();
79 BufferList::iterator BufferList::end()
85 BufferList::const_iterator BufferList::end() const
91 void BufferList::release(Buffer * buf)
93 // We may leak here, but we probably do not need to
96 BufferStorage::iterator const it =
97 find(bstore.begin(), bstore.end(), buf);
98 if (it != bstore.end()) {
101 LASSERT(tmp, return);
107 Buffer * BufferList::newInternalBuffer(string const & s)
109 Buffer * const buf = createNewBuffer(s);
111 buf->setInternal(true);
112 binternal.push_back(buf);
118 Buffer * BufferList::newBuffer(string const & s)
120 Buffer * const buf = createNewBuffer(s);
122 LYXERR(Debug::INFO, "Assigning to buffer " << bstore.size());
123 bstore.push_back(buf);
129 Buffer * BufferList::createNewBuffer(string const & s)
131 unique_ptr<Buffer> tmpbuf;
133 tmpbuf = make_unique<Buffer>(s);
134 } catch (ExceptionMessage const & message) {
135 if (message.type_ == ErrorException) {
136 Alert::error(message.title_, message.details_);
138 } else if (message.type_ == WarningException) {
139 Alert::warning(message.title_, message.details_);
143 tmpbuf->params().useClassDefaults();
144 return tmpbuf.release();
148 void BufferList::closeAll()
150 while (!bstore.empty())
151 release(bstore.front());
155 FileNameList BufferList::fileNames() const
158 BufferStorage::const_iterator it = bstore.begin();
159 BufferStorage::const_iterator end = bstore.end();
160 for (; it != end; ++it) {
162 nvec.push_back(buf->fileName());
168 Buffer * BufferList::first()
172 return bstore.front();
176 Buffer * BufferList::last()
180 return bstore.back();
184 Buffer * BufferList::getBuffer(unsigned int choice)
186 if (choice >= bstore.size())
188 return bstore[choice];
192 Buffer * BufferList::next(Buffer const * buf) const
194 // Something is wrong, but we can probably survive it.
195 LASSERT(buf, return 0);
199 BufferStorage::const_iterator it =
200 find(bstore.begin(), bstore.end(), buf);
201 LASSERT(it != bstore.end(), return 0);
203 Buffer * nextbuf = (it == bstore.end()) ? bstore.front() : *it;
208 Buffer * BufferList::previous(Buffer const * buf) const
210 // Something is wrong, but we can probably survive it.
211 LASSERT(buf, return 0);
215 BufferStorage::const_iterator it =
216 find(bstore.begin(), bstore.end(), buf);
217 LASSERT(it != bstore.end(), return 0);
219 Buffer * previousbuf = (it == bstore.begin()) ? bstore.back() : *(it - 1);
224 void BufferList::updateIncludedTeXfiles(string const & masterTmpDir,
225 OutputParams const & runparams_in)
227 OutputParams runparams = runparams_in;
228 runparams.is_child = true;
229 BufferStorage::iterator it = bstore.begin();
230 BufferStorage::iterator end = bstore.end();
231 for (; it != end; ++it) {
232 if (!(*it)->isDepClean(masterTmpDir)) {
233 string writefile = addName(masterTmpDir, (*it)->latexName());
234 (*it)->makeLaTeXFile(FileName(writefile), masterTmpDir,
235 runparams, Buffer::OnlyBody);
236 (*it)->markDepClean(masterTmpDir);
239 runparams.is_child = false;
243 void BufferList::emergencyWriteAll()
245 BufferStorage::const_iterator it = bstore.begin();
246 BufferStorage::const_iterator const en = bstore.end();
247 for (; it != en; ++it)
248 (*it)->emergencyWrite();
252 void BufferList::invalidateConverterCache() const
254 BufferStorage::const_iterator it = bstore.begin();
255 BufferStorage::const_iterator const en = bstore.end();
256 for (; it != en; ++it)
257 (*it)->params().invalidateConverterCache();
261 bool BufferList::exists(FileName const & fname) const
263 return getBuffer(fname) != 0;
267 bool BufferList::isLoaded(Buffer const * b) const
271 BufferStorage::const_iterator cit =
272 find(bstore.begin(), bstore.end(), b);
273 return cit != bstore.end();
277 bool BufferList::isOthersChild(Buffer * parent, Buffer * child)
279 LASSERT(parent, return false);
280 LASSERT(child, return false);
281 LASSERT(parent->isChild(child), return false);
283 // Does child document have a different parent?
284 Buffer const * parent_ = child->parent();
285 if (parent_ && parent_ != parent)
288 for(Buffer * buf : bstore)
289 if (buf != parent && buf->isChild(child))
295 Buffer * BufferList::getBuffer(support::FileName const & fname, bool internal) const
297 // 1) cheap test, using string comparison of file names
298 for (Buffer * b : bstore)
299 if (b->fileName() == fname)
301 // 2) possibly expensive test, using equivalence test of file names
302 for (Buffer * b : bstore)
303 if (equivalent(b->fileName(), fname))
306 // 1) cheap test, using string comparison of file names
307 for (Buffer * b : binternal)
308 if (b->fileName() == fname)
310 // 2) possibly expensive test, using equivalence test of file names
311 for (Buffer * b : binternal)
312 if (equivalent(b->fileName(), fname))
319 Buffer * BufferList::getBufferFromTmp(string const & s)
321 BufferStorage::iterator it = bstore.begin();
322 BufferStorage::iterator end = bstore.end();
323 for (; it < end; ++it) {
324 if (prefixIs(s, (*it)->temppath())) {
325 // check whether the filename matches the master
326 string const master_name = (*it)->latexName();
327 if (suffixIs(s, master_name))
329 // if not, try with the children
330 ListOfBuffers clist = (*it)->getDescendents();
331 ListOfBuffers::const_iterator cit = clist.begin();
332 ListOfBuffers::const_iterator cend = clist.end();
333 for (; cit != cend; ++cit) {
334 string const mangled_child_name = DocFileName(
335 changeExtension((*cit)->absFileName(),
336 ".tex")).mangledFileName();
337 if (suffixIs(s, mangled_child_name))
346 void BufferList::recordCurrentAuthor(Author const & author)
348 BufferStorage::iterator it = bstore.begin();
349 BufferStorage::iterator end = bstore.end();
350 for (; it != end; ++it)
351 (*it)->params().authors().recordCurrentAuthor(author);
355 void BufferList::updatePreviews()
357 BufferStorage::iterator it = bstore.begin();
358 BufferStorage::iterator end = bstore.end();
359 for (; it != end; ++it)
360 (*it)->updatePreviews();
364 int BufferList::bufferNum(FileName const & fname) const
366 FileNameList const buffers(fileNames());
367 FileNameList::const_iterator cit =
368 find(buffers.begin(), buffers.end(), fname);
369 if (cit == buffers.end())
371 return int(cit - buffers.begin());
375 void BufferList::changed(bool update_metrics) const
377 BufferStorage::const_iterator it = bstore.begin();
378 BufferStorage::const_iterator end = bstore.end();
379 for (; it != end; ++it)
380 (*it)->changed(update_metrics);
381 it = binternal.begin();
382 end = binternal.end();
383 for (; it != end; ++it)
384 (*it)->changed(update_metrics);