]> git.lyx.org Git - lyx.git/blob - src/BufferList.cpp
Whitespace & renaming
[lyx.git] / src / BufferList.cpp
1 /**
2  * \file BufferList.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "BufferList.h"
14
15 #include "Author.h"
16 #include "Buffer.h"
17 #include "BufferParams.h"
18
19 #include "frontends/alert.h"
20
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"
27
28 #include "support/lassert.h"
29
30 #include <algorithm>
31 #include <iterator>
32 #include <memory>
33
34 using namespace std;
35 using namespace lyx::support;
36
37 namespace lyx {
38
39 namespace Alert = lyx::frontend::Alert;
40
41
42 BufferList::BufferList()
43 {}
44
45
46 BufferList::~BufferList()
47 {
48         for (Buffer * buf : binternal)
49                 delete buf;
50 }
51
52
53 bool BufferList::empty() const
54 {
55         return bstore.empty();
56 }
57
58
59 BufferList::iterator BufferList::begin()
60 {
61         return bstore.begin();
62 }
63
64
65 BufferList::const_iterator BufferList::begin() const
66 {
67         return bstore.begin();
68 }
69
70
71 BufferList::iterator BufferList::end()
72 {
73         return bstore.end();
74 }
75
76
77 BufferList::const_iterator BufferList::end() const
78 {
79         return bstore.end();
80 }
81
82
83 void BufferList::release(Buffer * buf)
84 {
85         // We may leak here, but we probably do not need to
86         // shut down.
87         LASSERT(buf, return);
88         BufferStorage::iterator const it =
89                 find(bstore.begin(), bstore.end(), buf);
90         if (it != bstore.end()) {
91                 Buffer const * parent = buf->parent();
92                 Buffer * tmp = (*it);
93                 bstore.erase(it);
94                 LASSERT(tmp, return);
95                 delete tmp;
96                 if (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();
100         }
101 }
102
103
104 Buffer * BufferList::newInternalBuffer(string const & s)
105 {
106         Buffer * const buf = createNewBuffer(s);
107         if (buf) {
108                 buf->setInternal(true);
109                 binternal.push_back(buf);
110         }
111         return buf;
112 }
113
114
115 Buffer * BufferList::newBuffer(string const & s)
116 {
117         Buffer * const buf = createNewBuffer(s);
118         if (buf) {
119                 LYXERR(Debug::INFO, "Assigning to buffer " << bstore.size());
120                 bstore.push_back(buf);
121         }
122         return buf;
123 }
124
125
126 Buffer * BufferList::createNewBuffer(string const & s)
127 {
128         unique_ptr<Buffer> tmpbuf;
129         try {
130                 tmpbuf = make_unique<Buffer>(s);
131         } catch (ExceptionMessage const & message) {
132                 if (message.type_ == ErrorException) {
133                         Alert::error(message.title_, message.details_);
134                         exit(1);
135                 } else if (message.type_ == WarningException) {
136                         Alert::warning(message.title_, message.details_);
137                         return nullptr;
138                 }
139         }
140         tmpbuf->params().useClassDefaults();
141         return tmpbuf.release();
142 }
143
144
145 void BufferList::closeAll()
146 {
147         while (!bstore.empty())
148                 release(bstore.front());
149 }
150
151
152 FileNameList BufferList::fileNames() const
153 {
154         FileNameList nvec;
155         for (Buffer const * buf : bstore)
156                 nvec.push_back(buf->fileName());
157         return nvec;
158 }
159
160
161 Buffer * BufferList::first()
162 {
163         if (bstore.empty())
164                 return nullptr;
165         return bstore.front();
166 }
167
168
169 Buffer * BufferList::last()
170 {
171         if (bstore.empty())
172                 return nullptr;
173         return bstore.back();
174 }
175
176
177 Buffer * BufferList::getBuffer(unsigned int choice)
178 {
179         if (choice >= bstore.size())
180                 return nullptr;
181         return bstore[choice];
182 }
183
184
185 Buffer * BufferList::next(Buffer const * buf) const
186 {
187         // Something is wrong, but we can probably survive it.
188         LASSERT(buf, return nullptr);
189
190         if (bstore.empty())
191                 return nullptr;
192         BufferStorage::const_iterator it =
193                         find(bstore.begin(), bstore.end(), buf);
194         LASSERT(it != bstore.end(), return nullptr);
195         ++it;
196         Buffer * nextbuf = (it == bstore.end()) ? bstore.front() : *it;
197         return nextbuf;
198 }
199
200
201 Buffer * BufferList::previous(Buffer const * buf) const
202 {
203         // Something is wrong, but we can probably survive it.
204         LASSERT(buf, return nullptr);
205
206         if (bstore.empty())
207                 return nullptr;
208         BufferStorage::const_iterator it =
209                         find(bstore.begin(), bstore.end(), buf);
210         LASSERT(it != bstore.end(), return nullptr);
211
212         Buffer * previousbuf = (it == bstore.begin()) ? bstore.back() : *(it - 1);
213         return previousbuf;
214 }
215
216
217 void BufferList::updateIncludedTeXfiles(string const & masterTmpDir,
218                                         OutputParams const & runparams_in)
219 {
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);
228                 }
229         }
230 }
231
232
233 void BufferList::emergencyWriteAll()
234 {
235         for (Buffer * buf : bstore)
236                  buf->emergencyWrite();
237 }
238
239
240 void BufferList::invalidateConverterCache() const
241 {
242         for (Buffer const * buf : bstore)
243                 buf->params().invalidateConverterCache();
244 }
245
246
247 bool BufferList::exists(FileName const & fname) const
248 {
249         return getBuffer(fname) != nullptr;
250 }
251
252
253 bool BufferList::isLoaded(Buffer const * b) const
254 {
255         if (!b)
256                 return false;
257         BufferStorage::const_iterator cit =
258                 find(bstore.begin(), bstore.end(), b);
259         return cit != bstore.end();
260 }
261
262
263 bool BufferList::isInternal(Buffer const * b) const
264 {
265         if (!b)
266                 return false;
267         BufferStorage::const_iterator cit =
268                 find(binternal.begin(), binternal.end(), b);
269         return cit != binternal.end();
270 }
271
272
273 bool BufferList::isOthersChild(Buffer * parent, Buffer * child) const
274 {
275         LASSERT(parent, return false);
276         LASSERT(child, return false);
277         LASSERT(parent->isChild(child), return false);
278
279         // Does child document have a different parent?
280         Buffer const * parent_ = child->parent();
281         if (parent_ && parent_ != parent)
282                 return true;
283
284         for(Buffer const * buf : bstore)
285                 if (buf != parent && buf->isChild(child))
286                         return true;
287         return false;
288 }
289
290
291 Buffer * BufferList::getBuffer(support::FileName const & fname, bool internal) const
292 {
293         // 1) cheap test, using string comparison of file names
294         for (Buffer * b : bstore)
295                 if (b->fileName() == fname)
296                         return b;
297         // 2) possibly expensive test, using equivalence test of file names
298         for (Buffer * b : bstore)
299                 if (equivalent(b->fileName(), fname))
300                         return b;
301         if (internal) {
302                 // 1) cheap test, using string comparison of file names
303                 for (Buffer * b : binternal)
304                         if (b->fileName() == fname)
305                                 return b;
306                 // 2) possibly expensive test, using equivalence test of file names
307                 for (Buffer * b : binternal)
308                         if (equivalent(b->fileName(), fname))
309                                 return b;
310         }
311         return nullptr;
312 }
313
314
315 Buffer * BufferList::getBufferFromTmp(string const & path, bool realpath)
316 {
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))
323                                 return buf;
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))
330                                         return child;
331                         }
332                 }
333         }
334         return nullptr;
335 }
336
337
338 void BufferList::recordCurrentAuthor(Author const & author)
339 {
340         for (Buffer * buf : bstore)
341                 buf->params().authors().recordCurrentAuthor(author);
342 }
343
344
345 void BufferList::updatePreviews()
346 {
347         for (Buffer * buf : bstore)
348                 buf->updatePreviews();
349 }
350
351
352 int BufferList::bufferNum(FileName const & fname) const
353 {
354         FileNameList const buffers(fileNames());
355         FileNameList::const_iterator cit =
356                 find(buffers.begin(), buffers.end(), fname);
357         if (cit == buffers.end())
358                 return 0;
359         return int(cit - buffers.begin());
360 }
361
362
363 void BufferList::changed(bool update_metrics) const
364 {
365         for (Buffer const * buf : bstore)
366                 buf->changed(update_metrics);
367         for (Buffer const * buf : binternal)
368                 buf->changed(update_metrics);
369 }
370
371
372 } // namespace lyx