3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
9 * Full author contact details are available in file CREDITS.
16 #include "support/package.h"
17 #include "support/filetools.h"
19 #include <boost/filesystem/operations.hpp>
26 using lyx::support::addName;
27 using lyx::support::package;
29 namespace fs = boost::filesystem;
39 using std::istringstream;
42 using std::ostream_iterator;
46 string const sec_lastfiles = "[recent files]";
47 string const sec_lastfilepos = "[cursor positions]";
48 string const sec_lastopened = "[last opened files]";
49 string const sec_bookmarks = "[bookmarks]";
50 string const sec_session = "[session info]";
51 string const sec_toolbars = "[toolbars]";
58 LastFilesSection::LastFilesSection(unsigned int num) :
59 default_num_last_files(4),
60 absolute_max_last_files(100)
62 setNumberOfLastFiles(num);
66 void LastFilesSection::read(istream & is)
74 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ')
78 if (fs::exists(tmp) && !fs::is_directory(tmp) && lastfiles.size() < num_lastfiles)
79 lastfiles.push_back(tmp);
81 lyxerr << "LyX: Warning: Ignore last file: " << tmp << endl;
86 void LastFilesSection::write(ostream & os) const
88 os << '\n' << sec_lastfiles << '\n';
89 copy(lastfiles.begin(), lastfiles.end(),
90 ostream_iterator<string>(os, "\n"));
94 void LastFilesSection::add(string const & file)
96 // If file already exist, delete it and reinsert at front.
97 LastFiles::iterator it = find(lastfiles.begin(), lastfiles.end(), file);
98 if (it != lastfiles.end())
100 lastfiles.push_front(file);
101 if (lastfiles.size() > num_lastfiles)
102 lastfiles.pop_back();
106 void LastFilesSection::setNumberOfLastFiles(unsigned int no)
108 if (0 < no && no <= absolute_max_last_files)
111 lyxerr << "LyX: session: too many last files\n"
112 << "\tdefault (=" << default_num_last_files
113 << ") used." << endl;
114 num_lastfiles = default_num_last_files;
119 void LastOpenedSection::read(istream & is)
127 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ')
130 if (fs::exists(tmp) && !fs::is_directory(tmp))
131 lastopened.push_back(tmp);
133 lyxerr << "LyX: Warning: Ignore last opened file: " << tmp << endl;
138 void LastOpenedSection::write(ostream & os) const
140 os << '\n' << sec_lastopened << '\n';
141 copy(lastopened.begin(), lastopened.end(),
142 ostream_iterator<string>(os, "\n"));
146 void LastOpenedSection::add(string const & file)
148 lastopened.push_back(file);
152 void LastOpenedSection::clear()
158 void LastFilePosSection::read(istream & is)
166 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ')
175 istringstream itmp(tmp);
177 itmp.ignore(2); // ignore ", "
179 itmp.ignore(2); // ignore ", "
181 if (fs::exists(fname) && !fs::is_directory(fname) && lastfilepos.size() < num_lastfilepos)
182 lastfilepos[fname] = boost::tie(pit, pos);
184 lyxerr << "LyX: Warning: Ignore pos of last file: " << fname << endl;
186 lyxerr << "LyX: Warning: unknown pos of last file: " << tmp << endl;
192 void LastFilePosSection::write(ostream & os) const
194 os << '\n' << sec_lastfilepos << '\n';
195 for (FilePosMap::const_iterator file = lastfilepos.begin();
196 file != lastfilepos.end(); ++file) {
197 os << file->second.get<0>() << ", "
198 << file->second.get<1>() << ", "
199 << file->first << '\n';
204 void LastFilePosSection::save(string const & fname, FilePos pos)
206 lastfilepos[fname] = pos;
210 LastFilePosSection::FilePos LastFilePosSection::load(string const & fname) const
212 FilePosMap::const_iterator entry = lastfilepos.find(fname);
213 // Has position information, return it.
214 if (entry != lastfilepos.end())
215 return entry->second;
216 // Not found, return the first paragraph
222 void BookmarksSection::read(istream & is)
230 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ')
239 istringstream itmp(tmp);
241 itmp.ignore(2); // ignore ", "
243 itmp.ignore(2); // ignore ", "
245 // only load valid bookmarks
246 if (fs::exists(fname) && !fs::is_directory(fname) && bookmarks.size() < max_bookmarks)
247 bookmarks.push_back(Bookmark(fname, id, pos));
249 lyxerr << "LyX: Warning: Ignore bookmark of file: " << fname << endl;
251 lyxerr << "LyX: Warning: unknown Bookmark info: " << tmp << endl;
257 void BookmarksSection::write(ostream & os) const
259 os << '\n' << sec_bookmarks << '\n';
260 for (size_t i = 0; i < bookmarks.size(); ++i) {
261 os << bookmarks[i].par_id << ", "
262 << bookmarks[i].par_pos << ", "
263 << bookmarks[i].filename << '\n';
268 void BookmarksSection::save(std::string const & fname, int par_id, pos_type par_pos, bool persistent)
271 bookmarks.push_front(Bookmark(fname, par_id, par_pos));
272 if (bookmarks.size() > max_bookmarks)
273 bookmarks.pop_back();
276 temp_bookmark = Bookmark(fname, par_id, par_pos);
280 bool BookmarksSection::isValid(unsigned int i) const
282 // i == 0, or in the queue
283 return i <= bookmarks.size();
287 BookmarksSection::Bookmark const & BookmarksSection::bookmark(unsigned int i) const
290 return temp_bookmark;
292 return bookmarks[i-1];
296 void ToolbarSection::read(istream & is)
304 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ')
308 // Read session info, saved as key/value pairs
309 // would better yell if pos returns npos
310 string::size_type pos = tmp.find_first_of(" = ");
311 // silently ignore lines without " = "
312 if (pos != string::npos) {
313 string key = tmp.substr(0, pos);
316 istringstream value(tmp.substr(pos + 3));
318 value.ignore(1); // ignore " "
320 toolbars[key] = ToolbarInfo(state, location);
322 lyxerr << "LyX: Warning: Ignore toolbar info: " << tmp << endl;
324 lyxerr << "LyX: Warning: unknown Toolbar info: " << tmp << endl;
330 void ToolbarSection::write(ostream & os) const
332 os << '\n' << sec_toolbars << '\n';
333 for (ToolbarMap::const_iterator tb = toolbars.begin();
334 tb != toolbars.end(); ++tb) {
335 os << tb->first << " = "
336 << static_cast<int>(tb->second.state) << " "
337 << static_cast<int>(tb->second.location) << '\n';
342 ToolbarSection::ToolbarInfo & ToolbarSection::load(string const & name)
344 return toolbars[name];
348 void SessionInfoSection::read(istream & is)
356 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ')
360 // Read session info, saved as key/value pairs
361 // would better yell if pos returns npos
362 string::size_type pos = tmp.find_first_of(" = ");
363 // silently ignore lines without " = "
364 if (pos != string::npos) {
365 string key = tmp.substr(0, pos);
366 string value = tmp.substr(pos + 3);
367 sessioninfo[key] = value;
369 lyxerr << "LyX: Warning: Ignore session info: " << tmp << endl;
371 lyxerr << "LyX: Warning: unknown Session info: " << tmp << endl;
377 void SessionInfoSection::write(ostream & os) const
379 os << '\n' << sec_session << '\n';
380 for (MiscInfo::const_iterator val = sessioninfo.begin();
381 val != sessioninfo.end(); ++val) {
382 os << val->first << " = " << val->second << '\n';
387 void SessionInfoSection::save(string const & key, string const & value)
389 sessioninfo[key] = value;
393 string const SessionInfoSection::load(string const & key, bool release)
395 MiscInfo::const_iterator pos = sessioninfo.find(key);
397 if (pos != sessioninfo.end())
400 sessioninfo.erase(key);
405 Session::Session(unsigned int num) :
408 // locate the session file
409 // note that the session file name 'session' is hard-coded
410 session_file = addName(package().user_support(), "session");
416 void Session::readFile()
418 // we will not complain if we can't find session_file nor will
419 // we issue a warning. (Lgb)
420 ifstream is(session_file.c_str());
423 while (getline(is, tmp)) {
424 // Ignore comments, empty line or line stats with ' '
425 if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ')
428 // Determine section id
429 if (tmp == sec_lastfiles)
430 lastFiles().read(is);
431 else if (tmp == sec_lastopened)
432 lastOpened().read(is);
433 else if (tmp == sec_lastfilepos)
434 lastFilePos().read(is);
435 else if (tmp == sec_bookmarks)
436 bookmarks().read(is);
437 else if (tmp == sec_toolbars)
439 else if (tmp == sec_session)
440 sessionInfo().read(is);
442 lyxerr << "LyX: Warning: unknown Session section: " << tmp << endl;
447 void Session::writeFile() const
449 ofstream os(session_file.c_str());
451 os << "## Automatically generated lyx session file \n"
452 << "## Editing this file manually may cause lyx to crash.\n";
454 lastFiles().write(os);
455 lastOpened().write(os);
456 lastFilePos().write(os);
457 bookmarks().write(os);
458 toolbars().write(os);
459 sessionInfo().write(os);
461 lyxerr << "LyX: Warning: unable to save Session: "
462 << session_file << endl;