From 7fdf62dd8ed3771d17253822fc1722144ab8b4e5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=BCrgen=20Vigna?= Date: Fri, 14 Dec 2001 11:55:58 +0000 Subject: [PATCH] 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 --- src/BufferView2.C | 48 +++++++-- src/ChangeLog | 13 +++ src/insets/ChangeLog | 11 +++ src/insets/inset.h | 2 +- src/insets/insetcollapsable.h | 2 +- src/insets/insettabular.C | 179 ++++++++++++++++++++++------------ src/insets/insettabular.h | 16 ++- src/insets/insettext.C | 60 ++++++++---- src/insets/insettext.h | 2 + src/lyxfunc.C | 40 -------- src/text2.C | 13 ++- src/undo_funcs.C | 93 ++++++++++++------ 12 files changed, 304 insertions(+), 175 deletions(-) diff --git a/src/BufferView2.C b/src/BufferView2.C index 2fad793b7b..2dde52ce02 100644 --- a/src/BufferView2.C +++ b/src/BufferView2.C @@ -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(*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); diff --git a/src/ChangeLog b/src/ChangeLog index 2d3cfd4cd0..ff14ac48ab 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,16 @@ +2001-12-13 Juergen Vigna + + * 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 + + * 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 * undo_funcs.C (textHandleUndo): undo undo leak fix below, as per diff --git a/src/insets/ChangeLog b/src/insets/ChangeLog index b783858270..984d306d01 100644 --- a/src/insets/ChangeLog +++ b/src/insets/ChangeLog @@ -1,3 +1,14 @@ +2001-12-07 Juergen Vigna + + * insettext.C (paragraph): remove the deleteing of paragraphs as + it was a WRONG move! + +2001-12-06 John Levon + + * insettabular.h: + * insettabular.C: use new setSelection(). Allow + selection of single cells. + 2001-12-12 Jean-Marc Lasgouttes * insetquotes.C (latex): fix to use the local language setting at diff --git a/src/insets/inset.h b/src/insets/inset.h index a3b98f022d..9e9c654d1a 100644 --- a/src/insets/inset.h +++ b/src/insets/inset.h @@ -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 &); diff --git a/src/insets/insetcollapsable.h b/src/insets/insetcollapsable.h index 0e15112f60..9f73fbbbe8 100644 --- a/src/insets/insetcollapsable.h +++ b/src/insets/insetcollapsable.h @@ -83,7 +83,7 @@ public: bool lockInsetInInset(BufferView *, UpdatableInset *); /// bool unlockInsetInInset(BufferView *, UpdatableInset *, - bool lr = false); + bool lr = false); /// bool updateInsetInInset(BufferView *, Inset *); /// diff --git a/src/insets/insettabular.C b/src/insets/insettabular.C index ebc196602a..2da68f6db4 100644 --- a/src/insets/insettabular.C +++ b/src/insets/insettabular.C @@ -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(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); + } } diff --git a/src/insets/insettabular.h b/src/insets/insettabular.h index ae89b37ca0..d53d4305d2 100644 --- a/src/insets/insettabular.h +++ b/src/insets/insettabular.h @@ -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; diff --git a/src/insets/insettext.C b/src/insets/insettext.C index aff7ff54ea..1e0a9906fb 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -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(*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; diff --git a/src/insets/insettext.h b/src/insets/insettext.h index 9f862e4c04..5ffc127287 100644 --- a/src/insets/insettext.h +++ b/src/insets/insettext.h @@ -250,6 +250,8 @@ protected: /// void updateLocal(BufferView *, int what, bool mark_dirty) const; /// + void lockInset(BufferView *, UpdatableInset *); + /// mutable int drawTextXOffset; /// mutable int drawTextYOffset; diff --git a/src/lyxfunc.C b/src/lyxfunc.C index be9d478136..8253912947 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -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( - TEXT()->cursor.par()-> - getInset(TEXT()-> - cursor.pos())); - } else { - inset = 0; - } -#else - inset = static_cast(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( - 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)) == diff --git a/src/text2.C b/src/text2.C index 3207fcd63d..e9cca2e3a4 100644 --- a/src/text2.C +++ b/src/text2.C @@ -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(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; } } diff --git a/src/undo_funcs.C b/src/undo_funcs.C index dd06488668..d8b76866fc 100644 --- a/src/undo_funcs.C +++ b/src/undo_funcs.C @@ -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(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(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; } -- 2.39.2