X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FCursor.cpp;h=ac230a15e003cb2ca9ad18163e97f0e583bbce02;hb=09df753df4c24470617c64d25eae6df2db85dfed;hp=7147f8152a0b1b358bdd62109ea417935003189e;hpb=1050cc44714f8b78e233d6a559ead3d7a8b6aa56;p=lyx.git diff --git a/src/Cursor.cpp b/src/Cursor.cpp index 7147f8152a..ac230a15e0 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -15,7 +15,6 @@ #include "Bidi.h" #include "BufferView.h" -#include "bufferview_funcs.h" #include "Buffer.h" #include "Cursor.h" #include "CoordCache.h" @@ -34,16 +33,16 @@ #include "Paragraph.h" #include "paragraph_funcs.h" #include "ParIterator.h" +#include "TextMetrics.h" #include "insets/InsetTabular.h" #include "insets/InsetText.h" -#include "mathed/MathData.h" #include "mathed/InsetMath.h" #include "mathed/InsetMathScript.h" #include "mathed/MacroTable.h" - -#include "support/limited_stack.h" +#include "mathed/MathData.h" +#include "mathed/MathMacro.h" #include #include @@ -97,9 +96,9 @@ namespace { int xo; int yo; Inset const * inset = &it.inset(); - std::map const & data = + std::map const & data = c.bv().coordCache().getInsets().getData(); - std::map::const_iterator I = data.find(inset); + std::map::const_iterator I = data.find(inset); // FIXME: in the case where the inset is not in the cache, this // means that no part of it is visible on screen. In this case @@ -110,7 +109,7 @@ namespace { return it; } - Point o = I->second; + Point o = I->second.pos; inset->cursorPos(c.bv(), it.top(), c.boundary(), xo, yo); // Convert to absolute xo += o.x_; @@ -132,6 +131,7 @@ namespace { } + /* /// moves position closest to (x, y) in given box bool bruteFind(Cursor & cursor, int x, int y, int xlow, int xhigh, int ylow, int yhigh) @@ -161,7 +161,7 @@ namespace { for ( ; it != et; it.forwardPos(true)) { // avoid invalid nesting when selecting if (!cursor.selection() || positionable(it, cursor.anchor_)) { - Point p = bv_funcs::getPos(bv, it, false); + Point p = bv.getPos(it, false); int xo = p.x_; int yo = p.y_; if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) { @@ -186,6 +186,7 @@ namespace { return false; } + */ /// moves position closest to (x, y) in given box @@ -206,7 +207,7 @@ namespace { // << " xlow: " << xlow << " xhigh: " << xhigh // << " ylow: " << ylow << " yhigh: " << yhigh // << endl; - Inset & inset = bv.buffer()->inset(); + Inset & inset = bv.buffer().inset(); DocIterator it = doc_iterator_begin(inset); it.pit() = from; DocIterator et = doc_iterator_end(inset); @@ -216,9 +217,9 @@ namespace { for ( ; it != et; it.forwardPos()) { // avoid invalid nesting when selecting - if (bv_funcs::status(&bv, it) == bv_funcs::CUR_INSIDE + if (bv.cursorStatus(it) == CUR_INSIDE && (!cur.selection() || positionable(it, cur.anchor_))) { - Point p = bv_funcs::getPos(bv, it, false); + Point p = bv.getPos(it, false); int xo = p.x_; int yo = p.y_; if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) { @@ -253,8 +254,8 @@ namespace { odocstringstream ods; ods << '\n'; // only add blank line if we're not in an ERT or Listings inset - if (par.ownerCode() != Inset::ERT_CODE - && par.ownerCode() != Inset::LISTINGS_CODE) + if (par.ownerCode() != ERT_CODE + && par.ownerCode() != LISTINGS_CODE) ods << '\n'; return ods.str(); } @@ -266,7 +267,8 @@ namespace { // bv functions are not yet available! Cursor::Cursor(BufferView & bv) : DocIterator(), bv_(&bv), anchor_(), x_target_(-1), textTargetOffset_(0), - selection_(false), mark_(false), logicalpos_(false) + selection_(false), mark_(false), logicalpos_(false), + current_font(inherit_font) {} @@ -351,8 +353,7 @@ BufferView & Cursor::bv() const Buffer & Cursor::buffer() const { BOOST_ASSERT(bv_); - BOOST_ASSERT(bv_->buffer()); - return *bv_->buffer(); + return bv_->buffer(); } @@ -418,7 +419,7 @@ int Cursor::currentMode() void Cursor::getPos(int & x, int & y) const { - Point p = bv_funcs::getPos(bv(), *this, boundary()); + Point p = bv().getPos(*this, boundary()); x = p.x_; y = p.y_; } @@ -674,17 +675,17 @@ bool Cursor::openable(MathAtom const & t) const // we can't move into anything new during selection if (depth() >= anchor_.depth()) return false; - if (!ptr_cmp(t.nucleus(), &anchor_[depth()].inset())) + if (t.nucleus() != &anchor_[depth()].inset()) return false; return true; } -void Cursor::setScreenPos(int x, int y) +void Cursor::setScreenPos(int x, int /*y*/) { setTargetX(x); - bruteFind(*this, x, y, 0, bv().workWidth(), 0, bv().workHeight()); + //bruteFind(*this, x, y, 0, bv().workWidth(), 0, bv().workHeight()); } @@ -943,7 +944,13 @@ bool Cursor::macroModeClose() InsetMathNest * const in = inset().asInsetMath()->asNestInset(); if (in && in->interpretString(*this, s)) return true; - plainInsert(createInsetMath(name)); + MathAtom atom = createInsetMath(name); + MathMacro * atomAsMacro = atom.nucleus()->asMacro(); + if (atomAsMacro) { + // make non-greedy, i.e. don't eat parameters from the right + atomAsMacro->setDisplayMode(MathMacro::DISPLAY_NONGREEDY_INIT); + } + plainInsert(atom); return true; } @@ -1077,7 +1084,7 @@ bool Cursor::upDownInMath(bool up) // We want to keep the x-target on subsequent up/down movements // that cross beyond the end of short lines. Thus a special - // handling when the cursor is at the end of line: Use the new + // handling when the cursor is at the end of line: Use the new // x-target only if the old one was before the end of line // or the old one was after the beginning of the line bool inRTL = isWithinRtlParagraph(*this); @@ -1091,12 +1098,12 @@ bool Cursor::upDownInMath(bool up) right = pos() == textRow().endpos(); } if ((!left && !right) || - (left && !right && xo < x_target_) || + (left && !right && xo < x_target_) || (!left && right && x_target_ < xo)) setTargetX(xo); else xo = targetX(); - } else + } else xo = targetX(); // try neigbouring script insets @@ -1169,7 +1176,7 @@ bool Cursor::upDownInMath(bool up) } -bool Cursor::upDownInText(bool up, bool & updateNeeded) +bool Cursor::upDownInText(bool up, bool & updateNeeded) { BOOST_ASSERT(text()); @@ -1184,14 +1191,14 @@ bool Cursor::upDownInText(bool up, bool & updateNeeded) // if we cannot move up/down inside this inset anymore if (x_target_ == -1) setTargetX(xo); - else if (xo - textTargetOffset() != x_target() && + else if (xo - textTargetOffset() != x_target() && depth() == beforeDispatchCursor_.depth()) { // In text mode inside the line (not left or right) possibly set a new target_x, // but only if we are somewhere else than the previous target-offset. // We want to keep the x-target on subsequent up/down movements // that cross beyond the end of short lines. Thus a special - // handling when the cursor is at the end of line: Use the new + // handling when the cursor is at the end of line: Use the new // x-target only if the old one was before the end of line // or the old one was after the beginning of the line bool inRTL = isWithinRtlParagraph(*this); @@ -1205,16 +1212,16 @@ bool Cursor::upDownInText(bool up, bool & updateNeeded) right = pos() == textRow().endpos(); } if ((!left && !right) || - (left && !right && xo < x_target_) || + (left && !right && xo < x_target_) || (!left && right && x_target_ < xo)) setTargetX(xo); else xo = targetX(); - } else + } else xo = targetX(); // first get the current line - TextMetrics const & tm = bv_->textMetrics(text()); + TextMetrics & tm = bv_->textMetrics(text()); ParagraphMetrics const & pm = tm.parMetrics(pit()); int row; if (pos() && boundary()) @@ -1227,20 +1234,20 @@ bool Cursor::upDownInText(bool up, bool & updateNeeded) if (pit() == 0 && row == 0) return false; } else { - if (pit() + 1 >= int(text()->paragraphs().size()) && + if (pit() + 1 >= int(text()->paragraphs().size()) && row + 1 >= int(pm.rows().size())) return false; } // with and without selection are handled differently if (!selection()) { - int yo = bv_funcs::getPos(bv(), *this, boundary()).y_; + int yo = bv().getPos(*this, boundary()).y_; Cursor old = *this; // To next/previous row if (up) - text()->editXY(*this, xo, yo - textRow().ascent() - 1); + tm.editXY(*this, xo, yo - textRow().ascent() - 1); else - text()->editXY(*this, xo, yo + textRow().descent() + 1); + tm.editXY(*this, xo, yo + textRow().descent() + 1); clearSelection(); // This happens when you move out of an inset. @@ -1336,7 +1343,7 @@ docstring Cursor::selectionAsString(bool label) const return docstring(); if (inTexted()) { - Buffer const & buffer = *bv().buffer(); + Buffer const & buffer = bv().buffer(); ParagraphList const & pars = text()->paragraphs(); // should be const ... @@ -1398,8 +1405,6 @@ Encoding const * Cursor::getEncoding() const { if (empty()) return 0; - if (!bv().buffer()) - return 0; int s = 0; // go up until first non-0 text is hit // (innermost text is 0 in mathed) @@ -1409,7 +1414,7 @@ Encoding const * Cursor::getEncoding() const CursorSlice const & sl = operator[](s); Text const & text = *sl.text(); Font font = text.getPar(sl.pit()).getFont( - bv().buffer()->params(), sl.pos(), outerFont(sl.pit(), text.paragraphs())); + bv().buffer().params(), sl.pos(), outerFont(sl.pit(), text.paragraphs())); return font.language()->encoding(); } @@ -1440,7 +1445,7 @@ void Cursor::noUpdate() Font Cursor::getFont() const { - // The logic here should more or less match to the Text::setCurrentFont + // The logic here should more or less match to the Cursor::setCurrentFont // logic, i.e. the cursor height should give a hint what will happen // if a character is entered. @@ -1462,26 +1467,29 @@ Font Cursor::getFont() const // on space? Take the font before (only for RTL boundary stay) if (pos > 0) { + TextMetrics const & tm = bv().textMetrics(&text); if (pos == sl.lastpos() - || (par.isSeparator(pos) && - !text.isRTLBoundary(buffer(), par, pos))) + || (par.isSeparator(pos) + && !tm.isRTLBoundary(sl.pit(), pos))) --pos; } // get font at the position - Font font = par.getFont(bv().buffer()->params(), pos, + Font font = par.getFont(bv().buffer().params(), pos, outerFont(sl.pit(), text.paragraphs())); return font; } -void Cursor::fixIfBroken() +bool Cursor::fixIfBroken() { if (DocIterator::fixIfBroken()) { clearSelection(); resetAnchor(); + return true; } + return false; } @@ -1505,4 +1513,123 @@ bool notifyCursorLeaves(DocIterator const & old, Cursor & cur) } +void Cursor::setCurrentFont() +{ + CursorSlice const & cs = innerTextSlice(); + Paragraph const & par = cs.paragraph(); + pos_type cpit = cs.pit(); + pos_type cpos = cs.pos(); + Text const & ctext = *cs.text(); + TextMetrics const & tm = bv().textMetrics(&ctext); + + // are we behind previous char in fact? -> go to that char + if (cpos > 0 && boundary()) + --cpos; + + // find position to take the font from + if (cpos != 0) { + // paragraph end? -> font of last char + if (cpos == lastpos()) + --cpos; + // on space? -> look at the words in front of space + else if (cpos > 0 && par.isSeparator(cpos)) { + // abc| def -> font of c + // abc |[WERBEH], i.e. boundary==true -> font of c + // abc [WERBEH]| def, font of the space + if (!tm.isRTLBoundary(cpit, cpos)) + --cpos; + } + } + + // get font + BufferParams const & bufparams = buffer().params(); + current_font = par.getFontSettings(bufparams, cpos); + real_current_font = tm.getDisplayFont(cpit, cpos); + + // special case for paragraph end + if (cs.pos() == lastpos() + && tm.isRTLBoundary(cpit, cs.pos()) + && !boundary()) { + Language const * lang = par.getParLanguage(bufparams); + current_font.setLanguage(lang); + current_font.fontInfo().setNumber(FONT_OFF); + real_current_font.setLanguage(lang); + real_current_font.fontInfo().setNumber(FONT_OFF); + } +} + + +bool Cursor::textUndo() +{ + DocIterator dit = *this; + // Undo::textUndo() will modify dit. + if (!bv_->buffer().undo().textUndo(dit)) + return false; + // Set cursor + setCursor(dit); + selection() = false; + resetAnchor(); + fixIfBroken(); + return true; +} + + +bool Cursor::textRedo() +{ + DocIterator dit = *this; + // Undo::textRedo() will modify dit. + if (!bv_->buffer().undo().textRedo(dit)) + return false; + // Set cursor + setCursor(dit); + selection() = false; + resetAnchor(); + fixIfBroken(); + return true; +} + + +void Cursor::finishUndo() +{ + bv_->buffer().undo().finishUndo(); +} + + +void Cursor::recordUndo(UndoKind kind, pit_type from, pit_type to) +{ + bv_->buffer().undo().recordUndo(*this, kind, from, to); +} + + +void Cursor::recordUndo(UndoKind kind, pit_type from) +{ + bv_->buffer().undo().recordUndo(*this, kind, from); +} + + +void Cursor::recordUndo(UndoKind kind) +{ + bv_->buffer().undo().recordUndo(*this, kind); +} + + +void Cursor::recordUndoInset(UndoKind kind) +{ + bv_->buffer().undo().recordUndoInset(*this, kind); +} + + +void Cursor::recordUndoFullDocument() +{ + bv_->buffer().undo().recordUndoFullDocument(*this); +} + + +void Cursor::recordUndoSelection() +{ + bv_->buffer().undo().recordUndo(*this, ATOMIC_UNDO, + selBegin().pit(), selEnd().pit()); +} + + } // namespace lyx