Alfredo's CutAndPaste fixes

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@6877 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
André Pönitz 2003-04-29 09:40:49 +00:00
parent 4d1bbfdd26
commit 76d84c61fd
8 changed files with 109 additions and 117 deletions

View File

@ -1,3 +1,6 @@
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>

View File

@ -61,64 +61,57 @@ textclass_type textclass = 0;
} // 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);
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);
if (endpit == pars.end() || startpit == endpit) {
endpos -= startpit->erase(startpos, endpos);
return pitPosPair(endpit, endpos);
}
if (!endpar || startpar == endpar) {
if (startpar->erase(start, end)) {
// Some chars were erased, go to start to be safe
end = start;
}
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;
}
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
Paragraph * pit = startpar->next();
while (true) {
// *endpar can be 0
if (!pit)
break;
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);
}

View File

@ -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<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);

View File

@ -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);
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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;

View File

@ -40,6 +40,7 @@
#include "support/lstrings.h"
#include "support/BoostFormat.h"
#include <boost/tuple/tuple.hpp>
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,15 +1626,16 @@ 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() &&
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();
pit->getChar(pos) == Paragraph::META_INSET) {
Inset * ins = pit->getInset(pos);
if (ins && (ins->needFullRow() || ins->display())) {
--row;
y -= row->height();
}
}
cur.row(row);