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.
This commit is contained in:
Guillaume Munch 2016-09-03 23:54:05 +01:00
parent c9fc5bf1c6
commit 5fbbf0f281
4 changed files with 102 additions and 57 deletions

View File

@ -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)

View File

@ -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();
}

View File

@ -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),

View File

@ -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