mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-29 21:05:12 +00:00
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:
parent
4d1bbfdd26
commit
76d84c61fd
@ -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>
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
59
src/text2.C
59
src/text2.C
@ -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,16 +1626,17 @@ 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 &&
|
||||
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()))
|
||||
{
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user