]> git.lyx.org Git - lyx.git/blob - src/BufferList.cpp
Remove test that is not needed.
[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 #include "Session.h"
19 #include "LyX.h"
20 #include "output_latex.h"
21 #include "ParagraphList.h"
22
23 #include "frontends/alert.h"
24
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"
33
34 #include "support/lassert.h"
35 #include "support/bind.h"
36
37 #include <algorithm>
38 #include <functional>
39 #include <iterator>
40 #include <memory>
41
42 using namespace std;
43 using namespace lyx::support;
44
45 namespace lyx {
46
47 namespace Alert = lyx::frontend::Alert;
48
49
50 BufferList::BufferList()
51 {}
52
53
54 BufferList::~BufferList()
55 {
56         BufferStorage::iterator it = binternal.begin();
57         BufferStorage::iterator end = binternal.end();
58         for (; it != end; ++it)
59                 delete (*it);
60 }
61
62
63 bool BufferList::empty() const
64 {
65         return bstore.empty();
66 }
67
68
69 BufferList::iterator BufferList::begin()
70 {
71         return bstore.begin();
72 }
73
74
75 BufferList::const_iterator BufferList::begin() const
76 {
77         return bstore.begin();
78 }
79
80
81 BufferList::iterator BufferList::end()
82 {
83         return bstore.end();
84 }
85
86
87 BufferList::const_iterator BufferList::end() const
88 {
89         return bstore.end();
90 }
91
92
93 void BufferList::release(Buffer * buf)
94 {
95         // We may leak here, but we probably do not need to
96         // shut down.
97         LASSERT(buf, return);
98         BufferStorage::iterator const it =
99                 find(bstore.begin(), bstore.end(), buf);
100         if (it != bstore.end()) {
101                 Buffer const * parent = buf->parent();
102                 Buffer * tmp = (*it);
103                 bstore.erase(it);
104                 LASSERT(tmp, return);
105                 delete tmp;
106                 if (parent)
107                         // If this was a child, update the parent's buffer
108                         // to avoid crashes due to dangling pointers (bug 9979)
109                         parent->updateBuffer();
110         }
111 }
112
113
114 Buffer * BufferList::newInternalBuffer(string const & s)
115 {
116         Buffer * const buf = createNewBuffer(s);
117         if (buf) {
118                 buf->setInternal(true);
119                 binternal.push_back(buf);
120         }
121         return buf;
122 }
123
124
125 Buffer * BufferList::newBuffer(string const & s)
126 {
127         Buffer * const buf = createNewBuffer(s);
128         if (buf) {
129                 LYXERR(Debug::INFO, "Assigning to buffer " << bstore.size());
130                 bstore.push_back(buf);
131         }
132         return buf;
133 }
134
135
136 Buffer * BufferList::createNewBuffer(string const & s)
137 {
138         auto_ptr<Buffer> tmpbuf;
139         try {
140                 tmpbuf.reset(new Buffer(s));
141         } catch (ExceptionMessage const & message) {
142                 if (message.type_ == ErrorException) {
143                         Alert::error(message.title_, message.details_);
144                         exit(1);
145                 } else if (message.type_ == WarningException) {
146                         Alert::warning(message.title_, message.details_);
147                         return 0;
148                 }
149         }
150         tmpbuf->params().useClassDefaults();
151         return tmpbuf.release();
152 }
153
154
155 void BufferList::closeAll()
156 {
157         while (!bstore.empty())
158                 release(bstore.front());
159 }
160
161
162 FileNameList BufferList::fileNames() const
163 {
164         FileNameList nvec;
165         BufferStorage::const_iterator it = bstore.begin();
166         BufferStorage::const_iterator end = bstore.end();
167         for (; it != end; ++it) {
168                 Buffer * buf = *it;
169                 nvec.push_back(buf->fileName());
170         }
171         return nvec;
172 }
173
174
175 Buffer * BufferList::first()
176 {
177         if (bstore.empty())
178                 return 0;
179         return bstore.front();
180 }
181
182
183 Buffer * BufferList::last()
184 {
185         if (bstore.empty())
186                 return 0;
187         return bstore.back();
188 }
189
190
191 Buffer * BufferList::getBuffer(unsigned int choice)
192 {
193         if (choice >= bstore.size())
194                 return 0;
195         return bstore[choice];
196 }
197
198
199 Buffer * BufferList::next(Buffer const * buf) const
200 {
201         // Something is wrong, but we can probably survive it.
202         LASSERT(buf, return 0);
203
204         if (bstore.empty())
205                 return 0;
206         BufferStorage::const_iterator it = 
207                         find(bstore.begin(), bstore.end(), buf);
208         LASSERT(it != bstore.end(), return 0);
209         ++it;
210         Buffer * nextbuf = (it == bstore.end()) ? bstore.front() : *it;
211         return nextbuf;
212 }
213
214
215 Buffer * BufferList::previous(Buffer const * buf) const
216 {
217         // Something is wrong, but we can probably survive it.
218         LASSERT(buf, return 0);
219
220         if (bstore.empty())
221                 return 0;
222         BufferStorage::const_iterator it = 
223                         find(bstore.begin(), bstore.end(), buf);
224         LASSERT(it != bstore.end(), return 0);
225
226         Buffer * previousbuf = (it == bstore.begin()) ? bstore.back() : *(it - 1);
227         return previousbuf;
228 }
229
230
231 void BufferList::updateIncludedTeXfiles(string const & masterTmpDir,
232                                         OutputParams const & runparams_in)
233 {
234         OutputParams runparams = runparams_in;
235         runparams.is_child = true;
236         BufferStorage::iterator it = bstore.begin();
237         BufferStorage::iterator end = bstore.end();
238         for (; it != end; ++it) {
239                 if (!(*it)->isDepClean(masterTmpDir)) {
240                         string writefile = addName(masterTmpDir, (*it)->latexName());
241                         (*it)->makeLaTeXFile(FileName(writefile), masterTmpDir,
242                                              runparams, Buffer::OnlyBody);
243                         (*it)->markDepClean(masterTmpDir);
244                 }
245         }
246         runparams.is_child = false;
247 }
248
249
250 void BufferList::emergencyWriteAll()
251 {
252         BufferStorage::const_iterator it = bstore.begin();
253         BufferStorage::const_iterator const en = bstore.end();
254         for (; it != en; ++it)
255                  (*it)->emergencyWrite();
256 }
257
258
259 void BufferList::invalidateConverterCache() const
260 {
261         BufferStorage::const_iterator it = bstore.begin();
262         BufferStorage::const_iterator const en = bstore.end();
263         for (; it != en; ++it)
264                 (*it)->params().invalidateConverterCache();
265 }
266
267
268 bool BufferList::exists(FileName const & fname) const
269 {
270         return getBuffer(fname) != 0;
271 }
272
273
274  bool BufferList::isLoaded(Buffer const * b) const
275 {
276         if (!b)
277                 return false;
278         BufferStorage::const_iterator cit =
279                 find(bstore.begin(), bstore.end(), b);
280         return cit != bstore.end();
281 }
282
283
284 bool BufferList::isOthersChild(Buffer * parent, Buffer * child)
285 {
286         LASSERT(parent, return false);
287         LASSERT(child, return false);
288         LASSERT(parent->isChild(child), return false);
289         
290         // Does child document have a different parent?
291         Buffer const * parent_ = child->parent();
292         if (parent_ && parent_ != parent)
293                 return true;
294         
295         BufferStorage::iterator it = bstore.begin();
296         BufferStorage::iterator end = bstore.end();
297         for (; it != end; ++it) {
298                 Buffer * buf = *it;
299                 if (buf != parent && buf->isChild(child))
300                         return true;
301         }
302         return false;
303 }
304
305
306 namespace {
307
308 struct equivalent_to : public binary_function<FileName, FileName, bool>
309 {
310         bool operator()(FileName const & x, FileName const & y) const
311         { return equivalent(x, y); }
312 };
313
314 }
315
316
317 Buffer * BufferList::getBuffer(support::FileName const & fname, bool internal) const
318 {
319         // 1) cheap test, using string comparison of file names
320         BufferStorage::const_iterator it = find_if(bstore.begin(), bstore.end(),
321                 lyx::bind(equal_to<FileName>(), lyx::bind(&Buffer::fileName, _1), fname));
322         if (it != bstore.end())
323                 return *it;
324         // 2) possibly expensive test, using equivalence test of file names
325         it = find_if(bstore.begin(), bstore.end(),
326                 lyx::bind(equivalent_to(), lyx::bind(&Buffer::fileName, _1), fname));
327         if (it != bstore.end())
328                 return *it;
329
330         if (internal) {
331                 // 1) cheap test, using string comparison of file names
332                 BufferStorage::const_iterator it = find_if(binternal.begin(), binternal.end(),
333                         lyx::bind(equal_to<FileName>(), lyx::bind(&Buffer::fileName, _1), fname));
334                 if (it != binternal.end())
335                         return *it;
336                 // 2) possibly expensive test, using equivalence test of file names
337                 it = find_if(binternal.begin(), binternal.end(),
338                              lyx::bind(equivalent_to(), lyx::bind(&Buffer::fileName, _1), fname));
339                 if (it != binternal.end())
340                         return *it;
341         }
342
343         return 0;
344 }
345
346
347 Buffer * BufferList::getBufferFromTmp(string const & s)
348 {
349         BufferStorage::iterator it = bstore.begin();
350         BufferStorage::iterator end = bstore.end();
351         for (; it < end; ++it) {
352                 if (prefixIs(s, (*it)->temppath())) {
353                         // check whether the filename matches the master
354                         string const master_name = (*it)->latexName();
355                         if (suffixIs(s, master_name))
356                                 return *it;
357                         // if not, try with the children
358                         ListOfBuffers clist = (*it)->getDescendents();
359                         ListOfBuffers::const_iterator cit = clist.begin();
360                         ListOfBuffers::const_iterator cend = clist.end();
361                         for (; cit != cend; ++cit) {
362                                 string const mangled_child_name = DocFileName(
363                                         changeExtension((*cit)->absFileName(),
364                                                 ".tex")).mangledFileName();
365                                 if (suffixIs(s, mangled_child_name))
366                                         return *cit;
367                         }
368                 }
369         }
370         return 0;
371 }
372
373
374 void BufferList::recordCurrentAuthor(Author const & author)
375 {
376         BufferStorage::iterator it = bstore.begin();
377         BufferStorage::iterator end = bstore.end();
378         for (; it != end; ++it)
379                 (*it)->params().authors().recordCurrentAuthor(author);
380 }
381
382
383 void BufferList::updatePreviews()
384 {
385         BufferStorage::iterator it = bstore.begin();
386         BufferStorage::iterator end = bstore.end();
387         for (; it != end; ++it)
388                 (*it)->updatePreviews();
389 }
390
391
392 int BufferList::bufferNum(FileName const & fname) const
393 {
394         FileNameList const buffers(fileNames());
395         FileNameList::const_iterator cit =
396                 find(buffers.begin(), buffers.end(), fname);
397         if (cit == buffers.end())
398                 return 0;
399         return int(cit - buffers.begin());
400 }
401
402
403 void BufferList::changed(bool update_metrics) const
404 {
405         BufferStorage::const_iterator it = bstore.begin();
406         BufferStorage::const_iterator end = bstore.end();
407         for (; it != end; ++it)
408                 (*it)->changed(update_metrics);
409         it = binternal.begin();
410         end = binternal.end();
411         for (; it != end; ++it)
412                 (*it)->changed(update_metrics);
413 }
414
415
416 } // namespace lyx