X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Foutput_latex.C;h=fa96ec758b3fadb24a8307b899e63ef2636b1b6a;hb=ba62665f966508db5a4de6864f4aa7374c5a5356;hp=91f0e146b09871caf03a493fef26679eb05f61d1;hpb=24bb8d72f3726b08b37305878c6a414de104ba0f;p=lyx.git diff --git a/src/output_latex.C b/src/output_latex.C index 91f0e146b0..fa96ec758b 100644 --- a/src/output_latex.C +++ b/src/output_latex.C @@ -29,7 +29,6 @@ #include "insets/insetoptarg.h" #include "support/lstrings.h" -#include "support/unicode.h" namespace lyx { @@ -84,10 +83,6 @@ TeXDeeper(Buffer const & buf, } -int latexOptArgInsets(Buffer const & buf, Paragraph const & par, - odocstream & os, OutputParams const & runparams, int number); - - ParagraphList::const_iterator TeXEnvironment(Buffer const & buf, ParagraphList const & paragraphs, @@ -213,6 +208,8 @@ TeXEnvironment(Buffer const & buf, return par; } +} + int latexOptArgInsets(Buffer const & buf, Paragraph const & par, odocstream & os, OutputParams const & runparams, int number) @@ -233,18 +230,19 @@ int latexOptArgInsets(Buffer const & buf, Paragraph const & par, } +namespace { + ParagraphList::const_iterator TeXOnePar(Buffer const & buf, ParagraphList const & paragraphs, ParagraphList::const_iterator pit, - odocstream & ucs4, TexRow & texrow, + odocstream & os, TexRow & texrow, OutputParams const & runparams_in, string const & everypar) { lyxerr[Debug::LATEX] << "TeXOnePar... " << &*pit << " '" << everypar << "'" << endl; BufferParams const & bparams = buf.params(); - bool further_blank_line = false; LyXLayout_ptr style; // In an inset with unlimited length (all in one row), @@ -275,49 +273,42 @@ TeXOnePar(Buffer const & buf, if (!lyxrc.language_command_end.empty() && previous_language->babel() != doc_language->babel()) { - ucs4 << from_ascii(subst(lyxrc.language_command_end, + os << from_ascii(subst(lyxrc.language_command_end, "$$lang", previous_language->babel())) - << '\n'; + << '\n'; texrow.newline(); } if (lyxrc.language_command_end.empty() || language->babel() != doc_language->babel()) { - ucs4 << from_ascii(subst( + os << from_ascii(subst( lyxrc.language_command_begin, "$$lang", language->babel())) - << '\n'; + << '\n'; texrow.newline(); } } - // FIXME thailatex does not support the inputenc package, so we - // ignore switches from/to tis620-0 encoding here. This does of - // course only work as long as the non-thai text contains ASCII - // only, but it is the best we can do. - bool const use_thailatex = (language->encoding()->name() == "tis620-0" || - previous_language->encoding()->name() == "tis620-0"); - if (bparams.inputenc == "auto" && - language->encoding() != previous_language->encoding() && - !use_thailatex) { - ucs4 << "\\inputencoding{" - << from_ascii(language->encoding()->latexName()) - << "}\n"; + LyXFont const outerfont = + outerFont(std::distance(paragraphs.begin(), pit), + paragraphs); + // This must be identical to basefont in Paragraph::simpleTeXOnePar + LyXFont basefont = (pit->beginOfBody() > 0) ? + pit->getLabelFont(bparams, outerfont) : + pit->getLayoutFont(bparams, outerfont); + Encoding const & outer_encoding(*(outerfont.language()->encoding())); + // FIXME we switch from the outer encoding to the encoding of + // this paragraph, since I could not figure out the correct + // logic to take the encoding of the previous paragraph into + // account. This may result in some unneeded encoding changes. + if (switchEncoding(os, bparams, outer_encoding, + *(basefont.language()->encoding()))) { + os << '\n'; texrow.newline(); } - // We need to output the paragraph to a temporary stream if we - // need to change the encoding. Don't do this if the result does - // not go to a file but to the builtin source viewer. - odocstringstream par_stream; - bool const change_encoding = !runparams_in.dryrun && - bparams.inputenc == "auto" && - language->encoding() != doc_language->encoding() && - !use_thailatex; - // don't trigger the copy ctor because it's private on msvc - odocstream & os = *(change_encoding ? &par_stream : &ucs4); // In an inset with unlimited length (all in one row), // don't allow any special options in the paragraph @@ -340,11 +331,6 @@ TeXOnePar(Buffer const & buf, os << '\n'; texrow.newline(); } - - if (further_blank_line) { - os << '\n'; - texrow.newline(); - } } switch (style->latextype) { @@ -376,8 +362,7 @@ TeXOnePar(Buffer const & buf, // FIXME UNICODE os << from_utf8(everypar); - bool need_par = pit->simpleTeXOnePar(buf, bparams, - outerFont(std::distance(paragraphs.begin(), pit), paragraphs), + bool need_par = pit->simpleTeXOnePar(buf, bparams, outerfont, os, texrow, runparams); // Make sure that \\par is done with the font of the last @@ -389,9 +374,6 @@ TeXOnePar(Buffer const & buf, // Is this really needed ? (Dekel) // We do not need to use to change the font for the last paragraph // or for a command. - LyXFont const outerfont = - outerFont(std::distance(paragraphs.begin(), pit), - paragraphs); LyXFont const font = (pit->empty() @@ -411,14 +393,13 @@ TeXOnePar(Buffer const & buf, } else if (is_command) os << '}'; + bool pending_newline = false; switch (style->latextype) { case LATEX_ITEM_ENVIRONMENT: case LATEX_LIST_ENVIRONMENT: if (boost::next(pit) != paragraphs.end() - && (pit->params().depth() < boost::next(pit)->params().depth())) { - os << '\n'; - texrow.newline(); - } + && (pit->params().depth() < boost::next(pit)->params().depth())) + pending_newline = true; break; case LATEX_ENVIRONMENT: { // if its the last paragraph of the current environment @@ -434,27 +415,21 @@ TeXOnePar(Buffer const & buf, // fall through possible default: // we don't need it for the last paragraph!!! - if (boost::next(pit) != paragraphs.end()) { - os << '\n'; - texrow.newline(); - } + if (boost::next(pit) != paragraphs.end()) + pending_newline = true; } if (!pit->forceDefaultParagraphs()) { - further_blank_line = false; - - if (further_blank_line) { - os << '\n'; - texrow.newline(); - } - if (!pit->params().spacing().isDefault() && (boost::next(pit) == paragraphs.end() || !boost::next(pit)->hasSameLayout(*pit))) { - os << from_ascii(pit->params().spacing().writeEnvirEnd()) - << '\n'; - texrow.newline(); + if (pending_newline) { + os << '\n'; + texrow.newline(); + } + os << from_ascii(pit->params().spacing().writeEnvirEnd()); + pending_newline = true; } } @@ -464,18 +439,32 @@ TeXOnePar(Buffer const & buf, // we need to reset the language at the end of footnote or // float. + if (pending_newline) { + os << '\n'; + texrow.newline(); + } if (lyxrc.language_command_end.empty()) os << from_ascii(subst( lyxrc.language_command_begin, "$$lang", - doc_language->babel())) - << '\n'; + doc_language->babel())); else os << from_ascii(subst( lyxrc.language_command_end, "$$lang", - language->babel())) - << '\n'; + language->babel())); + pending_newline = true; + } + + // FIXME we switch from the encoding of this paragraph to the + // outer encoding, since I could not figure out the correct logic + // to take the encoding of the next paragraph into account. + // This may result in some unneeded encoding changes. + basefont = pit->getLayoutFont(bparams, outerfont); + switchEncoding(os, bparams, *(basefont.language()->encoding()), + outer_encoding); + if (pending_newline) { + os << '\n'; texrow.newline(); } @@ -491,59 +480,6 @@ TeXOnePar(Buffer const & buf, lyxerr.debugging(Debug::LATEX)) lyxerr << "TeXOnePar...done " << &*boost::next(pit) << endl; - if (change_encoding) { - lyxerr[Debug::LATEX] << "Converting paragraph to encoding " - << language->encoding()->iconvName() << endl; - docstring const par = par_stream.str(); - // Convert the paragraph to the 8bit encoding that we need to - // output. - std::vector const encoded = lyx::ucs4_to_eightbit(par.c_str(), - par.size(), language->encoding()->iconvName()); - // Interpret this as if it was in the 8 bit encoding of the - // document language and convert it back to UCS4. That means - // that faked does not contain pure UCS4 anymore, but what - // will be written to the output file will be correct, because - // the real output stream will do a UCS4 -> document language - // encoding conversion. - // This is of course a hack, but not a bigger one than mixing - // two encodings in one file. - // FIXME: Catch iconv conversion errors and display an error - // dialog. - - // Here follows an explanation how I (gb) came to the current - // solution: - - // codecvt facets are only used by file streams -> OK, maybe - // we could use file streams and not generic streams in the - // latex() methods? No, that does not work, we use them at - // several places to write to string streams. - // Next try: Maybe we could do something else than codecvt - // in our streams, and add a setEncoding() method? That - // does not work unless we rebuild the functionality of file - // and string streams, since both odocfstream and - // odocstringstream inherit from std::basic_ostream - // and we can neither add a method to that class nor change - // the inheritance of the file and string streams. - - // What might be possible is to encapsulate the real file and - // string streams in our own version, and use a homemade - // streambuf that would do the encoding conversion and then - // forward to the real stream. That would probably work, but - // would require far more code and a good understanding of - // stream buffers to get it right. - - // Another idea by JMarc is to use a modifier like - // os << setencoding("iso-8859-1"); - // That currently looks like the best idea. - - std::vector const faked = lyx::eightbit_to_ucs4(&(encoded[0]), - encoded.size(), doc_language->encoding()->iconvName()); - std::vector::const_iterator const end = faked.end(); - std::vector::const_iterator it = faked.begin(); - for (; it != end; ++it) - ucs4.put(*it); - } - return ++pit; } @@ -581,7 +517,8 @@ void latexParagraphs(Buffer const & buf, // well we have to check if we are in an inset with unlimited // length (all in one row) if that is true then we don't allow // any special options in the paragraph and also we don't allow - // any environment other then "Standard" to be valid! + // any environment other than the default layout of the + // text class to be valid! if (!par->forceDefaultParagraphs()) { LyXLayout_ptr const & layout = par->layout(); @@ -617,8 +554,7 @@ void latexParagraphs(Buffer const & buf, par = TeXOnePar(buf, paragraphs, par, os, texrow, runparams, everypar); } else if (layout->isEnvironment() || - !par->params().leftIndent().zero()) - { + !par->params().leftIndent().zero()) { par = TeXEnvironment(buf, paragraphs, par, os, texrow, runparams); } else { @@ -647,4 +583,28 @@ void latexParagraphs(Buffer const & buf, } +int switchEncoding(odocstream & os, BufferParams const & bparams, + Encoding const & oldEnc, Encoding const & newEnc) +{ + // FIXME thailatex does not support the inputenc package, so we + // ignore switches from/to tis620-0 encoding here. This does of + // course only work as long as the non-thai text contains ASCII + // only, but it is the best we can do. + if ((bparams.inputenc == "auto" || bparams.inputenc == "default") && + oldEnc.name() != newEnc.name() && + oldEnc.name() != "ascii" && newEnc.name() != "ascii" && + oldEnc.name() != "tis620-0" && newEnc.name() != "tis620-0") { + lyxerr[Debug::LATEX] << "Changing LaTeX encoding from " + << oldEnc.name() << " to " + << newEnc.name() << endl; + os << setEncoding(newEnc.iconvName()); + if (bparams.inputenc != "default") { + docstring const inputenc(from_ascii(newEnc.latexName())); + os << "\\inputencoding{" << inputenc << '}'; + return 16 + inputenc.length(); + } + } + return 0; +} + } // namespace lyx