From: André Pönitz Date: Tue, 29 Apr 2003 09:40:49 +0000 (+0000) Subject: Alfredo's CutAndPaste fixes X-Git-Tag: 1.6.10~16903 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=76d84c61fd406f9c0c12969e1d2b182e7039e912;p=features.git Alfredo's CutAndPaste fixes git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@6877 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/ChangeLog b/src/ChangeLog index 67e9158f2a..b9a28840fd 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,4 +1,7 @@ +2003-04-29 Alfredo Braunstein + * CutAndPaste.C (cutSelection): big rework, some bugs fixed + 2003-04-29 André Pönitz * ParagraphList.C: whitespace diff --git a/src/CutAndPaste.C b/src/CutAndPaste.C index 8d76ec1df3..e0312bdaeb 100644 --- a/src/CutAndPaste.C +++ b/src/CutAndPaste.C @@ -61,64 +61,57 @@ textclass_type textclass = 0; } // namespace anon +typedef std::pair pitPosPair; -bool CutAndPaste::cutSelection(Paragraph * startpar, Paragraph * endpar, - int start, int & end, textclass_type tc, - bool doclear, bool realcut) +pitPosPair CutAndPaste::cutSelection(ParagraphList & pars, + ParagraphList::iterator startpit, + ParagraphList::iterator endpit, + int startpos, int endpos, + textclass_type tc, bool doclear) { - if (!startpar || (start > startpar->size())) - return false; + copySelection(&*startpit, &*endpit, startpos, endpos, tc); + return eraseSelection(pars, startpit, endpit, startpos, + endpos, doclear); +} - if (realcut) { - copySelection(startpar, endpar, start, end, tc); - } - if (!endpar || startpar == endpar) { - if (startpar->erase(start, end)) { - // Some chars were erased, go to start to be safe - end = start; - } - return true; - } +pitPosPair CutAndPaste::eraseSelection(ParagraphList & pars, + ParagraphList::iterator startpit, + ParagraphList::iterator endpit, + int startpos, int endpos, bool doclear) +{ + if (startpit == pars.end() || (startpos > startpit->size())) + return pitPosPair(endpit, endpos); - bool actually_erased = false; + if (endpit == pars.end() || startpit == endpit) { + endpos -= startpit->erase(startpos, endpos); + return pitPosPair(endpit, endpos); + } // 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; - } + bool all_erased = true; - // Loop through the deleted pars if any, erasing as needed + startpit->erase(startpos, startpit->size()); + if (startpit->size() != startpos) + all_erased = false; - Paragraph * pit = startpar->next(); + endpos -= endpit->erase(0, endpos); + if (endpos != 0) + all_erased = false; - while (true) { - // *endpar can be 0 - if (!pit) - break; + // Loop through the deleted pars if any, erasing as needed - Paragraph * next = pit->next(); + 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 - if (pit != endpar) { - actually_erased |= pit->erase(0, pit->size()); - + pit->erase(0, pit->size()); + if (!pit->size()) { // remove the par if it's now empty - if (actually_erased) { - pit->previous()->next(pit->next()); - if (next) { - next->previous(pit->previous()); - } - - delete pit; - } - } - - if (pit == endpar) - break; - + pars.erase(pit); + } else + all_erased = false; pit = next; } @@ -131,31 +124,28 @@ bool CutAndPaste::cutSelection(Paragraph * startpar, Paragraph * endpar, } #endif - if (!startpar->next()) - return true; - - Buffer * buffer = current_view->buffer(); + if (boost::next(startpit) == pars.end()) + return pitPosPair(endpit, endpos); if (doclear) { - startpar->next()->stripLeadingSpaces(); + boost::next(startpit)->stripLeadingSpaces(); } - if (!actually_erased) - return true; - // paste the paragraphs again, if possible - if (startpar->hasSameLayout(startpar->next()) || - startpar->next()->empty()) { -#warning This is suspect. (Lgb) - // When doing this merge we must know if the par really - // belongs to an inset, and if it does then we have to use - // the insets paragraphs, and not the buffers. (Lgb) - mergeParagraph(buffer->params, buffer->paragraphs, startpar); + if (all_erased && + (startpit->hasSameLayout(&*boost::next(startpit)) || + boost::next(startpit)->empty())) { +#warning current_view used here. +// should we pass buffer or buffer->params around? + Buffer * buffer = current_view->buffer(); + mergeParagraph(buffer->params, pars, &*startpit); // this because endpar gets deleted here! - endpar = startpar; + endpit = startpit; + endpos = startpos; } - return true; + return pitPosPair(endpit, endpos); + } diff --git a/src/CutAndPaste.h b/src/CutAndPaste.h index 61b0402152..e27cb4ccbe 100644 --- a/src/CutAndPaste.h +++ b/src/CutAndPaste.h @@ -12,6 +12,7 @@ #define CUTANDPASTE_H #include "support/types.h" +#include "ParagraphList.h" class Paragraph; class BufferParams; @@ -19,12 +20,19 @@ class LyXTextClass; /// namespace CutAndPaste { - -/// realcut == false is we actually want a delete -bool cutSelection(Paragraph * startpar, Paragraph * endpar, - int start, int & end, lyx::textclass_type tc, - bool doclear = false, bool realcut = true); - +/// +std::pair +cutSelection(ParagraphList & pars, + ParagraphList::iterator startpit, + ParagraphList::iterator endpit, + int start, int end, lyx::textclass_type tc, + bool doclear = false); +/// +std::pair +eraseSelection(ParagraphList & pars, + ParagraphList::iterator startpit, + ParagraphList::iterator endpit, + int start, int end, bool doclear = false); /// bool copySelection(Paragraph * startpar, Paragraph * endpar, int start, int end, lyx::textclass_type tc); diff --git a/src/paragraph.C b/src/paragraph.C index 6f21d609c2..863e373468 100644 --- a/src/paragraph.C +++ b/src/paragraph.C @@ -330,7 +330,7 @@ void Paragraph::erase(pos_type pos) } -bool Paragraph::erase(pos_type start, pos_type end) +int Paragraph::erase(pos_type start, pos_type end) { return pimpl_->erase(start, end); } diff --git a/src/paragraph.h b/src/paragraph.h index 1842cd558e..8281ef0d26 100644 --- a/src/paragraph.h +++ b/src/paragraph.h @@ -219,8 +219,8 @@ public: void eraseIntern(lyx::pos_type pos); /// erase the char at the given position void erase(lyx::pos_type pos); - /// erase the given range. Returns true if actually erased. - bool erase(lyx::pos_type start, lyx::pos_type end); + /// erase the given range. Returns the number of chars actually erased + int erase(lyx::pos_type start, lyx::pos_type end); /** Get uninstantiated font setting. Returns the difference between the characters font and the layoutfont. diff --git a/src/paragraph_pimpl.C b/src/paragraph_pimpl.C index 16a57fee5d..a29dd64185 100644 --- a/src/paragraph_pimpl.C +++ b/src/paragraph_pimpl.C @@ -409,21 +409,17 @@ void Paragraph::Pimpl::erase(pos_type pos) } -bool Paragraph::Pimpl::erase(pos_type start, pos_type end) +int Paragraph::Pimpl::erase(pos_type start, pos_type end) { pos_type i = start; pos_type count = end - start; - bool any_erased = false; - while (count) { if (!erasePos(i)) { ++i; - } else { - any_erased = true; - } + } --count; } - return any_erased; + return end - i; } diff --git a/src/paragraph_pimpl.h b/src/paragraph_pimpl.h index 0031c56635..63e4f735e7 100644 --- a/src/paragraph_pimpl.h +++ b/src/paragraph_pimpl.h @@ -82,7 +82,7 @@ struct Paragraph::Pimpl { /// erase the given position void erase(lyx::pos_type pos); /// erase the given range - bool erase(lyx::pos_type start, lyx::pos_type end); + int erase(lyx::pos_type start, lyx::pos_type end); /// Inset * inset_owner; diff --git a/src/text2.C b/src/text2.C index 4d2e015154..940b08820d 100644 --- a/src/text2.C +++ b/src/text2.C @@ -40,6 +40,7 @@ #include "support/lstrings.h" #include "support/BoostFormat.h" +#include using std::vector; using std::copy; @@ -1309,41 +1310,34 @@ void LyXText::cutSelection(bool doclear, bool realcut) setUndo(bv(), Undo::DELETE, &*selection.start.par(), &*undoendpit); - // there are two cases: cut only within one paragraph or - // more than one paragraph - if (selection.start.par() == selection.end.par()) { - // only within one paragraph - endpit = selection.end.par(); - int pos = selection.end.pos(); - CutAndPaste::cutSelection(&*selection.start.par(), &*endpit, - selection.start.pos(), pos, - bv()->buffer()->params.textclass, - doclear, realcut); - selection.end.pos(pos); - } else { - endpit = selection.end.par(); - int pos = selection.end.pos(); - CutAndPaste::cutSelection(&*selection.start.par(), &*endpit, - selection.start.pos(), pos, - bv()->buffer()->params.textclass, - doclear, realcut); - cursor.par(endpit); - selection.end.par(endpit); - selection.end.pos(pos); - cursor.pos(selection.end.pos()); - } - ++endpit; + endpit = selection.end.par(); + int endpos = selection.end.pos(); + + boost::tie(endpit, endpos) = realcut ? + CutAndPaste::cutSelection(ownerParagraphs(), + selection.start.par(), endpit, + selection.start.pos(), endpos, + bv()->buffer()->params.textclass, + doclear) + : CutAndPaste::eraseSelection(ownerParagraphs(), + selection.start.par(), endpit, + selection.start.pos(), endpos, + doclear); // sometimes necessary if (doclear) selection.start.par()->stripLeadingSpaces(); - redoParagraphs(selection.start, endpit); - + redoParagraphs(selection.start, boost::next(endpit)); +#warning FIXME latent bug + // endpit will be invalidated on redoParagraphs once ParagraphList + // becomes a std::list? There are maybe other places on which this + // can happend? (Ab) // cutSelection can invalidate the cursor so we need to set // it anew. (Lgb) // we prefer the end for when tracking changes - cursor = selection.end; + cursor.pos(endpos); + cursor.par(endpit); // need a valid cursor. (Lgb) clearSelection(); @@ -1632,17 +1626,18 @@ void LyXText::setCursor(LyXCursor & cur, ParagraphList::iterator pit, // same paragraph and there is a previous row then put the cursor on // the end of the previous row cur.iy(y + row->baseline()); - Inset * ins; - if (row != beg && pos && - boost::prior(row)->par() == row->par() && - pos < pit->size() && - pit->getChar(pos) == Paragraph::META_INSET && - (ins = pit->getInset(pos)) && (ins->needFullRow() || ins->display())) - { - --row; - y -= row->height(); + if (row != beg && + pos && + boost::prior(row)->par() == row->par() && + pos < pit->size() && + pit->getChar(pos) == Paragraph::META_INSET) { + Inset * ins = pit->getInset(pos); + if (ins && (ins->needFullRow() || ins->display())) { + --row; + y -= row->height(); + } } - + cur.row(row); // y is now the beginning of the cursor row y += row->baseline();