X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FCursor.cpp;h=0e1c3ded5558c9dd62283ad29d738fc1c15e552d;hb=26ba2a65838731ce639a09539f617cb0f0be3b22;hp=7a723c6fdfa6de1774aab1e726c4b4a2b7048e62;hpb=abaf2e9bda86b74c4b29b6ead106026665f02a1b;p=lyx.git diff --git a/src/Cursor.cpp b/src/Cursor.cpp index 7a723c6fdf..0e1c3ded55 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -38,6 +38,7 @@ #include "support/gettext.h" #include "support/lassert.h" +#include "insets/InsetLayout.h" #include "insets/InsetTabular.h" #include "mathed/InsetMath.h" @@ -321,6 +322,7 @@ DocIterator CursorData::selectionEnd() const if (di.depth() > depth()) { di.resize(depth()); ++di.pos(); + di.boundary(true); } return di; } @@ -502,7 +504,7 @@ void CursorData::clearSelection() } -int CursorData::countInsetsInSelection(InsetCode const & inset_code) +int CursorData::countInsetsInSelection(InsetCode const & inset_code) const { if (!selection_) return 0; @@ -528,7 +530,7 @@ int CursorData::countInsetsInSelection(InsetCode const & inset_code) } -bool CursorData::insetInSelection(InsetCode const & inset_code) +bool CursorData::insetInSelection(InsetCode const & inset_code) const { if (!selection_) return false; @@ -637,9 +639,9 @@ void CursorData::recordUndo(UndoKind kind) const } -void CursorData::recordUndoInset(Inset const * in) const +void CursorData::recordUndoInset(Inset const * inset) const { - buffer()->undo().recordUndoInset(*this, in); + buffer()->undo().recordUndoInset(*this, inset); } @@ -669,7 +671,7 @@ void CursorData::recordUndoSelection() const } -int CursorData::currentMode() +int CursorData::currentMode() const { LASSERT(!empty(), return Inset::UNDECIDED_MODE); for (int i = depth() - 1; i >= 0; --i) { @@ -712,6 +714,7 @@ bool CursorData::confirmDeletion(bool const before) const Cursor::Cursor(BufferView & bv) : CursorData(&bv.buffer()), bv_(&bv), x_target_(-1), textTargetOffset_(0), + x_clickpos_(-1), y_clickpos_(-1), beforeDispatchPosX_(0), beforeDispatchPosY_(0) {} @@ -787,15 +790,15 @@ void Cursor::dispatch(FuncRequest const & cmd0) beginUndoGroup(); + Inset * nextins = nextInset(); // Is this a function that acts on inset at point? - if (lyxaction.funcHasFlag(cmd.action(), LyXAction::AtPoint) - && nextInset()) { + if (lyxaction.funcHasFlag(cmd.action(), LyXAction::AtPoint) && nextins) { disp_.dispatched(true); disp_.screenUpdate(Update::FitCursor | Update::Force); FuncRequest tmpcmd = cmd; - LYXERR(Debug::DEBUG, "Cursor::dispatch: (AtPoint) cmd: " + LYXERR(Debug::ACTION, "Cursor::dispatch: (AtPoint) cmd: " << cmd0 << endl << *this); - nextInset()->dispatch(*this, tmpcmd); + nextins->dispatch(*this, tmpcmd); if (disp_.dispatched()) { endUndoGroup(); return; @@ -805,7 +808,7 @@ void Cursor::dispatch(FuncRequest const & cmd0) // store some values to be used inside of the handlers beforeDispatchCursor_ = *this; for (; depth(); pop(), boundary(false)) { - LYXERR(Debug::DEBUG, "Cursor::dispatch: cmd: " + LYXERR(Debug::ACTION, "Cursor::dispatch: cmd: " << cmd0 << endl << *this); // In any of these cases, the cursor is invalid, and we should @@ -827,7 +830,7 @@ void Cursor::dispatch(FuncRequest const & cmd0) // it completely to get a 'bomb early' behaviour in case this // object will be used again. if (!disp_.dispatched()) { - LYXERR(Debug::DEBUG, "RESTORING OLD CURSOR!"); + LYXERR(Debug::ACTION, "RESTORING OLD CURSOR!"); // We might have invalidated the cursor when removing an empty // paragraph while the cursor could not be moved out the inset // while we initially thought we could. This might happen when @@ -897,19 +900,19 @@ void Cursor::pop() } -void Cursor::push(Inset & p) +void Cursor::push(Inset & inset) { - push_back(CursorSlice(p)); - p.setBuffer(*buffer()); + push_back(CursorSlice(inset)); + inset.setBuffer(*buffer()); } -void Cursor::pushBackward(Inset & p) +void Cursor::pushBackward(Inset & inset) { LASSERT(!empty(), return); //lyxerr << "Entering inset " << t << " front" << endl; - push(p); - p.idxFirst(*this); + push(inset); + inset.idxFirst(*this); } @@ -1379,19 +1382,26 @@ void Cursor::updateTextTargetOffset() } -bool Cursor::selHandle(bool sel) +void Cursor::setClickPos(int x, int y) +{ + x_clickpos_ = x; + y_clickpos_ = y; +} + + +bool Cursor::selHandle(bool selecting) { //lyxerr << "Cursor::selHandle" << endl; if (mark()) - sel = true; - if (sel == selection()) + selecting = true; + if (selecting == selection()) return false; - if (!sel) + if (!selecting) cap::saveSelection(*this); resetAnchor(); - selection(sel); + selection(selecting); return true; } @@ -1593,9 +1603,20 @@ bool Cursor::backspace(bool const force) // [|], can not delete from inside return false; } else { - if (inMathed()) - pullArg(); - else + if (inMathed()) { + switch (inset().asInsetMath()->getType()) { + case hullEqnArray: + case hullAlign: + case hullFlAlign: { + FuncRequest cmd(LFUN_CHAR_BACKWARD); + this->dispatch(cmd); + break; + } + default: + pullArg(); + break; + } + } else popBackward(); return true; } @@ -1700,8 +1721,11 @@ void Cursor::handleNest(MathAtom const & a) { idx_type const idx = a.nucleus()->asNestInset()->firstIdx(); //lyxerr << "Cursor::handleNest: " << idx << endl; + InsetMath const * im = selectionBegin().inset().asInsetMath(); + Parse::flags const f = im && im->currentMode() != InsetMath::MATH_MODE + ? Parse::TEXTMODE : Parse::NORMAL; MathAtom t = a; - asArray(cap::grabAndEraseSelection(*this), t.nucleus()->cell(idx)); + asArray(cap::grabAndEraseSelection(*this), t.nucleus()->cell(idx), f); insert(t); editInsertedInset(); } @@ -1788,6 +1812,7 @@ bool Cursor::macroModeClose(bool cancel) bool keep_mathmode = user_macro || (it != words.end() && (it->second.inset == "font" || it->second.inset == "oldfont" + || it->second.inset == "textsize" || it->second.inset == "mbox")); bool ert_macro = !user_macro && it == words.end() && atomAsMacro; @@ -1857,8 +1882,6 @@ void Cursor::pullArg() plainErase(); cell().insert(pos(), ar); resetAnchor(); - } else { - //formula()->mutateToText(); } } @@ -1878,7 +1901,7 @@ void Cursor::normalize() << " in atom: '"; odocstringstream os; otexrowstream ots(os); - WriteStream wi(ots, false, true, WriteStream::wsDefault); + TeXMathStream wi(ots, false, true, TeXMathStream::wsDefault); inset().asInsetMath()->write(wi); lyxerr << to_utf8(os.str()) << endl; pos() = lastpos(); @@ -1982,6 +2005,8 @@ bool Cursor::upDownInMath(bool up) // try to find best position within this inset if (!selection()) setCursor(bruteFind(*this, xo, yo)); + // FIXME : this is actually only needed for InsetMathMacro (bug #12952). + screenUpdateFlags(Update::SinglePar); return true; } @@ -2025,20 +2050,39 @@ bool Cursor::mathForward(bool word) posForward(); while (pos() < lastpos() && mc == nextMath().mathClass()); } else if (openable(nextAtom())) { + InsetMathScript const * n = nextMath().asScriptInset(); + bool to_brace_deco = n && !n->nuc().empty() + && n->nuc().back()->lyxCode() == MATH_DECORATION_CODE + && n->nuc().back()->mathClass() == MC_OP; // single step: try to enter the next inset pushBackward(nextMath()); inset().idxFirst(*this); + // Make sure the cursor moves directly to an + // \overbrace or \underbrace inset (bug 2264) + if (to_brace_deco) { + pushBackward(nextMath()); + inset().idxFirst(*this); + } } else posForward(); return true; } if (inset().idxForward(*this)) return true; + InsetMath const * m = inset().asInsetMath(); + bool from_brace_deco = m + && m->lyxCode() == MATH_DECORATION_CODE + && m->mathClass() == MC_OP; // try to pop forwards --- but don't pop out of math! leave that to // the FINISH lfuns int s = depth() - 2; - if (s >= 0 && operator[](s).inset().asInsetMath()) - return popForward(); + if (s >= 0 && operator[](s).inset().asInsetMath() && popForward()) { + // Make sure the cursor moves directly to an + // \overbrace or \underbrace inset (bug 2264) + bool to_script = inset().asInsetMath() + && inset().asInsetMath()->asScriptInset(); + return from_brace_deco && to_script ? mathForward(word) : true; + } return false; } @@ -2060,21 +2104,41 @@ bool Cursor::mathBackward(bool word) while (pos() > 0 && mc == prevMath().mathClass()); } } else if (openable(prevAtom())) { + InsetMathScript const * p = prevMath().asScriptInset(); + bool to_brace_deco = p && !p->nuc().empty() + && p->nuc().back()->lyxCode() == MATH_DECORATION_CODE + && p->nuc().back()->mathClass() == MC_OP; // single step: try to enter the preceding inset posBackward(); push(nextMath()); inset().idxLast(*this); + // Make sure the cursor moves directly to an + // \overbrace or \underbrace inset (bug 2264) + if (to_brace_deco) { + posBackward(); + push(nextMath()); + inset().idxLast(*this); + } } else posBackward(); return true; } if (inset().idxBackward(*this)) return true; + InsetMath const * m = inset().asInsetMath(); + bool from_brace_deco = m + && m->lyxCode() == MATH_DECORATION_CODE + && m->mathClass() == MC_OP; // try to pop backwards --- but don't pop out of math! leave that to // the FINISH lfuns int s = depth() - 2; - if (s >= 0 && operator[](s).inset().asInsetMath()) - return popBackward(); + if (s >= 0 && operator[](s).inset().asInsetMath() && popBackward()) { + // Make sure the cursor moves directly to an + // \overbrace or \underbrace inset (bug 2264) + bool to_script = inset().asInsetMath() + && inset().asInsetMath()->asScriptInset(); + return from_brace_deco && to_script ? mathBackward(word) : true; + } return false; } @@ -2400,7 +2464,8 @@ bool notifyCursorLeavesOrEnters(Cursor const & old, Cursor & cur) void Cursor::setLanguageFromInput() { if (!lyxrc.respect_os_kbd_language - || (inTexted() && paragraph().isPassThru())) + || !inTexted() + || paragraph().isPassThru()) return; string const & code = theApp()->inputLanguageCode(); Language const * lang = languages.getFromCode(code, buffer()->getLanguages()); @@ -2458,11 +2523,20 @@ void Cursor::setCurrentFont() real_current_font.setLanguage(lang); real_current_font.fontInfo().setNumber(FONT_OFF); } + + // No language in pass thru situations + if (cs.paragraph().isPassThru()) { + current_font.setLanguage(latex_language); + real_current_font.setLanguage(latex_language); + } } void Cursor::checkBufferStructure() { + if (buffer()->isInternal()) + return; + Buffer const * master = buffer()->masterBuffer(); master->tocBackend().updateItem(*this); if (master != buffer() && !master->hasGuiDelegate())