commit 5fbbf0f281b8543899036419e05242d7feac9a59
Author: Guillaume Munch <[email protected]>
Date: Sat Sep 3 23:54:05 2016 +0100
Reverse search: select a whole row
TexRow now returns a range {start, end} when looking up a particular row.
Reverse-search now selects the whole range instead of simply moving the
cursor.
---
src/Buffer.cpp | 6 +---
src/BufferView.cpp | 58 +++++++++++++------------------------------
src/TexRow.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++----
src/TexRow.h | 27 +++++++++++++++-----
4 files changed, 102 insertions(+), 57 deletions(-)
diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index bf83f9f..a66988b 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -2875,11 +2875,9 @@ void Buffer::getLanguages(std::set<Language const *> &
languages) const
DocIterator Buffer::getParFromID(int const id) const
{
Buffer * buf = const_cast<Buffer *>(this);
- if (id < 0) {
- // John says this is called with id == -1 from undo
- lyxerr << "getParFromID(), id: " << id << endl;
+ if (id < 0)
+ // This means non-existent
return doc_iterator_end(buf);
- }
for (DocIterator it = doc_iterator_begin(buf); !it.atEnd();
it.forwardPar())
if (it.paragraph().id() == id)
diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index ce83061..ad40dd6 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -2341,49 +2341,27 @@ void BufferView::setCursorFromRow(int row)
void BufferView::setCursorFromRow(int row, TexRow const & texrow)
{
- int tmpid;
- int tmppos;
- pit_type newpit = 0;
- pos_type newpos = 0;
-
- texrow.getIdFromRow(row, tmpid, tmppos);
-
- bool posvalid = (tmpid != -1);
- if (posvalid) {
- // we need to make sure that the row and position
- // we got back are valid, because the buffer may well
- // have changed since we last generated the LaTeX.
- DocIterator dit = buffer_.getParFromID(tmpid);
- if (dit == doc_iterator_end(&buffer_))
- posvalid = false;
- else if (dit.depth() > 1) {
- // We are in an inset.
- pos_type lastpos = dit.lastpos();
- dit.pos() = tmppos > lastpos ? lastpos : tmppos;
- setCursor(dit);
- recenter();
- return;
- } else {
- newpit = dit.pit();
- // now have to check pos.
- newpos = tmppos;
- Paragraph const & par = buffer_.text().getPar(newpit);
- if (newpos > par.size()) {
- LYXERR0("Requested position no longer valid.");
- newpos = par.size() - 1;
- }
- }
- }
- if (!posvalid) {
+ DocIterator start, end;
+ tie(start,end) = texrow.getDocIteratorFromRow(row, buffer_);
+ // we need to make sure that the DocIterators
+ // we got back are valid, because the buffer may well
+ // have changed since we last generated the LaTeX.
+ if (!start) {
+ LYXERR(Debug::LATEX,
+ "setCursorFromRow: invalid position for row " << row);
frontend::Alert::error(_("Inverse Search Failed"),
- _("Invalid position requested by inverse search.\n"
- "You need to update the viewed document."));
+ _("Invalid position requested by inverse
search.\n"
+ "You may need to update the viewed
document."));
return;
}
- d->cursor_.reset();
- buffer_.text().setCursor(d->cursor_, newpit, newpos);
- d->cursor_.selection(false);
- d->cursor_.resetAnchor();
+ // Setting selection start
+ d->cursor_.clearSelection();
+ setCursor(start);
+ // Setting selection end
+ if (end) {
+ d->cursor_.resetAnchor();
+ setCursorSelectionTo(end);
+ }
recenter();
}
diff --git a/src/TexRow.cpp b/src/TexRow.cpp
index d427227..b4366e0 100644
--- a/src/TexRow.cpp
+++ b/src/TexRow.cpp
@@ -13,6 +13,7 @@
#include <config.h>
+#include "Buffer.h"
#include "Cursor.h"
#include "Paragraph.h"
#include "TexRow.h"
@@ -198,6 +199,66 @@ bool TexRow::getIdFromRow(int row, int & id, int & pos)
const
}
+pair<TextEntry, TextEntry> TexRow::getEntriesFromRow(int const row) const
+{
+ LYXERR(Debug::LATEX, "getEntriesFromRow: row " << row << " requested");
+ // check bounds for row - 1, our target index
+ if (row <= 0)
+ return {text_none, text_none};
+ size_t const i = static_cast<size_t>(row - 1);
+ if (i >= rowlist_.size())
+ return {text_none, text_none};
+ // find the start entry
+ size_t j = i;
+ while (j > 0 && isNone(rowlist_[j].getTextEntry()))
+ --j;
+ TextEntry start = rowlist_[j].getTextEntry();
+ // find the end entry
+ j = i + 1;
+ while (j < rowlist_.size() && isNone(rowlist_[j].getTextEntry()))
+ ++j;
+ TextEntry end =
+ (j < rowlist_.size()) ? rowlist_[j].getTextEntry() : text_none;
+ // The following occurs for a displayed math inset for instance (for
good
+ // reasons involving subtleties of the algorithm in
getRowFromDocIterator).
+ // We want this inset selected.
+ if (start.id == end.id && start.pos == end.pos)
+ ++end.pos;
+ return {start, end};
+}
+
+
+pair<DocIterator, DocIterator> TexRow::getDocIteratorFromRow(
+ int const row,
+ Buffer const & buf) const
+{
+ TextEntry start, end;
+ tie(start,end) = getEntriesFromRow(row);
+ LYXERR(Debug::LATEX,
+ "getDocIteratorFromRow: for row " << row << ", TexRow has found "
+ "start (id=" << start.id << ",pos=" << start.pos << "), "
+ "end (id=" << end.id << ",pos=" << end.pos << ")");
+ // Finding start
+ DocIterator dit_start = buf.getParFromID(start.id);
+ if (dit_start)
+ dit_start.pos() = min(start.pos, dit_start.lastpos());
+ // Finding end
+ DocIterator dit_end = buf.getParFromID(end.id);
+ if (dit_end) {
+ dit_end.pos() = min(end.pos, dit_end.lastpos());
+ // So far dit_end belongs to the next row. Step backwards.
+ if (!dit_end.top().at_cell_begin()) {
+ CursorSlice end_top = dit_end.top();
+ end_top.backwardPos();
+ if (dit_start && end_top != dit_start.top())
+ dit_end.top() = end_top;
+ }
+ dit_end.boundary(true);
+ }
+ return {dit_start, dit_end};
+}
+
+
//static
RowEntry TexRow::rowEntryFromCursorSlice(CursorSlice const & slice)
{
@@ -427,12 +488,7 @@ pair<int,int> TexRow::rowFromCursor(Cursor const & cur)
const
pair<int,int> beg_rows = rowFromDocIterator(beg);
if (cur.selection()) {
DocIterator end = cur.selectionEnd();
- if (!cur.selIsMultiCell()
- // backwardPos asserts without the following test, IMO
it's not my
- // duty to check this.
- && (end.top().pit() != 0
- || end.top().idx() != 0
- || end.top().pos() != 0))
+ if (!cur.selIsMultiCell() && !end.top().at_cell_begin())
end.top().backwardPos();
pair<int,int> end_rows = rowFromDocIterator(end);
return make_pair(min(beg_rows.first, end_rows.first),
diff --git a/src/TexRow.h b/src/TexRow.h
index dc0efdc..4969f3a 100644
--- a/src/TexRow.h
+++ b/src/TexRow.h
@@ -36,6 +36,7 @@
namespace lyx {
class LyXErr;
+class Buffer;
class Cursor;
class CursorSlice;
class DocIterator;
@@ -130,15 +131,27 @@ public:
void newlines(size_t num_lines);
/**
- * getIdFromRow - find pid and position for a given row
+ * getEntriesFromRow - find pids and position for a given row
* @param row row number to find
- * @param id set to id if found
- * @param pos set to paragraph position if found
- * @return true if found, false otherwise
- *
- * If the row could not be found, pos is set to zero and
- * id is set to -1
+ * @return a pair of TextEntry denoting the start and end of the
position.
+ * The TextEntry values can be isNone(). If no row is found then the
first
+ * value isNone().
*/
+ std::pair<TextEntry,TextEntry> getEntriesFromRow(int row) const;
+
+ /**
+ * getDocIteratorFromRow - find pids and positions for a given row
+ * @param row number to find
+ * @param buffer here to look
+ * @return a pair of DocIterators the start and end of the position.
+ * The DocIterators can be invalid. The starting DocIterator being
invalid
+ * means that no row was found. Note: there is no guarantee that the
+ * DocIterators are in the same inset or even at the same depth.
+ */
+ std::pair<DocIterator, DocIterator> getDocIteratorFromRow(
+ int row,
+ Buffer const & buf) const;
+ //TODO: remove the following by replacing it with the above
bool getIdFromRow(int row, int & id, int & pos) const;
/// Finds the best pair of rows for dit