]> git.lyx.org Git - lyx.git/blob - src/BufferList.cpp
Change the "empty layout" to the "plain layout", to try to avoid confusion.
[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         if (it == bstore.end())
172                 return bstore.front();
173         else
174                 return *it;
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         if (it == bstore.begin())
188                 return bstore.back();
189         else
190                 return *(it - 1);
191 }
192
193
194 void BufferList::updateIncludedTeXfiles(string const & masterTmpDir,
195                                         OutputParams const & runparams)
196 {
197         BufferStorage::iterator it = bstore.begin();
198         BufferStorage::iterator end = bstore.end();
199         for (; it != end; ++it) {
200                 if (!(*it)->isDepClean(masterTmpDir)) {
201                         string writefile = addName(masterTmpDir, (*it)->latexName());
202                         (*it)->makeLaTeXFile(FileName(writefile), masterTmpDir,
203                                              runparams, false);
204                         (*it)->markDepClean(masterTmpDir);
205                 }
206         }
207 }
208
209
210 void BufferList::emergencyWriteAll()
211 {
212         for_each(bstore.begin(), bstore.end(),
213                  bind(&BufferList::emergencyWrite, this, _1));
214 }
215
216
217 docstring BufferList::emergencyWrite(Buffer * buf)
218 {
219         // Use ::assert to avoid a loop, BOOST_ASSERT ends up calling ::assert
220         // compare with 0 to avoid pointer/interger comparison
221         // ::assert(buf != 0);
222         if (!buf)
223                 return _("No file open!");
224
225         // No need to save if the buffer has not changed.
226         if (buf->isClean())
227                 return docstring();
228
229         string const doc = buf->isUnnamed()
230                 ? onlyFilename(buf->absFileName()) : buf->absFileName();
231
232         docstring user_message = bformat(
233                 _("LyX: Attempting to save document %1$s\n"), from_utf8(doc));
234
235         // We try to save three places:
236         // 1) Same place as document. Unless it is an unnamed doc.
237         if (!buf->isUnnamed()) {
238                 string s = buf->absFileName();
239                 s += ".emergency";
240                 lyxerr << "  " << s << endl;
241                 if (buf->writeFile(FileName(s))) {
242                         buf->markClean();
243                         user_message += _("  Save seems successful. Phew.\n");
244                         return user_message;
245                 } else {
246                         user_message += _("  Save failed! Trying...\n");
247                 }
248         }
249
250         // 2) In HOME directory.
251         string s = addName(package().home_dir().absFilename(), buf->absFileName());
252         s += ".emergency";
253         lyxerr << ' ' << s << endl;
254         if (buf->writeFile(FileName(s))) {
255                 buf->markClean();
256                 user_message += _("  Save seems successful. Phew.\n");
257                 return user_message;
258         }
259
260         user_message += _("  Save failed! Trying...\n");
261
262         // 3) In "/tmp" directory.
263         // MakeAbsPath to prepend the current
264         // drive letter on OS/2
265         s = addName(package().temp_dir().absFilename(), buf->absFileName());
266         s += ".emergency";
267         lyxerr << ' ' << s << endl;
268         if (buf->writeFile(FileName(s))) {
269                 buf->markClean();
270                 user_message += _("  Save seems successful. Phew.\n");
271                 return user_message;
272         }
273
274         user_message += _("  Save failed! Bummer. Document is lost.");
275         return user_message;
276 }
277
278
279 bool BufferList::exists(FileName const & fname) const
280 {
281         return getBuffer(fname) != 0;
282 }
283
284
285 bool BufferList::isLoaded(Buffer const * b) const
286 {
287         LASSERT(b, /**/);
288         BufferStorage::const_iterator cit =
289                 find(bstore.begin(), bstore.end(), b);
290         return cit != bstore.end();
291 }
292
293
294 Buffer * BufferList::getBuffer(support::FileName const & fname) const
295 {
296         BufferStorage::const_iterator it = find_if(bstore.begin(), bstore.end(),
297                 bind(equal_to<FileName>(), bind(&Buffer::fileName, _1), fname));
298         return it != bstore.end() ? (*it) : 0;
299 }
300
301
302 Buffer * BufferList::getBufferFromTmp(string const & s)
303 {
304         BufferStorage::iterator it = bstore.begin();
305         BufferStorage::iterator end = bstore.end();
306         for (; it < end; ++it)
307                 if (prefixIs(s, (*it)->temppath()))
308                         return *it;
309         return 0;
310 }
311
312
313 void BufferList::setCurrentAuthor(docstring const & name, docstring const & email)
314 {
315         BufferStorage::iterator it = bstore.begin();
316         BufferStorage::iterator end = bstore.end();
317         for (; it != end; ++it)
318                 (*it)->params().authors().record(0, Author(name, email));
319 }
320
321
322 int BufferList::bufferNum(FileName const & fname) const
323 {
324         FileNameList const & buffers = fileNames();
325         FileNameList::const_iterator cit =
326                 find(buffers.begin(), buffers.end(), fname);
327         if (cit == buffers.end())
328                 return 0;
329         return int(cit - buffers.begin());
330 }
331
332
333 bool BufferList::releaseChild(Buffer * parent, Buffer * child)
334 {
335         LASSERT(parent, return false);
336         LASSERT(child, return false);
337         LASSERT(parent->isChild(child), return false);
338
339         // Child document has a different parent, don't close it.
340         if (child->parent() != parent)
341                 return false;
342
343         BufferStorage::iterator it = bstore.begin();
344         BufferStorage::iterator end = bstore.end();
345         for (; it != end; ++it) {
346                 Buffer * buf = *it;
347                 if (buf != parent && buf->isChild(child)) {
348                         child->setParent(0);
349                         return false;
350                 }
351         }
352         release(child);
353         return true;
354 }
355
356
357 } // namespace lyx