#include "paragraph.h"
#include "paragraph_funcs.h"
#include "texrow.h"
-#include "undo_funcs.h"
+#include "undo.h"
#include "WordLangTuple.h"
#include "frontends/Alert.h"
#include "paragraph_funcs.h"
#include "ParagraphParameters.h"
#include "TextCache.h"
-#include "undo_funcs.h"
+#include "undo.h"
#include "vspace.h"
#include "insets/insetfloatlist.h"
+
+
+2003-10-14 André Pönitz <poenitz@gmx.net>
+
+ * iterators.[Ch]: new direct access to innermost LyXText and Inset
+
+ * undo.[Ch]: restoring part of 'undo in insets'
+
+ * Makefile.am:
+ * undo_funcs.[Ch]: merge with undo.[Ch]
+
+ * tabular.C: small cleansing stuff
+
2003-10-14 Alfredo Braunstein <abraunst@libero.it>
* paragraph_funcs.C (readParToken): report unknown insets as error
List::iterator it = list.begin();
List::iterator end = list.end();
for (; it != end; ++it) {
- if (it->inset) {
- if (it->inset->isTextInset()) {
- static_cast<UpdatableInset*>
- (it->inset)->deleteLyXText(bv, true);
- }
+ if (it->inset && it->inset->isTextInset()) {
+ static_cast<UpdatableInset*>
+ (it->inset)->deleteLyXText(bv, true);
}
}
}
trans_mgr.h \
undo.C \
undo.h \
- undo_funcs.C \
- undo_funcs.h \
vc-backend.C \
vc-backend.h \
version.C \
#ifndef LYXDEBUG_H
#define LYXDEBUG_H
-
#include "support/debugstream.h"
/** Ideally this should have been a namespace, but since we try to be
+
+2003-10-14 André Pönitz <poenitz@gmx.net>
+
+ * insetcollapsable.[Ch]:
+ * insettabular.[Ch]:
+ * insettext.[Ch]:
+ * inset.h: getText() as alternative to getParagraphs()
+
2003-10-13 Angus Leeming <leeming@lyx.org>
* insetexternal.C:
/// should return it's very first one!
virtual ParagraphList * getParagraphs(int /*num*/) const { return 0; }
///
+ virtual LyXText * getText(int /*num*/) const { return 0; }
+ ///
virtual bool haveParagraphs() const {
return false;
}
}
+LyXText * InsetCollapsable::getText(int i) const
+{
+ return inset.getText(i);
+}
+
+
LyXCursor const & InsetCollapsable::cursor(BufferView * bv) const
{
return inset.cursor(bv);
///
ParagraphList * getParagraphs(int) const;
///
+ LyXText * getText(int) const;
+ ///
LyXCursor const & cursor(BufferView *) const;
///
bool isOpen() const;
#include "paragraph.h"
#include "paragraph_funcs.h"
#include "ParagraphParameters.h"
-#include "undo_funcs.h"
+#include "undo.h"
#include "WordLangTuple.h"
#include "frontends/Alert.h"
<< inset << "): ";
if (!inset)
return false;
+
oldcell = -1;
+
if (inset == &tabular.getCellInset(actcell)) {
lyxerr[Debug::INSETTEXT] << "OK" << endl;
the_locking_inset = &tabular.getCellInset(actcell);
resetPos(bv);
return true;
- } else if (!the_locking_inset) {
+ }
+
+ if (!the_locking_inset) {
int const n = tabular.getNumberOfCells();
int const id = inset->id();
for (int i = 0; i < n; ++i) {
return the_locking_inset->lockInsetInInset(bv, inset);
}
}
- } else if (the_locking_inset && (the_locking_inset == inset)) {
+ return false;
+ }
+
+ if (the_locking_inset && (the_locking_inset == inset)) {
lyxerr[Debug::INSETTEXT] << "OK" << endl;
resetPos(bv);
- } else if (the_locking_inset) {
+ return false;
+ }
+
+ if (the_locking_inset) {
lyxerr[Debug::INSETTEXT] << "MAYBE" << endl;
return the_locking_inset->lockInsetInInset(bv, inset);
}
+
lyxerr[Debug::INSETTEXT] << "NOT OK" << endl;
return false;
}
bool const inset_hit = insetHit(bv, cmd.x, cmd.y);
- if ((ocell == actcell) && the_locking_inset && inset_hit) {
+ if (ocell == actcell && the_locking_inset && inset_hit) {
resetPos(bv);
FuncRequest cmd1 = cmd;
cmd1.x -= inset_x;
clearSelection();
finishUndo();
if (insetHit(bv, cmd.x, cmd.y) && cmd.button() != mouse_button::button3) {
- activateCellInsetAbs(bv, cmd.x, cmd.y, cmd.button());
+ inset_x = cursorx_ - top_x + tabular.getBeginningOfTextInCell(actcell);
+ inset_y = cursory_;
+ activateCellInset(bv, cmd.x - inset_x, cmd.y - inset_y, cmd.button());
}
}
return DISPATCHED;
case LFUN_ENDBUF:
case LFUN_ENDBUFSEL:
break;
- case LFUN_LAYOUT_TABULAR: {
+ case LFUN_LAYOUT_TABULAR:
InsetTabularMailer(*this).showDialog(bv);
break;
- }
- case LFUN_INSET_DIALOG_UPDATE: {
+ case LFUN_INSET_DIALOG_UPDATE:
InsetTabularMailer(*this).updateDialog(bv);
break;
- }
case LFUN_TABULAR_FEATURE:
if (!tabularFeatures(bv, arg))
result = UNDISPATCHED;
break;
case LFUN_PASTESELECTION:
{
- string const clip(bv->getClipboard());
- if (clip.empty())
+ string const clip = bv->getClipboard();
+ if (clip.empty())
break;
#if 0
if (clip.find('\t') != string::npos) {
bool moved = isRightToLeft(bv) ? moveNextCell(bv) : movePrevCell(bv);
if (!moved)
return FINISHED;
- if (lock) { // behind the inset
- if (activateCellInset(bv, 0, 0, mouse_button::none, true))
- return DISPATCHED;
- }
+ // behind the inset
+ if (lock && activateCellInset(bv, 0, 0, mouse_button::none, true))
+ return DISPATCHED;
resetPos(bv);
return DISPATCHED_NOUPDATE;
}
int sel_col_start;
int sel_col_end;
getSelection(sel_row_start, sel_row_end, sel_col_start, sel_col_end);
- for(int i = sel_row_start; i <= sel_row_end; ++i)
- for(int j = sel_col_start; j <= sel_col_end; ++j)
+ for (int i = sel_row_start; i <= sel_row_end; ++i)
+ for (int j = sel_col_start; j <= sel_col_end; ++j)
tabular.getCellInset(i, j).setFont(bv, font, tall, true);
if (!frozen)
void InsetTabular::tabularFeatures(BufferView * bv,
- LyXTabular::Feature feature,
- string const & value)
+ LyXTabular::Feature feature, string const & value)
{
int sel_col_start;
int sel_col_end;
switch (feature) {
- case LyXTabular::SET_PWIDTH:
- {
+ case LyXTabular::SET_PWIDTH: {
LyXLength const len(value);
LyXLength const & oldlen = tabular.getColumnPWidth(actcell);
}
}
break;
+
case LyXTabular::SET_SPECIAL_COLUMN:
case LyXTabular::SET_SPECIAL_MULTI:
tabular.setAlignSpecial(actcell,value,feature);
updateLocal(bv);
break;
+
case LyXTabular::APPEND_ROW:
// append the row into the tabular
unlockInsetInInset(bv, the_locking_inset);
tabular.setOwner(this);
updateLocal(bv);
break;
+
case LyXTabular::APPEND_COLUMN:
// append the column into the tabular
unlockInsetInInset(bv, the_locking_inset);
actcell = tabular.getCellNumber(row, column);
updateLocal(bv);
break;
+
case LyXTabular::DELETE_ROW:
unlockInsetInInset(bv, the_locking_inset);
- for(int i = sel_row_start; i <= sel_row_end; ++i) {
+ for (int i = sel_row_start; i <= sel_row_end; ++i)
tabular.deleteRow(sel_row_start);
- }
if (sel_row_start >= tabular.rows())
--sel_row_start;
actcell = tabular.getCellNumber(sel_row_start, column);
clearSelection();
updateLocal(bv);
break;
+
case LyXTabular::DELETE_COLUMN:
unlockInsetInInset(bv, the_locking_inset);
- for(int i = sel_col_start; i <= sel_col_end; ++i) {
+ for (int i = sel_col_start; i <= sel_col_end; ++i)
tabular.deleteColumn(sel_col_start);
- }
if (sel_col_start >= tabular.columns())
--sel_col_start;
actcell = tabular.getCellNumber(row, sel_col_start);
clearSelection();
updateLocal(bv);
break;
+
case LyXTabular::M_TOGGLE_LINE_TOP:
flag = false;
- case LyXTabular::TOGGLE_LINE_TOP:
- {
+ case LyXTabular::TOGGLE_LINE_TOP: {
bool lineSet = !tabular.topLine(actcell, flag);
for (int i = sel_row_start; i <= sel_row_end; ++i)
for (int j = sel_col_start; j <= sel_col_end; ++j)
case LyXTabular::M_TOGGLE_LINE_BOTTOM:
flag = false;
- case LyXTabular::TOGGLE_LINE_BOTTOM:
- {
+ case LyXTabular::TOGGLE_LINE_BOTTOM: {
bool lineSet = !tabular.bottomLine(actcell, flag);
for (int i = sel_row_start; i <= sel_row_end; ++i)
for (int j = sel_col_start; j <= sel_col_end; ++j)
case LyXTabular::M_TOGGLE_LINE_LEFT:
flag = false;
- case LyXTabular::TOGGLE_LINE_LEFT:
- {
+ case LyXTabular::TOGGLE_LINE_LEFT: {
bool lineSet = !tabular.leftLine(actcell, flag);
for (int i = sel_row_start; i <= sel_row_end; ++i)
for (int j = sel_col_start; j <= sel_col_end; ++j)
case LyXTabular::M_TOGGLE_LINE_RIGHT:
flag = false;
- case LyXTabular::TOGGLE_LINE_RIGHT:
- {
+ case LyXTabular::TOGGLE_LINE_RIGHT: {
bool lineSet = !tabular.rightLine(actcell, flag);
for (int i = sel_row_start; i <= sel_row_end; ++i)
for (int j = sel_col_start; j <= sel_col_end; ++j)
case LyXTabular::SET_ROTATE_CELL:
for (int i = sel_row_start; i <= sel_row_end; ++i)
- for (int j = sel_col_start; j<=sel_col_end; ++j)
+ for (int j = sel_col_start; j <= sel_col_end; ++j)
tabular.setRotateCell(
tabular.getCellNumber(i, j), true);
break;
tabular.setLTFoot(row, flag, ltt, true);
break;
- case LyXTabular::SET_LTNEWPAGE: {
- bool what = !tabular.getLTNewPage(row);
- tabular.setLTNewPage(row, what);
+ case LyXTabular::SET_LTNEWPAGE:
+ tabular.setLTNewPage(row, !tabular.getLTNewPage(row));
break;
- }
// dummy stuff just to avoid warnings
case LyXTabular::LAST_ACTION:
}
-bool InsetTabular::activateCellInsetAbs(BufferView * bv, int x, int y,
- mouse_button::state button)
-{
- inset_x = cursorx_ - top_x + tabular.getBeginningOfTextInCell(actcell);
- inset_y = cursory_;
- return activateCellInset(bv, x - inset_x, y - inset_y, button);
-}
-
-
bool InsetTabular::insetHit(BufferView *, int x, int) const
{
return x + top_x > cursorx_ + tabular.getBeginningOfTextInCell(actcell);
ParagraphList * InsetTabular::getParagraphs(int i) const
{
- return (i < tabular.getNumberOfCells())
+ return i < tabular.getNumberOfCells()
? tabular.getCellInset(i).getParagraphs(0)
: 0;
}
+LyXText * InsetTabular::getText(int i) const
+{
+ return i < tabular.getNumberOfCells()
+ ? tabular.getCellInset(i).getText(0)
+ : 0;
+}
+
+
LyXCursor const & InsetTabular::cursor(BufferView * bv) const
{
if (the_locking_inset)
InsetTabular::selectNextWordToSpellcheck(BufferView * bv, float & value) const
{
if (the_locking_inset) {
- WordLangTuple word(the_locking_inset->selectNextWordToSpellcheck(bv, value));
+ WordLangTuple word =
+ the_locking_inset->selectNextWordToSpellcheck(bv, value);
if (!word.word().empty())
return word;
if (tabular.isLastCell(actcell)) {
// otherwise we have to lock the next inset and ask for it's selecttion
tabular.getCellInset(actcell)
.localDispatch(FuncRequest(bv, LFUN_INSET_EDIT));
- WordLangTuple word(selectNextWordInt(bv, value));
+ WordLangTuple word = selectNextWordInt(bv, value);
if (!word.word().empty())
resetPos(bv);
return word;
// when entering this function the inset should be ALWAYS locked!
BOOST_ASSERT(the_locking_inset);
- WordLangTuple word(the_locking_inset->selectNextWordToSpellcheck(bv, value));
+ WordLangTuple word =
+ the_locking_inset->selectNextWordToSpellcheck(bv, value);
if (!word.word().empty())
return word;
++cols;
break;
case '\n':
- if ((p+1) < len)
+ if (p + 1 < len)
++rows;
maxCols = max(cols, maxCols);
cols = 1;
///
ParagraphList * getParagraphs(int) const;
///
+ LyXText * getText(int) const;
+ ///
LyXCursor const & cursor(BufferView *) const;
///
bool allowSpellcheck() const { return true; }
mouse_button::state button = mouse_button::none,
bool behind = false);
///
- bool activateCellInsetAbs(BufferView *, int x = 0, int y = 0,
- mouse_button::state button = mouse_button::none);
- ///
bool insetHit(BufferView * bv, int x, int y) const;
///
bool hasPasteBuffer() const;
#include "rowpainter.h"
#include "sgml.h"
#include "texrow.h"
-#include "undo_funcs.h"
+#include "undo.h"
#include "WordLangTuple.h"
#include "frontends/Alert.h"
}
+LyXText * InsetText::getText(int i) const
+{
+ return (i == 0) ? const_cast<LyXText*>(&text_) : 0;
+}
+
+
LyXCursor const & InsetText::cursor(BufferView * bv) const
{
if (the_locking_inset)
///
ParagraphList * getParagraphs(int) const;
///
+ LyXText * getText(int) const;
+ ///
LyXCursor const & cursor(BufferView *) const;
///
bool allowSpellcheck() const { return true; }
#include "iterators.h"
#include "paragraph.h"
+#include "debug.h"
#include "insets/inset.h"
}
+LyXText * ParIterator::text() const
+{
+ //lyxerr << "positions.size: " << pimpl_->positions.size() << std::endl;
+ if (pimpl_->positions.size() <= 1)
+ return 0;
+
+ ParPosition const & pos = pimpl_->positions[pimpl_->positions.size() - 2];
+ return (*pos.it)->inset->getText(*pos.index);
+}
+
+
+InsetOld * ParIterator::inset() const
+{
+ //lyxerr << "positions.size: " << pimpl_->positions.size() << std::endl;
+ if (pimpl_->positions.size() <= 1)
+ return 0;
+
+ ParPosition const & pos = pimpl_->positions[pimpl_->positions.size() - 2];
+ return (*pos.it)->inset;
+}
+
+
Paragraph & ParIterator::operator*() const
{
return *pimpl_->positions.back().pit;
#include <boost/scoped_ptr.hpp>
+class LyXText;
+class InsetOld;
+
class ParIterator {
public:
///
ParagraphList::iterator pit() const;
///
ParagraphList & plist() const;
+ /// returns 'innermost' LyXText if in an inset or '0' instead of
+ //bv->text
+ LyXText * text() const;
+ ///
+ InsetOld * inset() const;
///
size_t size() const;
///
#include "paragraph.h"
#include "ParagraphParameters.h"
#include "TextCache.h"
-#include "undo_funcs.h"
+#include "undo.h"
#include "insets/insetcommand.h"
#include "insets/insetexternal.h"
#include "math_hullinset.h"
#include "math_parser.h"
#include "math_spaceinset.h"
-#include "undo_funcs.h"
+#include "undo.h"
#include "ref_inset.h"
#include "LColor.h"
BOOST_ASSERT(pos <= size());
// First, reduce font against layout/label font
- // Update: The SetCharFont() routine in text2.C already
+ // Update: The setCharFont() routine in text2.C already
// reduces font, so we don't need to do that here. (Asger)
// No need to simplify this because it will disappear
// in a new kernel. (Asger)
/// the destructor removes the new paragraph from the list
~Paragraph();
+ ///
+ int id() const;
+ ///
+ void id(int i);
+
///
Language const * getParLanguage(BufferParams const &) const;
///
///
void validate(LaTeXFeatures &) const;
- /// return the unique ID of this paragraph
- int id() const;
- /// Set the Id of this paragraph.
- void id(int);
-
///
int startTeXParParams(BufferParams const &, std::ostream &, bool) const;
#ifndef DEBUG_STREAM_HPP
#define DEBUG_STREAM_HPP
-#include <boost/test/detail/nullstream.hpp>
+#include <iostream>
+#include <boost/test/detail/nullstream.hpp>
struct debug_trait {
enum type {
#include "ParagraphParameters.h"
#include "rowpainter.h"
#include "text_funcs.h"
-#include "undo_funcs.h"
+#include "undo.h"
#include "vspace.h"
#include "WordLangTuple.h"
// same Paragraph one to the right and make a rebreak
void LyXText::insertChar(char c)
{
- recordUndo(bv(), Undo::INSERT, ownerParagraphs(), cursor.par(), cursor.par());
+ recordUndo(Undo::INSERT, this, cursor.par(), cursor.par());
// When the free-spacing option is set for the current layout,
// disable the double-space checking
if (selection.start.par() == selection.end.par()) {
LyXCursor & startc = selection.start;
LyXCursor & endc = selection.end;
- recordUndo(bv(), Undo::INSERT, ownerParagraphs(), startc.par());
+ recordUndo(Undo::INSERT, this, startc.par());
getPar(startc)->acceptChange(startc.pos(), endc.pos());
finishUndo();
clearSelection();
if (selection.start.par() == selection.end.par()) {
LyXCursor & startc = selection.start;
LyXCursor & endc = selection.end;
- recordUndo(bv(), Undo::INSERT, ownerParagraphs(), startc.par());
+ recordUndo(Undo::INSERT, this, startc.par());
getPar(startc)->rejectChange(startc.pos(), endc.pos());
finishUndo();
clearSelection();
setCursor(to.par(), to.pos() + 1);
}
- recordUndo(bv(), Undo::ATOMIC, ownerParagraphs(), from.par(), to.par());
+ recordUndo(Undo::ATOMIC, this, from.par(), to.par());
pos_type pos = from.pos();
int par = from.par();
// if you had success make a backspace
if (old_cursor.par() != cursor.par() || old_cursor.pos() != cursor.pos()) {
- recordUndo(bv(), Undo::DELETE, ownerParagraphs(), old_cursor.par());
+ recordUndo(Undo::DELETE, this, old_cursor.par());
backspace();
}
}
}
if (cursor.par() != 0)
- recordUndo(bv(), Undo::DELETE, ownerParagraphs(),
- cursor.par() - 1, cursor.par());
+ recordUndo(Undo::DELETE, this, cursor.par() - 1, cursor.par());
ParagraphList::iterator tmppit = cursorPar();
// We used to do cursorLeftIntern() here, but it is
} else {
// this is the code for a normal backspace, not pasting
// any paragraphs
- recordUndo(bv(), Undo::DELETE, ownerParagraphs(), cursor.par());
+ recordUndo(Undo::DELETE, this, cursor.par());
// We used to do cursorLeftIntern() here, but it is
// not a good idea since it triggers the auto-delete
// mechanism. So we do a cursorLeftIntern()-lite,
#include "paragraph.h"
#include "paragraph_funcs.h"
#include "ParagraphParameters.h"
-#include "undo_funcs.h"
+#include "undo.h"
#include "vspace.h"
#include "frontends/font_metrics.h"
void LyXText::recUndo(paroffset_type first, paroffset_type last) const
{
- recordUndo(bv(), Undo::ATOMIC, ownerParagraphs(), first, last);
+ recordUndo(Undo::ATOMIC, this, first, last);
}
void LyXText::recUndo(lyx::paroffset_type par) const
{
- recordUndo(bv(), Undo::ATOMIC, ownerParagraphs(), par, par);
+ recordUndo(Undo::ATOMIC, this, par, par);
}
#include "paragraph.h"
#include "ParagraphParameters.h"
#include "text_funcs.h"
-#include "undo_funcs.h"
+#include "undo.h"
#include "vspace.h"
#include "frontends/Dialogs.h"
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
+ * \author Asger Alstrup
* \author Lars Gullik Bjønnes
+ * \author John Levon
* \author André Pönitz
+ * \author Jürgen Vigna
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "undo.h"
+
+#include "buffer.h"
+#include "debug.h"
+#include "BufferView.h"
+#include "funcrequest.h"
+#include "iterators.h"
+#include "lyxtext.h"
#include "paragraph.h"
-Undo::Undo(undo_kind kind_arg, int inset,
- int plist_arg,
+#include "insets/updatableinset.h"
+#include "insets/insettext.h"
+
+#include <iostream>
+
+using std::endl;
+using lyx::paroffset_type;
+
+
+/// The flag used by finishUndo().
+bool undo_finished;
+
+/// Whether actions are not added to the undo stacks.
+bool undo_frozen;
+
+Undo::Undo(undo_kind kind_arg, int text_arg,
int first, int last,
int cursor, int cursor_pos_arg,
ParagraphList const & par)
:
kind(kind_arg),
- inset_id(inset),
- plist(plist_arg),
+ text(text_arg),
first_par_offset(first),
last_par_offset(last),
cursor_par_offset(cursor),
pars(par)
{}
+
+std::ostream & operator<<(std::ostream & os, Undo const & undo)
+{
+ return os << " text: " << undo.text
+ << " first: " << undo.first_par_offset
+ << " last: " << undo.last_par_offset
+ << " cursor: " << undo.cursor_par_offset
+ << "/" << undo.cursor_pos;
+}
+
+
+namespace {
+
+void recordUndo(Undo::undo_kind kind,
+ LyXText * text, paroffset_type firstpar, paroffset_type lastpar,
+ limited_stack<Undo> & stack)
+{
+ Buffer * buf = text->bv()->buffer();
+
+ ParagraphList & plist = text->ownerParagraphs();
+ ParagraphList::iterator first = plist.begin();
+ advance(first, firstpar);
+ ParagraphList::iterator last = plist.begin();
+ advance(last, lastpar);
+
+ // try to find the appropriate list by counting the
+ // texts from buffer begin
+ ParIterator null = buf->par_iterator_end();
+
+ int tcount = 0;
+ // it.text() returns 0 for outermost text.
+ if (text != text->bv()->text)
+ for (ParIterator it = buf->par_iterator_begin(); it != null; ++it, ++tcount)
+ if (it.text() == text)
+ break;
+
+ // and calculate a stable reference to them
+ int const first_offset = firstpar;
+ int const last_offset = plist.size() - lastpar;
+
+ // Undo::ATOMIC are always recorded (no overlapping there).
+ // overlapping only with insert and delete inside one paragraph:
+ // nobody wants all removed character appear one by one when undoing.
+ if (! undo_finished && kind != Undo::ATOMIC) {
+ // Check whether storing is needed.
+ if (! buf->undostack().empty()
+ && buf->undostack().top().kind == kind
+ && buf->undostack().top().first_par_offset == first_offset
+ && buf->undostack().top().last_par_offset == last_offset) {
+ // No additonal undo recording needed -
+ // effectively, we combine undo recordings to one.
+ return;
+ }
+ }
+
+ // Record the cursor position in a stable way.
+ int const cursor_offset = text->cursor.par();
+
+ // make and push the Undo entry
+ stack.push(Undo(kind, tcount,
+ first_offset, last_offset,
+ cursor_offset, text->cursor.pos(),
+ ParagraphList()));
+ lyxerr << "undo record: " << stack.top() << endl;
+
+ // record the relevant paragraphs
+ ParagraphList & undo_pars = stack.top().pars;
+
+ for (ParagraphList::iterator it = first; it != last; ++it) {
+ undo_pars.push_back(*it);
+ undo_pars.back().id(it->id());
+ }
+ undo_pars.push_back(*last);
+ undo_pars.back().id(last->id());
+
+ // and make sure that next time, we should be combining if possible
+ undo_finished = false;
+}
+
+
+// Returns false if no undo possible.
+bool performUndoOrRedo(BufferView * bv, Undo const & undo)
+{
+ lyxerr << "undo, performing: " << undo << endl;
+ Buffer * buf = bv->buffer();
+ ParIterator plit = buf->par_iterator_begin();
+ ParIterator null = buf->par_iterator_end();
+
+ int tcount = undo.text;
+ for ( ; tcount && plit != null; ++plit, --tcount)
+ ;
+
+ LyXText * text = plit.text();
+ if (!text)
+ text = bv->text;
+ ParagraphList & plist = text->ownerParagraphs();
+
+ // remove new stuff between first and last
+ {
+ ParagraphList::iterator first = plist.begin();
+ advance(first, undo.first_par_offset);
+ ParagraphList::iterator last = plist.begin();
+ advance(last, plist.size() - undo.last_par_offset);
+ plist.erase(first, ++last);
+ }
+
+ // re-insert old stuff instead
+ if (plist.empty()) {
+ plist.assign(undo.pars.begin(), undo.pars.end());
+ } else {
+ ParagraphList::iterator first = plist.begin();
+ advance(first, undo.first_par_offset);
+ plist.insert(first, undo.pars.begin(), undo.pars.end());
+ }
+
+ // set cursor
+ lyxerr << "undo, text: " << text << " inset: " << plit.inset() << endl;
+ InsetOld * inset = plit.inset();
+ if (inset) {
+ // Magic needed to cope with inset locking
+ FuncRequest cmd(bv, LFUN_INSET_EDIT, "left");
+ inset->localDispatch(cmd);
+ }
+
+ // set cursor again to force the position to be the right one
+ text->setCursorIntern(undo.cursor_par_offset, undo.cursor_pos);
+
+ // clear any selection
+ text->clearSelection();
+ text->selection.cursor = text->cursor;
+ text->updateCounters();
+
+ // rebreak the entire document
+ bv->text->fullRebreak();
+
+ finishUndo();
+ return true;
+}
+
+
+// Returns false if no undo possible.
+bool textUndoOrRedo(BufferView * bv,
+ limited_stack<Undo> & stack, limited_stack<Undo> & otherstack)
+{
+ if (stack.empty()) {
+ /*
+ * Finish the undo operation in the case there was no entry
+ * on the stack to perform.
+ */
+ freezeUndo();
+ bv->unlockInset(bv->theLockingInset());
+ finishUndo();
+ unFreezeUndo();
+ return false;
+ }
+
+ Undo undo = stack.top();
+ stack.pop();
+ finishUndo();
+
+ if (!undo_frozen) {
+ otherstack.push(undo);
+ otherstack.top().pars.clear();
+ Buffer * buf = bv->buffer();
+ ParagraphList & plist = buf->paragraphs();
+ if (undo.first_par_offset + undo.last_par_offset <= int(plist.size())) {
+ ParagraphList::iterator first = plist.begin();
+ advance(first, undo.first_par_offset);
+ ParagraphList::iterator last = plist.begin();
+ advance(last, plist.size() - undo.last_par_offset + 1);
+ otherstack.top().pars.insert(otherstack.top().pars.begin(), first, last);
+ }
+ otherstack.top().cursor_pos = text
+ lyxerr << " undo other: " << otherstack.top() << endl;
+ }
+
+ // Now we can unlock the inset for safety 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 const ret = performUndoOrRedo(bv, undo);
+ unFreezeUndo();
+ return ret;
+}
+
+} // namespace anon
+
+
+void freezeUndo()
+{
+ // This is dangerous and for internal use only.
+ undo_frozen = true;
+}
+
+
+void unFreezeUndo()
+{
+ // This is dangerous and for internal use only.
+ undo_frozen = false;
+}
+
+
+void finishUndo()
+{
+ // Makes sure the next operation will be stored.
+ undo_finished = true;
+}
+
+
+bool textUndo(BufferView * bv)
+{
+ return textUndoOrRedo(bv, bv->buffer()->undostack(),
+ bv->buffer()->redostack());
+}
+
+
+bool textRedo(BufferView * bv)
+{
+ return textUndoOrRedo(bv, bv->buffer()->redostack(),
+ bv->buffer()->undostack());
+}
+
+
+void recordUndo(Undo::undo_kind kind,
+ LyXText const * text, paroffset_type first, paroffset_type last)
+{
+ if (!undo_frozen) {
+ Buffer * buf = text->bv()->buffer();
+ recordUndo(kind, const_cast<LyXText *>(text),
+ first, last, buf->undostack());
+ buf->redostack().clear();
+ }
+}
+
+
+void recordUndo(Undo::undo_kind kind, LyXText const * text, paroffset_type par)
+{
+ recordUndo(kind, text, par, par);
+}
+
+
+void recordUndo(BufferView * bv, Undo::undo_kind kind)
+{
+ recordUndo(kind, bv->text, bv->text->cursor.par());
+}
*
* \author Asger Alstrup
* \author Lars Gullik Bjønnes
+ * \author John Levon
* \author André Pönitz
+ * \author Jürgen Vigna
*
* Full author contact details are available in file CREDITS.
*/
#define UNDO_H
#include "ParagraphList_fwd.h"
+#include "support/types.h"
+
+class LyXText;
+class BufferView;
/**
* These are the elements put on the undo stack. Each object
* contains complete paragraphs and sufficient information
- * to restore the state. The work is done in undo_funcs.C
+ * to restore the state.
*/
class Undo {
public:
ATOMIC
};
///
- Undo(undo_kind kind, int inset_id,
- int plist,
+ Undo(undo_kind kind, int text,
int first, int last,
int cursor, int cursor_pos,
ParagraphList const & par_arg);
/// Which kind of operation are we recording for?
undo_kind kind;
- /// to what paragraph list do we belong?
- int plist;
-
- /**
- * ID of hosting inset if the cursor is in one.
- * if -1, then the cursor is not in an inset.
- * if >= 0, then the cursor is in inset with given id.
- */
- int inset_id;
+ /// hosting LyXText counted from buffer begin
+ int text;
/// Offset to the first paragraph in the main document paragraph list
int first_par_offset;
};
-#endif
+/// This will undo the last action - returns false if no undo possible
+bool textUndo(BufferView *);
+
+/// This will redo the last undo - returns false if no redo possible
+bool textRedo(BufferView *);
+
+/// Makes sure the next operation will be stored
+void finishUndo();
+
+/**
+ * Whilst undo is frozen, all actions do not get added
+ * to the undo stack
+ */
+void freezeUndo();
+
+/// Track undos again
+void unFreezeUndo();
+
+/**
+ * Record undo information - call with the first paragraph that will be changed
+ * and the last paragraph that will be changed. So we give an inclusive
+ * range.
+ * This is called before you make the changes to the paragraph, and it
+ * will record the original information of the paragraphs in the undo stack.
+ */
+void recordUndo(Undo::undo_kind kind,
+ LyXText const * text, lyx::paroffset_type first, lyx::paroffset_type last);
+
+/// Convienience: Prepare undo when change in a single paragraph.
+void recordUndo(Undo::undo_kind kind,
+ LyXText const * text, lyx::paroffset_type par);
+
+/// Convienience: Prepare undo for the paragraph that contains the cursor
+void recordUndo(BufferView *, Undo::undo_kind kind);
+
+/// Are we avoiding tracking undos currently ?
+extern bool undo_frozen;
+
+#endif // UNDO_FUNCS_H
+++ /dev/null
-/**
- * \file undo_funcs.C
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Asger Alstrup
- * \author Lars Gullik Bjønnes
- * \author John Levon
- * \author André Pönitz
- * \author Jürgen Vigna
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "undo_funcs.h"
-
-#include "buffer.h"
-#include "debug.h"
-#include "BufferView.h"
-#include "funcrequest.h"
-#include "iterators.h"
-#include "lyxtext.h"
-#include "paragraph.h"
-
-#include "insets/updatableinset.h"
-
-#include <iostream>
-
-using std::endl;
-using lyx::paroffset_type;
-
-
-/// The flag used by finishUndo().
-bool undo_finished;
-
-/// Whether actions are not added to the undo stacks.
-bool undo_frozen;
-
-namespace {
-
-
-void recordUndo(BufferView * bv, Undo::undo_kind kind,
- ParagraphList & plist, paroffset_type firstpar, paroffset_type lastpar,
- limited_stack<Undo> & stack)
-{
- Buffer * buf = bv->buffer();
-
- ParagraphList::iterator first = plist.begin();
- advance(first, firstpar);
- ParagraphList::iterator last = plist.begin();
- advance(last, lastpar);
-
- // First, record inset id, if cursor is in one
- UpdatableInset * inset = first->inInset();
- LyXText * text = inset ? inset->getLyXText(bv) : bv->text;
- int const inset_id = inset ? inset->id() : -1;
-
- // Try to find the appropriate list by counting the,
- ParIterator null = buf->par_iterator_end();
-
- int pcount = 0;
- for (ParIterator it = buf->par_iterator_begin(); it != null; ++it, ++pcount)
- if (&it.plist() == &plist)
- break;
-
- // And calculate a stable reference to them
- int const first_offset = firstpar;
- int const last_offset = plist.size() - lastpar;
-
- // Undo::ATOMIC are always recorded (no overlapping there).
- // Overlapping only with insert and delete inside one paragraph:
- // Nobody wants all removed character appear one by one when undoing.
- if (! undo_finished && kind != Undo::ATOMIC) {
- // Check whether storing is needed.
- if (! buf->undostack().empty()
- && buf->undostack().top().kind == kind
- && buf->undostack().top().first_par_offset == first_offset
- && buf->undostack().top().last_par_offset == last_offset) {
- // No additonal undo recording needed -
- // effectively, we combine undo recordings to one.
- return;
- }
- }
-
- // Record the cursor position in a stable way.
- int const cursor_offset = text->cursor.par();
-
- // Make and push the Undo entry
- stack.push(Undo(kind, inset_id,
- pcount,
- first_offset, last_offset,
- cursor_offset, text->cursor.pos(),
- ParagraphList()));
-
- // Record the relevant paragraphs
- ParagraphList & undo_pars = stack.top().pars;
-
- for (ParagraphList::iterator it = first; it != last; ++it) {
- undo_pars.push_back(*it);
- undo_pars.back().id(it->id());
- }
- undo_pars.push_back(*last);
- undo_pars.back().id(last->id());
-
- // And make sure that next time, we should be combining if possible
- undo_finished = false;
-}
-
-
-// Returns false if no undo possible.
-bool performUndoOrRedo(BufferView * bv, Undo const & undo)
-{
- Buffer * buf = bv->buffer();
-
- ParIterator null = buf->par_iterator_end();
- ParIterator plit = buf->par_iterator_begin();
- int n = undo.plist;
- for ( ; n && plit != null; ++plit, --n)
- ;
- BOOST_ASSERT(plit != null);
- ParagraphList & plist = plit.plist();
-
- // Remove new stuff between first and last
- {
- ParagraphList::iterator first = plist.begin();
- advance(first, undo.first_par_offset);
- ParagraphList::iterator last = plist.begin();
- advance(last, plist.size() - undo.last_par_offset);
- plist.erase(first, ++last);
- }
-
- // Re-insert old stuff instead
- {
- if (plist.empty()) {
- plist.assign(undo.pars.begin(), undo.pars.end());
- } else {
- ParagraphList::iterator first = plist.begin();
- advance(first, undo.first_par_offset);
- plist.insert(first, undo.pars.begin(), undo.pars.end());
- }
- }
-
- // Rebreak the entire document
- bv->text->fullRebreak();
-
- // set cursor
- {
- // Get a hold of the inset for the cursor, if relevant
- UpdatableInset * inset =
- static_cast<UpdatableInset *>(
- buf->getInsetFromID(undo.inset_id));
-
- LyXText * text = inset ? inset->getLyXText(bv) : bv->text;
- text->setCursorIntern(undo.cursor_par_offset, undo.cursor_pos);
-
- //lyxerr << "undo, inset: " << inset << endl;
-
- if (inset) {
- //lyxerr << "undo, inset owner: " << inset->owner() << endl;
-
- // Magic needed to update inset internal state
- FuncRequest cmd(bv, LFUN_INSET_EDIT, "left");
- if (inset->owner())
- inset->owner()->localDispatch(cmd);
- else
- inset->localDispatch(cmd);
- }
-
- // set cursor again to force the position to be the right one
- text->setCursorIntern(undo.cursor_par_offset, undo.cursor_pos);
-
- // Clear any selection and set the selection
- // cursor for any new selection.
- text->clearSelection();
- text->selection.cursor = text->cursor;
- text->updateCounters();
- }
-
- finishUndo();
- return true;
-}
-
-
-// Returns false if no undo possible.
-bool textUndoOrRedo(BufferView * bv,
- limited_stack<Undo> & stack,
- limited_stack<Undo> & otherstack)
-{
- if (stack.empty()) {
- /*
- * Finish the undo operation in the case there was no entry
- * on the stack to perform.
- */
- freezeUndo();
- bv->unlockInset(bv->theLockingInset());
- finishUndo();
- unFreezeUndo();
- return false;
- }
-
- Undo undo = stack.top();
- stack.pop();
- finishUndo();
-
- if (!undo_frozen) {
- otherstack.push(undo);
- otherstack.top().pars.clear();
- Buffer * buf = bv->buffer();
- ParagraphList & plist = buf->paragraphs();
- if (undo.first_par_offset + undo.last_par_offset <= int(plist.size())) {
- ParagraphList::iterator first = plist.begin();
- advance(first, undo.first_par_offset);
- ParagraphList::iterator last = plist.begin();
- advance(last, plist.size() - undo.last_par_offset + 1);
- otherstack.top().pars.insert(otherstack.top().pars.begin(), first, last);
- }
- }
-
- // Now we can unlock the inset for safety 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 const ret = performUndoOrRedo(bv, undo);
- unFreezeUndo();
- return ret;
-}
-
-} // namespace anon
-
-
-void freezeUndo()
-{
- // This is dangerous and for internal use only.
- undo_frozen = true;
-}
-
-
-void unFreezeUndo()
-{
- // This is dangerous and for internal use only.
- undo_frozen = false;
-}
-
-
-void finishUndo()
-{
- // Makes sure the next operation will be stored.
- undo_finished = true;
-}
-
-
-bool textUndo(BufferView * bv)
-{
- return textUndoOrRedo(bv, bv->buffer()->undostack(),
- bv->buffer()->redostack());
-}
-
-
-bool textRedo(BufferView * bv)
-{
- return textUndoOrRedo(bv, bv->buffer()->redostack(),
- bv->buffer()->undostack());
-}
-
-
-void recordUndo(BufferView * bv, Undo::undo_kind kind,
- ParagraphList & plist, paroffset_type first, paroffset_type last)
-{
- if (!undo_frozen) {
- recordUndo(bv, kind, plist, first, last, bv->buffer()->undostack());
- bv->buffer()->redostack().clear();
- }
-}
-
-
-void recordUndo(BufferView * bv, Undo::undo_kind kind,
- ParagraphList & plist, paroffset_type par)
-{
- recordUndo(bv, kind, plist, par, par);
-}
-
-
-void recordUndo(BufferView * bv, Undo::undo_kind kind)
-{
- recordUndo(bv, kind, bv->text->ownerParagraphs(), bv->text->cursor.par());
-}
+++ /dev/null
-// -*- C++ -*-
-/**
- * \file undo_funcs.h
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Asger Alstrup
- * \author Lars Gullik Bjønnes
- * \author John Levon
- * \author André Pönitz
- * \author Jürgen Vigna
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#ifndef UNDO_FUNCS_H
-#define UNDO_FUNCS_H
-
-#include "undo.h"
-#include "ParagraphList_fwd.h"
-#include "support/types.h"
-
-class BufferView;
-class Paragraph;
-
-/// This will undo the last action - returns false if no undo possible
-bool textUndo(BufferView *);
-
-/// This will redo the last undo - returns false if no redo possible
-bool textRedo(BufferView *);
-
-/// Makes sure the next operation will be stored
-void finishUndo();
-
-/**
- * Whilst undo is frozen, all actions do not get added
- * to the undo stack
- */
-void freezeUndo();
-
-/// Track undos again
-void unFreezeUndo();
-
-/**
- * Record undo information - call with the first paragraph that will be changed
- * and the last paragraph that will be changed. So we give an inclusive
- * range.
- * This is called before you make the changes to the paragraph, and it
- * will record the original information of the paragraphs in the undo stack.
- */
-void recordUndo(BufferView *, Undo::undo_kind kind,
- ParagraphList & plist, lyx::paroffset_type first, lyx::paroffset_type last);
-
-/// Convienience: Prepare undo when change in a single paragraph.
-void recordUndo(BufferView *, Undo::undo_kind kind,
- ParagraphList & plist, lyx::paroffset_type par);
-
-/// Convienience: Prepare undo for the paragraph that contains the cursor
-void recordUndo(BufferView *, Undo::undo_kind kind);
-
-/// Are we avoiding tracking undos currently ?
-extern bool undo_frozen;
-
-#endif // UNDO_FUNCS_H