]> git.lyx.org Git - lyx.git/blobdiff - src/Paragraph.cpp
Fix text direction of references with XeTeX/bidi
[lyx.git] / src / Paragraph.cpp
index cdd6b23b943986aba2c3ad4f14db95702e24d793..311e9528070f7cf0dfe23ade396091b36d741dac 100644 (file)
@@ -1005,7 +1005,7 @@ void Paragraph::Private::latexInset(BufferParams const & bparams,
        bool close = false;
        odocstream::pos_type const len = os.os().tellp();
 
-       if (inset->forceLTR()
+       if (inset->forceLTR(runparams)
            && running_font.isRightToLeft()
            // ERT is an exception, it should be output with no
            // decorations at all
@@ -1351,7 +1351,8 @@ void Paragraph::Private::validate(LaTeXFeatures & features) const
                otexstringstream os;
                os << layout_->preamble();
                size_t const length = os.length();
-               TeXOnePar(buf, buf.text(), buf.getParFromID(owner_->id()).pit(), os,
+               TeXOnePar(buf, *inset_owner_->getText(int(buf.getParFromID(owner_->id()).idx())),
+                         buf.getParFromID(owner_->id()).pit(), os,
                          features.runparams(), string(), 0, -1, true);
                if (os.length() > length)
                        features.addPreambleSnippet(os.release(), true);
@@ -1646,6 +1647,8 @@ void Paragraph::validate(LaTeXFeatures & features) const
        d->validate(features);
        bool fragile = features.runparams().moving_arg;
        fragile |= layout().needprotect;
+       if (inInset().getLayout().isNeedProtect())
+               fragile = true;
        if (needsCProtection(fragile))
                features.require("cprotect");
 }
@@ -1857,8 +1860,9 @@ char_type Paragraph::getUChar(BufferParams const & bparams,
        char_type c = d->text_[pos];
 
        // Return unchanged character in LTR languages
-       // or if we use poylglossia/bidi.
-       if (rp.use_polyglossia || !getFontSettings(bparams, pos).isRightToLeft())
+       // or if we use poylglossia/bidi (XeTeX).
+       if (rp.useBidiPackage()
+           || !getFontSettings(bparams, pos).isRightToLeft())
                return c;
 
        // Without polyglossia/bidi, we need to account for some special cases.
@@ -1877,7 +1881,8 @@ char_type Paragraph::getUChar(BufferParams const & bparams,
        char_type uc = c;
 
        // 1. In the following languages, parentheses need to be reversed.
-       bool const reverseparens = lang == "hebrew";
+       //    Also with polyglodia/luabidi
+       bool const reverseparens = (lang == "hebrew" || rp.use_polyglossia);
 
        // 2. In the following languages, brackets don't need to be reversed.
        bool const reversebrackets = lang != "arabic_arabtex"
@@ -1980,15 +1985,29 @@ depth_type Paragraph::getMaxDepthAfter() const
 }
 
 
-LyXAlignment Paragraph::getAlign() const
+LyXAlignment Paragraph::getAlign(BufferParams const & bparams) const
 {
        if (d->params_.align() == LYX_ALIGN_LAYOUT)
-               return d->layout_->align;
+               return getDefaultAlign(bparams);
        else
                return d->params_.align();
 }
 
 
+LyXAlignment Paragraph::getDefaultAlign(BufferParams const & bparams) const
+{
+       LyXAlignment res = layout().align;
+       if (isRTL(bparams)) {
+               // Swap sides
+               if (res == LYX_ALIGN_LEFT)
+                       res = LYX_ALIGN_RIGHT;
+               else if  (res == LYX_ALIGN_RIGHT)
+                       res = LYX_ALIGN_LEFT;
+       }
+       return res;
+}
+
+
 docstring const & Paragraph::labelString() const
 {
        return d->params_.labelString();
@@ -2228,8 +2247,9 @@ int Paragraph::Private::startTeXParParams(BufferParams const & bparams,
        InsetCode code = ownerCode();
        bool const lastpar = runparams.isLastPar;
        // RTL in classic (PDF)LaTeX (without the Bidi package)
+       // Luabibdi (used by LuaTeX) behaves like classic
        bool const rtl_classic = owner_->getParLanguage(bparams)->rightToLeft()
-               && !runparams.use_polyglossia;
+               && !runparams.useBidiPackage();
 
        switch (curAlign) {
        case LYX_ALIGN_NONE:
@@ -2291,8 +2311,9 @@ bool Paragraph::Private::endTeXParParams(BufferParams const & bparams,
        InsetCode code = ownerCode();
        bool const lastpar = runparams.isLastPar;
        // RTL in classic (PDF)LaTeX (without the Bidi package)
+       // Luabibdi (used by LuaTeX) behaves like classic
        bool const rtl_classic = owner_->getParLanguage(bparams)->rightToLeft()
-               && !runparams.use_polyglossia;
+               && !runparams.useBidiPackage();
 
        switch (curAlign) {
        case LYX_ALIGN_NONE:
@@ -2539,23 +2560,17 @@ void Paragraph::latex(BufferParams const & bparams,
                        open_font = false;
                }
 
-               string const running_lang = runparams.use_polyglossia ?
-                       running_font.language()->polyglossia() : running_font.language()->babel();
-               // close babel's font environment before opening CJK.
-               string const lang_end_command = runparams.use_polyglossia ?
-                       "\\end{$$lang}" : lyxrc.language_command_end;
-               bool const using_begin_end = runparams.use_polyglossia ||
-                                               !lang_end_command.empty();
-               if (!running_lang.empty() &&
-                   (!using_begin_end || running_lang == openLanguageName()) &&
-                   current_font.language()->encoding()->package() == Encoding::CJK) {
-                               string end_tag = subst(lang_end_command,
-                                                       "$$lang",
-                                                       running_lang);
-                               os << from_ascii(end_tag);
-                               column += end_tag.length();
-                               if (using_begin_end)
-                                       popLanguageName();
+               // if necessary, close language environment before opening CJK
+               string const running_lang = running_font.language()->babel();
+               string const lang_end_command = lyxrc.language_command_end;
+               if (!lang_end_command.empty() && !bparams.useNonTeXFonts
+                       && !running_lang.empty()
+                       && running_lang == openLanguageName()
+                       && current_font.language()->encoding()->package() == Encoding::CJK) {
+                       string end_tag = subst(lang_end_command, "$$lang", running_lang);
+                       os << from_ascii(end_tag);
+                       column += end_tag.length();
+                       popLanguageName();
                }
 
                // Switch file encoding if necessary (and allowed)
@@ -2703,7 +2718,7 @@ void Paragraph::latex(BufferParams const & bparams,
                                }
                        }
                        try {
-                               d->latexSpecialChar(os, bparams, rp, running_font, 
+                               d->latexSpecialChar(os, bparams, rp, running_font,
                                                                        alien_script, style, i, end_pos, column);
                        } catch (EncodingException & e) {
                                if (runparams.dryrun) {
@@ -2737,7 +2752,7 @@ void Paragraph::latex(BufferParams const & bparams,
        if (!alien_script.empty()) {
                os << "}";
                alien_script.clear();
-       }       
+       }
 
        // If we have an open font definition, we have to close it
        if (open_font) {
@@ -3023,7 +3038,7 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
 
        FontShape  curr_fs   = INHERIT_SHAPE;
        FontFamily curr_fam  = INHERIT_FAMILY;
-       FontSize   curr_size = FONT_SIZE_INHERIT;
+       FontSize   curr_size = INHERIT_SIZE;
 
        string const default_family =
                buf.masterBuffer()->params().fonts_default_family;
@@ -3188,41 +3203,41 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
                if (old_size != curr_size) {
                        if (size_flag) {
                                switch (old_size) {
-                               case FONT_SIZE_TINY:
+                               case TINY_SIZE:
                                        tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_TINY));
                                        break;
-                               case FONT_SIZE_SCRIPT:
+                               case SCRIPT_SIZE:
                                        tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_SCRIPT));
                                        break;
-                               case FONT_SIZE_FOOTNOTE:
+                               case FOOTNOTE_SIZE:
                                        tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_FOOTNOTE));
                                        break;
-                               case FONT_SIZE_SMALL:
+                               case SMALL_SIZE:
                                        tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_SMALL));
                                        break;
-                               case FONT_SIZE_LARGE:
+                               case LARGE_SIZE:
                                        tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_LARGE));
                                        break;
-                               case FONT_SIZE_LARGER:
+                               case LARGER_SIZE:
                                        tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_LARGER));
                                        break;
-                               case FONT_SIZE_LARGEST:
+                               case LARGEST_SIZE:
                                        tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_LARGEST));
                                        break;
-                               case FONT_SIZE_HUGE:
+                               case HUGE_SIZE:
                                        tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_HUGE));
                                        break;
-                               case FONT_SIZE_HUGER:
+                               case HUGER_SIZE:
                                        tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_HUGER));
                                        break;
-                               case FONT_SIZE_INCREASE:
+                               case INCREASE_SIZE:
                                        tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_INCREASE));
                                        break;
-                               case FONT_SIZE_DECREASE:
+                               case DECREASE_SIZE:
                                        tagsToClose.push_back(html::EndFontTag(html::FT_SIZE_DECREASE));
                                        break;
-                               case FONT_SIZE_INHERIT:
-                               case FONT_SIZE_NORMAL:
+                               case INHERIT_SIZE:
+                               case NORMAL_SIZE:
                                        break;
                                default:
                                        // the other tags are for internal use
@@ -3232,52 +3247,52 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
                                size_flag = false;
                        }
                        switch (curr_size) {
-                       case FONT_SIZE_TINY:
+                       case TINY_SIZE:
                                tagsToOpen.push_back(html::FontTag(html::FT_SIZE_TINY));
                                size_flag = true;
                                break;
-                       case FONT_SIZE_SCRIPT:
+                       case SCRIPT_SIZE:
                                tagsToOpen.push_back(html::FontTag(html::FT_SIZE_SCRIPT));
                                size_flag = true;
                                break;
-                       case FONT_SIZE_FOOTNOTE:
+                       case FOOTNOTE_SIZE:
                                tagsToOpen.push_back(html::FontTag(html::FT_SIZE_FOOTNOTE));
                                size_flag = true;
                                break;
-                       case FONT_SIZE_SMALL:
+                       case SMALL_SIZE:
                                tagsToOpen.push_back(html::FontTag(html::FT_SIZE_SMALL));
                                size_flag = true;
                                break;
-                       case FONT_SIZE_LARGE:
+                       case LARGE_SIZE:
                                tagsToOpen.push_back(html::FontTag(html::FT_SIZE_LARGE));
                                size_flag = true;
                                break;
-                       case FONT_SIZE_LARGER:
+                       case LARGER_SIZE:
                                tagsToOpen.push_back(html::FontTag(html::FT_SIZE_LARGER));
                                size_flag = true;
                                break;
-                       case FONT_SIZE_LARGEST:
+                       case LARGEST_SIZE:
                                tagsToOpen.push_back(html::FontTag(html::FT_SIZE_LARGEST));
                                size_flag = true;
                                break;
-                       case FONT_SIZE_HUGE:
+                       case HUGE_SIZE:
                                tagsToOpen.push_back(html::FontTag(html::FT_SIZE_HUGE));
                                size_flag = true;
                                break;
-                       case FONT_SIZE_HUGER:
+                       case HUGER_SIZE:
                                tagsToOpen.push_back(html::FontTag(html::FT_SIZE_HUGER));
                                size_flag = true;
                                break;
-                       case FONT_SIZE_INCREASE:
+                       case INCREASE_SIZE:
                                tagsToOpen.push_back(html::FontTag(html::FT_SIZE_INCREASE));
                                size_flag = true;
                                break;
-                       case FONT_SIZE_DECREASE:
+                       case DECREASE_SIZE:
                                tagsToOpen.push_back(html::FontTag(html::FT_SIZE_DECREASE));
                                size_flag = true;
                                break;
-                       case FONT_SIZE_NORMAL:
-                       case FONT_SIZE_INHERIT:
+                       case NORMAL_SIZE:
+                       case INHERIT_SIZE:
                                break;
                        default:
                                // the other tags are for internal use
@@ -3434,10 +3449,31 @@ bool Paragraph::needsCProtection(bool const fragile) const
        }
 
        // now check whether we have insets that need cprotection
-       pos_type size = d->text_.size();
-       for (pos_type i = 0; i < size; ++i)
-               if (isInset(i) && getInset(i)->needsCProtection(maintext, fragile))
+       pos_type size = pos_type(d->text_.size());
+       for (pos_type i = 0; i < size; ++i) {
+               if (!isInset(i))
+                       continue;
+               Inset const * ins = getInset(i);
+               if (ins->needsCProtection(maintext, fragile))
+                       return true;
+               if (ins->getLayout().latextype() == InsetLayout::ENVIRONMENT)
+                       // Environments need cprotection regardless the content
+                       return true;
+               // Now check math environments
+               InsetMath const * im = getInset(i)->asInsetMath();
+               if (!im || im->cell(0).empty())
+                       continue;
+               switch(im->cell(0)[0]->lyxCode()) {
+               case MATH_AMSARRAY_CODE:
+               case MATH_SUBSTACK_CODE:
+               case MATH_ENV_CODE:
+               case MATH_XYMATRIX_CODE:
+                       // these need cprotection
                        return true;
+               default:
+                       break;
+               }
+       }
 
        return false;
 }
@@ -3668,32 +3704,43 @@ bool Paragraph::allowEmpty() const
 
 bool Paragraph::brokenBiblio() const
 {
-       // there is a problem if there is no bibitem at position 0 or
-       // if there is another bibitem in the paragraph.
-       return d->layout_->labeltype == LABEL_BIBLIO
+       // There is a problem if there is no bibitem at position 0 in
+       // paragraphs that need one, if there is another bibitem in the
+       // paragraph or if this paragraph is not supposed to have
+       // a bibitem inset at all.
+       return ((d->layout_->labeltype == LABEL_BIBLIO
                && (d->insetlist_.find(BIBITEM_CODE) != 0
-                   || d->insetlist_.find(BIBITEM_CODE, 1) > 0);
+                   || d->insetlist_.find(BIBITEM_CODE, 1) > 0))
+               || (d->layout_->labeltype != LABEL_BIBLIO
+                   && d->insetlist_.find(BIBITEM_CODE) != -1));
 }
 
 
 int Paragraph::fixBiblio(Buffer const & buffer)
 {
-       // FIXME: What about the case where paragraph is not BIBLIO
-       // but there is an InsetBibitem?
        // FIXME: when there was already an inset at 0, the return value is 1,
        // which does not tell whether another inset has been remove; the
        // cursor cannot be correctly updated.
 
-       if (d->layout_->labeltype != LABEL_BIBLIO)
-               return 0;
-
        bool const track_changes = buffer.params().track_changes;
        int bibitem_pos = d->insetlist_.find(BIBITEM_CODE);
-       bool const hasbibitem0 = bibitem_pos == 0;
 
+       // The case where paragraph is not BIBLIO
+       if (d->layout_->labeltype != LABEL_BIBLIO) {
+               if (bibitem_pos == -1)
+                       // No InsetBibitem => OK
+                       return 0;
+               // There is an InsetBibitem: remove it!
+               d->insetlist_.release(bibitem_pos);
+               eraseChar(bibitem_pos, track_changes);
+               return (bibitem_pos == 0) ? -1 : -bibitem_pos;
+       }
+
+       bool const hasbibitem0 = bibitem_pos == 0;
        if (hasbibitem0) {
                bibitem_pos = d->insetlist_.find(BIBITEM_CODE, 1);
-               // There was an InsetBibitem at pos 0, and no other one => OK
+               // There was an InsetBibitem at pos 0,
+               // and no other one => OK
                if (bibitem_pos == -1)
                        return 0;
                // there is a bibitem at the 0 position, but since
@@ -3708,7 +3755,7 @@ int Paragraph::fixBiblio(Buffer const & buffer)
        }
 
        // We need to create an inset at the beginning
-       Inset * inset = 0;
+       Inset * inset = nullptr;
        if (bibitem_pos > 0) {
                // there was one somewhere in the paragraph, let's move it
                inset = d->insetlist_.release(bibitem_pos);
@@ -3722,6 +3769,8 @@ int Paragraph::fixBiblio(Buffer const & buffer)
        insertInset(0, inset, font, Change(track_changes ? Change::INSERTED
                                                   : Change::UNCHANGED));
 
+       // This is needed to get the counters right
+       buffer.updateBuffer();
        return 1;
 }