visual mode for bidi cursor movement --- in tables

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@24235 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Dov Feldstern 2008-04-11 12:02:10 +00:00
parent b89fffd7f9
commit 5dfa0c0381
5 changed files with 113 additions and 45 deletions

View File

@ -567,6 +567,14 @@ bool Cursor::posVisToNewRow(bool movingLeft)
Buffer const & buf = buffer();
Row const & row = textRow();
bool par_is_LTR = !par.isRTL(buf.params());
// Inside a table, determining whether to move to the next or previous row
// should be done based on the table's direction.
int s = depth() - 1;
if (s >= 1 && (*this)[s].inset().asInsetTabular()) {
par_is_LTR = !(*this)[s].inset().asInsetTabular()->isRightToLeft(*this);
LYXERR(Debug::RTL, "Inside table! par_is_LTR=" << (par_is_LTR ? 1 : 0));
}
// if moving left in an LTR paragraph or moving right in an RTL one,
// move to previous row

View File

@ -678,7 +678,7 @@ bool Text::cursorVisLeft(Cursor & cur, bool skip_inset)
}
// Are we already at leftmost pos in row?
if (left_pos == -1) {
if (cur.text()->empty() || left_pos == -1) {
Cursor new_cur = cur;
if (!new_cur.posVisToNewRow(true)) {
@ -768,7 +768,7 @@ bool Text::cursorVisRight(Cursor & cur, bool skip_inset)
}
// Are we already at rightmost pos in row?
if (right_pos == -1) {
if (cur.text()->empty() || right_pos == -1) {
Cursor new_cur = cur;
if (!new_cur.posVisToNewRow(false)) {

View File

@ -41,6 +41,7 @@ class InsetIterator;
class InsetLayout;
class InsetList;
class InsetMath;
class InsetTabular;
class InsetText;
class LaTeXFeatures;
class Lexer;
@ -129,6 +130,10 @@ public:
virtual InsetCollapsable * asInsetCollapsable() { return 0; }
/// is this inset based on the InsetCollapsable class?
virtual InsetCollapsable const * asInsetCollapsable() const { return 0; }
/// is this inset based on the InsetTabular class?
virtual InsetTabular * asInsetTabular() { return 0; }
/// is this inset based on the InsetTabular class?
virtual InsetTabular const * asInsetTabular() const { return 0; }
/// the real dispatcher
void dispatch(Cursor & cur, FuncRequest & cmd);

View File

@ -3218,53 +3218,67 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
break;
case LFUN_CHAR_FORWARD_SELECT:
case LFUN_CHAR_FORWARD:
cell(cur.idx())->dispatch(cur, cmd);
if (!cur.result().dispatched()) {
moveNextCell(cur);
if (sl == cur.top())
cmd = FuncRequest(LFUN_FINISHED_FORWARD);
else
cur.dispatched();
}
break;
case LFUN_CHAR_BACKWARD_SELECT:
case LFUN_CHAR_BACKWARD:
case LFUN_CHAR_RIGHT_SELECT:
case LFUN_CHAR_RIGHT:
case LFUN_CHAR_LEFT_SELECT:
case LFUN_CHAR_LEFT: {
// determine whether we move to next or previous cell, where to enter
// the new cell from, and which command to "finish" (i.e., exit the
// inset) with:
bool next_cell;
EntryDirection entry_from = ENTRY_DIRECTION_IGNORE;
FuncCode finish_lfun;
if (cmd.action == LFUN_CHAR_FORWARD
|| cmd.action == LFUN_CHAR_FORWARD_SELECT) {
next_cell = true;
finish_lfun = LFUN_FINISHED_FORWARD;
}
else if (cmd.action == LFUN_CHAR_BACKWARD
|| cmd.action == LFUN_CHAR_BACKWARD_SELECT) {
next_cell = false;
finish_lfun = LFUN_FINISHED_BACKWARD;
}
// LEFT or RIGHT commands --- the interpretation will depend on the
// table's direction.
else {
bool right = (cmd.action == LFUN_CHAR_RIGHT
|| cmd.action == LFUN_CHAR_RIGHT_SELECT);
next_cell = (isRightToLeft(cur) != right);
if (lyxrc.visual_cursor) {
entry_from = right ? ENTRY_DIRECTION_LEFT:ENTRY_DIRECTION_RIGHT;
}
if (right)
finish_lfun = LFUN_FINISHED_RIGHT;
else
finish_lfun = LFUN_FINISHED_LEFT;
}
// finally, now that we know what we want to do, do it!
cell(cur.idx())->dispatch(cur, cmd);
if (!cur.result().dispatched()) {
movePrevCell(cur);
// move to next/prev cell, as appropriate
LYXERR(Debug::RTL, "entering " << (next_cell ? "next" : "previous")
<< " cell from: " << int(entry_from));
if (next_cell)
moveNextCell(cur, entry_from);
else
movePrevCell(cur, entry_from);
// if we're exiting the table, call the appropriate FINISHED lfun
if (sl == cur.top())
cmd = FuncRequest(LFUN_FINISHED_BACKWARD);
cmd = FuncRequest(finish_lfun);
else
cur.dispatched();
}
break;
case LFUN_CHAR_RIGHT_SELECT:
case LFUN_CHAR_RIGHT:
//FIXME: for visual cursor, really move right
if (isRightToLeft(cur))
lyx::dispatch(FuncRequest(
cmd.action == LFUN_CHAR_RIGHT_SELECT ?
LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD));
else
lyx::dispatch(FuncRequest(
cmd.action == LFUN_CHAR_RIGHT_SELECT ?
LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD));
break;
case LFUN_CHAR_LEFT_SELECT:
case LFUN_CHAR_LEFT:
//FIXME: for visual cursor, really move left
if (isRightToLeft(cur))
lyx::dispatch(FuncRequest(
cmd.action == LFUN_CHAR_LEFT_SELECT ?
LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD));
else
lyx::dispatch(FuncRequest(
cmd.action == LFUN_CHAR_LEFT_SELECT ?
LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD));
break;
}
case LFUN_DOWN_SELECT:
case LFUN_DOWN:
@ -3958,7 +3972,7 @@ void InsetTabular::resetPos(Cursor & cur) const
}
void InsetTabular::moveNextCell(Cursor & cur)
void InsetTabular::moveNextCell(Cursor & cur, EntryDirection entry_from)
{
if (isRightToLeft(cur)) {
if (tabular.isFirstCellInRow(cur.idx())) {
@ -3978,11 +3992,29 @@ void InsetTabular::moveNextCell(Cursor & cur)
}
cur.pit() = 0;
cur.pos() = 0;
cur.boundary(false);
// in visual mode, place cursor at extreme left or right
switch(entry_from) {
case ENTRY_DIRECTION_RIGHT:
cur.posVisToRowExtremity(false /* !left */);
break;
case ENTRY_DIRECTION_LEFT:
cur.posVisToRowExtremity(true /* left */);
break;
case ENTRY_DIRECTION_IGNORE:
// nothing to do in this case
break;
}
resetPos(cur);
}
void InsetTabular::movePrevCell(Cursor & cur)
void InsetTabular::movePrevCell(Cursor & cur, EntryDirection entry_from)
{
if (isRightToLeft(cur)) {
if (tabular.isLastCellInRow(cur.idx())) {
@ -4004,6 +4036,22 @@ void InsetTabular::movePrevCell(Cursor & cur)
cur.pit() = cur.lastpit();
cur.pos() = cur.lastpos();
// in visual mode, place cursor at extreme left or right
switch(entry_from) {
case ENTRY_DIRECTION_RIGHT:
cur.posVisToRowExtremity(false /* !left */);
break;
case ENTRY_DIRECTION_LEFT:
cur.posVisToRowExtremity(true /* left */);
break;
case ENTRY_DIRECTION_IGNORE:
// nothing to do in this case
break;
}
// FIXME: this accesses the position cache before it is initialized
//resetPos(cur);
}

View File

@ -810,6 +810,13 @@ public:
///
void completionPosAndDim(Cursor const &, int & x, int & y, Dimension & dim) const;
///
virtual InsetTabular * asInsetTabular() { return this; }
///
virtual InsetTabular const * asInsetTabular() const { return this; }
///
bool isRightToLeft(Cursor & cur) const;
//
// Public structures and variables
///
@ -834,9 +841,11 @@ private:
void setCursorFromCoordinates(Cursor & cur, int x, int y) const;
///
void moveNextCell(Cursor & cur);
void moveNextCell(Cursor & cur,
EntryDirection entry_from = ENTRY_DIRECTION_IGNORE);
///
void movePrevCell(Cursor & cur);
void movePrevCell(Cursor & cur,
EntryDirection entry_from = ENTRY_DIRECTION_IGNORE);
///
int cellXPos(idx_type cell) const;
///
@ -850,8 +859,6 @@ private:
///
void cutSelection(Cursor & cur);
///
bool isRightToLeft(Cursor & cur) const;
///
void getSelection(Cursor & cur, row_type & rs, row_type & re,
col_type & cs, col_type & ce) const;
///