#include "frontends/FontMetrics.h"
#include "frontends/Painter.h"
+#include "frontends/Selection.h"
#include "insets/insettext.h"
#include "insets/insetbibitem.h"
pars_[next_par].applyLayout(tclass.defaultLayout());
}
- while (!pars_[next_par].empty() && pars_[next_par].isNewline(0))
- pars_[next_par].eraseChar(0, cur.buffer().params().trackChanges);
+ while (!pars_[next_par].empty() && pars_[next_par].isNewline(0)) {
+ if (!pars_[next_par].eraseChar(0, cur.buffer().params().trackChanges))
+ break; // the character couldn't be deleted physically due to change tracking
+ }
ParIterator current_it(cur);
ParIterator last_it(cur);
cur.resetAnchor();
setCursor(cur, to.pit(), to.pos());
cur.setSelection();
+ theSelection().haveSelection(cur.selection());
}
}
-void LyXText::acceptChange(LCursor & cur)
+void LyXText::acceptOrRejectChange(LCursor & cur, bool accept)
{
- // FIXME: change tracking (MG)
-
BOOST_ASSERT(this == cur.text());
- if (!cur.selection() && cur.lastpos() != 0)
+ if (!cur.selection())
return;
- // FIXME: we must handle start = end = 0
+ recordUndoSelection(cur, Undo::ATOMIC);
- recordUndoSelection(cur, Undo::INSERT);
+ pit_type begPit = cur.selectionBegin().pit();
+ pit_type endPit = cur.selectionEnd().pit();
- DocIterator it = cur.selectionBegin();
- DocIterator et = cur.selectionEnd();
- pit_type pit = it.pit();
- for (; pit <= et.pit(); ++pit) {
- pos_type left = (pit == it.pit() ? it.pos() : 0);
- pos_type right = (pit == et.pit() ? et.pos() : pars_[pit].size());
- pars_[pit].acceptChanges(left, right);
+ pos_type begPos = cur.selectionBegin().pos();
+ pos_type endPos = cur.selectionEnd().pos();
- // merge paragraph if appropriate:
- // if (right >= pars_[pit].size() && pit + 1 < et.pit() &&
- // pars_[pit].isDeleted(pars_[pit].size())) {
- // setCursorIntern(cur, pit + 1, 0);
- // backspacePos0(cur);
- //}
- }
- finishUndo();
- cur.clearSelection();
- setCursorIntern(cur, it.pit(), 0);
-}
+ // keep selection info, because endPos becomes invalid after the first loop
+ bool endsBeforeEndOfPar = (endPos < pars_[endPit].size());
+ // first, accept/reject changes within each individual paragraph (do not consider end-of-par)
+
+ for (pit_type pit = begPit; pit <= endPit; ++pit) {
+ pos_type parSize = pars_[pit].size();
-void LyXText::rejectChange(LCursor & cur)
-{
- // FIXME: change tracking (MG)
-
- BOOST_ASSERT(this == cur.text());
+ // ignore empty paragraphs; otherwise, an assertion will fail for
+ // acceptChanges(bparams, 0, 0) or rejectChanges(bparams, 0, 0)
+ if (parSize == 0)
+ continue;
- if (!cur.selection() && cur.lastpos() != 0)
- return;
+ // do not consider first paragraph if the cursor starts at pos size()
+ if (pit == begPit && begPos == parSize)
+ continue;
- // FIXME: we must handle start = end = 0
+ // do not consider last paragraph if the cursor ends at pos 0
+ if (pit == endPit && endPos == 0)
+ break; // last iteration anyway
- recordUndoSelection(cur, Undo::INSERT);
+ pos_type left = (pit == begPit ? begPos : 0);
+ pos_type right = (pit == endPit ? endPos : parSize);
- DocIterator it = cur.selectionBegin();
- DocIterator et = cur.selectionEnd();
- pit_type pit = it.pit();
- for (; pit <= et.pit(); ++pit) {
- pos_type left = (pit == it.pit() ? it.pos() : 0);
- pos_type right = (pit == et.pit() ? et.pos() : pars_[pit].size());
- pars_[pit].rejectChanges(left, right);
+ if (accept) {
+ pars_[pit].acceptChanges(cur.buffer().params(), left, right);
+ } else {
+ pars_[pit].rejectChanges(cur.buffer().params(), left, right);
+ }
+ }
+
+ // next, accept/reject imaginary end-of-par characters
+
+ for (pit_type pit = begPit; pit <= endPit; ++pit) {
+ pos_type pos = pars_[pit].size();
+
+ // skip if the selection ends before the end-of-par
+ if (pit == endPit && endsBeforeEndOfPar)
+ break; // last iteration anyway
+
+ // skip if this is not the last paragraph of the document
+ // note: the user should be able to accept/reject the par break of the last par!
+ if (pit == endPit && pit != pars_.size() - 1)
+ break; // last iteration anway
+
+ if (accept) {
+ if (pars_[pit].isInserted(pos)) {
+ pars_[pit].setChange(pos, Change(Change::UNCHANGED));
+ } else if (pars_[pit].isDeleted(pos)) {
+ if (pit == pars_.size() - 1) {
+ // we cannot remove a par break at the end of the last paragraph;
+ // instead, we mark it unchanged
+ pars_[pit].setChange(pos, Change(Change::UNCHANGED));
+ } else {
+ mergeParagraph(cur.buffer().params(), pars_, pit);
+ --endPit;
+ --pit;
+ }
+ }
+ } else {
+ if (pars_[pit].isDeleted(pos)) {
+ pars_[pit].setChange(pos, Change(Change::UNCHANGED));
+ } else if (pars_[pit].isInserted(pos)) {
+ if (pit == pars_.size() - 1) {
+ // we mark the par break at the end of the last paragraph unchanged
+ pars_[pit].setChange(pos, Change(Change::UNCHANGED));
+ } else {
+ mergeParagraph(cur.buffer().params(), pars_, pit);
+ --endPit;
+ --pit;
+ }
+ }
+ }
+ }
- // merge paragraph if appropriate:
- // if (right >= pars_[pit].size() && pit + 1 < et.pit() &&
- // pars_[pit].isInserted(pars_[pit].size())) {
- // setCursorIntern(cur, pit + 1, 0);
- // backspacePos0(cur);
- //}
+ // finally, invoke the DEPM
+ // FIXME: the following code will be changed in the near future
+ setCursorIntern(cur, endPit, 0);
+ for (pit_type pit = endPit - 1; pit >= begPit; --pit) {
+ bool dummy;
+ LCursor old = cur;
+ setCursorIntern(cur, pit, 0);
+ deleteEmptyParagraphMechanism(cur, old, dummy);
}
+
finishUndo();
cur.clearSelection();
- setCursorIntern(cur, it.pit(), 0);
+ setCursorIntern(cur, begPit, begPos);
+ cur.updateFlags(Update::Force);
+ updateLabels(cur.buffer());
}
// this is the code for a normal delete, not pasting
// any paragraphs
recordUndo(cur, Undo::DELETE);
- par.eraseChar(cur.pos(), cur.buffer().params().trackChanges);
- if (par.isDeleted(cur.pos()))
+ if(!par.eraseChar(cur.pos(), cur.buffer().params().trackChanges)) {
+ // the character has been logically deleted only => skip it
cur.forwardPosNoDescend();
+ }
needsUpdate = true;
} else {
if (cur.pit() == cur.lastpit())
odocstringstream os;
if (buf.params().trackChanges)
- os << "[C] ";
+ os << _("[Change Tracking] ");
Change change = par.lookupChange(cur.pos());
}
-//pos_type LyXText::x2pos(pit_type pit, int row, int x) const
-//{
-// int lastx = 0;
-// int currx = 0;
-// Paragraph const & par = pars_[pit];
-// Row const & r = par.rows()[row];
-// int pos = r.pos();
-// for (; currx < x && pos < r.endpos(); ++pos) {
-// lastx = currx;
-// currx += singleWidth(buffer, par, pos);
-// }
-// if (abs(lastx - x) < abs(currx - x) && pos != r.pos())
-// --pos;
-// return pos;
-//}
-
-
-pos_type LyXText::x2pos(BufferView const & bv, pit_type pit, int row,
- int x) const
-{
- TextMetrics const & tm = bv.textMetrics(this);
- ParagraphMetrics const & pm = tm.parMetrics(pit);
- BOOST_ASSERT(!pm.rows().empty());
- BOOST_ASSERT(row < int(pm.rows().size()));
- bool bound = false;
- Row const & r = pm.rows()[row];
- return r.pos() + tm.getColumnNearX(pit, r, x, bound);
-}
-
-
-//int LyXText::pos2x(pit_type pit, pos_type pos) const
-//{
-// Paragraph const & par = pars_[pit];
-// Row const & r = par.rows()[row];
-// int x = 0;
-// pos -= r.pos();
-//}
-
-
void LyXText::setCursorFromCoordinates(LCursor & cur, int const x, int const y)
{
BOOST_ASSERT(this == cur.text());
bool bound = false;
int xx = x;
- int right_margin = tm.rightMargin(pm);
pos_type const pos = row.pos()
+ tm.getColumnNearX(pit, row, xx, bound);
<< endl;
setCursor(cur, pit, pos, true, bound);
- return;
+ // remember new position.
+ cur.setTargetX();
}