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