]> git.lyx.org Git - lyx.git/blobdiff - src/Text3.cpp
cosmetics
[lyx.git] / src / Text3.cpp
index 887e9bd05068610bcc3f107efed245aa99368925..026d51e839f9b88bb6e0d229b273acc8e63b4d83 100644 (file)
 #include "Paragraph.h"
 #include "paragraph_funcs.h"
 #include "ParagraphParameters.h"
+#include "ParIterator.h"
+#include "TextClass.h"
 #include "TextMetrics.h"
 #include "VSpace.h"
-#include "ParIterator.h"
 
 #include "frontends/Clipboard.h"
 #include "frontends/Selection.h"
@@ -69,6 +70,7 @@
 #include "mathed/MathMacroTemplate.h"
 
 #include <boost/current_function.hpp>
+#include <boost/next_prior.hpp>
 
 #include <clocale>
 #include <sstream>
@@ -99,12 +101,12 @@ static void toggleAndShow(Cursor & cur, Text * text,
        text->toggleFree(cur, font, toggleall);
 
        if (font.language() != ignore_language ||
-                       font.fontInfo().number() != FONT_IGNORE) {
+           font.fontInfo().number() != FONT_IGNORE) {
                TextMetrics const & tm = cur.bv().textMetrics(text);
-               if (cur.boundary() != tm.isRTLBoundary(cur.pit(),
-                                                                                                               cur.pos(), cur.real_current_font))
+               if (cur.boundary() != tm.isRTLBoundary(cur.pit(), cur.pos(),
+                                                      cur.real_current_font))
                        text->setCursor(cur, cur.pit(), cur.pos(),
-                                                                                       false, !cur.boundary());
+                                       false, !cur.boundary());
        }
 }
 
@@ -179,7 +181,7 @@ static void specialChar(Cursor & cur, InsetSpecialChar::Kind kind)
        cur.recordUndo();
        cap::replaceSelection(cur);
        cur.insert(new InsetSpecialChar(kind));
-       cur.posRight();
+       cur.posForward();
 }
 
 
@@ -247,6 +249,129 @@ string const freefont2string()
 }
 
 
+/// the type of outline operation
+enum OutlineOp {
+       OutlineUp, // Move this header with text down
+       OutlineDown,   // Move this header with text up
+       OutlineIn, // Make this header deeper
+       OutlineOut // Make this header shallower
+};
+
+
+static void outline(OutlineOp mode, Cursor & cur)
+{
+       Buffer & buf = cur.buffer();
+       pit_type & pit = cur.pit();
+       ParagraphList & pars = buf.text().paragraphs();
+       ParagraphList::iterator bgn = pars.begin();
+       // The first paragraph of the area to be copied:
+       ParagraphList::iterator start = boost::next(bgn, pit);
+       // The final paragraph of area to be copied:
+       ParagraphList::iterator finish = start;
+       ParagraphList::iterator end = pars.end();
+
+       TextClass::const_iterator lit =
+               buf.params().getTextClass().begin();
+       TextClass::const_iterator const lend =
+               buf.params().getTextClass().end();
+
+       int const thistoclevel = start->layout()->toclevel;
+       int toclevel;
+       switch (mode) {
+               case OutlineUp: {
+                       // Move out (down) from this section header
+                       if (finish != end)
+                               ++finish;
+                       // Seek the one (on same level) below
+                       for (; finish != end; ++finish) {
+                               toclevel = finish->layout()->toclevel;
+                               if (toclevel != Layout::NOT_IN_TOC
+                                   && toclevel <= thistoclevel) {
+                                       break;
+                               }
+                       }
+                       ParagraphList::iterator dest = start;
+                       // Move out (up) from this header
+                       if (dest == bgn)
+                               break;
+                       // Search previous same-level header above
+                       do {
+                               --dest;
+                               toclevel = dest->layout()->toclevel;
+                       } while(dest != bgn
+                               && (toclevel == Layout::NOT_IN_TOC
+                                   || toclevel > thistoclevel));
+                       // Not found; do nothing
+                       if (toclevel == Layout::NOT_IN_TOC || toclevel > thistoclevel)
+                               break;
+                       pit_type const newpit = std::distance(bgn, dest);
+                       pit_type const len = std::distance(start, finish);
+                       pit_type const deletepit = pit + len;
+                       buf.undo().recordUndo(cur, ATOMIC_UNDO, newpit, deletepit - 1);
+                       pars.insert(dest, start, finish);
+                       start = boost::next(pars.begin(), deletepit);
+                       pit = newpit;
+                       pars.erase(start, finish);
+                       break;
+               }
+               case OutlineDown: {
+                       // Go down out of current header:
+                       if (finish != end)
+                               ++finish;
+                       // Find next same-level header:
+                       for (; finish != end; ++finish) {
+                               toclevel = finish->layout()->toclevel;
+                               if (toclevel != Layout::NOT_IN_TOC && toclevel <= thistoclevel)
+                                       break;
+                       }
+                       ParagraphList::iterator dest = finish;
+                       // Go one down from *this* header:
+                       if (dest != end)
+                               ++dest;
+                       else
+                               break;
+                       // Go further down to find header to insert in front of:
+                       for (; dest != end; ++dest) {
+                               toclevel = dest->layout()->toclevel;
+                               if (toclevel != Layout::NOT_IN_TOC && toclevel <= thistoclevel)
+                                       break;
+                       }
+                       // One such was found:
+                       pit_type newpit = std::distance(bgn, dest);
+                       pit_type const len = std::distance(start, finish);
+                       buf.undo().recordUndo(cur, ATOMIC_UNDO, pit, newpit - 1);
+                       pars.insert(dest, start, finish);
+                       start = boost::next(bgn, pit);
+                       pit = newpit - len;
+                       pars.erase(start, finish);
+                       break;
+               }
+               case OutlineIn:
+                       buf.undo().recordUndo(cur);
+                       for (; lit != lend; ++lit) {
+                               if ((*lit)->toclevel == thistoclevel + 1 &&
+                                   start->layout()->labeltype == (*lit)->labeltype) {
+                                       start->layout((*lit));
+                                       break;
+                               }
+                       }
+                       break;
+               case OutlineOut:
+                       buf.undo().recordUndo(cur);
+                       for (; lit != lend; ++lit) {
+                               if ((*lit)->toclevel == thistoclevel - 1 &&
+                                   start->layout()->labeltype == (*lit)->labeltype) {
+                                       start->layout((*lit));
+                                       break;
+                               }
+                       }
+                       break;
+               default:
+                       break;
+       }
+}
+
+
 void Text::number(Cursor & cur)
 {
        FontInfo font = ignore_font;
@@ -558,7 +683,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                cur.recordUndo();
                        cap::replaceSelection(cur);
                        cur.insert(new InsetNewline);
-                       cur.posRight();
+                       cur.posForward();
                        moveCursor(cur, false);
                }
                break;
@@ -714,7 +839,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        if (cur.selection())
                                cutSelection(cur, true, false);
                        insertInset(cur, inset);
-                       cur.posRight();
+                       cur.posForward();
                }
                break;
        }
@@ -732,7 +857,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        insertChar(cur, ' ');
                else {
                        doInsertInset(cur, this, cmd, false, false);
-                       cur.posRight();
+                       cur.posForward();
                }
                moveCursor(cur, false);
                break;
@@ -936,7 +1061,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                cur.insert(new InsetQuotes(c,
                                    bufparams.quotes_language,
                                    InsetQuotes::DoubleQ));
-                       cur.posRight();
+                       cur.posForward();
                }
                else
                        lyx::dispatch(FuncRequest(LFUN_SELF_INSERT, "\""));
@@ -1156,7 +1281,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        static_cast<InsetInfo *>(inset)->setInfo(to_utf8(ds));
                }
                insertInset(cur, inset);
-               cur.posRight();
+               cur.posForward();
                break;
        }
 #if 0
@@ -1168,7 +1293,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // Open the inset, and move the current selection
                // inside it.
                doInsertInset(cur, this, cmd, true, true);
-               cur.posRight();
+               cur.posForward();
                // These insets are numbered.
                updateLabels(bv->buffer());
                break;
@@ -1185,13 +1310,13 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // Open the inset, and move the current selection
                // inside it.
                doInsertInset(cur, this, cmd, true, true);
-               cur.posRight();
+               cur.posForward();
                break;
 
        case LFUN_TABULAR_INSERT:
                // if there were no arguments, just open the dialog
                if (doInsertInset(cur, this, cmd, false, true))
-                       cur.posRight();
+                       cur.posForward();
                else
                        bv->showDialog("tabularcreate");
 
@@ -1203,7 +1328,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                bool content = cur.selection();  // will some text be moved into the inset?
 
                doInsertInset(cur, this, cmd, true, true);
-               cur.posRight();
+               cur.posForward();
                ParagraphList & pars = cur.text()->paragraphs();
 
                TextClass const & tclass = bv->buffer().params().getTextClass();
@@ -1242,7 +1367,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_INDEX_INSERT:
                doInsertInset(cur, this, cmd, true, true);
-               cur.posRight();
+               cur.posForward();
                break;
 
        case LFUN_NOMENCL_INSERT: {
@@ -1260,7 +1385,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // description entry still needs to be filled in.
                if (cmd.action == LFUN_NOMENCL_INSERT)
                        inset->edit(cur, true);
-               cur.posRight();
+               cur.posForward();
                break;
        }
 
@@ -1274,7 +1399,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_CLEARDOUBLEPAGE_INSERT:
                // do nothing fancy
                doInsertInset(cur, this, cmd, false, false);
-               cur.posRight();
+               cur.posForward();
                break;
 
        case LFUN_DEPTH_DECREMENT:
@@ -1516,7 +1641,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        ParagraphParameters p;
                        setParagraphs(cur, p);
                        insertInset(cur, new InsetFloatList(to_utf8(cmd.argument())));
-                       cur.posRight();
+                       cur.posForward();
                } else {
                        lyxerr << "Non-existent float type: "
                               << to_utf8(cmd.argument()) << endl;
@@ -1582,6 +1707,32 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                }
                break;
 
+       case LFUN_OUTLINE_UP:
+               outline(OutlineUp, cur);
+               setCursor(cur, cur.pit(), 0);
+               updateLabels(cur.buffer());
+               needsUpdate = true;
+               break;
+
+       case LFUN_OUTLINE_DOWN:
+               outline(OutlineDown, cur);
+               setCursor(cur, cur.pit(), 0);
+               updateLabels(cur.buffer());
+               needsUpdate = true;
+               break;
+
+       case LFUN_OUTLINE_IN:
+               outline(OutlineIn, cur);
+               updateLabels(cur.buffer());
+               needsUpdate = true;
+               break;
+
+       case LFUN_OUTLINE_OUT:
+               outline(OutlineOut, cur);
+               updateLabels(cur.buffer());
+               needsUpdate = true;
+               break;
+
        default:
                LYXERR(Debug::ACTION)
                        << BOOST_CURRENT_FUNCTION
@@ -1613,8 +1764,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                    == olddim.height()) {
                        // if so, update _only_ this paragraph
                        cur.updateFlags(Update::SinglePar |
-                               Update::FitCursor |
-                               Update::MultiParSel);
+                               Update::FitCursor);
                        return;
                } else
                        needsUpdate = true;
@@ -1911,6 +2061,13 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                enable = true;
                break;
 
+       case LFUN_OUTLINE_UP:
+       case LFUN_OUTLINE_DOWN:
+       case LFUN_OUTLINE_IN:
+       case LFUN_OUTLINE_OUT:
+               enable = (cur.paragraph().layout()->toclevel != Layout::NOT_IN_TOC);
+               break;
+
        case LFUN_WORD_DELETE_FORWARD:
        case LFUN_WORD_DELETE_BACKWARD:
        case LFUN_LINE_DELETE: