+int BufferView::horizScrollOffset() const
+{
+ return d->horiz_scroll_offset_;
+}
+
+
+CursorSlice const & BufferView::currentRowSlice() const
+{
+ return d->current_row_slice_;
+}
+
+
+CursorSlice const & BufferView::lastRowSlice() const
+{
+ return d->last_row_slice_;
+}
+
+
+void BufferView::setCurrentRowSlice(CursorSlice const & rowSlice)
+{
+ // nothing to do if the cursor was already on this row
+ if (d->current_row_slice_ == rowSlice) {
+ d->last_row_slice_ = CursorSlice();
+ return;
+ }
+
+ // if the (previous) current row was scrolled, we have to
+ // remember it in order to repaint it next time.
+ if (d->horiz_scroll_offset_ != 0)
+ d->last_row_slice_ = d->current_row_slice_;
+ else
+ d->last_row_slice_ = CursorSlice();
+
+ // Since we changed row, the scroll offset is not valid anymore
+ d->horiz_scroll_offset_ = 0;
+ d->current_row_slice_ = rowSlice;
+}
+
+
+void BufferView::checkCursorScrollOffset(PainterInfo & pi)
+{
+ CursorSlice rowSlice = d->cursor_.bottom();
+ TextMetrics const & tm = textMetrics(rowSlice.text());
+
+ // Stop if metrics have not been computed yet, since it means
+ // that there is nothing to do.
+ if (!tm.contains(rowSlice.pit()))
+ return;
+ ParagraphMetrics const & pm = tm.parMetrics(rowSlice.pit());
+ Row const & row = pm.getRow(rowSlice.pos(),
+ d->cursor_.boundary()
+ && rowSlice == d->cursor_.top());
+ rowSlice.pos() = row.pos();
+
+ // Set the row on which the cursor lives.
+ setCurrentRowSlice(rowSlice);
+
+ /** FIXME: the code below adds an extraneous computation of inset
+ * positions, and can therefore be bad for performance (think for
+ * example about a very large tabular inset. Redawing the row
+ * where it is means redrawing the whole screen).
+ *
+ * The bug that this fixes is the following: assume that there is
+ * a very large math inset. Upon entering the inset, when pressing
+ * `End', the row is not scrolled and the cursor is not visible. I
+ * am not sure why the extra row computation fixes the problem,
+ * actually.
+ *
+ * A proper fix should be found and this code should be removed.
+ */
+ // Force the recomputation of inset positions
+ bool const drawing = pi.pain.isDrawingEnabled();
+ pi.pain.setDrawingEnabled(false);
+ // No need to care about vertical position.
+ RowPainter rp(pi, buffer().text(), d->cursor_.bottom().pit(), row,
+ -d->horiz_scroll_offset_, 0);
+ rp.paintText();
+ pi.pain.setDrawingEnabled(drawing);
+ /** END of bad code */
+
+ // Current x position of the cursor in pixels
+ int const cur_x = getPos(d->cursor_).x_;
+
+ // Horizontal scroll offset of the cursor row in pixels
+ int offset = d->horiz_scroll_offset_;
+ int const MARGIN = Length(2, Length::EM).inPixels(pi.base);
+ if (cur_x < offset + MARGIN) {
+ // scroll right
+ offset = cur_x - MARGIN;
+ } else if (cur_x > offset + workWidth() - MARGIN) {
+ // scroll left
+ offset = cur_x - workWidth() + MARGIN;
+ }
+
+ if (offset < row.left_margin || row.width() <= workWidth())
+ offset = 0;
+
+ if (offset != d->horiz_scroll_offset_)
+ LYXERR(Debug::PAINTING, "Horiz. scroll offset changed from "
+ << d->horiz_scroll_offset_ << " to " << offset);
+
+ if (d->update_strategy_ == NoScreenUpdate
+ && (offset != d->horiz_scroll_offset_
+ || !d->last_row_slice_.empty())) {
+ // FIXME: if one uses SingleParUpdate, then home/end
+ // will not work on long rows. Why?
+ d->update_strategy_ = FullScreenUpdate;
+ }
+
+ d->horiz_scroll_offset_ = offset;
+}
+
+