]> git.lyx.org Git - lyx.git/commitdiff
Implement inset-split (only for text insets for now) (#10260)
authorJuergen Spitzmueller <spitz@lyx.org>
Thu, 24 Dec 2020 09:48:52 +0000 (10:48 +0100)
committerJuergen Spitzmueller <spitz@lyx.org>
Thu, 24 Dec 2020 09:48:52 +0000 (10:48 +0100)
lib/RELEASE-NOTES
lib/ui/stdcontext.inc
src/FuncCode.h
src/LyXAction.cpp
src/Text.cpp
src/Text.h
src/Text3.cpp
src/insets/InsetFlex.cpp
src/insets/InsetTabular.cpp
src/insets/InsetText.cpp

index 6fbaba3f6bfc691f1dd4f01089f6a90c1a885234..f73427cd3cc6e8dbc9f838afa953c7c3e13359f1 100644 (file)
@@ -95,6 +95,9 @@
 * paragraph-select is a new convenience function to select the paragraph
   surrounding the actual cursor position.
 
+* split-inset is a new convenience function that splits an inset into two at the given
+  cursor position. This is only implemented for text insets currently.
+
 * tabular-style-insert: Insert a table in a specified style.
 
 
index d1895143b54fba25efaff0a71145c8e5e3fb98b8..b4ee95455b3542f9ba17ae7ab1102dfdc201efde 100644 (file)
@@ -357,6 +357,8 @@ Menuset
                Item "Paste" "paste"
                Submenu "Paste Recent|e" "edit_pasterecent"
                Separator
+               OptItem "Split Inset|t" "inset-split"
+               Separator
                Item "Jump Back to Saved Bookmark|B" "bookmark-goto 0"
                OptItem "Forward Search|F" "forward-search"
                Separator
index 6b970fb579647febfc55772ee71861201465b1bc..9857143c2599971587e1ddba0e4f1be056599dcd 100644 (file)
@@ -493,6 +493,7 @@ enum FuncCode
        LFUN_CITATION_OPEN,             // sanda, 20200815
        LFUN_TOOLBAR_SET,               // spitz 20201217
        // 385
+       LFUN_INSET_SPLIT,               // jspitzm 20201222
        LFUN_LASTACTION                 // end of the table
 };
 
index 462e397d3a7c8d6fd0c4a5c81684a1cfe228162c..1f0b9524a1e9ab77b0003eff86edb147c4e29fe5 100644 (file)
@@ -2225,6 +2225,20 @@ void LyXAction::init()
  */
                { LFUN_INSET_SETTINGS, "inset-settings", ReadOnly | AtPoint, Edit },
 
+/*!
+ * \var lyx::FuncCode lyx::LFUN_INSET_SPLIT
+ * \li Action: Splits the current inset into two at current position.
+ * \li Syntax: inset-split [<INSET>]
+ * \li Params: <INSET>: this can be used to make sure the right kind of inset
+                       is dissolved. For example "split" entry in the charstyles
+                       sub-menu should only dissolve the charstyle inset, even if the
+                       cursor is inside several nested insets of different type.\n
+                       For values see #lyx::InsetLayout::lyxtype_ .
+ * \li Origin: spitz, 22 Dec 2020
+ * \endvar
+ */
+               { LFUN_INSET_SPLIT, "inset-split", AtPoint, Edit },
+
 /*!
  * \var lyx::FuncCode lyx::LFUN_INSET_TOGGLE
  * \li Action: Toggles the collapsible inset at cursor position,
index d227bd5cd5af108f1072a0d0ec168aa058219edf..1f8288a71dbe985a8c05a263d2e74098835fe2b1 100644 (file)
@@ -33,6 +33,7 @@
 #include "ErrorList.h"
 #include "factory.h"
 #include "Font.h"
+#include "FuncRequest.h"
 #include "Language.h"
 #include "Layout.h"
 #include "Lexer.h"
@@ -1898,6 +1899,80 @@ bool Text::dissolveInset(Cursor & cur)
 }
 
 
+bool Text::splitInset(Cursor & cur)
+{
+       LASSERT(this == cur.text(), return false);
+
+       if (isMainText() || cur.inset().nargs() != 1)
+               return false;
+
+       cur.recordUndo();
+       if (cur.selection()) {
+               // start from selection begin
+               setCursor(cur, cur.selBegin().pit(), cur.selBegin().pos());
+               cur.clearSelection();
+       }
+       // save split position inside inset
+       // (we need to copy the whole inset first)
+       pos_type spos = cur.pos();
+       pit_type spit = cur.pit();
+       // some things only need to be done if the inset has content
+       bool const inset_non_empty = cur.lastpit() != 0 || cur.lastpos() != 0;
+
+       // move right before the inset
+       cur.popBackward();
+       cur.resetAnchor();
+       // remember position outside inset
+       pos_type ipos = cur.pos();
+       pit_type ipit = cur.pit();
+       // select inset ...
+       ++cur.pos();
+       cur.setSelection();
+       // ... and copy
+       cap::copySelectionToTemp(cur);
+       cur.clearSelection();
+       cur.resetAnchor();
+       // paste copied inset
+       cap::pasteFromTemp(cur, cur.buffer()->errorList("Paste"));
+       cur.forceBufferUpdate();
+
+       // if the inset has text, cut after split position
+       // and paste to new inset
+       if (inset_non_empty) {
+               // go back to first inset
+               cur.text()->setCursor(cur, ipit, ipos);
+               cur.forwardPos();
+               setCursor(cur, spit, spos);
+               cur.resetAnchor();
+               setCursor(cur, cur.lastpit(), getPar(cur.lastpit()).size());
+               cur.setSelection();
+               cap::cutSelectionToTemp(cur);
+               cur.setMark(false);
+               cur.selHandle(false);
+               cur.resetAnchor();
+               Cursor dummy = cur;
+               dummy.pos() = dummy.pit() = 0;
+               if (cur.bv().checkDepm(dummy, cur))
+                       cur.forceBufferUpdate();
+               // Move out of and jump over inset
+               cur.popBackward();
+               ++cur.pos();
+
+               // enter new inset
+               cur.forwardPos();
+               cur.setCursor(cur);
+               cur.resetAnchor();
+               cur.text()->selectAll(cur);
+               cutSelection(cur, false);
+               cap::pasteFromTemp(cur, cur.buffer()->errorList("Paste"));
+               cur.text()->setCursor(cur, 0, 0);
+       }
+
+       cur.finishUndo();
+       return true;
+}
+
+
 void Text::getWord(CursorSlice & from, CursorSlice & to,
        word_location const loc) const
 {
index 4defd94fa610e513ea29948da6f4fa7cf1e03e46..14108286047dcbae233a8f87b009887d50837d46 100644 (file)
@@ -245,6 +245,8 @@ public:
        // Dissolve the inset under cursor
        /// FIXME: replace Cursor with DocIterator.
        bool dissolveInset(Cursor & cur);
+       /// FIXME: replace Cursor with DocIterator.
+       bool splitInset(Cursor & cur);
        ///
        bool selectWordWhenUnderCursor(Cursor & cur, word_location);
        /// Change the case of the word at cursor position.
index 07d7e80d0aff8318208138d6daec9313905633ed..61b64efc874cbcafce2bf30b187b65f5295b62ef 100644 (file)
@@ -1370,6 +1370,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
+       case LFUN_INSET_SPLIT: {
+               if (splitInset(cur)) {
+                       needsUpdate = true;
+                       cur.forceBufferUpdate();
+               }
+               break;
+       }
+
        case LFUN_GRAPHICS_SET_GROUP: {
                InsetGraphics * ins = graphics::getCurrentGraphicsInset(cur);
                if (!ins)
index 4da349fd13463f438b2e71701e11a07e18aeba7c..e6076102f687ce9c428dc9c8574e68442653e307 100644 (file)
@@ -94,6 +94,7 @@ bool InsetFlex::getStatus(Cursor & cur, FuncRequest const & cmd,
                FuncStatus & flag) const
 {
        switch (cmd.action()) {
+       case LFUN_INSET_SPLIT:
        case LFUN_INSET_DISSOLVE:
                if (!cmd.argument().empty()) {
                        InsetLayout const & il = getLayout();
@@ -102,7 +103,7 @@ bool InsetFlex::getStatus(Cursor & cur, FuncRequest const & cmd,
                        if (il.lyxtype() == type
                            || (il.name() == DocumentClass::plainInsetLayout().name()
                                    && type == InsetLyXType::CHARSTYLE)) {
-                               FuncRequest temp_cmd(LFUN_INSET_DISSOLVE);
+                               FuncRequest temp_cmd(cmd.action());
                                return InsetCollapsible::getStatus(cur, temp_cmd, flag);
                        } else
                                return false;
@@ -117,6 +118,7 @@ bool InsetFlex::getStatus(Cursor & cur, FuncRequest const & cmd,
 void InsetFlex::doDispatch(Cursor & cur, FuncRequest & cmd)
 {
        switch (cmd.action()) {
+       case LFUN_INSET_SPLIT:
        case LFUN_INSET_DISSOLVE:
                if (!cmd.argument().empty()) {
                        InsetLayout const & il = getLayout();
@@ -126,7 +128,7 @@ void InsetFlex::doDispatch(Cursor & cur, FuncRequest & cmd)
                        if (il.lyxtype() == type
                            || (il.name() == DocumentClass::plainInsetLayout().name()
                                    && type == InsetLyXType::CHARSTYLE)) {
-                               FuncRequest temp_cmd(LFUN_INSET_DISSOLVE);
+                               FuncRequest temp_cmd(cmd.action());
                                InsetCollapsible::doDispatch(cur, temp_cmd);
                        } else
                                cur.undispatched();
index 181e68cb7c56bc80b6df31e33cd84f1281577b59..b3e8bd8d49fc0d3ded5b092274490cd5081c0111 100644 (file)
@@ -4226,6 +4226,7 @@ bool InsetTableCell::getStatus(Cursor & cur, FuncRequest const & cmd,
 {
        bool enabled = true;
        switch (cmd.action()) {
+       case LFUN_INSET_SPLIT:
        case LFUN_INSET_DISSOLVE:
                enabled = false;
                break;
index 5c4d32c20cd2899bc43326583a7be769481180a4..8e0500d9b2230d04806ce03cec8a3c82cd19cd30 100644 (file)
@@ -320,6 +320,7 @@ void InsetText::doDispatch(Cursor & cur, FuncRequest & cmd)
                fixParagraphsFont();
                break;
 
+       case LFUN_INSET_SPLIT:
        case LFUN_INSET_DISSOLVE: {
                bool const main_inset = text_.isMainText();
                bool const target_inset = cmd.argument().empty()
@@ -351,6 +352,7 @@ bool InsetText::getStatus(Cursor & cur, FuncRequest const & cmd,
        FuncStatus & status) const
 {
        switch (cmd.action()) {
+       case LFUN_INSET_SPLIT:
        case LFUN_INSET_DISSOLVE: {
                bool const main_inset = text_.isMainText();
                bool const target_inset = cmd.argument().empty()