Hi!

Attached find a cleaned up version of the patch for 1820, based on the explanations I provided last night (http://permalink.gmane.org/gmane.editors.lyx.devel/89979).

I now feel quite confident that this patch is good. I tried it on all the sample files I have and that I created, I tried it on the sample files Enrico sent in on Friday, and I also tried it on most of the LyX files that I just happen to have lying around --- and it does the right thing for all of them. Still, I would be very happy to have other people test it and provide feedback.

There are one or two FIXMEs in the patch --- if anyone can help me with them, that would be great, I'll try to work on them myself, too. But The patch should be applied even in its current form.

There's still the issue of a lyx2lyx for this, as this *is* a format change. I'm not sure how to go about this, though. First of all, as I already explained, the patch only fixes things which were outputting *incorrectly* (i.e., the output did not match the GUI) and now it does. So do we really want to force the *wrong* display for old files? Secondly, some of the fixes here actually fix things which caused encoding errors previously --- obviously, we don't try to simulate those, too... In a word --- I need help from the lyx2lyx people for this part.

Dov
Index: src/output_latex.cpp
===================================================================
--- src/output_latex.cpp        (revision 19080)
+++ src/output_latex.cpp        (working copy)
@@ -259,14 +259,23 @@
        OutputParams runparams = runparams_in;
        runparams.moving_arg |= style->needprotect;
 
+       // This paragraph's language
        Language const * const par_language = pit->getParLanguage(bparams);
+       // The document's language
        Language const * const doc_language = bparams.language;
-       Language const * const prev_par_language =
-               (pit != paragraphs.begin())
-               ? boost::prior(pit)->getParLanguage(bparams)
-               : doc_language;
+       // The language that was in effect when the environemnt this paragraph 
is 
+       // inside of was opened
+       Language const * const outer_language = 
+               (runparams.local_font != 0) ?
+                       runparams.local_font->language() : doc_language;
+       // The previous language that was in effect is either the language of
+       // the previous paragraph, if there is one, or else the outer language
+       // if there is no previous paragraph
+       Language const * const prev_language =
+               (pit != paragraphs.begin()) ?
+                       boost::prior(pit)->getParLanguage(bparams) : 
outer_language;
 
-       if (par_language->babel() != prev_par_language->babel()
+       if (par_language->babel() != prev_language->babel()
            // check if we already put language command in TeXEnvironment()
            && !(style->isEnvironment()
                 && (pit == paragraphs.begin() ||
@@ -275,19 +284,47 @@
                     || boost::prior(pit)->getDepth() < pit->getDepth())))
        {
                if (!lyxrc.language_command_end.empty() &&
-                   prev_par_language->babel() != doc_language->babel() &&
-                   !prev_par_language->babel().empty())
+                   prev_language->babel() != outer_language->babel() &&
+                   !prev_language->babel().empty())
                {
                        os << from_ascii(subst(lyxrc.language_command_end,
                                "$$lang",
-                               prev_par_language->babel()))
+                               prev_language->babel()))
                           << '\n';
                        texrow.newline();
                }
 
+               // We need to open a new language if we couldn't close the 
previous 
+               // one (because there's no language_command_end); and even if 
we closed
+               // the previous one, if the current language is different than 
the
+               // outer_language (which is currently in effect once the 
previous one
+               // is closed).
                if ((lyxrc.language_command_end.empty() ||
-                    par_language->babel() != doc_language->babel()) &&
+                    par_language->babel() != outer_language->babel()) &&
                    !par_language->babel().empty()) {
+                       // If we're inside an inset, and that inset is within 
an \L or \R
+                       // (or equivalents), then within the inset, too, any 
opposite
+                       // language paragraph should appear within an \L or \R 
(in addition
+                       // to, outside of, the normal language switch commands).
+                       if (lyxrc.rtl_support &&
+                                       // are we in an inset?
+                                       runparams.local_font != 0 &&
+                                       // is the inset within an \L or \R?
+                                       // 
+                                       // FIXME: currently, we don't check 
this; this means that
+                                       // we'll have unnnecessary \L and \R 
commands, but that 
+                                       // doesn't seem to hurt (though latex 
will complain)
+                                       // 
+                                       // is this paragraph in the opposite 
direction?
+                                       runparams.local_font->isRightToLeft() !=
+                                               par_language->rightToLeft()) {
+                               // FIXME: instead of \\R, \\L, use correct 
form, depending 
+                               // on the language (arabic, farsi, etc.)
+                               if (par_language->rightToLeft())
+                                       os << "\\R{";
+                               else
+                                       os << "\\L{";
+                       }
                        os << from_ascii(subst(
                                lyxrc.language_command_begin,
                                "$$lang",
@@ -457,8 +494,23 @@
                }
        }
 
-       if (boost::next(pit) == paragraphs.end()
-           && par_language->babel() != doc_language->babel()) {
+       // Closing the language is needed for the last paragraph; it is also
+       // needed if we're within an \L or \R that we may have opened above (not
+       // necessarily in this paragraph) and are about to close.
+       bool closing_rtl_ltr_environment = 
+               lyxrc.rtl_support && 
+               // have we opened and \L or \R environment?
+               runparams.local_font != 0 &&
+               runparams.local_font->isRightToLeft() != 
par_language->rightToLeft() &&
+               // are we about to close the language?
+               ((boost::next(pit) != paragraphs.end() &&
+                 par_language->babel() != 
+                       (boost::next(pit)->getParLanguage(bparams))->babel()) ||
+                (boost::next(pit) == paragraphs.end() &&
+                 par_language->babel() != outer_language->babel()));
+
+       if (closing_rtl_ltr_environment || (boost::next(pit) == paragraphs.end()
+           && par_language->babel() != outer_language->babel())) {
                // Since \selectlanguage write the language to the aux file,
                // we need to reset the language at the end of footnote or
                // float.
@@ -468,11 +520,11 @@
                        texrow.newline();
                }
                if (lyxrc.language_command_end.empty()) {
-                       if (!doc_language->babel().empty()) {
+                       if (!prev_language->babel().empty()) {
                                os << from_ascii(subst(
                                        lyxrc.language_command_begin,
                                        "$$lang",
-                                       doc_language->babel()));
+                                       prev_language->babel()));
                                pending_newline = true;
                        }
                } else if (!par_language->babel().empty()) {
@@ -483,13 +535,28 @@
                        pending_newline = true;
                }
        }
+       if (closing_rtl_ltr_environment)
+               os << "}";
 
        if (pending_newline) {
                os << '\n';
                texrow.newline();
        }
-       runparams_in.encoding = runparams.encoding;
 
+       // If this is the last paragraph, and a local_font was set upon entering
+       // the inset, the encoding should be set back to that local_font's 
+       // encoding. We don't use switchEncoding(), because no explicit encoding
+       // switch command is needed, since latex will automatically revert to it
+       // when this inset closes.
+       if (boost::next(pit) == paragraphs.end() && runparams_in.local_font != 
0) {
+               runparams_in.encoding = 
runparams_in.local_font->language()->encoding();
+               os << setEncoding(runparams_in.encoding->iconvName());
+       }
+       // Otherwise, the current encoding should be set for the next paragraph.
+       else
+               runparams_in.encoding = runparams.encoding;
+
+
        // we don't need it for the last paragraph!!!
        // Note from JMarc: we will re-add a \n explicitely in
        // TeXEnvironment, because it is needed in this case
Index: src/Font.cpp
===================================================================
--- src/Font.cpp        (revision 19080)
+++ src/Font.cpp        (working copy)
@@ -875,7 +875,8 @@
 int Font::latexWriteEndChanges(odocstream & os, BufferParams const & bparams,
                                  OutputParams const & runparams,
                                  Font const & base,
-                                 Font const & next) const
+                                 Font const & next,
+                                 bool const & closeLanguage) const
 {
        int count = 0;
        bool env = false;
@@ -953,7 +954,8 @@
                open_encoding_ = false;
        }
 
-       if (language() != base.language() && language() != next.language()) {
+       if (closeLanguage &&
+                       language() != base.language() && language() != 
next.language()) {
                os << '}';
                ++count;
        }
Index: src/Font.h
===================================================================
--- src/Font.h  (revision 19080)
+++ src/Font.h  (working copy)
@@ -309,7 +309,8 @@
        int latexWriteEndChanges(odocstream &, BufferParams const & bparams,
                                 OutputParams const & runparams,
                                 Font const & base,
-                                Font const & next) const;
+                                Font const & next,
+                                bool const & closeLanguage = true) const;
 
 
        /// Build GUI description of font state
Index: src/Paragraph.cpp
===================================================================
--- src/Paragraph.cpp   (revision 19080)
+++ src/Paragraph.cpp   (working copy)
@@ -191,7 +191,7 @@
        ///
        void simpleTeXSpecialChars(Buffer const &, BufferParams const &,
                                   odocstream &,
-                                  TexRow & texrow, OutputParams const &,
+                                  TexRow & texrow, OutputParams &,
                                   Font & running_font,
                                   Font & basefont,
                                   Font const & outerfont,
@@ -662,7 +662,7 @@
                                             BufferParams const & bparams,
                                             odocstream & os,
                                             TexRow & texrow,
-                                            OutputParams const & runparams,
+                                            OutputParams & runparams,
                                             Font & running_font,
                                             Font & basefont,
                                             Font const & outerfont,
@@ -752,14 +752,32 @@
 // right now, which means stupid latex code like \textsf{}. AFAIK,
 // this does not harm dvi output. A minor bug, thus (JMarc)
 #endif
-               // some insets cannot be inside a font change command
+               // Some insets cannot be inside a font change command.
+               // However, even such insets *can* be placed in \L or \R
+               // or their equivalents (for RTL language switches), so we don't
+               // close the language in those cases.
                if (open_font && inset->noFontChange()) {
-                       column += running_font.latexWriteEndChanges(
+                       bool closeLanguage = 
+                               (basefont.isRightToLeft() == 
running_font.isRightToLeft());
+                       unsigned int count = running_font.latexWriteEndChanges(
                                        os, bparams, runparams,
-                                               basefont, basefont);
-                       open_font = false;
-                       basefont = owner_->getLayoutFont(bparams, outerfont);
-                       running_font = basefont;
+                                               basefont, basefont, 
closeLanguage);
+                       column += count;
+                       // if any font properties were closed, update the 
running_font, 
+                       // making sure, however, to leave the language as it was
+                       if (count > 0) {
+                               // FIXME: probably a better way to keep track 
of the old 
+                               // language, than copying the entire font?
+                               Font const copy_font(running_font);
+                               basefont = owner_->getLayoutFont(bparams, 
outerfont);
+                               running_font = basefont;
+                               if (!closeLanguage)
+                                       
running_font.setLanguage(copy_font.language());
+                               // leave font open if language is still open
+                               open_font = (running_font.language() == 
basefont.language());
+                               if (closeLanguage)
+                                       runparams.local_font = &basefont;
+                       }
                }
 
                int tmp = inset->latex(buf, os, runparams);

Reply via email to