]> git.lyx.org Git - lyx.git/blob - src/Session.cpp
Re-engineer the toolbar support code:
[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 BookmarksSection::Bookmark const & BookmarksSection::bookmark(unsigned int i) const
289 {
290         return bookmarks[i];
291 }
292
293
294 void SessionInfoSection::read(istream & is)
295 {
296         string tmp;
297         do {
298                 char c = is.peek();
299                 if (c == '[')
300                         break;
301                 getline(is, tmp);
302                 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ')
303                         continue;
304
305                 try {
306                         // Read session info, saved as key/value pairs
307                         // would better yell if pos returns npos
308                         string::size_type pos = tmp.find_first_of(" = ");
309                         // silently ignore lines without " = "
310                         if (pos != string::npos) {
311                                 string key = tmp.substr(0, pos);
312                                 string value = tmp.substr(pos + 3);
313                                 sessioninfo[key] = value;
314                         } else
315                                 LYXERR(Debug::INIT, "LyX: Warning: Ignore session info: " << tmp);
316                 } catch (...) {
317                         LYXERR(Debug::INIT, "LyX: Warning: unknown Session info: " << tmp);
318                 }
319         } while (is.good());
320 }
321
322
323 void SessionInfoSection::write(ostream & os) const
324 {
325         os << '\n' << sec_session << '\n';
326         for (MiscInfo::const_iterator val = sessioninfo.begin();
327                 val != sessioninfo.end(); ++val) {
328                 os << val->first << " = " << val->second << '\n';
329         }
330 }
331
332
333 void SessionInfoSection::save(string const & key, string const & value)
334 {
335         sessioninfo[key] = value;
336 }
337
338
339 string const SessionInfoSection::load(string const & key, bool release)
340 {
341         MiscInfo::const_iterator pos = sessioninfo.find(key);
342         string value;
343         if (pos != sessioninfo.end())
344                 value = pos->second;
345         if (release)
346                 sessioninfo.erase(key);
347         return value;
348 }
349
350
351 Session::Session(unsigned int num) :
352         last_files(num)
353 {
354         // locate the session file
355         // note that the session file name 'session' is hard-coded
356         session_file = FileName(addName(package().user_support().absFilename(), "session"));
357         //
358         readFile();
359 }
360
361
362 void Session::readFile()
363 {
364         // we will not complain if we can't find session_file nor will
365         // we issue a warning. (Lgb)
366         ifstream is(session_file.toFilesystemEncoding().c_str());
367         string tmp;
368
369         while (getline(is, tmp)) {
370                 // Ignore comments, empty line or line stats with ' '
371                 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ')
372                         continue;
373
374                 // Determine section id
375                 if (tmp == sec_lastfiles)
376                         lastFiles().read(is);
377                 else if (tmp == sec_lastopened)
378                         lastOpened().read(is);
379                 else if (tmp == sec_lastfilepos)
380                         lastFilePos().read(is);
381                 else if (tmp == sec_bookmarks)
382                         bookmarks().read(is);
383                 else if (tmp == sec_session)
384                         sessionInfo().read(is);
385                 else
386                         LYXERR(Debug::INIT, "LyX: Warning: unknown Session section: " << tmp);
387         }
388 }
389
390
391 void Session::writeFile() const
392 {
393         ofstream os(session_file.toFilesystemEncoding().c_str());
394         if (os) {
395                 os << "## Automatically generated lyx session file \n"
396                     << "## Editing this file manually may cause lyx to crash.\n";
397
398                 lastFiles().write(os);
399                 lastOpened().write(os);
400                 lastFilePos().write(os);
401                 bookmarks().write(os);
402                 sessionInfo().write(os);
403         } else
404                 LYXERR(Debug::INIT, "LyX: Warning: unable to save Session: "
405                        << session_file);
406 }
407
408 }