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

Reply via email to