+2003-04-29 Alfredo Braunstein <abraunst@libero.it>
+ * CutAndPaste.C (cutSelection): big rework, some bugs fixed
+
2003-04-29 André Pönitz <poenitz@gmx.net>
* ParagraphList.C: whitespace
} // namespace anon
+typedef std::pair<ParagraphList::iterator, int> 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;
}
}
#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);
+
}
#define CUTANDPASTE_H
#include "support/types.h"
+#include "ParagraphList.h"
class Paragraph;
class BufferParams;
///
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<ParagraphList::iterator, int>
+cutSelection(ParagraphList & pars,
+ ParagraphList::iterator startpit,
+ ParagraphList::iterator endpit,
+ int start, int end, lyx::textclass_type tc,
+ bool doclear = false);
+///
+std::pair<ParagraphList::iterator, int>
+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);
}
-bool Paragraph::erase(pos_type start, pos_type end)
+int Paragraph::erase(pos_type start, pos_type end)
{
return pimpl_->erase(start, end);
}
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.
}
-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;
}
/// 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;
#include "support/lstrings.h"
#include "support/BoostFormat.h"
+#include <boost/tuple/tuple.hpp>
using std::vector;
using std::copy;
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();
// 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();