]> git.lyx.org Git - lyx.git/blobdiff - src/Paragraph.cpp
Script wrapper is needed with ASCII encoding
[lyx.git] / src / Paragraph.cpp
index 42abf41b67676ad688284a2678a2fbfa52e80485..5c8783b324a68a8a98fd0380bb48fcc9c3eb9994 100644 (file)
@@ -891,22 +891,25 @@ int Paragraph::Private::latexSurrogatePair(BufferParams const & bparams,
        }
        docstring latex2 = encoding.latexChar(c).first;
 
-       if (docstring(1, next) == latex1) {
-               // The encoding supports the combination:
-               // output as is (combining char after base char).
-               os << latex2 << latex1;
-               return latex1.length() + latex2.length();
-       }
-
        // Handle combining characters in "script" context (i.e., \textgreek and \textcyrillic)
        docstring::size_type const brace1 = latex2.find_first_of(from_ascii("{"));
        docstring::size_type const brace2 = latex2.find_last_of(from_ascii("}"));
        string script = to_ascii(latex2.substr(1, brace1 - 1));
        // "Script chars" need to embraced in \textcyrillic and \textgreek notwithstanding
-       // whether they are encodable or not (it only depends on the font encoding)
-       if (!runparams.isFullUnicode())
+       // whether they are encodable or not (it only depends on the font encoding),
+       // except if we are using fontspec.
+       bool scriptchar = false;
+       if (!bparams.useNonTeXFonts)
                // This will get us a script value to deal with below
-               Encodings::isKnownScriptChar(c, script);
+               scriptchar = Encodings::isKnownScriptChar(c, script);
+
+       if (!scriptchar && docstring(1, next) == latex1) {
+               // The encoding supports the combination:
+               // output as is (combining char after base char).
+               os << latex2 << latex1;
+               return latex1.length() + latex2.length();
+       }
+
        int pos = 0;
        int length = brace2;
        string fontenc;
@@ -924,7 +927,9 @@ int Paragraph::Private::latexSurrogatePair(BufferParams const & bparams,
                length -= pos;
                latex2 = latex2.substr(pos, length);
                // We only need the script macro with non-native font encodings
-               if (Encodings::needsScriptWrapper(script, fontenc)) {
+               // and with ASCII encoding (e.g., XeTeX with TeX fonts)
+               if (Encodings::needsScriptWrapper(script, fontenc)
+                   && runparams.encoding != encodings.fromLyXName("ascii")) {
                        scriptmacro = from_ascii("\\" + script + "{");
                        cb = from_ascii("}");
                }
@@ -1017,7 +1022,10 @@ int Paragraph::Private::writeScriptChars(BufferParams const & bparams,
        int pos = 0;
        int length = brace2;
        bool closing_brace = true;
-       if (!Encodings::needsScriptWrapper(script, fontenc)) {
+       // We only need the script macro with non-native font encodings
+       // and with ASCII encoding (e.g., XeTeX with TeX fonts)
+       if (!Encodings::needsScriptWrapper(script, fontenc)
+           && runparams.encoding != encodings.fromLyXName("ascii")) {
                // Correct font encoding is being used, so we can avoid \text[greek|cyr].
                pos = brace1 + 1;
                length -= pos;
@@ -1148,8 +1156,6 @@ void Paragraph::Private::latexInset(BufferParams const & bparams,
            // decorations at all
            && inset->lyxCode() != ERT_CODE) {
                if (runparams.use_polyglossia) {
-                       if (style.isEnvironment())
-                               os << "\\begin{LTR}";
                        os << "\\LRE{";
                } else if (running_font.language()->lang() == "farsi"
                           || running_font.language()->lang() == "arabic_arabi")
@@ -1209,12 +1215,8 @@ void Paragraph::Private::latexInset(BufferParams const & bparams,
                throw(e);
        }
 
-       if (close) {
-               if (runparams.use_polyglossia && style.isEnvironment())
-                       os << "\\end{LTR}";
-               else
-                       os << '}';
-       }
+       if (close)
+               os << '}';
 
        if (os.texrow().rows() > previous_row_count) {
                os.texrow().start(owner_->id(), i + 1);
@@ -1398,8 +1400,9 @@ void Paragraph::Private::latexSpecialChar(otexstream & os,
                string fontenc;
                fontenc = running_font.language()->fontenc(bparams);
                // "Script chars" need to embraced in \textcyrillic and \textgreek notwithstanding
-               // whether they are encodable or not (it only depends on the font encoding)
-               if (!runparams.isFullUnicode() && Encodings::isKnownScriptChar(c, script)) {
+               // whether they are encodable or not (it only depends on the font encoding),
+               // except if we are using fontspec.
+               if (!bparams.useNonTeXFonts && Encodings::isKnownScriptChar(c, script)) {
                        docstring const wrapper = from_ascii("\\" + script + "{");
                        docstring ltx = latex.first;
                        if (!prefixIs(ltx, wrapper))
@@ -2004,47 +2007,44 @@ char_type Paragraph::getUChar(BufferParams const & bparams,
 {
        char_type c = d->text_[pos];
 
-       // Return unchanged character in LTR languages.
-       if (!getFontSettings(bparams, pos).isRightToLeft())
+       // Return unchanged character in LTR languages
+       // or if we use poylglossia/bidi.
+       if (rp.use_polyglossia || !getFontSettings(bparams, pos).isRightToLeft())
                return c;
 
-       // FIXME This is a complete mess due to all the language-specific
-       // special cases. We need to unify this eventually, but this
-       // requires a file format change and some thought.
-       // We also need to unify the input of parentheses in different RTL
-       // languages. Currently, some have their own methods (Arabic:
-       // 18599/lyxsvn, Hebrew: e5f42f67d/lyxgit), some don't (Urdu, Syriac).
-       // Also note that the representation in the LyX file is probably wrong
-       // (see FIXME in TextMetrics::breakRow).
-       // Most likely, we should simply rely on Qt's unicode handling here.
-       string const & lang = getFontSettings(bparams, pos).language()->lang();
+       // Without polyglossia/bidi, we need to account for some special cases.
+       // FIXME This needs to be audited!
+       // Check if:
+       // * The input is as expected for all delimiters
+       //   => checked for Hebrew!
+       // * The output matches the display in the LyX workarea
+       //   => checked for Hebrew!
+       // * The special cases below are really necessary
+       //   => checked for Hebrew!
+       // * In arabic_arabi, brackets are transformed to Arabic
+       //   Ornate Parentheses. Is this is really wanted?
 
-       // With polyglossia, brackets and stuff need not be reversed in RTL scripts
-       // FIXME: The special casing for Hebrew parens is due to the special
-       // handling on input (for Hebrew in e5f42f67d/lyxgit); see #8251.
+       string const & lang = getFontSettings(bparams, pos).language()->lang();
        char_type uc = c;
-       if (rp.use_polyglossia) {
-               switch (c) {
-               case '(':
-                       if (lang == "hebrew")
-                               uc = ')';
-                       break;
-               case ')':
-                       if (lang == "hebrew")
-                               uc = '(';
-                       break;
-               }
-               return uc;
-       }
 
-       // In the following languages, brackets don't need to be reversed.
-       // Furthermore, in arabic_arabi, they are transformed to Arabic
-       // Ornate Parentheses (dunno if this is really wanted)
+       // 1. In the following languages, parentheses need to be reversed.
+       bool const reverseparens = lang == "hebrew";
+
+       // 2. In the following languages, brackets don't need to be reversed.
        bool const reversebrackets = lang != "arabic_arabtex"
                        && lang != "arabic_arabi"
-                       && lang != "farsi"; 
+                       && lang != "farsi";
 
+       // Now swap delimiters if needed.
        switch (c) {
+       case '(':
+               if (reverseparens)
+                       uc = ')';
+               break;
+       case ')':
+               if (reverseparens)
+                       uc = '(';
+               break;
        case '[':
                if (reversebrackets)
                        uc = ']';
@@ -2378,6 +2378,9 @@ int Paragraph::Private::startTeXParParams(BufferParams const & bparams,
        string const begin_tag = "\\begin";
        InsetCode code = ownerCode();
        bool const lastpar = runparams.isLastPar;
+       // RTL in classic (PDF)LaTeX (without the Bidi package)
+       bool const rtl_classic = owner_->getParLanguage(bparams)->rightToLeft()
+               && !runparams.use_polyglossia;
 
        switch (curAlign) {
        case LYX_ALIGN_NONE:
@@ -2387,16 +2390,18 @@ int Paragraph::Private::startTeXParParams(BufferParams const & bparams,
        case LYX_ALIGN_DECIMAL:
                break;
        case LYX_ALIGN_LEFT: {
-               if (!owner_->getParLanguage(bparams)->rightToLeft())
-                       corrected_env(os, begin_tag, "flushleft", code, lastpar, column);
-               else
+               if (rtl_classic)
+                       // Classic (PDF)LaTeX switches the left/right logic in RTL mode
                        corrected_env(os, begin_tag, "flushright", code, lastpar, column);
+               else
+                       corrected_env(os, begin_tag, "flushleft", code, lastpar, column);
                break;
        } case LYX_ALIGN_RIGHT: {
-               if (!owner_->getParLanguage(bparams)->rightToLeft())
-                       corrected_env(os, begin_tag, "flushright", code, lastpar, column);
-               else
+               if (rtl_classic)
+                       // Classic (PDF)LaTeX switches the left/right logic in RTL mode
                        corrected_env(os, begin_tag, "flushleft", code, lastpar, column);
+               else
+                       corrected_env(os, begin_tag, "flushright", code, lastpar, column);
                break;
        } case LYX_ALIGN_CENTER: {
                corrected_env(os, begin_tag, "center", code, lastpar, column);
@@ -2436,6 +2441,9 @@ bool Paragraph::Private::endTeXParParams(BufferParams const & bparams,
        string const end_tag = "\\par\\end";
        InsetCode code = ownerCode();
        bool const lastpar = runparams.isLastPar;
+       // RTL in classic (PDF)LaTeX (without the Bidi package)
+       bool const rtl_classic = owner_->getParLanguage(bparams)->rightToLeft()
+               && !runparams.use_polyglossia;
 
        switch (curAlign) {
        case LYX_ALIGN_NONE:
@@ -2445,16 +2453,18 @@ bool Paragraph::Private::endTeXParParams(BufferParams const & bparams,
        case LYX_ALIGN_DECIMAL:
                break;
        case LYX_ALIGN_LEFT: {
-               if (!owner_->getParLanguage(bparams)->rightToLeft())
-                       output = corrected_env(os, end_tag, "flushleft", code, lastpar, col);
-               else
+               if (rtl_classic)
+                       // Classic (PDF)LaTeX switches the left/right logic in RTL mode
                        output = corrected_env(os, end_tag, "flushright", code, lastpar, col);
+               else
+                       output = corrected_env(os, end_tag, "flushleft", code, lastpar, col);
                break;
        } case LYX_ALIGN_RIGHT: {
-               if (!owner_->getParLanguage(bparams)->rightToLeft())
-                       output = corrected_env(os, end_tag, "flushright", code, lastpar, col);
-               else
+               if (rtl_classic)
+                       // Classic (PDF)LaTeX switches the left/right logic in RTL mode
                        output = corrected_env(os, end_tag, "flushleft", code, lastpar, col);
+               else
+                       output = corrected_env(os, end_tag, "flushright", code, lastpar, col);
                break;
        } case LYX_ALIGN_CENTER: {
                corrected_env(os, end_tag, "center", code, lastpar, col);
@@ -3418,7 +3428,10 @@ docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
                } else {
                        char_type c = getUChar(buf.masterBuffer()->params(),
                                               runparams, i);
-                       xs << c;
+                       if (c == ' ' && (style.free_spacing || runparams.free_spacing))
+                               xs << XHTMLStream::ESCAPE_NONE << "&nbsp;";
+                       else
+                               xs << c;
                }
                font_old = font.fontInfo();
        }