]> git.lyx.org Git - lyx.git/blob - src/buffer_funcs.C
Implement os::current_root for native Win32 builds.
[lyx.git] / src / buffer_funcs.C
1 /**
2  * \file buffer_funcs.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  * \author Alfredo Braunstein
8  *
9  * Full author contact details are available in file CREDITS.
10  *
11  */
12
13 #include <config.h>
14
15 #include "buffer_funcs.h"
16
17 #include "buffer.h"
18 #include "bufferlist.h"
19 #include "bufferparams.h"
20 #include "dociterator.h"
21 #include "errorlist.h"
22 #include "gettext.h"
23 #include "LaTeX.h"
24 #include "paragraph.h"
25 #include "lyxvc.h"
26 #include "texrow.h"
27 #include "vc-backend.h"
28
29 #include "frontends/Alert.h"
30
31 #include "support/FileInfo.h"
32 #include "support/filetools.h"
33 #include "support/lyxlib.h"
34
35 #include <boost/bind.hpp>
36
37 using lyx::support::bformat;
38 using lyx::support::FileInfo;
39 using lyx::support::IsFileWriteable;
40 using lyx::support::LibFileSearch;
41 using lyx::support::MakeDisplayPath;
42 using lyx::support::OnlyFilename;
43 using lyx::support::OnlyPath;
44 using lyx::support::unlink;
45
46 using std::string;
47
48
49 extern BufferList bufferlist;
50
51 namespace {
52
53 bool readFile(Buffer * b, string const & s)
54 {
55         // File information about normal file
56         FileInfo fileN(s);
57         if (!fileN.exist()) {
58                 string const file = MakeDisplayPath(s, 50);
59                 string text = bformat(_("The specified document\n%1$s"
60                                         "\ncould not be read."), file);
61                 Alert::error(_("Could not read document"), text);
62                 return false;
63         }
64
65         // Check if emergency save file exists and is newer.
66         string const e = OnlyPath(s) + OnlyFilename(s) + ".emergency";
67         FileInfo fileE(e);
68
69         if (fileE.exist() && fileN.exist()
70             && fileE.getModificationTime() > fileN.getModificationTime())
71         {
72                 string const file = MakeDisplayPath(s, 20);
73                 string text = bformat(_("An emergency save of the document "
74                                         "%1$s exists.\n\n"
75                                         "Recover emergency save?"), file);
76                 switch (Alert::prompt(_("Load emergency save?"), text, 0, 2,
77                                       _("&Recover"),  _("&Load Original"),
78                                       _("&Cancel")))
79                 {
80                 case 0:
81                         // the file is not saved if we load the emergency file.
82                         b->markDirty();
83                         return b->readFile(e);
84                 case 1:
85                         break;
86                 default:
87                         return false;
88                 }
89         }
90
91         // Now check if autosave file is newer.
92         string const a = OnlyPath(s) + '#' + OnlyFilename(s) + '#';
93         FileInfo fileA(a);
94
95         if (fileA.exist() && fileN.exist()
96             && fileA.getModificationTime() > fileN.getModificationTime())
97         {
98                 string const file = MakeDisplayPath(s, 20);
99                 string text = bformat(_("The backup of the document "
100                                         "%1$s is newer.\n\nLoad the "
101                                         "backup instead?"), file);
102                 switch (Alert::prompt(_("Load backup?"), text, 0, 2,
103                                       _("&Load backup"), _("Load &original"),
104                                       _("&Cancel") ))
105                 {
106                 case 0:
107                         // the file is not saved if we load the autosave file.
108                         b->markDirty();
109                         return b->readFile(a);
110                 case 1:
111                         // Here we delete the autosave
112                         unlink(a);
113                         break;
114                 default:
115                         return false;
116                 }
117         }
118         return b->readFile(s);
119 }
120
121
122 } // namespace anon
123
124
125
126 bool loadLyXFile(Buffer * b, string const & s)
127 {
128         switch (IsFileWriteable(s)) {
129         case 0:
130                 b->setReadonly(true);
131                 // Fall through
132         case 1:
133                 if (readFile(b, s)) {
134                         b->lyxvc().file_found_hook(s);
135                         return true;
136                 }
137                 break;
138         case -1:
139                 string const file = MakeDisplayPath(s, 20);
140                 // Here we probably should run
141                 if (LyXVC::file_not_found_hook(s)) {
142                         string text = bformat(_("Do you want to retrieve the document"
143                                 " %1$s from version control?"), file);
144                         int const ret = Alert::prompt(_("Retrieve from version control?"),
145                                 text, 0, 1, _("&Retrieve"), _("&Cancel"));
146
147                         if (ret == 0) {
148                                 // How can we know _how_ to do the checkout?
149                                 // With the current VC support it has to be,
150                                 // a RCS file since CVS do not have special ,v files.
151                                 RCS::retrieve(s);
152                                 return loadLyXFile(b, s);
153                         }
154                 }
155                 break;
156         }
157         return false;
158 }
159
160
161 Buffer * newFile(string const & filename, string const & templatename,
162                  bool isNamed)
163 {
164         // get a free buffer
165         Buffer * b = bufferlist.newBuffer(filename);
166
167         string tname;
168         // use defaults.lyx as a default template if it exists.
169         if (templatename.empty())
170                 tname = LibFileSearch("templates", "defaults.lyx");
171         else
172                 tname = templatename;
173
174         if (!tname.empty()) {
175                 if (!b->readFile(tname)) {
176                         string const file = MakeDisplayPath(tname, 50);
177                         string const text  = bformat(_("The specified document template\n%1$s\ncould not be read."), file);
178                         Alert::error(_("Could not read template"), text);
179                         // no template, start with empty buffer
180                 }
181         }
182
183         if (!isNamed) {
184                 b->setUnnamed();
185                 b->setFileName(filename);
186         }
187
188         b->setReadonly(false);
189         b->fully_loaded(true);
190         b->updateDocLang(b->params().language);
191
192         return b;
193 }
194
195
196 void bufferErrors(Buffer const & buf, TeXErrors const & terr)
197 {
198         TeXErrors::Errors::const_iterator cit = terr.begin();
199         TeXErrors::Errors::const_iterator end = terr.end();
200
201         for (; cit != end; ++cit) {
202                 int par_id = -1;
203                 int posstart = -1;
204                 int const errorrow = cit->error_in_line;
205                 buf.texrow().getIdFromRow(errorrow, par_id, posstart);
206                 int posend = -1;
207                 buf.texrow().getIdFromRow(errorrow + 1, par_id, posend);
208                 buf.error(ErrorItem(cit->error_desc,
209                                          cit->error_text,
210                                          par_id, posstart, posend));
211         }
212 }
213
214
215 void bufferErrors(Buffer const & buf, ErrorList const & el)
216 {
217         for_each(el.begin(), el.end(), bind(ref(buf.error), _1));
218 }
219
220
221 string const BufferFormat(Buffer const & buffer)
222 {
223         if (buffer.isLinuxDoc())
224                 return "linuxdoc";
225         else if (buffer.isDocBook())
226                 return "docbook";
227         else if (buffer.isLiterate())
228                 return "literate";
229         else
230                 return "latex";
231 }
232
233
234 int countWords(DocIterator const & from, DocIterator const & to)
235 {
236         int count = 0;
237         bool inword = false;
238         for (DocIterator dit = from ; dit != to ; dit.forwardPos()) {
239                 // Copied and adapted from isLetter() in ControlSpellChecker
240                 if (dit.inTexted()
241                     && dit.pos() != dit.lastpos()
242                     && dit.paragraph().isLetter(dit.pos())
243                     && !isDeletedText(dit.paragraph(), dit.pos())) {
244                         if (!inword) {
245                                 ++count;
246                                 inword = true;
247                         }
248                 } else if (inword)
249                         inword = false;
250         }
251
252         return count;
253 }
254