John&JMarc's change tracking patch

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@10424 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Jean-Marc Lasgouttes 2005-09-07 10:37:05 +00:00
parent a18c3cda5c
commit 52a2eb2c52
18 changed files with 163 additions and 59 deletions

View File

@ -1,3 +1,32 @@
2005-08-03 Jean-Marc Lasgouttes <lasgouttes@lyx.org>
* text.C (read): remove unused variable.
(readParToken): remove static Change variable (never good in
recursive settings...); add it as a parameter instead.
* paragraph_pimpl.C (acceptChange): make debug info conditional.
* metricsinfo.C (PainterInfo): add new member erased_.
* rowpainter.C (RowPainter): add erased_ member, initialized from
PainterInfo.
(paintInset): pass erased_ to Inset::draw.
* lyxfunc.C (lookupChange): new function. Tells whether change
tracking is disabled at a given postion.
(getStatus): disable some actions when in deleted text with change
tracking.
2005-08-03 John Levon <levon@movementarian.org>
* tabular.C (appendColumn, setMultiColumn): adapt to change to
InsetText::clear().
* paragraph_pimpl.C (markErased): add bool argument and handle it.
Also make sure to mark insets recursively.
(rejectChange, erase): be recursive
* paragraph.C (markErased): add bool argument.
2005-08-04 Jean-Marc Lasgouttes <lasgouttes@lyx.org>
* lyxfind.C (findNextChange): tiny cleanup.

View File

@ -1,3 +1,20 @@
2005-08-03 Jean-Marc Lasgouttes <lasgouttes@lyx.org>
* insettabular.C (draw): pass PainterInfro::erased_ to
drawCellLines
(drawCellLines): add an erased bool and handle it.
2005-08-03 John Levon <levon@movementarian.org>
* insettext.C (clear): remove bool argument.
(read): adapt to clear() changes.
* insettabular.C (cutSelection): adapt to MarkErased changes.
* insettext.C (markErased):
* insettabular.C (markErased):
* insetbase.C (markErased): add bool argument.
2005-09-06 Jürgen Spitzmüller <j.spitzmueller@gmx.de>
* insettabular.C: mark tabular_stack_ (of CutAndPaste) dirty

View File

@ -273,7 +273,7 @@ std::string const & InsetBase::getInsetName() const
}
void InsetBase::markErased()
void InsetBase::markErased(bool)
{}

View File

@ -372,12 +372,12 @@ public:
virtual mode_type currentMode() const { return UNDECIDED_MODE; }
/// returns whether this inset is allowed in other insets of given mode
virtual bool allowedIn(mode_type) const { return true; }
/// is this inset allowed within a font change?
virtual bool noFontChange() const { return false; }
///
virtual void markErased();
/// mark the inset as erased or not
virtual void markErased(bool erased);
/// pretty arbitrary
virtual int width() const { return 10; }
/// pretty arbitrary

View File

@ -304,10 +304,10 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) const
|| y + d < 0
|| y - a > bv->workHeight()) {
cell(idx)->draw(nullpi, cx, y);
drawCellLines(nop, nx, y, i, idx);
drawCellLines(nop, nx, y, i, idx, pi.erased_);
} else {
cell(idx)->draw(pi, cx, y);
drawCellLines(pi.pain, nx, y, i, idx);
drawCellLines(pi.pain, nx, y, i, idx, pi.erased_);
}
nx += tabular.getWidthOfColumn(idx);
++idx;
@ -366,28 +366,35 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
void InsetTabular::drawCellLines(Painter & pain, int x, int y,
row_type row, idx_type cell) const
row_type row, idx_type cell, bool erased) const
{
int x2 = x + tabular.getWidthOfColumn(cell);
bool on_off = false;
LColor::color col = LColor::tabularline;
LColor::color onoffcol = LColor::tabularonoffline;
if (erased) {
col = LColor::strikeout;
onoffcol = LColor::strikeout;
}
if (!tabular.topAlreadyDrawn(cell)) {
on_off = !tabular.topLine(cell);
pain.line(x, y - tabular.getAscentOfRow(row),
x2, y - tabular.getAscentOfRow(row),
on_off ? LColor::tabularonoffline : LColor::tabularline,
on_off ? onoffcol : col,
on_off ? Painter::line_onoffdash : Painter::line_solid);
}
on_off = !tabular.bottomLine(cell);
pain.line(x, y + tabular.getDescentOfRow(row),
x2, y + tabular.getDescentOfRow(row),
on_off ? LColor::tabularonoffline : LColor::tabularline,
on_off ? onoffcol : col,
on_off ? Painter::line_onoffdash : Painter::line_solid);
if (!tabular.leftAlreadyDrawn(cell)) {
on_off = !tabular.leftLine(cell);
pain.line(x, y - tabular.getAscentOfRow(row),
x, y + tabular.getDescentOfRow(row),
on_off ? LColor::tabularonoffline : LColor::tabularline,
on_off ? onoffcol : col,
on_off ? Painter::line_onoffdash : Painter::line_solid);
}
on_off = !tabular.rightLine(cell);
@ -395,7 +402,7 @@ void InsetTabular::drawCellLines(Painter & pain, int x, int y,
y - tabular.getAscentOfRow(row),
x2 - tabular.getAdditionalWidth(cell),
y + tabular.getDescentOfRow(row),
on_off ? LColor::tabularonoffline : LColor::tabularline,
on_off ? onoffcol : col,
on_off ? Painter::line_onoffdash : Painter::line_solid);
}
@ -435,7 +442,7 @@ void InsetTabular::edit(LCursor & cur, bool left)
void InsetTabular::doDispatch(LCursor & cur, FuncRequest & cmd)
{
lyxerr << "# InsetTabular::dispatch: cmd: " << cmd << endl;
lyxerr << "# InsetTabular::doDispatch: cmd: " << cmd << endl;
lyxerr << " cur:\n" << cur << endl;
CursorSlice sl = cur.top();
LCursor & bvcur = cur.bv().cursor();
@ -1770,13 +1777,19 @@ void InsetTabular::cutSelection(LCursor & cur)
if (!cur.selection())
return;
bool const track = cur.buffer().params().tracking_changes;
row_type rs, re;
col_type cs, ce;
getSelection(cur, rs, re, cs, ce);
for (row_type i = rs; i <= re; ++i)
for (col_type j = cs; j <= ce; ++j)
cell(tabular.getCellNumber(i, j))->clear(track);
for (row_type i = rs; i <= re; ++i) {
for (col_type j = cs; j <= ce; ++j) {
shared_ptr<InsetText> t
= cell(tabular.getCellNumber(i, j));
if (cur.buffer().params().tracking_changes)
t->markErased(true);
else
t->clear();
}
}
// cursor position might be invalid now
cur.pos() = cur.lastpos();
@ -1821,10 +1834,10 @@ LyXText * InsetTabular::getText(int idx) const
}
void InsetTabular::markErased()
void InsetTabular::markErased(bool erased)
{
for (idx_type idx = 0; idx < nargs(); ++idx)
cell(idx)->markErased();
cell(idx)->markErased(erased);
}

View File

@ -115,7 +115,7 @@ public:
LyXText * getText(int) const;
///
void markErased();
void markErased(bool);
// this should return true if we have a "normal" cell, otherwise true.
// "normal" means without width set!
@ -156,7 +156,7 @@ private:
///
void drawCellLines(Painter &, int x, int y, row_type row,
idx_type cell) const;
idx_type cell, bool erased) const;
///
void setCursorFromCoordinates(LCursor & cur, int x, int y) const;

View File

@ -108,14 +108,17 @@ void InsetText::init()
}
void InsetText::clear(bool just_mark_erased)
void InsetText::markErased(bool erased)
{
ParagraphList & pars = paragraphs();
for_each(pars.begin(), pars.end(),
bind(&Paragraph::markErased, _1, erased));
}
void InsetText::clear()
{
ParagraphList & pars = paragraphs();
if (just_mark_erased) {
for_each(pars.begin(), pars.end(),
bind(&Paragraph::markErased, _1));
return;
}
// This is a gross hack...
LyXLayout_ptr old_layout = pars.begin()->layout();
@ -142,7 +145,7 @@ void InsetText::write(Buffer const & buf, ostream & os) const
void InsetText::read(Buffer const & buf, LyXLex & lex)
{
clear(false);
clear();
#ifdef WITH_WARNINGS
#warning John, look here. Doesnt make much sense.
@ -352,7 +355,7 @@ void InsetText::markNew(bool track_changes)
void InsetText::setText(string const & data, LyXFont const & font)
{
clear(false);
clear();
Paragraph & first = paragraphs().front();
for (unsigned int i = 0; i < data.length(); ++i)
first.insertChar(i, data[i], font);

View File

@ -40,8 +40,8 @@ public:
explicit InsetText(BufferParams const &);
///
InsetText();
/// empty inset to empty par, or just mark as erased
void clear(bool just_mark_erased);
/// empty inset to empty par
void clear();
///
void read(Buffer const & buf, LyXLex & lex);
///
@ -107,7 +107,8 @@ public:
bool getStatus(LCursor & cur, FuncRequest const & cmd, FuncStatus &) const;
/// mark as erased for change tracking
void markErased() { clear(true); }
void markErased(bool erased);
/**
* Mark as new. Used when pasting in tabular, and adding rows
* or columns. Note that pasting will ensure that tracking already

View File

@ -174,6 +174,28 @@ bool getStatus(LCursor cursor,
return res;
}
/** Return the change status at cursor position, taking in account the
* status at each level of the document iterator (a table in a deleted
* footnote is deleted).
* When \param outer is true, the top slice is not looked at.
*/
Change::Type lookupChange(DocIterator const & dit, bool outer = false)
{
size_t const depth = dit.depth() - outer ? 1 : 0;
for (size_t i = 0 ; i < depth ; ++i) {
CursorSlice const & slice = dit[i];
if (!slice.inset().inMathed()
&& slice.pos() < slice.paragraph().size()) {
Change::Type const ch = slice.paragraph().lookupChange(slice.pos());
if (ch != Change::UNCHANGED)
return ch;
}
}
return Change::UNCHANGED;
}
}
LyXFunc::LyXFunc(LyXView * lv)
@ -594,6 +616,15 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
flag.enabled(false);
}
// Are we in a DELETED change-tracking region?
if (buf && buf->params().tracking_changes
&& lookupChange(cur, true) == Change::DELETED
&& !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
&& !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
flag.message(N_("This portion of the document is deleted."));
flag.enabled(false);
}
// the default error message if we disable the command
if (!flag.enabled() && flag.message().empty())
flag.message(N_("Command disabled"));

View File

@ -47,7 +47,7 @@ MetricsInfo::MetricsInfo(BufferView * bv, LyXFont const & font, int textwidth)
PainterInfo::PainterInfo(BufferView * bv, Painter & painter)
: pain(painter), ltr_pos(false)
: pain(painter), ltr_pos(false), erased_(false)
{
base.bv = bv;
}

View File

@ -92,6 +92,8 @@ public:
Painter & pain;
/// Whether the text at this point is right-to-left (for InsetNewline)
bool ltr_pos;
/// Whether the parent is deleted (change tracking)
bool erased_;
};
class TextMetricsInfo {};

View File

@ -1659,9 +1659,9 @@ void Paragraph::setChange(lyx::pos_type pos, Change::Type type)
}
void Paragraph::markErased()
void Paragraph::markErased(bool erased)
{
pimpl_->markErased();
pimpl_->markErased(erased);
}

View File

@ -231,8 +231,8 @@ public:
/// reject change
void rejectChange(lyx::pos_type start, lyx::pos_type end);
/// mark whole par as erased
void markErased();
/// mark whole par as erased or not
void markErased(bool erased);
/// Paragraphs can contain "manual labels", for example, Description
/// environment. The text for this user-editable label is stored in

View File

@ -165,15 +165,21 @@ Change const Paragraph::Pimpl::lookupChangeFull(pos_type pos) const
}
void Paragraph::Pimpl::markErased()
void Paragraph::Pimpl::markErased(bool erased)
{
BOOST_ASSERT(tracking());
// FIXME: we should actually remove INSERTED chars.
// difficult because owning insettexts/tabulars need
// to update themselves when rows etc. change
changes_->set(Change::DELETED, 0, size());
changes_->reset(Change::DELETED);
if (erased) {
erase(0, size());
} else {
pos_type i = 0;
for (pos_type i = 0; i < size(); ++i) {
changes_->set(Change::UNCHANGED, i);
if (owner_->isInset(i))
owner_->getInset(i)->markErased(false);
}
}
}
@ -187,7 +193,7 @@ void Paragraph::Pimpl::acceptChange(pos_type start, pos_type end)
return;
}
lyxerr << "acceptchange" << endl;
lyxerr[Debug::CHANGES] << "acceptchange" << endl;
pos_type i = start;
for (; i < end; ++i) {
@ -208,7 +214,7 @@ void Paragraph::Pimpl::acceptChange(pos_type start, pos_type end)
}
}
lyxerr << "endacceptchange" << endl;
lyxerr[Debug::CHANGES] << "endacceptchange" << endl;
changes_->reset(Change::UNCHANGED);
}
@ -239,6 +245,8 @@ void Paragraph::Pimpl::rejectChange(pos_type start, pos_type end)
case Change::DELETED:
changes_->set(Change::UNCHANGED, i);
if (owner_->isInset(i))
owner_->getInset(i)->markErased(false);
break;
}
}
@ -353,9 +361,8 @@ bool Paragraph::Pimpl::erase(pos_type pos)
// only allow the actual removal if it was /new/ text
if (changetype != Change::INSERTED) {
if (owner_->text_[pos] == Paragraph::META_INSET) {
owner_->getInset(pos)->markErased();
}
if (owner_->isInset(pos))
owner_->getInset(pos)->markErased(true);
return false;
}
}

View File

@ -55,7 +55,7 @@ public:
/// set change at pos
void setChange(lyx::pos_type pos, Change::Type type);
/// mark as erased
void markErased();
void markErased(bool);
/// accept change
void acceptChange(lyx::pos_type start, lyx::pos_type end);
/// reject change

View File

@ -101,6 +101,9 @@ private:
pit_type const pit_;
Paragraph const & par_;
/// is row erased? (change tracking)
bool erased_;
// Looks ugly - is
double const xo_;
int const yo_; // current baseline
@ -116,6 +119,7 @@ RowPainter::RowPainter(PainterInfo & pi,
LyXText const & text, pit_type pit, Row const & row, int x, int y)
: bv_(*pi.base.bv), pain_(pi.pain), text_(text), pars_(text.paragraphs()),
row_(row), pit_(pit), par_(text.paragraphs()[pit]),
erased_(pi.erased_),
xo_(x), yo_(y), width_(text_.width())
{
RowMetrics m = text_.computeRowMetrics(pit, row_);
@ -152,6 +156,7 @@ void RowPainter::paintInset(pos_type const pos, LyXFont const & font)
PainterInfo pi(const_cast<BufferView *>(&bv_), pain_);
pi.base.font = font;
pi.ltr_pos = (text_.bidi.level(pos) % 2 == 0);
pi.erased_ = erased_ || isDeletedText(par_, pos);
theCoords.insets().add(inset, int(x_), yo_);
inset->drawSelection(pi, int(x_), yo_);
inset->draw(pi, int(x_), yo_);
@ -299,9 +304,7 @@ void RowPainter::paintFromPos(pos_type & vpos)
double const orig_x = x_;
char const c = par_.getChar(pos);
if (c == Paragraph::META_INSET) {
if (par_.isInset(pos)) {
paintInset(pos, orig_font);
++vpos;
paintForeignMark(orig_x, orig_font);
@ -309,6 +312,7 @@ void RowPainter::paintFromPos(pos_type & vpos)
}
// usual characters, no insets
char const c = par_.getChar(pos);
// special case languages
std::string const & lang = orig_font.language()->lang();

View File

@ -515,7 +515,7 @@ void LyXTabular::appendColumn(BufferParams const & bp, idx_type const cell)
}
//++column;
for (row_type i = 0; i < rows_; ++i) {
cell_info[i][column + 1].inset->clear(false);
cell_info[i][column + 1].inset->clear();
if (bp.tracking_changes)
cell_info[i][column + 1].inset->markNew(true);
}
@ -1350,7 +1350,7 @@ void LyXTabular::setMultiColumn(Buffer * buffer, idx_type cell,
cellstruct & cs1 = cellinfo_of_cell(cell + i);
cs1.multicolumn = CELL_PART_OF_MULTICOLUMN;
cs.inset->appendParagraphs(buffer, cs1.inset->paragraphs());
cs1.inset->clear(false);
cs1.inset->clear();
}
set_row_column_number_info();
}

View File

@ -152,10 +152,8 @@ int numberOfHfills(Paragraph const & par, Row const & row)
void readParToken(Buffer const & buf, Paragraph & par, LyXLex & lex,
string const & token, LyXFont & font)
string const & token, LyXFont & font, Change & change)
{
static Change change;
BufferParams const & bp = buf.params();
if (token[0] != '\\') {
@ -346,10 +344,11 @@ void readParagraph(Buffer const & buf, Paragraph & par, LyXLex & lex)
lex.nextToken();
string token = lex.getString();
LyXFont font;
Change change;
while (lex.isOK()) {
readParToken(buf, par, lex, token, font);
readParToken(buf, par, lex, token, font, change);
lex.nextToken();
token = lex.getString();
@ -1989,8 +1988,6 @@ void LyXText::write(Buffer const & buf, std::ostream & os) const
bool LyXText::read(Buffer const & buf, LyXLex & lex)
{
static Change current_change;
Paragraph::depth_type depth = 0;
while (lex.isOK()) {