+
+void Paragraph::Pimpl::acceptChange(pos_type start, pos_type end)
+{
+ if (!tracking())
+ return;
+
+ if (!size()) {
+ changes_.reset(new Changes(Change::UNCHANGED));
+ return;
+ }
+
+ lyxerr[Debug::CHANGES] << "acceptchange" << endl;
+ pos_type i = start;
+
+ for (; i < end; ++i) {
+ switch (lookupChange(i).type) {
+ case Change::UNCHANGED:
+ break;
+
+ case Change::INSERTED:
+ changes_->set(Change::UNCHANGED, i);
+ break;
+
+ case Change::DELETED:
+ // Suppress access to nonexistent
+ // "end-of-paragraph char":
+ if (i < size()) {
+ eraseIntern(i);
+ changes_->erase(i);
+ --end;
+ --i;
+ }
+ break;
+ }
+ }
+
+ lyxerr[Debug::CHANGES] << "endacceptchange" << endl;
+ changes_->reset(Change::UNCHANGED);
+}
+
+
+void Paragraph::Pimpl::rejectChange(pos_type start, pos_type end)
+{
+ if (!tracking())
+ return;
+
+ if (!size()) {
+ changes_.reset(new Changes(Change::UNCHANGED));
+ return;
+ }
+
+ pos_type i = start;
+
+ for (; i < end; ++i) {
+ switch (lookupChange(i).type) {
+ case Change::UNCHANGED:
+ break;
+
+ case Change::INSERTED:
+ if (i < size()) {
+ eraseIntern(i);
+ changes_->erase(i);
+ --end;
+ --i;
+ }
+ break;
+
+ case Change::DELETED:
+ changes_->set(Change::UNCHANGED, i);
+ // No real char at position size():
+ if (i < size() && owner_->isInset(i))
+ owner_->getInset(i)->markErased(false);
+ break;
+ }
+ }
+ changes_->reset(Change::UNCHANGED);
+}
+
+
+Paragraph::value_type Paragraph::Pimpl::getChar(pos_type pos) const
+{
+ return owner_->getChar(pos);
+}
+
+
+void Paragraph::Pimpl::insertChar(pos_type pos, value_type c, Change change)
+{
+ BOOST_ASSERT(pos <= size());
+
+ if (tracking()) {
+ changes_->record(change, pos);
+ }
+
+ // This is actually very common when parsing buffers (and
+ // maybe inserting ascii text)
+ if (pos == size()) {
+ // when appending characters, no need to update tables
+ owner_->text_.push_back(c);
+ return;
+ }
+
+ owner_->text_.insert(owner_->text_.begin() + pos, c);