X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FCutAndPaste.C;h=c2ddae5c60dfcd7720ca3933fb553b34cf921502;hb=28902af06012253c7b5eb80e179a352aac17d6a5;hp=846c4041fb43df1801a72fb895aa8147de429a8e;hpb=238b880c224150a892c6358a0c2af07caecdad7b;p=lyx.git diff --git a/src/CutAndPaste.C b/src/CutAndPaste.C index 846c4041fb..c2ddae5c60 100644 --- a/src/CutAndPaste.C +++ b/src/CutAndPaste.C @@ -6,6 +6,7 @@ * \author Jürgen Vigna * \author Lars Gullik Bjønnes * \author Alfredo Braunstein + * \author Michael Gerz * * Full author contact details are available in file CREDITS. */ @@ -44,18 +45,15 @@ #include "support/lstrings.h" -#include "frontends/Application.h" #include "frontends/Clipboard.h" #include -using lyx::pos_type; -using lyx::pit_type; -using lyx::textclass_type; -using lyx::support::bformat; +namespace lyx { -using lyx::frontend::Clipboard; +using support::bformat; +using frontend::Clipboard; using std::endl; using std::for_each; @@ -67,7 +65,7 @@ using std::string; namespace { -typedef std::pair PitPosPair; +typedef std::pair PitPosPair; typedef limited_stack > CutStack; @@ -78,26 +76,6 @@ CutStack theCuts(10); // when we (hopefully) have a one-for-all paste mechanism. bool dirty_tabular_stack_; -class resetParagraph : public std::unary_function { -public: - resetParagraph(Buffer const & b) : buffer_(b) {} - void operator()(Paragraph & p) const { - // FIXME: change tracking (MG) - // set p's text to INSERTED in CT mode; clear CT info otherwise - - // ERT paragraphs have the Language latex_language. - // This is invalid outside of ERT, so we need to change it - // to the buffer language. - if (p.ownerCode() == InsetBase::ERT_CODE) { - p.changeLanguage(buffer_.params(), latex_language, - buffer_.getLanguage()); - } - p.setInsetOwner(0); - } -private: - Buffer const & buffer_; -}; - void region(CursorSlice const & i1, CursorSlice const & i2, InsetBase::row_type & r1, InsetBase::row_type & r2, @@ -149,7 +127,8 @@ pasteSelectionHelper(LCursor & cur, ParagraphList const & parlist, for (ParagraphList::size_type i = 0; i < insertion.size(); ++i) { for (pos_type j = 0; j < insertion[i].size(); ++j) { if (insertion[i].isNewline(j)) { - insertion[i].erase(j); + // do not track deletion of newline + insertion[i].eraseChar(j, false); breakParagraphConservative( buffer.params(), insertion, i, j); @@ -176,13 +155,13 @@ pasteSelectionHelper(LCursor & cur, ParagraphList const & parlist, // since we store pointers to insets at some places and we don't // want to invalidate them. insertion.swap(in.paragraphs()); - lyx::cap::switchBetweenClasses(textclass, tc, in, errorlist); + cap::switchBetweenClasses(textclass, tc, in, errorlist); insertion.swap(in.paragraphs()); ParagraphList::iterator tmpbuf = insertion.begin(); int depth_delta = pars[pit].params().depth() - tmpbuf->params().depth(); - Paragraph::depth_type max_depth = pars[pit].getMaxDepthAfter(); + depth_type max_depth = pars[pit].getMaxDepthAfter(); for (; tmpbuf != insertion.end(); ++tmpbuf) { // If we have a negative jump so that the depth would @@ -208,11 +187,12 @@ pasteSelectionHelper(LCursor & cur, ParagraphList const & parlist, for (pos_type i = 0; i < tmpbuf->size(); ++i) { if (tmpbuf->getChar(i) == Paragraph::META_INSET && !pars[pit].insetAllowed(tmpbuf->getInset(i)->lyxCode())) - tmpbuf->erase(i--); + // do not track deletion of invalid insets + tmpbuf->eraseChar(i--, false); } - // FIXME: Change tracking (MG) - // set tmpbuf's text to INSERTED in CT mode; clear CT info otherwise + tmpbuf->setChange(Change(buffer.params().trackChanges ? + Change::INSERTED : Change::UNCHANGED)); } bool const empty = pars[pit].empty(); @@ -230,8 +210,8 @@ pasteSelectionHelper(LCursor & cur, ParagraphList const & parlist, ParIterator fend = par_iterator_end(in); for (; fpit != fend; ++fpit) { - InsetList::iterator lit = fpit->insetlist.begin(); - InsetList::iterator eit = fpit->insetlist.end(); + InsetList::const_iterator lit = fpit->insetlist.begin(); + InsetList::const_iterator eit = fpit->insetlist.end(); for (; lit != eit; ++lit) { switch (lit->inset->lyxCode()) { @@ -308,28 +288,23 @@ PitPosPair eraseSelectionHelper(BufferParams const & params, return PitPosPair(endpit, endpos); // Start and end is inside same paragraph - if (endpit == pit_type(pars.size()) || - startpit == endpit) { - endpos -= pars[startpit].erase(startpos, endpos); + if (endpit == pit_type(pars.size()) || startpit == endpit) { + endpos -= pars[startpit].eraseChars(startpos, endpos, params.trackChanges); return PitPosPair(endpit, endpos); } - // A paragraph break has to be physically removed by merging, but - // only if either (1) change tracking is off, or (2) the para break - // is "blue" for (pit_type pit = startpit; pit != endpit + 1;) { - // FIXME: Change tracking (MG) - bool const merge = !params.trackChanges || - pars[pit].lookupChange(pars[pit].size()) == - Change::INSERTED; - pos_type const left = ( pit == startpit ? startpos : 0 ); - pos_type const right = ( pit == endpit ? endpos : - pars[pit].size() + 1 ); - // Logical erase only: - pars[pit].erase(left, right); - // Separate handling of para break: + pos_type const left = (pit == startpit ? startpos : 0); + pos_type const right = (pit == endpit ? endpos : pars[pit].size() + 1); + + bool const merge = pars[pit].isMergedOnEndOfParDeletion(params.trackChanges); + + // Logically erase only, including the end-of-paragraph character + pars[pit].eraseChars(left, right, params.trackChanges); + + // Separate handling of paragraph break: if (merge && pit != endpit && - (pit + 1 != endpit || pars[pit].hasSameLayout(pars[pit + 1]))) { + (pit + 1 != endpit || pars[pit].hasSameLayout(pars[pit + 1]))) { pos_type const thissize = pars[pit].size(); if (doclear) pars[pit + 1].stripLeadingSpaces(); @@ -360,15 +335,29 @@ void copySelectionHelper(Buffer const & buf, ParagraphList & pars, ParagraphList paragraphs(boost::next(pars.begin(), startpit), boost::next(pars.begin(), endpit + 1)); - for_each(paragraphs.begin(), paragraphs.end(), resetParagraph(buf)); + ParagraphList::iterator it = paragraphs.begin(); + ParagraphList::iterator it_end = paragraphs.end(); + + for (; it != it_end; it++) { + // ERT paragraphs have the Language latex_language. + // This is invalid outside of ERT, so we need to change it + // to the buffer language. + if (it->ownerCode() == InsetBase::ERT_CODE) { + it->changeLanguage(buf.params(), latex_language, + buf.getLanguage()); + } + it->setInsetOwner(0); + } // Cut out the end of the last paragraph. Paragraph & back = paragraphs.back(); - back.erase(end, back.size()); + // do not track deletion here; it is an internal action not visible to the user + back.eraseChars(end, back.size(), false); // Cut out the begin of the first paragraph Paragraph & front = paragraphs.front(); - front.erase(0, start); + // again, do not track deletion + front.eraseChars(0, start, false); theCuts.push(make_pair(paragraphs, tc)); } @@ -378,14 +367,13 @@ void copySelectionHelper(Buffer const & buf, ParagraphList & pars, -namespace lyx { namespace cap { -string grabAndEraseSelection(LCursor & cur) +docstring grabAndEraseSelection(LCursor & cur) { if (!cur.selection()) - return string(); - string res = grabSelection(cur); + return docstring(); + docstring res = grabSelection(cur); eraseSelection(cur); return res; } @@ -416,8 +404,8 @@ 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"), - lyx::from_utf8(name), lyx::from_utf8(it->layout()->name()), - lyx::from_utf8(tclass1.name()), lyx::from_utf8(tclass2.name())); + from_utf8(name), from_utf8(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, it->id(), 0, @@ -441,8 +429,8 @@ void switchBetweenClasses(textclass_type c1, textclass_type c2, "Character style %1$s is " "undefined because of class " "conversion from\n%2$s to %3$s"), - lyx::from_utf8(name), lyx::from_utf8(tclass1.name()), - lyx::from_utf8(tclass2.name())); + 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"), @@ -457,9 +445,9 @@ void switchBetweenClasses(textclass_type c1, textclass_type c2, } -std::vector const availableSelections(Buffer const & buffer) +std::vector const availableSelections(Buffer const & buffer) { - vector selList; + vector selList; CutStack::const_iterator cit = theCuts.begin(); CutStack::const_iterator end = theCuts.end(); @@ -467,13 +455,14 @@ std::vector const availableSelections(Buffer const & buffer) // we do not use cit-> here because gcc 2.9x does not // like it (JMarc) ParagraphList const & pars = (*cit).first; - string asciiSel; + docstring asciiSel; ParagraphList::const_iterator pit = pars.begin(); ParagraphList::const_iterator pend = pars.end(); for (; pit != pend; ++pit) { asciiSel += pit->asString(buffer, false); if (asciiSel.size() > 25) { - asciiSel.replace(22, string::npos, "..."); + asciiSel.replace(22, docstring::npos, + from_ascii("...")); break; } } @@ -485,7 +474,7 @@ std::vector const availableSelections(Buffer const & buffer) } -lyx::size_type numberOfSelections() +size_type numberOfSelections() { return theCuts.size(); } @@ -510,8 +499,8 @@ void cutSelection(LCursor & cur, bool doclear, bool realcut) // solved by running the line below only when the selection has // finished. The solution used currently just works, to make it // faster we need to be more clever and probably also have more - // calls to theApp->selection().put. (Lgb) -// theApp->selection().put(cur.selectionAsString(true)); + // calls to theSelection().put. (Lgb) +// theSelection().put(cur.selectionAsString(true)); // make sure that the depth behind the selection are restored, too @@ -575,7 +564,7 @@ void cutSelection(LCursor & cur, bool doclear, bool realcut) void copySelection(LCursor & cur) { // stuff the selection onto the X clipboard, from an explicit copy request - theApp->clipboard().put(cur.selectionAsString(true)); + theClipboard().put(cur.selectionAsString(true)); // this doesn't make sense, if there is no selection if (!cur.selection()) @@ -603,11 +592,11 @@ void copySelection(LCursor & cur) if (cur.inMathed()) { //lyxerr << "copySelection in mathed" << endl; ParagraphList pars; - pars.push_back(Paragraph()); + Paragraph par; BufferParams const & bp = cur.buffer().params(); - pars.back().layout(bp.getLyXTextClass().defaultLayout()); - for_each(pars.begin(), pars.end(), resetParagraph(cur.buffer())); - pars.back().insert(0, grabSelection(cur), LyXFont()); + par.layout(bp.getLyXTextClass().defaultLayout()); + par.insert(0, grabSelection(cur), LyXFont(), Change(Change::UNCHANGED)); + pars.push_back(par); theCuts.push(make_pair(pars, bp.textclass)); } // tell tabular that a recent copy happened @@ -615,11 +604,11 @@ void copySelection(LCursor & cur) } -std::string getSelection(Buffer const & buf, size_t sel_index) +docstring getSelection(Buffer const & buf, size_t sel_index) { return sel_index < theCuts.size() ? theCuts[sel_index].first.back().asString(buf, false) - : string(); + : docstring(); } @@ -630,8 +619,6 @@ void pasteParagraphList(LCursor & cur, ParagraphList const & parlist, LyXText * text = cur.text(); BOOST_ASSERT(text); - recordUndo(cur); - pit_type endpit; PitPosPair ppp; @@ -654,6 +641,7 @@ void pasteSelection(LCursor & cur, ErrorList & errorList, size_t sel_index) if (!checkPastePossible(sel_index)) return; + recordUndo(cur); pasteParagraphList(cur, theCuts[sel_index].first, theCuts[sel_index].second, errorList); cur.setSelection(); @@ -676,7 +664,7 @@ void replaceSelectionWithString(LCursor & cur, string const & str, bool backward string::const_iterator cit = str.begin(); string::const_iterator end = str.end(); for (; cit != end; ++cit, ++pos) - par.insertChar(pos, (*cit), font); + par.insertChar(pos, (*cit), font, cur.buffer().params().trackChanges); // Cut the selection cutSelection(cur, true, false); @@ -684,7 +672,7 @@ void replaceSelectionWithString(LCursor & cur, string const & str, bool backward // select the replacement if (backwards) { selbeg.pos() += str.length(); - cur.setSelection(selbeg, -str.length()); + cur.setSelection(selbeg, -int(str.length())); } else cur.setSelection(selbeg, str.length()); } @@ -748,10 +736,10 @@ void selClearOrDel(LCursor & cur) } -string grabSelection(LCursor const & cur) +docstring grabSelection(LCursor const & cur) { if (!cur.selection()) - return string(); + return docstring(); // FIXME: What is wrong with the following? #if 0 @@ -770,7 +758,7 @@ string grabSelection(LCursor const & cur) MathArray::const_iterator it = i1.cell().begin(); return asString(MathArray(it + i1.pos(), it + i2.pos())); } else { - return "unknown selection 1"; + return from_ascii("unknown selection 1"); } } @@ -778,7 +766,7 @@ string grabSelection(LCursor const & cur) InsetBase::col_type c1, c2; region(i1, i2, r1, r2, c1, c2); - string data; + docstring data; if (i1.inset().asInsetMath()) { for (InsetBase::row_type row = r1; row <= r2; ++row) { if (row > r1) @@ -791,7 +779,7 @@ string grabSelection(LCursor const & cur) } } } else { - data = "unknown selection 2"; + data = from_ascii("unknown selection 2"); } return data; } @@ -810,4 +798,5 @@ bool tabularStackDirty() } // namespace cap + } // namespace lyx