]> git.lyx.org Git - lyx.git/blob - src/BufferList.cpp
Typos.
[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 <boost/bind.hpp>
36
37 #include <algorithm>
38 #include <functional>
39
40 using boost::bind;
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 bool BufferList::empty() const
55 {
56         return bstore.empty();
57 }
58
59
60 BufferList::iterator BufferList::begin()
61 {
62         return bstore.begin();
63 }
64
65
66 BufferList::const_iterator BufferList::begin() const
67 {
68         return bstore.begin();
69 }
70
71
72 BufferList::iterator BufferList::end()
73 {
74         return bstore.end();
75 }
76
77
78 BufferList::const_iterator BufferList::end() const
79 {
80         return bstore.end();
81 }
82
83
84 void BufferList::release(Buffer * buf)
85 {
86         LASSERT(buf, /**/);
87         BufferStorage::iterator const it =
88                 find(bstore.begin(), bstore.end(), buf);
89         if (it != bstore.end()) {
90                 Buffer * tmp = (*it);
91                 LASSERT(tmp, /**/);
92                 bstore.erase(it);
93                 delete tmp;
94         }
95 }
96
97
98 Buffer * BufferList::newBuffer(string const & s, bool const ronly)
99 {
100         auto_ptr<Buffer> tmpbuf;
101         try {
102                 tmpbuf.reset(new Buffer(s, ronly));
103         } catch (ExceptionMessage const & message) {
104                 if (message.type_ == ErrorException) {
105                         Alert::error(message.title_, message.details_);
106                         exit(1);
107                 } else if (message.type_ == WarningException) {
108                         Alert::warning(message.title_, message.details_);
109                         return 0;
110                 }
111         }
112         tmpbuf->params().useClassDefaults();
113         LYXERR(Debug::INFO, "Assigning to buffer " << bstore.size());
114         bstore.push_back(tmpbuf.get());
115         return tmpbuf.release();
116 }
117
118
119 void BufferList::closeAll()
120 {
121         while (!bstore.empty())
122                 release(bstore.front());
123 }
124
125
126 FileNameList const & BufferList::fileNames() const
127 {
128         static FileNameList nvec;
129         nvec.clear();
130         transform(bstore.begin(), bstore.end(),
131                   back_inserter(nvec),
132                   boost::bind(&Buffer::fileName, _1));
133         return nvec;
134 }
135
136
137 Buffer * BufferList::first()
138 {
139         if (bstore.empty())
140                 return 0;
141         return bstore.front();
142 }
143
144
145 Buffer * BufferList::last()
146 {
147         if (bstore.empty())
148                 return 0;
149         return bstore.back();
150 }
151
152
153 Buffer * BufferList::getBuffer(unsigned int choice)
154 {
155         if (choice >= bstore.size())
156                 return 0;
157         return bstore[choice];
158 }
159
160
161 Buffer * BufferList::next(Buffer const * buf) const
162 {
163         LASSERT(buf, /**/);
164
165         if (bstore.empty())
166                 return 0;
167         BufferStorage::const_iterator it = find(bstore.begin(),
168                                                 bstore.end(), buf);
169         LASSERT(it != bstore.end(), /**/);
170         ++it;
171         Buffer * nextbuf = (it == bstore.end()) ? bstore.front() : *it;
172         if (nextbuf->fileName().extension() == "internal")
173                 return next(nextbuf);
174         return nextbuf;
175 }
176
177
178 Buffer * BufferList::previous(Buffer const * buf) const
179 {
180         LASSERT(buf, /**/);
181
182         if (bstore.empty())
183                 return 0;
184         BufferStorage::const_iterator it = find(bstore.begin(),
185                                                 bstore.end(), buf);
186         LASSERT(it != bstore.end(), /**/);
187
188         Buffer * previousbuf = (it == bstore.begin()) ? bstore.back() : *(it - 1);
189         if (previousbuf->fileName().extension() == "internal")
190                 return previous(previousbuf);
191         return previousbuf;
192 }
193
194
195 void BufferList::updateIncludedTeXfiles(string const & masterTmpDir,
196                                         OutputParams const & runparams)
197 {
198         BufferStorage::iterator it = bstore.begin();
199         BufferStorage::iterator end = bstore.end();
200         for (; it != end; ++it) {
201                 if (!(*it)->isDepClean(masterTmpDir)) {
202                         string writefile = addName(masterTmpDir, (*it)->latexName());
203                         (*it)->makeLaTeXFile(FileName(writefile), masterTmpDir,
204                                              runparams, false);
205                         (*it)->markDepClean(masterTmpDir);
206                 }
207         }
208 }
209
210
211 void BufferList::emergencyWriteAll()
212 {
213         for_each(bstore.begin(), bstore.end(),
214                  bind(&BufferList::emergencyWrite, this, _1));
215 }
216
217
218 docstring BufferList::emergencyWrite(Buffer * buf)
219 {
220         // Use ::assert to avoid a loop, BOOST_ASSERT ends up calling ::assert
221         // compare with 0 to avoid pointer/interger comparison
222         // ::assert(buf != 0);
223         if (!buf)
224                 return _("No file open!");
225
226         // No need to save if the buffer has not changed.
227         if (buf->isClean())
228                 return docstring();
229
230         string const doc = buf->isUnnamed()
231                 ? onlyFilename(buf->absFileName()) : buf->absFileName();
232
233         docstring user_message = bformat(
234                 _("LyX: Attempting to save document %1$s\n"), from_utf8(doc));
235
236         // We try to save three places:
237         // 1) Same place as document. Unless it is an unnamed doc.
238         if (!buf->isUnnamed()) {
239                 string s = buf->absFileName();
240                 s += ".emergency";
241                 lyxerr << "  " << s << endl;
242                 if (buf->writeFile(FileName(s))) {
243                         buf->markClean();
244                         user_message += _("  Save seems successful. Phew.\n");
245                         return user_message;
246                 } else {
247                         user_message += _("  Save failed! Trying...\n");
248                 }
249         }
250
251         // 2) In HOME directory.
252         string s = addName(package().home_dir().absFilename(), buf->absFileName());
253         s += ".emergency";
254         lyxerr << ' ' << s << endl;
255         if (buf->writeFile(FileName(s))) {
256                 buf->markClean();
257                 user_message += _("  Save seems successful. Phew.\n");
258                 return user_message;
259         }
260
261         user_message += _("  Save failed! Trying...\n");
262
263         // 3) In "/tmp" directory.
264         // MakeAbsPath to prepend the current
265         // drive letter on OS/2
266         s = addName(package().temp_dir().absFilename(), buf->absFileName());
267         s += ".emergency";
268         lyxerr << ' ' << s << endl;
269         if (buf->writeFile(FileName(s))) {
270                 buf->markClean();
271                 user_message += _("  Save seems successful. Phew.\n");
272                 return user_message;
273         }
274
275         user_message += _("  Save failed! Bummer. Document is lost.");
276         return user_message;
277 }
278
279
280 bool BufferList::exists(FileName const & fname) const
281 {
282         return getBuffer(fname) != 0;
283 }
284
285
286 bool BufferList::isLoaded(Buffer const * b) const
287 {
288         LASSERT(b, /**/);
289         BufferStorage::const_iterator cit =
290                 find(bstore.begin(), bstore.end(), b);
291         return cit != bstore.end();
292 }
293
294
295 Buffer * BufferList::getBuffer(support::FileName const & fname) const
296 {
297         BufferStorage::const_iterator it = find_if(bstore.begin(), bstore.end(),
298                 bind(equal_to<FileName>(), bind(&Buffer::fileName, _1), fname));
299         return it != bstore.end() ? (*it) : 0;
300 }
301
302
303 Buffer * BufferList::getBufferFromTmp(string const & s)
304 {
305         BufferStorage::iterator it = bstore.begin();
306         BufferStorage::iterator end = bstore.end();
307         for (; it < end; ++it)
308                 if (prefixIs(s, (*it)->temppath()))
309                         return *it;
310         return 0;
311 }
312
313
314 void BufferList::setCurrentAuthor(docstring const & name, docstring const & email)
315 {
316         BufferStorage::iterator it = bstore.begin();
317         BufferStorage::iterator end = bstore.end();
318         for (; it != end; ++it)
319                 (*it)->params().authors().record(0, Author(name, email));
320 }
321
322
323 int BufferList::bufferNum(FileName const & fname) const
324 {
325         FileNameList const & buffers = fileNames();
326         FileNameList::const_iterator cit =
327                 find(buffers.begin(), buffers.end(), fname);
328         if (cit == buffers.end())
329                 return 0;
330         return int(cit - buffers.begin());
331 }
332
333
334 bool BufferList::releaseChild(Buffer * parent, Buffer * child)
335 {
336         LASSERT(parent, return false);
337         LASSERT(child, return false);
338         LASSERT(parent->isChild(child), return false);
339
340         // Child document has a different parent, don't close it.
341         if (child->parent() != parent)
342                 return false;
343
344         BufferStorage::iterator it = bstore.begin();
345         BufferStorage::iterator end = bstore.end();
346         for (; it != end; ++it) {
347                 Buffer * buf = *it;
348                 if (buf != parent && buf->isChild(child)) {
349                         child->setParent(0);
350                         return false;
351                 }
352         }
353         release(child);
354         return true;
355 }
356
357
358 } // namespace lyx