+private:
+ // ensures that it_ points to a valid value unless row_it_ == row_end_
+ void normalize()
+ {
+ if (row_it_ == row_end_)
+ return;
+ while (it_ == it_end_) {
+ ++row_it_;
+ if (row_it_ != row_end_) {
+ it_ = row_it_->begin();
+ it_end_ = row_it_->end();
+ } else
+ return;
+ }
+ }
+ //
+ RowList::const_iterator row_it_;
+ //
+ RowList::const_iterator row_end_;
+ //
+ RowEntryList::const_iterator it_;
+ //
+ RowEntryList::const_iterator it_end_;
+};
+
+
+TexRow::RowListIterator TexRow::begin() const
+{
+ return RowListIterator(rowlist_.begin(), rowlist_.end());
+}
+
+
+TexRow::RowListIterator TexRow::end() const
+{
+ return RowListIterator(rowlist_.end(), rowlist_.end());
+}
+
+
+std::pair<int,int> TexRow::rowFromDocIterator(DocIterator const & dit) const
+{
+ bool beg_found = false;
+ bool end_is_next = true;
+ int end_offset = 1;
+ size_t best_slice = 0;
+ RowEntry best_entry = row_none;
+ size_t const n = dit.depth();
+ // this loop finds a pair (best_beg_row,best_end_row) where best_beg_row is
+ // the first row of the topmost possible CursorSlice, and best_end_row is
+ // the one just before the first row matching the next CursorSlice.
+ RowListIterator const begin = this->begin();//necessary disambiguation
+ RowListIterator const end = this->end();
+ RowListIterator best_beg_entry;
+ //best last entry with same pos as the beg_entry, or first entry with pos
+ //immediately following the beg_entry
+ RowListIterator best_end_entry;
+ RowListIterator it = begin;
+ for (; it != end; ++it) {
+ // Compute the best end row.
+ if (beg_found
+ && (!sameParOrInsetMath(*it, *best_end_entry)
+ || comparePos(*it, *best_end_entry) <= 0)
+ && sameParOrInsetMath(*it, best_entry)) {
+ switch (comparePos(*it, best_entry)) {
+ case 0:
+ // Either it is the last one that matches pos...
+ best_end_entry = it;
+ end_is_next = false;
+ end_offset = 1;
+ break;
+ case -1: {
+ // ...or it is the row preceding the first that matches pos+1
+ if (!end_is_next) {
+ end_is_next = true;
+ if (it.row() != best_end_entry.row())
+ end_offset = 0;
+ best_end_entry = it;
+ }
+ break;
+ }
+ }
+ }
+ // Compute the best begin row. It is better than the previous one if it
+ // matches either at a deeper level, or at the same level but not
+ // before.
+ for (size_t i = best_slice; i < n; ++i) {
+ RowEntry entry_i = rowEntryFromCursorSlice(dit[i]);
+ if (sameParOrInsetMath(*it, entry_i)) {
+ if (comparePos(*it, entry_i) >= 0
+ && (i > best_slice
+ || !beg_found
+ || !sameParOrInsetMath(*it, *best_beg_entry)
+ || (comparePos(*it, *best_beg_entry) <= 0
+ && comparePos(entry_i, *best_beg_entry) != 0)
+ )
+ ) {
+ beg_found = true;
+ end_is_next = false;
+ end_offset = 1;
+ best_slice = i;
+ best_entry = entry_i;
+ best_beg_entry = best_end_entry = it;
+ }
+ //found CursorSlice
+ break;
+ }
+ }
+ }
+ if (!beg_found)
+ return std::make_pair(-1,-1);
+ int const best_beg_row = distance(rowlist_.begin(),
+ best_beg_entry.row()) + 1;
+ int const best_end_row = distance(rowlist_.begin(),
+ best_end_entry.row()) + end_offset;
+ return std::make_pair(best_beg_row, best_end_row);
+}
+
+
+std::pair<int,int> TexRow::rowFromCursor(Cursor const & cur) const
+{
+ DocIterator beg = cur.selectionBegin();
+ std::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))
+ end.top().backwardPos();
+ std::pair<int,int> end_rows = rowFromDocIterator(end);
+ return std::make_pair(std::min(beg_rows.first, end_rows.first),
+ std::max(beg_rows.second, end_rows.second));
+ } else
+ return std::make_pair(beg_rows.first, beg_rows.second);