Dear list, It does not look so difficult to implement this feature so I tried to implement it by myself. Attached is my patch. Since I rarely submit a patch here so I am afraid that there might be many problems (format, logic, bugs). Please have a look and give me some feedbacks.
Many files have been modified: src/BufferView_pimpl.C When a new buffer is loaded, it tries to get last cursor position from ref().lastfiles(). When a file is going to be closed, current location is saved as bookmark 0, and to ref().lastfiles(). A side effect of this is that a file can be re-opened (and to the same location) from bookmark 0. src/lastfiles.C: I do not want to change the Files structure so I use a map to store position information. lastfile format is changed to "<id, pos> filename" if position information is available, and "filename" if not. The biggest changes are to read/write lastfile. I hope that I have not broken anything here. src/lyxfunc.C: save cursor position when the buffer is closed. lib/ui/stdmenus.ui: add a menu item with an awkard name. I am worrying about two problem though: 1. Will invalid paragraph id, pos crash lyx? I mean, if a file is saved (with id, pos saved locally), and is modified externally (get a revised copy from others), id, pos will no longer be valid and "goto bookmark 0" will fail. 2. Save position does not seem to work when I quit lyx by closing the lyx window. Only close-buffer will do. Where should I handle the close event? 3. Is saved_positions[0] really unused? Cheers, Bo
Index: src/BufferView_pimpl.C =================================================================== --- src/BufferView_pimpl.C (revision 13455) +++ src/BufferView_pimpl.C (working copy) @@ -293,6 +293,14 @@ setBuffer(b); bv_->showErrorList(_("Parse")); + + // load position when the file was last closed + int id; + lyx::pos_type pos; + LyX::ref().lastfiles().loadFilePosition(s, id, pos); + // if id is valid ... + if( id >= 0 ) + saved_positions[0] = Position(s, id, pos); if (tolastfiles) LyX::ref().lastfiles().newFile(b->fileName()); @@ -767,7 +775,14 @@ saved_positions[i] = Position(buffer_->fileName(), cursor_.paragraph().id(), cursor_.pos()); - if (i > 0) + // if i == 0, (called when this buffer is closed), + // save current position to lastfile + if (i == 0) { + LyX::ref().lastfiles().saveFilePosition(buffer_->fileName(), + cursor_.paragraph().id(), + cursor_.pos()); + } + else owner_->message(bformat(_("Saved bookmark %1$d"), i)); } Index: src/lastfiles.C =================================================================== --- src/lastfiles.C (revision 13455) +++ src/lastfiles.C (working copy) @@ -19,6 +19,11 @@ #include <fstream> #include <iterator> +// file_pos is a map to save position of cursor when a file is closed. +#include <map> +#include <sstream> +#include <utility> + namespace fs = boost::filesystem; using std::copy; @@ -26,10 +31,16 @@ using std::find; using std::getline; using std::string; +using std::map; +using std::pair; using std::ifstream; using std::ofstream; using std::ostream_iterator; +// store file position information to a map to avoid changing the +// dequeue structure Files +typedef map<string, pair<int, lyx::pos_type> > file_pos; +file_pos filePositions; LastFiles::LastFiles(string const & filename, bool st, unsigned int num) : dostat(st) @@ -60,6 +71,22 @@ string tmp; while (getline(ifs, tmp) && files.size() < num_files) { + // <id, position> filename\n + if (tmp[0] == '<' && tmp.find('>', 1) != string::npos ) { + std::istringstream itmp(tmp); + string fname; + int id; + lyx::pos_type pos; + itmp.ignore(1); // ignore '<' + itmp >> id; + itmp.ignore(2); // ignore ", " + itmp >> pos; + itmp.ignore(2); // ingore '> ' + itmp >> fname; + filePositions[fname] = pair<int, lyx::pos_type>(id, pos); + tmp = fname; + } + // the last part of "<> file" or or lines without <>. if (dostat && !fs::exists(tmp)) continue; files.push_back(tmp); @@ -71,8 +98,18 @@ { ofstream ofs(filename.c_str()); if (ofs) { - copy(files.begin(), files.end(), - ostream_iterator<string>(ofs, "\n")); + for (const_iterator file=files.begin(); file != files.end(); ++file) { + // has position information, save in the format of + // <id, pos> filename + file_pos::iterator entry = filePositions.find(*file); + if (entry != filePositions.end() ) + ofs << "<" << (*entry).second.first << ", " << + (*entry).second.second << "> " << *file << endl; + // if not, simply save filename + else + ofs << *file << endl; + } + ofs.close(); } else lyxerr << "LyX: Warning: unable to save LastFiles: " << filename << endl; @@ -90,7 +127,26 @@ files.pop_back(); } +void LastFiles::saveFilePosition(string const& fname, int id, lyx::pos_type pos ) const +{ + filePositions[fname] = pair<int, lyx::pos_type>(id, pos); +} +void LastFiles::loadFilePosition(string const& fname, int& id, lyx::pos_type& pos ) const +{ + file_pos::iterator entry = filePositions.find(fname); + // has position information, return it. + if( entry != filePositions.end() ) { + id = (*entry).second.first; + pos = (*entry).second.second; + } + // not found, return invalid id number + else { + id = -1; + pos = 0; + } +} + string const LastFiles::operator[](unsigned int i) const { if (i < files.size()) Index: src/lyxfunc.C =================================================================== --- src/lyxfunc.C (revision 13455) +++ src/lyxfunc.C (working copy) @@ -1879,6 +1879,8 @@ void LyXFunc::closeBuffer() { + // save current position to lastfile + view()->savePosition(0); if (bufferlist.close(owner->buffer(), true) && !quitting) { if (bufferlist.empty()) { // need this otherwise SEGV may occur while Index: src/lastfiles.h =================================================================== --- src/lastfiles.h (revision 13455) +++ src/lastfiles.h (working copy) @@ -12,6 +12,9 @@ #ifndef LASTFILES_H #define LASTFILES_H +// for pos_type +#include <support/types.h> + #include <boost/utility.hpp> #include <deque> @@ -56,6 +59,18 @@ @param file the file we write the lastfiles list to. */ void writeFile(std::string const & file) const; + /** add cursor position to the fname entry in the lastfile + @param fname file entry for which to save position information + @param id id of the paragraph of the location when the file is closed. + @param pos position of the cursor when the file is closed. + */ + void LastFiles::saveFilePosition(std::string const& fname, int id, lyx::pos_type pos) const; + /** load saved cursor position to the fname entry in the lastfile + @param fname file entry for which to load position information + @param id id of the paragraph of the location when the file is closed. + @param pos position of the cursor when the file is closed. + */ + void LastFiles::loadFilePosition(std::string const& fname, int& id, lyx::pos_type& pos ) const; /** Return file #n# in the lastfiles list. @param n number in the list to get */ Index: lib/ui/stdmenus.ui =================================================================== --- lib/ui/stdmenus.ui (revision 13455) +++ lib/ui/stdmenus.ui (working copy) @@ -403,6 +403,7 @@ End Menu "navigate_bookmarks" + Item "Go to saved position|0" "bookmark-goto 0" Item "Go to Bookmark 1|1" "bookmark-goto 1" Item "Go to Bookmark 2|2" "bookmark-goto 2" Item "Go to Bookmark 3|3" "bookmark-goto 3"