]> git.lyx.org Git - lyx.git/blob - src/bufferlist.C
the spellcheck cleanup
[lyx.git] / src / bufferlist.C
1 /**
2  * \file bufferlist.C
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 "debug.h"
19 #include "gettext.h"
20 #include "lastfiles.h"
21 #include "lyx_cb.h"
22 #include "lyx_main.h"
23 #include "paragraph.h"
24
25 #include "frontends/Alert.h"
26
27 #include "support/filetools.h"
28 #include "support/lyxfunctional.h"
29
30 #include <boost/bind.hpp>
31
32 using lyx::support::AddName;
33 using lyx::support::bformat;
34 using lyx::support::GetEnvPath;
35 using lyx::support::MakeAbsPath;
36 using lyx::support::MakeDisplayPath;
37 using lyx::support::OnlyFilename;
38 using lyx::support::removeAutosaveFile;
39 using lyx::support::prefixIs;
40
41 using std::auto_ptr;
42 using std::endl;
43 using std::find;
44 using std::find_if;
45 using std::for_each;
46 using std::string;
47 using std::vector;
48
49
50 BufferList::BufferList()
51 {}
52
53
54 bool BufferList::empty() const
55 {
56         return bstore.empty();
57 }
58
59
60 bool BufferList::quitWriteBuffer(Buffer * buf)
61 {
62         string file;
63         if (buf->isUnnamed())
64                 file = OnlyFilename(buf->fileName());
65         else
66                 file = MakeDisplayPath(buf->fileName(), 30);
67
68         string text = bformat(_("The document %1$s has unsaved changes.\n\n"
69                 "Do you want to save the document or discard the changes?"), file);
70         int const ret = Alert::prompt(_("Save changed document?"),
71                 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
72
73         if (ret == 0) {
74                 // FIXME: WriteAs can be asynch !
75                 // but not right now...maybe we should remove that
76
77                 bool succeeded;
78
79                 if (buf->isUnnamed())
80                         succeeded = WriteAs(buf);
81                 else
82                         succeeded = MenuWrite(buf);
83
84                 if (!succeeded)
85                         return false;
86         } else if (ret == 1) {
87                 // if we crash after this we could
88                 // have no autosave file but I guess
89                 // this is really inprobable (Jug)
90                 if (buf->isUnnamed())
91                         removeAutosaveFile(buf->fileName());
92
93         } else {
94                 return false;
95         }
96
97         return true;
98 }
99
100
101 bool BufferList::quitWriteAll()
102 {
103         BufferStorage::iterator it = bstore.begin();
104         BufferStorage::iterator end = bstore.end();
105         for (; it != end; ++it) {
106                 if ((*it)->isClean())
107                         continue;
108
109                 if (!quitWriteBuffer(*it))
110                         return false;
111         }
112
113         return true;
114 }
115
116
117 void BufferList::release(Buffer * buf)
118 {
119         BOOST_ASSERT(buf);
120         BufferStorage::iterator it = find(bstore.begin(), bstore.end(), buf);
121         if (it != bstore.end()) {
122                 Buffer * tmp = (*it);
123                 bstore.erase(it);
124                 delete tmp;
125         }
126 }
127
128
129 Buffer * BufferList::newBuffer(string const & s, bool ronly)
130 {
131         auto_ptr<Buffer> tmpbuf(new Buffer(s, ronly));
132         tmpbuf->params().useClassDefaults();
133         lyxerr[Debug::INFO] << "Assigning to buffer "
134                             << bstore.size() << endl;
135         bstore.push_back(tmpbuf.get());
136         return tmpbuf.release();
137 }
138
139
140 void BufferList::closeAll()
141 {
142         while (!bstore.empty()) {
143                 close(bstore.front(), false);
144         }
145 }
146
147
148 bool BufferList::close(Buffer * buf, bool ask)
149 {
150         BOOST_ASSERT(buf);
151
152         // FIXME: is the quitting check still necessary ?
153         if (!ask || buf->isClean() || quitting || buf->paragraphs().empty()) {
154                 release(buf);
155                 return true;
156         }
157
158         string fname;
159         if (buf->isUnnamed())
160                 fname = OnlyFilename(buf->fileName());
161         else
162                 fname = MakeDisplayPath(buf->fileName(), 30);
163
164         string text = bformat(_("The document %1$s has unsaved changes.\n\n"
165                 "Do you want to save the document or discard the changes?"), fname);
166         int const ret = Alert::prompt(_("Save changed document?"),
167                 text, 0, 2, _("&Save"), _("&Discard"), _("&Cancel"));
168
169         if (ret == 0) {
170                 if (buf->isUnnamed()) {
171                         if (!WriteAs(buf))
172                                 return false;
173                 } else if (buf->save()) {
174                         LyX::ref().lastfiles().newFile(buf->fileName());
175                 } else {
176                         return false;
177                 }
178         } else if (ret == 2) {
179                 return false;
180         }
181
182         if (buf->isUnnamed()) {
183                 removeAutosaveFile(buf->fileName());
184         }
185
186         release(buf);
187         return true;
188 }
189
190
191 vector<string> const BufferList::getFileNames() const
192 {
193         vector<string> nvec;
194         std::copy(bstore.begin(), bstore.end(),
195                   lyx::back_inserter_fun(nvec, &Buffer::fileName));
196         return nvec;
197 }
198
199
200 Buffer * BufferList::first()
201 {
202         if (bstore.empty())
203                 return 0;
204         return bstore.front();
205 }
206
207
208 Buffer * BufferList::getBuffer(unsigned int choice)
209 {
210         if (choice >= bstore.size())
211                 return 0;
212         return bstore[choice];
213 }
214
215
216 void BufferList::updateIncludedTeXfiles(string const & mastertmpdir,
217                                         LatexRunParams const & runparams)
218 {
219         BufferStorage::iterator it = bstore.begin();
220         BufferStorage::iterator end = bstore.end();
221         for (; it != end; ++it) {
222                 if (!(*it)->isDepClean(mastertmpdir)) {
223                         string writefile = mastertmpdir;
224                         writefile += '/';
225                         writefile += (*it)->getLatexName();
226                         (*it)->makeLaTeXFile(writefile, mastertmpdir,
227                                              runparams, false);
228                         (*it)->markDepClean(mastertmpdir);
229                 }
230         }
231 }
232
233
234 void BufferList::emergencyWriteAll()
235 {
236         for_each(bstore.begin(), bstore.end(),
237                  boost::bind(&BufferList::emergencyWrite, this, _1));
238 }
239
240
241 void BufferList::emergencyWrite(Buffer * buf)
242 {
243         // assert(buf) // this is not good since C assert takes an int
244                        // and a pointer is a long (JMarc)
245         assert(buf != 0); // use c assert to avoid a loop
246
247
248         // No need to save if the buffer has not changed.
249         if (buf->isClean())
250                 return;
251
252         string const doc = buf->isUnnamed()
253                 ? OnlyFilename(buf->fileName()) : buf->fileName();
254
255         lyxerr << bformat(_("LyX: Attempting to save document %1$s"), doc) << endl;
256
257         // We try to save three places:
258         // 1) Same place as document. Unless it is an unnamed doc.
259         if (!buf->isUnnamed()) {
260                 string s = buf->fileName();
261                 s += ".emergency";
262                 lyxerr << "  " << s << endl;
263                 if (buf->writeFile(s)) {
264                         buf->markClean();
265                         lyxerr << _("  Save seems successful. Phew.") << endl;
266                         return;
267                 } else {
268                         lyxerr << _("  Save failed! Trying...") << endl;
269                 }
270         }
271
272         // 2) In HOME directory.
273         string s = AddName(GetEnvPath("HOME"), buf->fileName());
274         s += ".emergency";
275         lyxerr << ' ' << s << endl;
276         if (buf->writeFile(s)) {
277                 buf->markClean();
278                 lyxerr << _("  Save seems successful. Phew.") << endl;
279                 return;
280         }
281
282         lyxerr << _("  Save failed! Trying...") << endl;
283
284         // 3) In "/tmp" directory.
285         // MakeAbsPath to prepend the current
286         // drive letter on OS/2
287         s = AddName(MakeAbsPath("/tmp/"), buf->fileName());
288         s += ".emergency";
289         lyxerr << ' ' << s << endl;
290         if (buf->writeFile(s)) {
291                 buf->markClean();
292                 lyxerr << _("  Save seems successful. Phew.") << endl;
293                 return;
294         }
295         lyxerr << _("  Save failed! Bummer. Document is lost.") << endl;
296 }
297
298
299 bool BufferList::exists(string const & s) const
300 {
301         return find_if(bstore.begin(), bstore.end(),
302                        lyx::compare_memfun(&Buffer::fileName, s))
303                 != bstore.end();
304 }
305
306
307 bool BufferList::isLoaded(Buffer const * b) const
308 {
309         BOOST_ASSERT(b);
310         BufferStorage::const_iterator cit =
311                 find(bstore.begin(), bstore.end(), b);
312         return cit != bstore.end();
313 }
314
315
316 Buffer * BufferList::getBuffer(string const & s)
317 {
318         BufferStorage::iterator it =
319                 find_if(bstore.begin(), bstore.end(),
320                         lyx::compare_memfun(&Buffer::fileName, s));
321         return it != bstore.end() ? (*it) : 0;
322 }
323
324
325 Buffer * BufferList::getBufferFromTmp(string const & s)
326 {
327         BufferStorage::iterator it = bstore.begin();
328         BufferStorage::iterator end = bstore.end();
329         for (; it < end; ++it)
330                 if (prefixIs(s, (*it)->temppath()))
331                         return *it;
332         return 0;
333 }
334
335
336 void BufferList::setCurrentAuthor(string const & name, string const & email)
337 {
338         BufferStorage::iterator it = bstore.begin();
339         BufferStorage::iterator end = bstore.end();
340         for (; it != end; ++it) {
341                 (*it)->params().authors().record(0, Author(name, email));
342         }
343 }