]> git.lyx.org Git - lyx.git/blobdiff - src/Cursor.cpp
Clean includes using the output of iwyu tool
[lyx.git] / src / Cursor.cpp
index eb8c50110f80a318e6ac4bc74cdd80254439f128..7197b91cf26951477c8515f69915c3bc686dc0d5 100644 (file)
 
 #include <config.h>
 
+#include "Cursor.h"
+
 #include "Buffer.h"
 #include "BufferView.h"
 #include "CoordCache.h"
-#include "Cursor.h"
 #include "CutAndPaste.h"
-#include "DispatchResult.h"
 #include "FuncCode.h"
 #include "FuncRequest.h"
+#include "Language.h"
 #include "Layout.h"
 #include "LyXAction.h"
 #include "LyXRC.h"
 #include "Paragraph.h"
-#include "ParIterator.h"
 #include "Row.h"
 #include "texstream.h"
 #include "Text.h"
 
 #include "support/debug.h"
 #include "support/docstream.h"
-#include "support/ExceptionMessage.h"
 #include "support/gettext.h"
 #include "support/lassert.h"
 
 #include "insets/InsetTabular.h"
-#include "insets/InsetText.h"
 
 #include "mathed/InsetMath.h"
 #include "mathed/InsetMathBrace.h"
@@ -51,6 +49,8 @@
 #include "mathed/MathFactory.h"
 #include "mathed/InsetMathMacro.h"
 
+#include "frontends/Application.h"
+
 #include <sstream>
 #include <limits>
 #include <map>
@@ -121,19 +121,19 @@ DocIterator bruteFind(Cursor const & c, int x, int y)
 
 CursorData::CursorData()
        : DocIterator(), anchor_(), selection_(false), mark_(false),
-         word_selection_(false), autocorrect_(false), current_font(inherit_font)
+         word_selection_(false), current_font(inherit_font)
 {}
 
 
 CursorData::CursorData(Buffer * buffer)
        : DocIterator(buffer), anchor_(), selection_(false), mark_(false),
-         word_selection_(false), autocorrect_(false), current_font(inherit_font)
+         word_selection_(false), current_font(inherit_font)
 {}
 
 
 CursorData::CursorData(DocIterator const & dit)
        : DocIterator(dit), anchor_(), selection_(false), mark_(false),
-         word_selection_(false), autocorrect_(false), current_font(inherit_font)
+         word_selection_(false), current_font(inherit_font)
 {}
 
 
@@ -330,6 +330,8 @@ namespace {
 
 docstring parbreak(CursorData const * cur)
 {
+       if (cur->inset().getLayout().parbreakIgnored())
+               return docstring();
        odocstringstream os;
        os << '\n';
        // only add blank line if we're not in a ParbreakIsNewline situation
@@ -342,7 +344,7 @@ docstring parbreak(CursorData const * cur)
 }
 
 
-docstring CursorData::selectionAsString(bool with_label) const
+docstring CursorData::selectionAsString(bool const with_label, bool const skipdelete) const
 {
        if (!selection())
                return docstring();
@@ -350,8 +352,12 @@ docstring CursorData::selectionAsString(bool with_label) const
        if (inMathed())
                return cap::grabSelection(*this);
 
-       int const label = with_label
+       int label = with_label
                ? AS_STR_LABEL | AS_STR_INSETS : AS_STR_INSETS;
+       if (skipdelete)
+               label = with_label
+                               ? AS_STR_LABEL | AS_STR_INSETS | AS_STR_SKIPDELETE
+                               : AS_STR_INSETS | AS_STR_SKIPDELETE;
 
        idx_type const startidx = selBegin().idx();
        idx_type const endidx = selEnd().idx();
@@ -496,6 +502,56 @@ void CursorData::clearSelection()
 }
 
 
+int CursorData::countInsetsInSelection(InsetCode const & inset_code)
+{
+       if (!selection_)
+               return 0;
+
+       DocIterator from, to;
+       from = selectionBegin();
+       to = selectionEnd();
+
+       int count = 0;
+
+       if (!from.nextInset())      //move to closest inset
+               from.forwardInset();
+
+       while (!from.empty() && from < to) {
+               Inset * inset = from.nextInset();
+               if (!inset)
+                       break;
+               if (inset->lyxCode() == inset_code)
+                       count ++;
+               from.forwardInset();
+       }
+       return count;
+}
+
+
+bool CursorData::insetInSelection(InsetCode const & inset_code)
+{
+       if (!selection_)
+               return false;
+
+       DocIterator from, to;
+       from = selectionBegin();
+       to = selectionEnd();
+
+       if (!from.nextInset())      //move to closest inset
+               from.forwardInset();
+
+       while (!from.empty() && from < to) {
+               Inset * inset = from.nextInset();
+               if (!inset)
+                       break;
+               if (inset->lyxCode() == inset_code)
+                       return true;
+               from.forwardInset();
+       }
+       return false;
+}
+
+
 bool CursorData::fixIfBroken()
 {
        bool const broken_cursor = DocIterator::fixIfBroken();
@@ -521,38 +577,18 @@ void CursorData::sanitize()
 }
 
 
-bool CursorData::isInside(Inset const * p) const
-{
-       for (size_t i = 0; i != depth(); ++i)
-               if (&operator[](i).inset() == p)
-                       return true;
-       return false;
-}
-
-
-void CursorData::leaveInset(Inset const & inset)
+bool CursorData::undoAction()
 {
-       for (size_t i = 0; i != depth(); ++i) {
-               if (&operator[](i).inset() == &inset) {
-                       resize(i);
-                       return;
-               }
-       }
-}
-
-
-bool CursorData::textUndo()
-{
-       if (!buffer()->undo().textUndo(*this))
+       if (!buffer()->undo().undoAction(*this))
                return false;
        sanitize();
        return true;
 }
 
 
-bool CursorData::textRedo()
+bool CursorData::redoAction()
 {
-       if (!buffer()->undo().textRedo(*this))
+       if (!buffer()->undo().redoAction(*this))
                return false;
        sanitize();
        return true;
@@ -577,6 +613,12 @@ void CursorData::endUndoGroup() const
 }
 
 
+void CursorData::splitUndoGroup() const
+{
+       buffer()->undo().splitUndoGroup(*this);
+}
+
+
 void CursorData::recordUndo(pit_type from, pit_type to) const
 {
        buffer()->undo().recordUndo(*this, from, to);
@@ -871,6 +913,31 @@ void Cursor::pushBackward(Inset & p)
 }
 
 
+void Cursor::editInsertedInset()
+{
+       LASSERT(!empty(), return);
+       if (pos() == 0)
+               return;
+
+       InsetMath &p = prevMath();
+       if (!p.isActive())
+               return;
+
+       posBackward();
+       push(p);
+       p.idxFirst(*this);
+       // this could be a while() loop, but only one cell is not empty in
+       // cases we are interested in. The cell is not empty because we
+       // have inserted the selection in there.
+       if (!cell().empty()) {
+               // if it is not empty, move to the next one.
+               if (!inset().idxNext(*this))
+                       // If there is no next one, exit the inset.
+                       popForward();
+       }
+}
+
+
 bool Cursor::popBackward()
 {
        LASSERT(!empty(), return false);
@@ -1365,10 +1432,7 @@ bool Cursor::atFirstOrLastRow(bool up)
 ///////////////////////////////////////////////////////////////////
 
 #include "mathed/InsetMathChar.h"
-#include "mathed/InsetMathGrid.h"
-#include "mathed/InsetMathScript.h"
 #include "mathed/InsetMathUnknown.h"
-#include "mathed/MathFactory.h"
 #include "mathed/MathStream.h"
 #include "mathed/MathSupport.h"
 
@@ -1491,14 +1555,11 @@ void Cursor::niceInsert(MathAtom const & t)
        plainInsert(t);
        // If possible, enter the new inset and move the contents of the selection
        if (t->isActive()) {
-               posBackward();
-               // be careful here: don't use 'pushBackward(t)' as this we need to
-               // push the clone, not the original
-               pushBackward(*nextInset());
-               // We may not use niceInsert here (recursion)
+               idx_type const idx = prevMath().asNestInset()->firstIdx();
                MathData ar(buffer());
                asArray(safe, ar);
-               insert(ar);
+               prevMath().cell(idx).insert(0, ar);
+               editInsertedInset();
        } else if (t->asMacro() && !safe.empty()) {
                MathData ar(buffer());
                asArray(safe, ar);
@@ -1635,14 +1696,14 @@ bool Cursor::down()
 }
 
 
-void Cursor::handleNest(MathAtom const & a, int c)
+void Cursor::handleNest(MathAtom const & a)
 {
-       //lyxerr << "Cursor::handleNest: " << c << endl;
+       idx_type const idx = a.nucleus()->asNestInset()->firstIdx();
+       //lyxerr << "Cursor::handleNest: " << idx << endl;
        MathAtom t = a;
-       asArray(cap::grabAndEraseSelection(*this), t.nucleus()->cell(c));
+       asArray(cap::grabAndEraseSelection(*this), t.nucleus()->cell(idx));
        insert(t);
-       posBackward();
-       pushBackward(*nextInset());
+       editInsertedInset();
 }
 
 
@@ -1684,14 +1745,15 @@ bool Cursor::macroModeClose(bool cancel)
        --pos();
        cell().erase(pos());
 
-       // do nothing if the macro name is empty
-       if (s == "\\" || cancel)
-               return false;
-
        // trigger updates of macros, at least, if no full
        // updates take place anyway
        screenUpdateFlags(Update::Force);
 
+       // do nothing if the macro name is empty
+       if (s == "\\" || cancel) {
+               return false;
+       }
+
        docstring const name = s.substr(1);
        InsetMathNest * const in = inset().asInsetMath()->asNestInset();
        if (in && in->interpretString(*this, s))
@@ -1703,12 +1765,13 @@ bool Cursor::macroModeClose(bool cancel)
        // try to put argument into macro, if we just inserted a macro
        bool macroArg = false;
        InsetMathMacro * atomAsMacro = atom.nucleus()->asMacro();
+       InsetMathNest * atomAsNest = atom.nucleus()->asNestInset();
        if (atomAsMacro) {
                // macros here are still unfolded (in init mode in fact). So
                // we have to resolve the macro here manually and check its arity
                // to put the selection behind it if arity > 0.
                MacroData const * data = buffer()->getMacro(atomAsMacro->name());
-               if (!selection.empty() && data && data->numargs() - data->optionals() > 0) {
+               if (!selection.empty() && data && data->numargs()) {
                        macroArg = true;
                        atomAsMacro->setDisplayMode(InsetMathMacro::DISPLAY_INTERACTIVE_INIT, 1);
                } else
@@ -1717,8 +1780,8 @@ bool Cursor::macroModeClose(bool cancel)
        }
 
        // insert remembered selection into first argument of a non-macro
-       else if (atom.nucleus()->nargs() > 0)
-               atom.nucleus()->cell(0).append(selection);
+       else if (atomAsNest && atomAsNest->nargs() > 0)
+               atomAsNest->cell(atomAsNest->firstIdx()).append(selection);
 
        MathWordList const & words = mathedWordList();
        MathWordList::const_iterator it = words.find(name);
@@ -1770,13 +1833,13 @@ bool Cursor::inMacroMode() const
 
 InsetMathUnknown * Cursor::activeMacro()
 {
-       return inMacroMode() ? prevAtom().nucleus()->asUnknownInset() : 0;
+       return inMacroMode() ? prevAtom().nucleus()->asUnknownInset() : nullptr;
 }
 
 
 InsetMathUnknown const * Cursor::activeMacro() const
 {
-       return inMacroMode() ? prevAtom().nucleus()->asUnknownInset() : 0;
+       return inMacroMode() ? prevAtom().nucleus()->asUnknownInset() : nullptr;
 }
 
 
@@ -2231,6 +2294,12 @@ void Cursor::screenUpdateFlags(Update::flags f) const
 }
 
 
+void Cursor::noScreenUpdate() const
+{
+       disp_.screenUpdate(Update::None);
+}
+
+
 void Cursor::forceBufferUpdate() const
 {
        disp_.forceBufferUpdate();
@@ -2249,12 +2318,6 @@ bool Cursor::needBufferUpdate() const
 }
 
 
-void Cursor::noScreenUpdate() const
-{
-       disp_.screenUpdate(Update::None);
-}
-
-
 Font Cursor::getFont() const
 {
        // The logic here should more or less match to the
@@ -2334,6 +2397,20 @@ bool notifyCursorLeavesOrEnters(Cursor const & old, Cursor & cur)
 }
 
 
+void Cursor::setLanguageFromInput()
+{
+       if (!lyxrc.respect_os_kbd_language)
+               return;
+       string const & code = theApp()->inputLanguageCode();
+       Language const * lang = languages.getFromCode(code, buffer()->getLanguages());
+       if (lang) {
+               current_font.setLanguage(lang);
+               real_current_font.setLanguage(lang);
+       } else
+               LYXERR0("setLanguageFromCode: unknown language code " << code);
+}
+
+
 void Cursor::setCurrentFont()
 {
        CursorSlice const & cs = innerTextSlice();
@@ -2367,6 +2444,9 @@ void Cursor::setCurrentFont()
        current_font = par.getFontSettings(bufparams, cpos);
        real_current_font = tm.displayFont(cpit, cpos);
 
+       // set language to input language
+       setLanguageFromInput();
+
        // special case for paragraph end
        if (cs.pos() == lastpos()
            && tm.isRTLBoundary(cpit, cs.pos())
@@ -2388,12 +2468,6 @@ void Cursor::checkBufferStructure()
                // In case the master has no gui associated with it,
                // the TocItem is not updated (part of bug 5699).
                buffer()->tocBackend().updateItem(*this);
-
-       // If the last tracked change of the paragraph has just been
-       // deleted, then we need to recompute the buffer flag
-       // tracked_changes_present_.
-       if (inTexted() && paragraph().isChangeUpdateRequired())
-               disp_.forceChangesUpdate();
 }