]> git.lyx.org Git - lyx.git/blob - src/Session.cpp
Correct enabling of the "Navigate->Bookmarks->Clear Bookmarks" menu item.
[lyx.git] / src / Session.cpp
1 /**
2  * \file Session.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  * \author Bo Peng
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "Session.h"
15
16 #include "support/debug.h"
17 #include "support/filetools.h"
18 #include "support/Package.h"
19
20 #include <fstream>
21 #include <sstream>
22 #include <algorithm>
23 #include <iterator>
24
25 using namespace std;
26 using namespace lyx::support;
27
28 namespace {
29
30 string const sec_lastfiles = "[recent files]";
31 string const sec_lastfilepos = "[cursor positions]";
32 string const sec_lastopened = "[last opened files]";
33 string const sec_bookmarks = "[bookmarks]";
34 string const sec_session = "[session info]";
35 string const sec_toolbars = "[toolbars]";
36
37 } // anon namespace
38
39
40 namespace lyx {
41
42
43 LastFilesSection::LastFilesSection(unsigned int num) :
44         default_num_last_files(4),
45         absolute_max_last_files(100)
46 {
47         setNumberOfLastFiles(num);
48 }
49
50
51 void LastFilesSection::read(istream & is)
52 {
53         string tmp;
54         do {
55                 char c = is.peek();
56                 if (c == '[')
57                         break;
58                 getline(is, tmp);
59                 FileName const file(tmp);
60                 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ' || !file.isAbsolute())
61                         continue;
62
63                 // read lastfiles
64                 if (file.exists() && !file.isDirectory()
65                     && lastfiles.size() < num_lastfiles)
66                         lastfiles.push_back(file);
67                 else
68                         LYXERR(Debug::INIT, "LyX: Warning: Ignore last file: " << tmp);
69         } while (is.good());
70 }
71
72
73 void LastFilesSection::write(ostream & os) const
74 {
75         os << '\n' << sec_lastfiles << '\n';
76         copy(lastfiles.begin(), lastfiles.end(),
77              ostream_iterator<FileName>(os, "\n"));
78 }
79
80
81 void LastFilesSection::add(FileName const & file)
82 {
83         // If file already exist, delete it and reinsert at front.
84         LastFiles::iterator it = find(lastfiles.begin(), lastfiles.end(), file);
85         if (it != lastfiles.end())
86                 lastfiles.erase(it);
87         lastfiles.push_front(file);
88         if (lastfiles.size() > num_lastfiles)
89                 lastfiles.pop_back();
90 }
91
92
93 void LastFilesSection::setNumberOfLastFiles(unsigned int no)
94 {
95         if (0 < no && no <= absolute_max_last_files)
96                 num_lastfiles = no;
97         else {
98                 LYXERR(Debug::INIT, "LyX: session: too many last files\n"
99                         << "\tdefault (=" << default_num_last_files << ") used.");
100                 num_lastfiles = default_num_last_files;
101         }
102 }
103
104
105 void LastOpenedSection::read(istream & is)
106 {
107         string tmp;
108         do {
109                 char c = is.peek();
110                 if (c == '[')
111                         break;
112                 getline(is, tmp);
113                 FileName const file(tmp);
114                 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ' || !file.isAbsolute())
115                         continue;
116
117                 if (file.exists() && !file.isDirectory())
118                         lastopened.push_back(file);
119                 else
120                         LYXERR(Debug::INIT, "LyX: Warning: Ignore last opened file: " << tmp);
121         } while (is.good());
122 }
123
124
125 void LastOpenedSection::write(ostream & os) const
126 {
127         os << '\n' << sec_lastopened << '\n';
128         copy(lastopened.begin(), lastopened.end(),
129              ostream_iterator<FileName>(os, "\n"));
130 }
131
132
133 void LastOpenedSection::add(FileName const & file)
134 {
135         lastopened.push_back(file);
136 }
137
138
139 void LastOpenedSection::clear()
140 {
141         lastopened.clear();
142 }
143
144
145 void LastFilePosSection::read(istream & is)
146 {
147         string tmp;
148         do {
149                 char c = is.peek();
150                 if (c == '[')
151                         break;
152                 getline(is, tmp);
153                 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ')
154                         continue;
155
156                 try {
157                         // read lastfilepos
158                         // pos, file\n
159                         FilePos filepos;
160                         string fname;
161                         istringstream itmp(tmp);
162                         itmp >> filepos.pit;
163                         itmp.ignore(2);  // ignore ", "
164                         itmp >> filepos.pos;
165                         itmp.ignore(2);  // ignore ", "
166                         getline(itmp, fname);
167                         FileName const file(fname);
168                         if (!file.isAbsolute())
169                                 continue;
170                         if (file.exists() && !file.isDirectory()
171                             && lastfilepos.size() < num_lastfilepos)
172                                 lastfilepos[file] = filepos;
173                         else
174                                 LYXERR(Debug::INIT, "LyX: Warning: Ignore pos of last file: " << fname);
175                 } catch (...) {
176                         LYXERR(Debug::INIT, "LyX: Warning: unknown pos of last file: " << tmp);
177                 }
178         } while (is.good());
179 }
180
181
182 void LastFilePosSection::write(ostream & os) const
183 {
184         os << '\n' << sec_lastfilepos << '\n';
185         for (FilePosMap::const_iterator file = lastfilepos.begin();
186                 file != lastfilepos.end(); ++file) {
187                 os << file->second.pit << ", " << file->second.pos << ", "
188                    << file->first << '\n';
189         }
190 }
191
192
193 void LastFilePosSection::save(FileName const & fname, FilePos const & pos)
194 {
195         lastfilepos[fname] = pos;
196 }
197
198
199 LastFilePosSection::FilePos LastFilePosSection::load(FileName const & fname) const
200 {
201         FilePosMap::const_iterator entry = lastfilepos.find(fname);
202         // Has position information, return it.
203         if (entry != lastfilepos.end())
204                 return entry->second;
205         // Not found, return the first paragraph
206         return FilePos();
207 }
208
209
210 void BookmarksSection::clear()
211 {
212         // keep bookmark[0], the temporary one
213         bookmarks.resize(1);
214         bookmarks.resize(max_bookmarks + 1);
215 }
216
217
218 void BookmarksSection::read(istream & is)
219 {
220         string tmp;
221         do {
222                 char c = is.peek();
223                 if (c == '[')
224                         break;
225                 getline(is, tmp);
226                 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ')
227                         continue;
228
229                 try {
230                         // read bookmarks
231                         // idx, pit, pos, file\n
232                         unsigned int idx;
233                         pit_type pit;
234                         pos_type pos;
235                         string fname;
236                         istringstream itmp(tmp);
237                         itmp >> idx;
238                         itmp.ignore(2);  // ignore ", "
239                         itmp >> pit;
240                         itmp.ignore(2);  // ignore ", "
241                         itmp >> pos;
242                         itmp.ignore(2);  // ignore ", "
243                         getline(itmp, fname);
244                         FileName const file(fname);
245                         if (!file.isAbsolute())
246                                 continue;
247                         // only load valid bookmarks
248                         if (file.exists() && !file.isDirectory() && idx <= max_bookmarks)
249                                 bookmarks[idx] = Bookmark(file, pit, pos, 0, 0);
250                         else
251                                 LYXERR(Debug::INIT, "LyX: Warning: Ignore bookmark of file: " << fname);
252                 } catch (...) {
253                         LYXERR(Debug::INIT, "LyX: Warning: unknown Bookmark info: " << tmp);
254                 }
255         } while (is.good());
256 }
257
258
259 void BookmarksSection::write(ostream & os) const
260 {
261         os << '\n' << sec_bookmarks << '\n';
262         for (size_t i = 1; i <= max_bookmarks; ++i) {
263                 if (isValid(i))
264                         os << i << ", "
265                            << bookmarks[i].bottom_pit << ", "
266                            << bookmarks[i].bottom_pos << ", "
267                            << bookmarks[i].filename << '\n';
268         }
269 }
270
271
272 void BookmarksSection::save(FileName const & fname,
273         pit_type bottom_pit, pos_type bottom_pos,
274         int top_id, pos_type top_pos, unsigned int idx)
275 {
276         // silently ignore bookmarks when idx is out of range
277         if (idx <= max_bookmarks)
278                 bookmarks[idx] = Bookmark(fname, bottom_pit, bottom_pos, top_id, top_pos);
279 }
280
281
282 bool BookmarksSection::isValid(unsigned int i) const
283 {
284         return i <= max_bookmarks && !bookmarks[i].filename.empty();
285 }
286
287
288 bool BookmarksSection::hasValid() const
289 {
290         for (size_t i = 1; i <= size(); ++i) {
291                 if (isValid(i))
292                         return true;
293         }
294         return false;
295 }
296
297
298 BookmarksSection::Bookmark const & BookmarksSection::bookmark(unsigned int i) const
299 {
300         return bookmarks[i];
301 }
302
303
304 Session::Session(unsigned int num) :
305         last_files(num)
306 {
307         // locate the session file
308         // note that the session file name 'session' is hard-coded
309         session_file = FileName(addName(package().user_support().absFilename(), "session"));
310         //
311         readFile();
312 }
313
314
315 void Session::readFile()
316 {
317         // we will not complain if we can't find session_file nor will
318         // we issue a warning. (Lgb)
319         ifstream is(session_file.toFilesystemEncoding().c_str());
320         string tmp;
321
322         while (getline(is, tmp)) {
323                 // Ignore comments, empty line or line stats with ' '
324                 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ')
325                         continue;
326
327                 // Determine section id
328                 if (tmp == sec_lastfiles)
329                         lastFiles().read(is);
330                 else if (tmp == sec_lastopened)
331                         lastOpened().read(is);
332                 else if (tmp == sec_lastfilepos)
333                         lastFilePos().read(is);
334                 else if (tmp == sec_bookmarks)
335                         bookmarks().read(is);
336                 else
337                         LYXERR(Debug::INIT, "LyX: Warning: unknown Session section: " << tmp);
338         }
339 }
340
341
342 void Session::writeFile() const
343 {
344         ofstream os(session_file.toFilesystemEncoding().c_str());
345         if (os) {
346                 os << "## Automatically generated lyx session file \n"
347                     << "## Editing this file manually may cause lyx to crash.\n";
348
349                 lastFiles().write(os);
350                 lastOpened().write(os);
351                 lastFilePos().write(os);
352                 bookmarks().write(os);
353         } else
354                 LYXERR(Debug::INIT, "LyX: Warning: unable to save Session: "
355                        << session_file);
356 }
357
358 }