+2000-05-27 Dekel Tsur <dekel@math.tau.ac.il>
+
+ * src/text.C (draw): draw bars under foreign language words.
+
+ * src/LColor.[Ch]: add LColor::language
+
+2000-05-27 Dekel Tsur <dekel@math.tau.ac.il>
+
+ * src/lyxcursor.h (boundary): New member variable
+
+ * src/text.C (IsBoundary): New methods
+
+ * src/text.C: Use the above for currect cursor movement when there
+ is both RTL & LTR text.
+
+ * src/text2.C: ditto
+
+ * src/bufferview_funcs.C (ToggleAndShow): ditto
+
2000-05-30 Jean-Marc Lasgouttes <Jean-Marc.Lasgouttes@inria.fr>
* src/text.C (DeleteLineForward): set selection to true to avoid
# the document. Default is true.
#\language_auto_end false
+# Set mark_foreign_language to "false" to disable the highlighting of words
+# with a foreign language to the language of the documet.
+# Default is "true"
+#\mark_foreign_language false
+
#
# HEBREW SUPPORT SECTION ####################################################
#
# For example,
#\bind "F12" "language hebrew"
+# You might want ot disable the foreign language marking:
+#\mark_foreign_language false
+
# Finally, you need to select iso8859-8 font encoding, and select screen fonts
# (below are the default fonts. You need to replace them by Hebrew fonts)
#\screen_font_encoding iso8859-8
{ notebg, N_("note background"), "notebg", "yellow", "notebg" },
{ noteframe, N_("note frame"), "noteframe", "black", "noteframe" },
{ depthbar, N_("depth bar"), "depthbar", "IndianRed", "depthbar" },
+ { language, N_("language"), "language", "Blue", "language" },
{ command, N_("command-inset"), "command", "black", "command" },
{ commandbg, N_("command-inset background"), "commandbg", "grey80", "commandbg" },
{ commandframe, N_("inset frame"), "commandframe", "black", "commandframe" },
/// Color for the depth bars in the margin
depthbar,
+ /// Color for marking foreign language words
+ language,
/// Text color for command insets
command,
else
bv->text->ToggleFree(font, toggleall);
bv->update(1);
+
+ if (font.language() != ignore_language ||
+ font.latex() != LyXFont::IGNORE) {
+ LyXText * text = bv->text;
+ LyXCursor & cursor = text->cursor;
+ text->ComputeBidiTables(cursor.row);
+ if (cursor.boundary !=
+ text->IsBoundary(cursor.par, cursor.pos,
+ text->real_current_font) )
+ text->SetCursor(cursor.par, cursor.pos,
+ false, !cursor.boundary);
+ }
}
}
if (current_view->available()) {
if (old_language != new_language &&
old_language->RightToLeft == new_language->RightToLeft &&
- ! current_view->buffer()->isMultiLingual() ) {
+ ! current_view->buffer()->isMultiLingual() )
current_view->buffer()->ChangeLanguage(old_language,
new_language);
- current_view->buffer()->redraw();
+ if (old_language != new_language) {
+ //current_view->buffer()->redraw();
+ redo = true;
}
}
params->language_info = new_language;
///
LyXParagraph::size_type pos;
///
+ bool boundary;
+ ///
int x;
///
int x_fix;
Row * row;
///
inline bool operator==(const LyXCursor &a) const
- { return (a.par == par) && (a.pos == pos); }
+ { return a.par == par && a.pos == pos && a.boundary == boundary ; }
inline bool operator!=(const LyXCursor &a) const
- { return (a.par != par) || (a.pos != pos); }
+ { return a.par != par || a.pos != pos || a.boundary != boundary; }
};
#endif
break;
case LFUN_LANGUAGE:
- {
Lang(owner->view(), argument);
owner->view()->setState();
owner->getMiniBuffer()->Set(CurrentState(owner->view()));
- }
break;
case LFUN_EMPH:
Emph(owner->view());
owner->getMiniBuffer()->Set(CurrentState(owner->view()));
break;
-
+
case LFUN_BOLD:
Bold(owner->view());
owner->getMiniBuffer()->Set(CurrentState(owner->view()));
owner->view()->beforeChange();
owner->view()->update(-2);
if (is_rtl)
- tmptext->CursorLeft();
+ tmptext->CursorLeft(false);
if (tmptext->cursor.pos < tmptext->cursor.par->Last()
&& tmptext->cursor.par->GetChar(tmptext->cursor.pos)
== LyXParagraph::META_INSET
break;
}
if (!is_rtl)
- tmptext->CursorRight();
+ tmptext->CursorRight(false);
owner->view()->text->FinishUndo();
moveCursorUpdate(false);
owner->getMiniBuffer()->Set(CurrentState(owner->view()));
if(!txt->mark_set) owner->view()->beforeChange();
owner->view()->update(-2);
if (!is_rtl)
- txt->CursorLeft();
+ txt->CursorLeft(false);
if (txt->cursor.pos < txt->cursor.par->Last()
&& txt->cursor.par->GetChar(txt->cursor.pos)
== LyXParagraph::META_INSET
break;
}
if (is_rtl)
- txt->CursorRight();
+ txt->CursorRight(false);
owner->view()->text->FinishUndo();
moveCursorUpdate(false);
RC_BACKUPDIR_PATH,
RC_RTL_SUPPORT,
RC_AUTO_NUMBER,
+ RC_MARK_FOREIGN_LANGUAGE,
RC_LANGUAGE_PACKAGE,
RC_LANGUAGE_AUTO_BEGIN,
RC_LANGUAGE_AUTO_END,
{ "\\literate_error_filter", RC_LITERATE_ERROR_FILTER },
{ "\\literate_extension", RC_LITERATE_EXTENSION },
{ "\\make_backup", RC_MAKE_BACKUP },
+ { "\\mark_foreign_language", RC_MARK_FOREIGN_LANGUAGE },
{ "\\num_lastfiles", RC_NUMLASTFILES },
{ "\\override_x_deadkeys", RC_OVERRIDE_X_DEADKEYS },
{ "\\pdf_mode", RC_PDF_MODE },
hasBindFile = false;
rtl_support = false;
auto_number = true;
+ mark_foreign_language = true;
language_package = "\\usepackage{babel}";
language_auto_begin = true;
language_auto_end = true;
if (lexrc.next())
auto_number = lexrc.GetBool();
break;
+ case RC_MARK_FOREIGN_LANGUAGE:
+ if (lexrc.next())
+ mark_foreign_language = lexrc.GetBool();
case RC_SHOW_BANNER:
if (lexrc.next())
show_banner = lexrc.GetBool();
os << "\\rtl " << tostr(rtl_support) << "\n";
case RC_AUTO_NUMBER:
os << "\\auto_number" << tostr(auto_number) << "\n";
+ case RC_MARK_FOREIGN_LANGUAGE:
+ os << "\\mark_foreign_language " <<
+ tostr(mark_foreign_language) << "\n";
case RC_LANGUAGE_AUTO_BEGIN:
os << "\\language_auto_begin "
<< tostr(language_auto_begin) << "\n";
///
bool auto_number;
///
+ bool mark_foreign_language;
+ ///
bool show_banner;
/// Do we have to use a GUI?
bool use_gui;
/** returns the column near the specified x-coordinate of the row
x is set to the real beginning of this column
*/
- int GetColumnNearX(Row * row, int & x) const;
+ int GetColumnNearX(Row * row, int & x, bool & boundary) const;
/** returns a pointer to a specified row. y is set to the beginning
of the row
///
void SetCursor(LyXParagraph * par,
LyXParagraph::size_type pos,
- bool setfont = true) const;
+ bool setfont = true,
+ bool boundary = false) const;
+
void SetCursor(LyXCursor &, LyXParagraph * par,
- LyXParagraph::size_type pos) const;
+ LyXParagraph::size_type pos,
+ bool boundary = false) const;
///
void SetCursorIntern(LyXParagraph * par,
LyXParagraph::size_type pos,
- bool setfont = true) const;
+ bool setfont = true,
+ bool boundary = false) const;
+ ///
+ void SetCurrentFont() const;
+
+ ///
+ bool IsBoundary(LyXParagraph * par,
+ LyXParagraph::size_type pos) const;
+ ///
+ bool IsBoundary(LyXParagraph * par,
+ LyXParagraph::size_type pos,
+ LyXFont const & font) const;
+
///
void SetCursorFromCoordinates(int x, long y) const;
void SetCursorFromCoordinates(LyXCursor &, int x, long y) const;
///
void CursorDown() const;
///
- void CursorLeft() const;
+ void CursorLeft(bool internal = true) const;
///
- void CursorRight() const;
+ void CursorRight(bool internal = true) const;
+ ///
+ void CursorLeftIntern(bool internal = true) const;
+ ///
+ void CursorRightIntern(bool internal = true) const;
///
void CursorLeftOneWord() const;
///
/// for external use in lyx_cb.C
void SetCursorParUndo();
///
- void CursorLeftIntern() const;
- ///
- void CursorRightIntern() const;
- ///
void RemoveTableRow(LyXCursor * cursor) const;
///
bool IsEmptyTableCell() const;
void toggleAppendix();
///
unsigned short paperWidth() const { return paperwidth; }
+
+ ///
+ void ComputeBidiTables(Row *row) const;
+
+ /// Maps positions in the visual string to positions in logical string.
+ inline
+ LyXParagraph::size_type log2vis(LyXParagraph::size_type pos) const {
+ if (bidi_start == -1)
+ return pos;
+ else
+ return log2vis_list[pos-bidi_start];
+ }
+
+ /// Maps positions in the logical string to positions in visual string.
+ inline
+ LyXParagraph::size_type vis2log(LyXParagraph::size_type pos) const {
+ if (bidi_start == -1)
+ return pos;
+ else
+ return vis2log_list[pos-bidi_start];
+ }
+
+ inline
+ int bidi_level(LyXParagraph::size_type pos) const {
+ if (bidi_start == -1)
+ return 0;
+ else
+ return bidi_levels[pos-bidi_start];
+ }
+
+ inline
+ bool bidi_InRange(LyXParagraph::size_type pos) const {
+ return bidi_start == -1 ||
+ (bidi_start <= pos && pos <= bidi_end);
+ }
private:
///
BufferView * owner_;
mutable LyXParagraph::size_type bidi_start;
///
- mutable bool bidi_same_direction;
+ mutable LyXParagraph::size_type bidi_end;
///
- void ComputeBidiTables(Row *row) const;
-
- /// Maps positions in the visual string to positions in logical string.
- inline
- LyXParagraph::size_type log2vis(LyXParagraph::size_type pos) const {
- if (bidi_start == -1)
- return pos;
- else
- return log2vis_list[pos-bidi_start];
- }
-
- /// Maps positions in the logical string to positions in visual string.
- inline
- LyXParagraph::size_type vis2log(LyXParagraph::size_type pos) const {
- if (bidi_start == -1)
- return pos;
- else
- return vis2log_list[pos-bidi_start];
- }
-
- inline
- int bidi_level(LyXParagraph::size_type pos) const {
- if (bidi_start == -1)
- return 0;
- else
- return bidi_levels[pos-bidi_start];
- }
+ mutable bool bidi_same_direction;
///
unsigned char TransformChar(unsigned char c, Letter_Form form) const;
bidi_start = -1;
return;
}
- LyXParagraph::size_type last = RowLastPrintable(row);
bidi_start = row->pos;
+ bidi_end = RowLastPrintable(row);
- if (bidi_start > last) {
+ if (bidi_start > bidi_end) {
bidi_start = -1;
return;
}
- if (last + 2 - bidi_start >
+ if (bidi_end + 2 - bidi_start >
static_cast<LyXParagraph::size_type>(log2vis_list.size())) {
LyXParagraph::size_type new_size =
- (last + 2 - bidi_start < 500) ?
- 500 : 2 * (last + 2 - bidi_start);
+ (bidi_end + 2 - bidi_start < 500) ?
+ 500 : 2 * (bidi_end + 2 - bidi_start);
log2vis_list.resize(new_size);
vis2log_list.resize(new_size);
bidi_levels.resize(new_size);
}
- vis2log_list[last + 1 - bidi_start] = -1;
- log2vis_list[last + 1 - bidi_start] = -1;
+ vis2log_list[bidi_end + 1 - bidi_start] = -1;
+ log2vis_list[bidi_end + 1 - bidi_start] = -1;
LyXParagraph::size_type stack[2];
bool rtl_par = row->par->getParLanguage()->RightToLeft;
bool rtl0 = false;
LyXParagraph::size_type main_body = BeginningOfMainBody(row->par);
- for (LyXParagraph::size_type lpos = bidi_start; lpos <= last; ++lpos) {
+ for (LyXParagraph::size_type lpos = bidi_start; lpos <= bidi_end; ++lpos) {
bool is_space = row->par->IsLineSeparator(lpos);
LyXParagraph::size_type pos =
- (is_space && lpos+1 <= last &&
+ (is_space && lpos+1 <= bidi_end &&
+ !row->par->IsLineSeparator(lpos+1) &&
(!row->par->table || !row->par->IsNewline(lpos+1)) )
? lpos + 1 : lpos;
LyXFont font = row->par->GetFontSettings(pos);
while (level > 0) {
LyXParagraph::size_type old_lpos = stack[--level];
- int delta = last - old_lpos;
+ int delta = bidi_end - old_lpos;
if (level % 2)
delta = -delta;
log2vis_list[old_lpos - bidi_start] += delta;
}
LyXParagraph::size_type vpos = bidi_start - 1;
- for (LyXParagraph::size_type lpos = bidi_start; lpos <= last; ++lpos) {
+ for (LyXParagraph::size_type lpos = bidi_start; lpos <= bidi_end; ++lpos) {
vpos += log2vis_list[lpos - bidi_start];
vis2log_list[vpos - bidi_start] = lpos;
log2vis_list[lpos - bidi_start] = vpos;
}
+// This method requires a previous call to ComputeBidiTables()
+bool LyXText::IsBoundary(LyXParagraph * par, LyXParagraph::size_type pos) const
+{
+ if (!lyxrc.rtl_support)
+ return false; // This is just for speedup
+
+ if (!bidi_InRange(pos - 1) ||
+ (par->table && par->IsNewline(pos-1)) )
+ return false;
+
+ bool rtl = bidi_level(pos - 1) % 2;
+ bool rtl2 = rtl;
+ if (pos == par->Last() ||
+ (par->table && par->IsNewline(pos)))
+ rtl2 = par->isRightToLeftPar();
+ else if (bidi_InRange(pos))
+ rtl2 = bidi_level(pos) % 2;
+ return rtl != rtl2;
+}
+
+bool LyXText::IsBoundary(LyXParagraph * par, LyXParagraph::size_type pos,
+ LyXFont const & font) const
+{
+ if (!lyxrc.rtl_support)
+ return false; // This is just for speedup
+
+ bool rtl = font.isVisibleRightToLeft();
+ bool rtl2 = rtl;
+ if (pos == par->Last() ||
+ (par->table && par->IsNewline(pos)))
+ rtl2 = par->isRightToLeftPar();
+ else if (bidi_InRange(pos))
+ rtl2 = bidi_level(pos) % 2;
+ return rtl != rtl2;
+}
+
+
void LyXText::draw(Row const * row,
LyXParagraph::size_type & vpos,
int offset, float & x)
LyXParagraph::size_type pos = vis2log(vpos);
char c = row->par->GetChar(pos);
+ float tmpx = x;
if (IsNewlineChar(c)) {
++vpos;
font.setColor(LColor::footnote);
- float tmpx = x;
-
// draw it and set new x position
pain.text(int(x), offset + y, fs, font);
offset + row->baseline, x);
}
++vpos;
+
+ if (lyxrc.mark_foreign_language &&
+ font.language() != buffer->params.language_info) {
+ int y = offset + row->baseline + 2;
+ pain.line(int(tmpx), y, int(x), y,
+ LColor::language);
+ }
+
return;
}
++vpos;
LyXParagraph::size_type last = RowLastPrintable(row);
- float tmpx = x;
if (font.language()->lang == "hebrew") {
if (is_nikud(c)) {
pain.line(int(tmpx), offset + row->baseline + 2,
int(x), offset + row->baseline + 2);
+ } else if (lyxrc.mark_foreign_language &&
+ font.language() != buffer->params.language_info) {
+ int y = offset + row->baseline + 2;
+ pain.line(int(tmpx), y, int(x), y,
+ LColor::language);
}
// If we want ulem.sty support, drawing
}
}
- cursor.pos++;
+ ++cursor.pos;
CheckParagraphInTable(cursor.par, cursor.pos);
if (par->table->SetWidthOfCell(NumberOfCell(par, pos),
WidthOfCell(par, tmp_pos))) {
LyXCursor tmpcursor = cursor;
- SetCursorIntern(par, pos);
+ SetCursorIntern(par, pos, false);
/* make a complete redraw */
RedoDrawingOfParagraph(cursor);
cursor = tmpcursor;
else
status = LyXText::NEED_MORE_REFRESH;
}
- SetCursorIntern(cursor.par, cursor.pos);
+ SetCursorIntern(cursor.par, cursor.pos, false, cursor.boundary);
}
current_font = rawtmpfont;
real_current_font = realtmpfont;
}
- SetCursorIntern(cursor.par, cursor.pos);
+ SetCursorIntern(cursor.par, cursor.pos, true, cursor.boundary);
+ if (IsBoundary(cursor.par, cursor.pos) != cursor.boundary)
+ SetCursor(cursor.par, cursor.pos, false, !cursor.boundary);
}
/* table stuff -- end*/
current_font = rawtmpfont;
real_current_font = realtmpfont;
- SetCursor(cursor.par, cursor.pos + 1, false);
+ SetCursor(cursor.par, cursor.pos + 1, false, cursor.boundary);
/* cursor MUST be in row now */
if (row->next && row->next->par == row->par)
}
current_font = rawtmpfont;
real_current_font = realtmpfont;
- SetCursor(cursor.par, cursor.pos + 1, false);
+ SetCursor(cursor.par, cursor.pos + 1, false, cursor.boundary);
if (row->next && row->next->par == row->par)
need_break_row = row->next;
else
current_font = rawtmpfont;
real_current_font = realtmpfont;
- SetCursor(cursor.par, cursor.pos + 1, false);
+ SetCursor(cursor.par, cursor.pos + 1, false, cursor.boundary);
}
/* check, wether the last characters font has changed. */
return;
}
/* table stuff -- end */
+
+ // LyXFont rawtmpfont = current_font;
+ // LyXFont realtmpfont = real_current_font;
+ // We don't need the above variables as calling to SetCursor() with third
+ // argument eqaul to false, will not change current_font & real_current_font
- LyXFont rawtmpfont = current_font;
- LyXFont realtmpfont = real_current_font;
-
// Get the font that is used to calculate the baselineskip
- int const lastpos = cursor.par->Last();
+ LyXParagraph::size_type lastpos = cursor.par->Last();
LyXFont rawparfont = cursor.par->GetFontSettings(lastpos - 1);
if (cursor.pos == 0) {
if (cursor.par->Previous()) {
// steps into the above paragraph.
SetCursorIntern(cursor.par->Previous(),
- cursor.par->Previous()->Last());
+ cursor.par->Previous()->Last(), false);
}
/* Pasting is not allowed, if the paragraphs have different
UpdateCounters(cursor.row);
// the row may have changed, block, hfills etc.
- SetCursor(cursor.par, cursor.pos);
+ SetCursor(cursor.par, cursor.pos, false);
}
} else {
/* this is the code for a normal backspace, not pasting
// not a good idea since it triggers the auto-delete
// mechanism. So we do a CursorLeftIntern()-lite,
// without the dreaded mechanism. (JMarc)
- SetCursorIntern(cursor.par, cursor.pos - 1);
+ SetCursorIntern(cursor.par, cursor.pos - 1, false, cursor.boundary);
// some insets are undeletable here
if (cursor.par->GetChar(cursor.pos) == LyXParagraph::META_INSET) {
refresh_y = y;
refresh_row = tmprow;
status = LyXText::NEED_MORE_REFRESH;
- current_font = rawtmpfont;
- real_current_font = realtmpfont;
- SetCursor(cursor.par, cursor.pos, false);
+ SetCursor(cursor.par, cursor.pos, false, cursor.boundary);
+ //current_font = rawtmpfont;
+ //real_current_font = realtmpfont;
// check, whether the last character's font has changed.
- rawtmpfont = cursor.par->GetFontSettings(cursor.par->Last() - 1);
- if (rawparfont != rawtmpfont)
+ if (rawparfont !=
+ cursor.par->GetFontSettings(cursor.par->Last() - 1))
RedoHeightOfParagraph(cursor);
return;
}
status = LyXText::NEED_MORE_REFRESH;
BreakAgainOneRow(row);
- current_font = rawtmpfont;
- real_current_font = realtmpfont;
- SetCursor(cursor.par, cursor.pos, false);
+ SetCursor(cursor.par, cursor.pos, false, cursor.boundary);
// cursor MUST be in row now
if (row->next && row->next->par == row->par)
status = LyXText::NEED_MORE_REFRESH;
refresh_y = y;
refresh_row = row;
- current_font = rawtmpfont;
- real_current_font = realtmpfont;
- SetCursor(cursor.par, cursor.pos, false);
+ SetCursor(cursor.par, cursor.pos, false, cursor.boundary);
}
}
- // restore the current font
- // That is what a user expects!
- current_font = rawtmpfont;
- real_current_font = realtmpfont;
+
+ // current_font = rawtmpfont;
+ // real_current_font = realtmpfont;
+
+ lastpos = cursor.par->Last();
+ if (cursor.pos == lastpos) {
+ SetCurrentFont();
+ if (IsBoundary(cursor.par, cursor.pos) != cursor.boundary)
+ SetCursor(cursor.par, cursor.pos, false, !cursor.boundary);
+ }
// check, wether the last characters font has changed.
- rawtmpfont = cursor.par->GetFontSettings(cursor.par->Last() - 1);
- if (rawparfont != rawtmpfont) {
+ if (rawparfont !=
+ cursor.par->GetFontSettings(lastpos - 1)) {
RedoHeightOfParagraph(cursor);
} else {
// now the special right address boxes
/* returns the column near the specified x-coordinate of the row
* x is set to the real beginning of this column */
-int LyXText::GetColumnNearX(Row * row, int & x) const
+int LyXText::GetColumnNearX(Row * row, int & x, bool & boundary) const
{
float tmpx = 0.0;
float fill_separator, fill_hfill, fill_label_hfill;
LyXParagraph::size_type c = 0;
LyXLayout const & layout = textclasslist.Style(buffer->params.textclass,
row->par->GetLayout());
+ bool left_side = false;
+
/* table stuff -- begin */
if (row->par->table) {
//the last row doesn't need a newline at the end
&& row->par->IsNewline(last))
last--;
int cell = NumberOfCell(row->par, row->pos);
- float x_old = tmpx;
- bool ready = false;
+ float cell_x = tmpx + row->par->table->WidthOfColumn(cell);
tmpx += row->par->table->GetBeginningOfTextInCell(cell);
- while (vc <= last
- && (c = vis2log(vc)) >= 0
- && tmpx + (SingleWidth(row->par, c)/2) <= x
- && !ready){
- if (row->par->IsNewline(c)) {
- if (x_old + row->par->table->WidthOfColumn(cell) <= x){
- tmpx = x_old + row->par->table->WidthOfColumn(cell);
- x_old = tmpx;
- ++cell;
- tmpx += row->par->table->GetBeginningOfTextInCell(cell);
- ++vc;
- } else
- ready = true;
- } else {
- tmpx += SingleWidth(row->par, c);
- ++vc;
- }
+ float last_tmpx = tmpx;
+ while (vc <= last && tmpx <= x) {
+ c = vis2log(vc);
+ last_tmpx = tmpx;
+ if (row->par->IsNewline(c)) {
+ if (cell_x <= x){
+ ++cell;
+ tmpx = cell_x + row->par->table->GetBeginningOfTextInCell(cell);
+ cell_x += row->par->table->WidthOfColumn(cell);
+ ++vc;
+ } else
+ break;
+ } else {
+ tmpx += SingleWidth(row->par, c);
+ ++vc;
+ }
+ }
+ if (vc > row->pos && !row->par->IsNewline(c) &&
+ (tmpx+last_tmpx)/2 > x) {
+ tmpx = last_tmpx;
+ left_side = true;
}
} else {
/* table stuff -- end*/
}
if (vc > row->pos && (tmpx+last_tmpx)/2 > x) {
- vc--;
tmpx = last_tmpx;
+ left_side = true;
}
}
+
if (vc > last + 1) // This shouldn't happen.
vc = last+1;
+ boundary = false;
+
if (row->pos > last) // Row is empty?
c = row->pos;
- else if (vc > last ||
- (vc - 1 >= row->pos &&
- ( (row->par->IsSeparator(vis2log(vc)) && vis2log(vc) != last)
- || (row->par->table && row->par->IsNewline(vc) )
- ))) {
- c = vis2log(vc - 1);
- if (bidi_level(c) % 2 == 0)
- ++c;
- } else {
+ else if (vc == row->pos ||
+ (row->par->table && vc <= last && row->par->IsNewline(vc-1)) ) {
c = vis2log(vc);
if (bidi_level(c) % 2 == 1)
++c;
+ } else {
+ c = vis2log(vc - 1);
+ bool rtl = (bidi_level(c) % 2 == 1);
+ if (left_side == rtl) {
+ ++c;
+ boundary = IsBoundary(row->par, c);
+ }
}
if (!row->par->table && row->pos <= last && c > last
SetCursor(sel_end_cursor.par, sel_end_cursor.pos);
ClearSelection();
SetSelection();
- SetCursor(tmpcursor.par, tmpcursor.pos);
+ SetCursor(tmpcursor.par, tmpcursor.pos, true, tmpcursor.boundary);
}
status = LyXText::NEED_MORE_REFRESH;
refresh_y = y;
refresh_row = tmprow;
- SetCursor(cur.par, cur.pos);
+ SetCursor(cur.par, cur.pos, false, cursor.boundary);
}
}
// a selection with no contents is not a selection
- if (sel_start_cursor.x == sel_end_cursor.x &&
- sel_start_cursor.y == sel_end_cursor.y)
+ if (sel_start_cursor.par == sel_end_cursor.par &&
+ sel_start_cursor.pos == sel_end_cursor.pos)
selection = false;
// Stuff what we got on the clipboard. Even if there is no selection.
void LyXText::SetCursor(LyXParagraph * par,
- LyXParagraph::size_type pos, bool setfont) const
+ LyXParagraph::size_type pos,
+ bool setfont, bool boundary) const
{
LyXCursor old_cursor = cursor;
- SetCursorIntern(par, pos, setfont);
+ SetCursorIntern(par, pos, setfont, boundary);
DeleteEmptyParagraphMechanism(old_cursor);
}
void LyXText::SetCursor(LyXCursor & cur, LyXParagraph * par,
- LyXParagraph::size_type pos) const
+ LyXParagraph::size_type pos, bool boundary) const
{
// correct the cursor position if impossible
if (pos > par->Last()){
cur.par = par;
cur.pos = pos;
+ cur.boundary = boundary;
/* get the cursor y position in text */
long y = 0;
if (last < row->pos)
cursor_vpos = 0;
- else if ((pos > last) ||
- ((pos - 1 >= row->pos) &&
- (row->par->IsSeparator(pos) ||
- (row->par->table && row->par->IsNewline(pos)))))
+ else if (pos > last && !boundary)
+ cursor_vpos = (row->par->isRightToLeftPar())
+ ? row->pos : last+1;
+ else if (pos > row->pos &&
+ (pos > last || boundary ||
+ (row->par->table && row->par->IsNewline(pos))))
/// Place cursor after char at (logical) position pos-1
- cursor_vpos = !(bidi_level(pos-1) % 2)
+ cursor_vpos = (bidi_level(pos-1) % 2 == 0)
? log2vis(pos-1) + 1 : log2vis(pos-1);
else
/// Place cursor before char at (logical) position pos
- cursor_vpos = !(bidi_level(pos) % 2)
+ cursor_vpos = (bidi_level(pos) % 2 == 0)
? log2vis(pos) : log2vis(pos) + 1;
/* table stuff -- begin*/
void LyXText::SetCursorIntern(LyXParagraph * par,
- LyXParagraph::size_type pos, bool setfont) const
+ LyXParagraph::size_type pos,
+ bool setfont, bool boundary) const
{
- SetCursor(cursor, par, pos);
+ SetCursor(cursor, par, pos, boundary);
// #warning Remove this when verified working (Jug 20000413)
#if 0
// correct the cursor position if impossible
cursor.x_fix = cursor.x;
cursor.row = row;
#endif
- if (setfont) {
- if (cursor.pos &&
- (cursor.pos == cursor.par->Last() || cursor.par->IsSeparator(cursor.pos)
- || (cursor.par->table && cursor.par->IsNewline(cursor.pos))
- )) {
- current_font = cursor.par->GetFontSettings(cursor.pos - 1);
- real_current_font = GetFont(cursor.par, cursor.pos - 1);
- } else {
- current_font = cursor.par->GetFontSettings(cursor.pos);
- real_current_font = GetFont(cursor.par, cursor.pos);
+ if (setfont)
+ SetCurrentFont();
+}
+
+void LyXText::SetCurrentFont() const
+{
+ LyXParagraph::size_type pos = cursor.pos;
+ if (cursor.boundary && pos > 0)
+ --pos;
+
+ if (pos > 0) {
+ if (pos == cursor.par->Last() ||
+ (cursor.par->table && cursor.par->IsNewline(pos)))
+ --pos;
+ else if (cursor.par->IsSeparator(pos)) {
+ if (pos > cursor.row->pos &&
+ bidi_level(pos) % 2 ==
+ bidi_level(pos - 1) % 2)
+ --pos;
+ else if (pos + 1 < cursor.par->Last())
+ ++pos;
}
}
+
+ current_font = cursor.par->GetFontSettings(pos);
+ real_current_font = GetFont(cursor.par, pos);
}
/* get the row first */
Row * row = GetRowNearY(y);
-
cursor.par = row->par;
-
- int column = GetColumnNearX(row, x);
+
+ int column = GetColumnNearX(row, x, cursor.boundary);
cursor.pos = row->pos + column;
cursor.x = x;
cursor.y = y + row->baseline;
-
cursor.row = row;
-
- if (cursor.pos &&
- (cursor.pos == cursor.par->Last()
- || cursor.par->IsSeparator(cursor.pos)
- || (cursor.pos && cursor.pos == BeginningOfMainBody(cursor.par)
- && !cursor.par->IsSeparator(cursor.pos))
- || (cursor.par->table && cursor.par->IsNewline(cursor.pos))
- )) {
- current_font = cursor.par->GetFontSettings(cursor.pos - 1);
- real_current_font = GetFont(cursor.par, cursor.pos - 1);
- } else {
- current_font = cursor.par->GetFontSettings(cursor.pos);
- real_current_font = GetFont(cursor.par, cursor.pos);
- }
+ SetCurrentFont();
DeleteEmptyParagraphMechanism(old_cursor);
}
/* get the row first */
Row * row = GetRowNearY(y);
- int column = GetColumnNearX(row, x);
+ int column = GetColumnNearX(row, x, cur.boundary);
cur.par = row->par;
cur.pos = row->pos + column;
}
-void LyXText::CursorLeft() const
+void LyXText::CursorLeft(bool internal) const
{
- CursorLeftIntern();
+ CursorLeftIntern(internal);
if (cursor.par->table) {
int cell = NumberOfCell(cursor.par, cursor.pos);
if (cursor.par->table->IsContRow(cell) &&
}
-void LyXText::CursorLeftIntern() const
+void LyXText::CursorLeftIntern(bool internal) const
{
if (cursor.pos > 0) {
- SetCursor(cursor.par, cursor.pos - 1);
- }
- else if (cursor.par->Previous()) { // steps into the above paragraph.
- SetCursor(cursor.par->Previous(), cursor.par->Previous()->Last());
+ bool boundary = cursor.boundary;
+ SetCursor(cursor.par, cursor.pos - 1, true, false);
+ if (!internal && !boundary &&
+ IsBoundary(cursor.par, cursor.pos + 1))
+ SetCursor(cursor.par, cursor.pos + 1, true, true);
+ } else if (cursor.par->Previous()) { // steps into the above paragraph.
+ LyXParagraph * par = cursor.par->Previous();
+ LyXParagraph::size_type pos = par->Last();
+ SetCursor(par, pos);
+ if (IsBoundary(par, pos))
+ SetCursor(par, pos, false, true);
}
}
-void LyXText::CursorRight() const
+void LyXText::CursorRight(bool internal) const
{
- CursorRightIntern();
+ CursorRightIntern(internal);
if (cursor.par->table) {
int cell = NumberOfCell(cursor.par, cursor.pos);
if (cursor.par->table->IsContRow(cell) &&
}
-void LyXText::CursorRightIntern() const
+void LyXText::CursorRightIntern(bool internal) const
{
if (cursor.pos < cursor.par->Last()) {
- SetCursor(cursor.par, cursor.pos + 1);
- }
- else if (cursor.par->Next()) {
+ if (!internal && cursor.boundary &&
+ (!cursor.par->table || !cursor.par->IsNewline(cursor.pos)))
+ SetCursor(cursor.par, cursor.pos, true, false);
+ else {
+ SetCursor(cursor.par, cursor.pos + 1, true, false);
+ if (!internal && IsBoundary(cursor.par, cursor.pos))
+ SetCursor(cursor.par, cursor.pos, true, true);
+ }
+ } else if (cursor.par->Next())
SetCursor(cursor.par->Next(), 0);
- }
}