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