}
// FIXME: needed when ?
- bv_->text->top_y(screen().topCursorVisible(bv_->text->cursor, bv_->text->top_y()));
+ bv_->text->top_y(screen().topCursorVisible(bv_->text));
// Buffer-dependent dialogs should be updated or
// hidden. This should go here because some dialogs (eg ToC)
bv_->theLockingInset(the_locking_inset);
}
- bv_->text->top_y(screen().topCursorVisible(bv_->text->cursor, bv_->text->top_y()));
+ bv_->text->top_y(screen().topCursorVisible(bv_->text));
switchKeyMap();
owner_->busy(false);
+2003-06-27 André Pönitz <poenitz@gmx.net>
+
+ * BufferView_pimpl.C:
+ * bufferview_funcs.C:
+ * lyxcursor.C:
+ * lyxcursor.h:
+ * lyxfunc.C:
+ * lyxtext.h:
+ * rowpainter.C:
+ * text.C:
+ * text2.C:
+ * text3.C: remove LyXCursor::row_ member
+
2003-06-26 Alfredo Brauntein <abraunst@lyx.org>
* lyx_main.C (LyX): get full path of document loaded on the
if (font.language() != ignore_language ||
font.number() != LyXFont::IGNORE) {
LyXCursor & cursor = text->cursor;
- text->computeBidiTables(bv->buffer(), cursor.row());
+ text->computeBidiTables(bv->buffer(), text->cursorRow());
if (cursor.boundary() !=
text->isBoundary(bv->buffer(), *cursor.par(), cursor.pos(),
text->real_current_font))
+
+2003-06-27 André Pönitz <poenitz@gmx.net>
+
+ * screen.[Ch]: take care of removed LyXCursor::row_ member
+
2003-06-19 Angus Leeming <leeming@lyx.org>
* Dialogs.h: (showTexinfo):
}
-unsigned int LyXScreen::topCursorVisible(LyXCursor const & cursor, int top_y)
+unsigned int LyXScreen::topCursorVisible(LyXText * text)
{
- int const vheight = workarea().workHeight();
+ LyXCursor const & cursor = text->cursor;
+ int top_y = text->top_y();
int newtop = top_y;
+ int const vheight = workarea().workHeight();
- RowList::iterator row = cursor.row();
+ RowList::iterator row = text->cursorRow();
#warning SUPER HACK DISABLED (Lgb)
#if 0
+ row->height()
- row->baseline() - vheight;
} else {
- // scroll down
- newtop = cursor.y()
- - vheight / 2; /* the scroll region must be so big!! */
+ // scroll down, the scroll region must be so big!!
+ newtop = cursor.y() - vheight / 2;
}
} else if (static_cast<int>((cursor.y()) - row->baseline()) <
bool LyXScreen::fitCursor(LyXText * text, BufferView * bv)
{
// Is a change necessary?
- int const newtop = topCursorVisible(text->cursor, text->top_y());
+ int const newtop = topCursorVisible(text);
bool const result = (newtop != text->top_y());
if (result) {
draw(text, bv, newtop);
int const bottom = min(
max(static_cast<int>(text->selection.end.y()
- - text->selection.end.row()->baseline()
- + text->selection.end.row()->height()),
+ - text->getRow(text->selection.end)->baseline()
+ + text->getRow(text->selection.end)->height()),
text->top_y()),
static_cast<int>(text->top_y() + workarea().workHeight()));
int const top = min(
max(static_cast<int>(text->selection.start.y() -
- text->selection.start.row()->baseline()),
+ text->getRow(text->selection.start)->baseline()),
text->top_y()),
static_cast<int>(text->top_y() + workarea().workHeight()));
return;
int const top_tmp = text->toggle_cursor.y()
- - text->toggle_cursor.row()->baseline();
+ - text->getRow(text->toggle_cursor)->baseline();
int const bottom_tmp = text->toggle_end_cursor.y()
- - text->toggle_end_cursor.row()->baseline()
- + text->toggle_end_cursor.row()->height();
+ - text->getRow(text->toggle_end_cursor)->baseline()
+ + text->getRow(text->toggle_end_cursor)->height();
int const offset = yo < 0 ? yo : 0;
int const bottom = min(max(bottom_tmp, text->top_y()),
/**
* topCursorVisible - get a new "top" to make the cursor visible
- * @param c the cursor
- * @param top_y the current y location of the containing region
+ * in a LyXText
*
* This helper function calculates a new y co-ordinate for
* the top of the containing region such that the cursor contained
* within the LyXText is "nicely" visible.
*/
- virtual unsigned int topCursorVisible(LyXCursor const & c, int top_y);
+ virtual unsigned int topCursorVisible(LyXText *);
/**
* fitCursor - fit the cursor onto the work area
+
+2003-06-27 André Pönitz <poenitz@gmx.net>
+
+ * insettext.C: take care of removed LyXCursor::row_ member
+
2003-06-21 Alfredo Braunstein <abraunst@libero.it>
* inseterror.[Ch]: removed
RowList::iterator InsetText::crow(BufferView * bv) const
{
- return getLyXText(bv)->cursor.row();
+ return getLyXText(bv)->cursorRow();
}
inset_y = ciy(bv) + drawTextYOffset;
}
- t->top_y(bv->screen().topCursorVisible(t->cursor, t->top_y()));
+ t->top_y(bv->screen().topCursorVisible(t));
if (!owner()) {
const_cast<InsetText*>(this)->updateLocal(bv, FULL, false);
// this will scroll the screen such that the cursor becomes visible
inset_x = cix(bv) - top_x + drawTextXOffset;
inset_y = ciy(bv) + drawTextYOffset;
}
- t->top_y(bv->screen().topCursorVisible(t->cursor, t->top_y()));
+ t->top_y(bv->screen().topCursorVisible(t));
if (!owner()) {
const_cast<InsetText*>(this)->updateLocal(bv, FULL, false);
// this will scroll the screen such that the cursor becomes visible
LyXCursor::LyXCursor()
: par_(), pos_(0), boundary_(false),
- x_(0), ix_(0), x_fix_(0), y_(0), iy_(0), row_(0)
+ x_(0), ix_(0), x_fix_(0), y_(0), iy_(0)
{}
}
-void LyXCursor::row(RowList::iterator r)
-{
- row_ = r;
-}
-
-
-RowList::iterator LyXCursor::row() const
-{
- return row_;
-}
-
-
void LyXCursor::irow(RowList::iterator r)
{
irow_ = r;
* FIXME: explain why we need this ? especially for y...
*/
int iy() const;
- /// set the row of the paragraph the cursor is in
- void row(RowList::iterator r);
- /// return the row of the paragraph this cursor is in
- RowList::iterator row() const;
/// set the stored next row
void irow(RowList::iterator r);
/**
int y_;
/// the stored next-row y position
int iy_;
- /// the containing row
- RowList::iterator row_;
/// the containing row for the next line
RowList::iterator irow_;
};
}
goto exit_with_message;
case LFUN_DOWN:
- if (boost::next(TEXT()->cursor.row()) != TEXT()->rows().end())
+ if (boost::next(TEXT()->cursorRow()) != TEXT()->rows().end())
TEXT()->cursorDown(view());
else
TEXT()->cursorRight(view());
/// only the top-level LyXText has this non-zero
BufferView * bv_owner;
+ /// returns a pointer to a specified row.
+ RowList::iterator
+ getRow(ParagraphList::iterator pit, lyx::pos_type pos) const;
public:
+ /// returns a pointer cursor row
+ RowList::iterator getRow(LyXCursor const & cursor) const;
+ /// convenience
+ RowList::iterator cursorRow() const;
+
/** returns a pointer to the row near the specified y-coordinate
(relative to the whole text). y is set to the real beginning
of this row
int const endx = text_.selection.end.x();
int const starty = text_.selection.start.y();
int const endy = text_.selection.end.y();
- RowList::iterator startrow = text_.selection.start.row();
- RowList::iterator endrow = text_.selection.end.row();
+ RowList::iterator startrow = text_.getRow(text_.selection.start);
+ RowList::iterator endrow = text_.getRow(text_.selection.end);
if (text_.bidi_same_direction) {
int x;
// move one row up!
// This touches only the screen-update. Otherwise we would may have
// an empty row on the screen
- if (cursor.pos() && cursor.row()->pos() == cursor.pos()
- && !cursor.row()->par()->isNewline(cursor.pos() - 1))
+ if (cursor.pos() && cursorRow()->pos() == cursor.pos()
+ && !cursorRow()->par()->isNewline(cursor.pos() - 1))
{
cursorLeft(bv());
}
- int y = cursor.y() - cursor.row()->baseline();
+ int y = cursor.y() - cursorRow()->baseline();
// Do not forget the special right address boxes
if (layout->margintype == MARGIN_RIGHT_ADDRESS_BOX) {
- RowList::iterator r = cursor.row();
+ RowList::iterator r = cursorRow();
RowList::iterator beg = rows().begin();
while (r != beg && boost::prior(r)->par() == r->par()) {
postPaint(y);
- removeParagraph(cursor.row());
+ removeParagraph(cursorRow());
// set the dimensions of the cursor row
- cursor.row()->fill(fill(cursor.row(), workWidth()));
+ cursorRow()->fill(fill(cursorRow(), workWidth()));
- setHeightOfRow(cursor.row());
+ setHeightOfRow(cursorRow());
#warning Trouble Point! (Lgb)
// When ::breakParagraph is called from within an inset we must
while (!next_par->empty() && next_par->isNewline(0))
next_par->erase(0);
- insertParagraph(next_par, boost::next(cursor.row()));
+ insertParagraph(next_par, boost::next(cursorRow()));
updateCounters();
// This check is necessary. Otherwise the new empty paragraph will
else
setCursor(cursor.par(), 0);
- if (boost::next(cursor.row()) != rows().end())
- breakAgain(boost::next(cursor.row()));
+ if (boost::next(cursorRow()) != rows().end())
+ breakAgain(boost::next(cursorRow()));
need_break_row = rows().end();
}
// When the free-spacing option is set for the current layout,
// disable the double-space checking
- bool const freeSpacing = cursor.row()->par()->layout()->free_spacing ||
- cursor.row()->par()->isFreeSpacing();
+ bool const freeSpacing = cursorRow()->par()->layout()->free_spacing ||
+ cursorRow()->par()->isFreeSpacing();
if (lyxrc.auto_number) {
static string const number_operators = "+-/*";
}
// the display inset stuff
- if (cursor.row()->pos() < cursor.row()->par()->size()
- && cursor.row()->par()->isInset(cursor.row()->pos())) {
- Inset * inset = cursor.row()->par()->getInset(cursor.row()->pos());
+ if (cursorRow()->pos() < cursorRow()->par()->size()
+ && cursorRow()->par()->isInset(cursorRow()->pos())) {
+ Inset * inset = cursorRow()->par()->getInset(cursorRow()->pos());
if (inset && (inset->display() || inset->needFullRow())) {
// force a new break
- cursor.row()->fill(-1); // to force a new break
+ cursorRow()->fill(-1); // to force a new break
}
}
// get the cursor row fist
- RowList::iterator row = cursor.row();
+ RowList::iterator row = cursorRow();
int y = cursor.y() - row->baseline();
if (c != Paragraph::META_INSET) {
// Here case LyXText::InsertInset already insertet the character
|| cursor.par()->isNewline(cursor.pos())
|| ((cursor.pos() + 1 < cursor.par()->size()) &&
cursor.par()->isInset(cursor.pos() + 1))
- || cursor.row()->fill() == -1))
+ || cursorRow()->fill() == -1))
{
pos_type z = rowBreakPoint(*boost::prior(row));
cursorRight(bv());
else {
LyXCursor tmpcursor = cursor;
- tmpcursor.row(0); // ??
selection.set(true); // to avoid deletion
cursorRightOneWord();
setCursor(tmpcursor, tmpcursor.par(), tmpcursor.pos());
cursorLeft(bv());
else {
LyXCursor tmpcursor = cursor;
- tmpcursor.row(0); // ??
selection.set(true); // to avoid deletion
cursorLeftOneWord();
setCursor(tmpcursor, tmpcursor.par(), tmpcursor.pos());
LyXCursor tmpcursor = cursor;
// We can't store the row over a regular setCursor
// so we set it to 0 and reset it afterwards.
- tmpcursor.row(0); // ??
selection.set(true); // to avoid deletion
cursorEnd();
setCursor(tmpcursor, tmpcursor.par(), tmpcursor.pos());
++pos;
}
- if (to.row() != from.row())
- postPaint(from.y() - from.row()->baseline());
+ if (getRow(to) != getRow(from))
+ postPaint(from.y() - getRow(from)->baseline());
}
cursorLeft(bv());
// the layout things can change the height of a row !
- int const tmpheight = cursor.row()->height();
- setHeightOfRow(cursor.row());
- if (cursor.row()->height() != tmpheight) {
- postPaint(cursor.y() - cursor.row()->baseline());
+ int const tmpheight = cursorRow()->height();
+ setHeightOfRow(cursorRow());
+ if (cursorRow()->height() != tmpheight) {
+ postPaint(cursor.y() - cursorRow()->baseline());
}
return;
}
}
ParagraphList::iterator tmppit = cursor.par();
- RowList::iterator tmprow = cursor.row();
+ RowList::iterator tmprow = cursorRow();
// We used to do cursorLeftIntern() here, but it is
// not a good idea since it triggers the auto-delete
if (cursor.pos())
cursor.pos(cursor.pos() - 1);
- postPaint(cursor.y() - cursor.row()->baseline());
+ postPaint(cursor.y() - cursorRow()->baseline());
// remove the lost paragraph
// This one is not safe, since the paragraph that the tmprow and the
//RemoveRow(tmprow);
// This rebuilds the rows.
- appendParagraph(cursor.row());
+ appendParagraph(cursorRow());
updateCounters();
// the row may have changed, block, hfills etc.
}
}
- RowList::iterator row = cursor.row();
+ RowList::iterator row = cursorRow();
int y = cursor.y() - row->baseline();
pos_type z;
// remember that a space at the end of a row doesnt count
}
+RowList::iterator LyXText::cursorRow() const
+{
+ return getRow(cursor.par(), cursor.pos());
+}
+
+
+RowList::iterator LyXText::getRow(LyXCursor const & cur) const
+{
+ return getRow(cur.par(), cur.pos());
+}
+
+
+RowList::iterator
+LyXText::getRow(ParagraphList::iterator pit, pos_type pos) const
+{
+ if (rows().empty())
+ return rowlist_.end();
+
+ // find the first row of the specified paragraph
+ RowList::iterator rit = rowlist_.begin();
+ RowList::iterator end = rowlist_.end();
+ while (boost::next(rit) != end && rit->par() != pit) {
+ ++rit;
+ }
+
+ // now find the wanted row
+ while (rit->pos() < pos
+ && boost::next(rit) != end
+ && boost::next(rit)->par() == pit
+ && boost::next(rit)->pos() <= pos) {
+ ++rit;
+ }
+
+ return rit;
+}
+
// returns pointer to a specified row
RowList::iterator
LyXText::getRow(ParagraphList::iterator pit, pos_type pos, int & y) const
void LyXText::redoHeightOfParagraph()
{
- RowList::iterator tmprow = cursor.row();
+ RowList::iterator tmprow = cursorRow();
int y = cursor.y() - tmprow->baseline();
setHeightOfRow(tmprow);
void LyXText::redoDrawingOfParagraph(LyXCursor const & cur)
{
- RowList::iterator tmprow = cur.row();
+ RowList::iterator tmprow = getRow(cur);
int y = cur.y() - tmprow->baseline();
setHeightOfRow(tmprow);
void LyXText::redoParagraphs(LyXCursor const & cur,
ParagraphList::iterator endpit)
{
- RowList::iterator tmprit = cur.row();
+ RowList::iterator tmprit = getRow(cur);
int y = cur.y() - tmprit->baseline();
ParagraphList::iterator first_phys_pit;
void LyXText::cursorHome()
{
- setCursor(cursor.par(), cursor.row()->pos());
+ setCursor(cursor.par(), cursorRow()->pos());
}
if (cursor.par()->empty())
return;
- RowList::iterator rit = cursor.row();
+ RowList::iterator rit = cursorRow();
RowList::iterator next_rit = boost::next(rit);
ParagraphList::iterator pit = rit->par();
pos_type last_pos = lastPos(*this, rit);
while (tmppit != boost::prior(selection.start.par())) {
setCursor(tmppit, 0);
- postPaint(cursor.y() - cursor.row()->baseline());
+ postPaint(cursor.y() - cursorRow()->baseline());
ParagraphList::iterator pit = cursor.par();
ParagraphParameters & params = pit->params();
// check the special right address boxes
if (pit->layout()->margintype == MARGIN_RIGHT_ADDRESS_BOX) {
tmpcursor.par(pit);
- tmpcursor.row(row);
tmpcursor.y(y);
tmpcursor.x(0);
tmpcursor.x_fix(0);
}
}
- cur.row(row);
// y is now the beginning of the cursor row
y += row->baseline();
// y is now the cursor baseline
--pos;
else // potentional bug... BUG (Lgb)
if (pit->isSeparator(pos)) {
- if (pos > cursor.row()->pos() &&
+ if (pos > cursorRow()->pos() &&
bidi_level(pos) % 2 ==
bidi_level(pos - 1) % 2)
--pos;
*/
bool beforeFullRowInset(LyXText & lt, LyXCursor const & cur)
{
- RowList::iterator row = cur.row();
+ RowList::iterator row = lt.getRow(cur);
if (boost::next(row) == lt.rows().end())
return false;
cur.pos(row->pos() + column);
cur.x(x);
cur.y(y + row->baseline());
- cur.row(row);
if (beforeFullRowInset(*this, cur)) {
pos_type const last = lastPrintablePos(*this, row);
{
#if 1
int x = cursor.x_fix();
- int y = cursor.y() - cursor.row()->baseline() - 1;
+ int y = cursor.y() - cursorRow()->baseline() - 1;
setCursorFromCoordinates(x, y);
if (!selecting) {
int topy = top_y();
}
#else
setCursorFromCoordinates(bv(), cursor.x_fix(),
- cursor.y() - cursor.row()->baseline() - 1);
+ cursor.y() - cursorRow()->baseline() - 1);
#endif
}
{
#if 1
int x = cursor.x_fix();
- int y = cursor.y() - cursor.row()->baseline() +
- cursor.row()->height() + 1;
+ int y = cursor.y() - cursorRow()->baseline() +
+ cursorRow()->height() + 1;
setCursorFromCoordinates(x, y);
- if (!selecting && cursor.row() == cursor.irow()) {
+ if (!selecting && cursorRow() == cursor.irow()) {
int topy = top_y();
int y1 = cursor.iy() - topy;
int y2 = y1;
}
#else
setCursorFromCoordinates(bv(), cursor.x_fix(),
- cursor.y() - cursor.row()->baseline()
- + cursor.row()->height() + 1);
+ cursor.y() - cursorRow()->baseline()
+ + cursorRow()->height() + 1);
#endif
}
selection.cursor.par() == old_cursor.par()
&& selection.cursor.pos() == old_cursor.pos());
- if (old_cursor.row() != rows().begin()) {
+ if (getRow(old_cursor) != rows().begin()) {
RowList::iterator
- prevrow = boost::prior(old_cursor.row());
- const_cast<LyXText *>(this)->postPaint(old_cursor.y() - old_cursor.row()->baseline() - prevrow->height());
+ prevrow = boost::prior(getRow(old_cursor));
+ postPaint(old_cursor.y() - getRow(old_cursor)->baseline() - prevrow->height());
tmpcursor = cursor;
cursor = old_cursor; // that undo can restore the right cursor position
#warning FIXME. --end() iterator is usable here
cursor = tmpcursor;
// delete old row
- removeRow(old_cursor.row());
+ removeRow(getRow(old_cursor));
// delete old par
ownerParagraphs().erase(old_cursor.par());
}
setHeightOfRow(prevrow);
} else {
- RowList::iterator nextrow = boost::next(old_cursor.row());
- const_cast<LyXText *>(this)->postPaint(
- old_cursor.y() - old_cursor.row()->baseline());
+ RowList::iterator nextrow = boost::next(getRow(old_cursor));
+ postPaint(old_cursor.y() - getRow(old_cursor)->baseline());
tmpcursor = cursor;
cursor = old_cursor; // that undo can restore the right cursor position
cursor = tmpcursor;
// delete old row
- removeRow(old_cursor.row());
+ removeRow(getRow(old_cursor));
// delete old par
ownerParagraphs().erase(old_cursor.par());
// We are an inset's lyxtext. Tell the top-level lyxtext
// it needs to update the row we're in.
LyXText * t = bv()->text;
- t->postRowPaint(t->cursor.row(), t->cursor.y() - t->cursor.row()->baseline());
+ t->postRowPaint(t->cursorRow(), t->cursor.y() - t->cursorRow()->baseline());
}
// We are an inset's lyxtext. Tell the top-level lyxtext
// it needs to update the row we're in.
LyXText * t = bv()->text;
- t->postRowPaint(t->cursor.row(), t->cursor.y() - t->cursor.row()->baseline());
+ t->postRowPaint(t->cursorRow(), t->cursor.y() - t->cursorRow()->baseline());
}
{
int y = top_y();
- if (cursor.row() == rows().begin()) {
+ if (cursorRow() == rows().begin()) {
if (y > 0) {
int new_y = bv()->text->top_y() - bv()->workHeight();
bv()->screen().draw(bv()->text, bv(), new_y < 0 ? 0 : new_y);
return;
}
- RowList::iterator cursorrow = cursor.row();
+ RowList::iterator cursorrow = cursorRow();
setCursorFromCoordinates(cursor.x_fix(), y);
finishUndo();
int new_y;
- if (cursorrow == bv()->text->cursor.row()) {
+ if (cursorrow == bv()->text->cursorRow()) {
// we have a row which is taller than the workarea. The
// simplest solution is to move to the previous row instead.
cursorUp(true);
if (inset_owner) {
new_y = bv()->text->cursor.iy()
+ bv()->theLockingInset()->insetInInsetY() + y
- + cursor.row()->height()
+ + cursorRow()->height()
- bv()->workHeight() + 1;
} else {
new_y = cursor.y()
- - cursor.row()->baseline()
- + cursor.row()->height()
+ - cursorRow()->baseline()
+ + cursorRow()->height()
- bv()->workHeight() + 1;
}
}
bv()->screen().draw(bv()->text, bv(), new_y < 0 ? 0 : new_y);
- if (cursor.row() != rows().begin()) {
+ if (cursorRow() != rows().begin()) {
LyXCursor cur;
- setCursor(cur, boost::prior(cursor.row())->par(),
- boost::prior(cursor.row())->pos(), false);
+ setCursor(cur, boost::prior(cursorRow())->par(),
+ boost::prior(cursorRow())->pos(), false);
if (cur.y() > top_y()) {
cursorUp(true);
}
{
int topy = top_y();
- if (boost::next(cursor.row()) == rows().end()) {
- int y = cursor.y() - cursor.row()->baseline() +
- cursor.row()->height();
+ if (boost::next(cursorRow()) == rows().end()) {
+ int y = cursor.y() - cursorRow()->baseline() +
+ cursorRow()->height();
if (y > topy + bv()->workHeight()) {
bv()->screen().draw(bv()->text, bv(), bv()->text->top_y() + bv()->workHeight());
bv()->updateScrollbar();
getRowNearY(y);
- RowList::iterator cursorrow = cursor.row();
+ RowList::iterator cursorrow = cursorRow();
setCursorFromCoordinates(cursor.x_fix(), y);
// + bv->workHeight());
finishUndo();
int new_y;
- if (cursorrow == bv()->text->cursor.row()) {
+ if (cursorrow == bv()->text->cursorRow()) {
// we have a row which is taller than the workarea. The
// simplest solution is to move to the next row instead.
cursorDown(true);
if (inset_owner) {
new_y = bv()->text->cursor.iy()
+ bv()->theLockingInset()->insetInInsetY()
- + y - cursor.row()->baseline();
+ + y - cursorRow()->baseline();
} else {
- new_y = cursor.y() - cursor.row()->baseline();
+ new_y = cursor.y() - cursorRow()->baseline();
}
}
bv()->screen().draw(bv()->text, bv(), new_y);
- RowList::iterator next_row = boost::next(cursor.row());
+ RowList::iterator next_row = boost::next(cursorRow());
if (next_row != rows().end()) {
LyXCursor cur;
setCursor(cur, next_row->par(), next_row->pos(), false);
break;
}
- RowList::iterator cursorrow = bv->text->cursor.row();
+ RowList::iterator cursorrow = bv->text->cursorRow();
bv->text->setCursorFromCoordinates(cmd.x, cmd.y + bv->text->top_y());
#if 0
// sorry for this but I have a strange error that the y value jumps at
<< bv->text->cursor.y() << endl;
#endif
// This is to allow jumping over large insets
- if (cursorrow == bv->text->cursor.row()) {
+ if (cursorrow == bv->text->cursorRow()) {
if (cmd.y >= bv->workHeight())
bv->text->cursorDown(false);
else if (cmd.y < 0)