]> git.lyx.org Git - lyx.git/blobdiff - src/Cursor.cpp
Update Win installer for new dictionary links. Untested.
[lyx.git] / src / Cursor.cpp
index 7a723c6fdfa6de1774aab1e726c4b4a2b7048e62..0e1c3ded5558c9dd62283ad29d738fc1c15e552d 100644 (file)
@@ -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())