docstring parbreak(Paragraph const & par)
{
- odocstringstream ods;
- ods << '\n';
+ odocstringstream os;
+ os << '\n';
// only add blank line if we're not in an ERT or Listings inset
if (par.ownerCode() != ERT_CODE
&& par.ownerCode() != LISTINGS_CODE)
- ods << '\n';
- return ods.str();
+ os << '\n';
+ return os.str();
}
} // namespace anon
}
+bool Cursor::posVisRight(bool skip_inset)
+{
+ Cursor new_cur = *this; // where we will move to
+ pos_type left_pos; // position visually left of current cursor
+ pos_type right_pos; // position visually right of current cursor
+ bool new_pos_is_RTL; // is new position we're moving to RTL?
+
+ getSurroundingPos(left_pos, right_pos);
+
+ LYXERR(Debug::RTL, left_pos <<"|"<< right_pos << " (pos: "<< pos() <<")");
+
+ // Are we at an inset?
+ new_cur.pos() = right_pos;
+ new_cur.boundary(false);
+ if (!skip_inset &&
+ text()->checkAndActivateInsetVisual(new_cur, right_pos >= pos(), false)) {
+ // we actually move the cursor at the end of this function, for now
+ // we just keep track of the new position in new_cur...
+ LYXERR(Debug::RTL, "entering inset at: " << new_cur.pos());
+ }
+
+ // Are we already at rightmost pos in row?
+ else if (text()->empty() || right_pos == -1) {
+
+ new_cur = *this;
+ if (!new_cur.posVisToNewRow(false)) {
+ LYXERR(Debug::RTL, "not moving!");
+ return false;
+ }
+
+ // we actually move the cursor at the end of this function, for now
+ // just keep track of the new position in new_cur...
+ LYXERR(Debug::RTL, "right edge, moving: " << int(new_cur.pit()) << ","
+ << int(new_cur.pos()) << "," << (new_cur.boundary() ? 1 : 0));
+
+ }
+ // normal movement to the right
+ else {
+ new_cur = *this;
+ // Recall, if the cursor is at position 'x', that means *before*
+ // the character at position 'x'. In RTL, "before" means "to the
+ // right of", in LTR, "to the left of". So currently our situation
+ // is this: the position to our right is 'right_pos' (i.e., we're
+ // currently to the left of 'right_pos'). In order to move to the
+ // right, it depends whether or not the character at 'right_pos' is RTL.
+ new_pos_is_RTL = paragraph().getFontSettings(
+ bv().buffer().params(), right_pos).isVisibleRightToLeft();
+ // If the character at 'right_pos' *is* LTR, then in order to move to
+ // the right of it, we need to be *after* 'right_pos', i.e., move to
+ // position 'right_pos' + 1.
+ if (!new_pos_is_RTL) {
+ new_cur.pos() = right_pos + 1;
+ // set the boundary to true in two situations:
+ if (
+ // 1. if new_pos is now lastpos (which means that we're moving
+ // right to the end of an LTR chunk which is at the end of an
+ // RTL paragraph);
+ new_cur.pos() == lastpos()
+ // 2. if the position *after* right_pos is RTL (we want to be
+ // *after* right_pos, not before right_pos + 1!)
+ || paragraph().getFontSettings(bv().buffer().params(),
+ new_cur.pos()).isVisibleRightToLeft()
+ )
+ new_cur.boundary(true);
+ else // set the boundary to false
+ new_cur.boundary(false);
+ }
+ // Otherwise (if the character at position 'right_pos' is RTL), then
+ // moving to the right of it is as easy as setting the new position
+ // to 'right_pos'.
+ else {
+ new_cur.pos() = right_pos;
+ new_cur.boundary(false);
+ }
+
+ }
+
+ bool moved = (new_cur.pos() != pos()
+ || new_cur.pit() != pit()
+ || new_cur.boundary() != boundary());
+
+ if (moved) {
+ LYXERR(Debug::RTL, "moving to: " << new_cur.pos()
+ << (new_cur.boundary() ? " (boundary)" : ""));
+ *this = new_cur;
+ }
+
+ return moved;
+}
+
+
+bool Cursor::posVisLeft(bool skip_inset)
+{
+ Cursor new_cur = *this; // where we will move to
+ pos_type left_pos; // position visually left of current cursor
+ pos_type right_pos; // position visually right of current cursor
+ bool new_pos_is_RTL; // is new position we're moving to RTL?
+
+ getSurroundingPos(left_pos, right_pos);
+
+ LYXERR(Debug::RTL, left_pos <<"|"<< right_pos << " (pos: "<< pos() <<")");
+
+ // Are we at an inset?
+ new_cur.pos() = left_pos;
+ new_cur.boundary(false);
+ if (!skip_inset &&
+ text()->checkAndActivateInsetVisual(new_cur, left_pos >= pos(), true)) {
+ // we actually move the cursor at the end of this function, for now
+ // we just keep track of the new position in new_cur...
+ LYXERR(Debug::RTL, "entering inset at: " << new_cur.pos());
+ }
+
+ // Are we already at leftmost pos in row?
+ else if (text()->empty() || left_pos == -1) {
+
+ new_cur = *this;
+ if (!new_cur.posVisToNewRow(true)) {
+ LYXERR(Debug::RTL, "not moving!");
+ return false;
+ }
+
+ // we actually move the cursor at the end of this function, for now
+ // just keep track of the new position in new_cur...
+ LYXERR(Debug::RTL, "left edge, moving: " << int(new_cur.pit()) << ","
+ << int(new_cur.pos()) << "," << (new_cur.boundary() ? 1 : 0));
+
+ }
+ // normal movement to the left
+ else {
+ new_cur = *this;
+ // Recall, if the cursor is at position 'x', that means *before*
+ // the character at position 'x'. In RTL, "before" means "to the
+ // right of", in LTR, "to the left of". So currently our situation
+ // is this: the position to our left is 'left_pos' (i.e., we're
+ // currently to the right of 'left_pos'). In order to move to the
+ // left, it depends whether or not the character at 'left_pos' is RTL.
+ new_pos_is_RTL = paragraph().getFontSettings(
+ bv().buffer().params(), left_pos).isVisibleRightToLeft();
+ // If the character at 'left_pos' *is* RTL, then in order to move to
+ // the left of it, we need to be *after* 'left_pos', i.e., move to
+ // position 'left_pos' + 1.
+ if (new_pos_is_RTL) {
+ new_cur.pos() = left_pos + 1;
+ // set the boundary to true in two situations:
+ if (
+ // 1. if new_pos is now lastpos (which means that we're moving left
+ // to the end of an RTL chunk which is at the end of an LTR
+ // paragraph);
+ new_cur.pos() == lastpos()
+ // 2. if the position *after* left_pos is not RTL (we want to be
+ // *after* left_pos, not before left_pos + 1!)
+ || !paragraph().getFontSettings(bv().buffer().params(),
+ new_cur.pos()).isVisibleRightToLeft()
+ )
+ new_cur.boundary(true);
+ else // set the boundary to false
+ new_cur.boundary(false);
+ }
+ // Otherwise (if the character at position 'left_pos' is LTR), then
+ // moving to the left of it is as easy as setting the new position
+ // to 'left_pos'.
+ else {
+ new_cur.pos() = left_pos;
+ new_cur.boundary(false);
+ }
+
+ }
+
+ bool moved = (new_cur.pos() != pos()
+ || new_cur.pit() != pit()
+ || new_cur.boundary() != boundary());
+
+ if (moved) {
+ LYXERR(Debug::RTL, "moving to: " << new_cur.pos()
+ << (new_cur.boundary() ? " (boundary)" : ""));
+ *this = new_cur;
+ }
+
+ return moved;
+}
+
+
void Cursor::getSurroundingPos(pos_type & left_pos, pos_type & right_pos)
{
// preparing bidi tables
{
if (!selection())
return *this;
- DocIterator di = (anchor() < top() ? anchor_ : *this);
+
+ DocIterator di;
+ // FIXME: This is a work-around for the problem that
+ // CursorSlice doesn't keep track of the boundary.
+ if (anchor() == top())
+ di = anchor_.boundary() > boundary() ? anchor_ : *this;
+ else
+ di = anchor() < top() ? anchor_ : *this;
di.resize(depth());
return di;
}
{
if (!selection())
return *this;
- DocIterator di = (anchor() > top() ? anchor_ : *this);
+
+ DocIterator di;
+ // FIXME: This is a work-around for the problem that
+ // CursorSlice doesn't keep track of the boundary.
+ if (anchor() == top())
+ di = anchor_.boundary() < boundary() ? anchor_ : *this;
+ else
+ di = anchor() > top() ? anchor_ : *this;
+
if (di.depth() > depth()) {
di.resize(depth());
++di.pos();
void Cursor::setSelection()
{
- selection() = true;
+ setSelection(true);
// A selection with no contents is not a selection
// FIXME: doesnt look ok
- if (pit() == anchor().pit() && pos() == anchor().pos())
- selection() = false;
+ if (idx() == anchor().idx() &&
+ pit() == anchor().pit() &&
+ pos() == anchor().pos())
+ setSelection(false);
}
void Cursor::setSelection(DocIterator const & where, int n)
{
setCursor(where);
- selection() = true;
+ setSelection(true);
anchor_ = where;
pos() += n;
}
void Cursor::clearSelection()
{
- selection() = false;
- mark() = false;
+ setSelection(false);
+ setMark(false);
resetAnchor();
}
cap::saveSelection(*this);
resetAnchor();
- selection() = sel;
+ setSelection(sel);
return true;
}
// let's require two backspaces for 'big stuff' and
// highlight on the first
resetAnchor();
- selection() = true;
+ setSelection(true);
--pos();
} else {
--pos();
// 'clever' UI hack: only erase large items if previously slected
if (pos() != lastpos() && nextAtom()->nargs() > 0) {
resetAnchor();
- selection() = true;
+ setSelection(true);
++pos();
} else {
plainErase();
<< pos() << ' ' << lastpos() << " in idx: " << idx()
<< " in atom: '";
odocstringstream os;
- WriteStream wi(os, false, true);
+ WriteStream wi(os, false, true, false);
inset().asInsetMath()->write(wi);
lyxerr << to_utf8(os.str()) << endl;
pos() = lastpos();
safe = cap::grabAndEraseSelection(*this);
}
+ recordUndoInset();
+
if (lastpos() != 0) {
// something left in the cell
if (pos() == 0) {
}
} else {
// nothing left in the cell
- pullArg();
+ popBackward();
plainErase();
+ resetAnchor();
}
insert(safe);
}
}
-docstring Cursor::selectionAsString(bool label) const
+docstring Cursor::selectionAsString(bool with_label) const
{
if (!selection())
return docstring();
+ int const label = with_label
+ ? AS_STR_LABEL | AS_STR_INSETS : AS_STR_INSETS;
+
if (inTexted()) {
+ idx_type const startidx = selBegin().idx();
+ idx_type const endidx = selEnd().idx();
+ if (startidx != endidx) {
+ // multicell selection
+ InsetTabular * table = inset().asInsetTabular();
+ LASSERT(table, return docstring());
+ return table->asString(startidx, endidx);
+ }
+
ParagraphList const & pars = text()->paragraphs();
- // should be const ...
- pit_type startpit = selBegin().pit();
- pit_type endpit = selEnd().pit();
+ pit_type const startpit = selBegin().pit();
+ pit_type const endpit = selEnd().pit();
size_t const startpos = selBegin().pos();
size_t const endpos = selEnd().pos();
}
-docstring Cursor::currentState()
+docstring Cursor::currentState() const
{
if (inMathed()) {
odocstringstream os;
}
-docstring Cursor::getPossibleLabel()
+docstring Cursor::getPossibleLabel() const
{
return inMathed() ? from_ascii("eq:") : text()->getPossibleLabel(*this);
}
{
if (DocIterator::fixIfBroken()) {
clearSelection();
- resetAnchor();
return true;
}
return false;
return false;
// Set cursor
setCursor(dit);
- selection() = false;
- resetAnchor();
+ clearSelection();
fixIfBroken();
return true;
}
return false;
// Set cursor
setCursor(dit);
- selection() = false;
- resetAnchor();
+ clearSelection();
fixIfBroken();
return true;
}
-void Cursor::finishUndo()
+void Cursor::finishUndo() const
{
bv_->buffer().undo().finishUndo();
}
-void Cursor::recordUndo(UndoKind kind, pit_type from, pit_type to)
+void Cursor::beginUndoGroup() const
+{
+ bv_->buffer().undo().beginUndoGroup();
+}
+
+
+void Cursor::endUndoGroup() const
+{
+ bv_->buffer().undo().endUndoGroup();
+}
+
+
+void Cursor::recordUndo(UndoKind kind, pit_type from, pit_type to) const
{
bv_->buffer().undo().recordUndo(*this, kind, from, to);
}
-void Cursor::recordUndo(UndoKind kind, pit_type from)
+void Cursor::recordUndo(UndoKind kind, pit_type from) const
{
bv_->buffer().undo().recordUndo(*this, kind, from);
}
-void Cursor::recordUndo(UndoKind kind)
+void Cursor::recordUndo(UndoKind kind) const
{
bv_->buffer().undo().recordUndo(*this, kind);
}
-void Cursor::recordUndoInset(UndoKind kind)
+void Cursor::recordUndoInset(UndoKind kind) const
{
bv_->buffer().undo().recordUndoInset(*this, kind);
}
-void Cursor::recordUndoFullDocument()
+void Cursor::recordUndoFullDocument() const
{
bv_->buffer().undo().recordUndoFullDocument(*this);
}
-void Cursor::recordUndoSelection()
+void Cursor::recordUndoSelection() const
{
if (inMathed()) {
if (cap::multipleCellsSelected(*this))
void Cursor::checkBufferStructure()
{
- if (paragraph().layout().toclevel == Layout::NOT_IN_TOC)
- return;
Buffer const * master = buffer().masterBuffer();
- master->tocBackend().updateItem(ParConstIterator(*this));
- master->structureChanged();
+ master->tocBackend().updateItem(*this);
}