diff --git a/src/BufferView.C b/src/BufferView.C index 47fb2a8992..1cce3fed18 100644 --- a/src/BufferView.C +++ b/src/BufferView.C @@ -424,8 +424,15 @@ void BufferView::putSelectionAt(PosIterator const & cur, if (length) { text->setSelectionRange(cursor(), length); cursor().setSelection(); - if (backwards) + if (backwards) { +#if 0 swap(cursor().cursor_, cursor().anchor_); +#else + DocumentIterator it = cursor(); + cursor().setCursor(cursor().anchor_, false); + cursor().anchor_ = it; +#endif + } } fitCursor(); diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index 755a325c81..a523795405 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -474,7 +474,7 @@ void BufferView::Pimpl::scrollDocView(int value) bv_->cursor().reset(); LyXText * text = bv_->text(); - CursorSlice & cur = bv_->cursor().cursor_.front(); + CursorSlice & cur = bv_->cursor().front(); int y = text->cursorY(cur); if (y < first) text->setCursorFromCoordinates(bv_->cursor(), 0, first); @@ -541,10 +541,10 @@ void BufferView::Pimpl::selectionRequested() } if (!xsel_cache_.set || - cur.cursor_.back() != xsel_cache_.cursor || + cur.back() != xsel_cache_.cursor || cur.anchor_.back() != xsel_cache_.anchor) { - xsel_cache_.cursor = cur.cursor_.back(); + xsel_cache_.cursor = cur.back(); xsel_cache_.anchor = cur.anchor_.back(); xsel_cache_.set = cur.selection(); sel = cur.selectionAsString(false); @@ -613,12 +613,8 @@ void BufferView::Pimpl::update() // Callback for cursor timer void BufferView::Pimpl::cursorToggle() { - if (!buffer_) { - cursor_timeout.restart(); - return; - } - - screen().toggleCursor(*bv_); + if (buffer_) + screen().toggleCursor(*bv_); cursor_timeout.restart(); } @@ -720,7 +716,7 @@ void BufferView::Pimpl::center() bv_->cursor().clearSelection(); int const half_height = workarea().workHeight() / 2; - int new_y = text->cursorY(bv_->cursor().cursor_.front()) - half_height; + int new_y = text->cursorY(bv_->cursor().front()) - half_height; if (new_y < 0) new_y = 0; @@ -1108,6 +1104,7 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & cmd) case LFUN_SETMARK: cur.clearSelection(); if (cur.mark()) { + cur.mark() = false; cur.message(N_("Mark removed")); } else { cur.mark() = true; diff --git a/src/ChangeLog b/src/ChangeLog index 5a814307cb..e399c247fb 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -7,6 +7,22 @@ * BufferView_pimpl.C: rename textwidth -> maxwidth, prepareToPrint -> computeRowMetrics and remove textWidth accessor. +2004-03-01 André Pönitz + + * dociterator.[Ch]: new class for the 'iterator part' of LCursor. + + * cursor.[Ch]: adjust, additioally: remove the 'current_' machinery + + * Makefile.am: + * BufferView.C: + * BufferView_pimpl.C: + * buffer.C: + * lyxfind.C: + * lyxfunc.C: + * text.C: + * text2.C: + * text3.C: adjust + 2004-03-01 Alfredo Braunstein * Bidi.[Ch] (computeTables): const correctness diff --git a/src/Makefile.am b/src/Makefile.am index 9d489999b9..455a559fa8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -130,7 +130,6 @@ lyx_SOURCES = \ changes.h \ chset.C \ chset.h \ - lfuns.h \ config.h.in \ converter.C \ converter.h \ @@ -144,6 +143,8 @@ lyx_SOURCES = \ debug.h \ dimension.C \ dimension.h \ + dociterator.C \ + dociterator.h \ dispatchresult.h \ encoding.C \ encoding.h \ @@ -178,6 +179,7 @@ lyx_SOURCES = \ layout.h \ lengthcommon.C \ lengthcommon.h \ + lfuns.h \ lyx_cb.C \ lyx_cb.h \ lyx_main.C \ diff --git a/src/buffer.C b/src/buffer.C index ca80561974..567c168afb 100644 --- a/src/buffer.C +++ b/src/buffer.C @@ -151,16 +151,16 @@ struct Buffer::Impl string temppath; TexRow texrow; - /// need to regenerate .tex ? + /// need to regenerate .tex? DepClean dep_clean; - /// is save needed + /// is save needed? mutable bool lyx_clean; - /// is autosave needed + /// is autosave needed? mutable bool bak_clean; - /// is this a unnamed file (New...) + /// is this a unnamed file (New...)? bool unnamed; /// buffer is r/o @@ -174,13 +174,13 @@ struct Buffer::Impl boost::scoped_ptr messages; - /** set to true only when the file is fully loaded. + /** Set to true only when the file is fully loaded. * Used to prevent the premature generation of previews * and by the citation inset. */ bool file_fully_loaded; - /// our Text + /// our text LyXText text; }; diff --git a/src/cursor.C b/src/cursor.C index f06ab8264f..810fdc4eef 100644 --- a/src/cursor.C +++ b/src/cursor.C @@ -57,19 +57,17 @@ limited_stack theCutBuffer; LCursor::LCursor(BufferView & bv) - : cursor_(1), anchor_(1), bv_(&bv), current_(0), - cached_y_(0), x_target_(-1), - selection_(false), mark_(false) + : DocumentIterator(bv), anchor_(bv), + cached_y_(0), x_target_(-1), selection_(false), mark_(false) {} void LCursor::reset() { - cursor_.clear(); + clear(); + push_back(CursorSlice()); anchor_.clear(); - cursor_.push_back(CursorSlice()); anchor_.push_back(CursorSlice()); - current_ = 0; cached_y_ = 0; clearTargetX(); selection_ = false; @@ -77,6 +75,14 @@ void LCursor::reset() } +void LCursor::setCursor(DocumentIterator const & cur, bool sel) +{ + // this (intentionally) does not touch the anchor + DocumentIterator::operator=(cur); + selection() = sel; +} + + DispatchResult LCursor::dispatch(FuncRequest const & cmd0) { lyxerr << "\nLCursor::dispatch: cmd: " << cmd0 << endl << *this << endl; @@ -84,9 +90,11 @@ DispatchResult LCursor::dispatch(FuncRequest const & cmd0) BOOST_ASSERT(idx() <= lastidx()); BOOST_ASSERT(par() <= lastpar()); FuncRequest cmd = cmd0; + nopop_ = false; + DocumentIterator orig = *this; disp_.update(true); disp_.val(NONE); - for (current_ = cursor_.size() - 1; current_ >= 1; --current_) { + while (size() != 1) { // the inset's dispatch() is supposed to reset the update and // val flags if necessary inset()->dispatch(*this, cmd); @@ -96,7 +104,6 @@ DispatchResult LCursor::dispatch(FuncRequest const & cmd0) switch (disp_.val()) { case NONE: // the inset handled the event fully - current_ = cursor_.size() - 1; return DispatchResult(true, true); case FINISHED_LEFT: // the inset handled the event partially @@ -112,15 +119,15 @@ DispatchResult LCursor::dispatch(FuncRequest const & cmd0) cmd = FuncRequest(LFUN_FINISHED_DOWN); break; default: - //lyxerr << "not handled on level " << current_ + //lyxerr << "not handled on level " << depth() // << " val: " << disp_.val() << endl; break; } } - BOOST_ASSERT(current_ == 0); - bv_->text()->dispatch(*this, cmd); + bv().text()->dispatch(*this, cmd); + if (nopop_) + setCursor(orig, false); //lyxerr << " result: " << res.val() << endl; - current_ = cursor_.size() - 1; return disp_; } @@ -128,57 +135,60 @@ DispatchResult LCursor::dispatch(FuncRequest const & cmd0) bool LCursor::getStatus(FuncRequest const & cmd, FuncStatus & status) { lyxerr << "\nLCursor::getStatus: cmd: " << cmd << endl << *this << endl; + DocumentIterator orig = *this; BOOST_ASSERT(pos() <= lastpos()); BOOST_ASSERT(idx() <= lastidx()); BOOST_ASSERT(par() <= lastpar()); - for (current_ = cursor_.size() - 1; current_ >= 1; --current_) { + for ( ; size() != 0; pop_back()) { // the inset's getStatus() will return 'true' if it made // a definitive decision on whether it want to handle the // request or not. The result of this decision is put into // the 'status' parameter. bool const res = inset()->getStatus(*this, cmd, status); if (res) { - current_ = cursor_.size() - 1; + setCursor(orig, false); return true; } } - BOOST_ASSERT(current_ == 0); - bool const res = bv_->text()->getStatus(*this, cmd, status); - current_ = cursor_.size() - 1; + bool const res = bv().text()->getStatus(*this, cmd, status); + setCursor(orig, false); return res; } -void LCursor::push(InsetBase * inset) +BufferView & LCursor::bv() const { - lyxerr << "LCursor::push() inset: " << inset << endl; - cursor_.push_back(CursorSlice(inset)); - anchor_.push_back(CursorSlice(inset)); - ++current_; - updatePos(); + return DocumentIterator::bv(); } +/* void LCursor::pop(int depth) { - while (int(cursor_.size()) > depth + 1) + while (int(size()) > depth + 1) pop(); lyxerr << "LCursor::pop() result: " << *this << endl; } +*/ void LCursor::pop() { - BOOST_ASSERT(cursor_.size() >= 1); - cursor_.pop_back(); + BOOST_ASSERT(size() >= 1); + pop_back(); anchor_.pop_back(); - current_ = cursor_.size() - 1; +} + + +void LCursor::push(InsetBase * p) +{ + push_back(CursorSlice(p)); } void LCursor::pushLeft(InsetBase * p) { - BOOST_ASSERT(!cursor_.empty()); + BOOST_ASSERT(!empty()); //lyxerr << "Entering inset " << t << " left" << endl; push(p); p->idxFirst(*this); @@ -187,7 +197,7 @@ void LCursor::pushLeft(InsetBase * p) bool LCursor::popLeft() { - BOOST_ASSERT(!cursor_.empty()); + BOOST_ASSERT(!empty()); //lyxerr << "Leaving inset to the left" << endl; if (depth() <= 1) { if (depth() == 1) @@ -202,7 +212,7 @@ bool LCursor::popLeft() bool LCursor::popRight() { - BOOST_ASSERT(!cursor_.empty()); + BOOST_ASSERT(!empty()); //lyxerr << "Leaving inset to the right" << endl; if (depth() <= 1) { if (depth() == 1) @@ -216,28 +226,11 @@ bool LCursor::popRight() } -CursorSlice & LCursor::current() -{ - BOOST_ASSERT(!cursor_.empty()); - //lyxerr << "accessing cursor slice " << current_ - // << ": " << cursor_[current_] << endl; - return cursor_[current_]; -} - - -CursorSlice const & LCursor::current() const -{ - //lyxerr << "accessing cursor slice " << current_ - // << ": " << cursor_[current_] << endl; - return cursor_[current_]; -} - - int LCursor::currentMode() { - BOOST_ASSERT(!cursor_.empty()); - for (int i = cursor_.size() - 1; i >= 1; --i) { - int res = cursor_[i].inset()->currentMode(); + BOOST_ASSERT(!empty()); + for (int i = size() - 1; i >= 1; --i) { + int res = operator[](i).inset()->currentMode(); if (res != MathInset::UNDECIDED_MODE) return res; } @@ -245,46 +238,18 @@ int LCursor::currentMode() } -LyXText * LCursor::innerText() const -{ - BOOST_ASSERT(!cursor_.empty()); - if (cursor_.size() > 1) { - // go up until first non-0 text is hit - // (innermost text is 0 in mathed) - for (int i = cursor_.size() - 1; i >= 1; --i) - if (cursor_[i].text()) - return cursor_[i].text(); - } - return bv_->text(); -} - - -CursorSlice const & LCursor::innerTextSlice() const -{ - BOOST_ASSERT(!cursor_.empty()); - if (cursor_.size() > 1) { - // go up until first non-0 text is hit - // (innermost text is 0 in mathed) - for (int i = cursor_.size() - 1; i >= 1; --i) - if (cursor_[i].text()) - return cursor_[i]; - } - return cursor_[0]; -} - - void LCursor::updatePos() { - BOOST_ASSERT(!cursor_.empty()); - if (cursor_.size() > 1) - cached_y_ = bv_->top_y() + cursor_.back().inset()->yo(); - //cached_y_ = cursor_.back().inset()->yo(); + BOOST_ASSERT(!empty()); + if (size() > 1) + cached_y_ = bv().top_y() + back().inset()->yo(); + //cached_y_ = back().inset()->yo(); } void LCursor::getDim(int & asc, int & des) const { - BOOST_ASSERT(!cursor_.empty()); + BOOST_ASSERT(!empty()); if (inMathed()) { BOOST_ASSERT(inset()); BOOST_ASSERT(inset()->asMathInset()); @@ -301,18 +266,18 @@ void LCursor::getDim(int & asc, int & des) const void LCursor::getPos(int & x, int & y) const { - BOOST_ASSERT(!cursor_.empty()); + BOOST_ASSERT(!empty()); x = 0; y = 0; - if (cursor_.size() == 1) { - x = bv_->text()->cursorX(cursor_.front()); - y = bv_->text()->cursorY(cursor_.front()); + if (size() == 1) { + x = bv().text()->cursorX(front()); + y = bv().text()->cursorY(front()); } else { if (!inset()) { lyxerr << "#### LCursor::getPos: " << *this << endl; BOOST_ASSERT(inset()); } - inset()->getCursorPos(cursor_.back(), x, y); + inset()->getCursorPos(back(), x, y); // getCursorPos gives _screen_ coordinates. We need to add // top_y to get document coordinates. This is hidden in cached_y_. //y += cached_y_ - inset()->yo(); @@ -335,60 +300,12 @@ void LCursor::paste(string const & data) } -InsetBase * LCursor::innerInsetOfType(int code) const -{ - for (int i = cursor_.size() - 1; i >= 1; --i) - if (cursor_[i].inset_->lyxCode() == code) - return cursor_[i].inset_; - return 0; -} - - -InsetTabular * LCursor::innerInsetTabular() const -{ - return static_cast(innerInsetOfType(InsetBase::TABULAR_CODE)); -} - - void LCursor::resetAnchor() { - anchor_ = cursor_; + anchor_ = *this; } -BufferView & LCursor::bv() const -{ - return *bv_; -} - - -MathAtom const & LCursor::prevAtom() const -{ - BOOST_ASSERT(pos() > 0); - return cell()[pos() - 1]; -} - - -MathAtom & LCursor::prevAtom() -{ - BOOST_ASSERT(pos() > 0); - return cell()[pos() - 1]; -} - - -MathAtom const & LCursor::nextAtom() const -{ - BOOST_ASSERT(pos() < lastpos()); - return cell()[pos()]; -} - - -MathAtom & LCursor::nextAtom() -{ - BOOST_ASSERT(pos() < lastpos()); - return cell()[pos()]; -} - bool LCursor::posLeft() { @@ -423,34 +340,34 @@ CursorSlice const & LCursor::anchor() const CursorSlice const & LCursor::selBegin() const { if (!selection()) - return cursor_.back(); - return anchor() < cursor_.back() ? anchor() : cursor_.back(); + return back(); + return anchor() < back() ? anchor() : back(); } CursorSlice & LCursor::selBegin() { if (!selection()) - return cursor_.back(); + return back(); // can't use std::min as this returns a const ref - return anchor() < cursor_.back() ? anchor() : cursor_.back(); + return anchor() < back() ? anchor() : back(); } CursorSlice const & LCursor::selEnd() const { if (!selection()) - return cursor_.back(); - return anchor() > cursor_.back() ? anchor() : cursor_.back(); + return back(); + return anchor() > back() ? anchor() : back(); } CursorSlice & LCursor::selEnd() { if (!selection()) - return cursor_.back(); + return back(); // can't use std::min as this returns a const ref - return anchor() > cursor_.back() ? anchor() : cursor_.back(); + return anchor() > back() ? anchor() : back(); } @@ -463,10 +380,10 @@ void LCursor::setSelection() } -void LCursor::setSelection(CursorBase const & where, size_t n) +void LCursor::setSelection(DocumentIterator const & where, size_t n) { selection() = true; - cursor_ = where; + setCursor(where, false); anchor_ = where; pos() += n; } @@ -499,122 +416,11 @@ void LCursor::clearTargetX() } -LyXText * LCursor::text() const -{ - return current_ ? current().text() : bv_->text(); -} - - -Paragraph & LCursor::paragraph() -{ - BOOST_ASSERT(inTexted()); - return current_ ? current().paragraph() : *bv_->text()->getPar(par()); -} - - -Paragraph const & LCursor::paragraph() const -{ - BOOST_ASSERT(inTexted()); - return current_ ? current().paragraph() : *bv_->text()->getPar(par()); -} - - -Row & LCursor::textRow() -{ - return *paragraph().getRow(pos()); -} - - -Row const & LCursor::textRow() const -{ - return *paragraph().getRow(pos()); -} - - -LCursor::par_type LCursor::lastpar() const -{ - return inMathed() ? 0 : text()->paragraphs().size() - 1; -} - - -LCursor::pos_type LCursor::lastpos() const -{ - InsetBase * inset = current().inset(); - return inset && inset->asMathInset() ? cell().size() : paragraph().size(); -} - - -LCursor::row_type LCursor::crow() const -{ - return paragraph().row(pos()); -} - - -LCursor::row_type LCursor::lastcrow() const -{ - return paragraph().rows.size(); -} - - -LCursor::idx_type LCursor::lastidx() const -{ - return current_ ? current().lastidx() : 0; -} - - -size_t LCursor::nargs() const -{ - // assume 1x1 grid for 'plain text' - return current_ ? current().nargs() : 1; -} - - -size_t LCursor::ncols() const -{ - // assume 1x1 grid for 'plain text' - return current_ ? current().ncols() : 1; -} - - -size_t LCursor::nrows() const -{ - // assume 1x1 grid for 'plain text' - return current_ ? current().nrows() : 1; -} - - -LCursor::row_type LCursor::row() const -{ - BOOST_ASSERT(current_ > 0); - return current().row(); -} - - -LCursor::col_type LCursor::col() const -{ - BOOST_ASSERT(current_ > 0); - return current().col(); -} - - -MathArray const & LCursor::cell() const -{ - BOOST_ASSERT(current_ > 0); - return current().cell(); -} - - -MathArray & LCursor::cell() -{ - BOOST_ASSERT(current_ > 0); - return current().cell(); -} - void LCursor::info(std::ostream & os) const { for (int i = 1, n = depth(); i < n; ++i) { - cursor_[i].inset()->infoize(os); + operator[](i).inset()->infoize(os); os << " "; } if (pos() != 0) @@ -701,7 +507,7 @@ void LCursor::eraseSelection() for (col_type col = c1; col <= c2; ++col) p->cell(p->index(row, col)).clear(); } - current() = i1; + back() = i1; } else { lyxerr << "can't erase this selection 1" << endl; } @@ -786,9 +592,8 @@ void LCursor::selClearOrDel() std::ostream & operator<<(std::ostream & os, LCursor const & cur) { - for (size_t i = 0, n = cur.cursor_.size(); i != n; ++i) - os << " " << cur.cursor_[i] << " | " << cur.anchor_[i] << "\n"; - os << " current: " << cur.current_ << endl; + for (size_t i = 0, n = cur.size(); i != n; ++i) + os << " " << cur.operator[](i) << " | " << cur.anchor_[i] << "\n"; os << " selection: " << cur.selection_ << endl; return os; } @@ -796,89 +601,21 @@ std::ostream & operator<<(std::ostream & os, LCursor const & cur) -// -// CursorBase -// - - -void increment(CursorBase & it) -{ - CursorSlice & top = it.back(); - MathArray & ar = top.asMathInset()->cell(top.idx_); - - // move into the current inset if possible - // it is impossible for pos() == size()! - MathInset * n = 0; - if (top.pos() != top.lastpos()) - n = (ar.begin() + top.pos_)->nucleus(); - if (n && n->isActive()) { - it.push_back(CursorSlice(n)); - return; - } - - // otherwise move on one cell back if possible - if (top.pos() < top.lastpos()) { - // pos() == lastpos() is valid! - ++top.pos_; - return; - } - - // otherwise try to move on one cell if possible - while (top.idx() < top.lastidx()) { - ++top.idx_; - if (top.asMathInset()->validCell(top.idx_)) { - top.pos_ = 0; - return; - } - } - - // otherwise leave array, move on one back - // this might yield pos() == size(), but that's a ok. - it.pop_back(); - // it certainly invalidates top - ++it.back().pos_; -} - - -CursorBase ibegin(InsetBase * p) -{ - CursorBase it; - it.push_back(CursorSlice(p)); - return it; -} - - -CursorBase iend(InsetBase * p) -{ - CursorBase it; - it.push_back(CursorSlice(p)); - CursorSlice & cur = it.back(); - cur.idx() = cur.lastidx(); - cur.pos() = cur.lastpos(); - return it; -} - - - - /////////////////////////////////////////////////////////////////// // // The part below is the non-integrated rest of the original math // cursor. This should be either generalized for texted or moved -// back to the math insets. +// back to mathed (in most cases to MathNestInset). // /////////////////////////////////////////////////////////////////// -#include "mathed/math_braceinset.h" #include "mathed/math_charinset.h" -#include "mathed/math_commentinset.h" #include "mathed/math_factory.h" #include "mathed/math_gridinset.h" #include "mathed/math_macroarg.h" #include "mathed/math_macrotemplate.h" #include "mathed/math_mathmlstream.h" #include "mathed/math_scriptinset.h" -#include "mathed/math_spaceinset.h" #include "mathed/math_support.h" #include "mathed/math_unknowninset.h" @@ -888,7 +625,7 @@ CursorBase iend(InsetBase * p) bool LCursor::isInside(InsetBase const * p) { for (unsigned i = 0; i < depth(); ++i) - if (cursor_[i].inset() == p) + if (operator[](i).inset() == p) return true; return false; } @@ -915,7 +652,8 @@ bool LCursor::openable(MathAtom const & t) const } -bool positionable(CursorBase const & cursor, CursorBase const & anchor) +bool positionable(DocumentIterator const & cursor, + DocumentIterator const & anchor) { // avoid deeper nested insets when selecting if (cursor.size() > anchor.size()) @@ -1127,10 +865,10 @@ bool LCursor::erase() bool LCursor::up() { macroModeClose(); - CursorBase save = cursor_; + DocumentIterator save = *this; if (goUpDown(true)) return true; - cursor_ = save; + setCursor(save, false); autocorrect() = false; return selection(); } @@ -1139,10 +877,10 @@ bool LCursor::up() bool LCursor::down() { macroModeClose(); - CursorBase save = cursor_; + DocumentIterator save = *this; if (goUpDown(false)) return true; - cursor_ = save; + setCursor(save, false); autocorrect() = false; return selection(); } @@ -1203,8 +941,8 @@ int LCursor::targetX() const MathHullInset * LCursor::formula() const { - for (int i = cursor_.size() - 1; i >= 1; --i) { - MathInset * inset = cursor_[i].inset()->asMathInset(); + for (int i = size() - 1; i >= 1; --i) { + MathInset * inset = operator[](i).inset()->asMathInset(); if (inset && inset->asHullInset()) return static_cast(inset); } @@ -1248,12 +986,12 @@ bool LCursor::inMacroArgMode() const MathGridInset * LCursor::enclosingGrid(idx_type & idx) const { for (MathInset::difference_type i = depth() - 1; i >= 0; --i) { - MathInset * m = cursor_[i].inset()->asMathInset(); + MathInset * m = operator[](i).inset()->asMathInset(); if (!m) return 0; MathGridInset * p = m->asGridInset(); if (p) { - idx = cursor_[i].idx_; + idx = operator[](i).idx_; return p; } } @@ -1279,8 +1017,8 @@ void LCursor::touch() { #warning look here #if 0 - CursorBase::const_iterator it = cursor_.begin(); - CursorBase::const_iterator et = cursor_.end(); + DocumentIterator::const_iterator it = begin(); + DocumentIterator::const_iterator et = end(); for ( ; it != et; ++it) it->cell().touch(); #endif @@ -1416,11 +1154,11 @@ bool LCursor::goUpDown(bool up) bool LCursor::bruteFind(int x, int y, int xlow, int xhigh, int ylow, int yhigh) { - CursorBase best_cursor; + DocumentIterator best_cursor(bv()); double best_dist = 1e10; - CursorBase it = ibegin(formula()); - CursorBase et = iend(formula()); + DocumentIterator it = bufferBegin(bv()); + DocumentIterator et = bufferEnd(); while (1) { // avoid invalid nesting when selecting if (!selection() || positionable(it, anchor_)) { @@ -1441,11 +1179,11 @@ bool LCursor::bruteFind(int x, int y, int xlow, int xhigh, int ylow, int yhigh) if (it == et) break; - increment(it); + it.forwardPos(); } if (best_dist < 1e10) - cursor_ = best_cursor; + setCursor(best_cursor, false); return best_dist < 1e10; } @@ -1454,9 +1192,9 @@ void LCursor::bruteFind2(int x, int y) { double best_dist = 1e10; - CursorBase it = cursor_; + DocumentIterator it = *this; it.back().pos() = 0; - CursorBase et = cursor_; + DocumentIterator et = *this; et.back().pos() = et.back().asMathInset()->cell(et.back().idx_).size(); for (int i = 0; ; ++i) { int xo, yo; @@ -1468,24 +1206,11 @@ void LCursor::bruteFind2(int x, int y) lyxerr << "i: " << i << " d: " << d << " best: " << best_dist << endl; if (d <= best_dist) { best_dist = d; - cursor_ = it; + setCursor(it, false); } if (it == et) break; - increment(it); - } -} - - -void LCursor::lockToggle() -{ - if (pos() != lastpos()) { - // toggle previous inset ... - nextAtom().nucleus()->lock(!nextAtom()->lock()); - } else if (popLeft() && pos() != lastpos()) { - // ... or enclosing inset if we are in the last inset position - nextAtom().nucleus()->lock(!nextAtom()->lock()); - ++pos(); + it.forwardPos(); } } @@ -1498,7 +1223,7 @@ CursorSlice LCursor::normalAnchor() } //lyx::BOOST_ASSERT(Anchor_.size() >= cursor.depth()); // use Anchor on the same level as Cursor - CursorSlice normal = anchor_[current_]; + CursorSlice normal = anchor_[size() - 1]; #if 0 if (depth() < anchor_.size() && !(normal < xx())) { // anchor is behind cursor -> move anchor behind the inset @@ -1519,7 +1244,7 @@ DispatchResult dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_MOUSE_MOTION: case LFUN_MOUSE_RELEASE: case LFUN_MOUSE_DOUBLE: { - CursorSlice & pos = cursor_.back(); + CursorSlice & pos = back(); int x = 0; int y = 0; getPos(x, y); @@ -1576,48 +1301,6 @@ void LCursor::handleFont(string const & font) } -bool LCursor::inMathed() const -{ - return current_ && inset()->inMathed(); -} - - -bool LCursor::inTexted() const -{ - return !inMathed(); -} - - -InsetBase * LCursor::nextInset() -{ - if (pos() == lastpos()) - return 0; - if (inMathed()) - return nextAtom().nucleus(); - return paragraph().isInset(pos()) ? paragraph().getInset(pos()) : 0; -} - - -InsetBase * LCursor::prevInset() -{ - if (pos() == 0) - return 0; - if (inMathed()) - return prevAtom().nucleus(); - return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0; -} - - -InsetBase const * LCursor::prevInset() const -{ - if (pos() == 0) - return 0; - if (inMathed()) - return prevAtom().nucleus(); - return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0; -} - - void LCursor::message(string const & msg) const { bv().owner()->getLyXFunc().setMessage(msg); @@ -1705,7 +1388,7 @@ string LCursor::getPossibleLabel() } -void LCursor::notdispatched() +void LCursor::undispatched() { disp_.dispatched(false); } @@ -1717,7 +1400,13 @@ void LCursor::dispatched(dispatch_result_t res) } -void LCursor::noupdate() +void LCursor::noUpdate() { disp_.update(false); } + + +void LCursor::noPop() +{ + nopop_ = true; +} diff --git a/src/cursor.h b/src/cursor.h index 8cde34016e..e14fb97006 100644 --- a/src/cursor.h +++ b/src/cursor.h @@ -12,23 +12,17 @@ #ifndef CURSOR_H #define CURSOR_H -#include "cursor_slice.h" #include "dispatchresult.h" +#include "dociterator.h" #include #include -class BufferView; class UpdatableInset; -class MathAtom; class DispatchResult; class FuncStatus; class FuncRequest; class InsetTabular; -class LyXText; -class Paragraph; -class Row; - // these should go class MathHullInset; @@ -36,40 +30,14 @@ class MathUnknownInset; class MathGridInset; -// only needed for gcc 2.95, remove when support terminated -template -bool ptr_cmp(A const * a, B const * b) -{ - return a == b; -} - - -// this is used for traversing math insets -typedef std::vector CursorBase; -/// move on one step -void increment(CursorBase &); -/// -CursorBase ibegin(InsetBase * p); -/// -CursorBase iend(InsetBase * p); - - /** * The cursor class describes the position of a cursor within a document. */ -class LCursor { +// The public inheritance should go in favour of a suitable data member +// (or maybe private inheritance) at some point of time. +class LCursor : public DocumentIterator { public: - /// type for cell number in inset - typedef CursorSlice::idx_type idx_type; - /// type for paragraph numbers positions within a cell - typedef CursorSlice::par_type par_type; - /// type for cursor positions within a cell - typedef CursorSlice::pos_type pos_type; - /// type for row indices - typedef CursorSlice::row_type row_type; - /// type for col indices - typedef CursorSlice::col_type col_type; /// create the cursor of a BufferView explicit LCursor(BufferView & bv); @@ -88,16 +56,8 @@ public: bool popLeft(); /// pop one slice off the cursor stack and go right bool popRight(); - /// restrict cursor nesting to given size - void pop(int depth); - /// access to current cursor slice - CursorSlice & current(); - /// access to current cursor slice - CursorSlice const & current() const; - /// how many nested insets do we have? - size_t depth() const { return cursor_.size(); } - /// depth of current slice - int currentDepth() const { return current_; } + /// sets cursor part + void setCursor(DocumentIterator const & it, bool sel); // // selection @@ -113,7 +73,7 @@ public: /// void setSelection(); /// set selection at given position - void setSelection(CursorBase const & where, size_t n); + void setSelection(DocumentIterator const & where, size_t n); /// void clearSelection(); /// access start of selection @@ -154,70 +114,6 @@ public: /// std::string currentState(); - // - // access to the 'current' cursor slice - // - /// the containing inset - InsetBase * inset() const { return current().inset(); } - /// return the cell of the inset this cursor is in - idx_type idx() const { return current().idx(); } - /// return the cell of the inset this cursor is in - idx_type & idx() { return current().idx(); } - /// return the last possible cell in this inset - idx_type lastidx() const; - /// return the paragraph this cursor is in - par_type par() const { return current().par(); } - /// return the paragraph this cursor is in - par_type & par() { return current().par(); } - /// return the last possible paragraph in this inset - par_type lastpar() const; - /// return the position within the paragraph - pos_type pos() const { return current().pos(); } - /// return the position within the paragraph - pos_type & pos() { return current().pos(); } - /// return the last position within the paragraph - pos_type lastpos() const; - /// return the display row of the cursor with in the current par - row_type crow() const; - /// return the display row of the cursor with in the current par - row_type lastcrow() const; - - /// return the number of embedded cells - size_t nargs() const; - /// return the number of embedded cells - size_t ncols() const; - /// return the number of embedded cells - size_t nrows() const; - /// return the grid row of the current cell - row_type row() const; - /// return the last row of the current grid - row_type lastrow() const { return nrows() - 1; } - /// return the grid column of the current cell - col_type col() const; - /// return the last column of the current grid - col_type lastcol() const { return ncols() - 1; } - /// the inset just behind the cursor - InsetBase * nextInset(); - /// the inset just in front of the cursor - InsetBase * prevInset(); - /// the inset just in front of the cursor - InsetBase const * prevInset() const; - - // - // math-specific part - // - /// return the mathed cell this cursor is in - MathArray const & cell() const; - /// return the mathed cell this cursor is in - MathArray & cell(); - /// the mathatom left of the cursor - MathAtom const & prevAtom() const; - /// the mathatom left of the cursor - MathAtom & prevAtom(); - /// the mathatom right of the cursor - MathAtom const & nextAtom() const; - /// the mathatom right of the cursor - MathAtom & nextAtom(); /// auto-correct mode bool autocorrect() const { return autocorrect_; } /// auto-correct mode @@ -226,31 +122,6 @@ public: bool macromode() const { return macromode_; } /// are we entering a macro name? bool & macromode() { return macromode_; } - - // - // text-specific part - /// see comment for boundary_ below - bool boundary() const { return current().boundary(); } - /// see comment for boundary_ below - bool & boundary() { return current().boundary(); } - /// the paragraph we're in - Paragraph & paragraph(); - /// the paragraph we're in - Paragraph const & paragraph() const; - /// the row in the paragraph we're in - Row & textRow(); - /// the row in the paragraph we're in - Row const & textRow() const; - /// - LyXText * text() const; - /// - InsetBase * innerInsetOfType(int code) const; - /// - InsetTabular * innerInsetTabular() const; - /// - LyXText * innerText() const; - /// - CursorSlice const & innerTextSlice() const; /// returns x,y position void getPos(int & x, int & y) const; /// returns cursor dimension @@ -288,7 +159,7 @@ public: void resetAnchor(); /// access to owning BufferView BufferView & bv() const; - /// get some interesting description of current position + /// get some interesting description of top position void info(std::ostream & os) const; /// are we in math mode (2), text mode (1) or unsure (0)? int currentMode(); @@ -298,28 +169,26 @@ public: void replaceWord(std::string const & replacestring); /// update our view void update(); - /// + /// set dispatch result void dispatched(dispatch_result_t res); - void notdispatched(); - void noupdate(); + /// assume event was not (yet) dispatched + void undispatched(); + /// don't call update() when done + void noUpdate(); + /// don't pop cursor to the level where the LFUN was handled + void noPop(); /// output friend std::ostream & operator<<(std::ostream & os, LCursor const & cur); public: //private: - /// mainly used as stack, but wee need random access - std::vector cursor_; /// the anchor position - std::vector anchor_; + DocumentIterator anchor_; /// DispatchResult disp_; private: - /// - BufferView * bv_; - /// current slice - int current_; /// int cached_y_; /** @@ -339,6 +208,8 @@ private: bool selection_; // are we on the way to get one? bool mark_; + /// + bool nopop_; // // math specific stuff that could be promoted to "global" later @@ -389,7 +260,7 @@ public: void adjust(pos_type from, int diff); /// MathHullInset * formula() const; - /// current offset in the current cell + /// current offset in the top cell /// interpret name a name of a macro void macroModeClose(); /// are we currently typing the name of a macro? @@ -419,9 +290,6 @@ public: /// returns the normalized anchor of the selection CursorSlice normalAnchor(); - /// lock/unlock inset - void lockToggle(); - /// hack for reveal codes void markInsert(); void markErase(); @@ -430,11 +298,6 @@ public: /// split font inset etc void handleFont(std::string const & font); - /// are we in mathed? - bool inMathed() const; - /// are we in texted? - bool inTexted() const; - /// display a message void message(std::string const & msg) const; /// display an error message diff --git a/src/cursor_slice.C b/src/cursor_slice.C index c7eb6673fb..746ab78224 100644 --- a/src/cursor_slice.C +++ b/src/cursor_slice.C @@ -213,7 +213,7 @@ bool operator>(CursorSlice const & p, CursorSlice const & q) std::ostream & operator<<(std::ostream & os, CursorSlice const & item) { os -// << "inset: " << item.inset_ + << "inset: " << item.inset_ // << " text: " << item.text() << " idx: " << item.idx_ << " par: " << item.par_ diff --git a/src/dociterator.C b/src/dociterator.C new file mode 100644 index 0000000000..fb7b7482ad --- /dev/null +++ b/src/dociterator.C @@ -0,0 +1,401 @@ + +#include "dociterator.h" + +#include "BufferView.h" +#include "debug.h" +#include "lyxtext.h" +#include "lyxrow.h" +#include "paragraph.h" + +#include "mathed/math_data.h" +#include "mathed/math_inset.h" + +#include + + + +std::ostream & operator<<(std::ostream & os, DocumentIterator const & cur); + + +DocumentIterator::DocumentIterator() + : bv_(0) +{} + + +DocumentIterator::DocumentIterator(BufferView & bv) + : std::vector(1), bv_(&bv) +{} + + +InsetBase * DocumentIterator::nextInset() +{ + if (pos() == lastpos()) + return 0; + if (inMathed()) + return nextAtom().nucleus(); + return paragraph().isInset(pos()) ? paragraph().getInset(pos()) : 0; +} + + +InsetBase * DocumentIterator::prevInset() +{ + if (pos() == 0) + return 0; + if (inMathed()) + return prevAtom().nucleus(); + return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0; +} + + +InsetBase const * DocumentIterator::prevInset() const +{ + if (pos() == 0) + return 0; + if (inMathed()) + return prevAtom().nucleus(); + return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0; +} + + +MathAtom const & DocumentIterator::prevAtom() const +{ + BOOST_ASSERT(pos() > 0); + return cell()[pos() - 1]; +} + + +MathAtom & DocumentIterator::prevAtom() +{ + BOOST_ASSERT(pos() > 0); + return cell()[pos() - 1]; +} + + +MathAtom const & DocumentIterator::nextAtom() const +{ + BOOST_ASSERT(pos() < lastpos()); + return cell()[pos()]; +} + + +MathAtom & DocumentIterator::nextAtom() +{ + BOOST_ASSERT(pos() < lastpos()); + return cell()[pos()]; +} + + +LyXText * DocumentIterator::text() const +{ + return size() > 1 ? top().text() : bv().text(); +} + + +Paragraph & DocumentIterator::paragraph() +{ + BOOST_ASSERT(inTexted()); + return size() > 1 ? top().paragraph() : *bv().text()->getPar(par()); +} + + +Paragraph const & DocumentIterator::paragraph() const +{ + BOOST_ASSERT(inTexted()); + return size() > 1 ? top().paragraph() : *bv().text()->getPar(par()); +} + + +Row & DocumentIterator::textRow() +{ + return *paragraph().getRow(pos()); +} + + +Row const & DocumentIterator::textRow() const +{ + return *paragraph().getRow(pos()); +} + + +DocumentIterator::par_type DocumentIterator::lastpar() const +{ + return inMathed() ? 0 : text()->paragraphs().size() - 1; +} + + +DocumentIterator::pos_type DocumentIterator::lastpos() const +{ + return inMathed() ? cell().size() : paragraph().size(); +} + + +DocumentIterator::row_type DocumentIterator::crow() const +{ + return paragraph().row(pos()); +} + + +DocumentIterator::row_type DocumentIterator::lastcrow() const +{ + return paragraph().rows.size(); +} + + +DocumentIterator::idx_type DocumentIterator::lastidx() const +{ + return size() > 1 ? top().lastidx() : 0; +} + + +size_t DocumentIterator::nargs() const +{ + // assume 1x1 grid for main text + return size() > 1 ? top().nargs() : 1; +} + + +size_t DocumentIterator::ncols() const +{ + // assume 1x1 grid for main text + return size() > 1 ? top().ncols() : 1; +} + + +size_t DocumentIterator::nrows() const +{ + // assume 1x1 grid for main text + return size() > 1 ? top().nrows() : 1; +} + + +DocumentIterator::row_type DocumentIterator::row() const +{ + return size() > 1 ? top().row() : 0; +} + + +DocumentIterator::col_type DocumentIterator::col() const +{ + return size() > 1 ? top().col() : 0; +} + + +MathArray const & DocumentIterator::cell() const +{ + BOOST_ASSERT(size() > 1); + return top().cell(); +} + + +MathArray & DocumentIterator::cell() +{ + BOOST_ASSERT(size() > 1); + return top().cell(); +} + + +bool DocumentIterator::inMathed() const +{ + return size() > 1 && inset()->inMathed(); +} + + +bool DocumentIterator::inTexted() const +{ + return !inMathed(); +} + + +LyXText * DocumentIterator::innerText() const +{ + BOOST_ASSERT(!empty()); + if (size() > 1) { + // go up until first non-0 text is hit + // (innermost text is 0 in mathed) + for (int i = size() - 1; i >= 1; --i) + if (operator[](i).text()) + return operator[](i).text(); + } + return bv().text(); +} + + +CursorSlice const & DocumentIterator::innerTextSlice() const +{ + BOOST_ASSERT(!empty()); + if (size() > 1) { + // go up until first non-0 text is hit + // (innermost text is 0 in mathed) + for (int i = size() - 1; i >= 1; --i) + if (operator[](i).text()) + return operator[](i); + } + return operator[](0); +} + + +InsetBase * DocumentIterator::innerInsetOfType(int code) const +{ + for (int i = size() - 1; i >= 1; --i) + if (operator[](i).inset_->lyxCode() == code) + return operator[](i).inset_; + return 0; +} + + +void DocumentIterator::forwardPos() +{ + CursorSlice & top = back(); + //lyxerr << "XXX\n" << *this << std::endl; + + // move into an inset to the right if possible + InsetBase * n = 0; + if (top.pos() != lastpos()) { + // this is impossible for pos() == size() + if (inMathed()) { + n = (top.cell().begin() + top.pos())->nucleus(); + } else { + if (paragraph().isInset(top.pos())) + n = paragraph().getInset(top.pos()); + } + } + + if (n && n->isActive()) { + //lyxerr << "... descend" << std::endl; + push_back(CursorSlice(n)); + return; + } + + // otherwise move on one cell back if possible + if (top.pos() < lastpos()) { + //lyxerr << "... next pos" << std::endl; + ++top.pos(); + return; + } + //lyxerr << "... no next pos" << std::endl; + + // otherwise move on one cell back if possible + if (top.par() < lastpar()) { + //lyxerr << "... next par" << std::endl; + ++top.par(); + top.pos() = 0; + return; + } + //lyxerr << "... no next par" << std::endl; + + // otherwise try to move on one cell if possible + // [stupid hack for necessary for MathScriptInset] + while (top.idx() < lastidx()) { + //lyxerr << "... next idx" << std::endl; + ++top.idx(); + top.par() = 0; + top.pos() = 0; + if (top.inset() && top.inset()->validCell(top.idx())) { + //lyxerr << " ... ok" << std::endl; + return; + } + } + //lyxerr << "... no next idx" << std::endl; + + // otherwise leave inset an jump over inset as a whole + pop_back(); + // 'top' is invalid now... + if (size()) + ++back().pos_; + //else + // lyxerr << "... no slice left" << std::endl; +} + + +void DocumentIterator::forwardPar() +{ + CursorSlice & top = back(); + lyxerr << "XXX " << *this << std::endl; + + // move into an inset to the right if possible + InsetBase * n = 0; + if (top.pos() != lastpos()) { + // this is impossible for pos() == size() + if (inMathed()) { + n = (top.cell().begin() + top.pos())->nucleus(); + } else { + if (paragraph().isInset(top.pos())) + n = paragraph().getInset(top.pos()); + } + } + + if (n && n->isActive()) { + lyxerr << "... descend" << std::endl; + push_back(CursorSlice(n)); + return; + } + + // otherwise move on one cell back if possible + if (top.pos() < lastpos()) { + lyxerr << "... next pos" << std::endl; + ++top.pos(); + return; + } + + // otherwise move on one cell back if possible + if (top.par() < lastpar()) { + lyxerr << "... next par" << std::endl; + ++top.par(); + top.pos() = 0; + return; + } + + // otherwise try to move on one cell if possible + // [stupid hack for necessary for MathScriptInset] + while (top.idx() < top.lastidx()) { + lyxerr << "... next idx" + << " was: " << top.idx() << " max: " << top.lastidx() << std::endl; + ++top.idx(); + top.par() = 0; + top.pos() = 0; + if (top.inset() && top.inset()->validCell(top.idx())) { + lyxerr << " ... ok" << std::endl; + return; + } + } + + // otherwise leave inset an jump over inset as a whole + pop_back(); + // 'top' is invalid now... + if (size()) + ++back().pos_; +} + + +DocumentIterator bufferBegin(BufferView & bv) +{ + return DocumentIterator(bv); +} + + +DocumentIterator bufferEnd() +{ + return DocumentIterator(); +} + + +DocumentIterator insetBegin(BufferView & bv, InsetBase * p) +{ + DocumentIterator it(bv); + it.back() = CursorSlice(p); + return it; +} + + +DocumentIterator insetEnd() +{ + return DocumentIterator(); +} + + +std::ostream & operator<<(std::ostream & os, DocumentIterator const & cur) +{ + for (size_t i = 0, n = cur.size(); i != n; ++i) + os << " " << cur.operator[](i) << "\n"; + return os; +} diff --git a/src/dociterator.h b/src/dociterator.h new file mode 100644 index 0000000000..24c2b49a69 --- /dev/null +++ b/src/dociterator.h @@ -0,0 +1,185 @@ +// -*- C++ -*- +/** + * \file dociterator.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author André Pönitz + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef DOCITERATOR_H +#define DOCITERATOR_H + +#include "cursor_slice.h" + +#include + +class BufferView; +class MathAtom; +class LyXText; +class Paragraph; +class Row; + + +// only needed for gcc 2.95, remove when support terminated +template +bool ptr_cmp(A const * a, B const * b) +{ + return a == b; +} + + +// The public inheritance should go in favour of a suitable data member +// (or maybe private inheritance) at some point of time. +class DocumentIterator : public std::vector +{ +public: + /// type for cell number in inset + typedef CursorSlice::idx_type idx_type; + /// type for paragraph numbers positions within a cell + typedef CursorSlice::par_type par_type; + /// type for cursor positions within a cell + typedef CursorSlice::pos_type pos_type; + /// type for row indices + typedef CursorSlice::row_type row_type; + /// type for col indices + typedef CursorSlice::col_type col_type; + +public: + /// + DocumentIterator(); + /// + explicit DocumentIterator(BufferView & bv); + /// + BufferView & bv() const { return *bv_; } + + // + // access to slice at tip + // + /// access to tip + CursorSlice & top() { return back(); } + /// access to tip + CursorSlice const & top() const { return back(); } + /// how many nested insets do we have? + size_t depth() const { return size(); } + /// the containing inset + InsetBase * inset() const { return back().inset(); } + /// return the cell of the inset this cursor is in + idx_type idx() const { return back().idx(); } + /// return the cell of the inset this cursor is in + idx_type & idx() { return back().idx(); } + /// return the last possible cell in this inset + idx_type lastidx() const; + /// return the paragraph this cursor is in + par_type par() const { return back().par(); } + /// return the paragraph this cursor is in + par_type & par() { return back().par(); } + /// return the last possible paragraph in this inset + par_type lastpar() const; + /// return the position within the paragraph + pos_type pos() const { return back().pos(); } + /// return the position within the paragraph + pos_type & pos() { return back().pos(); } + /// return the last position within the paragraph + pos_type lastpos() const; + /// return the display row of the cursor with in the top par + row_type crow() const; + /// return the display row of the cursor with in the top par + row_type lastcrow() const; + + /// return the number of embedded cells + size_t nargs() const; + /// return the number of embedded cells + size_t ncols() const; + /// return the number of embedded cells + size_t nrows() const; + /// return the grid row of the top cell + row_type row() const; + /// return the last row of the top grid + row_type lastrow() const { return nrows() - 1; } + /// return the grid column of the top cell + col_type col() const; + /// return the last column of the top grid + col_type lastcol() const { return ncols() - 1; } + /// the inset just behind the cursor + InsetBase * nextInset(); + /// the inset just in front of the cursor + InsetBase * prevInset(); + /// the inset just in front of the cursor + InsetBase const * prevInset() const; + + /// are we in mathed? + bool inMathed() const; + /// are we in texted? + bool inTexted() const; + + // + // math-specific part + // + /// return the mathed cell this cursor is in + MathArray const & cell() const; + /// return the mathed cell this cursor is in + MathArray & cell(); + /// the mathatom left of the cursor + MathAtom const & prevAtom() const; + /// the mathatom left of the cursor + MathAtom & prevAtom(); + /// the mathatom right of the cursor + MathAtom const & nextAtom() const; + /// the mathatom right of the cursor + MathAtom & nextAtom(); + + // + // text-specific part + // + /// see comment for boundary_ below + bool boundary() const { return top().boundary(); } + /// see comment for boundary_ below + bool & boundary() { return top().boundary(); } + /// the paragraph we're in + Paragraph & paragraph(); + /// the paragraph we're in + Paragraph const & paragraph() const; + /// the row in the paragraph we're in + Row & textRow(); + /// the row in the paragraph we're in + Row const & textRow() const; + /// + LyXText * text() const; + /// + CursorSlice const & innerTextSlice() const; + /// + InsetBase * innerInsetOfType(int code) const; + /// + LyXText * innerText() const; + + // + // elementary moving + // + /// move on one position + void forwardPos(); + /// move on one paragraph + void forwardPar(); + /// move on one cell + void forwardIdx(); + /// move on one inset + void forwardInset(); + +private: + /// + BufferView * bv_; +}; + + +/// +DocumentIterator bufferBegin(BufferView & bv); +/// +DocumentIterator bufferEnd(); +/// +DocumentIterator insetBegin(BufferView & bv, InsetBase * inset); +/// +DocumentIterator insetEnd(); + +#endif diff --git a/src/frontends/xforms/xformsImage.C b/src/frontends/xforms/xformsImage.C index dcb4de0599..bdb98f49cd 100644 --- a/src/frontends/xforms/xformsImage.C +++ b/src/frontends/xforms/xformsImage.C @@ -470,7 +470,7 @@ unsigned int packedcolor(LColor::color col) bool const success = getRGBColor(col, r, g, b); if (!success) // Set to black on failure - return FL_PACK(255,255,255); + return FL_PACK(255, 255, 255); return FL_PACK(r, g, b); } diff --git a/src/insets/insetbase.C b/src/insets/insetbase.C index 53b749e730..e9be990c99 100644 --- a/src/insets/insetbase.C +++ b/src/insets/insetbase.C @@ -35,8 +35,8 @@ void InsetBase::dispatch(LCursor & cur, FuncRequest const & cmd) void InsetBase::priv_dispatch(LCursor & cur, FuncRequest const &) { - cur.noupdate(); - cur.notdispatched(); + cur.noUpdate(); + cur.undispatched(); } diff --git a/src/insets/insetbranch.C b/src/insets/insetbranch.C index 1774899434..800e56ceb1 100644 --- a/src/insets/insetbranch.C +++ b/src/insets/insetbranch.C @@ -125,7 +125,7 @@ void InsetBranch::priv_dispatch(LCursor & cur, FuncRequest const & cmd) if (cmd.button() != mouse_button::button3) InsetCollapsable::priv_dispatch(cur, cmd); else - cur.notdispatched(); + cur.undispatched(); break; case LFUN_INSET_DIALOG_UPDATE: diff --git a/src/insets/insetcommand.C b/src/insets/insetcommand.C index 5e6430cb8e..dd1f782f48 100644 --- a/src/insets/insetcommand.C +++ b/src/insets/insetcommand.C @@ -105,7 +105,7 @@ void InsetCommand::priv_dispatch(LCursor & cur, FuncRequest const & cmd) InsetCommandParams p; InsetCommandMailer::string2params(mailer_name_, cmd.argument, p); if (p.getCmdName().empty()) { - cur.notdispatched(); + cur.undispatched(); } else { setParams(p); cur.bv().update(); diff --git a/src/insets/insetlabel.C b/src/insets/insetlabel.C index 75644d4295..42731136e5 100644 --- a/src/insets/insetlabel.C +++ b/src/insets/insetlabel.C @@ -99,7 +99,7 @@ void InsetLabel::priv_dispatch(LCursor & cur, FuncRequest const & cmd) InsetCommandParams p; InsetCommandMailer::string2params("label", cmd.argument, p); if (p.getCmdName().empty()) { - cur.notdispatched(); + cur.undispatched(); break; } if (p.getContents() != params().getContents()) diff --git a/src/insets/insettabular.C b/src/insets/insettabular.C index 36344554f2..e12e7dd2e8 100644 --- a/src/insets/insettabular.C +++ b/src/insets/insettabular.C @@ -415,7 +415,7 @@ void InsetTabular::priv_dispatch(LCursor & cur, FuncRequest const & cmd) { lyxerr << "# InsetTabular::dispatch: cmd: " << cmd << endl; //lyxerr << " cur:\n" << cur << endl; - CursorSlice sl = cur.current(); + CursorSlice sl = cur.top(); switch (cmd.action) { @@ -426,7 +426,7 @@ void InsetTabular::priv_dispatch(LCursor & cur, FuncRequest const & cmd) cur.selection() = false; setPos(cur, cmd.x, cmd.y); cur.resetAnchor(); - cur.bv().cursor() = cur; + cur.bv().cursor().setCursor(cur, false); //if (cmd.button() == mouse_button::button2) // dispatch(cur, FuncRequest(LFUN_PASTESELECTION, "paragraph")); //lyxerr << "# InsetTabular::MousePress\n" << cur.bv().cursor() << endl; @@ -436,8 +436,7 @@ void InsetTabular::priv_dispatch(LCursor & cur, FuncRequest const & cmd) if (cmd.button() != mouse_button::button1) break; setPos(cur, cmd.x, cmd.y); - cur.bv().cursor().cursor_ = cur.cursor_; - cur.bv().cursor().selection() = true; + cur.bv().cursor().setCursor(cur, true); //lyxerr << "# InsetTabular::MouseMotion\n" << cur.bv().cursor() << endl; break; @@ -471,9 +470,9 @@ void InsetTabular::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_RIGHT: cell(cur.idx()).dispatch(cur, cmd); cur.dispatched(NONE); // override the cell's result - if (sl == cur.current()) + if (sl == cur.top()) isRightToLeft(cur) ? movePrevCell(cur) : moveNextCell(cur); - if (sl == cur.current()) + if (sl == cur.top()) cur.dispatched(FINISHED_RIGHT); break; @@ -481,9 +480,9 @@ void InsetTabular::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_LEFT: cell(cur.idx()).dispatch(cur, cmd); cur.dispatched(NONE); // override the cell's result - if (sl == cur.current()) + if (sl == cur.top()) isRightToLeft(cur) ? moveNextCell(cur) : movePrevCell(cur); - if (sl == cur.current()) + if (sl == cur.top()) cur.dispatched(FINISHED_LEFT); break; @@ -491,14 +490,14 @@ void InsetTabular::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_DOWN: cell(cur.idx()).dispatch(cur, cmd); cur.dispatched(NONE); // override the cell's result - if (sl == cur.current()) + if (sl == cur.top()) if (tabular.row_of_cell(cur.idx()) != tabular.rows() - 1) { cur.idx() = tabular.getCellBelow(cur.idx()); cur.par() = 0; cur.pos() = 0; resetPos(cur); } - if (sl == cur.current()) + if (sl == cur.top()) cur.dispatched(FINISHED_DOWN); break; @@ -506,14 +505,14 @@ void InsetTabular::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_UP: cell(cur.idx()).dispatch(cur, cmd); cur.dispatched(NONE); // override the cell's result - if (sl == cur.current()) + if (sl == cur.top()) if (tabular.row_of_cell(cur.idx()) != 0) { cur.idx() = tabular.getCellAbove(cur.idx()); cur.par() = cur.lastpar(); cur.pos() = cur.lastpos(); resetPos(cur); } - if (sl == cur.current()) + if (sl == cur.top()) cur.dispatched(FINISHED_UP); break; @@ -564,7 +563,7 @@ void InsetTabular::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_TABULAR_FEATURE: if (!tabularFeatures(cur, cmd.argument)) - cur.notdispatched(); + cur.undispatched(); break; // insert file functions @@ -572,7 +571,7 @@ void InsetTabular::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_FILE_INSERT_ASCII: { string tmpstr = getContentsOfAsciiFile(&cur.bv(), cmd.argument, false); if (!tmpstr.empty() && !insertAsciiString(cur.bv(), tmpstr, false)) - cur.notdispatched(); + cur.undispatched(); break; } diff --git a/src/insets/insettext.C b/src/insets/insettext.C index f5ab5875f7..faf3173e58 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -289,7 +289,7 @@ void InsetText::edit(LCursor & cur, bool left) setViewCache(&cur.bv()); int const par = left ? 0 : paragraphs().size() - 1; int const pos = left ? 0 : paragraphs().back().size(); - text_.setCursor(cur.current(), par, pos); + text_.setCursor(cur.top(), par, pos); cur.clearSelection(); finishUndo(); sanitizeEmptyText(cur.bv()); diff --git a/src/insets/insettext.h b/src/insets/insettext.h index e752fc9844..d0ae16da75 100644 --- a/src/insets/insettext.h +++ b/src/insets/insettext.h @@ -22,7 +22,6 @@ #include "frontends/mouse_state.h" - class Buffer; class BufferParams; class BufferView; @@ -33,10 +32,10 @@ class Painter; class Paragraph; class Row; + /** A text inset is like a TeX box to write full text (including styles and other insets) in a given space. - @author: Jürgen Vigna */ class InsetText : public UpdatableInset { public: @@ -174,7 +173,6 @@ private: /// void clearInset(Painter &, int x, int y) const; - /* Private structures and variables */ /// bool autoBreakRows_; /// diff --git a/src/lyxfind.C b/src/lyxfind.C index 710de709ce..6613798d87 100644 --- a/src/lyxfind.C +++ b/src/lyxfind.C @@ -390,7 +390,7 @@ int replace(BufferView * bv, string const & searchstr, text->replaceSelectionWithString(bv->cursor(), replacestr); text->setSelectionRange(bv->cursor(), replacestr.length()); - bv->cursor().current() = fw ? bv->cursor().selEnd() : bv->cursor().selBegin(); + bv->cursor().top() = fw ? bv->cursor().selEnd() : bv->cursor().selBegin(); bv->buffer()->markDirty(); find(bv, searchstr, cs, mw, fw); bv->update(); diff --git a/src/lyxfunc.C b/src/lyxfunc.C index 048a5ae563..dee64f6b12 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -339,7 +339,7 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const break; case LFUN_LAYOUT_TABULAR: - disable = !cur.innerInsetTabular(); + disable = !cur.innerInsetOfType(InsetBase::TABULAR_CODE); break; case LFUN_DEPTH_MIN: @@ -405,7 +405,8 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const if (tli) { FuncStatus ret; //ret.disabled(true); - InsetTabular * tab = cur.innerInsetTabular(); + InsetTabular * tab = static_cast + (cur.innerInsetOfType(InsetBase::TABULAR_CODE)); if (tab) { ret = tab->getStatus(cmd.argument); flag |= ret; diff --git a/src/lyxtext.h b/src/lyxtext.h index d2c393df4d..5ab7cd9e0b 100644 --- a/src/lyxtext.h +++ b/src/lyxtext.h @@ -412,6 +412,13 @@ public: /// our 'outermost' Font LyXFont font_; + /// + double fill_separator(Row const & row) const; + /// + double fill_hfill(Row const & row) const; + /// + double + fill_label_hfill(ParagraphList::iterator pit, Row const & row) const; private: /// return past-the-last paragraph influenced by a layout diff --git a/src/mathed/math_gridinset.C b/src/mathed/math_gridinset.C index fb0ab8cfdb..ed6c545748 100644 --- a/src/mathed/math_gridinset.C +++ b/src/mathed/math_gridinset.C @@ -1113,7 +1113,7 @@ void MathGridInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) else if (s == "swap-column") swapCol(col(cur.idx())); else { - cur.notdispatched(); + cur.undispatched(); return; } lyxerr << "returning FINISHED_LEFT" << endl; diff --git a/src/mathed/math_hullinset.C b/src/mathed/math_hullinset.C index d47beb27d7..3f46a091c1 100644 --- a/src/mathed/math_hullinset.C +++ b/src/mathed/math_hullinset.C @@ -1070,7 +1070,7 @@ bool MathHullInset::searchForward(BufferView * bv, string const & str, #warning pretty ugly #endif static MathHullInset * lastformula = 0; - static CursorBase current = CursorBase(ibegin(nucleus())); + static CursorBase current = DocumentIterator(ibegin(nucleus())); static MathArray ar; static string laststr; @@ -1086,7 +1086,7 @@ bool MathHullInset::searchForward(BufferView * bv, string const & str, } //lyxerr << "searching '" << str << "' in " << this << ar << endl; - for (CursorBase it = current; it != iend(nucleus()); increment(it)) { + for (DocumentIterator it = current; it != iend(nucleus()); increment(it)) { CursorSlice & top = it.back(); MathArray const & a = top.asMathInset()->cell(top.idx_); if (a.matchpart(ar, top.pos_)) { diff --git a/src/mathed/math_nestinset.C b/src/mathed/math_nestinset.C index a0b2ad65a0..099f31766c 100644 --- a/src/mathed/math_nestinset.C +++ b/src/mathed/math_nestinset.C @@ -384,24 +384,20 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) break; case LFUN_FINISHED_LEFT: - cur.pop(cur.currentDepth()); cur.bv().cursor() = cur; break; case LFUN_FINISHED_RIGHT: - cur.pop(cur.currentDepth()); ++cur.pos(); cur.bv().cursor() = cur; break; case LFUN_FINISHED_UP: - cur.pop(cur.currentDepth()); //idxUpDown(cur, true); cur.bv().cursor() = cur; break; case LFUN_FINISHED_DOWN: - cur.pop(cur.currentDepth()); //idxUpDown(cur, false); cur.bv().cursor() = cur; break; @@ -554,7 +550,15 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) break; case LFUN_INSET_TOGGLE: - cur.lockToggle(); + //lockToggle(); + if (cur.pos() != cur.lastpos()) { + // toggle previous inset ... + cur.nextAtom().nucleus()->lock(!cur.nextAtom()->lock()); + } else if (cur.popLeft() && cur.pos() != cur.lastpos()) { + // ... or enclosing inset if we are in the last inset position + cur.nextAtom().nucleus()->lock(!cur.nextAtom()->lock()); + ++cur.pos(); + } break; case LFUN_SELFINSERT: @@ -780,7 +784,7 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) cur.insert(ar); break; } - cur.notdispatched(); + cur.undispatched(); break; } @@ -790,7 +794,7 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_WORD_REPLACE: case LFUN_WORD_FIND: if (!searchForward(&cur.bv(), cmd.getArg(0), false, false)) - cur.notdispatched(); + cur.undispatched(); break; cur.normalize(); @@ -876,7 +880,7 @@ void MathNestInset::lfunMouseRelease(LCursor & cur, FuncRequest const & cmd) return; } - cur.notdispatched(); + cur.undispatched(); } @@ -914,9 +918,7 @@ void MathNestInset::lfunMouseMotion(LCursor & cur, FuncRequest const & cmd) cur.selBegin(); //cur.setScreenPos(cmd.x + xo_, cmd.y + yo_); - cur.bv().cursor().cursor_ = cur.cursor_; - cur.bv().cursor().selection() = true; - return; + cur.bv().cursor().setCursor(cur, true); } diff --git a/src/mathed/ref_inset.C b/src/mathed/ref_inset.C index 6350669d5e..5089f85ec2 100644 --- a/src/mathed/ref_inset.C +++ b/src/mathed/ref_inset.C @@ -61,36 +61,35 @@ void RefInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) MathArray ar; if (createMathInset_fromDialogStr(cmd.argument, ar)) { *this = *ar[0].nucleus()->asRefInset(); - return; + break; } } - cur.notdispatched(); - return; + cur.undispatched(); + break; case LFUN_MOUSE_RELEASE: if (cmd.button() == mouse_button::button3) { lyxerr << "trying to goto ref" << cell(0) << endl; cur.bv().dispatch(FuncRequest(LFUN_REF_GOTO, asString(cell(0)))); - return; + break; } if (cmd.button() == mouse_button::button1) { - // Eventually trigger dialog with button 3 - // not 1 + // Eventually trigger dialog with button 3, not 1 string const data = createDialogStr("ref"); cur.bv().owner()->getDialogs().show("ref", data, this); - return; + break; } - cur.notdispatched(); - return; + cur.undispatched(); + break; case LFUN_MOUSE_PRESS: case LFUN_MOUSE_MOTION: // eat other mouse commands - return; + break; default: CommandInset::priv_dispatch(cur, cmd); - return; + break; } } diff --git a/src/text.C b/src/text.C index e8754421c1..3951e81102 100644 --- a/src/text.C +++ b/src/text.C @@ -1168,10 +1168,10 @@ void LyXText::cursorLeftOneWord(LCursor & cur) void LyXText::selectWord(LCursor & cur, word_location loc) { BOOST_ASSERT(this == cur.text()); - CursorSlice from = cur.current(); - CursorSlice to = cur.current(); + CursorSlice from = cur.top(); + CursorSlice to = cur.top(); getWord(from, to, loc); - if (cur.current() != from) + if (cur.top() != from) setCursor(cur, from.par(), from.pos()); if (to == from) return; @@ -1340,9 +1340,9 @@ void LyXText::Delete(LCursor & cur) { BOOST_ASSERT(this == cur.text()); // just move to the right, if we had success make a backspace - CursorSlice sl = cur.current(); + CursorSlice sl = cur.top(); cursorRight(cur); - if (sl == cur.current()) { + if (sl == cur.top()) { recordUndo(cur, Undo::DELETE, cur.par(), max(0, cur.par() - 1)); backspace(cur); } @@ -1820,9 +1820,9 @@ int LyXText::cursorX(CursorSlice const & cur) const ParagraphList::iterator pit = getPar(cur); if (pit->rows.empty()) return xo_; + Row const & row = *pit->getRow(cur.pos()); - pos_type pos = cur.pos(); pos_type cursor_vpos = 0; @@ -1894,7 +1894,7 @@ CursorSlice & LyXText::cursor() << "\nthis: " << this << endl; BOOST_ASSERT(false); } - return bv()->cursor().current(); + return bv()->cursor().top(); } @@ -1906,7 +1906,7 @@ CursorSlice const & LyXText::cursor() const << "\nthis: " << this << endl; BOOST_ASSERT(false); } - return bv()->cursor().current(); + return bv()->cursor().top(); } diff --git a/src/text2.C b/src/text2.C index af078d47b4..f5acc81d85 100644 --- a/src/text2.C +++ b/src/text2.C @@ -414,9 +414,8 @@ void LyXText::setFont(LCursor & cur, LyXFont const & font, bool toggleall) return; } - // ok we have a selection. + // Ok, we have a selection. recordUndoSelection(cur); - freezeUndo(); ParagraphList::iterator beg = getPar(cur.selBegin().par()); ParagraphList::iterator end = getPar(cur.selEnd().par()); @@ -432,8 +431,6 @@ void LyXText::setFont(LCursor & cur, LyXFont const & font, bool toggleall) setCharFont(pos.pit(), pos.pos(), f); } - unFreezeUndo(); - redoParagraphs(beg, ++end); } @@ -486,7 +483,7 @@ void LyXText::toggleFree(LCursor & cur, LyXFont const & font, bool toggleall) // Try implicit word selection // If there is a change in the language the implicit word selection // is disabled. - CursorSlice resetCursor = cur.current(); + CursorSlice resetCursor = cur.top(); bool implicitSelection = font.language() == ignore_language && font.number() == LyXFont::IGNORE @@ -499,7 +496,7 @@ void LyXText::toggleFree(LCursor & cur, LyXFont const & font, bool toggleall) // and cursor is set to the original position. if (implicitSelection) { cur.clearSelection(); - cur.current() = resetCursor; + cur.top() = resetCursor; cur.resetAnchor(); } } @@ -511,7 +508,7 @@ string LyXText::getStringToIndex(LCursor & cur) // Try implicit word selection // If there is a change in the language the implicit word selection // is disabled. - CursorSlice const reset_cursor = cur.current(); + CursorSlice const reset_cursor = cur.top(); bool const implicitSelection = selectWordWhenUnderCursor(cur, lyx::PREVIOUS_WORD); @@ -524,7 +521,7 @@ string LyXText::getStringToIndex(LCursor & cur) idxstring = cur.selectionAsString(false); // Reset cursors to their original position. - cur.current() = reset_cursor; + cur.top() = reset_cursor; cur.resetAnchor(); // Clear the implicit selection. @@ -1088,9 +1085,9 @@ void LyXText::insertStringAsParagraphs(LCursor & cur, string const & str) bool LyXText::setCursor(LCursor & cur, par_type par, pos_type pos, bool setfont, bool boundary) { - CursorSlice old_cursor = cur.current(); + CursorSlice old_cursor = cur.top(); setCursorIntern(cur, par, pos, setfont, boundary); - return deleteEmptyParagraphMechanism(cur.current(), old_cursor); + return deleteEmptyParagraphMechanism(cur.top(), old_cursor); } @@ -1145,8 +1142,8 @@ void LyXText::setCursor(CursorSlice & cur, par_type par, void LyXText::setCursorIntern(LCursor & cur, par_type par, pos_type pos, bool setfont, bool boundary) { - setCursor(cur.current(), par, pos, boundary); - cur.x_target() = cursorX(cur.current()); + setCursor(cur.top(), par, pos, boundary); + cur.x_target() = cursorX(cur.top()); if (setfont) setCurrentFont(cur); } @@ -1298,7 +1295,7 @@ void LyXText::setCursorFromCoordinates(LCursor & cur, int x, int y) { x -= xo_; y -= yo_; - CursorSlice old_cursor = cur.current(); + CursorSlice old_cursor = cur.top(); ParagraphList::iterator pit; Row const & row = *getRowNearY(y, pit); lyxerr << "hit row at: " << row.pos() << endl; @@ -1308,7 +1305,7 @@ void LyXText::setCursorFromCoordinates(LCursor & cur, int x, int y) cur.par() = parOffset(pit); cur.pos() = pos; cur.boundary() = bound; - deleteEmptyParagraphMechanism(cur.current(), old_cursor); + deleteEmptyParagraphMechanism(cur.top(), old_cursor); } @@ -1402,7 +1399,7 @@ void LyXText::cursorUp(LCursor & cur) { Row const & row = cur.textRow(); int x = cur.x_target(); - int y = cursorY(cur.current()) - row.baseline() - 1; + int y = cursorY(cur.top()) - row.baseline() - 1; setCursorFromCoordinates(cur, x, y); if (!cur.selection()) { @@ -1417,7 +1414,7 @@ void LyXText::cursorDown(LCursor & cur) { Row const & row = cur.textRow(); int x = cur.x_target(); - int y = cursorY(cur.current()) - row.baseline() + row.height() + 1; + int y = cursorY(cur.top()) - row.baseline() + row.height() + 1; setCursorFromCoordinates(cur, x, y); if (!cur.selection()) { diff --git a/src/text3.C b/src/text3.C index 2a74b4218c..113d7b90a3 100644 --- a/src/text3.C +++ b/src/text3.C @@ -262,7 +262,7 @@ void LyXText::gotoInset(LCursor & cur, if (!gotoNextInset(cur, codes, contents)) { if (cur.pos() || cur.par() != 0) { - CursorSlice tmp = cur.current(); + CursorSlice tmp = cur.top(); cur.par() = 0; cur.pos() = 0; if (!gotoNextInset(cur, codes, contents)) { @@ -376,7 +376,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) //lyxerr << "*** LyXText::dispatch: cmd: " << cmd << endl; BufferView * bv = &cur.bv(); - CursorSlice sl = cur.current(); + CursorSlice sl = cur.top(); switch (cmd.action) { @@ -466,7 +466,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) cursorLeft(cur); else cursorRight(cur); - if (sl == cur.current()) + if (sl == cur.top()) cur.dispatched(FINISHED_RIGHT); break; @@ -477,7 +477,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) cursorRight(cur); else cursorLeft(cur); - if (sl == cur.current()) + if (sl == cur.top()) cur.dispatched(FINISHED_LEFT); break; @@ -485,7 +485,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_UPSEL: cur.selHandle(cmd.action == LFUN_UPSEL); cursorUp(cur); - if (sl == cur.current()) + if (sl == cur.top()) cur.dispatched(FINISHED_UP); break; @@ -493,7 +493,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_DOWNSEL: cur.selHandle(cmd.action == LFUN_DOWNSEL); cursorDown(cur); - if (sl == cur.current()) + if (sl == cur.top()) cur.dispatched(FINISHED_DOWN); break; @@ -788,7 +788,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_INSET_TOGGLE: cur.clearSelection(); if (!toggleInset(cur)) - cur.notdispatched(); + cur.undispatched(); else bv->switchKeyMap(); break; @@ -869,7 +869,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_BEGINNINGBUFSEL: if (in_inset_) { - cur.notdispatched(); + cur.undispatched(); } else { if (!cur.selection()) cur.resetAnchor(); @@ -880,7 +880,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_ENDBUFSEL: if (in_inset_) { - cur.notdispatched(); + cur.undispatched(); } else { if (!cur.selection()) cur.resetAnchor(); @@ -890,8 +890,8 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) break; case LFUN_GETXY: - cur.message(tostr(cursorX(cur.current())) + ' ' - + tostr(cursorY(cur.current()))); + cur.message(tostr(cursorX(cur.top())) + ' ' + + tostr(cursorY(cur.top()))); break; case LFUN_SETXY: { @@ -1095,12 +1095,12 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) "Dispatch: no selection possible\n"; break; } - CursorSlice old = cur.current(); + CursorSlice old = cur.top(); setCursorFromCoordinates(cur, cmd.x, cmd.y); // This is to allow jumping over large insets // FIXME: shouldn't be top-text-specific - if (!in_inset_ && cur.current() == old) { + if (!in_inset_ && cur.top() == old) { if (cmd.y - bv->top_y() >= bv->workHeight()) cursorDown(cur); else if (cmd.y - bv->top_y() < 0) @@ -1108,8 +1108,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) } // don't set anchor_ - bv->cursor().cursor_ = cur.cursor_; - bv->cursor().setSelection(); + bv->cursor().setCursor(cur, false); break; } @@ -1154,7 +1153,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) setCursorFromCoordinates(cur, cmd.x, cmd.y); cur.resetAnchor(); finishUndo(); - cur.x_target() = cursorX(cur.current()); + cur.x_target() = cursorX(cur.top()); // set cursor and anchor to this position bv->cursor() = cur; @@ -1179,7 +1178,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) // do nothing if we used the mouse wheel if (cmd.button() == mouse_button::button4 || cmd.button() == mouse_button::button5) { - cur.notdispatched(); + cur.undispatched(); break; } @@ -1444,7 +1443,6 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_FINISHED_LEFT: lyxerr << "handle LFUN_FINISHED_LEFT" << endl; - cur.pop(cur.currentDepth()); if (isRTL(cur.paragraph())) cursorLeft(cur); cur.bv().cursor() = cur; @@ -1452,7 +1450,6 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_FINISHED_RIGHT: lyxerr << "handle LFUN_FINISHED_RIGHT" << endl; - cur.pop(cur.currentDepth()); if (!isRTL(cur.paragraph())) cursorRight(cur); cur.bv().cursor() = cur; @@ -1460,14 +1457,12 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_FINISHED_UP: lyxerr << "handle LFUN_FINISHED_UP" << endl; - cur.pop(cur.currentDepth()); cursorUp(cur); cur.bv().cursor() = cur; break; case LFUN_FINISHED_DOWN: lyxerr << "handle LFUN_FINISHED_DOWN" << endl; - cur.pop(cur.currentDepth()); cursorDown(cur); cur.bv().cursor() = cur; break; @@ -1598,7 +1593,7 @@ void LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) break; default: - cur.notdispatched(); + cur.undispatched(); break; } } diff --git a/src/undo.C b/src/undo.C index 2f32fe663a..c5a14fe45b 100644 --- a/src/undo.C +++ b/src/undo.C @@ -27,27 +27,15 @@ using lyx::paroffset_type; -/// The flag used by finishUndo(). -bool undo_finished; +namespace { /// Whether actions are not added to the undo stacks. bool undo_frozen; -Undo::Undo(undo_kind kind_, int text_, int index_, - int first_par_, int end_par_, int cursor_par_, int cursor_pos_) - : - kind(kind_), - text(text_), - index(index_), - first_par(first_par_), - end_par(end_par_), - cursor_par(cursor_par_), - cursor_pos(cursor_pos_) -{} +/// The flag used by finishUndo(). +bool undo_finished; -namespace { - std::ostream & operator<<(std::ostream & os, Undo const & undo) { return os << " text: " << undo.text @@ -97,6 +85,15 @@ void recordUndo(Undo::undo_kind kind, LCursor & cur, paroffset_type first_par, paroffset_type last_par, limited_stack & stack) { +#if 0 + DocumentIterator it = bufferBegin(cur.bv()); + DocumentIterator et = bufferEnd(); + size_t count = 0; + for ( ; it != et; it.forwardPos(), ++count) + if (it.top() == cur.top()) + lyxerr << "### found at " << count << std::endl; +#endif + if (first_par > last_par) { paroffset_type t = first_par; first_par = last_par; @@ -121,27 +118,39 @@ void recordUndo(Undo::undo_kind kind, } } - // make and push the Undo entry - int textnum; - LyXText * text = cur.text(); - BOOST_ASSERT(text); // not in mathed (yet) - ParIterator pit = text2pit(buf, text, textnum); - stack.push(Undo(kind, textnum, pit.index(), - first_par, end_par, cur.par(), cur.pos())); - //lyxerr << "undo record: " << stack.top() << std::endl; + // push and fill the Undo entry + if (cur.inTexted()) { + stack.push(Undo()); + LyXText * text = cur.text(); + int textnum; + ParIterator pit = text2pit(buf, text, textnum); + Undo & undo = stack.top(); + undo.kind = kind; + undo.text = textnum; + undo.index = pit.index(); + undo.first_par = first_par; + undo.end_par = end_par; + undo.cursor_par = cur.par(); + undo.cursor_pos = cur.pos(); + undo.math = false; + //lyxerr << "undo record: " << stack.top() << std::endl; - // record the relevant paragraphs - ParagraphList & undo_pars = stack.top().pars; + // record the relevant paragraphs + ParagraphList & plist = text->paragraphs(); + ParagraphList::iterator first = plist.begin(); + advance(first, first_par); + ParagraphList::iterator last = plist.begin(); + advance(last, last_par); - ParagraphList & plist = text->paragraphs(); - ParagraphList::iterator first = plist.begin(); - advance(first, first_par); - ParagraphList::iterator last = plist.begin(); - advance(last, last_par); - - for (ParagraphList::iterator it = first; it != last; ++it) - undo_pars.push_back(*it); - undo_pars.push_back(*last); + for (ParagraphList::iterator it = first; it != last; ++it) + undo.pars.push_back(*it); + undo.pars.push_back(*last); + } else { + BOOST_ASSERT(false); // not in mathed (yet) + stack.push(Undo()); + Undo & undo = stack.top(); + undo.math = false; + } // and make sure that next time, we should be combining if possible undo_finished = false; diff --git a/src/undo.h b/src/undo.h index dfa93d440d..17fc89dc62 100644 --- a/src/undo.h +++ b/src/undo.h @@ -19,6 +19,8 @@ #include "ParagraphList_fwd.h" #include "support/types.h" +#include + class LCursor; class BufferView; @@ -28,8 +30,7 @@ class BufferView; * contains complete paragraphs and sufficient information * to restore the state. */ -class Undo { -public: +struct Undo { /// This is used to combine consecutive undo recordings of the same kind. enum undo_kind { /** @@ -46,11 +47,6 @@ public: ATOMIC }; - /// constructor - Undo(undo_kind kind, int text, int index, - int first_par, int end_par, int cursor_par, int cursor_pos); - -public: /// which kind of operation are we recording for? undo_kind kind; /// hosting LyXText counted from buffer begin @@ -65,8 +61,12 @@ public: int cursor_par; /// the position of the cursor in the hosting paragraph int cursor_pos; - /// the contents of the paragraphs saved + /// the contents of the saved paragraphs (for texted) ParagraphList pars; + /// the contents of the saved matharray (for mathed) + std::string array; + /// in mathed? + bool math; }; @@ -79,7 +79,7 @@ bool textRedo(BufferView &); /// makes sure the next operation will be stored void finishUndo(); -/// whilst undo is frozen, all actions do not get added to the undo stack +/// whilst undo is frozen, no actions gets added to the undo stack void freezeUndo(); /// track undos again @@ -108,7 +108,4 @@ void recordUndoSelection(LCursor & cur, Undo::undo_kind kind = Undo::ATOMIC); /// convienience: prepare undo for the single paragraph containing the cursor void recordUndoFullDocument(LCursor & cur); -/// are we avoiding tracking undos currently? -extern bool undo_frozen; - #endif // UNDO_FUNCS_H