[LyX/master] Keep last file positions in last-use ordering

Jean-Marc Lasgouttes lasgouttes at lyx.org
Sun Oct 20 10:23:53 UTC 2019


commit 58d22e0c6edab4cb68af63d3ccaafcb875be995d
Author: Jean-Marc Lasgouttes <lasgouttes at lyx.org>
Date:   Sun Oct 20 11:47:04 2019 +0200

    Keep last file positions in last-use ordering
    
    Using a map would sort the elements in alphabetic ordering, which
    means that when the number of elements is larger than 100, the wrong
    elements get pruned.
    
    This commit uses a list instead. Searching an item needs linear time,
    but this should not be a problem for a list with less than 100
    elements.
    
    Fixes bug #10310.
---
 src/BufferView.cpp |    3 ++-
 src/Session.cpp    |   36 ++++++++++++++++++++++--------------
 src/Session.h      |   18 +++++++++---------
 3 files changed, 33 insertions(+), 24 deletions(-)

diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index 97adab8..b960da6 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -345,9 +345,10 @@ BufferView::~BufferView()
 	// That is to say, if a cursor is in a nested inset, it will be
 	// restore to the left of the top level inset.
 	LastFilePosSection::FilePos fp;
+	fp.file = buffer_.fileName();
 	fp.pit = d->cursor_.bottom().pit();
 	fp.pos = d->cursor_.bottom().pos();
-	theSession().lastFilePos().save(buffer_.fileName(), fp);
+	theSession().lastFilePos().save(fp);
 
 	if (d->last_inset_)
 		d->last_inset_->setMouseHover(this, false);
diff --git a/src/Session.cpp b/src/Session.cpp
index eb0fc64..3947883 100644
--- a/src/Session.cpp
+++ b/src/Session.cpp
@@ -196,10 +196,10 @@ void LastFilePosSection::read(istream & is)
 			getline(itmp, fname);
 			if (!FileName::isAbsolute(fname))
 				continue;
-			FileName const file(fname);
-			if (file.exists() && !file.isDirectory()
+			filepos.file = FileName(fname);
+			if (filepos.file.exists() && !filepos.file.isDirectory()
 			    && lastfilepos.size() < num_lastfilepos)
-				lastfilepos[file] = filepos;
+				lastfilepos.push_back(filepos);
 			else
 				LYXERR(Debug::INIT, "LyX: Warning: Ignore pos of last file: " << fname);
 		} catch (...) {
@@ -212,26 +212,34 @@ void LastFilePosSection::read(istream & is)
 void LastFilePosSection::write(ostream & os) const
 {
 	os << '\n' << sec_lastfilepos << '\n';
-	for (FilePosMap::const_iterator file = lastfilepos.begin();
-		file != lastfilepos.end(); ++file) {
-		os << file->second.pit << ", " << file->second.pos << ", "
-		   << file->first << '\n';
-	}
+	for (auto const & file_p : lastfilepos)
+		os << file_p.pit << ", " << file_p.pos << ", " << file_p.file << '\n';
 }
 
 
-void LastFilePosSection::save(FileName const & fname, FilePos const & pos)
+void LastFilePosSection::save(FilePos const & pos)
 {
-	lastfilepos[fname] = pos;
+	// Remove element if it was already present. Iterating should
+	// not be a problem since the list is small (<100 elements).
+	for (FilePosList::const_iterator it = lastfilepos.begin();
+	     it != lastfilepos.end(); ++it)
+		if (it->file == pos.file) {
+			lastfilepos.erase(it);
+			break;
+		}
+
+	// insert new element at front.
+	lastfilepos.push_front(pos);
 }
 
 
 LastFilePosSection::FilePos LastFilePosSection::load(FileName const & fname) const
 {
-	FilePosMap::const_iterator entry = lastfilepos.find(fname);
-	// Has position information, return it.
-	if (entry != lastfilepos.end())
-		return entry->second;
+	for (auto & fp : lastfilepos)
+		if (fp.file == fname)
+			// Has position information, return it.
+			return fp;
+
 	// Not found, return the first paragraph
 	return FilePos();
 }
diff --git a/src/Session.h b/src/Session.h
index 31ffee8..65bf19d 100644
--- a/src/Session.h
+++ b/src/Session.h
@@ -16,7 +16,7 @@
 #include "support/FileName.h"
 #include "support/types.h"
 
-#include <map>
+#include <list>
 #include <string>
 #include <vector>
 
@@ -148,12 +148,13 @@ public:
 	///
 	struct FilePos {
 		FilePos() : pit(0), pos(0) {}
+		support::FileName file;
 		pit_type pit;
 		pos_type pos;
 	};
 
 	///
-	typedef std::map<support::FileName, FilePos> FilePosMap;
+	typedef std::list<FilePos> FilePosList;
 
 public:
 	///
@@ -165,13 +166,12 @@ public:
 	///
 	void write(std::ostream & os) const;
 
-	/** add cursor position to the fname entry in the filepos map
-	    @param fname file entry for which to save position information
-	    @param pos position of the cursor when the BufferView is closed.
+	/** add cursor position to the fname entry in the filepos list
+	    @param pos file name and position of the cursor when the BufferView is closed.
 	*/
-	void save(support::FileName const & fname, FilePos const & pos);
+	void save(FilePos const & pos);
 
-	/** load saved cursor position from the fname entry in the filepos map
+	/** load saved cursor position from the fname entry in the filepos list
 	    @param fname file entry for which to load position information
 	*/
 	FilePos load(support::FileName const & fname) const;
@@ -181,8 +181,8 @@ private:
 	unsigned int const num_lastfilepos;
 
 
-	/// a map of file positions
-	FilePosMap lastfilepos;
+	/// a list of file positions
+	FilePosList lastfilepos;
 };
 
 


More information about the lyx-cvs mailing list