refactoring visual cursor movement functions

Specifically, moved the functions which actually move left or right from Text
into Cursor, and changed the semantics so that they now return whether or not
the cursor has moved. The functions in Text now use the new functions in Cursor.

This change is being made in preparation of the Word-level visual movement.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@24601 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Dov Feldstern 2008-05-04 20:17:59 +00:00
parent 02eb8d0b78
commit ffda0d89b4
3 changed files with 208 additions and 164 deletions

View File

@ -453,6 +453,188 @@ bool Cursor::posForward()
}
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

View File

@ -122,6 +122,22 @@ public:
bool posBackward();
/// move one step forward
bool posForward();
/// move visually one step to the right
/**
* @note: This method may move into an inset unless skip_inset == true.
* @note: This method may move into a new paragraph.
* @note: This method may move out of the current slice.
* @return: true if moved, false if not moved
*/
bool posVisRight(bool skip_inset = false);
/// move visually one step to the left
/**
* @note: This method may move into an inset unless skip_inset == true.
* @note: This method may move into a new paragraph.
* @note: This method may move out of the current slice.
* @return: true if moved, false if not moved
*/
bool posVisLeft(bool skip_inset = false);
/// move visually to next/previous row
/**
* Assuming we were to keep moving left (right) from the current cursor

View File

@ -655,181 +655,27 @@ bool Text::cursorBackward(Cursor & cur)
bool Text::cursorVisLeft(Cursor & cur, bool skip_inset)
{
pit_type new_pit = cur.pit(); // the paragraph to which we will move
pos_type new_pos; // the position we will move to
bool new_boundary; // will we move to a boundary position?
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?
cur.getSurroundingPos(left_pos, right_pos);
LYXERR(Debug::RTL, left_pos <<"|"<< right_pos << " (pos: "<<cur.pos()<<")");
// Are we at an inset?
Cursor temp_cur = cur;
temp_cur.pos() = left_pos;
temp_cur.boundary(false);
if (!skip_inset &&
checkAndActivateInsetVisual(temp_cur, left_pos >= cur.pos(), true)) {
LYXERR(Debug::RTL, "entering inset at: " << temp_cur.pos());
cur = temp_cur; // set the real cursor to new position inside inset!
temp_cur.posVisLeft(skip_inset);
if (temp_cur.depth() > cur.depth()) {
cur = temp_cur;
return false;
}
// Are we already at leftmost pos in row?
if (cur.text()->empty() || left_pos == -1) {
Cursor new_cur = cur;
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...
new_pit = new_cur.pit();
new_pos = new_cur.pos();
new_boundary = new_cur.boundary();
LYXERR(Debug::RTL, "left edge, moving: " << int(new_pit) << ","
<< int(new_pos) << "," << (new_boundary ? 1 : 0));
}
// normal movement to the left
else {
// 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 = cur.paragraph().getFontSettings(
cur.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_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_pos == cur.lastpos()
// 2. if the position *after* left_pos is not RTL (we want to be
// *after* left_pos, not before left_pos + 1!)
|| !cur.paragraph().getFontSettings(cur.bv().buffer().params(),
new_pos).isVisibleRightToLeft()
)
new_boundary = true;
else // set the boundary to false
new_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_pos = left_pos;
new_boundary = false;
}
}
LYXERR(Debug::RTL, "moving to: " << new_pos
<< (new_boundary ? " (boundary)" : ""));
return setCursor(cur, new_pit, new_pos, true, new_boundary);
return setCursor(cur, temp_cur.pit(), temp_cur.pos(),
true, temp_cur.boundary());
}
bool Text::cursorVisRight(Cursor & cur, bool skip_inset)
{
pit_type new_pit = cur.pit(); // the paragraph to which we will move
pos_type new_pos; // the position we will move to
bool new_boundary; // will we move to a boundary position?
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?
cur.getSurroundingPos(left_pos, right_pos);
LYXERR(Debug::RTL, left_pos <<"|"<< right_pos << " (pos: "<<cur.pos()<<")");
// Are we at an inset?
Cursor temp_cur = cur;
temp_cur.pos() = right_pos;
temp_cur.boundary(false);
if (!skip_inset &&
checkAndActivateInsetVisual(temp_cur, right_pos >= cur.pos(), false)) {
LYXERR(Debug::RTL, "entering inset at: " << temp_cur.pos());
cur = temp_cur; // set the real cursor to new position inside inset!
temp_cur.posVisRight(skip_inset);
if (temp_cur.depth() > cur.depth()) {
cur = temp_cur;
return false;
}
// Are we already at rightmost pos in row?
if (cur.text()->empty() || right_pos == -1) {
Cursor new_cur = cur;
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...
new_pit = new_cur.pit();
new_pos = new_cur.pos();
new_boundary = new_cur.boundary();
LYXERR(Debug::RTL, "right edge, moving: " << int(new_pit) << ","
<< int(new_pos) << "," << (new_boundary ? 1 : 0));
}
// normal movement to the right
else {
// 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 = cur.paragraph().getFontSettings(
cur.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_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_pos == cur.lastpos()
// 2. if the position *after* right_pos is RTL (we want to be
// *after* right_pos, not before right_pos + 1!)
|| cur.paragraph().getFontSettings(cur.bv().buffer().params(),
new_pos).isVisibleRightToLeft()
)
new_boundary = true;
else // set the boundary to false
new_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_pos = right_pos;
new_boundary = false;
}
}
LYXERR(Debug::RTL, "moving to: " << new_pos
<< (new_boundary ? " (boundary)" : ""));
return setCursor(cur, new_pit, new_pos, true, new_boundary);
return setCursor(cur, temp_cur.pit(), temp_cur.pos(),
true, temp_cur.boundary());
}