Losts of fixes to cursor handling with insets. Cursor up/down now can

transverse also inset if they are on it's way, Page up/down for InsetText
fixed (cleanly now as I finally understood the algorithm ;) This fixes some
non reported bugs, some in Michaels list, some reported on the mailing
list and #314 on our buglist.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@4008 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Jürgen Vigna 2002-04-16 14:10:39 +00:00
parent 48f5aa9517
commit 1eba5295d8
14 changed files with 244 additions and 42 deletions

View File

@ -912,13 +912,13 @@ Box BufferView::Pimpl::insetDimensions(LyXText const & text,
int const width = inset.width(bv_, font);
int const inset_x = font.isVisibleRightToLeft()
? (cursor.x() - width) : cursor.x();
? (cursor.ix() - width) : cursor.ix();
return Box(
inset_x + inset.scroll(),
inset_x + width,
cursor.y() - inset.ascent(bv_, font),
cursor.y() + inset.descent(bv_, font));
cursor.iy() - inset.ascent(bv_, font),
cursor.iy() + inset.descent(bv_, font));
}
@ -1167,19 +1167,27 @@ void BufferView::Pimpl::cursorPrevious(LyXText * text)
int y = text->first_y;
Row * cursorrow = text->cursor.row();
text->setCursorFromCoordinates(bv_, bv_->text->cursor.x_fix(), y);
text->setCursorFromCoordinates(bv_, text->cursor.x_fix(), y);
finishUndo();
// This is to allow jumping over large insets
if ((cursorrow == text->cursor.row()))
text->cursorUp(bv_);
if (text->inset_owner ||
text->cursor.row()->height() < workarea_.height())
screen_->draw(bv_->text, bv_,
if (text->inset_owner) {
int new_y = bv_->text->cursor.iy()
+ bv_->theLockingInset()->insetInInsetY()
+ y
+ text->cursor.row()->height()
- workarea_.height() + 1;
screen_->draw(bv_->text, bv_, new_y < 0 ? 0 : new_y);
} else if (text->cursor.row()->height() < workarea_.height()) {
screen_->draw(text, bv_,
text->cursor.y()
- text->cursor.row()->baseline()
+ text->cursor.row()->height()
- workarea_.height() + 1);
}
updateScrollbar();
}
@ -1190,8 +1198,11 @@ void BufferView::Pimpl::cursorNext(LyXText * text)
return;
int y = text->first_y + workarea_.height();
// if (text->inset_owner)
// y += bv_->text->first;
if (text->inset_owner && !text->first_y) {
y -= (bv_->text->cursor.iy()
- bv_->text->first_y
+ bv_->theLockingInset()->insetInInsetY());
}
text->getRowNearY(y);
Row * cursorrow = text->cursor.row();
@ -1201,10 +1212,15 @@ void BufferView::Pimpl::cursorNext(LyXText * text)
if ((cursorrow == bv_->text->cursor.row()))
text->cursorDown(bv_);
if (text->inset_owner ||
text->cursor.row()->height() < workarea_.height())
screen_->draw(bv_->text, bv_, text->cursor.y() -
if (text->inset_owner) {
screen_->draw(bv_->text, bv_,
bv_->text->cursor.iy()
+ bv_->theLockingInset()->insetInInsetY()
+ y - text->cursor.row()->baseline());
} else if (text->cursor.row()->height() < workarea_.height()) {
screen_->draw(text, bv_, text->cursor.y() -
text->cursor.row()->baseline());
}
updateScrollbar();
}

View File

@ -1,3 +1,24 @@
2002-04-16 Juergen Vigna <jug@sad.it>
* text2.C (setCursor): set also the irow().
(setCursorFromCoordinates): fixed to set the (i) cursor values right!
(cursorUp):
(cursorDown): support for locking an inset if the x_fix value goes
inside it. That way I can transverse insets too with cursor up/down.
* lyxrow.h: added irow helper function same as other (i) functions.
* BufferView_pimpl.C (cursorPrevious):
(cursorNext): fixed for insets!
2002-04-15 Juergen Vigna <jug@sad.it>
* BufferView_pimpl.C (insetDimensions): use ix/iy values for inset
position otherwise it is wrong in some cases.
* lyxfunc.C (dispatch): fix FINISHED UP/DOWN to handle x position
inside the inset before the call.
2002-04-16 Angus Leeming <a.leeming@ic.ac.uk>
* buffer.[Ch] (getBibkeyList): make it const.

View File

@ -1,3 +1,32 @@
2002-04-16 Juergen Vigna <jug@sad.it>
* insettabular.C (insetButtonPress):
(insetUnlock): call a redraw on unlocking the cell inset.
* insettext.C (insetButtonPress): same as below.
(lockInset): new function to set initial values when inset should
be locked.
(insetButtonPress): use above function.
(insetUnlock): don't force a repaint only set the updateStatus. The
outside world should repaint if it thinks it should be done!
* insettabular.C (insetButtonPress): init values if not set as locked
as we are locked if someone presses on us and don't call the edit()
call of the InsetText to lock it do it as BufferView does it!
* inset.h (insetInInsetY): make func const and return an int.
* insettext.C:
* insettabular.C:
* insetcollapsable.C: adapt the above changed function.
2002-04-15 Juergen Vigna <jug@sad.it>
* insettext.C (getCursorPos): return relative position as to be able
to give them directly to the edit() call.
(edit): we have to set also x_fix as it is not set inside the
setCursorFromCoordinates call!
(insetMotionNotify): ditto.
2002-04-16 Angus Leeming <a.leeming@ic.ac.uk>
* insetbib.C (getKeys): strip leading '\t's from the line too.

View File

@ -478,7 +478,7 @@ public:
virtual UpdatableInset * getFirstLockingInsetOfType(Inset::Code c)
{ return (c == lyxCode()) ? this : 0; }
///
virtual unsigned int insetInInsetY() { return 0; }
virtual int insetInInsetY() const { return 0; }
///
virtual bool updateInsetInInset(BufferView *, Inset *)
{ return false; }

View File

@ -252,7 +252,7 @@ void InsetCollapsable::edit(BufferView * bv, int xp, int yp,
if (!bv->lockInset(this))
return;
if (yp <= button_bottom_y) {
inset.edit(bv);
inset.edit(bv, xp, 0, button);
} else {
LyXFont font(LyXFont::ALL_SANE);
int yy = ascent(bv, font) + yp -
@ -481,7 +481,7 @@ bool InsetCollapsable::updateInsetInInset(BufferView * bv, Inset *in)
}
unsigned int InsetCollapsable::insetInInsetY()
int InsetCollapsable::insetInInsetY() const
{
return inset.insetInInsetY() - (top_baseline - inset.y());
}

View File

@ -87,7 +87,7 @@ public:
///
bool updateInsetInInset(BufferView *, Inset *);
///
unsigned int insetInInsetY();
int insetInInsetY() const;
///
bool insetButtonRelease(BufferView *, int, int, int);
///

View File

@ -598,6 +598,7 @@ void InsetTabular::insetUnlock(BufferView * bv)
if (the_locking_inset) {
the_locking_inset->insetUnlock(bv);
the_locking_inset = 0;
updateLocal(bv, CELL, false);
}
hideInsetCursor(bv);
oldcell = -1;
@ -729,7 +730,7 @@ bool InsetTabular::updateInsetInInset(BufferView * bv, Inset * inset)
}
unsigned int InsetTabular::insetInInsetY()
int InsetTabular::insetInInsetY() const
{
if (!the_locking_inset)
return 0;
@ -776,6 +777,12 @@ void InsetTabular::insetButtonPress(BufferView * bv, int x, int y, int button)
int const orow = actrow;
hideInsetCursor(bv);
if (!locked) {
locked = true;
the_locking_inset = 0;
inset_x = 0;
inset_y = 0;
}
setPos(bv, x, y);
if (actrow != orow)
updateLocal(bv, NONE, false);
@ -801,20 +808,20 @@ void InsetTabular::insetButtonPress(BufferView * bv, int x, int y, int button)
return;
} else if (the_locking_inset) {
the_locking_inset->insetUnlock(bv);
the_locking_inset = 0;
updateLocal(bv, CELL, false);
}
the_locking_inset = 0;
if (button == 2) {
localDispatch(bv, LFUN_PASTESELECTION, "paragraph");
return;
}
if (inset_hit && bv->theLockingInset()) {
// only activate the Inset so that no internal inset is hit
// by this call. It should be only hit by the insetButtonPress call.
if (activateCellInsetAbs(bv, 0, 0, 0))
the_locking_inset->insetButtonPress(bv,
x - inset_x,
y - inset_y,
button);
if (!bv->lockInset(static_cast<UpdatableInset*>(tabular->GetCellInset(actcell)))) {
lyxerr[Debug::INSETS] << "Cannot lock inset" << endl;
return;
}
the_locking_inset->insetButtonPress(
bv, x - inset_x, y - inset_y, button);
return;
}
showInsetCursor(bv);

View File

@ -117,7 +117,7 @@ public:
///
bool updateInsetInInset(BufferView *, Inset *);
///
unsigned int insetInInsetY();
int insetInInsetY() const;
///
UpdatableInset * getLockingInset() const;
///

View File

@ -675,9 +675,11 @@ void InsetText::edit(BufferView * bv, int x, int y, unsigned int button)
lt = getLyXText(bv);
clear = true;
}
if (!checkAndActivateInset(bv, x, tmp_y, button))
if (!checkAndActivateInset(bv, x, tmp_y, button)) {
lt->setCursorFromCoordinates(bv, x - drawTextXOffset,
y + insetAscent);
lt->cursor.x_fix(lt->cursor.x());
}
lt->clearSelection();
finishUndo();
// If the inset is empty set the language of the current font to the
@ -756,15 +758,21 @@ void InsetText::insetUnlock(BufferView * bv)
if (the_locking_inset) {
the_locking_inset->insetUnlock(bv);
the_locking_inset = 0;
updateLocal(bv, CURSOR_PAR, false);
}
hideInsetCursor(bv);
no_selection = true;
locked = false;
int code;
#if 0
if (drawFrame_ == LOCKED)
code = CURSOR|CLEAR_FRAME;
else
code = CURSOR;
#else
if (drawFrame_ == LOCKED)
code = CLEAR_FRAME;
#endif
bool clear = false;
if (!lt) {
lt = getLyXText(bv);
@ -786,9 +794,47 @@ void InsetText::insetUnlock(BufferView * bv)
}
if (clear)
lt = 0;
#if 0
updateLocal(bv, code, false);
#else
setUpdateStatus(bv, code);
#endif
}
void InsetText::lockInset(BufferView * bv)
{
locked = true;
the_locking_inset = 0;
inset_pos = inset_x = inset_y = 0;
inset_boundary = false;
inset_par = 0;
old_par = 0;
bool clear = false;
if (!lt) {
lt = getLyXText(bv);
clear = true;
}
lt->setCursor(bv, par, 0);
lt->clearSelection();
finishUndo();
// If the inset is empty set the language of the current font to the
// language to the surronding text (if different).
if (par->size() == 0 && !par->next() &&
bv->getParentLanguage(this) != lt->current_font.language()) {
LyXFont font(LyXFont::ALL_IGNORE);
font.setLanguage(bv->getParentLanguage(this));
setFont(bv, font, false);
}
if (clear)
lt = 0;
int code = CURSOR;
if (drawFrame_ == LOCKED)
code = CURSOR|DRAW_FRAME;
setUpdateStatus(bv, code);
}
void InsetText::lockInset(BufferView * bv, UpdatableInset * inset)
{
the_locking_inset = inset;
@ -932,6 +978,9 @@ void InsetText::insetButtonPress(BufferView * bv, int x, int y, int button)
mouse_x = x;
mouse_y = y;
if (!locked)
lockInset(bv);
int tmp_x = x - drawTextXOffset;
int tmp_y = y + insetAscent - getLyXText(bv)->first_y;
Inset * inset = bv->checkInsetHit(getLyXText(bv), tmp_x, tmp_y);
@ -1082,6 +1131,7 @@ void InsetText::insetMotionNotify(BufferView * bv, int x, int y, int state)
hideInsetCursor(bv);
LyXCursor cur = lt->cursor;
lt->setCursorFromCoordinates(bv, x - drawTextXOffset, y + insetAscent);
lt->cursor.x_fix(lt->cursor.x());
if (cur == lt->cursor) {
if (clear)
lt = 0;
@ -1700,19 +1750,18 @@ int InsetText::beginningOfMainBody(Buffer const * buf, Paragraph * p) const
}
void InsetText::getCursorPos(BufferView * bv,
int & x, int & y) const
void InsetText::getCursorPos(BufferView * bv, int & x, int & y) const
{
if (the_locking_inset) {
the_locking_inset->getCursorPos(bv, x, y);
return;
}
x = cx(bv);
y = cy(bv);
x = cx(bv) - top_x - TEXT_TO_INSET_OFFSET;
y = cy(bv) - TEXT_TO_INSET_OFFSET;
}
unsigned int InsetText::insetInInsetY()
int InsetText::insetInInsetY() const
{
if (!the_locking_inset)
return 0;
@ -1754,7 +1803,7 @@ void InsetText::showInsetCursor(BufferView * bv, bool show)
int const asc = lyxfont::maxAscent(font);
int const desc = lyxfont::maxDescent(font);
bv->fitLockedInsetCursor(cx(bv), ciy(bv), asc, desc);
bv->fitLockedInsetCursor(cx(bv), cy(bv), asc, desc);
if (show)
bv->showLockedInsetCursor(cx(bv), cy(bv), asc, desc);
setCursorVisible(true);

View File

@ -150,7 +150,7 @@ public:
///
void getCursorPos(BufferView *, int & x, int & y) const;
///
unsigned int insetInInsetY();
int insetInInsetY() const;
///
void toggleInsetCursor(BufferView *);
///
@ -259,7 +259,9 @@ public:
protected:
///
void updateLocal(BufferView *, int what, bool mark_dirty) const;
///
/// set parameters for an initial lock of this inset
void lockInset(BufferView *);
/// lock an inset inside this one
void lockInset(BufferView *, UpdatableInset *);
///
mutable int drawTextXOffset;

View File

@ -127,3 +127,15 @@ Row * LyXCursor::row() const
{
return row_;
}
void LyXCursor::irow(Row * r)
{
irow_ = r;
}
Row * LyXCursor::irow() const
{
return irow_;
}

View File

@ -63,6 +63,10 @@ public:
void row(Row * r);
///
Row * row() const;
///
void irow(Row * r);
///
Row * irow() const;
private:
/// The paragraph the cursor is in.
Paragraph * par_;
@ -84,6 +88,9 @@ private:
int iy_;
///
Row * row_;
/// the row of the position before the inset when we put
/// the cursor on the end of the row before, otherwise equal to row.
Row * irow_;
};
///

View File

@ -885,6 +885,12 @@ string const LyXFunc::dispatch(kb_action action, string argument)
if ((action > 1) || ((action == LFUN_UNKNOWN_ACTION) &&
(!keyseq.deleted())))
{
UpdatableInset * inset = owner->view()->theLockingInset();
#if 1
int inset_x;
int dummy_y;
inset->getCursorPos(owner->view(), inset_x, dummy_y);
#endif
if ((action == LFUN_UNKNOWN_ACTION)
&& argument.empty()) {
argument = keyseq.getiso();
@ -896,7 +902,7 @@ string const LyXFunc::dispatch(kb_action action, string argument)
} else if (action == LFUN_REDO) {
owner->view()->menuRedo();
goto exit_with_message;
} else if (((result=owner->view()->theLockingInset()->
} else if (((result=inset->
// Hand-over to inset's own dispatch:
localDispatch(owner->view(), action, argument)) ==
UpdatableInset::DISPATCHED) ||
@ -918,8 +924,16 @@ string const LyXFunc::dispatch(kb_action action, string argument)
}
goto exit_with_message;
} else if (result == UpdatableInset::FINISHED_UP) {
if (TEXT()->cursor.row()->previous()) {
if (TEXT()->cursor.irow()->previous()) {
#if 1
TEXT()->setCursorFromCoordinates(
owner->view(), TEXT()->cursor.ix() + inset_x,
TEXT()->cursor.iy() -
TEXT()->cursor.irow()->baseline() - 1);
TEXT()->cursor.x_fix(TEXT()->cursor.x());
#else
TEXT()->cursorUp(owner->view());
#endif
moveCursorUpdate(true, false);
owner->showState();
} else {
@ -927,10 +941,20 @@ string const LyXFunc::dispatch(kb_action action, string argument)
}
goto exit_with_message;
} else if (result == UpdatableInset::FINISHED_DOWN) {
if (TEXT()->cursor.row()->next())
if (TEXT()->cursor.irow()->next()) {
#if 1
TEXT()->setCursorFromCoordinates(
owner->view(), TEXT()->cursor.ix() + inset_x,
TEXT()->cursor.iy() -
TEXT()->cursor.irow()->baseline() +
TEXT()->cursor.irow()->height() + 1);
TEXT()->cursor.x_fix(TEXT()->cursor.x());
#else
TEXT()->cursorDown(owner->view());
else
#endif
} else {
TEXT()->cursorRight(owner->view());
}
moveCursorUpdate(true, false);
owner->showState();
goto exit_with_message;

View File

@ -2064,6 +2064,7 @@ void LyXText::setCursor(BufferView * bview, LyXCursor & cur, Paragraph * par,
int y = 0;
Row * row = getRow(par, pos, y);
Row * old_row = row;
cur.irow(row);
// if we are before the first char of this row and are still in the
// same paragraph and there is a previous row then put the cursor on
// the end of the previous row
@ -2262,19 +2263,28 @@ void LyXText::setCursorFromCoordinates(BufferView * bview, LyXCursor & cur,
cur.par(row->par());
cur.pos(row->pos() + column);
cur.x(x);
cur.ix(x);
cur.y(y + row->baseline());
cur.row(row);
Inset * ins;
if (row->next() && cur.pos() &&
if (row->next() && row->next()->pos() == cur.pos() &&
cur.par() == row->next()->par() &&
cur.par()->getChar(cur.pos()) == Paragraph::META_INSET &&
(ins=cur.par()->getInset(cur.pos())) &&
(ins->needFullRow() || ins->display()))
{
// we enter here if we put the cursor on the end of the row before
// a inset which uses a full row and in that case we HAVE to calculate
// the right (i) values.
pos_type last = rowLastPrintable(row);
float x = getCursorX(bview, row->next(), cur.pos(), last, bound);
cur.ix(int(x));
cur.iy(y + row->height() + row->next()->baseline());
cur.irow(row->next());
} else {
cur.iy(cur.y());
cur.ix(cur.x());
cur.irow(row);
}
cur.row(row);
cur.boundary(bound);
}
@ -2311,16 +2321,41 @@ void LyXText::cursorRight(BufferView * bview, bool internal) const
void LyXText::cursorUp(BufferView * bview) const
{
#if 1
int x = cursor.x_fix();
int y = cursor.y() - cursor.row()->baseline() - 1;
setCursorFromCoordinates(bview, x, y);
int y1 = cursor.iy() - first_y;
int y2 = y1;
Inset * inset_hit = bview->checkInsetHit(const_cast<LyXText *>(this), x, y1);
if (inset_hit && isHighlyEditableInset(inset_hit)) {
inset_hit->edit(bview, x, y - (y2 - y1), 0);
}
#else
setCursorFromCoordinates(bview, cursor.x_fix(),
cursor.y() - cursor.row()->baseline() - 1);
#endif
}
void LyXText::cursorDown(BufferView * bview) const
{
#if 1
int x = cursor.x_fix();
int y = cursor.y() - cursor.row()->baseline() +
cursor.row()->height() + 1;
setCursorFromCoordinates(bview, x, y);
int y1 = cursor.iy() - first_y;
int y2 = y1;
Inset * inset_hit = bview->checkInsetHit(const_cast<LyXText *>(this), x, y1);
if (inset_hit && isHighlyEditableInset(inset_hit)) {
inset_hit->edit(bview, x, y - (y2 - y1), 0);
}
#else
setCursorFromCoordinates(bview, cursor.x_fix(),
cursor.y() - cursor.row()->baseline()
+ cursor.row()->height() + 1);
#endif
}