#include "Paragraph.h"
#include "ParagraphParameters.h"
#include "ParIterator.h"
-#include "RowPainter.h"
#include "Session.h"
#include "Text.h"
#include "TextClass.h"
struct BufferView::Private
{
- Private(BufferView & bv): wh_(0), cursor_(bv),
+ Private(BufferView & bv) : update_strategy_(NoScreenUpdate),
+ wh_(0), cursor_(bv),
anchor_pit_(0), anchor_ypos_(0),
inlineCompletionUniqueChars_(0),
last_inset_(0), clickable_inset_(false),
mouse_position_cache_(),
bookmark_edit_position_(-1), gui_(0),
horiz_scroll_offset_(0)
- {}
+ {
+ xsel_cache_.set = false;
+ }
///
ScrollbarParameters scrollbarParameters_;
}
-bool BufferView::fitCursor()
+bool BufferView::needsFitCursor() const
{
if (cursorStatus(d->cursor_) == CUR_INSIDE) {
frontend::FontMetrics const & fm =
// Now do the first drawing step if needed. This consists on updating
// the CoordCache in updateMetrics().
// The second drawing step is done in WorkArea::redraw() if needed.
+ // FIXME: is this still true now that Buffer::changed() is used all over?
// Case when no explicit update is requested.
if (!flags) {
if (flags == Update::FitCursor
|| flags == (Update::Decoration | Update::FitCursor)) {
// tell the frontend to update the screen if needed.
- if (fitCursor()) {
+ if (needsFitCursor()) {
showCursor();
return;
}
return;
}
// no screen update is needed in principle, but this
- // could change if cursor row needs scrolling.
+ // could change if cursor row needs horizontal scrolling.
d->update_strategy_ = NoScreenUpdate;
buffer_.changed(false);
return;
// This is done at draw() time. So we need a redraw!
buffer_.changed(false);
- if (fitCursor()) {
+ if (needsFitCursor()) {
// The cursor is off screen so ensure it is visible.
// refresh it:
showCursor();
// paragraph position which is computed at draw() time.
// So we need a redraw!
buffer_.changed(false);
- if (fitCursor())
+ if (needsFitCursor())
showCursor();
}
}
-/** Return the change status at cursor position, taking in account the
+/** Return the change status at cursor position, taking into account the
* status at each level of the document iterator (a table in a deleted
* footnote is deleted).
* When \param outer is true, the top slice is not looked at.
iss >> opt;
flag.setEnabled(opt.repl_buf_name.empty()
|| !buffer_.isReadonly());
+ break;
}
- case LFUN_LABEL_GOTO: {
+ case LFUN_LABEL_GOTO:
flag.setEnabled(!cmd.argument().empty()
|| getInsetByCode<InsetRef>(cur, REF_CODE));
break;
- }
case LFUN_CHANGES_TRACK:
flag.setEnabled(true);
string const argument = to_utf8(cmd.argument());
Cursor & cur = d->cursor_;
+ Cursor old = cur;
// Don't dispatch function that does not apply to internal buffers.
if (buffer_.isInternal()
for (Buffer * b = &buffer_; i == 0 || b != &buffer_;
b = theBufferList().next(b)) {
- DocIterator dit = b->getParFromID(id);
- if (dit.atEnd()) {
+ Cursor cur(*this);
+ cur.setCursor(b->getParFromID(id));
+ if (cur.atEnd()) {
LYXERR(Debug::INFO, "No matching paragraph found! [" << id << "].");
++i;
continue;
}
- LYXERR(Debug::INFO, "Paragraph " << dit.paragraph().id()
+ LYXERR(Debug::INFO, "Paragraph " << cur.paragraph().id()
<< " found in buffer `"
<< b->absFileName() << "'.");
if (b == &buffer_) {
// Set the cursor
- dit.pos() = pos;
- setCursor(dit);
+ cur.pos() = pos;
+ mouseSetCursor(cur);
dr.screenUpdate(Update::Force | Update::FitCursor);
} else {
// Switch to other buffer view and resend cmd
p = Point(0, 0);
if (act == LFUN_SCREEN_DOWN && scrolled < height_)
p = Point(width_, height_);
- Cursor old = cur;
bool const in_texted = cur.inTexted();
cur.setCursor(doc_iterator_begin(cur.buffer()));
cur.selHandle(false);
buffer_.undo().endUndoGroup();
dr.dispatched(dispatched);
+
+ // NOTE: The code below is copied from Cursor::dispatch. If you
+ // need to modify this, please update the other one too.
+
+ // notify insets we just entered/left
+ if (cursor() != old) {
+ old.beginUndoGroup();
+ old.fixIfBroken();
+ bool badcursor = notifyCursorLeavesOrEnters(old, cursor());
+ if (badcursor) {
+ cursor().fixIfBroken();
+ resetInlineCompletionPos();
+ }
+ old.endUndoGroup();
+ }
}
// Build temporary cursor.
Inset * inset = d->text_metrics_[&buffer_.text()].editXY(cur, cmd.x(), cmd.y());
+ if (inset) {
+ // If inset is not editable, cur.pos() might point behind the
+ // inset (depending on cmd.x(), cmd.y()). This is needed for
+ // editing to fix bug 9628, but e.g. the context menu needs a
+ // cursor in front of the inset.
+ if (inset->hasSettings() &&
+ cur.nextInset() != inset && cur.prevInset() == inset)
+ cur.backwardPos();
+ }
// Put anchor at the same position.
cur.resetAnchor();
void BufferView::setCursorFromRow(int row)
+{
+ setCursorFromRow(row, buffer_.texrow());
+}
+
+
+void BufferView::setCursorFromRow(int row, TexRow const & texrow)
{
int tmpid;
int tmppos;
pit_type newpit = 0;
pos_type newpos = 0;
- buffer_.texrow().getIdFromRow(row, tmpid, tmppos);
+ texrow.getIdFromRow(row, tmpid, tmppos);
bool posvalid = (tmpid != -1);
if (posvalid) {
Buffer const * buf = *it;
// find label
- Toc & toc = buf->tocBackend().toc("label");
- TocIterator toc_it = toc.begin();
- TocIterator end = toc.end();
+ shared_ptr<Toc> toc = buf->tocBackend().toc("label");
+ TocIterator toc_it = toc->begin();
+ TocIterator end = toc->end();
for (; toc_it != end; ++toc_it) {
if (label == toc_it->str()) {
lyx::dispatch(toc_it->action());
d->cursor_.setCursor(dit);
d->cursor_.setSelection(false);
+ d->cursor_.setCurrentFont();
// FIXME
// It seems on general grounds as if this is probably needed, but
// it is not yet clear.
d->cursor_ = cur;
// we would rather not do this here, but it needs to be done before
- // the changed() signal is sent.
+ // the changed() signal is sent.
buffer_.updateBuffer();
buffer_.changed(true);
int lastw = 0;
// Addup contribution of nested insets, from inside to outside,
- // keeping the outer paragraph for a special handling below
+ // keeping the outer paragraph for a special handling below
for (size_t i = dit.depth() - 1; i >= 1; --i) {
CursorSlice const & sl = dit[i];
int xx = 0;
// FIXME (Abdel 23/09/2007): this is a bit messy because of the
// elimination of Inset::dim_ cache. This coordOffset() method needs
// to be rewritten in light of the new design.
- Dimension const & dim = parMetrics(dit[i - 1].text(),
- dit[i - 1].pit()).insetDimension(&sl.inset());
+ Dimension const & dim = coordCache().getInsets().dim(&sl.inset());
lastw = dim.wid;
} else {
Dimension const dim = sl.inset().dimension(*this);
}
-void BufferView::checkCursorScrollOffset(PainterInfo & pi)
+void BufferView::checkCursorScrollOffset()
{
CursorSlice rowSlice = d->cursor_.bottom();
TextMetrics const & tm = textMetrics(rowSlice.text());
return;
ParagraphMetrics const & pm = tm.parMetrics(rowSlice.pit());
Row const & row = pm.getRow(rowSlice.pos(),
- d->cursor_.boundary()
- && rowSlice == d->cursor_.top());
+ 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(workWidth());
+ int const MARGIN = 2 * theFontMetrics(d->cursor_.real_current_font).em();
+ //lyxerr << "cur_x=" << cur_x << ", offset=" << offset << ", margin=" << MARGIN << endl;
if (cur_x < offset + MARGIN) {
// scroll right
offset = cur_x - MARGIN;
// Check whether the row where the cursor lives needs to be scrolled.
// Update the drawing strategy if needed.
- checkCursorScrollOffset(pi);
+ checkCursorScrollOffset();
switch (d->update_strategy_) {
LYXERR(Debug::PAINTING, "Strategy: NoScreenUpdate");
pi.full_repaint = true;
pi.pain.setDrawingEnabled(false);
- tm.draw(pi, 0, y);
+ tm.draw(pi, 0, y);
break;
case SingleParUpdate:
// In general, only the current row of the outermost paragraph
// will be redrawn. Particular cases where selection spans
// multiple paragraph are correctly detected in TextMetrics.
- tm.draw(pi, 0, y);
+ tm.draw(pi, 0, y);
break;
case DecorationUpdate: