commit a09ceda2c42b7ec1e03afb4166bdfcf4c52b719b
Author: Juergen Spitzmueller <[email protected]>
Date:   Sat Jan 13 14:51:01 2018 +0100

    Once more rework outline wrt environments.
    
    * Fixes UNDO issues
    * Takes care of some special cases
    
    Signed-off-by: Juergen Spitzmueller <[email protected]>
---
 src/Text3.cpp |  153 ++++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 92 insertions(+), 61 deletions(-)

diff --git a/src/Text3.cpp b/src/Text3.cpp
index f4190d2..b339e07 100644
--- a/src/Text3.cpp
+++ b/src/Text3.cpp
@@ -366,7 +366,23 @@ enum OutlineOp {
 };
 
 
-static void outline(OutlineOp mode, Cursor & cur)
+static void insertSeparator(Cursor & cur, depth_type const depth)
+{
+       Buffer & buf = *cur.buffer();
+       lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_BREAK));
+       DocumentClass const & tc = buf.params().documentClass();
+       lyx::dispatch(FuncRequest(LFUN_LAYOUT, from_ascii("\"") + 
tc.plainLayout().name()
+                                 + from_ascii("\" ignoreautonests")));
+       // FIXME: Bibitem mess!
+       if (cur.prevInset() && cur.prevInset()->lyxCode() == BIBITEM_CODE)
+               lyx::dispatch(FuncRequest(LFUN_CHAR_DELETE_BACKWARD));
+       lyx::dispatch(FuncRequest(LFUN_SEPARATOR_INSERT, "plain"));
+       while (cur.paragraph().params().depth() > depth)
+               lyx::dispatch(FuncRequest(LFUN_DEPTH_DECREMENT));
+}
+
+
+static void outline(OutlineOp mode, Cursor & cur, Text * text)
 {
        Buffer & buf = *cur.buffer();
        pit_type & pit = cur.pit();
@@ -377,6 +393,7 @@ static void outline(OutlineOp mode, Cursor & cur)
        // The final paragraph of area to be copied:
        ParagraphList::iterator finish = start;
        ParagraphList::iterator const end = pars.end();
+       depth_type const current_depth = cur.paragraph().params().depth();
 
        int const thistoclevel = buf.text().getTocLevel(distance(bgn, start));
        int toclevel;
@@ -411,27 +428,47 @@ static void outline(OutlineOp mode, Cursor & cur)
                        // Not found; do nothing
                        if (toclevel == Layout::NOT_IN_TOC || toclevel > 
thistoclevel)
                                return;
+                       pit_type newpit = distance(bgn, dest);
+                       pit_type const len = distance(start, finish);
+                       pit_type const deletepit = pit + len;
+                       buf.undo().recordUndo(cur, newpit, deletepit - 1);
                        // If we move an environment upwards, make sure it is
-                       // separated from its new neighbour below.
+                       // separated from its new neighbour below:
+                       // If an environment of the same layout follows, and 
the moved
+                       // paragraph sequence does not end with a separator, 
insert one.
                        ParagraphList::iterator lastmoved = finish;
                        --lastmoved;
                        if (start->layout().isEnvironment()
-                               && dest->layout() == start->layout()
-                               && 
!lastmoved->isEnvSeparator(lastmoved->beginOfBody())) {
-                               cur.pit() = distance(bgn, finish);
-                               cur.pos() = 0;
-                               
lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_BREAK));
-                               DocumentClass const & tc = 
buf.params().documentClass();
-                               lyx::dispatch(FuncRequest(LFUN_LAYOUT, 
from_ascii("\"") + tc.plainLayout().name()
-                                                         + from_ascii("\" 
ignoreautonests")));
-                               
lyx::dispatch(FuncRequest(LFUN_SEPARATOR_INSERT, "plain"));
-                               ++finish;
+                           && dest->layout() == start->layout()
+                           && 
!lastmoved->isEnvSeparator(lastmoved->beginOfBody())) {
+                               cur.pit() = distance(bgn, lastmoved);
+                               cur.pos() = cur.lastpos();
+                               insertSeparator(cur, current_depth);
                                cur.pit() = pit;
                        }
-                       pit_type const newpit = distance(bgn, dest);
-                       pit_type const len = distance(start, finish);
-                       pit_type const deletepit = pit + len;
-                       buf.undo().recordUndo(cur, newpit, deletepit - 1);
+                       // Likewise, if we moved an environment upwards, make 
sure it
+                       // is separated from its new neighbour above.
+                       // The paragraph before the target of movement
+                       if (dest != bgn) {
+                               ParagraphList::iterator before = dest;
+                               --before;
+                               // Get the parent paragraph (outer in nested 
context)
+                               pit_type const parent =
+                                       before->params().depth() > current_depth
+                                               ? text->depthHook(distance(bgn, 
before), current_depth)
+                                               : distance(bgn, before);
+                               // If a environment with same layout preceeds 
the moved one in the new
+                               // position, and there is no separator yet, 
insert one.
+                               if (start->layout().isEnvironment()
+                                   && pars[parent].layout() == start->layout()
+                                   && 
!before->isEnvSeparator(before->beginOfBody())) {
+                                       cur.pit() = distance(bgn, before);
+                                       cur.pos() = cur.lastpos();
+                                       insertSeparator(cur, current_depth);
+                                       cur.pit() = pit;
+                               }
+                       }
+                       newpit = distance(bgn, dest);
                        pars.splice(dest, start, finish);
                        cur.pit() = newpit;
                        break;
@@ -449,26 +486,45 @@ static void outline(OutlineOp mode, Cursor & cur)
                                      && toclevel <= thistoclevel)
                                        break;
                        }
-                       // One such was found:
+                       // One such was found, so go on...
                        // If we move an environment downwards, make sure it is
-                       // separated from its new neighbour below.
+                       // separated from its new neighbour above.
+                       pit_type newpit = distance(bgn, dest);
+                       buf.undo().recordUndo(cur, pit, newpit - 1);
+                       // The paragraph before the target of movement
+                       ParagraphList::iterator before = dest;
+                       --before;
+                       // Get the parent paragraph (outer in nested context)
+                       pit_type const parent =
+                               before->params().depth() > current_depth
+                                       ? text->depthHook(distance(bgn, 
before), current_depth)
+                                       : distance(bgn, before);
+                       // If a environment with same layout preceeds the moved 
one in the new
+                       // position, and there is no separator yet, insert one.
+                       if (start->layout().isEnvironment()
+                           && pars[parent].layout() == start->layout()
+                           && !before->isEnvSeparator(before->beginOfBody())) {
+                               cur.pit() = distance(bgn, before);
+                               cur.pos() = cur.lastpos();
+                               insertSeparator(cur, current_depth);
+                               cur.pit() = pit;
+                       }
+                       // Likewise, make sure moved environments are separated
+                       // from their new neighbour below:
+                       // If an environment of the same layout follows, and 
the moved
+                       // paragraph sequence does not end with a separator, 
insert one.
                        ParagraphList::iterator lastmoved = finish;
                        --lastmoved;
-                       if (start->layout().isEnvironment()
-                               && dest->layout() == start->layout()
-                               && 
!lastmoved->isEnvSeparator(lastmoved->beginOfBody())) {
-                               cur.pit() = distance(bgn, finish);
-                               cur.pos() = 0;
-                               
lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_BREAK));
-                               DocumentClass const & tc = 
buf.params().documentClass();
-                               lyx::dispatch(FuncRequest(LFUN_LAYOUT, 
from_ascii("\"") + tc.plainLayout().name()
-                                                         + from_ascii("\" 
ignoreautonests")));
-                               
lyx::dispatch(FuncRequest(LFUN_SEPARATOR_INSERT, "plain"));
-                               ++finish;
+                       if (dest != end
+                           && start->layout().isEnvironment()
+                           && dest->layout() == start->layout()
+                           && 
!lastmoved->isEnvSeparator(lastmoved->beginOfBody())) {
+                               cur.pit() = distance(bgn, lastmoved);
+                               cur.pos() = cur.lastpos();
+                               insertSeparator(cur, current_depth);
                                cur.pit() = pit;
                        }
-                       pit_type newpit = distance(bgn, dest);
-                       buf.undo().recordUndo(cur, pit, newpit - 1);
+                       newpit = distance(bgn, dest);
                        pit_type const len = distance(start, finish);
                        pars.splice(dest, start, finish);
                        cur.pit() = newpit - len;
@@ -2583,54 +2639,29 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                }
                break;
 
-       case LFUN_OUTLINE_UP: {
-               outline(OutlineUp, cur);
+       case LFUN_OUTLINE_UP:
+               outline(OutlineUp, cur, this);
                setCursor(cur, cur.pit(), 0);
-               // If we moved an environment upwards, make sure it is
-               // separated from its new neighbour above.
-               pit_type pit = cur.pit();
-               if (pit > 0 && pars_[pit].layout().isEnvironment()
-                       && pars_[pit - 1].layout() == pars_[pit].layout()) {
-                       lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_BREAK));
-                       DocumentClass const & tc = 
bv->buffer().params().documentClass();
-                       lyx::dispatch(FuncRequest(LFUN_LAYOUT, from_ascii("\"") 
+ tc.plainLayout().name()
-                                                 + from_ascii("\" 
ignoreautonests")));
-                       lyx::dispatch(FuncRequest(LFUN_SEPARATOR_INSERT, 
"plain"));
-                       setCursor(cur, pit + 1, 0);
-               }
                cur.forceBufferUpdate();
                needsUpdate = true;
                break;
-       }
 
        case LFUN_OUTLINE_DOWN: {
-               outline(OutlineDown, cur);
+               outline(OutlineDown, cur, this);
                setCursor(cur, cur.pit(), 0);
-               // If we moved an environment downwards, make sure it is
-               // separated from its new neighbour above.
-               pit_type pit = cur.pit();
-               if (pit > 0 && pars_[pit].layout().isEnvironment()
-                       && pars_[pit - 1].layout() == pars_[pit].layout()) {
-                       lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_BREAK));
-                       DocumentClass const & tc = 
bv->buffer().params().documentClass();
-                       lyx::dispatch(FuncRequest(LFUN_LAYOUT, from_ascii("\"") 
+ tc.plainLayout().name()
-                                                 + from_ascii("\" 
ignoreautonests")));
-                       lyx::dispatch(FuncRequest(LFUN_SEPARATOR_INSERT, 
"plain"));
-                       setCursor(cur, pit + 1, 0);
-               }
                cur.forceBufferUpdate();
                needsUpdate = true;
                break;
        }
 
        case LFUN_OUTLINE_IN:
-               outline(OutlineIn, cur);
+               outline(OutlineIn, cur, this);
                cur.forceBufferUpdate();
                needsUpdate = true;
                break;
 
        case LFUN_OUTLINE_OUT:
-               outline(OutlineOut, cur);
+               outline(OutlineOut, cur, this);
                cur.forceBufferUpdate();
                needsUpdate = true;
                break;

Reply via email to