From: Lars Gullik Bjønnes Date: Thu, 3 Feb 2000 19:51:27 +0000 (+0000) Subject: applied the hebrew patch X-Git-Tag: 1.6.10~22388 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=c779cef938fc3720f4a912ba7356f9ffd9ff3233;p=features.git applied the hebrew patch git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@528 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/ChangeLog b/ChangeLog index 597439972d..da616d7d67 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2000-02-03 Lars Gullik Bjønnes + * applied the hebrew patch. + * src/lyxrow.h: make sure that all Row variables are initialized. * src/text2.C (TextHandleUndo): comment out a delete, this might diff --git a/src/BufferView.C b/src/BufferView.C index 994e28c095..b228294cfc 100644 --- a/src/BufferView.C +++ b/src/BufferView.C @@ -44,6 +44,8 @@ using std::for_each; #include "lyx_cb.h" #include "gettext.h" #include "layout.h" +#include "intl.h" +#include "lyxrc.h" using std::find_if; @@ -467,6 +469,7 @@ int BufferView::resizeCurrentBuffer() updateScrollbar(); redraw(); owner_->getMiniBuffer()->Init(); + SetState(); AllowInput(); // Now if the title form still exist kill it @@ -1231,6 +1234,8 @@ int BufferView::WorkAreaButtonRelease(FL_OBJECT * ob, Window , (abs(last_click_y - y) >= 5)) { return 0; } + SetState(); + owner_->getMiniBuffer()->Set(CurrentState()); // Did we hit an editable inset? if (inset_hit != 0) { @@ -1303,15 +1308,15 @@ int BufferView::WorkAreaButtonRelease(FL_OBJECT * ob, Window , // Do we want to close a float? (click on the float-label) if (text->cursor.row->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE - && text->cursor.pos == 0 + //&& text->cursor.pos == 0 && text->cursor.row->previous && text->cursor.row->previous->par-> footnoteflag != LyXParagraph::OPEN_FOOTNOTE){ LyXFont font (LyXFont::ALL_SANE); - font.setSize(LyXFont::SIZE_SMALL); + font.setSize(LyXFont::SIZE_FOOTNOTE); int box_x = 20; // LYX_PAPER_MARGIN; - box_x += font.textWidth("Mwide-figM", 10); + box_x += font.textWidth(" wide-tab ", 10); int screen_first = screen->first; @@ -1351,8 +1356,10 @@ Inset * BufferView::checkInsetHit(int & x, int & y) int y_tmp = y + getScreen()->first; - LyXCursor cursor = text->cursor; - if (cursor.pos < cursor.par->Last() + LyXCursor & cursor = text->cursor; + LyXDirection direction = text->GetFontDirection(text->real_current_font); + + if (cursor.pos < cursor.par->Last() && cursor.par->GetChar(cursor.pos) == LyXParagraph::META_INSET && cursor.par->GetInset(cursor.pos) && cursor.par->GetInset(cursor.pos)->Editable()) { @@ -1360,26 +1367,50 @@ Inset * BufferView::checkInsetHit(int & x, int & y) // Check whether the inset really was hit Inset * tmpinset = cursor.par->GetInset(cursor.pos); LyXFont font = text->GetFont(cursor.par, cursor.pos); - if (x > cursor.x - && x < cursor.x + tmpinset->Width(font) + int start_x, end_x; + if (direction == LYX_DIR_LEFT_TO_RIGHT) { + start_x = cursor.x; + end_x = cursor.x + tmpinset->Width(font); + } else { + start_x = cursor.x - tmpinset->Width(font); + end_x = cursor.x; + } + + if (x > start_x && x < end_x && y_tmp > cursor.y - tmpinset->Ascent(font) && y_tmp < cursor.y + tmpinset->Descent(font)) { - x = x - cursor.x; + x = x - start_x; // The origin of an inset is on the baseline y = y_tmp - (cursor.y); return tmpinset; } - } else if (cursor.pos - 1 >= 0 + } + + if (cursor.pos - 1 >= 0 && cursor.par->GetChar(cursor.pos - 1) == LyXParagraph::META_INSET && cursor.par->GetInset(cursor.pos - 1) && cursor.par->GetInset(cursor.pos - 1)->Editable()) { text->CursorLeft(); - Inset * result = checkInsetHit(x, y); - if (result == 0) { + Inset * tmpinset = cursor.par->GetInset(cursor.pos); + LyXFont font = text->GetFont(cursor.par, cursor.pos); + int start_x, end_x; + if (direction == LYX_DIR_LEFT_TO_RIGHT) { + start_x = cursor.x; + end_x = cursor.x + tmpinset->Width(font); + } else { + start_x = cursor.x - tmpinset->Width(font); + end_x = cursor.x; + } + if (x > start_x && x < end_x + && y_tmp > cursor.y - tmpinset->Ascent(font) + && y_tmp < cursor.y + tmpinset->Descent(font)) { + x = x - start_x; + // The origin of an inset is on the baseline + y = y_tmp - (cursor.y); + return tmpinset; + } else { text->CursorRight(); return 0; - } else { - return result; } } return 0; @@ -1759,6 +1790,22 @@ void BufferView::smallUpdate(signed char f) } } +extern LyXRC * lyxrc; +void BufferView::SetState() { + bool primary; + + if (!lyxrc->rtl_support) + return; + + if (text->GetFontDirection(text->real_current_font) + == LYX_DIR_LEFT_TO_RIGHT) { + if (!owner_->getIntl()->primarykeymap) + owner_->getIntl()->KeyMapPrim(); + } else { + if (owner_->getIntl()->primarykeymap) + owner_->getIntl()->KeyMapSec(); + } +} void BufferView::insetSleep() { diff --git a/src/BufferView.h b/src/BufferView.h index 9248a676ba..bba675ec06 100644 --- a/src/BufferView.h +++ b/src/BufferView.h @@ -207,6 +207,10 @@ public: */ static int work_area_handler(FL_OBJECT *, int event, FL_Coord, FL_Coord, int key, void *xev); + + /// + void SetState(); + private: /// int WorkAreaMotionNotify(FL_OBJECT * ob, diff --git a/src/LyXAction.C b/src/LyXAction.C index b0fa6c6a9c..33f1230e0e 100644 --- a/src/LyXAction.C +++ b/src/LyXAction.C @@ -196,6 +196,7 @@ void LyXAction::init() { LFUN_NOUN, "font-noun", N_("Toggle noun style"), Noop }, { LFUN_ROMAN, "font-roman", N_("Toggle roman font style"), Noop }, + { LFUN_RTL, "font-rtl", N_("Toggle RTL"), Noop }, { LFUN_SANS, "font-sans", N_("Toggle sans font style"), Noop }, { LFUN_FONT_SIZE, "font-size", N_("Set font size"), Noop }, { LFUN_FONT_STATE, "font-state", N_("Show font state"), diff --git a/src/buffer.C b/src/buffer.C index ffdcc84081..e4b86df493 100644 --- a/src/buffer.C +++ b/src/buffer.C @@ -677,6 +677,18 @@ bool Buffer::readLyXformat2(LyXLex & lex, LyXParagraph * par) else lex.printError("Unknown LaTeX font flag " "`$$Token'"); + } else if (token == "\\direction") { + lex.next(); + string tok = lex.GetString(); + if (tok == "ltr") + font.setDirection(LyXFont::LTR_DIR); + else if (tok == "rtl") + font.setDirection(LyXFont::RTL_DIR); + else if (tok == "default") + font.setDirection(LyXFont::INHERIT_DIR); + else + lex.printError("Unknown font flag " + "`$$Token'"); } else if (token == "\\emph") { lex.next(); font.setEmph(font.setLyXMisc(lex.GetString())); @@ -1681,11 +1693,16 @@ void Buffer::makeLaTeXFile(string const & fname, && params.orientation == BufferParams::ORIENTATION_LANDSCAPE) options += "landscape,"; - // language should be a parameter to \documentclass + // language should be a parameter to \documentclass if (params.language != "default") { + if (params.language == "hebrew") + options += "english,"; + else if (lyxrc->rtl_support) + options += "hebrew,"; options += params.language + ','; - } - + } else if (lyxrc->rtl_support) + options += "hebrew,english,"; + // the user-defined options if (!params.options.empty()) { options += params.options + ','; @@ -1840,7 +1857,7 @@ void Buffer::makeLaTeXFile(string const & fname, // We try to load babel late, in case it interferes // with other packages. - if (params.language != "default") { + if (params.language != "default" || lyxrc->rtl_support ) { LFile += "\\usepackage{babel}\n"; texrow.newline(); } diff --git a/src/commandtags.h b/src/commandtags.h index debdb5ad3d..d7ec3bf177 100644 --- a/src/commandtags.h +++ b/src/commandtags.h @@ -243,6 +243,7 @@ enum kb_action { LFUN_SEQUENCE, // Andre' 991111 LFUN_SAVEPREFERENCES, // Lgb 991127 LFUN_DATE_INSERT, // jdblair 20000131 + LFUN_RTL, // Dekel 20000203 LFUN_LASTACTION /* this marks the end of the table */ }; diff --git a/src/intl.h b/src/intl.h index 8cf5bf36d5..919966dcad 100644 --- a/src/intl.h +++ b/src/intl.h @@ -58,6 +58,8 @@ public: /// bool keymapon; /// + bool primarykeymap; + /// char * chsetcode; /// static void DispatchCallback(FL_OBJECT *, long); @@ -71,8 +73,6 @@ private: /// void Keymap(long code); /// - bool primarykeymap; - /// int curkeymap; /// int otherkeymap; diff --git a/src/layout.h b/src/layout.h index 58cb39ce3b..cef49cad6e 100644 --- a/src/layout.h +++ b/src/layout.h @@ -65,6 +65,15 @@ enum LYX_MARGIN_TYPE { MARGIN_RIGHT_ADDRESS_BOX }; + +/// +enum LyXDirection { + /// + LYX_DIR_LEFT_TO_RIGHT = 1, + /// + LYX_DIR_RIGHT_TO_LEFT = -1 +}; + /// enum LyXAlignment { /// diff --git a/src/lyx_cb.C b/src/lyx_cb.C index c3aade0dcb..d9f6767994 100644 --- a/src/lyx_cb.C +++ b/src/lyx_cb.C @@ -2104,6 +2104,7 @@ void BufferView::openStuff() update(-2); text->OpenStuff(); update(0); + current_view->SetState(); } } @@ -2117,6 +2118,7 @@ void BufferView::toggleFloat() update(-2); text->ToggleFootnote(); update(0); + current_view->SetState(); } } @@ -2132,6 +2134,7 @@ void BufferView::menuUndo() owner()->getMiniBuffer()->Set(_("No further undo information")); else update(-1); + current_view->SetState(); } } @@ -2152,6 +2155,7 @@ void BufferView::menuRedo() owner()->getMiniBuffer()->Set(_("No further redo information")); else update(-1); + current_view->SetState(); } } @@ -2315,6 +2319,14 @@ void TexCB() ToggleAndShow(font); } +void RTLCB() +{ + LyXFont font(LyXFont::ALL_IGNORE); + font.setDirection (LyXFont::TOGGLE_DIR); + ToggleAndShow(font); +} + + void StyleResetCB() { @@ -2929,6 +2941,13 @@ extern "C" void DocumentApplyCB(FL_OBJECT *, long) if (!current_view->available()) return; + if (lyxrc->rtl_support) { + current_view->text->SetCursor(current_view->text->cursor.par, + current_view->text->cursor.pos); + current_view->SetState(); + //minibuffer->Set(CurrentState()); + } + LyXTextClassList::ClassList::size_type new_class = fl_get_choice(fd_form_document->choice_class) - 1; if (params->textclass != new_class) { // try to load new_class @@ -3270,6 +3289,7 @@ extern "C" void TableApplyCB(FL_OBJECT *, long) current_view->update(1); current_view->owner()->getMiniBuffer()->Set(_("Table inserted")); + current_view->SetState(); } @@ -3534,6 +3554,7 @@ extern "C" void FigureApplyCB(FL_OBJECT *, long) current_view->update(0); current_view->owner()->getMiniBuffer()->Set(_("Figure inserted")); current_view->text->UnFreezeUndo(); + current_view->SetState(); } diff --git a/src/lyx_cb.h b/src/lyx_cb.h index 9619bdd979..13c2854f06 100644 --- a/src/lyx_cb.h +++ b/src/lyx_cb.h @@ -24,6 +24,8 @@ extern void BoldCB(); /// extern void NounCB(); /// +extern void RTLCB(); +/// extern "C" void MarginCB(FL_OBJECT *, long); /// extern "C" void FigureCB(FL_OBJECT *, long); diff --git a/src/lyxfont.C b/src/lyxfont.C index c51edfc907..d7231df75a 100644 --- a/src/lyxfont.C +++ b/src/lyxfont.C @@ -59,6 +59,9 @@ string const lGUISizeNames[15] = string const GUIMiscNames[5] = { N_("Off"), N_("On"), N_("Toggle"), N_("Inherit"), N_("Ignore") }; +string const GUIDirectionNames[5] = +{ N_("LTR"), N_("RTL"), N_("Toggle"), N_("Inherit"), N_("Ignore") }; + string const GUIColorNames[13] = { N_("None"), N_("Black"), N_("White"), N_("Red"), N_("Green"), N_("Blue"), N_("Cyan"), N_("Magenta"), @@ -240,6 +243,19 @@ void LyXFont::update(LyXFont const & newfont, bool toggleall) setNoun(setMisc(newfont.noun(), noun())); setLatex(setMisc(newfont.latex(), latex())); + switch(newfont.direction()) { + case TOGGLE_DIR: + if (direction() == LTR_DIR) + setDirection(RTL_DIR); + else + setDirection(LTR_DIR); + break; + case IGNORE_DIR: + break; + default: + setDirection(newfont.direction()); + } + if(newfont.color() == color() && toggleall) setColor(INHERIT_COLOR); // toggle 'back' else if (newfont.color() != IGNORE_COLOR) @@ -268,6 +284,8 @@ void LyXFont::reduce(LyXFont const & tmplt) setLatex(INHERIT); if (color() == tmplt.color()) setColor(INHERIT_COLOR); + if (direction() == tmplt.direction()) + setDirection(INHERIT_DIR); } @@ -325,6 +343,12 @@ LyXFont & LyXFont::realize(LyXFont const & tmplt) bits &= ~(Col_Mask << Col_Pos); bits |= (tmplt.bits & Col_Mask << Col_Pos); } + if ((bits & (Dir_Mask << Dir_Pos)) == ui32(INHERIT_DIR) << Dir_Pos) + { + bits &= ~(Dir_Mask << Dir_Pos); + bits |= (tmplt.bits & Dir_Mask << Dir_Pos); + } + return *this; } @@ -336,7 +360,8 @@ bool LyXFont::resolved() const shape() != INHERIT_SHAPE && size() != INHERIT_SIZE && emph() != INHERIT && underbar() != INHERIT && noun() != INHERIT && latex() != INHERIT && - color() != INHERIT_COLOR); + color() != INHERIT_COLOR && + direction() != INHERIT_DIR); } @@ -363,6 +388,8 @@ string LyXFont::stateText() const buf += string(_("Noun ")) + _(GUIMiscNames[noun()].c_str()) + ", "; if (latex() != INHERIT) buf += string(_("Latex ")) + _(GUIMiscNames[latex()].c_str()) + ", "; + if (direction() != INHERIT_DIR) + buf += string(_("Direction ")) + _(GUIDirectionNames[direction()].c_str()) + ", "; if (buf.empty()) buf = _("Default"); buf = strip(buf, ' '); @@ -549,6 +576,17 @@ LyXFont & LyXFont::lyxRead(LyXLex & lex) lex.next(); string tok = lex.GetString(); setLyXColor(tok); + } else if (tok == "direction") { + lex.next(); + string tok = lowercase(lex.GetString()); + + if (tok == "ltr") { + setDirection(LTR_DIR); + } else if (tok == "rtl") { + setDirection(RTL_DIR); + } else { + lex.printError("Illegal type`$$Token'"); + } } else { lex.printError("Unknown tag `$$Token'"); error = true; @@ -615,12 +653,26 @@ void LyXFont::lyxWriteChanges(LyXFont const & orgfont, ostream & os) const if (orgfont.color() != color()) { os << "\\color " << LyXColorNames[color()] << "\n"; } + if (orgfont.direction() != direction()) { + switch (direction()) { + case RTL_DIR: os << "\\direction rtl \n"; break; + case LTR_DIR: os << "\\direction ltr\n"; break; + case TOGGLE_DIR: lyxerr << "LyXFont::lyxWriteFontChanges: " + "TOGGLE should not appear here!" + << endl; + case INHERIT_DIR: os << "\\direction default \n"; break; + case IGNORE_DIR: lyxerr << "LyXFont::lyxWriteFontChanges: " + "IGNORE should not appear here!" + << endl; + break; + } + } } /// Writes the head of the LaTeX needed to impose this font // Returns number of chars written. -int LyXFont::latexWriteStartChanges(string & file, LyXFont const & base) const +int LyXFont::latexWriteStartChanges(string & file, LyXFont const & base, LyXFont const & prev) const { LyXFont f = *this; f.reduce(base); @@ -630,7 +682,21 @@ int LyXFont::latexWriteStartChanges(string & file, LyXFont const & base) const int count = 0; bool env = false; - + + FONT_DIRECTION direction = f.direction(); + if (direction != prev.direction()) { + if (direction == LTR_DIR) { + file += "\\L{"; + count += 3; + env = true; //We have opened a new environment + } + if (direction == RTL_DIR) { + file += "\\R{"; + count += 3; + env = true; //We have opened a new environment + } + } + if (f.family() != INHERIT_FAMILY) { file += '\\'; file += LaTeXFamilyNames[f.family()]; @@ -693,7 +759,7 @@ int LyXFont::latexWriteStartChanges(string & file, LyXFont const & base) const /// Writes ending block of LaTeX needed to close use of this font // Returns number of chars written // This one corresponds to latexWriteStartChanges(). (Asger) -int LyXFont::latexWriteEndChanges(string & file, LyXFont const & base) const +int LyXFont::latexWriteEndChanges(string & file, LyXFont const & base, LyXFont const & next) const { LyXFont f = *this; // why do you need this? f.reduce(base); // why isn't this just "reduce(base);" (Lgb) @@ -706,6 +772,15 @@ int LyXFont::latexWriteEndChanges(string & file, LyXFont const & base) const int count = 0; bool env = false; + + FONT_DIRECTION direction = f.direction(); + if ( direction != next.direction() + && (direction == RTL_DIR || direction == LTR_DIR) ) { + file += '}'; + ++count; + env = true; // Size change need not bother about closing env. + } + if (f.family() != INHERIT_FAMILY) { file += '}'; ++count; diff --git a/src/lyxfont.h b/src/lyxfont.h index 668cdde652..c8d003835d 100644 --- a/src/lyxfont.h +++ b/src/lyxfont.h @@ -119,6 +119,19 @@ public: IGNORE_SIZE }; + enum FONT_DIRECTION { + /// + LTR_DIR, + /// + RTL_DIR, + /// + TOGGLE_DIR, + /// + INHERIT_DIR, + /// + IGNORE_DIR + }; + /// Used for emph, underbar, noun and latex toggles enum FONT_MISC_STATE { /// @@ -227,7 +240,10 @@ public: /// FONT_COLOR color() const; - + + /// + FONT_DIRECTION direction() const; + /// LyXFont & setFamily(LyXFont::FONT_FAMILY f); /// @@ -246,7 +262,9 @@ public: LyXFont & setLatex(LyXFont::FONT_MISC_STATE l); /// LyXFont & setColor(LyXFont::FONT_COLOR c); - + /// + LyXFont & setDirection(LyXFont::FONT_DIRECTION d); + /// Set family after LyX text format LyXFont & setLyXFamily(string const &); @@ -304,13 +322,15 @@ public: to this font. Returns number of chars written. Base is the font state active now. */ - int latexWriteStartChanges(string &, LyXFont const & base) const; + int latexWriteStartChanges(string &, LyXFont const & base, + LyXFont const & prev) const; /** Writes tha tail of the LaTeX needed to chagne to this font. Returns number of chars written. Base is the font state we want to achieve. */ - int latexWriteEndChanges(string &, LyXFont const & base) const; + int latexWriteEndChanges(string &, LyXFont const & base, + LyXFont const & next) const; /// Build GUI description of font state string stateText() const; @@ -405,7 +425,9 @@ private: /// Nou_Pos = 22, /// - Lat_Pos = 25 + Lat_Pos = 25, + /// + Dir_Pos = 28 }; /// @@ -421,6 +443,8 @@ private: /// Col_Mask = 0x0f, /// + Dir_Mask = 0x07, + /// Misc_Mask = 0x07 }; @@ -433,7 +457,8 @@ private: | ui32(OFF) << Emp_Pos | ui32(OFF) << Und_Pos | ui32(OFF) << Nou_Pos - | ui32(OFF) << Lat_Pos}; + | ui32(OFF) << Lat_Pos + | ui32(LTR_DIR) << Dir_Pos}; /// All inherit font enum{ inherit = ui32(INHERIT_FAMILY) << Fam_Pos @@ -444,7 +469,8 @@ private: | ui32(INHERIT) << Emp_Pos | ui32(INHERIT) << Und_Pos | ui32(INHERIT) << Nou_Pos - | ui32(INHERIT) << Lat_Pos}; + | ui32(INHERIT) << Lat_Pos + | ui32(INHERIT_DIR) << Dir_Pos}; /// All ignore font enum{ ignore = ui32(IGNORE_FAMILY) << Fam_Pos @@ -455,7 +481,8 @@ private: | ui32(IGNORE) << Emp_Pos | ui32(IGNORE) << Und_Pos | ui32(IGNORE) << Nou_Pos - | ui32(IGNORE) << Lat_Pos}; + | ui32(IGNORE) << Lat_Pos + | ui32(IGNORE_DIR) << Dir_Pos}; /// Updates a misc setting according to request LyXFont::FONT_MISC_STATE setMisc(LyXFont::FONT_MISC_STATE newfont, @@ -562,6 +589,10 @@ inline LyXFont::FONT_COLOR LyXFont::color() const return LyXFont::FONT_COLOR((bits >> Col_Pos) & Col_Mask); } +inline LyXFont::FONT_DIRECTION LyXFont::direction() const +{ + return LyXFont::FONT_DIRECTION((bits >> Dir_Pos) & Dir_Mask); +} inline LyXFont & LyXFont::setFamily(LyXFont::FONT_FAMILY f) { @@ -632,4 +663,12 @@ inline LyXFont & LyXFont::setColor(LyXFont::FONT_COLOR c) bits |= ui32(c) << Col_Pos; return *this; } + +inline LyXFont & LyXFont::setDirection(LyXFont::FONT_DIRECTION d) +{ + bits &= ~(Dir_Mask << Dir_Pos); + bits |= ui32(d) << Dir_Pos; + return *this; +} + #endif diff --git a/src/lyxfunc.C b/src/lyxfunc.C index 996b328543..051edd32ca 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -164,6 +164,7 @@ void LyXFunc::moveCursorUpdate(bool selecting) /* ---> Everytime the cursor is moved, show the current font state. */ // should this too me moved out of this func? //owner->getMiniBuffer()->Set(CurrentState()); + owner->view()->SetState(); } @@ -202,6 +203,8 @@ int LyXFunc::processKeyEvent(XEvent * ev) keysym_return == XK_Escape) { owner->view()->unlockInset(owner->view()->the_locking_inset); owner->view()->text->CursorRight(); + moveCursorUpdate(false); + owner->getMiniBuffer()->Set(CurrentState()); return 0; } @@ -404,6 +407,10 @@ LyXFunc::func_status LyXFunc::getStatus(int ac) const if (font.latex() == LyXFont::ON) box = LyXFunc::ToggleOn; break; + case LFUN_RTL: + if (font.direction() == LyXFont::RTL_DIR) + box = LyXFunc::ToggleOn; + break; default: box = LyXFunc::OK; break; @@ -547,8 +554,20 @@ string LyXFunc::Dispatch(int ac, return string(); else { setMessage(N_("Text mode")); - if (action == LFUN_RIGHT || action == -1) + LyXDirection direction = owner->view()->text->GetParDirection(owner->view()->text->cursor.par); + if ( action == -1 || + (action == LFUN_RIGHT + && direction == LYX_DIR_LEFT_TO_RIGHT)) { owner->view()->text->CursorRight(); + moveCursorUpdate(false); + owner->getMiniBuffer()->Set(CurrentState()); + } + if ( action == LFUN_LEFT + && direction == LYX_DIR_RIGHT_TO_LEFT) { + owner->view()->text->CursorRight(); + moveCursorUpdate(false); + owner->getMiniBuffer()->Set(CurrentState()); + } if (action == LFUN_LEFT || action == LFUN_RIGHT) return string(); } @@ -918,6 +937,8 @@ string LyXFunc::Dispatch(int ac, case LFUN_TEX: TexCB(); + owner->view()->SetState(); + owner->getMiniBuffer()->Set(CurrentState()); break; case LFUN_MELT: @@ -938,7 +959,8 @@ string LyXFunc::Dispatch(int ac, MeltCB(ob, 0); } else - FootCB(ob, 0); + FootCB(ob, 0); + owner->view()->SetState(); break; case LFUN_MARGINMELT: @@ -952,6 +974,7 @@ string LyXFunc::Dispatch(int ac, } else MarginCB(ob, 0); + owner->view()->SetState(); break; // --- version control ------------------------------- @@ -1140,6 +1163,14 @@ string LyXFunc::Dispatch(int ac, owner->getToolbar()->combox->Show(); break; + case LFUN_RTL: + { + RTLCB(); + owner->view()->SetState(); + owner->getMiniBuffer()->Set(CurrentState()); + } + break; + case LFUN_EMPH: EmphCB(); break; @@ -1264,9 +1295,12 @@ string LyXFunc::Dispatch(int ac, case LFUN_RIGHT: { LyXText * tmptext = owner->view()->text; + LyXDirection direction = tmptext->GetParDirection(tmptext->cursor.par); if(!tmptext->mark_set) owner->view()->beforeChange(); owner->view()->update(-2); + if (direction == LYX_DIR_RIGHT_TO_LEFT) + tmptext->CursorLeft(); if (tmptext->cursor.pos < tmptext->cursor.par->Last() && tmptext->cursor.par->GetChar(tmptext->cursor.pos) == LyXParagraph::META_INSET @@ -1277,7 +1311,8 @@ string LyXFunc::Dispatch(int ac, tmpinset->Edit(0, 0); break; } - tmptext->CursorRight(); + if (direction == LYX_DIR_LEFT_TO_RIGHT) + tmptext->CursorRight(); owner->view()->text->FinishUndo(); moveCursorUpdate(false); owner->getMiniBuffer()->Set(CurrentState()); @@ -1289,9 +1324,11 @@ string LyXFunc::Dispatch(int ac, // This is soooo ugly. Isn`t it possible to make // it simpler? (Lgb) LyXText * txt = owner->view()->text; + LyXDirection direction = txt->GetParDirection(txt->cursor.par); if(!txt->mark_set) owner->view()->beforeChange(); owner->view()->update(-2); - txt->CursorLeft(); + if (direction == LYX_DIR_LEFT_TO_RIGHT) + txt->CursorLeft(); if (txt->cursor.pos < txt->cursor.par->Last() && txt->cursor.par->GetChar(txt->cursor.pos) == LyXParagraph::META_INSET @@ -1303,6 +1340,9 @@ string LyXFunc::Dispatch(int ac, txt->cursor.pos)), 0); break; } + if (direction == LYX_DIR_RIGHT_TO_LEFT) + txt->CursorRight(); + owner->view()->text->FinishUndo(); moveCursorUpdate(false); owner->getMiniBuffer()->Set(CurrentState()); @@ -1402,7 +1442,11 @@ string LyXFunc::Dispatch(int ac, if(!owner->view()->text->mark_set) owner->view()->beforeChange(); owner->view()->update(-2); - owner->view()->text->CursorRightOneWord(); + if (owner->view()->text->GetParDirection(owner->view()->text->cursor.par) + == LYX_DIR_LEFT_TO_RIGHT) + owner->view()->text->CursorRightOneWord(); + else + owner->view()->text->CursorLeftOneWord(); owner->view()->text->FinishUndo(); moveCursorUpdate(false); owner->getMiniBuffer()->Set(CurrentState()); @@ -1412,7 +1456,11 @@ string LyXFunc::Dispatch(int ac, if(!owner->view()->text->mark_set) owner->view()->beforeChange(); owner->view()->update(-2); - owner->view()->text->CursorLeftOneWord(); + if (owner->view()->text->GetParDirection(owner->view()->text->cursor.par) + == LYX_DIR_LEFT_TO_RIGHT) + owner->view()->text->CursorLeftOneWord(); + else + owner->view()->text->CursorRightOneWord(); owner->view()->text->FinishUndo(); moveCursorUpdate(false); owner->getMiniBuffer()->Set(CurrentState()); @@ -1442,7 +1490,11 @@ string LyXFunc::Dispatch(int ac, /* cursor selection ---------------------------- */ case LFUN_RIGHTSEL: owner->view()->update(-2); - owner->view()->text->CursorRight(); + if (owner->view()->text->GetParDirection(owner->view()->text->cursor.par) + == LYX_DIR_LEFT_TO_RIGHT) + owner->view()->text->CursorRight(); + else + owner->view()->text->CursorLeft(); owner->view()->text->FinishUndo(); moveCursorUpdate(true); owner->getMiniBuffer()->Set(CurrentState()); @@ -1450,7 +1502,11 @@ string LyXFunc::Dispatch(int ac, case LFUN_LEFTSEL: owner->view()->update(-2); - owner->view()->text->CursorLeft(); + if (owner->view()->text->GetParDirection(owner->view()->text->cursor.par) + == LYX_DIR_LEFT_TO_RIGHT) + owner->view()->text->CursorLeft(); + else + owner->view()->text->CursorRight(); owner->view()->text->FinishUndo(); moveCursorUpdate(true); owner->getMiniBuffer()->Set(CurrentState()); @@ -1522,7 +1578,11 @@ string LyXFunc::Dispatch(int ac, case LFUN_WORDRIGHTSEL: owner->view()->update(-2); - owner->view()->text->CursorRightOneWord(); + if (owner->view()->text->GetParDirection(owner->view()->text->cursor.par) + == LYX_DIR_LEFT_TO_RIGHT) + owner->view()->text->CursorRightOneWord(); + else + owner->view()->text->CursorLeftOneWord(); owner->view()->text->FinishUndo(); moveCursorUpdate(true); owner->getMiniBuffer()->Set(CurrentState()); @@ -1530,7 +1590,11 @@ string LyXFunc::Dispatch(int ac, case LFUN_WORDLEFTSEL: owner->view()->update(-2); - owner->view()->text->CursorLeftOneWord(); + if (owner->view()->text->GetParDirection(owner->view()->text->cursor.par) + == LYX_DIR_LEFT_TO_RIGHT) + owner->view()->text->CursorLeftOneWord(); + else + owner->view()->text->CursorRightOneWord(); owner->view()->text->FinishUndo(); moveCursorUpdate(true); owner->getMiniBuffer()->Set(CurrentState()); @@ -1599,6 +1663,9 @@ string LyXFunc::Dispatch(int ac, owner->view()->cut(); } SetUpdateTimer(); + moveCursorUpdate(false); + owner->getMiniBuffer()->Set(CurrentState()); + owner->view()->SetState(); break; case LFUN_DELETE_SKIP: @@ -1654,6 +1721,7 @@ string LyXFunc::Dispatch(int ac, owner->view()->update( 1 ); SetUpdateTimer(); moveCursorUpdate(false); + owner->getMiniBuffer()->Set(CurrentState()); break; /* -------> Delete word backward. */ @@ -1664,6 +1732,7 @@ string LyXFunc::Dispatch(int ac, owner->view()->update( 1 ); SetUpdateTimer(); moveCursorUpdate(false); + owner->getMiniBuffer()->Set(CurrentState()); break; /* -------> Kill to end of line. */ @@ -1712,6 +1781,8 @@ string LyXFunc::Dispatch(int ac, owner->view()->cut(); } SetUpdateTimer(); + owner->getMiniBuffer()->Set(CurrentState()); + owner->view()->SetState(); } break; @@ -1755,6 +1826,8 @@ string LyXFunc::Dispatch(int ac, SetUpdateTimer(0.01); owner->view()->text->sel_cursor = owner->view()->text->cursor; + owner->view()->SetState(); + owner->getMiniBuffer()->Set(CurrentState()); break; } @@ -1766,6 +1839,8 @@ string LyXFunc::Dispatch(int ac, SetUpdateTimer(0.01); owner->view()->text->sel_cursor = owner->view()->text->cursor; + owner->view()->SetState(); + owner->getMiniBuffer()->Set(CurrentState()); break; } @@ -1797,6 +1872,8 @@ string LyXFunc::Dispatch(int ac, } SetUpdateTimer(0.01); owner->view()->text->sel_cursor = cursor; + owner->view()->SetState(); + owner->getMiniBuffer()->Set(CurrentState()); } break; @@ -2297,6 +2374,7 @@ string LyXFunc::Dispatch(int ac, } owner->view()->text->InsertFootnoteEnvironment(kind); owner->view()->update(1); + owner->view()->SetState(); } break; diff --git a/src/lyxrc.C b/src/lyxrc.C index b30469c415..11bf1382dd 100644 --- a/src/lyxrc.C +++ b/src/lyxrc.C @@ -128,6 +128,7 @@ enum LyXRCTags { RC_RELYX_COMMAND, RC_HTML_COMMAND, RC_MAKE_BACKUP, + RC_RTL_SUPPORT, RC_PDFLATEX_COMMAND, RC_PDF_MODE, RC_VIEWPDF_COMMAND, @@ -204,6 +205,7 @@ static keyword_item lyxrcTags[] = { { "\\printer", RC_PRINTER }, { "\\ps_command", RC_PS_COMMAND }, { "\\relyx_command", RC_RELYX_COMMAND }, + { "\\rtl", RC_RTL_SUPPORT }, { "\\screen_dpi", RC_SCREEN_DPI }, { "\\screen_font_encoding", RC_SCREEN_FONT_ENCODING }, { "\\screen_font_menu", RC_SCREEN_FONT_MENU }, @@ -323,6 +325,7 @@ LyXRC::LyXRC() isp_use_esc_chars = false; use_kbmap = false; hasBindFile = false; + rtl_support = false; defaultKeyBindings(); /// date_insert_format = "%A, %e. %B %Y"; @@ -911,6 +914,10 @@ int LyXRC::read(string const & filename) if (lexrc.next()) date_insert_format = lexrc.GetString(); break; + case RC_RTL_SUPPORT: + if (lexrc.next()) + rtl_support = lexrc.GetBool(); + break; case RC_LAST: break; // this is just a dummy } } @@ -1199,6 +1206,8 @@ void LyXRC::output(ostream & os) const os << "\\personal_dictionary \"" << isp_pers_dict << "\"\n"; case RC_ESC_CHARS: os << "\\escape_chars \"" << isp_esc_chars << "\"\n"; + case RC_RTL_SUPPORT: + os << "\\rtl " << tostr(rtl_support) << "\n"; case RC_MAKE_BACKUP: os << "\\make_backup " << tostr(make_backup) << "\n"; case RC_DATE_INSERT_FORMAT: diff --git a/src/lyxrc.h b/src/lyxrc.h index d1d30fbcda..6b30d0a6db 100644 --- a/src/lyxrc.h +++ b/src/lyxrc.h @@ -199,7 +199,8 @@ public: string lyxpipes; /// string date_insert_format; - + /// + bool rtl_support; private: /// void defaultKeyBindings(); diff --git a/src/lyxtext.h b/src/lyxtext.h index e0f1ceb0cf..4b3bd8190d 100644 --- a/src/lyxtext.h +++ b/src/lyxtext.h @@ -21,6 +21,7 @@ #include "undo.h" #include "lyxcursor.h" #include "lyxparagraph.h" +#include "layout.h" class Buffer; class BufferParams; @@ -226,10 +227,12 @@ public: void SelectSelectedWord(); /// void SetCursor(LyXParagraph * par, - LyXParagraph::size_type pos) const; + LyXParagraph::size_type pos, + bool setfont = true) const; /// void SetCursorIntern(LyXParagraph * par, - LyXParagraph::size_type pos) const; + LyXParagraph::size_type pos, + bool setfont = true) const; /// void SetCursorFromCoordinates(int x, long y) const; /// @@ -474,6 +477,18 @@ public: void toggleAppendix(); /// unsigned short paperWidth() const { return paperwidth; } + + /// + LyXDirection GetDocumentDirection() const; + /// + LyXDirection GetParDirection(LyXParagraph * par) const; + + /// + LyXDirection GetFontDirection(LyXFont const &font) const; + + /// + LyXDirection GetLetterDirection(LyXParagraph * par, LyXParagraph::size_type pos) const; + private: /// width of the paper unsigned short paperwidth; @@ -523,7 +538,8 @@ private: void PrepareToPrint(Row * row, float & x, float & fill_separator, float & fill_hfill, - float & fill_label_hfill) const; + float & fill_label_hfill, + bool bidi = true) const; /// void DeleteEmptyParagraphMechanism(LyXCursor const & old_cursor) const; @@ -590,6 +606,41 @@ private: */ bool HfillExpansion(Row const * row_ptr, LyXParagraph::size_type pos) const; + + /// + mutable vector log2vis_list; + + /// + mutable vector vis2log_list; + + /// + mutable LyXParagraph::size_type bidi_start; + + /// + void ComputeBidiTables(Row *row) const; + + /// + void ComputeBidiTablesFromTo(Row *row, + LyXParagraph::size_type from, + LyXParagraph::size_type to, + LyXParagraph::size_type offset) 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]; + } + /** returns the paragraph position of the last character in the specified row */ diff --git a/src/paragraph.C b/src/paragraph.C index b54f9b0f23..c641f54f6d 100644 --- a/src/paragraph.C +++ b/src/paragraph.C @@ -985,6 +985,8 @@ LyXFont LyXParagraph::getFont(LyXParagraph::size_type pos) const tmpfont = layout.font; else tmpfont = layout.labelfont; + if (current_view->text->GetParDirection((LyXParagraph *)this) == LYX_DIR_RIGHT_TO_LEFT) + tmpfont.setDirection(LyXFont::RTL_DIR); } // check for environment font information @@ -2314,6 +2316,17 @@ LyXParagraph * LyXParagraph::TeXOnePar(string & file, TexRow & texrow, texrow.newline(); } + LyXDirection direction = current_view->text->GetParDirection((LyXParagraph *)this); + LyXDirection global_direction = current_view->text->GetDocumentDirection(); + if (direction != global_direction) { + if (direction == LYX_DIR_LEFT_TO_RIGHT) + file += "{\\unsethebrew\n"; + else + file += "{\\sethebrew\n"; + texrow.newline(); + } + + switch (style.latextype) { case LATEX_COMMAND: file += '\\'; @@ -2368,6 +2381,9 @@ LyXParagraph * LyXParagraph::TeXOnePar(string & file, TexRow & texrow, } else if (style.resfont.size() != font.size()){ file += "{\\" + font.latexSize() + " \\par}"; } + + if (direction != global_direction) + file += "\\par}"; switch (style.latextype) { case LATEX_ITEM_ENVIRONMENT: @@ -2447,7 +2463,7 @@ bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow) bool return_value = false; LyXLayout const & style = textclasslist.Style(current_view->buffer()->params.textclass, GetLayout()); - LyXFont basefont; + LyXFont basefont, last_font; // Maybe we have to create a optional argument. if (style.labeltype != LABEL_MANUAL) @@ -2490,7 +2506,7 @@ bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow) if (i == main_body && !IsDummy()) { if (main_body > 0) { if (open_font) { - column += running_font.latexWriteEndChanges(file, basefont); + column += running_font.latexWriteEndChanges(file, basefont, basefont); open_font = false; } basefont = getFont(-1); // Now use the layout font @@ -2535,6 +2551,7 @@ bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow) // Fully instantiated font LyXFont font = getFont(i); + last_font = running_font; // Spaces at end of font change are simulated to be // outside font change, i.e. we write "\textXX{text} " @@ -2547,7 +2564,8 @@ bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow) // We end font definition before blanks if (!font.equalExceptLatex(running_font) && open_font) { column += running_font.latexWriteEndChanges(file, - basefont); + basefont, + (i == main_body-1) ? basefont : font); running_font = basefont; open_font = false; } @@ -2564,7 +2582,7 @@ bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow) // Do we need to change font? if (!font.equalExceptLatex(running_font) && i != main_body-1) { - column += font.latexWriteStartChanges(file, basefont); + column += font.latexWriteStartChanges(file, basefont, last_font); running_font = font; open_font = true; } @@ -2577,7 +2595,7 @@ bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow) file += '\n'; } else { if (open_font) { - column += running_font.latexWriteEndChanges(file, basefont); + column += running_font.latexWriteEndChanges(file, basefont, basefont); open_font = false; } basefont = getFont(-1); @@ -2600,7 +2618,7 @@ bool LyXParagraph::SimpleTeXOnePar(string & file, TexRow & texrow) // If we have an open font definition, we have to close it if (open_font) { - running_font.latexWriteEndChanges(file, basefont); + running_font.latexWriteEndChanges(file, basefont, basefont); } // Needed if there is an optional argument but no contents. @@ -2662,6 +2680,7 @@ bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow) LyXFont basefont = getFont(-1); // Get layout font // Which font is currently active? LyXFont running_font = basefont; + LyXFont last_font; // Do we have an open font change? bool open_font = false; int current_cell_number = -1; @@ -2682,6 +2701,7 @@ bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow) // Fully instantiated font LyXFont font = getFont(i); + last_font = running_font; // Spaces at end of font change are simulated to be // outside font change. @@ -2695,7 +2715,7 @@ bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow) // We end font definition before blanks if (font != running_font && open_font) { column += running_font.latexWriteEndChanges(file, - basefont); + basefont, font); running_font = basefont; open_font = false; } @@ -2705,7 +2725,7 @@ bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow) } // Do we need to change font? if (font != running_font) { - column += font.latexWriteStartChanges(file, basefont); + column += font.latexWriteStartChanges(file, basefont, last_font); running_font = font; open_font = true; } @@ -2723,7 +2743,7 @@ bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow) // SimpleTeXSpecialChars() if (open_font) { column += running_font - .latexWriteEndChanges(file, basefont); + .latexWriteEndChanges(file, basefont, basefont); open_font = false; } basefont = getFont(-1); @@ -2761,7 +2781,7 @@ bool LyXParagraph::SimpleTeXOneTablePar(string & file, TexRow & texrow) // If we have an open font definition, we have to close it if (open_font) { - running_font.latexWriteEndChanges(file, basefont); + running_font.latexWriteEndChanges(file, basefont, basefont); } ++current_cell_number; tmp = table->TexEndOfCell(file, current_cell_number); @@ -2789,6 +2809,7 @@ bool LyXParagraph::TeXContTableRows(string & file, textclasslist.Style(current_view->buffer()->params.textclass, GetLayout()); LyXFont basefont = getFont(-1); // Get layout font + LyXFont last_font; // Which font is currently active? LyXFont running_font = basefont; // Do we have an open font change? @@ -2822,6 +2843,7 @@ bool LyXParagraph::TeXContTableRows(string & file, // Fully instantiated font LyXFont font = getFont(i); + last_font = running_font; // Spaces at end of font change are simulated to // be outside font change. i.e. we write @@ -2835,7 +2857,7 @@ bool LyXParagraph::TeXContTableRows(string & file, // We end font definition before blanks if (font != running_font && open_font) { - column += running_font.latexWriteEndChanges(file, basefont); + column += running_font.latexWriteEndChanges(file, basefont, font); running_font = basefont; open_font = false; } @@ -2848,7 +2870,7 @@ bool LyXParagraph::TeXContTableRows(string & file, if (font != running_font) { column += font.latexWriteStartChanges(file, - basefont); + basefont, last_font); running_font = font; open_font = true; } @@ -2867,7 +2889,7 @@ bool LyXParagraph::TeXContTableRows(string & file, } // If we have an open font definition, we have to close it if (open_font) { - running_font.latexWriteEndChanges(file, basefont); + running_font.latexWriteEndChanges(file, basefont, basefont); open_font = false; } basefont = getFont(-1); @@ -3308,8 +3330,18 @@ void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow, case LyXParagraph::META_INSET: { Inset * inset = GetInset(i); if (inset) { + bool close = false; int len = file.length(); + if ( (inset->LyxCode() == Inset::GRAPHICS_CODE + || inset->LyxCode() == Inset::MATH_CODE) + && current_view->text->GetFontDirection(running_font) + == LYX_DIR_RIGHT_TO_LEFT) { + file += "\\L{"; + close = true; + } int tmp = inset->Latex(file, style.isCommand()); + if (close) + file += "}"; if (tmp) { column = 0; @@ -3326,7 +3358,7 @@ void LyXParagraph::SimpleTeXSpecialChars(string & file, TexRow & texrow, case LyXParagraph::META_NEWLINE: if (open_font) { column += running_font.latexWriteEndChanges(file, - basefont); + basefont, basefont); open_font = false; } basefont = getFont(-1); diff --git a/src/tex-strings.C b/src/tex-strings.C index 11eb4ae9c6..75106e0836 100644 --- a/src/tex-strings.C +++ b/src/tex-strings.C @@ -56,7 +56,7 @@ char const * tex_babel[] = {"default", "afrikaans", "american", "english", "esperanto", "estonian", "finnish", "francais", "french", "frenchb", "galician", - "german", "greek", "hungarian", "irish", + "german", "greek", "hebrew", "hungarian", "irish", "italian", "lsorbian", "magyar", "norsk", "polish", "portuges", "romanian", "russian", "scottish", diff --git a/src/text.C b/src/text.C index 5c61b1cc2e..49d1f03714 100644 --- a/src/text.C +++ b/src/text.C @@ -28,6 +28,7 @@ #include "lyxscreen.h" #include "minibuffer.h" #include "debug.h" +#include "lyxrc.h" #include "LyXView.h" using std::max; @@ -39,6 +40,7 @@ extern int mono_video; extern int reverse_video; extern int fast_selection; extern BufferView * current_view; +extern LyXRC * lyxrc; // ale070405 extern int bibitemMaxWidth(LyXFont const &); @@ -129,14 +131,152 @@ LyXParagraph::size_type LyXText::RowLast(Row const * row) const return row->next->pos - 1; } +LyXDirection LyXText::GetDocumentDirection() const { + return (lyxrc->rtl_support && parameters->language == "hebrew") + ? LYX_DIR_RIGHT_TO_LEFT : LYX_DIR_LEFT_TO_RIGHT; +} + +LyXDirection LyXText::GetParDirection(LyXParagraph * par) const { + if (!lyxrc->rtl_support || par->table) + return LYX_DIR_LEFT_TO_RIGHT; + + if (par->size() > 0) + return (GetFont(par, 0).direction() == LyXFont::RTL_DIR) + ? LYX_DIR_RIGHT_TO_LEFT : LYX_DIR_LEFT_TO_RIGHT; + else + return GetDocumentDirection(); +} + +LyXDirection LyXText::GetFontDirection(LyXFont const &font) const { + if (lyxrc->rtl_support + && font.direction() == LyXFont::RTL_DIR + && font.latex() != LyXFont::ON) + return LYX_DIR_RIGHT_TO_LEFT; + else + return LYX_DIR_LEFT_TO_RIGHT; +} + +LyXDirection LyXText::GetLetterDirection(LyXParagraph * par, + LyXParagraph::size_type pos) const { + if (!lyxrc->rtl_support) + return LYX_DIR_LEFT_TO_RIGHT; + + LyXDirection direction = GetFontDirection(GetFont(par, pos)); + if (par->IsLineSeparator(pos) && 0 < pos && pos < par->Last()-1 + && !par->IsLineSeparator(pos+1) + && !(par->table && par->IsNewline(pos+1)) + && ( GetFontDirection(GetFont(par, pos-1)) != direction || + GetFontDirection(GetFont(par, pos+1)) != direction) ) + return GetParDirection(par); + else + return direction; +} + +void LyXText::ComputeBidiTables(Row *row) const { + + if (!lyxrc->rtl_support) { + bidi_start = -1; + return; + } + LyXParagraph::size_type last = RowLast(row); + bidi_start = row->pos; + + if (bidi_start > last) { + bidi_start = -1; + return; + } + + if (last+2-bidi_start > + static_cast(log2vis_list.size()) ) { + LyXParagraph::size_type new_size = + (last+2-bidi_start < 500) ? 500 : 2*(last+2-bidi_start); + log2vis_list.resize(new_size); + vis2log_list.resize(new_size); + } + + vis2log_list[last+1-bidi_start] = -1; + log2vis_list[last+1-bidi_start] = -1; + + LyXParagraph::size_type main_body = BeginningOfMainBody(row->par); + if (main_body > 0 && row->pos < main_body-1 && main_body-1 <= last + && row->par->IsLineSeparator(main_body-1)) { + // This is needed in case there is a direction change in + // the label which is continued into the main body + if (GetParDirection(row->par) == LYX_DIR_LEFT_TO_RIGHT) { + ComputeBidiTablesFromTo(row,bidi_start,main_body-2,0); + log2vis_list[main_body-1-bidi_start] = main_body-1; + vis2log_list[main_body-1-bidi_start] = main_body-1; + if (main_body <= last) + ComputeBidiTablesFromTo(row,main_body,last,0); + } else { + ComputeBidiTablesFromTo(row,bidi_start,main_body-2,last-main_body+2); + log2vis_list[main_body-1-bidi_start] = last-main_body+1+bidi_start; + vis2log_list[last-main_body+1-bidi_start] = main_body-1; + if (main_body <= last) + ComputeBidiTablesFromTo(row,main_body,last,-main_body); + } + } else + ComputeBidiTablesFromTo(row,bidi_start,last,0); +} + + +void LyXText::ComputeBidiTablesFromTo(Row *row, + LyXParagraph::size_type from, + LyXParagraph::size_type to, + LyXParagraph::size_type offset) const { + + LyXParagraph::size_type vpos, old_lpos, stack[2]; + LyXDirection par_direction = GetParDirection(row->par); + LyXDirection direction = par_direction; + LyXParagraph::size_type lpos = from; + int level = 0; + + while (lpos <= to) { + if (GetLetterDirection(row->par, lpos) == direction) { + log2vis_list[lpos-bidi_start] = direction; + lpos++; + } else { + if (level == 0 || + (level == 1 && direction == LYX_DIR_RIGHT_TO_LEFT + && GetFont(row->par, lpos).direction() == LyXFont::RTL_DIR + && GetFont(row->par, lpos).latex() == LyXFont::ON ) ) { + // The last check is needed when the char is a space + stack[level++] = lpos; + } else { + old_lpos = stack[--level]; + log2vis_list[old_lpos-bidi_start] = + log2vis_list[lpos-bidi_start] = + (old_lpos-lpos)*direction; + lpos++; + } + direction = static_cast(-direction); + } + } + + while (level > 0) { + old_lpos = stack[--level]; + log2vis_list[old_lpos-bidi_start] = (old_lpos-(to+1))*direction; + direction = static_cast(-direction); + } -void LyXText::Draw(Row const * row, LyXParagraph::size_type & pos, + vpos = (par_direction == LYX_DIR_LEFT_TO_RIGHT) + ? from-1 : to+1; + vpos += offset; + for (lpos = from; lpos <= to; lpos++) { + vpos += log2vis_list[lpos-bidi_start]; + vis2log_list[vpos-bidi_start] = lpos; + log2vis_list[lpos-bidi_start] = vpos; + } +} + +void LyXText::Draw(Row const * row, LyXParagraph::size_type & vpos, LyXScreen & scr, int offset, float & x) { + LyXParagraph::size_type pos = vis2log(vpos); char c = row->par->GetChar(pos); if (IsNewlineChar(c)) { - ++pos; + ++vpos; // Draw end-of-line marker LyXFont font = GetFont(row->par, pos); @@ -144,15 +284,28 @@ void LyXText::Draw(Row const * row, LyXParagraph::size_type & pos, int wid = font.width('n'); int y = (offset + row->baseline); XPoint p[3]; - p[0].x = int(x + wid*0.375); p[0].y = int(y - 0.875*asc*0.75); - p[1].x = int(x); p[1].y = int(y - 0.500*asc*0.75); - p[2].x = int(x + wid*0.375); p[2].y = int(y - 0.125*asc*0.75); - scr.drawLines(::getGC(gc_new_line), p, 3); + if (GetLetterDirection(row->par, pos) == LYX_DIR_LEFT_TO_RIGHT) { + p[0].x = int(x + wid*0.375); p[0].y = int(y - 0.875*asc*0.75); + p[1].x = int(x); p[1].y = int(y - 0.500*asc*0.75); + p[2].x = int(x + wid*0.375); p[2].y = int(y - 0.125*asc*0.75); + scr.drawLines(::getGC(gc_new_line), p, 3); + + p[0].x = int(x); p[0].y = int(y - 0.500*asc*0.75); + p[1].x = int(x + wid); p[1].y = int(y - 0.500*asc*0.75); + p[2].x = int(x + wid); p[2].y = int(y - asc*0.75); + scr.drawLines(::getGC(gc_new_line), p, 3); + } else { + p[0].x = int(x + wid*0.625); p[0].y = int(y - 0.875*asc*0.75); + p[1].x = int(x + wid); p[1].y = int(y - 0.500*asc*0.75); + p[2].x = int(x + wid*0.625); p[2].y = int(y - 0.125*asc*0.75); + scr.drawLines(::getGC(gc_new_line), p, 3); - p[0].x = int(x); p[0].y = int(y - 0.500*asc*0.75); - p[1].x = int(x + wid); p[1].y = int(y - 0.500*asc*0.75); - p[2].x = int(x + wid); p[2].y = int(y - asc*0.75); - scr.drawLines(::getGC(gc_new_line), p, 3); + p[0].x = int(x + wid); p[0].y = int(y - 0.500*asc*0.75); + p[1].x = int(x); p[1].y = int(y - 0.500*asc*0.75); + p[2].x = int(x); p[2].y = int(y - asc*0.75); + scr.drawLines(::getGC(gc_new_line), p, 3); + } + x += wid; return; } @@ -210,13 +363,13 @@ void LyXText::Draw(Row const * row, LyXParagraph::size_type & pos, scr.drawLine(gc_foot, offset + row->baseline, int(tmpx), int(x - tmpx)); - ++pos; + ++vpos; return; } else if (c == LyXParagraph::META_INSET) { Inset * tmpinset = row->par->GetInset(pos); if (tmpinset) tmpinset->Draw(font, scr, offset + row->baseline, x); - ++pos; + ++vpos; return; } @@ -235,15 +388,16 @@ void LyXText::Draw(Row const * row, LyXParagraph::size_type & pos, // will only overflow if the machine is out of memory... static string textstring; textstring = c; - ++pos; + ++vpos; LyXParagraph::size_type last = RowLast(row); - while (pos <= last - && static_cast(c = row->par->GetChar(pos)) > ' ' + while (vpos <= last && + (pos = vis2log(vpos)) >= 0 + && static_cast(c = row->par->GetChar(pos)) > ' ' && font2 == GetFont(row->par, pos)) { textstring += c; - ++pos; + ++vpos; } float tmpx = x; @@ -604,7 +758,7 @@ bool LyXText::HitInTable(Row * row, int x) const if (!row->par->table) return false; PrepareToPrint(row, tmpx, fill_separator, - fill_hfill, fill_label_hfill); + fill_hfill, fill_label_hfill, false); return (x > tmpx && x < tmpx + row->par->table->WidthOfTable()); } @@ -767,8 +921,8 @@ int LyXText::Fill(Row const * row, int paper_width) const int left_margin = LabelEnd(row); // if the row ends with newline, this newline will not be relevant - if (last >= 0 && row->par->IsNewline(last)) - --last; + //if (last >= 0 && row->par->IsNewline(last)) + // --last; // if the row ends with a space, this space will not be relevant if (last >= 0 && row->par->IsLineSeparator(last)) @@ -790,17 +944,25 @@ int LyXText::Fill(Row const * row, int paper_width) const LyXParagraph::size_type main_body = BeginningOfMainBody(row->par); LyXParagraph::size_type i = row->pos; + while (i <= last) { - w += SingleWidth(row->par, i); - ++i; - if (i == main_body) { - w += GetFont(row->par, -2) - .stringWidth(layout.labelsep); + if (main_body > 0 && i == main_body) { + w += GetFont(row->par, -2). + stringWidth(layout.labelsep); if (row->par->IsLineSeparator(i - 1)) w -= SingleWidth(row->par, i - 1); if (w < left_margin) w = left_margin; } + w += SingleWidth(row->par, i); + ++i; + } + if (main_body > 0 && main_body > last) { + w += GetFont(row->par, -2).stringWidth(layout.labelsep); + if (last >= 0 && row->par->IsLineSeparator(last)) + w -= SingleWidth(row->par, last); + if (w < left_margin) + w = left_margin; } fill = paper_width - w - RightMargin(row); @@ -2380,16 +2542,16 @@ void LyXText::InsertChar(char c) status = LyXText::NEED_MORE_REFRESH; BreakAgainOneRow(row); - SetCursor(cursor.par, cursor.pos + 1); + + current_font = rawtmpfont; + real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos + 1, false); /* cursor MUST be in row now */ if (row->next && row->next->par == row->par) need_break_row = row->next; else need_break_row = 0; - - current_font = rawtmpfont; - real_current_font = realtmpfont; // check, wether the last characters font has changed. if (cursor.pos && cursor.pos == cursor.par->Last() @@ -2421,14 +2583,13 @@ void LyXText::InsertChar(char c) row = row->next; BreakAgainOneRow(row); } - SetCursor(cursor.par, cursor.pos + 1); + current_font = rawtmpfont; + real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos + 1, false); if (row->next && row->next->par == row->par) need_break_row = row->next; else - need_break_row = 0; - - current_font = rawtmpfont; - real_current_font = realtmpfont; + need_break_row = 0; } else { refresh_y = y; refresh_x = cursor.x; @@ -2442,9 +2603,9 @@ void LyXText::InsertChar(char c) else status = LyXText::NEED_MORE_REFRESH; - SetCursor(cursor.par, cursor.pos + 1); current_font = rawtmpfont; real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos + 1, false); } /* check, wether the last characters font has changed. */ @@ -2477,11 +2638,11 @@ void LyXText::charInserted() } } - void LyXText::PrepareToPrint(Row * row, float & x, float & fill_separator, float & fill_hfill, - float & fill_label_hfill) const + float & fill_label_hfill, + bool bidi) const { float nh, nlh, ns; @@ -2490,8 +2651,19 @@ void LyXText::PrepareToPrint(Row * row, float & x, fill_label_hfill = 0; fill_separator = 0; fill_label_hfill = 0; - - x = LeftMargin(row); + + LyXDirection direction = GetParDirection(row->par); + + if (direction == LYX_DIR_RIGHT_TO_LEFT) { + x = RightMargin(row); + if (row->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) { + LyXFont font(LyXFont::ALL_SANE); + font.setSize(LyXFont::SIZE_SMALL); + x += font.textWidth("Mwide-figM", 10); + } + } + else + x = LeftMargin(row); /* is there a manual margin with a manual label */ if (textclasslist.Style(parameters->textclass, @@ -2522,11 +2694,11 @@ void LyXText::PrepareToPrint(Row * row, float & x, else { /* is it block, flushleft or flushright? * set x how you need it */ - int align; - if (row->par->FirstPhysicalPar()->align == LYX_ALIGN_LAYOUT) - align = textclasslist.Style(parameters->textclass, row->par->GetLayout()).align; - else - align = row->par->FirstPhysicalPar()->align; + int align; + if (row->par->FirstPhysicalPar()->align == LYX_ALIGN_LAYOUT) + align = textclasslist.Style(parameters->textclass, row->par->GetLayout()).align; + else + align = row->par->FirstPhysicalPar()->align; /* center displayed insets */ if (row->par->GetChar(row->pos) == LyXParagraph::META_INSET @@ -2544,6 +2716,8 @@ void LyXText::PrepareToPrint(Row * row, float & x, && row->next->par->GetInset(row->next->pos)->display()) ) fill_separator = w / ns; + else if (direction == LYX_DIR_RIGHT_TO_LEFT) + x += w; break; case LYX_ALIGN_RIGHT: x += w; @@ -2553,8 +2727,32 @@ void LyXText::PrepareToPrint(Row * row, float & x, break; } } - } + if (!bidi) + return; + ComputeBidiTables(row); + if (direction == LYX_DIR_RIGHT_TO_LEFT) { + LyXParagraph::size_type main_body = + BeginningOfMainBody(row->par); + LyXParagraph::size_type last = RowLast(row); + + if (row->pos <= last + && !row->par->table + && last != vis2log(last) + && row->par->IsLineSeparator(last)) { + if (!(main_body > 0 && main_body-1 == last)) + x -= fill_separator+SingleWidth(row->par,last); + } else if (main_body > 0 && + (main_body-1 > last || + !row->par->IsLineSeparator(main_body-1))) { + LyXLayout const & layout = textclasslist.Style(parameters->textclass, + row->par->GetLayout()); + x += GetFont(row->par, -2).stringWidth(layout.labelsep); + if (main_body-1 <= last) + x += fill_label_hfill; + } + } +} /* important for the screen */ @@ -3203,9 +3401,9 @@ void LyXText::Backspace() refresh_y = y; refresh_row = tmprow; status = LyXText::NEED_MORE_REFRESH; - SetCursor(cursor.par, cursor.pos); current_font = rawtmpfont; real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos, false); // check, whether the last character's font has changed. rawtmpfont = cursor.par->GetFontSettings(cursor.par->Last() - 1); if (rawparfont != rawtmpfont) @@ -3234,8 +3432,9 @@ void LyXText::Backspace() status = LyXText::NEED_MORE_REFRESH; BreakAgainOneRow(row); - - SetCursor(cursor.par, cursor.pos); + current_font = rawtmpfont; + real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos, false); // cursor MUST be in row now if (row->next && row->next->par == row->par) @@ -3253,7 +3452,9 @@ void LyXText::Backspace() status = LyXText::NEED_MORE_REFRESH; refresh_y = y; refresh_row = row; - SetCursor(cursor.par, cursor.pos); + current_font = rawtmpfont; + real_current_font = realtmpfont; + SetCursor(cursor.par, cursor.pos, false); } } @@ -3280,24 +3481,21 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, Row * row_ptr, long y) { /* returns a printed row */ - LyXParagraph::size_type pos, pos_end; + LyXDirection direction = GetParDirection(row_ptr->par); + LyXParagraph::size_type vpos, pos, pos_end; float x, tmpx; int y_top, y_bottom; float fill_separator, fill_hfill, fill_label_hfill; LyXParagraph * par, * firstpar; - int left_margin; LyXFont font; int maxdesc; if (row_ptr->height <= 0) { lyxerr << "LYX_ERROR: row.height: " << row_ptr->height << endl; return; } - left_margin = LabelEnd(row_ptr); PrepareToPrint(row_ptr, x, fill_separator, fill_hfill, fill_label_hfill); - LyXParagraph::size_type main_body = - BeginningOfMainBody(row_ptr->par); /* initialize the pixmap */ scr.fillRectangle(gc_clear, @@ -3307,20 +3505,35 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, /* selection code */ if (sel_start_cursor.row == row_ptr && sel_end_cursor.row == row_ptr) { - scr.fillRectangle(gc_selection, sel_start_cursor.x, + if (sel_start_cursor.x < sel_end_cursor.x) + scr.fillRectangle(gc_selection, sel_start_cursor.x, offset, - sel_end_cursor.x - - sel_start_cursor.x, + sel_end_cursor.x - sel_start_cursor.x, + row_ptr->height); + else + scr.fillRectangle(gc_selection, sel_end_cursor.x, + offset, + sel_start_cursor.x - sel_end_cursor.x, row_ptr->height); } else if (sel_start_cursor.row == row_ptr) { + if (direction == LYX_DIR_LEFT_TO_RIGHT) scr.fillRectangle(gc_selection, sel_start_cursor.x, offset, paperwidth - sel_start_cursor.x, row_ptr->height); + else + scr.fillRectangle(gc_selection, 0, offset, + sel_start_cursor.x, row_ptr->height); } else if (sel_end_cursor.row == row_ptr) { + if (direction == LYX_DIR_LEFT_TO_RIGHT) scr.fillRectangle(gc_selection, 0, offset, sel_end_cursor.x, row_ptr->height); + else + scr.fillRectangle(gc_selection, sel_end_cursor.x, + offset, + paperwidth - sel_end_cursor.x, + row_ptr->height); } else if (y > sel_start_cursor.y && y < sel_end_cursor.y) { scr.fillRectangle(gc_selection, 0, offset, paperwidth, row_ptr->height); @@ -3418,14 +3631,13 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, paperwidth - LYX_PAPER_MARGIN, offset, offset + row_ptr->height); - - + } else { if (row_ptr->previous && row_ptr->previous->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) { LyXFont font(LyXFont::ALL_SANE); font.setSize(LyXFont::SIZE_FOOTNOTE); - + int box_x = LYX_PAPER_MARGIN; box_x += font.textWidth(" wide-tab ", 10); @@ -3522,19 +3734,31 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, * an extra row and has a pagebreak at the top. */ maxdesc = int(font.maxDescent() * layout.spacing.getValue() * parameters->spacing.getValue()) + int(layout.parsep) * DefaultHeight(); + if (direction == LYX_DIR_RIGHT_TO_LEFT) + tmpx = paperwidth - LeftMargin(row_ptr) - + font.stringWidth(tmpstring); scr.drawString(font, tmpstring, offset + row_ptr->baseline - row_ptr->ascent_of_text - maxdesc, - int(x)); + int(tmpx)); } } else { - x -= font.stringWidth( layout.labelsep); - x -= font.stringWidth( tmpstring); + if (direction == LYX_DIR_LEFT_TO_RIGHT) + tmpx = x - font.stringWidth(layout.labelsep) + - font.stringWidth(tmpstring); + else { + tmpx = paperwidth - LeftMargin(row_ptr) + + font.stringWidth(layout.labelsep); + if (row_ptr->par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) { + LyXFont font(LyXFont::ALL_SANE); + font.setSize(LyXFont::SIZE_SMALL); + tmpx += font.textWidth("Mwide-figM", 10); + } + } /* draw it! */ scr.drawString(font, tmpstring, - offset + row_ptr->baseline, int(x)); + offset + row_ptr->baseline, int(tmpx)); } - x = tmpx; } /* the labels at the top of an environment. More or less for bibliography */ } else if (layout.labeltype == LABEL_TOP_ENVIRONMENT || @@ -3548,29 +3772,35 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, maxdesc = int(font.maxDescent() * layout.spacing.getValue() * parameters->spacing.getValue() + (layout.labelbottomsep * DefaultHeight())); - int top_label_x = int(x); + tmpx = x; if (layout.labeltype == LABEL_CENTERED_TOP_ENVIRONMENT){ - top_label_x = int(x + (paperwidth - RightMargin(row_ptr) - x) / 2); - top_label_x -= (font.stringWidth( tmpstring)/2); - } - + tmpx = ( ((direction == LYX_DIR_LEFT_TO_RIGHT) + ? x : LeftMargin(row_ptr) ) + + paperwidth - RightMargin(row_ptr) ) / 2; + tmpx -= (font.stringWidth(tmpstring)/2); + } else if (direction == LYX_DIR_RIGHT_TO_LEFT) + tmpx = paperwidth - LeftMargin(row_ptr) - + font.stringWidth(tmpstring); + scr.drawString(font, tmpstring, offset + row_ptr->baseline - row_ptr->ascent_of_text - maxdesc, - top_label_x); + int(tmpx)); } } } if (layout.labeltype == LABEL_BIBLIO) { // ale970302 if (row_ptr->par->bibkey) { - tmpx = x; - x -= font.stringWidth(layout.labelsep); font = GetFont(row_ptr->par, -1); - x -= row_ptr->par->bibkey->Width(font); + if (direction == LYX_DIR_LEFT_TO_RIGHT) + tmpx = x - font.stringWidth(layout.labelsep) + - row_ptr->par->bibkey->Width(font); + else + tmpx = paperwidth - LeftMargin(row_ptr) + + font.stringWidth(layout.labelsep); row_ptr->par->bibkey->Draw(font, scr, offset + row_ptr->baseline, - x); - x = tmpx; + tmpx); } } } @@ -3622,7 +3852,7 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, /* draw the text in the pixmap */ pos_end = RowLast(row_ptr); - pos = row_ptr->pos; + vpos = row_ptr->pos; /* table stuff -- begin*/ if (row_ptr->par->table) { bool on_off; @@ -3630,7 +3860,8 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, float x_old = x; x += row_ptr->par->table->GetBeginningOfTextInCell(cell); - while (pos <= pos_end) { + while (vpos <= pos_end) { + pos = vis2log(vpos); if (row_ptr->par->IsNewline(pos)) { x = x_old + row_ptr->par->table->WidthOfColumn(cell); @@ -3668,7 +3899,7 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, x += row_ptr->par->table->GetBeginningOfTextInCell(cell); if (row_ptr->par->table->IsFirstCell(cell)) --cell; // little hack, sorry - ++pos; + ++vpos; } else if (row_ptr->par->IsHfill(pos)) { x += 1; @@ -3676,7 +3907,7 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, offset + row_ptr->baseline - DefaultHeight()/2, offset + row_ptr->baseline); x += 2; - ++pos; + ++vpos; } else { if (row_ptr->par->IsSeparator(pos)) { tmpx = x; @@ -3705,9 +3936,9 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, int(x - tmpx)); } } - ++pos; + ++vpos; } else - Draw(row_ptr, pos, scr, offset, x); + Draw(row_ptr, vpos, scr, offset, x); } } @@ -3747,9 +3978,21 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, } } else { /* table stuff -- end*/ - - while (pos <= pos_end) { - + LyXParagraph::size_type main_body = + BeginningOfMainBody(row_ptr->par); + if (main_body > 0 && + (main_body-1 > pos_end || + !row_ptr->par->IsLineSeparator(main_body-1))) + main_body = 0; + + while (vpos <= pos_end) { + pos = vis2log(vpos); + if (main_body > 0 && pos == main_body-1) { + x += fill_label_hfill + + GetFont(row_ptr->par, -2).stringWidth(layout.labelsep) + - SingleWidth(row_ptr->par, main_body-1); + } + if (row_ptr->par->IsHfill(pos)) { x += 1; scr.drawVerticalLine(gc_fill, int(x), @@ -3775,7 +4018,7 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, offset + row_ptr->baseline); } x += 2; - ++pos; + ++vpos; } else { if (row_ptr->par->IsSeparator(pos)) { tmpx = x; @@ -3806,17 +4049,9 @@ void LyXText::GetVisibleRow(LyXScreen & scr, int offset, int(x - tmpx)); } } - ++pos; + ++vpos; } else - Draw(row_ptr, pos, scr, offset, x); - } - if (pos == main_body) { - x += GetFont(row_ptr->par, -2).stringWidth( - layout.labelsep); - if (row_ptr->par->IsLineSeparator(pos - 1)) - x-= SingleWidth(row_ptr->par, pos - 1); - if (x < left_margin) - x = left_margin; + Draw(row_ptr, vpos, scr, offset, x); } } } @@ -3863,28 +4098,27 @@ int LyXText::GetColumnNearX(Row * row, int & x) const float tmpx = 0.0; float fill_separator, fill_hfill, fill_label_hfill; - int left_margin = LabelEnd(row); PrepareToPrint(row, tmpx, fill_separator, fill_hfill, fill_label_hfill); - int main_body = BeginningOfMainBody(row->par); - - int c = row->pos; - int last = RowLast(row); - if (row->par->IsNewline(last)) - --last; - + LyXDirection direction = GetParDirection(row->par); + LyXParagraph::size_type vc = row->pos; + LyXParagraph::size_type last = RowLast(row); + LyXParagraph::size_type c; + LyXLayout const & layout = textclasslist.Style(parameters->textclass, row->par->GetLayout()); /* table stuff -- begin */ if (row->par->table) { - if (!row->next || row->next->par != row->par) - last = RowLast(row); /* the last row doesn't need a newline at the end*/ + if (row->next && row->next->par == row->par //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; tmpx += row->par->table->GetBeginningOfTextInCell(cell); - while (c <= last + while (vc <= last + && (c = vis2log(vc)) >= 0 && tmpx + (SingleWidth(row->par, c)/2) <= x && !ready){ if (row->par->IsNewline(c)) { @@ -3893,26 +4127,32 @@ int LyXText::GetColumnNearX(Row * row, int & x) const x_old = tmpx; ++cell; tmpx += row->par->table->GetBeginningOfTextInCell(cell); - ++c; + ++vc; } else ready = true; } else { tmpx += SingleWidth(row->par, c); - ++c; + ++vc; } } - } else + } else { /* table stuff -- end*/ - - while (c <= last - && tmpx + (SingleWidth(row->par, c)/2) <= x) { - - if (c && c == main_body - && !row->par->IsLineSeparator(c - 1)) { - tmpx += GetFont(row->par, -2) - .stringWidth(layout.labelsep); - if (tmpx < left_margin) - tmpx = left_margin; + LyXParagraph::size_type main_body = BeginningOfMainBody(row->par); + float last_tmpx = tmpx; + + if (main_body > 0 && + (main_body-1 > last || + !row->par->IsLineSeparator(main_body-1))) + main_body = 0; + + while (vc <= last && tmpx <= x) { + c = vis2log(vc); + last_tmpx = tmpx; + if (main_body > 0 && c == main_body-1) { + tmpx += fill_label_hfill + + GetFont(row->par, -2).stringWidth(layout.labelsep); + if (row->par->IsLineSeparator(main_body-1)) + tmpx -= SingleWidth(row->par, main_body-1); } tmpx += SingleWidth(row->par, c); @@ -3926,25 +4166,54 @@ int LyXText::GetColumnNearX(Row * row, int & x) const && row->par->IsSeparator(c)) { tmpx+= fill_separator; } - ++c; - if (c == main_body - && row->par->IsLineSeparator(c - 1)) { - tmpx += GetFont(row->par, -2) - .stringWidth(layout.labelsep); - tmpx-= SingleWidth(row->par, c - 1); - if (tmpx < left_margin) - tmpx = left_margin; - } + ++vc; } + + if (vc > row->pos && (tmpx+last_tmpx)/2 > x) { + vc--; + tmpx = last_tmpx; + } + } /* make sure that a last space in a row doesnt count */ - if (c > 0 && c >= last - && row->par->IsLineSeparator(c - 1) - && !(!row->next || row->next->par != row->par)) { - tmpx -= SingleWidth(row->par, c - 1); - tmpx -= fill_separator; + if (row->pos <= last + && !(!row->next || row->next->par != row->par)) + if (direction == LYX_DIR_LEFT_TO_RIGHT && vc > last + && row->par->IsLineSeparator(vis2log(last)) ) { + vc = last; + tmpx -= fill_separator+SingleWidth(row->par, vis2log(last)); + } else if (direction == LYX_DIR_RIGHT_TO_LEFT + && vc == row->pos + && row->par->IsLineSeparator(vis2log(row->pos)) ) { + vc = row->pos+1; + tmpx += fill_separator+SingleWidth(row->par, vis2log(row->pos)); + } + + if (row->pos > last) // Row is empty? + c = row->pos; + else if (vc <= last) { + c = vis2log(vc); + LyXDirection direction = GetLetterDirection(row->par , c); + if (vc > row->pos && row->par->IsLineSeparator(c) + && GetLetterDirection(row->par , vis2log(vc-1)) != direction) + c = vis2log(vc-1); + if (direction == LYX_DIR_RIGHT_TO_LEFT) + ++c; + } else { + c = vis2log(last)+1; + if (GetLetterDirection(row->par, c-1) == LYX_DIR_RIGHT_TO_LEFT) + --c; } - c-= row->pos; - + + if (!row->par->table && row->pos <= last && c > last + && row->par->IsNewline(last)) { + if (GetLetterDirection(row->par,last) == LYX_DIR_LEFT_TO_RIGHT) + tmpx -= SingleWidth(row->par, last); + else + tmpx += SingleWidth(row->par, last); + c = last; + } + + c-= row->pos; x = int(tmpx); return c; } diff --git a/src/text2.C b/src/text2.C index 8903d40b85..bfcc2827e9 100644 --- a/src/text2.C +++ b/src/text2.C @@ -936,8 +936,16 @@ void LyXText::SetSelection() last_sel_cursor = cursor; // and now the whole selection - - if (sel_cursor.y < cursor.y || + + if (sel_cursor.par == cursor.par) + if (sel_cursor.pos < cursor.pos) { + sel_end_cursor = cursor; + sel_start_cursor = sel_cursor; + } else { + sel_end_cursor = sel_cursor; + sel_start_cursor = cursor; + } + else if (sel_cursor.y < cursor.y || (sel_cursor.y == cursor.y && sel_cursor.x < cursor.x)) { sel_end_cursor = cursor; sel_start_cursor = sel_cursor; @@ -1596,35 +1604,43 @@ void LyXText::SetCounter(LyXParagraph * par) const par->incCounter(i + par->enumdepth); char * s = new char[25]; int number = par->getCounter(i + par->enumdepth); + + static const char *roman[20] = { + "i", "ii", "iii", "iv", "v", + "vi", "vii", "viii", "ix", "x", + "xi", "xii", "xiii", "xiv", "xv", + "xvi", "xvii", "xviii", "xix", "xx" + }; + static const char hebrew[22] = { + 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', + 'é', 'ë', 'ì', 'î', 'ð', 'ñ', 'ò', 'ô', 'ö', + '÷', 'ø', 'ù', 'ú' + }; + switch (par->enumdepth) { case 1: - sprintf(s, "(%c)", (number % 27) + 'a' - 1); + if (GetParDirection(par) == LYX_DIR_LEFT_TO_RIGHT) + sprintf(s, "(%c)", ((number-1) % 26) + 'a'); + else + sprintf(s, "(%c)", hebrew[(number-1) % 22]); break; case 2: - switch (number) { - case 1: sprintf(s, "i."); break; - case 2: sprintf(s, "ii."); break; - case 3: sprintf(s, "iii."); break; - case 4: sprintf(s, "iv."); break; - case 5: sprintf(s, "v."); break; - case 6: sprintf(s, "vi."); break; - case 7: sprintf(s, "vii."); break; - case 8: sprintf(s, "viii."); break; - case 9: sprintf(s, "ix."); break; - case 10: sprintf(s, "x."); break; - case 11: sprintf(s, "xi."); break; - case 12: sprintf(s, "xii."); break; - case 13: sprintf(s, "xiii."); break; - default: - sprintf(s, "\\roman{%d}.", number); - break; - } + if (GetParDirection(par) == LYX_DIR_LEFT_TO_RIGHT) + sprintf(s, "%s.", roman[(number-1) % 20]); + else + sprintf(s, ".%s", roman[(number-1) % 20]); break; case 3: - sprintf(s, "%c.", (number % 27) + 'A' - 1); + if (GetParDirection(par) == LYX_DIR_LEFT_TO_RIGHT) + sprintf(s, "%c.", ((number-1) % 26) + 'A'); + else + sprintf(s, ".%c", ((number-1) % 26) + 'A'); break; default: - sprintf(s, "%d.", number); + if (GetParDirection(par) == LYX_DIR_LEFT_TO_RIGHT) + sprintf(s, "%d.", number); + else + sprintf(s, ".%d", number); break; } par->labelstring = s; @@ -1653,18 +1669,31 @@ void LyXText::SetCounter(LyXParagraph * par) const if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE && (par->footnotekind == LyXParagraph::FIG || par->footnotekind == LyXParagraph::WIDE_FIG)) - s = "Figure:"; + if (GetParDirection(par) == LYX_DIR_LEFT_TO_RIGHT) + s = "Figure:"; + else + s = ":øåéà"; else if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE && (par->footnotekind == LyXParagraph::TAB || par->footnotekind == LyXParagraph::WIDE_TAB)) - s = "Table:"; + if (GetParDirection(par) == LYX_DIR_LEFT_TO_RIGHT) + s = "Table:"; + else + s = ":äìáè"; else if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE && par->footnotekind == LyXParagraph::ALGORITHM) - s = "Algorithm:"; + if (GetParDirection(par) == LYX_DIR_LEFT_TO_RIGHT) + s = "Algorithm:"; + else + s = ":íúéøåâìà"; else { /* par->SetLayout(0); s = layout->labelstring; */ - s = "Senseless: "; + if (GetParDirection(par) == LYX_DIR_LEFT_TO_RIGHT) + s = "Senseless: "; + else + s = " :úåòîùî øñç"; + } } par->labelstring = s; @@ -2882,22 +2911,22 @@ int LyXText::UpdateInset(Inset * inset) void LyXText::SetCursor(LyXParagraph * par, - LyXParagraph::size_type pos) const + LyXParagraph::size_type pos, bool setfont) const { LyXCursor old_cursor = cursor; - SetCursorIntern(par, pos); + SetCursorIntern(par, pos, setfont); DeleteEmptyParagraphMechanism(old_cursor); } void LyXText::SetCursorIntern(LyXParagraph * par, - LyXParagraph::size_type pos) const + LyXParagraph::size_type pos, bool setfont) const { long y; Row * row; - int left_margin; LyXParagraph * tmppar; - + LyXParagraph::size_type vpos,cursor_vpos; + // correct the cursor position if impossible if (pos > par->Last()){ tmppar = par->ParFromPos(pos); @@ -2923,6 +2952,25 @@ void LyXText::SetCursorIntern(LyXParagraph * par, cursor.par = par; cursor.pos = pos; + if (setfont) + 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); + if (pos == 0 && par->size() == 0 + && GetDocumentDirection() == LYX_DIR_RIGHT_TO_LEFT) { + current_font.setDirection(LyXFont::RTL_DIR); + real_current_font.setDirection(LyXFont::RTL_DIR); + } + } + /* get the cursor y position in text */ row = GetRow(par, pos, y); /* y is now the beginning of the cursor row */ @@ -2931,19 +2979,33 @@ void LyXText::SetCursorIntern(LyXParagraph * par, cursor.y = y; /* now get the cursors x position */ - float x; float fill_separator, fill_hfill, fill_label_hfill; - left_margin = LabelEnd(row); PrepareToPrint(row, x, fill_separator, fill_hfill, fill_label_hfill); - LyXParagraph::size_type main_body = - BeginningOfMainBody(row->par); + + LyXParagraph::size_type last = RowLast(row); + if (row->pos > last) + cursor_vpos = 0; + else if (pos <= last ) { + LyXDirection letter_direction = GetLetterDirection(row->par, pos); + LyXDirection font_direction = GetFontDirection(real_current_font); + if (letter_direction == font_direction || pos == 0) + cursor_vpos = (letter_direction == LYX_DIR_LEFT_TO_RIGHT) + ? log2vis(pos) : log2vis(pos)+1; + else + cursor_vpos = (font_direction == LYX_DIR_LEFT_TO_RIGHT) + ? log2vis(pos-1)+1 : log2vis(pos-1); + } else + cursor_vpos = (GetLetterDirection(row->par, last) == LYX_DIR_LEFT_TO_RIGHT) + ? log2vis(last)+1 : log2vis(last); + /* table stuff -- begin*/ if (row->par->table) { int cell = NumberOfCell(row->par, row->pos); float x_old = x; x += row->par->table->GetBeginningOfTextInCell(cell); - for (pos = row->pos; pos < cursor.pos; ++pos) { + for (vpos = row->pos; vpos < cursor_vpos; ++vpos) { + pos = vis2log(vpos); if (row->par->IsNewline(pos)) { x = x_old + row->par->table->WidthOfColumn(cell); x_old = x; @@ -2953,16 +3015,23 @@ void LyXText::SetCursorIntern(LyXParagraph * par, x += SingleWidth(row->par, pos); } } - } else + } else { /* table stuff -- end*/ - - for (pos = row->pos; pos < cursor.pos; ++pos) { - if (pos && pos == main_body - && !row->par->IsLineSeparator(pos - 1)) { - x += GetFont(row->par, -2).stringWidth( + LyXParagraph::size_type main_body = + BeginningOfMainBody(row->par); + if (main_body > 0 && + (main_body-1 > last || + !row->par->IsLineSeparator(main_body-1))) + main_body = 0; + + for (vpos = row->pos; vpos < cursor_vpos; ++vpos) { + pos = vis2log(vpos); + if (main_body > 0 && pos == main_body-1) { + x += fill_label_hfill + + GetFont(row->par, -2).stringWidth( textclasslist.Style(parameters->textclass, row->par->GetLayout()).labelsep); - if (x < left_margin) - x = left_margin; + if (row->par->IsLineSeparator(main_body-1)) + x -= SingleWidth(row->par, main_body-1); } x += SingleWidth(row->par, pos); @@ -2975,34 +3044,13 @@ void LyXText::SetCursorIntern(LyXParagraph * par, else if (pos >= main_body && row->par->IsSeparator(pos)) { x+= fill_separator; } - - if (pos + 1 == main_body - && row->par->IsLineSeparator(pos)) { - x += GetFont(row->par, -2).stringWidth( - textclasslist.Style(parameters->textclass, row->par->GetLayout()).labelsep); - if (row->par->IsLineSeparator(pos)) - x -= SingleWidth(row->par, pos); - if (x < left_margin) - x = left_margin; - } } + } cursor.x = int(x); cursor.x_fix = cursor.x; 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)) - )) { - 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); - } } @@ -3028,6 +3076,7 @@ void LyXText::SetCursorFromCoordinates(int x, long y) const || 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);