X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FCutAndPaste.C;h=36c863428ff1f183dce6c9092f39c18c789aea12;hb=c544107e324090c6eafb4c56749da2624b9b1122;hp=73c48237555da5fe9fe0f17d0cbaf22e7b5dd49c;hpb=35cf7dcb2bdfdcda465b69c58465f657c77fd9d7;p=lyx.git diff --git a/src/CutAndPaste.C b/src/CutAndPaste.C index 73c4823755..36c863428f 100644 --- a/src/CutAndPaste.C +++ b/src/CutAndPaste.C @@ -1,471 +1,423 @@ -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1995-2000 The LyX Team. +/* \file CutAndPaste.C + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. * - * ====================================================== */ + * \author Juergen Vigna + * \author Lars Gullik Bjønnes + * \author Alfredo Braunstein + * + * Full author contact details are available in file CREDITS + */ #include #include "CutAndPaste.h" #include "BufferView.h" #include "buffer.h" -#include "lyxparagraph.h" -#include "insets/inseterror.h" -#include "lyx_gui_misc.h" +#include "errorlist.h" +#include "paragraph.h" +#include "ParagraphParameters.h" +#include "lyxtext.h" #include "lyxcursor.h" +#include "iterators.h" +#include "lyxtextclasslist.h" +#include "undo_funcs.h" +#include "gettext.h" +#include "paragraph_funcs.h" +#include "debug.h" +#include "insets/insetinclude.h" +#include "insets/insettabular.h" + +#include "support/LAssert.h" +#include "support/lstrings.h" +#include "support/limited_stack.h" + +using std::endl; +using std::pair; +using std::make_pair; +using std::for_each; +using std::vector; -#ifdef __GNUG__ -#pragma implementation -#endif +using namespace lyx::support; +using lyx::pos_type; +using lyx::textclass_type; + + +typedef limited_stack > CutStack; + +namespace { + +CutStack cuts(10); + +} // namespace anon + + +std::vector +CutAndPaste::availableSelections(Buffer const & buffer) +{ + vector selList; + + CutStack::const_iterator cit = cuts.begin(); + CutStack::const_iterator end = cuts.end(); + for (; cit != end; ++cit) { + // we do not use cit-> here because gcc 2.9x does not + // like it (JMarc) + ParagraphList const & pars = (*cit).first; + string 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, "..."); + break; + } + } + + selList.push_back(asciiSel); + } + + return selList; +} -using std::pair; -extern BufferView * current_view; - -// Jürgen, note that this means that you cannot currently have a list -// of selections cut/copied. So IMHO later we should have a -// list/vector/deque that we could store -// struct selection_item { -// LyXParagraph * buf; -// LyXTextClassList::size_type textclass; -// }; -// in and some method of choosing beween them (based on the first few chars -// in the selection probably.) This would be a nice feature and quite -// easy to implement. (Lgb) -// -// Sure but I just cleaned up this code for now with the same functionality -// as before. I also want to add a XClipboard function so that we can copy -// text from LyX to some other X-application in the form of ASCII or in the -// form of LaTeX (or Docbook depending on the document-class!). Think how nice -// it could be to select a math-inset do a "Copy to X-Clipboard as LaTeX" and -// then do a middle mouse button click in the application you want and have -// the whole formula there in LaTeX-Code. (Jug) - -static LyXParagraph * buf = 0; -static LyXTextClassList::size_type textclass = 0; - -// for now here this should be in another Cut&Paste Class! -// Jürgen, I moved this out of CutAndPaste since it does not operate on any -// member of the CutAndPaste class and in addition it was private. -// Perhaps it even should take a parameter? (Lgb) -static -void DeleteBuffer() +PitPosPair CutAndPaste::cutSelection(BufferParams const & params, + ParagraphList & pars, + ParagraphList::iterator startpit, + ParagraphList::iterator endpit, + int startpos, int endpos, + textclass_type tc, bool doclear) { - if (!buf) - return; - - LyXParagraph * tmppar; - - while (buf) { - tmppar = buf; - buf = buf->next; - delete tmppar; - } - buf = 0; + copySelection(startpit, endpit, startpos, endpos, tc); + return eraseSelection(params, pars, startpit, endpit, startpos, + endpos, doclear); } -bool CutAndPaste::cutSelection(LyXParagraph * startpar, LyXParagraph ** endpar, - int start, int & end, char tc, bool doclear) +PitPosPair CutAndPaste::eraseSelection(BufferParams const & params, + ParagraphList & pars, + ParagraphList::iterator startpit, + ParagraphList::iterator endpit, + int startpos, int endpos, bool doclear) { - if (!startpar || (start > startpar->Last())) - return false; - - DeleteBuffer(); - - textclass = tc; - - if (!(*endpar) || (startpar->ParFromPos(start) == - (*endpar)->ParFromPos(end))) { - // only within one paragraph - buf = new LyXParagraph; - LyXParagraph::size_type i = start; - if (end > startpar->Last()) - end = startpar->Last(); - for (; i < end; ++i) { - startpar->CopyIntoMinibuffer(current_view->buffer()->params, - start); -#ifndef NEW_TABULAR - /* table stuff -- begin */ - if (startpar->table && startpar->IsNewline(start)) { - ++start; - } else { - /* table stuff -- end */ -#endif - startpar->Erase(start); -#ifndef NEW_TABULAR - } -#endif - buf->InsertFromMinibuffer(buf->Last()); + if (startpit == pars.end() || (startpos > startpit->size())) + return PitPosPair(endpit, endpos); + + if (endpit == pars.end() || startpit == endpit) { + endpos -= startpit->erase(startpos, endpos); + return PitPosPair(endpit, endpos); } - } else { - // more than one paragraph - (*endpar)->BreakParagraphConservative(current_view->buffer()->params, - end); - *endpar = (*endpar)->Next(); - end = 0; - - startpar->BreakParagraphConservative(current_view->buffer()->params, - start); - - // store the selection - buf = startpar->ParFromPos(start)->next; - buf->previous = 0; - (*endpar)->previous->next = 0; - - // cut the selection - startpar->ParFromPos(start)->next = (*endpar); - - (*endpar)->previous = startpar->ParFromPos(start); - -#ifndef NEW_INSETS - // care about footnotes - if (buf->footnoteflag) { - LyXParagraph * tmppar = buf; - while (tmppar){ - tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE; - tmppar = tmppar->next; - } + + // clear end/begin fragments of the first/last par in selection + bool all_erased = true; + + startpit->erase(startpos, startpit->size()); + if (startpit->size() != startpos) + all_erased = false; + + endpos -= endpit->erase(0, endpos); + if (endpos != 0) + all_erased = false; + + // Loop through the deleted pars if any, erasing as needed + + ParagraphList::iterator pit = boost::next(startpit); + + while (pit != endpit && pit != pars.end()) { + ParagraphList::iterator const next = boost::next(pit); + // "erase" the contents of the par + pit->erase(0, pit->size()); + if (!pit->size()) { + // remove the par if it's now empty + pars.erase(pit); + } else + all_erased = false; + pit = next; } -#endif +#if 0 // FIXME: why for cut but not copy ? // the cut selection should begin with standard layout - buf->Clear(); - - // paste the paragraphs again, if possible - if (doclear) - startpar->Next()->StripLeadingSpaces(textclass); -#ifndef NEW_INSETS - if (startpar->FirstPhysicalPar()->HasSameLayout(startpar->Next()) || -#else - if (startpar->HasSameLayout(startpar->Next()) || -#endif - !startpar->Next()->Last()) { - startpar->ParFromPos(start)->PasteParagraph(current_view->buffer()->params); - (*endpar) = startpar; // this because endpar gets deleted here! + if (realcut) { + buf->params().clear(); + buf->bibkey = 0; + buf->layout(textclasslist[buffer->params.textclass].defaultLayoutName()); } - } - return true; -} +#endif + if (boost::next(startpit) == pars.end()) + return PitPosPair(endpit, endpos); -bool CutAndPaste::copySelection(LyXParagraph * startpar, LyXParagraph * endpar, - int start, int end, char tc) -{ - if (!startpar || (start > startpar->Last())) - return false; - - DeleteBuffer(); - - textclass = tc; - - if (!(endpar) || (startpar->ParFromPos(start) == - (endpar)->ParFromPos(end))) { - // only within one paragraph - buf = new LyXParagraph; - LyXParagraph::size_type i = start; - if (end > startpar->Last()) - end = startpar->Last(); - for (; i < end; ++i) { - startpar->CopyIntoMinibuffer(current_view->buffer()->params, i); - buf->InsertFromMinibuffer(buf->Last()); - } - } else { - // copy more than one paragraph - // clone the paragraphs within the selection - LyXParagraph *tmppar = startpar->ParFromPos(start); - buf = tmppar->Clone(); - LyXParagraph *tmppar2 = buf; - - while (tmppar != endpar->ParFromPos(end) - && tmppar->next) { - tmppar = tmppar->next; - tmppar2->next = tmppar->Clone(); - tmppar2->next->previous = tmppar2; - tmppar2 = tmppar2->next; + if (doclear) { + boost::next(startpit)->stripLeadingSpaces(); } - tmppar2->next = 0; - -#ifndef NEW_INSETS - // care about footnotes - if (buf->footnoteflag) { - tmppar = buf; - while (tmppar) { - tmppar->footnoteflag = LyXParagraph::NO_FOOTNOTE; - tmppar = tmppar->next; - } + + // paste the paragraphs again, if possible + if (all_erased && + (startpit->hasSameLayout(*boost::next(startpit)) || + boost::next(startpit)->empty())) { + mergeParagraph(params, pars, startpit); + // this because endpar gets deleted here! + endpit = startpit; + endpos = startpos; } -#endif - - // the buf paragraph is too big - LyXParagraph::size_type tmpi2 = startpar->PositionInParFromPos(start); - for (; tmpi2; --tmpi2) - buf->Erase(0); - - // now tmppar 2 is too big, delete all after end - - tmpi2 = endpar->PositionInParFromPos(end); - while (tmppar2->size() > tmpi2) { - tmppar2->Erase(tmppar2->size() - 1); + + return PitPosPair(endpit, endpos); + +} + + +namespace { + +struct resetOwnerAndChanges { + void operator()(Paragraph & p) { + p.cleanChanges(); + p.setInsetOwner(0); } - } - return true; +}; + +} // anon namespace + +bool CutAndPaste::copySelection(ParagraphList::iterator startpit, + ParagraphList::iterator endpit, + int start, int end, textclass_type tc) +{ + Assert(0 <= start && start <= startpit->size()); + Assert(0 <= end && end <= endpit->size()); + Assert(startpit != endpit || start <= end); + + ParagraphList paragraphs; + + // Clone the paragraphs within the selection. + ParagraphList::iterator postend = boost::next(endpit); + + paragraphs.assign(startpit, postend); + for_each(paragraphs.begin(), paragraphs.end(), resetOwnerAndChanges()); + + // Cut out the end of the last paragraph. + Paragraph & back = paragraphs.back(); + back.erase(end, back.size()); + + // Cut out the begin of the first paragraph + Paragraph & front = paragraphs.front(); + front.erase(0, start); + + cuts.push(make_pair(paragraphs, tc)); + + return true; } -bool CutAndPaste::pasteSelection(LyXParagraph ** par, LyXParagraph ** endpar, - int & pos, char tc) +pair +CutAndPaste::pasteSelection(Buffer const & buffer, + ParagraphList & pars, + ParagraphList::iterator pit, int pos, + textclass_type tc, + ErrorList & errorlist) { - if (!checkPastePossible(*par, pos)) - return false; - - if (pos > (*par)->Last()) - pos = (*par)->Last(); - - LyXParagraph * tmpbuf; - LyXParagraph * tmppar = *par; - int tmppos = pos; - - // There are two cases: cutbuffer only one paragraph or many - if (!buf->next) { - // only within a paragraph - tmpbuf = buf->Clone(); -#ifndef NEW_TABULAR - /* table stuff -- begin */ - bool table_too_small = false; - if ((*par)->table) { - while (buf->size() && !table_too_small) { - if (buf->IsNewline(0)){ - while((tmppos < tmppar->Last()) && - !tmppar->IsNewline(tmppos)) - ++tmppos; - buf->Erase(0); - if (tmppos < tmppar->Last()) - ++tmppos; - else - table_too_small = true; - } else { - // This is an attempt to fix the - // "never insert a space at the - // beginning of a paragraph" problem. - if (!tmppos && buf->IsLineSeparator(0)) { - buf->Erase(0); - } else { - buf->CutIntoMinibuffer(current_view->buffer()->params, 0); - buf->Erase(0); - if (tmppar->InsertFromMinibuffer(tmppos)) - ++tmppos; - } - } - } - } else { - /* table stuff -- end */ -#endif - // Some provisions should be done here for checking - // if we are inserting at the beginning of a - // paragraph. If there are a space at the beginning - // of the text to insert and we are inserting at - // the beginning of the paragraph the space should - // be removed. - while (buf->size()) { - // This is an attempt to fix the - // "never insert a space at the - // beginning of a paragraph" problem. - if (!tmppos && buf->IsLineSeparator(0)) { - buf->Erase(0); - } else { - buf->CutIntoMinibuffer(current_view->buffer()->params, 0); - buf->Erase(0); - if (tmppar->InsertFromMinibuffer(tmppos)) - ++tmppos; + return pasteSelection(buffer, pars, pit, pos, tc, 0, errorlist); +} + + +pair +CutAndPaste::pasteSelection(Buffer const & buffer, + ParagraphList & pars, + ParagraphList::iterator pit, int pos, + textclass_type tc, size_t cut_index, + ErrorList & errorlist) +{ + if (!checkPastePossible()) + return make_pair(PitPosPair(pit, pos), pit); + + Assert (pos <= pit->size()); + + // Make a copy of the CaP paragraphs. + ParagraphList simple_cut_clone = cuts[cut_index].first; + textclass_type const textclass = cuts[cut_index].second; + + // Now remove all out of the pars which is NOT allowed in the + // new environment and set also another font if that is required. + + // Make sure there is no class difference. + SwitchLayoutsBetweenClasses(textclass, tc, simple_cut_clone, + errorlist); + + ParagraphList::iterator tmpbuf = simple_cut_clone.begin(); + int depth_delta = pit->params().depth() - tmpbuf->params().depth(); + + Paragraph::depth_type max_depth = pit->getMaxDepthAfter(); + + for (; tmpbuf != simple_cut_clone.end(); ++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 level so that subsequent + // paragraphs are aligned correctly to this paragraph + // at level 0. + if ((int(tmpbuf->params().depth()) + depth_delta) < 0) + depth_delta = 0; + + // Set the right depth so that we are not too deep or shallow. + tmpbuf->params().depth(tmpbuf->params().depth() + depth_delta); + if (tmpbuf->params().depth() > max_depth) + tmpbuf->params().depth(max_depth); + + // Only set this from the 2nd on as the 2nd depends + // for maxDepth still on pit. + if (tmpbuf != simple_cut_clone.begin()) + max_depth = tmpbuf->getMaxDepthAfter(); + + // Set the inset owner of this paragraph. + tmpbuf->setInsetOwner(pit->inInset()); + for (pos_type i = 0; i < tmpbuf->size(); ++i) { + if (tmpbuf->getChar(i) == Paragraph::META_INSET) { + if (!pit->insetAllowed(tmpbuf->getInset(i)->lyxCode())) { + tmpbuf->erase(i--); + } + } else { + LyXFont f1 = tmpbuf->getFont(buffer.params, i, outerFont(pit, pars)); + LyXFont f2 = f1; + if (!pit->checkInsertChar(f1)) { + tmpbuf->erase(i--); + } else if (f1 != f2) { + tmpbuf->setFont(i, f1); + } + } } - } -#ifndef NEW_TABULAR } -#endif - delete buf; - buf = tmpbuf; - *endpar = tmppar->Next(); - pos = tmppos; - } else { - // many paragraphs - - // make a copy of the simple cut_buffer - tmpbuf = buf; - LyXParagraph * simple_cut_clone = tmpbuf->Clone(); - LyXParagraph * tmpbuf2 = simple_cut_clone; -#ifndef NEW_INSETS - if ((*par)->footnoteflag){ - tmpbuf->footnoteflag = (*par)->footnoteflag; - tmpbuf->footnotekind = (*par)->footnotekind; - } -#endif - while (tmpbuf->next) { - tmpbuf = tmpbuf->next; - tmpbuf2->next = tmpbuf->Clone(); - tmpbuf2->next->previous = tmpbuf2; - tmpbuf2 = tmpbuf2->next; -#ifndef NEW_INSETS - if ((*par)->footnoteflag){ - tmpbuf->footnoteflag = (*par)->footnoteflag; - tmpbuf->footnotekind = (*par)->footnotekind; - } -#endif + + // Make the buf exactly the same layout than + // the cursor paragraph. + simple_cut_clone.begin()->makeSameLayout(*pit); + + // Prepare the paragraphs and insets for insertion + // A couple of insets store buffer references so need + // updating + ParIterator fpit(simple_cut_clone.begin(), simple_cut_clone); + ParIterator fend(simple_cut_clone.end(), simple_cut_clone); + + for (; fpit != fend; ++fpit) { + InsetList::iterator lit = fpit->insetlist.begin(); + InsetList::iterator eit = fpit->insetlist.end(); + + for (; lit != eit; ++lit) { + switch (lit->inset->lyxCode()) { + case InsetOld::INCLUDE_CODE: { + InsetInclude * ii = static_cast(lit->inset); + InsetInclude::Params ip = ii->params(); + ip.masterFilename_ = buffer.fileName(); + ii->set(ip); + break; + } + + case InsetOld::TABULAR_CODE: { + InsetTabular * it = static_cast(lit->inset); + it->buffer(const_cast(&buffer)); + break; + } + + default: + break; // nothing + } + } } - - // make sure there is no class difference - SwitchLayoutsBetweenClasses(textclass, tc, buf); - - // make the buf exactly the same layout than - // the cursor paragraph - buf->MakeSameLayout(*par); - - // find the end of the buffer - LyXParagraph * lastbuffer = buf; - while (lastbuffer->Next()) - lastbuffer = lastbuffer->Next(); - + bool paste_the_end = false; - - // open the paragraph for inserting the buf - // if necessary - if (((*par)->Last() > pos) || !(*par)->Next()) { - (*par)->BreakParagraphConservative(current_view->buffer()->params, - pos); - paste_the_end = true; + + // Open the paragraph for inserting the buf + // if necessary. + if (pit->size() > pos || boost::next(pit) == pars.end()) { + breakParagraphConservative(buffer.params, + pars, pit, pos); + paste_the_end = true; } - - // set the end for redoing later - *endpar = (*par)->ParFromPos(pos)->next->Next(); - - // paste it! - lastbuffer->ParFromPos(lastbuffer->Last())->next = - (*par)->ParFromPos(pos)->next; - (*par)->ParFromPos(pos)->next->previous = - lastbuffer->ParFromPos(lastbuffer->Last()); - - (*par)->ParFromPos(pos)->next = buf; - buf->previous = (*par)->ParFromPos(pos); - - if ((*par)->ParFromPos(pos)->Next() == lastbuffer) - lastbuffer = *par; - - (*par)->ParFromPos(pos)->PasteParagraph(current_view->buffer()->params); - - // store the new cursor position - *par = lastbuffer; - pos = lastbuffer->Last(); - - // maybe some pasting - if (lastbuffer->Next() && paste_the_end) { - if (lastbuffer->Next()->HasSameLayout(lastbuffer)) { - lastbuffer->ParFromPos(lastbuffer->Last())->PasteParagraph(current_view->buffer()->params); - } else if (!lastbuffer->Next()->Last()) { - lastbuffer->Next()->MakeSameLayout(lastbuffer); - lastbuffer->ParFromPos(lastbuffer->Last())->PasteParagraph(current_view->buffer()->params); - } else if (!lastbuffer->Last()) { - lastbuffer->MakeSameLayout(lastbuffer->next); - lastbuffer->ParFromPos(lastbuffer->Last())->PasteParagraph(current_view->buffer()->params); - } else - lastbuffer->Next()->StripLeadingSpaces(tc); + + // Set the end for redoing later. + ParagraphList::iterator endpit = boost::next(boost::next(pit)); + + // Paste it! + + ParagraphList::iterator past_pit = boost::next(pit); + pars.splice(past_pit, simple_cut_clone); + ParagraphList::iterator last_paste = boost::prior(past_pit); + + // If we only inserted one paragraph. + if (boost::next(pit) == last_paste) + last_paste = pit; + + mergeParagraph(buffer.params, pars, pit); + + // Store the new cursor position. + pit = last_paste; + pos = last_paste->size(); + + // Maybe some pasting. +#warning CHECK! Are we comparing last_paste to the wrong list here? (Lgb) + if (boost::next(last_paste) != pars.end() && + paste_the_end) { + if (boost::next(last_paste)->hasSameLayout(*last_paste)) { + mergeParagraph(buffer.params, pars, + last_paste); + } else if (boost::next(last_paste)->empty()) { + boost::next(last_paste)->makeSameLayout(*last_paste); + mergeParagraph(buffer.params, pars, + last_paste); + } else if (last_paste->empty()) { + last_paste->makeSameLayout(*boost::next(last_paste)); + mergeParagraph(buffer.params, pars, + last_paste); + } else + boost::next(last_paste)->stripLeadingSpaces(); } - // restore the simple cut buffer - buf = simple_cut_clone; - } - return true; + return make_pair(PitPosPair(pit, pos), endpit); } -int CutAndPaste::nrOfParagraphs() const +int CutAndPaste::nrOfParagraphs() { - if (!buf) return 0; - - int n = 1; - LyXParagraph * tmppar = buf; - while(tmppar->next) { - ++n; - tmppar = tmppar->next; - } - return n; + return cuts.empty() ? 0 : cuts[0].first.size(); } -int CutAndPaste::SwitchLayoutsBetweenClasses(LyXTextClassList::size_type c1, - LyXTextClassList::size_type c2, - LyXParagraph * par) +int CutAndPaste::SwitchLayoutsBetweenClasses(textclass_type c1, + textclass_type c2, + ParagraphList & pars, + ErrorList & errorlist) { - int ret = 0; - if (!par || c1 == c2) - return ret; -#ifndef NEW_INSETS - par = par->FirstPhysicalPar(); -#endif - while (par) { - string name = textclasslist.NameOfLayout(c1, par->layout); - int lay = 0; - pair pp = - textclasslist.NumberOfLayout(c2, name); - if (pp.first) { - lay = pp.second; - } else { // layout not found - // use default layout "Standard" (0) - lay = 0; - } - par->layout = lay; - - if (name != textclasslist.NameOfLayout(c2, par->layout)) { - ++ret; - string s = _("Layout had to be changed from\n") - + name + _(" to ") - + textclasslist.NameOfLayout(c2, par->layout) - + _("\nbecause of class conversion from\n") - + textclasslist.NameOfClass(c1) + _(" to ") - + textclasslist.NameOfClass(c2); - InsetError * new_inset = new InsetError(s); - par->InsertInset(0, new_inset); + Assert(!pars.empty()); + + int ret = 0; + if (c1 == c2) + return ret; + + LyXTextClass const & tclass1 = textclasslist[c1]; + LyXTextClass const & tclass2 = textclasslist[c2]; + ParIterator end = ParIterator(pars.end(), pars); + for (ParIterator it = ParIterator(pars.begin(), pars); it != end; ++it) { + string const name = it->layout()->name(); + bool hasLayout = tclass2.hasLayout(name); + + if (hasLayout) + it->layout(tclass2[name]); + else + it->layout(tclass2.defaultLayout()); + + if (!hasLayout && name != tclass1.defaultLayoutName()) { + ++ret; + string 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"), + name, it->layout()->name(), tclass1.name(), tclass2.name()); + // To warn the user that something had to be done. + errorlist.push_back(ErrorItem("Changed Layout", s, + it->id(), 0, + it->size())); + } } - - par = par->next; - } - return ret; + return ret; } -bool CutAndPaste::checkPastePossible(LyXParagraph * par, int) const +bool CutAndPaste::checkPastePossible() { - if (!buf) return false; - -#ifndef NEW_INSETS - // be carefull with footnotes in footnotes - if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE) { - // check whether the cut_buffer includes a footnote - LyXParagraph * tmppar = buf; - while (tmppar && tmppar->footnoteflag == LyXParagraph::NO_FOOTNOTE) - tmppar = tmppar->next; - - if (tmppar) { - WriteAlert(_("Impossible operation"), - _("Can't paste float into float!"), - _("Sorry.")); - return false; - } - } -#endif -#ifndef NEW_TABULAR - /* table stuff -- begin */ - if (par->table) { - if (buf->next) { - WriteAlert(_("Impossible operation"), - _("Table cell cannot include more than one paragraph!"), - _("Sorry.")); - return false; - } - } - /* table stuff -- end */ -#endif - return true; + return !cuts.empty() && !cuts[0].first.empty(); }