John's InsetTabular cursor patch and modifications/fixes to undo/redo code.

TODO: Still some problems in multiparagraph redo! And deleting of substituted
      paragraphs when undoing/redoing.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@3209 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Jürgen Vigna 2001-12-14 11:55:58 +00:00
parent 039a64bb48
commit 7fdf62dd8e
12 changed files with 304 additions and 175 deletions

View File

@ -249,10 +249,12 @@ void BufferView::menuUndo()
void BufferView::menuRedo()
{
#if 0 // this should not be here (Jug 20011206)
if (theLockingInset()) {
owner()->message(_("Redo not yet supported in math mode"));
return;
}
}
#endif
if (available()) {
owner()->message(_("Redo"));
@ -398,16 +400,46 @@ void BufferView::replaceWord(string const & replacestring)
bool BufferView::lockInset(UpdatableInset * inset)
{
if (!inset)
return false;
// don't relock if we're already locked
if (theLockingInset() == inset)
return true;
if (!theLockingInset() && inset) {
theLockingInset(inset);
return true;
} else if (inset) {
return theLockingInset()->lockInsetInInset(this, inset);
if (!theLockingInset()) {
// first check if it's the inset under the cursor we want lock
// should be most of the time
char const c = text->cursor.par()->getChar(text->cursor.pos());
if (c == Paragraph::META_INSET) {
Inset * in = text->cursor.par()->getInset(text->cursor.pos());
if (inset == in) {
theLockingInset(inset);
return true;
}
}
// Then do a deep look of the inset and lock the right one
Paragraph * par = buffer()->paragraph;
int const id = inset->id();
while(par) {
Paragraph::inset_iterator it =
par->inset_iterator_begin();
Paragraph::inset_iterator const end =
par->inset_iterator_end();
for (; it != end; ++it) {
if ((*it) == inset) {
theLockingInset(inset);
return true;
}
if ((*it)->getInsetFromID(id)) {
text->setCursorIntern(this, par, it.getPos());
theLockingInset(static_cast<UpdatableInset *>(*it));
return theLockingInset()->lockInsetInInset(this, inset);
}
}
par = par->next();
}
return false;
}
return false;
return theLockingInset()->lockInsetInInset(this, inset);
}
@ -461,6 +493,8 @@ void BufferView::fitLockedInsetCursor(int x, int y, int asc, int desc)
int BufferView::unlockInset(UpdatableInset * inset)
{
if (!inset)
return 0;
if (inset && theLockingInset() == inset) {
inset->insetUnlock(this);
theLockingInset(0);

View File

@ -1,3 +1,16 @@
2001-12-13 Juergen Vigna <jug@sad.it>
* undo_funcs.C (textRedo/Undo): fixed as the first paragraph was
actually sometimes the before-paragraph.
(setUndo): don't clear the redostack if we're not actually undoing!
2001-12-06 Juergen Vigna <jug@sad.it>
* undo_funcs.C (textHandleUndo): well after John's hint I got here
and fixed redoing of main paragraph, so we can use it now ;)
* text2.C (redoParagraphs): fixed a crash when having only 1 row!
2001-12-13 Jean-Marc Lasgouttes <lasgouttes@freesurf.fr>
* undo_funcs.C (textHandleUndo): undo undo leak fix below, as per

View File

@ -1,3 +1,14 @@
2001-12-07 Juergen Vigna <jug@sad.it>
* insettext.C (paragraph): remove the deleteing of paragraphs as
it was a WRONG move!
2001-12-06 John Levon <moz@compsoc.man.ac.uk>
* insettabular.h:
* insettabular.C: use new setSelection(). Allow
selection of single cells.
2001-12-12 Jean-Marc Lasgouttes <lasgouttes@freesurf.fr>
* insetquotes.C (latex): fix to use the local language setting at

View File

@ -464,7 +464,7 @@ public:
{ return false; }
///
virtual bool unlockInsetInInset(BufferView *, UpdatableInset *,
bool /*lr*/ = false)
bool /*lr*/ = false)
{ return false; }
/// An updatable inset could handle lyx editing commands
virtual RESULT localDispatch(BufferView *, kb_action, string const &);

View File

@ -83,7 +83,7 @@ public:
bool lockInsetInInset(BufferView *, UpdatableInset *);
///
bool unlockInsetInInset(BufferView *, UpdatableInset *,
bool lr = false);
bool lr = false);
///
bool updateInsetInInset(BufferView *, Inset *);
///

View File

@ -134,7 +134,7 @@ InsetTabular::InsetTabular(Buffer const & buf, int rows, int columns)
// for now make it always display as display() inset
// just for test!!!
the_locking_inset = 0;
locked = no_selection = false;
locked = false;
oldcell = -1;
actrow = actcell = 0;
clearSelection();
@ -150,10 +150,10 @@ InsetTabular::InsetTabular(InsetTabular const & tab, Buffer const & buf,
{
tabular.reset(new LyXTabular(this, *(tab.tabular), same_id));
the_locking_inset = 0;
locked = no_selection = false;
locked = false;
oldcell = -1;
actrow = actcell = 0;
sel_cell_start = sel_cell_end = 0;
clearSelection();
need_update = INIT;
in_update = false;
in_reset_pos = false;
@ -296,11 +296,11 @@ void InsetTabular::draw(BufferView * bv, LyXFont const & font, int baseline,
cx = nx + tabular->GetBeginningOfTextInCell(cell);
if (first_visible_cell < 0)
first_visible_cell = cell;
if (hasSelection())
if (hasSelection()) {
drawCellSelection(pain, nx, baseline, i, j, cell);
}
tabular->GetCellInset(cell)->draw(bv, font, baseline, cx,
cleared);
tabular->GetCellInset(cell)->draw(bv, font, baseline, cx, cleared);
drawCellLines(pain, nx, baseline, i, cell);
nx += tabular->GetWidthOfColumn(cell);
++cell;
@ -448,6 +448,7 @@ void InsetTabular::drawCellLines(Painter & pain, int x, int baseline,
void InsetTabular::drawCellSelection(Painter & pain, int x, int baseline,
int row, int column, int cell) const
{
lyx::Assert(hasSelection());
int cs = tabular->column_of_cell(sel_cell_start);
int ce = tabular->column_of_cell(sel_cell_end);
if (cs > ce) {
@ -534,7 +535,7 @@ void InsetTabular::edit(BufferView * bv, int x, int y, unsigned int button)
inset_x = 0;
inset_y = 0;
setPos(bv, x, y);
sel_cell_start = sel_cell_end = actcell;
clearSelection();
finishUndo();
if (insetHit(bv, x, y) && (button != 3)) {
activateCellInsetAbs(bv, x, y, button);
@ -558,7 +559,7 @@ void InsetTabular::edit(BufferView * bv, bool front)
actcell = 0;
else
actcell = tabular->GetNumberOfCells() - 1;
sel_cell_start = sel_cell_end = actcell;
clearSelection();
resetPos(bv);
finishUndo();
}
@ -571,11 +572,10 @@ void InsetTabular::insetUnlock(BufferView * bv)
the_locking_inset = 0;
}
hideInsetCursor(bv);
no_selection = false;
oldcell = -1;
locked = false;
if (scroll(false) || hasSelection()) {
sel_cell_start = sel_cell_end = 0;
clearSelection();
if (scroll(false)) {
scroll(bv, 0.0F);
}
@ -593,8 +593,9 @@ void InsetTabular::updateLocal(BufferView * bv, UpdateCodes what,
}
if (need_update < what) // only set this if it has greater update
need_update = what;
if ((what == INIT) && hasSelection())
if ((what == INIT) && hasSelection()) {
clearSelection();
}
// Dirty Cast! (Lgb)
if (need_update != NONE) {
bv->updateInset(const_cast<InsetTabular *>(this), mark_dirty);
@ -616,6 +617,26 @@ bool InsetTabular::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
the_locking_inset = tabular->GetCellInset(actcell);
resetPos(bv);
return true;
} else if (!the_locking_inset) {
int const n = tabular->GetNumberOfCells();
int const id = inset->id();
for (int i = 0; i < n; ++i) {
InsetText * in = tabular->GetCellInset(i);
if (inset == in) {
actcell = i;
the_locking_inset = in;
locked = true;
resetPos(bv);
return true;
}
if (in->getInsetFromID(id)) {
actcell = i;
the_locking_inset = in;
locked = true;
resetPos(bv);
return the_locking_inset->lockInsetInInset(bv, inset);
}
}
} else if (the_locking_inset && (the_locking_inset == inset)) {
lyxerr[Debug::INSETTEXT] << "OK" << endl;
resetPos(bv);
@ -716,8 +737,6 @@ void InsetTabular::insetButtonPress(BufferView * bv, int x, int y, int button)
updateLocal(bv, SELECTION, false);
}
no_selection = false;
int const ocell = actcell;
int const orow = actrow;
@ -725,7 +744,7 @@ void InsetTabular::insetButtonPress(BufferView * bv, int x, int y, int button)
setPos(bv, x, y);
if (actrow != orow)
updateLocal(bv, NONE, false);
sel_cell_start = sel_cell_end = actcell;
clearSelection();
if (button == 3) {
if ((ocell != actcell) && the_locking_inset) {
the_locking_inset->insetUnlock(bv);
@ -783,7 +802,6 @@ void InsetTabular::insetButtonRelease(BufferView * bv,
button);
return;
}
no_selection = false;
}
@ -796,17 +814,18 @@ void InsetTabular::insetMotionNotify(BufferView * bv, int x, int y, int button)
button);
return;
}
if (!no_selection) {
hideInsetCursor(bv);
int const old_cell = actcell;
setPos(bv, x, y);
sel_cell_end = actcell;
if (sel_cell_end != old_cell)
updateLocal(bv, SELECTION, false);
showInsetCursor(bv);
hideInsetCursor(bv);
// int const old_cell = actcell;
setPos(bv, x, y);
if (!hasSelection()) {
setSelection(actcell, actcell);
} else {
setSelection(sel_cell_start, actcell);
}
no_selection = false;
updateLocal(bv, SELECTION, false);
showInsetCursor(bv);
}
@ -826,7 +845,6 @@ InsetTabular::localDispatch(BufferView * bv, kb_action action,
// We need to save the value of the_locking_inset as the call to
// the_locking_inset->LocalDispatch might unlock it.
old_locking_inset = the_locking_inset;
no_selection = false;
UpdatableInset::RESULT result =
UpdatableInset::localDispatch(bv, action, arg);
if (result == DISPATCHED || result == DISPATCHED_NOUPDATE) {
@ -852,7 +870,7 @@ InsetTabular::localDispatch(BufferView * bv, kb_action action,
moveNextCell(bv, old_locking_inset != 0);
else
movePrevCell(bv, old_locking_inset != 0);
sel_cell_start = sel_cell_end = actcell;
clearSelection();
if (hs)
updateLocal(bv, SELECTION, false);
if (!the_locking_inset) {
@ -895,65 +913,96 @@ InsetTabular::localDispatch(BufferView * bv, kb_action action,
result=DISPATCHED;
switch (action) {
// --- Cursor Movements ----------------------------------
case LFUN_RIGHTSEL:
if (tabular->IsLastCellInRow(actcell))
case LFUN_RIGHTSEL: {
int const start = hasSelection() ? sel_cell_start : actcell;
if (tabular->IsLastCellInRow(actcell)) {
setSelection(start, actcell);
break;
moveRight(bv, false);
sel_cell_end = actcell;
}
int end = actcell;
// if we are starting a selection, only select
// the current cell at the beginning
if (hasSelection()) {
moveRight(bv, false);
end = actcell;
}
setSelection(start, end);
updateLocal(bv, SELECTION, false);
break;
}
case LFUN_RIGHT:
result = moveRight(bv);
sel_cell_start = sel_cell_end = actcell;
clearSelection();
if (hs)
updateLocal(bv, SELECTION, false);
break;
case LFUN_LEFTSEL:
if (tabular->IsFirstCellInRow(actcell))
case LFUN_LEFTSEL: {
int const start = hasSelection() ? sel_cell_start : actcell;
if (tabular->IsFirstCellInRow(actcell)) {
setSelection(start, actcell);
break;
moveLeft(bv, false);
sel_cell_end = actcell;
}
int end = actcell;
// if we are starting a selection, only select
// the current cell at the beginning
if (hasSelection()) {
moveLeft(bv, false);
end = actcell;
}
setSelection(start, end);
updateLocal(bv, SELECTION, false);
break;
}
case LFUN_LEFT:
result = moveLeft(bv);
sel_cell_start = sel_cell_end = actcell;
clearSelection();
if (hs)
updateLocal(bv, SELECTION, false);
break;
case LFUN_DOWNSEL:
{
case LFUN_DOWNSEL: {
int const start = hasSelection() ? sel_cell_start : actcell;
int const ocell = actcell;
moveDown(bv, false);
// if we are starting a selection, only select
// the current cell at the beginning
if (hasSelection()) {
moveDown(bv, false);
}
if ((ocell == sel_cell_end) ||
(tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
sel_cell_end = tabular->GetCellBelow(sel_cell_end);
setSelection(start, tabular->GetCellBelow(sel_cell_end));
else
sel_cell_end = tabular->GetLastCellBelow(sel_cell_end);
setSelection(start, tabular->GetLastCellBelow(sel_cell_end));
updateLocal(bv, SELECTION, false);
}
break;
case LFUN_DOWN:
result = moveDown(bv, old_locking_inset != 0);
sel_cell_start = sel_cell_end = actcell;
if (hs)
clearSelection();
if (hs) {
updateLocal(bv, SELECTION, false);
}
break;
case LFUN_UPSEL:
{
case LFUN_UPSEL: {
int const start = hasSelection() ? sel_cell_start : actcell;
int const ocell = actcell;
moveUp(bv, false);
// if we are starting a selection, only select
// the current cell at the beginning
if (hasSelection()) {
moveUp(bv, false);
}
if ((ocell == sel_cell_end) ||
(tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
sel_cell_end = tabular->GetCellAbove(sel_cell_end);
setSelection(start, tabular->GetCellAbove(sel_cell_end));
else
sel_cell_end = tabular->GetLastCellAbove(sel_cell_end);
setSelection(start, tabular->GetLastCellAbove(sel_cell_end));
updateLocal(bv, SELECTION, false);
}
break;
case LFUN_UP:
result = moveUp(bv, old_locking_inset != 0);
sel_cell_start = sel_cell_end = actcell;
clearSelection();
if (hs)
updateLocal(bv, SELECTION, false);
break;
@ -1575,8 +1624,7 @@ void InsetTabular::setFont(BufferView * bv, LyXFont const & font, bool tall,
bool selectall)
{
if (selectall) {
sel_cell_start = 0;
sel_cell_end = tabular->GetNumberOfCells() - 1;
setSelection(0, tabular->GetNumberOfCells() - 1);
}
if (hasSelection()) {
setUndo(bv, Undo::EDIT,
@ -1876,7 +1924,7 @@ void InsetTabular::tabularFeatures(BufferView * bv,
}
tabular->SetMultiColumn(s_start, s_end - s_start + 1);
actcell = s_start;
sel_cell_end = sel_cell_start;
clearSelection();
updateLocal(bv, INIT, true);
break;
}
@ -2480,17 +2528,22 @@ bool InsetTabular::doClearArea() const
void InsetTabular::getSelection(int & srow, int & erow, int & scol, int & ecol) const
{
srow = tabular->row_of_cell(sel_cell_start);
erow = tabular->row_of_cell(sel_cell_end);
if (srow > erow)
swap(srow, erow);
int const start = hasSelection() ? sel_cell_start : actcell;
int const end = hasSelection() ? sel_cell_end : actcell;
srow = tabular->row_of_cell(start);
erow = tabular->row_of_cell(end);
if (srow > erow) {
swap(srow, erow);
}
scol = tabular->column_of_cell(sel_cell_start);
ecol = tabular->column_of_cell(sel_cell_end);
if (scol > ecol)
swap(scol, ecol);
else
ecol = tabular->right_column_of_cell(sel_cell_end);
scol = tabular->column_of_cell(start);
ecol = tabular->column_of_cell(end);
if (scol > ecol) {
swap(scol, ecol);
} else {
ecol = tabular->right_column_of_cell(end);
}
}

View File

@ -269,11 +269,17 @@ private:
void removeTabularRow();
///
bool hasSelection() const {
return sel_cell_start != sel_cell_end;
return has_selection;
}
///
void clearSelection() const {
sel_cell_start = sel_cell_end = 0;
sel_cell_start = sel_cell_end = 0;
has_selection = false;
}
void setSelection(int start, int end) const {
sel_cell_start = start;
sel_cell_end = end;
has_selection = true;
}
///
bool activateCellInset(BufferView *, int x = 0, int y = 0,
@ -316,9 +322,11 @@ private:
mutable unsigned int inset_x;
///
mutable unsigned int inset_y;
///
/// true if a set of cells are selected
mutable bool has_selection;
/// the starting cell selection nr
mutable int sel_cell_start;
///
/// the ending cell selection nr
mutable int sel_cell_end;
///
mutable int actcell;

View File

@ -780,6 +780,17 @@ void InsetText::insetUnlock(BufferView * bv)
lt = 0;
}
void InsetText::lockInset(BufferView * bv, UpdatableInset * inset)
{
the_locking_inset = inset;
inset_x = cx(bv) - top_x + drawTextXOffset;
inset_y = cy(bv) + drawTextYOffset;
inset_pos = cpos(bv);
inset_par = cpar(bv);
inset_boundary = cboundary(bv);
updateLocal(bv, CURSOR, false);
}
bool InsetText::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
{
@ -787,15 +798,32 @@ bool InsetText::lockInsetInInset(BufferView * bv, UpdatableInset * inset)
<< inset << "): ";
if (!inset)
return false;
if (!the_locking_inset) {
Paragraph * p = par;
int const id = inset->id();
while(p) {
Paragraph::inset_iterator it =
p->inset_iterator_begin();
Paragraph::inset_iterator const end =
p->inset_iterator_end();
for (; it != end; ++it) {
if ((*it) == inset) {
getLyXText(bv)->setCursorIntern(bv, p, it.getPos());
lockInset(bv, inset);
return true;
}
if ((*it)->getInsetFromID(id)) {
lockInset(bv, static_cast<UpdatableInset *>(*it));
return the_locking_inset->lockInsetInInset(bv, inset);
}
}
p = p->next();
}
return false;
}
if (inset == cpar(bv)->getInset(cpos(bv))) {
lyxerr[Debug::INSETS] << "OK" << endl;
the_locking_inset = inset;
inset_x = cx(bv) - top_x + drawTextXOffset;
inset_y = cy(bv) + drawTextYOffset;
inset_pos = cpos(bv);
inset_par = cpar(bv);
inset_boundary = cboundary(bv);
updateLocal(bv, CURSOR, false);
lockInset(bv, inset);
return true;
} else if (the_locking_inset && (the_locking_inset == inset)) {
if (cpar(bv) == inset_par && cpos(bv) == inset_pos) {
@ -2388,19 +2416,11 @@ Paragraph * InsetText::paragraph() const
void InsetText::paragraph(Paragraph * p)
{
// first we have to delete the old contents otherwise we'll have a
// memory leak! But there check that we don't delete the paragraphs
// the new par is refering to (could happen in LyXText::EmptyParagrapM...)
// well don't do deletes at all if we come from there. Really stupid
// thing! (Jug 20011205)
if (par->next() != p) {
the_locking_inset = 0;
while (par && par != p) {
Paragraph * tmp = par->next();
delete par;
par = tmp;
}
}
// GENERAL COMMENT: We don't have to free the old paragraphs as the
// caller of this function has to take care of it. This IS important
// as we could have to insert a paragraph before this one and just
// link the actual to a new ones next and set it with this function
// and are done!
par = p;
// set ourself as owner for all the paragraphs inserted!
Paragraph * np = par;

View File

@ -250,6 +250,8 @@ protected:
///
void updateLocal(BufferView *, int what, bool mark_dirty) const;
///
void lockInset(BufferView *, UpdatableInset *);
///
mutable int drawTextXOffset;
///
mutable int drawTextYOffset;

View File

@ -813,50 +813,10 @@ string const LyXFunc::dispatch(int ac,
}
// Undo/Redo is a bit tricky for insets.
if (action == LFUN_UNDO) {
#ifdef RETHINK_THIS_FOR_NOW_WE_LEAVE_ALL_UNLOCKED
int slx;
int sly;
UpdatableInset * inset =
owner->view()->theLockingInset()->getLockingInset();
int inset_id = inset->id();
inset->getCursorPos(owner->view(), slx, sly);
owner->view()->unlockInset(inset);
#else
owner->view()->unlockInset(owner->view()->theLockingInset());
#endif
owner->view()->menuUndo();
#ifdef RETHINK_THIS_FOR_NOW_WE_LEAVE_ALL_UNLOCKED
#if 0
if (TEXT()->cursor.par()->
isInset(TEXT()->cursor.pos())) {
inset = static_cast<UpdatableInset*>(
TEXT()->cursor.par()->
getInset(TEXT()->
cursor.pos()));
} else {
inset = 0;
}
#else
inset = static_cast<UpdatableInset *>(owner->view()->buffer()->getInsetFromID(inset_id));
#endif
if (inset)
inset->edit(owner->view(),slx,sly,0);
#endif
return string();
} else if (action == LFUN_REDO) {
int slx;
int sly;
UpdatableInset * inset = owner->view()->
theLockingInset();
inset->getCursorPos(owner->view(), slx, sly);
owner->view()->unlockInset(inset);
owner->view()->menuRedo();
inset = static_cast<UpdatableInset*>(
TEXT()->cursor.par()->
getInset(TEXT()->
cursor.pos()));
if (inset)
inset->edit(owner->view(),slx,sly,0);
return string();
} else if (((result=owner->view()->theLockingInset()->
localDispatch(owner->view(), action, argument)) ==

View File

@ -862,8 +862,9 @@ void LyXText::redoParagraphs(BufferView * bview, LyXCursor const & cur,
if (!tmprow->previous()) {
// a trick/hack for UNDO
// Can somebody please tell me _why_ this solves
// anything. (Lgb)
// This is needed because in an UNDO/REDO we could have changed
// the firstParagrah() so the paragraph inside the row is NOT
// my really first par anymore. Got it Lars ;) (Jug 20011206)
first_phys_par = firstParagraph();
} else {
first_phys_par = tmprow->par();
@ -886,7 +887,7 @@ void LyXText::redoParagraphs(BufferView * bview, LyXCursor const & cur,
tmppar = tmprow->next()->par();
else
tmppar = 0;
while (tmppar != endpar) {
while (tmprow->next() && tmppar != endpar) {
removeRow(tmprow->next());
if (tmprow->next()) {
tmppar = tmprow->next()->par();
@ -2185,8 +2186,7 @@ void LyXText::setCursor(BufferView *bview, LyXCursor & cur, Paragraph * par,
void LyXText::setCursorIntern(BufferView * bview, Paragraph * par,
pos_type pos,
bool setfont, bool boundary) const
pos_type pos, bool setfont, bool boundary) const
{
InsetText * it = static_cast<InsetText *>(par->inInset());
if (it) {
@ -2205,8 +2205,7 @@ void LyXText::setCursorIntern(BufferView * bview, Paragraph * par,
// I moved the lyxerr stuff in here so we can see if
// this is actually really needed and where!
// (Jug)
it->getLyXText(bview)->setCursorIntern(bview, par, pos, setfont,
boundary);
// it->getLyXText(bview)->setCursorIntern(bview, par, pos, setfont, boundary);
return;
}
}

View File

@ -36,16 +36,25 @@ bool textUndo(BufferView * bv)
finishUndo();
if (!undo_frozen) {
Paragraph * first = bv->buffer()->getParFromID(undo->number_of_before_par);
if (!first)
if (first && first->next())
first = first->next();
else if (!first)
first = firstUndoParagraph(bv, undo->number_of_inset_id);
if (first) {
bv->buffer()->redostack.push(
createUndo(bv, undo->kind, first,
bv->buffer()->getParFromID(undo->number_of_behind_par)));
bv->buffer()->getParFromID(undo->number_of_behind_par)));
}
}
}
return textHandleUndo(bv, undo);
// now we can unlock the inset for saftey because the inset pointer could
// be changed during the undo-function. Anyway if needed we have to lock
// the right inset/position if this is requested.
freezeUndo();
bv->unlockInset(bv->theLockingInset());
bool ret = textHandleUndo(bv, undo);
unFreezeUndo();
return ret;
}
@ -58,7 +67,9 @@ bool textRedo(BufferView * bv)
finishUndo();
if (!undo_frozen) {
Paragraph * first = bv->buffer()->getParFromID(undo->number_of_before_par);
if (!first)
if (first && first->next())
first = first->next();
else if (!first)
first = firstUndoParagraph(bv, undo->number_of_inset_id);
if (first) {
bv->buffer()->undostack.push(
@ -67,7 +78,14 @@ bool textRedo(BufferView * bv)
}
}
}
return textHandleUndo(bv, undo);
// now we can unlock the inset for saftey because the inset pointer could
// be changed during the undo-function. Anyway if needed we have to lock
// the right inset/position if this is requested.
freezeUndo();
bv->unlockInset(bv->theLockingInset());
bool ret = textHandleUndo(bv, undo);
unFreezeUndo();
return ret;
}
@ -82,7 +100,6 @@ bool textHandleUndo(BufferView * bv, Undo * undo)
bv->buffer()->getParFromID(undo->number_of_behind_par);
Paragraph * tmppar;
Paragraph * tmppar2;
Paragraph * endpar;
Paragraph * tmppar5;
// if there's no before take the beginning
@ -159,38 +176,51 @@ bool textHandleUndo(BufferView * bv, Undo * undo)
// Set the cursor for redoing
if (before) {
bv->text->setCursorIntern(bv, before, 0);
Inset * it = before->inInset();
if (it)
it->getLyXText(bv)->setCursorIntern(bv, before, 0);
else
bv->text->setCursorIntern(bv, before, 0);
}
Paragraph * endpar = 0;
// calculate the endpar for redoing the paragraphs.
if (behind) {
endpar = behind->next();
} else
endpar = behind;
if (behind)
endpar = behind->next();
tmppar = bv->buffer()->getParFromID(undo->number_of_cursor_par);
UpdatableInset* it = static_cast<UpdatableInset*>(tmppar3->inInset());
if (it) {
it->getLyXText(bv)->redoParagraphs(bv, it->getLyXText(bv)->cursor,
endpar);
LyXFont font;
it->update(bv, font, false);
// we now would have to rebreak the whole paragraph the undo-par
// was in. How we do it here is not really true. We would have to
// save this information in the undo-struct and then we could do
// the right rebreak. Here we only handle the case where this
// was in the actual paragraph, which not always is true.
bv->text->redoParagraphs(bv, bv->text->cursor,
bv->text->cursor.par());
if (tmppar){
it = static_cast<UpdatableInset*>(tmppar->inInset());
it->edit(bv);
it->getLyXText(bv)->setCursorIntern(bv, tmppar, undo->cursor_pos);
it->getLyXText(bv)->updateCounters(bv, it->getLyXText(bv)->cursor.row());
}
LyXFont font;
it->update(bv, font, false);
#ifdef THIS_DOES_NOT_WORK
// we need this anyway as also if the undo was
// inside an inset we have to redo the
// paragraph breaking
bv->text->redoParagraphs(bv, bv->text->cursor,
bv->text->cursor.par());
#endif
bv->text->setCursorIntern(bv, bv->text->cursor.par(),
bv->text->cursor.pos());
} else {
bv->text->redoParagraphs(bv, bv->text->cursor, endpar);
if (tmppar) {
bv->text->setCursorIntern(bv, tmppar, undo->cursor_pos);
bv->text->updateCounters(bv, bv->text->cursor.row());
LyXText * t;
Inset * it = tmppar->inInset();
if (it)
t = it->getLyXText(bv);
else
t = bv->text;
t->setCursorIntern(bv, tmppar, undo->cursor_pos);
t->updateCounters(bv, t->cursor.row());
}
}
result = true;
@ -226,9 +256,10 @@ void unFreezeUndo()
void setUndo(BufferView * bv, Undo::undo_kind kind,
Paragraph const * first, Paragraph const * behind)
{
if (!undo_frozen)
if (!undo_frozen) {
bv->buffer()->undostack.push(createUndo(bv, kind, first, behind));
bv->buffer()->redostack.clear();
bv->buffer()->redostack.clear();
}
}
@ -287,10 +318,10 @@ Undo * createUndo(BufferView * bv, Undo::undo_kind kind,
}
if (start && end && (start != end->next()) &&
((before_number != behind_number) ||
((before_number < 0) && (behind_number < 0)))) {
((before_number < 0) && (behind_number < 0))))
{
Paragraph * tmppar = start;
Paragraph * tmppar2 = new Paragraph(*tmppar, true);
tmppar2->id(tmppar->id());
// a memory optimization: Just store the layout information
// when only edit
@ -302,8 +333,7 @@ Undo * createUndo(BufferView * bv, Undo::undo_kind kind,
while (tmppar != end && tmppar->next()) {
tmppar = tmppar->next();
tmppar2->next(new Paragraph(*tmppar, false));
tmppar2->next()->id(tmppar->id());
tmppar2->next(new Paragraph(*tmppar, true));
// a memory optimization: Just store the layout
// information when only edit
if (kind == Undo::EDIT) {
@ -330,9 +360,8 @@ Undo * createUndo(BufferView * bv, Undo::undo_kind kind,
void setCursorParUndo(BufferView * bv)
{
setUndo(bv, Undo::FINISH,
bv->text->cursor.par(),
bv->text->cursor.par()->next());
setUndo(bv, Undo::FINISH, bv->text->cursor.par(),
bv->text->cursor.par()->next());
}
@ -340,7 +369,7 @@ Paragraph * firstUndoParagraph(BufferView * bv, int inset_id)
{
Inset * inset = bv->buffer()->getInsetFromID(inset_id);
if (inset) {
Paragraph * result = inset->firstParagraph();
Paragraph * result = inset->getFirstParagraph(0);
if (result)
return result;
}