From: Dov Feldstern Date: Sun, 4 May 2008 20:22:19 +0000 (+0000) Subject: visual mode for bidi cursor movement --- at the word-at-a-time level X-Git-Tag: 1.6.10~4909 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=553d896bb6919136c3f3cdad7509af42571a6119;p=features.git visual mode for bidi cursor movement --- at the word-at-a-time level git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@24602 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/Text.cpp b/src/Text.cpp index e2bec2e19c..c324b572f5 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -622,6 +622,84 @@ bool Text::cursorBackwardOneWord(Cursor & cur) } +bool Text::cursorVisLeftOneWord(Cursor & cur) +{ + LASSERT(this == cur.text(), /**/); + + pos_type left_pos, right_pos; + bool left_is_letter, right_is_letter; + + Cursor temp_cur = cur; + + // always try to move at least once... + while (temp_cur.posVisLeft(true /* skip_inset */)) { + + // collect some information about current cursor position + temp_cur.getSurroundingPos(left_pos, right_pos); + left_is_letter = + (left_pos > -1 ? temp_cur.paragraph().isLetter(left_pos) : false); + right_is_letter = + (right_pos > -1 ? temp_cur.paragraph().isLetter(right_pos) : false); + + // if we're not at a letter/non-letter boundary, continue moving + if (left_is_letter == right_is_letter) + continue; + + // we should stop when we have an LTR word on our right or an RTL word + // on our left + if ((left_is_letter && temp_cur.paragraph().getFontSettings( + temp_cur.bv().buffer().params(), + left_pos).isRightToLeft()) + || (right_is_letter && !temp_cur.paragraph().getFontSettings( + temp_cur.bv().buffer().params(), + right_pos).isRightToLeft())) + break; + } + + return setCursor(cur, temp_cur.pit(), temp_cur.pos(), + true, temp_cur.boundary()); +} + + +bool Text::cursorVisRightOneWord(Cursor & cur) +{ + LASSERT(this == cur.text(), /**/); + + pos_type left_pos, right_pos; + bool left_is_letter, right_is_letter; + + Cursor temp_cur = cur; + + // always try to move at least once... + while (temp_cur.posVisRight(true /* skip_inset */)) { + + // collect some information about current cursor position + temp_cur.getSurroundingPos(left_pos, right_pos); + left_is_letter = + (left_pos > -1 ? temp_cur.paragraph().isLetter(left_pos) : false); + right_is_letter = + (right_pos > -1 ? temp_cur.paragraph().isLetter(right_pos) : false); + + // if we're not at a letter/non-letter boundary, continue moving + if (left_is_letter == right_is_letter) + continue; + + // we should stop when we have an LTR word on our right or an RTL word + // on our left + if ((left_is_letter && temp_cur.paragraph().getFontSettings( + temp_cur.bv().buffer().params(), + left_pos).isRightToLeft()) + || (right_is_letter && !temp_cur.paragraph().getFontSettings( + temp_cur.bv().buffer().params(), + right_pos).isRightToLeft())) + break; + } + + return setCursor(cur, temp_cur.pit(), temp_cur.pos(), + true, temp_cur.boundary()); +} + + void Text::selectWord(Cursor & cur, word_location loc) { LASSERT(this == cur.text(), /**/); diff --git a/src/Text.h b/src/Text.h index 526fa2ee85..34977dab01 100644 --- a/src/Text.h +++ b/src/Text.h @@ -193,6 +193,10 @@ public: bool cursorBackwardOneWord(Cursor & cur); /// bool cursorForwardOneWord(Cursor & cur); + /// + bool cursorVisLeftOneWord(Cursor & cur); + /// + bool cursorVisRightOneWord(Cursor & cur); /// Delete from cursor up to the end of the current or next word. void deleteWordForward(Cursor & cur); /// Delete from cursor to start of current or prior word. diff --git a/src/Text3.cpp b/src/Text3.cpp index b63f7aa7c8..a38b5ab579 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -633,16 +633,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_WORD_RIGHT: case LFUN_WORD_RIGHT_SELECT: - //FIXME: for visual cursor mode, really move right - if (reverseDirectionNeeded(cur)) { - cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ? - LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD; + if (lyxrc.visual_cursor) { + needsUpdate |= cur.selHandle(cmd.action == LFUN_WORD_RIGHT_SELECT); + needsUpdate |= cursorVisRightOneWord(cur); + if (!needsUpdate && oldTopSlice == cur.top() + && cur.boundary() == oldBoundary) { + cur.undispatched(); + cmd = FuncRequest(LFUN_FINISHED_RIGHT); + } } else { - cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ? - LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD; + if (reverseDirectionNeeded(cur)) { + cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ? + LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD; + } else { + cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ? + LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD; + } + dispatch(cur, cmd); + return; } - dispatch(cur, cmd); - return; + break; case LFUN_WORD_FORWARD: case LFUN_WORD_FORWARD_SELECT: @@ -652,16 +662,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_WORD_LEFT: case LFUN_WORD_LEFT_SELECT: - //FIXME: for visual cursor mode, really move left - if (reverseDirectionNeeded(cur)) { - cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ? - LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD; + if (lyxrc.visual_cursor) { + needsUpdate |= cur.selHandle(cmd.action == LFUN_WORD_LEFT_SELECT); + needsUpdate |= cursorVisLeftOneWord(cur); + if (!needsUpdate && oldTopSlice == cur.top() + && cur.boundary() == oldBoundary) { + cur.undispatched(); + cmd = FuncRequest(LFUN_FINISHED_LEFT); + } } else { - cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ? - LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD; + if (reverseDirectionNeeded(cur)) { + cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ? + LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD; + } else { + cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ? + LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD; + } + dispatch(cur, cmd); + return; } - dispatch(cur, cmd); - return; + break; case LFUN_WORD_BACKWARD: case LFUN_WORD_BACKWARD_SELECT: