///
map<string, Inset *> edited_insets_;
- /// When the row where the cursor lies is scrolled, this
- /// contains the scroll offset
// cache for id of the paragraph which was edited the last time
int bookmark_edit_position_;
+ /// When the row where the cursor lies is scrolled, this
+ /// contains the scroll offset
int horiz_scroll_offset_;
/// a slice pointing to the start of the row where the cursor
/// is (at last draw time)
}
+void BufferView::copySettingsFrom(BufferView const & bv)
+{
+ setCursor(bv.cursor());
+ d->anchor_pit_ = bv.d->anchor_pit_;
+ d->anchor_ypos_ = bv.d->anchor_ypos_;
+}
+
+
int BufferView::defaultMargin() const
{
// The value used to be hardcoded to 10
}
+bool BufferView::hasMathRow(MathData const * cell) const
+{
+ return d->math_rows_.find(cell) != d->math_rows_.end();
+}
+
+
MathRow const & BufferView::mathRow(MathData const * cell) const
{
auto it = d->math_rows_.find(cell);
Text & t = buffer_.text();
TextMetrics & tm = d->text_metrics_[&t];
- LYXERR(Debug::GUI, " Updating scrollbar: height: "
+ LYXERR(Debug::SCROLLING, " Updating scrollbar: height: "
<< t.paragraphs().size()
<< " curr par: " << d->cursor_.bottom().pit()
<< " default height " << defaultRowHeight());
<< d->par_height_[pit]);
}
- int top_pos = first.second->position() - first.second->ascent();
- int bottom_pos = last.second->position() + last.second->descent();
+ int top_pos = first.second->top();
+ int bottom_pos = last.second->bottom();
bool first_visible = first.first == 0 && top_pos >= 0;
bool last_visible = last.first + 1 == int(parsize) && bottom_pos <= height_;
if (first_visible && last_visible) {
d->anchor_ypos_ = - offset + row_dim.ascent();
if (how == SCROLL_CENTER)
d->anchor_ypos_ += height_/2 - row_dim.height() / 2;
+ else if (!lyxrc.scroll_below_document && d->anchor_pit_ == max_pit)
+ d->anchor_ypos_ = height_ - offset - row_dim.descent();
+ else if (offset > height_)
+ d->anchor_ypos_ = height_ - offset - defaultRowHeight();
+ else
+ d->anchor_ypos_ = defaultRowHeight() * 2;
+
return d->anchor_ypos_ != old_ypos || d->anchor_pit_ != old_pit;
}
}
case LFUN_INDEX_TAG_ALL: {
+ if (cur.pos() == 0)
+ // nothing precedes
+ break;
+
Inset * ins = cur.nextInset();
if (!ins || ins->lyxCode() != INDEX_CODE)
// not at index inset
// Get word or selection
cur.text()->selectWord(cur, WHOLE_WORD);
docstring const searched_string = cur.selectionAsString(false);
+ if (searched_string.empty())
+ break;
// Start from the beginning
lyx::dispatch(FuncRequest(LFUN_BUFFER_BEGIN));
while (findOne(this, searched_string,
// Put anchor at the same position.
cur.resetAnchor();
- cur.beginUndoGroup();
+ old.beginUndoGroup();
// Try to dispatch to an non-editable inset near this position
// via the temp cursor. If the inset wishes to change the real
cursor().fixIfBroken();
}
- cur.endUndoGroup();
+ old.endUndoGroup();
// Do we have a selection?
theSelection().haveSelection(cursor().selection());
int const ymax = height_ + pixels;
while (true) {
pair<pit_type, ParagraphMetrics const *> last = tm.last();
- int bottom_pos = last.second->position() + last.second->descent();
+ int bottom_pos = last.second->bottom();
if (lyxrc.scroll_below_document)
bottom_pos += height_ - minVisiblePart();
if (last.first + 1 == int(text->paragraphs().size())) {
int ymin = - pixels;
while (true) {
pair<pit_type, ParagraphMetrics const *> first = tm.first();
- int top_pos = first.second->position() - first.second->ascent();
+ int top_pos = first.second->top();
if (first.first == 0) {
if (top_pos >= 0)
return 0;
}
+void BufferView::setSelection(DocIterator const & from,
+ DocIterator const & to)
+{
+ if (from.pit() != to.pit()) {
+ // there are multiple paragraphs in selection
+ cursor().setCursor(from);
+ cursor().clearSelection();
+ cursor().selection(true);
+ cursor().setCursor(to);
+ cursor().selection(true);
+ } else {
+ // only single paragraph
+ int const size = to.pos() - from.pos();
+ putSelectionAt(from, size, false);
+ }
+ processUpdateFlags(Update::Force | Update::FitCursor);
+}
+
+
bool BufferView::selectIfEmpty(DocIterator & cur)
{
if ((cur.inTexted() && !cur.paragraph().empty())
bool BufferView::singleParUpdate()
{
- Text & buftext = buffer_.text();
- pit_type const bottom_pit = d->cursor_.bottom().pit();
- TextMetrics & tm = textMetrics(&buftext);
- Dimension const old_dim = tm.parMetrics(bottom_pit).dim();
+ CursorSlice const & its = d->cursor_.innerTextSlice();
+ pit_type const pit = its.pit();
+ TextMetrics & tm = textMetrics(its.text());
+ Dimension const old_dim = tm.parMetrics(pit).dim();
// make sure inline completion pointer is ok
if (d->inlineCompletionPos_.fixIfBroken())
d->inlineCompletionPos_ = DocIterator();
- // In Single Paragraph mode, rebreak only
- // the (main text, not inset!) paragraph containing the cursor.
- // (if this paragraph contains insets etc., rebreaking will
- // recursively descend)
- tm.redoParagraph(bottom_pit);
- ParagraphMetrics & pm = tm.parMetrics(bottom_pit);
- if (pm.height() != old_dim.height()) {
- // Paragraph height has changed so we cannot proceed to
- // the singlePar optimisation.
+ /* Try to rebreak only the paragraph containing the cursor (if
+ * this paragraph contains insets etc., rebreaking will
+ * recursively descend). We need a full redraw if either
+ * 1/ the height has changed
+ * or
+ * 2/ the width has changed and it was equal to the textmetrics
+ * width; the goal is to catch the case of a one-row inset that
+ * grows with its contents, but optimize the case of typing at
+ * the end of a mmultiple-row paragraph.
+ *
+ * NOTE: if only the height has changed, then it should be
+ * possible to update all metrics at minimal cost. However,
+ * since this is risky, we do not try that right now.
+ */
+ tm.redoParagraph(pit);
+ ParagraphMetrics & pm = tm.parMetrics(pit);
+ if (pm.height() != old_dim.height()
+ || (pm.width() != old_dim.width() && old_dim.width() == tm.width())) {
+ // Paragraph height or width has changed so we cannot proceed
+ // to the singlePar optimisation.
+ LYXERR(Debug::PAINTING, "SinglePar optimization failed.");
return false;
}
// Since position() points to the baseline of the first row, we
// the height does not change but the ascent does.
pm.setPosition(pm.position() - old_dim.ascent() + pm.ascent());
- tm.updatePosCache(bottom_pit);
+ tm.updatePosCache(pit);
- LYXERR(Debug::PAINTING, "\ny1: " << pm.position() - pm.ascent()
- << " y2: " << pm.position() + pm.descent()
- << " pit: " << bottom_pit
- << " singlepar: 1");
+ LYXERR(Debug::PAINTING, "\ny1: " << pm.top() << " y2: " << pm.bottom()
+ << " pit: " << pit << " singlepar: 1");
return true;
}
}
}
anchor_pm.setPosition(d->anchor_ypos_);
- tm.updatePosCache(d->anchor_pit_);
LYXERR(Debug::PAINTING, "metrics: "
<< " anchor pit = " << d->anchor_pit_
y1 -= pm.descent();
// Save the paragraph position in the cache.
pm.setPosition(y1);
- tm.updatePosCache(pit1);
y1 -= pm.ascent();
}
y2 += pm.ascent();
// Save the paragraph position in the cache.
pm.setPosition(y2);
- tm.updatePosCache(pit2);
y2 += pm.descent();
}
void BufferView::caretPosAndDim(Point & p, Dimension & dim) const
{
Cursor const & cur = cursor();
- if (cur.inMathed()) {
+ if (cur.inMathed() && hasMathRow(&cur.cell())) {
MathRow const & mrow = mathRow(&cur.cell());
dim = mrow.caret_dim;
} else {
// and possibly grey out below
pair<pit_type, ParagraphMetrics const *> lastpm = tm.last();
- int const y2 = lastpm.second->position() + lastpm.second->descent();
+ int const y2 = lastpm.second->bottom();
if (y2 < height_) {
Color color = buffer().isInternal()
pair<pit_type, ParagraphMetrics const *> lastpm = tm.last();
for (pit_type pit = firstpm.first; pit <= lastpm.first; ++pit) {
ParagraphMetrics const & pm = tm.parMetrics(pit);
- if (pm.position() + pm.descent() > 0) {
+ if (pm.bottom() > 0) {
if (d->anchor_pit_ != pit
|| d->anchor_ypos_ != pm.position())
LYXERR(Debug::PAINTING, "Found new anchor pit = " << d->anchor_pit_