From 73b9ca2a4b2db9a2d005311bae34bd3863d5ee66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gullik=20Bj=C3=B8nnes?= Date: Tue, 30 May 2000 19:31:11 +0000 Subject: [PATCH] two patches from Dekel git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@780 a592a061-630c-0410-9148-cb99ea01b6c8 --- ChangeLog | 19 ++++ lib/lyxrc.example | 8 ++ src/LColor.C | 1 + src/LColor.h | 2 + src/bufferview_funcs.C | 12 +++ src/lyx_cb.C | 6 +- src/lyxcursor.h | 6 +- src/lyxfunc.C | 12 +-- src/lyxrc.C | 9 ++ src/lyxrc.h | 2 + src/lyxtext.h | 100 +++++++++++-------- src/text.C | 213 ++++++++++++++++++++++++++--------------- src/text2.C | 132 ++++++++++++++----------- 13 files changed, 340 insertions(+), 182 deletions(-) diff --git a/ChangeLog b/ChangeLog index 094b267977..59c59af405 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2000-05-27 Dekel Tsur + + * src/text.C (draw): draw bars under foreign language words. + + * src/LColor.[Ch]: add LColor::language + +2000-05-27 Dekel Tsur + + * 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 * src/text.C (DeleteLineForward): set selection to true to avoid diff --git a/lib/lyxrc.example b/lib/lyxrc.example index 19c68350cf..b37ba8c5a3 100644 --- a/lib/lyxrc.example +++ b/lib/lyxrc.example @@ -659,6 +659,11 @@ # 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 #################################################### # @@ -675,6 +680,9 @@ # 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 diff --git a/src/LColor.C b/src/LColor.C index 9fec78cbca..c4763d8f72 100644 --- a/src/LColor.C +++ b/src/LColor.C @@ -66,6 +66,7 @@ LColor::LColor() { 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" }, diff --git a/src/LColor.h b/src/LColor.h index 57e29fc8e4..4fc25de94d 100644 --- a/src/LColor.h +++ b/src/LColor.h @@ -78,6 +78,8 @@ public: /// Color for the depth bars in the margin depthbar, + /// Color for marking foreign language words + language, /// Text color for command insets command, diff --git a/src/bufferview_funcs.C b/src/bufferview_funcs.C index bc99b1eca5..f4765b4205 100644 --- a/src/bufferview_funcs.C +++ b/src/bufferview_funcs.C @@ -293,5 +293,17 @@ void ToggleAndShow(BufferView * bv, LyXFont const & font) 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); + } } } diff --git a/src/lyx_cb.C b/src/lyx_cb.C index 54210ed8ef..ace787145d 100644 --- a/src/lyx_cb.C +++ b/src/lyx_cb.C @@ -2377,10 +2377,12 @@ extern "C" void DocumentApplyCB(FL_OBJECT *, long) 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; diff --git a/src/lyxcursor.h b/src/lyxcursor.h index 0a2af4cba0..e1a8a64ef5 100644 --- a/src/lyxcursor.h +++ b/src/lyxcursor.h @@ -24,6 +24,8 @@ struct LyXCursor { /// LyXParagraph::size_type pos; /// + bool boundary; + /// int x; /// int x_fix; @@ -33,9 +35,9 @@ struct LyXCursor { 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 diff --git a/src/lyxfunc.C b/src/lyxfunc.C index 1eb58c30a2..e5c5fa8a6f 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -1222,18 +1222,16 @@ string LyXFunc::Dispatch(int ac, 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())); @@ -1367,7 +1365,7 @@ string LyXFunc::Dispatch(int ac, 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 @@ -1379,7 +1377,7 @@ string LyXFunc::Dispatch(int ac, break; } if (!is_rtl) - tmptext->CursorRight(); + tmptext->CursorRight(false); owner->view()->text->FinishUndo(); moveCursorUpdate(false); owner->getMiniBuffer()->Set(CurrentState(owner->view())); @@ -1395,7 +1393,7 @@ string LyXFunc::Dispatch(int ac, 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 @@ -1412,7 +1410,7 @@ string LyXFunc::Dispatch(int ac, break; } if (is_rtl) - txt->CursorRight(); + txt->CursorRight(false); owner->view()->text->FinishUndo(); moveCursorUpdate(false); diff --git a/src/lyxrc.C b/src/lyxrc.C index 1f1661d377..28a2bdb700 100644 --- a/src/lyxrc.C +++ b/src/lyxrc.C @@ -137,6 +137,7 @@ enum LyXRCTags { RC_BACKUPDIR_PATH, RC_RTL_SUPPORT, RC_AUTO_NUMBER, + RC_MARK_FOREIGN_LANGUAGE, RC_LANGUAGE_PACKAGE, RC_LANGUAGE_AUTO_BEGIN, RC_LANGUAGE_AUTO_END, @@ -213,6 +214,7 @@ keyword_item lyxrcTags[] = { { "\\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 }, @@ -367,6 +369,7 @@ void LyXRC::setDefaults() { hasBindFile = false; rtl_support = false; auto_number = true; + mark_foreign_language = true; language_package = "\\usepackage{babel}"; language_auto_begin = true; language_auto_end = true; @@ -1011,6 +1014,9 @@ int LyXRC::read(string const & filename) 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(); @@ -1337,6 +1343,9 @@ void LyXRC::output(ostream & os) const 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"; diff --git a/src/lyxrc.h b/src/lyxrc.h index d560d32930..b931af0111 100644 --- a/src/lyxrc.h +++ b/src/lyxrc.h @@ -221,6 +221,8 @@ public: /// bool auto_number; /// + bool mark_foreign_language; + /// bool show_banner; /// Do we have to use a GUI? bool use_gui; diff --git a/src/lyxtext.h b/src/lyxtext.h index 1f56ba635b..21b2adab07 100644 --- a/src/lyxtext.h +++ b/src/lyxtext.h @@ -182,7 +182,7 @@ public: /** 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 @@ -244,13 +244,28 @@ public: /// 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; @@ -259,9 +274,13 @@ public: /// 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; /// @@ -469,10 +488,6 @@ public: /// for external use in lyx_cb.C void SetCursorParUndo(); /// - void CursorLeftIntern() const; - /// - void CursorRightIntern() const; - /// void RemoveTableRow(LyXCursor * cursor) const; /// bool IsEmptyTableCell() const; @@ -480,6 +495,41 @@ public: 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_; @@ -612,36 +662,10 @@ private: 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; diff --git a/src/text.C b/src/text.C index 7d85629a10..fdcff33627 100644 --- a/src/text.C +++ b/src/text.C @@ -280,26 +280,26 @@ void LyXText::ComputeBidiTables(Row * row) 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(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; @@ -308,10 +308,11 @@ void LyXText::ComputeBidiTables(Row * row) const 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); @@ -367,14 +368,14 @@ void LyXText::ComputeBidiTables(Row * row) const 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; @@ -382,6 +383,43 @@ void LyXText::ComputeBidiTables(Row * row) const } +// 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) @@ -390,6 +428,7 @@ void LyXText::draw(Row const * row, LyXParagraph::size_type pos = vis2log(vpos); char c = row->par->GetChar(pos); + float tmpx = x; if (IsNewlineChar(c)) { ++vpos; @@ -492,8 +531,6 @@ void LyXText::draw(Row const * row, font.setColor(LColor::footnote); - float tmpx = x; - // draw it and set new x position pain.text(int(x), offset + y, fs, font); @@ -511,6 +548,14 @@ void LyXText::draw(Row const * row, 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; } @@ -532,7 +577,6 @@ void LyXText::draw(Row const * row, ++vpos; LyXParagraph::size_type last = RowLastPrintable(row); - float tmpx = x; if (font.language()->lang == "hebrew") { if (is_nikud(c)) { @@ -597,6 +641,11 @@ void LyXText::draw(Row const * row, 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 @@ -2403,7 +2452,7 @@ void LyXText::InsertCharInTable(char c) } } - cursor.pos++; + ++cursor.pos; CheckParagraphInTable(cursor.par, cursor.pos); @@ -2439,7 +2488,7 @@ void LyXText::CheckParagraphInTable(LyXParagraph * par, 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; @@ -2460,7 +2509,7 @@ void LyXText::CheckParagraphInTable(LyXParagraph * par, else status = LyXText::NEED_MORE_REFRESH; } - SetCursorIntern(cursor.par, cursor.pos); + SetCursorIntern(cursor.par, cursor.pos, false, cursor.boundary); } @@ -2525,7 +2574,9 @@ void LyXText::BackspaceInTable() 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*/ @@ -2666,7 +2717,7 @@ void LyXText::InsertChar(char c) 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) @@ -2706,7 +2757,7 @@ void LyXText::InsertChar(char c) } 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 @@ -2726,7 +2777,7 @@ void LyXText::InsertChar(char c) 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. */ @@ -3298,12 +3349,14 @@ void LyXText::Backspace() 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) { @@ -3365,7 +3418,7 @@ void LyXText::Backspace() 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 @@ -3416,7 +3469,7 @@ void LyXText::Backspace() 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 @@ -3428,7 +3481,7 @@ void LyXText::Backspace() // 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) { @@ -3529,12 +3582,12 @@ void LyXText::Backspace() 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; } @@ -3560,9 +3613,7 @@ void LyXText::Backspace() 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) @@ -3580,19 +3631,23 @@ void LyXText::Backspace() 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 @@ -4444,7 +4499,7 @@ int LyXText::DefaultHeight() const /* 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; @@ -4457,6 +4512,8 @@ int LyXText::GetColumnNearX(Row * row, int & x) const 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 @@ -4464,26 +4521,29 @@ int LyXText::GetColumnNearX(Row * row, int & x) const && 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*/ @@ -4523,28 +4583,31 @@ int LyXText::GetColumnNearX(Row * row, int & x) const } 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 diff --git a/src/text2.C b/src/text2.C index 445fb211e1..e0ed5616ba 100644 --- a/src/text2.C +++ b/src/text2.C @@ -846,7 +846,7 @@ void LyXText::SetFont(LyXFont const & font, bool toggleall) SetCursor(sel_end_cursor.par, sel_end_cursor.pos); ClearSelection(); SetSelection(); - SetCursor(tmpcursor.par, tmpcursor.pos); + SetCursor(tmpcursor.par, tmpcursor.pos, true, tmpcursor.boundary); } @@ -875,7 +875,7 @@ void LyXText::RedoHeightOfParagraph(LyXCursor const & cur) status = LyXText::NEED_MORE_REFRESH; refresh_y = y; refresh_row = tmprow; - SetCursor(cur.par, cur.pos); + SetCursor(cur.par, cur.pos, false, cursor.boundary); } @@ -1054,8 +1054,8 @@ void LyXText::SetSelection() } // 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. @@ -3115,16 +3115,17 @@ int LyXText::UpdateInset(Inset * inset) 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()){ @@ -3154,6 +3155,7 @@ void LyXText::SetCursor(LyXCursor & cur, LyXParagraph * par, cur.par = par; cur.pos = pos; + cur.boundary = boundary; /* get the cursor y position in text */ long y = 0; @@ -3175,16 +3177,18 @@ void LyXText::SetCursor(LyXCursor & cur, LyXParagraph * par, 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*/ @@ -3248,9 +3252,10 @@ void LyXText::SetCursor(LyXCursor & cur, LyXParagraph * par, 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 @@ -3369,18 +3374,32 @@ void LyXText::SetCursorIntern(LyXParagraph * par, 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); } @@ -3391,29 +3410,14 @@ void LyXText::SetCursorFromCoordinates(int x, long y) const /* 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); } @@ -3422,7 +3426,7 @@ void LyXText::SetCursorFromCoordinates(LyXCursor & cur, int x, long y) const /* 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; @@ -3432,9 +3436,9 @@ void LyXText::SetCursorFromCoordinates(LyXCursor & cur, int x, long y) const } -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) && @@ -3445,20 +3449,27 @@ void LyXText::CursorLeft() const } -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) && @@ -3469,14 +3480,19 @@ void LyXText::CursorRight() const } -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); - } }