From 1eba5295d868793052e6cb1c79cdff1ee1f0a1cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Vigna?= Date: Tue, 16 Apr 2002 14:10:39 +0000 Subject: [PATCH] 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 --- src/BufferView_pimpl.C | 40 +++++++++++++++------- src/ChangeLog | 21 ++++++++++++ src/insets/ChangeLog | 29 ++++++++++++++++ src/insets/inset.h | 2 +- src/insets/insetcollapsable.C | 4 +-- src/insets/insetcollapsable.h | 2 +- src/insets/insettabular.C | 25 +++++++++----- src/insets/insettabular.h | 2 +- src/insets/insettext.C | 63 +++++++++++++++++++++++++++++++---- src/insets/insettext.h | 6 ++-- src/lyxcursor.C | 12 +++++++ src/lyxcursor.h | 7 ++++ src/lyxfunc.C | 32 +++++++++++++++--- src/text2.C | 41 +++++++++++++++++++++-- 14 files changed, 244 insertions(+), 42 deletions(-) diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index ee6dde8a4c..1a43fd4abc 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -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(); } diff --git a/src/ChangeLog b/src/ChangeLog index 033155323c..966b5a71ef 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,24 @@ +2002-04-16 Juergen Vigna + + * 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 + + * 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 * buffer.[Ch] (getBibkeyList): make it const. diff --git a/src/insets/ChangeLog b/src/insets/ChangeLog index b86eca6d83..f110b20fb2 100644 --- a/src/insets/ChangeLog +++ b/src/insets/ChangeLog @@ -1,3 +1,32 @@ +2002-04-16 Juergen Vigna + + * 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 + + * 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 * insetbib.C (getKeys): strip leading '\t's from the line too. diff --git a/src/insets/inset.h b/src/insets/inset.h index 9b0a4c5149..77c03f1988 100644 --- a/src/insets/inset.h +++ b/src/insets/inset.h @@ -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; } diff --git a/src/insets/insetcollapsable.C b/src/insets/insetcollapsable.C index 53e97c3f42..ca3defd7c8 100644 --- a/src/insets/insetcollapsable.C +++ b/src/insets/insetcollapsable.C @@ -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()); } diff --git a/src/insets/insetcollapsable.h b/src/insets/insetcollapsable.h index d76ff26158..e7f496e5f8 100644 --- a/src/insets/insetcollapsable.h +++ b/src/insets/insetcollapsable.h @@ -87,7 +87,7 @@ public: /// bool updateInsetInInset(BufferView *, Inset *); /// - unsigned int insetInInsetY(); + int insetInInsetY() const; /// bool insetButtonRelease(BufferView *, int, int, int); /// diff --git a/src/insets/insettabular.C b/src/insets/insettabular.C index b4496156bc..3a2d8ece08 100644 --- a/src/insets/insettabular.C +++ b/src/insets/insettabular.C @@ -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(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); diff --git a/src/insets/insettabular.h b/src/insets/insettabular.h index 29689b89a9..ccaa6a8a0e 100644 --- a/src/insets/insettabular.h +++ b/src/insets/insettabular.h @@ -117,7 +117,7 @@ public: /// bool updateInsetInInset(BufferView *, Inset *); /// - unsigned int insetInInsetY(); + int insetInInsetY() const; /// UpdatableInset * getLockingInset() const; /// diff --git a/src/insets/insettext.C b/src/insets/insettext.C index 2919ea6d72..27db48df81 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -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); diff --git a/src/insets/insettext.h b/src/insets/insettext.h index 20fcfbdaec..bb6beb7689 100644 --- a/src/insets/insettext.h +++ b/src/insets/insettext.h @@ -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; diff --git a/src/lyxcursor.C b/src/lyxcursor.C index 47489a0fdd..a6caad2024 100644 --- a/src/lyxcursor.C +++ b/src/lyxcursor.C @@ -127,3 +127,15 @@ Row * LyXCursor::row() const { return row_; } + + +void LyXCursor::irow(Row * r) +{ + irow_ = r; +} + + +Row * LyXCursor::irow() const +{ + return irow_; +} diff --git a/src/lyxcursor.h b/src/lyxcursor.h index fe3cc2842c..d33515c44d 100644 --- a/src/lyxcursor.h +++ b/src/lyxcursor.h @@ -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_; }; /// diff --git a/src/lyxfunc.C b/src/lyxfunc.C index af1d9f9571..d4986d6b2f 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -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; diff --git a/src/text2.C b/src/text2.C index 089965c997..64c45adcd4 100644 --- a/src/text2.C +++ b/src/text2.C @@ -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(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(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 }