X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FCutAndPaste.C;h=0f3a66c47aef613aa776324fe549e5395828ee4e;hb=8a5d04fd84e344a1ba1cfd3f5cce67d41874cfa3;hp=c6eec1d8b6d811425c08e833f1d395ce9b3fd798;hpb=c8089f8bf9d66c8428e8869895c61145ee4dd5e9;p=lyx.git diff --git a/src/CutAndPaste.C b/src/CutAndPaste.C index c6eec1d8b6..0f3a66c47a 100644 --- a/src/CutAndPaste.C +++ b/src/CutAndPaste.C @@ -14,7 +14,6 @@ #endif #include "CutAndPaste.h" -//#include "debug.h" #include "BufferView.h" #include "buffer.h" #include "paragraph.h" @@ -24,9 +23,15 @@ #include "gettext.h" #include "iterators.h" #include "lyxtextclasslist.h" +#include "undo_funcs.h" +#include "paragraph_funcs.h" +#include "debug.h" #include "insets/inseterror.h" +#include "BoostFormat.h" + +using std::endl; using std::pair; using lyx::pos_type; using lyx::textclass_type; @@ -54,6 +59,7 @@ extern BufferView * current_view; namespace { +// FIXME: stupid name Paragraph * buf = 0; textclass_type textclass = 0; @@ -86,79 +92,93 @@ bool CutAndPaste::cutSelection(Paragraph * startpar, Paragraph ** endpar, if (!startpar || (start > startpar->size())) return false; - if (realcut) - DeleteBuffer(); - - textclass = tc; + if (realcut) { + copySelection(startpar, *endpar, start, end, tc); + } - if (!(*endpar) || startpar == (*endpar)) { - // only within one paragraph - if (realcut) { - buf = new Paragraph; - buf->layout(startpar->layout()); - } - pos_type i = start; - if (end > startpar->size()) - end = startpar->size(); - for (; i < end; ++i) { - if (realcut) - startpar->copyIntoMinibuffer(*current_view->buffer(), - start); - startpar->erase(start); - if (realcut) - buf->insertFromMinibuffer(buf->size()); + if (!endpar || startpar == *endpar) { + if (startpar->erase(start, end)) { + // Some chars were erased, go to start to be safe + end = start; } - end = start - 1; - } else { - // more than one paragraph - (*endpar)->breakParagraphConservative(current_view->buffer()->params, - end); - *endpar = (*endpar)->next(); + return true; + } + + bool actually_erased = false; + + // clear end/begin fragments of the first/last par in selection + actually_erased |= (startpar)->erase(start, startpar->size()); + if ((*endpar)->erase(0, end)) { + actually_erased = true; end = 0; - - startpar->breakParagraphConservative(current_view->buffer()->params, - start); - - // store the selection - if (realcut) { - buf = startpar->next(); - buf->previous(0); - } else { - startpar->next()->previous(0); + } + + // Loop through the deleted pars if any, erasing as needed + + Paragraph * pit = startpar->next(); + + while (1) { + // *endpar can be 0 + if (!pit) + break; + + Paragraph * next = pit->next(); + + // "erase" the contents of the par + if (pit != *endpar) { + actually_erased |= pit->erase(0, pit->size()); + + // remove the par if it's now empty + if (actually_erased) { + pit->previous()->next(pit->next()); + if (next) { + next->previous(pit->previous()); + } + lyxerr << "deleting pit " << pit << endl; + + delete pit; + } } - (*endpar)->previous()->next(0); + + if (pit == *endpar) + break; + + pit = next; + } - // cut the selection - startpar->next(*endpar); +#if 0 // FIXME: why for cut but not copy ? + // the cut selection should begin with standard layout + if (realcut) { + buf->params().clear(); + buf->bibkey = 0; + buf->layout(textclasslist[buffer->params.textclass].defaultLayoutName()); + } +#endif - (*endpar)->previous(startpar); + if (!startpar->next()) + return true; + + Buffer * buffer = current_view->buffer(); - // the cut selection should begin with standard layout - if (realcut) { - buf->params().clear(); - buf->bibkey = 0; - buf->layout(textclasslist[current_view->buffer()->params.textclass].defaultLayoutName()); - } + if (doclear) { + startpar->next()->stripLeadingSpaces(); + } - // paste the paragraphs again, if possible - if (doclear) - startpar->next()->stripLeadingSpaces(textclass); - if (startpar->hasSameLayout(startpar->next()) || - !startpar->next()->size()) { - startpar->pasteParagraph(current_view->buffer()->params); - (*endpar) = startpar; // this because endpar gets deleted here! - } - // this paragraph's are of noone's owner! - Paragraph * p = buf; - while (p) { - p->setInsetOwner(0); - p = p->next(); - } + if (!actually_erased) + return true; + + // paste the paragraphs again, if possible + if (startpar->hasSameLayout(startpar->next()) || + startpar->next()->empty()) { + mergeParagraph(buffer->params, startpar); + // this because endpar gets deleted here! + (*endpar) = startpar; } + return true; } - + bool CutAndPaste::copySelection(Paragraph * startpar, Paragraph * endpar, int start, int end, char tc) { @@ -186,6 +206,7 @@ bool CutAndPaste::copySelection(Paragraph * startpar, Paragraph * endpar, Paragraph * tmppar = startpar; buf = new Paragraph(*tmppar, false); Paragraph * tmppar2 = buf; + tmppar2->cleanChanges(); while (tmppar != endpar && tmppar->next()) { @@ -193,6 +214,8 @@ bool CutAndPaste::copySelection(Paragraph * startpar, Paragraph * endpar, tmppar2->next(new Paragraph(*tmppar, false)); tmppar2->next()->previous(tmppar2); tmppar2 = tmppar2->next(); + // reset change info + tmppar2->cleanChanges(); } tmppar2->next(0); @@ -283,7 +306,13 @@ bool CutAndPaste::pasteSelection(Paragraph ** par, Paragraph ** endpar, // temporary set *par as previous of tmpbuf as we might have to realize // the font. tmpbuf->previous(*par); - Paragraph::depth_type max_depth = (*par)->getMaxDepthAfter(current_view->buffer()); + + // make sure there is no class difference + SwitchLayoutsBetweenClasses(textclass, tc, tmpbuf, + current_view->buffer()->params); + + Paragraph::depth_type max_depth = (*par)->getMaxDepthAfter(); + while(tmpbuf) { // if we have a negative jump so that the depth would go below // 0 depth then we have to redo the delta to this new max depth @@ -298,7 +327,7 @@ bool CutAndPaste::pasteSelection(Paragraph ** par, Paragraph ** endpar, // only set this from the 2nd on as the 2nd depends for maxDepth // still on *par if (tmpbuf->previous() != (*par)) - max_depth = tmpbuf->getMaxDepthAfter(current_view->buffer()); + max_depth = tmpbuf->getMaxDepthAfter(); // set the inset owner of this paragraph tmpbuf->setInsetOwner((*par)->inInset()); for(pos_type i = 0; i < tmpbuf->size(); ++i) { @@ -322,10 +351,6 @@ bool CutAndPaste::pasteSelection(Paragraph ** par, Paragraph ** endpar, // now reset it to 0 buf->previous(0); - // make sure there is no class difference - SwitchLayoutsBetweenClasses(textclass, tc, buf, - current_view->buffer()->params); - // make the buf exactly the same layout than // the cursor paragraph buf->makeSameLayout(*par); @@ -340,8 +365,8 @@ bool CutAndPaste::pasteSelection(Paragraph ** par, Paragraph ** endpar, // open the paragraph for inserting the buf // if necessary if (((*par)->size() > pos) || !(*par)->next()) { - (*par)->breakParagraphConservative(current_view->buffer()->params, - pos); + breakParagraphConservative( + current_view->buffer()->params, *par, pos); paste_the_end = true; } // set the end for redoing later @@ -357,22 +382,22 @@ bool CutAndPaste::pasteSelection(Paragraph ** par, Paragraph ** endpar, if ((*par)->next() == lastbuffer) lastbuffer = *par; - (*par)->pasteParagraph(current_view->buffer()->params); + mergeParagraph(current_view->buffer()->params, *par); // store the new cursor position *par = lastbuffer; pos = lastbuffer->size(); // maybe some pasting if (lastbuffer->next() && paste_the_end) { if (lastbuffer->next()->hasSameLayout(lastbuffer)) { - lastbuffer->pasteParagraph(current_view->buffer()->params); + mergeParagraph(current_view->buffer()->params, lastbuffer); } else if (!lastbuffer->next()->size()) { lastbuffer->next()->makeSameLayout(lastbuffer); - lastbuffer->pasteParagraph(current_view->buffer()->params); + mergeParagraph(current_view->buffer()->params, lastbuffer); } else if (!lastbuffer->size()) { lastbuffer->makeSameLayout(lastbuffer->next()); - lastbuffer->pasteParagraph(current_view->buffer()->params); + mergeParagraph(current_view->buffer()->params, lastbuffer); } else - lastbuffer->next()->stripLeadingSpaces(tc); + lastbuffer->next()->stripLeadingSpaces(); } // restore the simple cut buffer buf = simple_cut_clone; @@ -406,31 +431,41 @@ int CutAndPaste::SwitchLayoutsBetweenClasses(textclass_type c1, if (!par || c1 == c2) return ret; + LyXTextClass const & tclass1 = textclasslist[c1]; + LyXTextClass const & tclass2 = textclasslist[c2]; ParIterator end = ParIterator(); for (ParIterator it = ParIterator(par); it != end; ++it) { par = *it; - string const name = par->layout(); - LyXTextClass const & tclass = textclasslist[c2]; - - bool hasLayout = tclass.hasLayout(name); + string const name = par->layout()->name(); + bool hasLayout = tclass2.hasLayout(name); - string lay = tclass.defaultLayoutName(); - if (hasLayout) { - lay = name; - } else { - // not found: use default layout - lay = tclass.defaultLayoutName(); - } - par->layout(lay); + if (hasLayout) + par->layout(tclass2[name]); + else + par->layout(tclass2.defaultLayout()); - if (name != par->layout()) { + if (!hasLayout && name != tclass1.defaultLayoutName()) { ++ret; +#if USE_BOOST_FORMAT + boost::format fmt(_("Layout had to be changed from\n" + "%1$s to %2$s\n" + "because of class conversion from\n" + "%3$s to %4$s")); + fmt % name + % par->layout()->name() + % tclass1.name() + % tclass2.name(); + + string const s = fmt.str(); +#else string const s = _("Layout had to be changed from\n") + name + _(" to ") - + par->layout() + + par->layout()->name() + _("\nbecause of class conversion from\n") - + textclasslist[c1].name() + _(" to ") - + textclasslist[c2].name(); + + tclass1.name() + _(" to ") + + tclass2.name(); +#endif + freezeUndo(); InsetError * new_inset = new InsetError(s); LyXText * txt = current_view->getLyXText(); LyXCursor cur = txt->cursor; @@ -438,6 +473,7 @@ int CutAndPaste::SwitchLayoutsBetweenClasses(textclass_type c1, txt->insertInset(current_view, new_inset); txt->fullRebreak(current_view); txt->setCursorIntern(current_view, cur.par(), cur.pos()); + unFreezeUndo(); } } return ret;