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"










Reply via email to