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