]> git.lyx.org Git - lyx.git/blobdiff - src/CutAndPaste.cpp
Name change CharStyle -> Flex
[lyx.git] / src / CutAndPaste.cpp
index 06b60df14da680df4cd343bada141917ef26a991..7aeed7a2cdd60f07f8dd005ca7bd91e0d9a7e6f8 100644 (file)
@@ -18,6 +18,7 @@
 #include "Buffer.h"
 #include "buffer_funcs.h"
 #include "BufferParams.h"
+#include "BufferView.h"
 #include "Cursor.h"
 #include "debug.h"
 #include "ErrorList.h"
@@ -29,6 +30,7 @@
 #include "LyXFunc.h"
 #include "LyXRC.h"
 #include "Text.h"
+#include "TextClass_ptr.h"
 #include "TextClassList.h"
 #include "Paragraph.h"
 #include "paragraph_funcs.h"
@@ -36,7 +38,7 @@
 #include "ParIterator.h"
 #include "Undo.h"
 
-#include "insets/InsetCharStyle.h"
+#include "insets/InsetFlex.h"
 #include "insets/InsetTabular.h"
 
 #include "mathed/MathData.h"
@@ -70,7 +72,7 @@ namespace {
 
 typedef std::pair<pit_type, int> PitPosPair;
 
-typedef limited_stack<pair<ParagraphList, textclass_type> > CutStack;
+typedef limited_stack<pair<ParagraphList, TextClass_ptr> > CutStack;
 
 CutStack theCuts(10);
 // persistent selection, cleared until the next selection
@@ -106,7 +108,7 @@ bool checkPastePossible(int index)
 
 pair<PitPosPair, pit_type>
 pasteSelectionHelper(Cursor & cur, ParagraphList const & parlist,
-                    textclass_type textclass, ErrorList & errorlist)
+                    TextClass_ptr textclass, ErrorList & errorlist)
 {
        Buffer const & buffer = cur.buffer();
        pit_type pit = cur.pit();
@@ -120,7 +122,7 @@ pasteSelectionHelper(Cursor & cur, ParagraphList const & parlist,
 
        // Make a copy of the CaP paragraphs.
        ParagraphList insertion = parlist;
-       textclass_type const tc = buffer.params().textclass;
+       TextClass_ptr const tc = buffer.params().getTextClass_ptr();
 
        // Now remove all out of the pars which is NOT allowed in the
        // new environment and set also another font if that is required.
@@ -146,7 +148,7 @@ pasteSelectionHelper(Cursor & cur, ParagraphList const & parlist,
        // If we are in an inset which returns forceDefaultParagraphs,
        // set the paragraphs to default
        if (cur.inset().forceDefaultParagraphs(cur.idx())) {
-               Layout_ptr const layout =
+               LayoutPtr const layout =
                        buffer.params().getTextClass().defaultLayout();
                ParagraphList::iterator const end = insertion.end();
                for (ParagraphList::iterator par = insertion.begin();
@@ -286,7 +288,7 @@ pasteSelectionHelper(Cursor & cur, ParagraphList const & parlist,
 PitPosPair eraseSelectionHelper(BufferParams const & params,
        ParagraphList & pars,
        pit_type startpit, pit_type endpit,
-       int startpos, int endpos, bool doclear)
+       int startpos, int endpos)
 {
        // Start of selection is really invalid.
        if (startpit == pit_type(pars.size()) ||
@@ -302,12 +304,6 @@ PitPosPair eraseSelectionHelper(BufferParams const & params,
        for (pit_type pit = startpit; pit != endpit + 1;) {
                pos_type const left  = (pit == startpit ? startpos : 0);
                pos_type right = (pit == endpit ? endpos : pars[pit].size() + 1);
-               // FIXME: this is a quick fix for bug 3600. It stops a crash but the problem
-               // still remains unsolved (e.g. the second example in the bug report).
-               // c.f. http://bugzilla.lyx.org/show_bug.cgi?id=3600
-               if (right > pars[pit].size() + 1)
-                       right = pars[pit].size() + 1;
-
                bool const merge = pars[pit].isMergedOnEndOfParDeletion(params.trackChanges);
 
                // Logically erase only, including the end-of-paragraph character
@@ -315,14 +311,11 @@ PitPosPair eraseSelectionHelper(BufferParams const & params,
 
                // Separate handling of paragraph break:
                if (merge && pit != endpit &&
-                   (pit + 1 != endpit || pars[pit].hasSameLayout(pars[pit + 1]))) {
-                       pos_type const thissize = pars[pit].size();
-                       if (doclear)
-                               pars[pit + 1].stripLeadingSpaces(params.trackChanges);
+                   (pit + 1 != endpit || pars[pit].hasSameLayout(pars[endpit]))) {
+                       if (pit + 1 == endpit)
+                               endpos += pars[pit].size();
                        mergeParagraph(params, pars, pit);
                        --endpit;
-                       if (pit == endpit)
-                               endpos += thissize;
                } else
                        ++pit;
        }
@@ -334,7 +327,7 @@ PitPosPair eraseSelectionHelper(BufferParams const & params,
 }
 
 
-void putClipboard(ParagraphList const & paragraphs, textclass_type textclass,
+void putClipboard(ParagraphList const & paragraphs, TextClass_ptr textclass,
                  docstring const & plaintext)
 {
        // For some strange reason gcc 3.2 and 3.3 do not accept
@@ -342,7 +335,7 @@ void putClipboard(ParagraphList const & paragraphs, textclass_type textclass,
        Buffer buffer("", false);
        buffer.setUnnamed(true);
        buffer.paragraphs() = paragraphs;
-       buffer.params().textclass = textclass;
+       buffer.params().setTextClass(textclass);
        std::ostringstream lyx;
        if (buffer.write(lyx))
                theClipboard().put(lyx.str(), plaintext);
@@ -353,7 +346,7 @@ void putClipboard(ParagraphList const & paragraphs, textclass_type textclass,
 
 void copySelectionHelper(Buffer const & buf, ParagraphList & pars,
        pit_type startpit, pit_type endpit,
-       int start, int end, textclass_type tc, CutStack & cutstack)
+       int start, int end, TextClass_ptr tc, CutStack & cutstack)
 {
        BOOST_ASSERT(0 <= start && start <= pars[startpit].size());
        BOOST_ASSERT(0 <= end && end <= pars[endpit].size());
@@ -410,20 +403,22 @@ docstring grabAndEraseSelection(Cursor & cur)
 }
 
 
-void switchBetweenClasses(textclass_type c1, textclass_type c2,
-       InsetText & in, ErrorList & errorlist)
+void switchBetweenClasses(TextClass_ptr const & c1, 
+       TextClass_ptr const & c2, InsetText & in, ErrorList & errorlist)
 {
+       errorlist.clear();
+
        BOOST_ASSERT(!in.paragraphs().empty());
        if (c1 == c2)
                return;
-
-       TextClass const & tclass1 = textclasslist[c1];
-       TextClass const & tclass2 = textclasslist[c2];
+       
+       TextClass const & tclass1 = *c1;
+       TextClass const & tclass2 = *c2;
 
        // layouts
        ParIterator end = par_iterator_end(in);
        for (ParIterator it = par_iterator_begin(in); it != end; ++it) {
-               string const name = it->layout()->name();
+               docstring const name = it->layout()->name();
                bool hasLayout = tclass2.hasLayout(name);
 
                if (hasLayout)
@@ -435,7 +430,7 @@ void switchBetweenClasses(textclass_type c1, textclass_type c2,
                        docstring const s = bformat(
                                                 _("Layout had to be changed from\n%1$s to %2$s\n"
                                                "because of class conversion from\n%3$s to %4$s"),
-                        from_utf8(name), from_utf8(it->layout()->name()),
+                        name, it->layout()->name(),
                         from_utf8(tclass1.name()), from_utf8(tclass2.name()));
                        // To warn the user that something had to be done.
                        errorlist.push_back(ErrorItem(_("Changed Layout"), s,
@@ -447,30 +442,26 @@ void switchBetweenClasses(textclass_type c1, textclass_type c2,
        // character styles
        InsetIterator const i_end = inset_iterator_end(in);
        for (InsetIterator it = inset_iterator_begin(in); it != i_end; ++it) {
-               if (it->lyxCode() == Inset::CHARSTYLE_CODE) {
-                       InsetCharStyle & inset =
-                               static_cast<InsetCharStyle &>(*it);
-                       string const name = inset.params().type;
-                       CharStyles::iterator const found_cs =
-                               tclass2.charstyle(name);
-                       if (found_cs == tclass2.charstyles().end()) {
-                               // The character style is undefined in tclass2
-                               inset.setUndefined();
+               if (it->lyxCode() == Inset::FLEX_CODE) {
+                       InsetFlex & inset =
+                               static_cast<InsetFlex &>(*it);
+                       string const name = inset.params().name;
+                       InsetLayout const il = 
+                               tclass2.insetlayout(from_utf8(name));
+                       inset.setLayout(il);
+                       if (il.labelstring == from_utf8("UNDEFINED")) {
+                               // The flex inset is undefined in tclass2
                                docstring const s = bformat(_(
-                                       "Character style %1$s is "
+                                       "Flex inset %1$s is "
                                        "undefined because of class "
                                        "conversion from\n%2$s to %3$s"),
                                         from_utf8(name), from_utf8(tclass1.name()),
                                         from_utf8(tclass2.name()));
                                // To warn the user that something had to be done.
                                errorlist.push_back(ErrorItem(
-                                       _("Undefined character style"),
+                                       _("Undefined flex inset"),
                                        s, it.paragraph().id(), it.pos(), it.pos() + 1));
-                       } else if (inset.undefined()) {
-                               // The character style is undefined in
-                               // tclass1 and is defined in tclass2
-                               inset.setDefined(found_cs);
-                       }
+                       } 
                }
        }
 }
@@ -524,6 +515,8 @@ void cutSelection(Cursor & cur, bool doclear, bool realcut)
                Text * text = cur.text();
                BOOST_ASSERT(text);
 
+               saveSelection(cur);
+
                // make sure that the depth behind the selection are restored, too
                recordUndoSelection(cur);
                pit_type begpit = cur.selBegin().pit();
@@ -537,7 +530,7 @@ void cutSelection(Cursor & cur, bool doclear, bool realcut)
                                text->paragraphs(),
                                begpit, endpit,
                                cur.selBegin().pos(), endpos,
-                               bp.textclass, theCuts);
+                               bp.getTextClass_ptr(), theCuts);
                        // Stuff what we got on the clipboard.
                        // Even if there is no selection.
                        putClipboard(theCuts[0].first, theCuts[0].second,
@@ -548,8 +541,7 @@ void cutSelection(Cursor & cur, bool doclear, bool realcut)
                        eraseSelectionHelper(bp,
                                text->paragraphs(),
                                begpit, endpit,
-                               cur.selBegin().pos(), endpos,
-                               doclear);
+                               cur.selBegin().pos(), endpos);
 
                // cutSelection can invalidate the cursor so we need to set
                // it anew. (Lgb)
@@ -565,7 +557,6 @@ void cutSelection(Cursor & cur, bool doclear, bool realcut)
                // need a valid cursor. (Lgb)
                cur.clearSelection();
                updateLabels(cur.buffer());
-               theSelection().haveSelection(false);
 
                // tell tabular that a recent copy happened
                dirtyTabularStack(false);
@@ -622,7 +613,8 @@ void copySelectionToStack(Cursor & cur, CutStack & cutstack)
                        ++pos;
 
                copySelectionHelper(cur.buffer(), pars, par, cur.selEnd().pit(),
-                       pos, cur.selEnd().pos(), cur.buffer().params().textclass, cutstack);
+                       pos, cur.selEnd().pos(), 
+                       cur.buffer().params().getTextClass_ptr(), cutstack);
                dirtyTabularStack(false);
        }
 
@@ -634,7 +626,7 @@ void copySelectionToStack(Cursor & cur, CutStack & cutstack)
                par.layout(bp.getTextClass().defaultLayout());
                par.insert(0, grabSelection(cur), Font(), Change(Change::UNCHANGED));
                pars.push_back(par);
-               cutstack.push(make_pair(pars, bp.textclass));
+               cutstack.push(make_pair(pars, bp.getTextClass_ptr()));
        }
 }
 
@@ -661,7 +653,7 @@ void copySelection(Cursor & cur, docstring const & plaintext)
                par.layout(bp.getTextClass().defaultLayout());
                par.insert(0, plaintext, Font(), Change(Change::UNCHANGED));
                pars.push_back(par);
-               theCuts.push(make_pair(pars, bp.textclass));
+               theCuts.push(make_pair(pars, bp.getTextClass_ptr()));
        } else
                copySelectionToStack(cur, theCuts);
 
@@ -672,24 +664,17 @@ void copySelection(Cursor & cur, docstring const & plaintext)
 
 void saveSelection(Cursor & cur)
 {
-       LYXERR(Debug::ACTION) << BOOST_CURRENT_FUNCTION << ": `"
-              << to_utf8(cur.selectionAsString(true)) << "'."
-              << endl;
-
-#if 0
-       // FIXME: The two lines below would allow middle-mouse 
-       // pasting that preserves the LyX formatting when the selection
-       // is internal. They would also allow to use the feature on
-       // Windows and Mac. In the future, we may want to optionally enable
-       // this feature via a rc setting.
-       // This is currently disabled because it eats too much resources
-       // while selecting (cf. bug 3877)
-       if (cur.selection())
+       // This function is called, not when a selection is formed, but when
+       // a selection is cleared. Therefore, multiple keyboard selection
+       // will not repeatively trigger this function (bug 3877).
+       if (cur.selection() 
+           && cur.selBegin() == cur.bv().cursor().selBegin()
+           && cur.selEnd() == cur.bv().cursor().selEnd()) {
+               LYXERR(Debug::ACTION) << BOOST_CURRENT_FUNCTION << ": `"
+                          << to_utf8(cur.selectionAsString(true)) << "'."
+                          << endl;
                copySelectionToStack(cur, selectionBuffer);
-#endif
-
-       // tell X whether we now have a valid selection
-       theSelection().haveSelection(cur.selection());
+       }
 }
 
 
@@ -714,7 +699,7 @@ docstring getSelection(Buffer const & buf, size_t sel_index)
 
 
 void pasteParagraphList(Cursor & cur, ParagraphList const & parlist,
-                       textclass_type textclass, ErrorList & errorList)
+                       TextClass_ptr textclass, ErrorList & errorList)
 {
        if (cur.inTexted()) {
                Text * text = cur.text();
@@ -746,7 +731,6 @@ void pasteFromStack(Cursor & cur, ErrorList & errorList, size_t sel_index)
        pasteParagraphList(cur, theCuts[sel_index].first,
                           theCuts[sel_index].second, errorList);
        cur.setSelection();
-       saveSelection(cur);
 }
 
 
@@ -769,7 +753,7 @@ void pasteClipboard(Cursor & cur, ErrorList & errorList, bool asParagraphs)
                        if (buffer.readString(lyx)) {
                                recordUndo(cur);
                                pasteParagraphList(cur, buffer.paragraphs(),
-                                       buffer.params().textclass, errorList);
+                                       buffer.params().getTextClass_ptr(), errorList);
                                cur.setSelection();
                                return;
                        }
@@ -795,7 +779,6 @@ void pasteSelection(Cursor & cur, ErrorList & errorList)
        recordUndo(cur);
        pasteParagraphList(cur, selectionBuffer[0].first,
                           selectionBuffer[0].second, errorList);
-       cur.setSelection();
 }
 
 
@@ -825,7 +808,6 @@ void replaceSelectionWithString(Cursor & cur, docstring const & str, bool backwa
                cur.setSelection(selbeg, -int(str.length()));
        } else
                cur.setSelection(selbeg, str.length());
-       saveSelection(cur);
 }
 
 
@@ -842,6 +824,7 @@ void eraseSelection(Cursor & cur)
        CursorSlice const & i1 = cur.selBegin();
        CursorSlice const & i2 = cur.selEnd();
        if (i1.inset().asInsetMath()) {
+               saveSelection(cur);
                cur.top() = i1;
                if (i1.idx() == i2.idx()) {
                        i1.cell().erase(i1.pos(), i2.pos());
@@ -862,7 +845,6 @@ void eraseSelection(Cursor & cur)
                }
                // need a valid cursor. (Lgb)
                cur.clearSelection();
-               theSelection().haveSelection(false);
        } else {
                lyxerr << "can't erase this selection 1" << endl;
        }