2 * \file output_latex.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
8 * Full author contact details are available in file CREDITS.
13 #include "output_latex.h"
16 #include "BufferParams.h"
18 #include "InsetList.h"
22 #include "OutputParams.h"
23 #include "Paragraph.h"
24 #include "paragraph_funcs.h"
25 #include "ParagraphParameters.h"
26 #include "TextClass.h"
30 #include "insets/InsetBibitem.h"
31 #include "insets/InsetOptArg.h"
33 #include "support/lassert.h"
34 #include "support/debug.h"
35 #include "support/lstrings.h"
37 #include <boost/next_prior.hpp>
40 using namespace lyx::support;
53 static int open_encoding_ = none;
54 static int cjk_inherited_ = 0;
57 ParagraphList::const_iterator
58 TeXEnvironment(Buffer const & buf,
60 ParagraphList::const_iterator pit,
61 odocstream & os, TexRow & texrow,
62 OutputParams const & runparams);
64 ParagraphList::const_iterator
65 TeXOnePar(Buffer const & buf,
67 ParagraphList::const_iterator pit,
68 odocstream & os, TexRow & texrow,
69 OutputParams const & runparams,
70 string const & everypar = string());
73 ParagraphList::const_iterator
74 TeXDeeper(Buffer const & buf,
76 ParagraphList::const_iterator pit,
77 odocstream & os, TexRow & texrow,
78 OutputParams const & runparams)
80 LYXERR(Debug::LATEX, "TeXDeeper... " << &*pit);
81 ParagraphList::const_iterator par = pit;
83 ParagraphList const & paragraphs = text.paragraphs();
85 while (par != paragraphs.end() &&
86 par->params().depth() == pit->params().depth()) {
87 if (par->layout().isEnvironment()) {
88 par = TeXEnvironment(buf, text, par,
89 os, texrow, runparams);
91 par = TeXOnePar(buf, text, par,
92 os, texrow, runparams);
95 LYXERR(Debug::LATEX, "TeXDeeper...done ");
101 ParagraphList::const_iterator
102 TeXEnvironment(Buffer const & buf,
104 ParagraphList::const_iterator pit,
105 odocstream & os, TexRow & texrow,
106 OutputParams const & runparams)
108 LYXERR(Debug::LATEX, "TeXEnvironment... " << &*pit);
110 BufferParams const & bparams = buf.params();
112 // FIXME This test should not be necessary.
113 // We should perhaps issue an error if it is.
114 Layout const & style = pit->forcePlainLayout() ?
115 bparams.documentClass().plainLayout() : pit->layout();
117 ParagraphList const & paragraphs = text.paragraphs();
119 Language const * const par_language = pit->getParLanguage(bparams);
120 Language const * const doc_language = bparams.language;
121 Language const * const prev_par_language =
122 (pit != paragraphs.begin())
123 ? boost::prior(pit)->getParLanguage(bparams)
125 if (par_language->babel() != prev_par_language->babel()) {
127 if (!lyxrc.language_command_end.empty() &&
128 prev_par_language->babel() != doc_language->babel() &&
129 !prev_par_language->babel().empty()) {
130 os << from_ascii(subst(
131 lyxrc.language_command_end,
133 prev_par_language->babel()))
134 // the '%' is necessary to prevent unwanted whitespace
139 if ((lyxrc.language_command_end.empty() ||
140 par_language->babel() != doc_language->babel()) &&
141 !par_language->babel().empty()) {
142 os << from_ascii(subst(
143 lyxrc.language_command_begin,
145 par_language->babel()))
146 // the '%' is necessary to prevent unwanted whitespace
152 bool leftindent_open = false;
153 if (!pit->params().leftIndent().zero()) {
154 os << "\\begin{LyXParagraphLeftIndent}{"
155 << from_ascii(pit->params().leftIndent().asLatexString())
158 leftindent_open = true;
161 if (style.isEnvironment()) {
162 os << "\\begin{" << from_ascii(style.latexname()) << '}';
163 if (style.optionalargs > 0) {
164 int ret = latexOptArgInsets(*pit, os, runparams,
171 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
173 << pit->params().labelWidthString()
175 } else if (style.labeltype == LABEL_BIBLIO) {
177 os << '{' << bibitemWidest(buf) << "}\n";
179 os << from_ascii(style.latexparam()) << '\n';
183 // in multilingual environments, the CJK tags have to be nested properly
184 bool cjk_nested = false;
185 if (par_language->encoding()->package() == Encoding::CJK &&
186 open_encoding_ != CJK && pit->isMultiLingual(bparams)) {
187 os << "\\begin{CJK}{" << from_ascii(par_language->encoding()->latexName())
188 << "}{" << from_ascii(bparams.fontsCJK) << "}%\n";
189 open_encoding_ = CJK;
194 ParagraphList::const_iterator par = pit;
196 par = TeXOnePar(buf, text, par, os, texrow, runparams);
198 if (par == paragraphs.end()) {
199 // Make sure that the last paragraph is
200 // correctly terminated (because TeXOnePar does
201 // not add a \n in this case)
204 } else if (par->params().depth() > pit->params().depth()) {
205 if (par->layout().isParagraph()) {
207 // How to handle this? (Lgb)
208 //&& !suffixIs(os, "\n\n")
210 // There should be at least one '\n' already
211 // but we need there to be two for Standard
212 // paragraphs that are depth-increment'ed to be
213 // output correctly. However, tables can
214 // also be paragraphs so don't adjust them.
217 // Will it ever harm to have one '\n' too
218 // many? i.e. that we sometimes will have
219 // three in a row. (Lgb)
223 par = TeXDeeper(buf, text, par, os, texrow,
226 } while (par != paragraphs.end()
227 && par->layout() == pit->layout()
228 && par->params().depth() == pit->params().depth()
229 && par->params().leftIndent() == pit->params().leftIndent());
231 if (open_encoding_ == CJK && cjk_nested) {
232 // We need to close the encoding even if it does not change
233 // to do correct environment nesting
234 os << "\\end{CJK}\n";
236 open_encoding_ = none;
239 if (style.isEnvironment()) {
240 os << "\\end{" << from_ascii(style.latexname()) << "}\n";
244 if (leftindent_open) {
245 os << "\\end{LyXParagraphLeftIndent}\n";
249 if (par != paragraphs.end())
250 LYXERR(Debug::LATEX, "TeXEnvironment...done " << &*par);
258 int latexOptArgInsets(Paragraph const & par, odocstream & os,
259 OutputParams const & runparams, int number)
263 InsetList::const_iterator it = par.insetList().begin();
264 InsetList::const_iterator end = par.insetList().end();
265 for (; it != end && number > 0 ; ++it) {
266 if (it->inset->lyxCode() == OPTARG_CODE) {
268 static_cast<InsetOptArg *>(it->inset);
269 lines += ins->latexOptional(os, runparams);
279 ParagraphList::const_iterator
280 TeXOnePar(Buffer const & buf,
282 ParagraphList::const_iterator const pit,
283 odocstream & os, TexRow & texrow,
284 OutputParams const & runparams_in,
285 string const & everypar)
287 LYXERR(Debug::LATEX, "TeXOnePar... " << &*pit << " '"
289 BufferParams const & bparams = buf.params();
290 ParagraphList const & paragraphs = text.paragraphs();
292 ParagraphList::const_iterator priorpit = pit;
293 if (priorpit != paragraphs.begin())
295 ParagraphList::const_iterator nextpit = pit;
296 if (nextpit != paragraphs.end())
299 OutputParams runparams = runparams_in;
300 runparams.isLastPar = nextpit == paragraphs.end();
302 if (runparams.verbatim) {
303 int const dist = distance(paragraphs.begin(), pit);
304 Font const outerfont = outerFont(dist, paragraphs);
306 // No newline if only one paragraph in this lyxtext
312 /*bool need_par = */ pit->latex(bparams, outerfont,
313 os, texrow, runparams);
317 // FIXME This check should not really be needed.
318 // Perhaps we should issue an error if it is.
319 Layout const style = pit->forcePlainLayout() ?
320 bparams.documentClass().plainLayout() : pit->layout();
322 runparams.moving_arg |= style.needprotect;
324 bool const maintext = text.isMainText(buf);
325 // we are at the beginning of an inset and CJK is already open;
326 // we count inheritation levels to get the inset nesting right.
327 if (pit == paragraphs.begin() && !maintext
328 && (cjk_inherited_ > 0 || open_encoding_ == CJK)) {
330 open_encoding_ = none;
333 // This paragraph's language
334 Language const * const par_language = pit->getParLanguage(bparams);
335 // The document's language
336 Language const * const doc_language = bparams.language;
337 // The language that was in effect when the environment this paragraph is
338 // inside of was opened
339 Language const * const outer_language =
340 (runparams.local_font != 0) ?
341 runparams.local_font->language() : doc_language;
342 // The previous language that was in effect is either the language of
343 // the previous paragraph, if there is one, or else the outer language
344 // if there is no previous paragraph
345 Language const * const prev_language =
346 (pit != paragraphs.begin()) ?
347 priorpit->getParLanguage(bparams) : outer_language;
349 if (par_language->babel() != prev_language->babel()
350 // check if we already put language command in TeXEnvironment()
351 && !(style.isEnvironment()
352 && (pit == paragraphs.begin() ||
353 (priorpit->layout() != pit->layout() &&
354 priorpit->getDepth() <= pit->getDepth())
355 || priorpit->getDepth() < pit->getDepth())))
357 if (!lyxrc.language_command_end.empty() &&
358 prev_language->babel() != outer_language->babel() &&
359 !prev_language->babel().empty())
361 os << from_ascii(subst(lyxrc.language_command_end,
363 prev_language->babel()))
364 // the '%' is necessary to prevent unwanted whitespace
369 // We need to open a new language if we couldn't close the previous
370 // one (because there's no language_command_end); and even if we closed
371 // the previous one, if the current language is different than the
372 // outer_language (which is currently in effect once the previous one
374 if ((lyxrc.language_command_end.empty() ||
375 par_language->babel() != outer_language->babel()) &&
376 !par_language->babel().empty()) {
377 // If we're inside an inset, and that inset is within an \L or \R
378 // (or equivalents), then within the inset, too, any opposite
379 // language paragraph should appear within an \L or \R (in addition
380 // to, outside of, the normal language switch commands).
381 // This behavior is not correct for ArabTeX, though.
382 if ( // not for ArabTeX
383 (par_language->lang() != "arabic_arabtex" &&
384 outer_language->lang() != "arabic_arabtex") &&
385 // are we in an inset?
386 runparams.local_font != 0 &&
387 // is the inset within an \L or \R?
389 // FIXME: currently, we don't check this; this means that
390 // we'll have unnnecessary \L and \R commands, but that
391 // doesn't seem to hurt (though latex will complain)
393 // is this paragraph in the opposite direction?
394 runparams.local_font->isRightToLeft() !=
395 par_language->rightToLeft()
397 // FIXME: I don't have a working copy of the Arabi package, so
398 // I'm not sure if the farsi and arabic_arabi stuff is correct
400 if (par_language->lang() == "farsi")
402 else if (outer_language->lang() == "farsi")
404 else if (par_language->lang() == "arabic_arabi")
406 else if (outer_language->lang() == "arabic_arabi")
408 // remaining RTL languages currently is hebrew
409 else if (par_language->rightToLeft())
414 // With CJK, the CJK tag has to be closed first (see below)
415 if (runparams.encoding->package() != Encoding::CJK) {
416 os << from_ascii(subst(
417 lyxrc.language_command_begin,
419 par_language->babel()))
420 // the '%' is necessary to prevent unwanted whitespace
427 // Switch file encoding if necessary; no need to do this for "default"
428 // encoding, since this only affects the position of the outputted
429 // \inputencoding command; the encoding switch will occur when necessary
430 if (bparams.inputenc == "auto" &&
431 runparams.encoding->package() != Encoding::none) {
432 // Look ahead for future encoding changes.
433 // We try to output them at the beginning of the paragraph,
434 // since the \inputencoding command is not allowed e.g. in
436 for (pos_type i = 0; i < pit->size(); ++i) {
437 char_type const c = pit->getChar(i);
438 Encoding const * const encoding =
439 pit->getFontSettings(bparams, i).language()->encoding();
440 if (encoding->package() != Encoding::CJK &&
441 runparams.encoding->package() == Encoding::inputenc &&
446 // All characters before c are in the ASCII range, and
447 // c is non-ASCII (but no inset), so change the
448 // encoding to that required by the language of c.
449 // With CJK, only add switch if we have CJK content at the beginning
451 if (encoding->package() != Encoding::CJK || i == 0) {
452 OutputParams tmp_rp = runparams;
453 runparams.moving_arg = false;
454 pair<bool, int> enc_switch = switchEncoding(os, bparams, runparams,
457 // the following is necessary after a CJK environment in a multilingual
458 // context (nesting issue).
459 if (par_language->encoding()->package() == Encoding::CJK &&
460 open_encoding_ != CJK && cjk_inherited_ == 0) {
461 os << "\\begin{CJK}{" << from_ascii(par_language->encoding()->latexName())
462 << "}{" << from_ascii(bparams.fontsCJK) << "}%\n";
463 open_encoding_ = CJK;
466 if (encoding->package() != Encoding::none && enc_switch.first) {
467 if (enc_switch.second > 0) {
468 // the '%' is necessary to prevent unwanted whitespace
472 // With CJK, the CJK tag had to be closed first (see above)
473 if (runparams.encoding->package() == Encoding::CJK) {
474 os << from_ascii(subst(
475 lyxrc.language_command_begin,
477 par_language->babel()))
478 // the '%' is necessary to prevent unwanted whitespace
482 runparams.encoding = encoding;
489 bool const useSetSpace = bparams.documentClass().provides("SetSpace");
490 if (pit->allowParagraphCustomization()) {
491 if (pit->params().startOfAppendix()) {
492 os << "\\appendix\n";
496 if (!pit->params().spacing().isDefault()
497 && (pit == paragraphs.begin()
498 || !priorpit->hasSameLayout(*pit)))
500 os << from_ascii(pit->params().spacing().writeEnvirBegin(useSetSpace))
505 if (style.isCommand()) {
511 switch (style.latextype) {
513 os << '\\' << from_ascii(style.latexname());
515 // Separate handling of optional argument inset.
516 if (style.optionalargs > 0) {
517 int ret = latexOptArgInsets(*pit, os, runparams,
525 os << from_ascii(style.latexparam());
527 case LATEX_ITEM_ENVIRONMENT:
528 case LATEX_LIST_ENVIRONMENT:
531 case LATEX_BIB_ENVIRONMENT:
532 // ignore this, the inset will write itself
538 Font const outerfont = outerFont(distance(paragraphs.begin(), pit),
542 os << from_utf8(everypar);
543 bool need_par = pit->latex(bparams, outerfont,
544 os, texrow, runparams);
546 // Make sure that \\par is done with the font of the last
547 // character if this has another size as the default.
548 // This is necessary because LaTeX (and LyX on the screen)
549 // calculates the space between the baselines according
550 // to this font. (Matthias)
552 // Is this really needed ? (Dekel)
553 // We do not need to use to change the font for the last paragraph
556 Font const font = pit->empty()
557 ? pit->getLayoutFont(bparams, outerfont)
558 : pit->getFont(bparams, pit->size() - 1, outerfont);
560 bool const is_command = style.isCommand();
562 if (style.resfont.size() != font.fontInfo().size()
563 && nextpit != paragraphs.end()
567 os << "\\" << from_ascii(font.latexSize()) << " \\par}";
568 } else if (need_par) {
570 } else if (is_command)
573 bool pending_newline = false;
574 switch (style.latextype) {
575 case LATEX_ITEM_ENVIRONMENT:
576 case LATEX_LIST_ENVIRONMENT:
577 if (nextpit != paragraphs.end()
578 && (pit->params().depth() < nextpit->params().depth()))
579 pending_newline = true;
581 case LATEX_ENVIRONMENT: {
582 // if its the last paragraph of the current environment
583 // skip it otherwise fall through
584 ParagraphList::const_iterator next = nextpit;
586 if (next != paragraphs.end() && (next->layout() != pit->layout()
587 || next->params().depth() != pit->params().depth()))
591 // fall through possible
593 // we don't need it for the last paragraph!!!
594 if (nextpit != paragraphs.end())
595 pending_newline = true;
598 if (pit->allowParagraphCustomization()) {
599 if (!pit->params().spacing().isDefault()
600 && (nextpit == paragraphs.end() || !nextpit->hasSameLayout(*pit)))
602 if (pending_newline) {
606 os << from_ascii(pit->params().spacing().writeEnvirEnd(useSetSpace));
607 pending_newline = true;
611 // Closing the language is needed for the last paragraph; it is also
612 // needed if we're within an \L or \R that we may have opened above (not
613 // necessarily in this paragraph) and are about to close.
614 bool closing_rtl_ltr_environment =
616 (par_language->lang() != "arabic_arabtex" &&
617 outer_language->lang() != "arabic_arabtex") &&
618 // have we opened and \L or \R environment?
619 runparams.local_font != 0 &&
620 runparams.local_font->isRightToLeft() != par_language->rightToLeft() &&
621 // are we about to close the language?
622 ((nextpit != paragraphs.end() &&
623 par_language->babel() !=
624 (nextpit->getParLanguage(bparams))->babel()) ||
625 (nextpit == paragraphs.end() &&
626 par_language->babel() != outer_language->babel()));
628 if (closing_rtl_ltr_environment || (nextpit == paragraphs.end()
629 && par_language->babel() != outer_language->babel())) {
630 // Since \selectlanguage write the language to the aux file,
631 // we need to reset the language at the end of footnote or
634 if (pending_newline) {
638 // when the paragraph uses CJK, the language has to be closed earlier
639 if (font.language()->encoding()->package() != Encoding::CJK) {
640 if (lyxrc.language_command_end.empty()) {
641 if (!prev_language->babel().empty()) {
642 os << from_ascii(subst(
643 lyxrc.language_command_begin,
645 prev_language->babel()));
646 pending_newline = true;
648 } else if (!par_language->babel().empty()) {
649 os << from_ascii(subst(
650 lyxrc.language_command_end,
652 par_language->babel()));
653 pending_newline = true;
657 if (closing_rtl_ltr_environment)
660 if (pending_newline) {
665 // if this is a CJK-paragraph and the next isn't, close CJK
666 // also if the next paragraph is a multilingual environment (because of nesting)
667 if (nextpit != paragraphs.end() && open_encoding_ == CJK &&
668 (nextpit->getParLanguage(bparams)->encoding()->package() != Encoding::CJK ||
669 nextpit->layout().isEnvironment() && nextpit->isMultiLingual(bparams))
670 // in environments, CJK has to be closed later (nesting!)
671 && !style.isEnvironment()) {
672 os << "\\end{CJK}\n";
673 open_encoding_ = none;
676 // If this is the last paragraph, close the CJK environment
677 // if necessary. If it's an environment, we'll have to \end that first.
678 if (nextpit == paragraphs.end() && !style.isEnvironment()) {
679 switch (open_encoding_) {
681 // do nothing at the end of child documents
682 if (maintext && buf.masterBuffer() != &buf)
688 os << "\\end{CJK}\n";
693 open_encoding_ = none;
698 open_encoding_ = none;
708 // If this is the last paragraph, and a local_font was set upon entering
709 // the inset, and we're using "auto" or "default" encoding, the encoding
710 // should be set back to that local_font's encoding.
711 if (nextpit == paragraphs.end() && runparams_in.local_font != 0
712 && runparams_in.encoding != runparams_in.local_font->language()->encoding()
713 && (bparams.inputenc == "auto" || bparams.inputenc == "default")) {
714 runparams_in.encoding = runparams_in.local_font->language()->encoding();
715 os << setEncoding(runparams_in.encoding->iconvName());
717 // Otherwise, the current encoding should be set for the next paragraph.
719 runparams_in.encoding = runparams.encoding;
722 // we don't need it for the last paragraph!!!
723 // Note from JMarc: we will re-add a \n explicitely in
724 // TeXEnvironment, because it is needed in this case
725 if (nextpit != paragraphs.end()) {
726 Layout const & next_layout = nextpit->layout();
727 // no blank lines before environments!
728 if (!next_layout.isEnvironment() || style == next_layout) {
734 if (nextpit != paragraphs.end())
735 LYXERR(Debug::LATEX, "TeXOnePar...done " << &*nextpit);
743 // LaTeX all paragraphs
744 void latexParagraphs(Buffer const & buf,
748 OutputParams const & runparams,
749 string const & everypar)
751 bool was_title = false;
752 bool already_title = false;
753 BufferParams const & bparams = buf.params();
754 DocumentClass const & tclass = bparams.documentClass();
755 ParagraphList const & paragraphs = text.paragraphs();
756 ParagraphList::const_iterator par = paragraphs.begin();
757 ParagraphList::const_iterator endpar = paragraphs.end();
759 LASSERT(runparams.par_begin <= runparams.par_end, /**/);
760 // if only part of the paragraphs will be outputed
761 if (runparams.par_begin != runparams.par_end) {
762 par = boost::next(paragraphs.begin(), runparams.par_begin);
763 endpar = boost::next(paragraphs.begin(), runparams.par_end);
764 // runparams will be passed to nested paragraphs, so
765 // we have to reset the range parameters.
766 const_cast<OutputParams&>(runparams).par_begin = 0;
767 const_cast<OutputParams&>(runparams).par_end = 0;
770 bool const maintext = text.isMainText(buf);
771 bool const is_child = buf.masterBuffer() != &buf;
773 // Open a CJK environment at the beginning of the main buffer
774 // if the document's language is a CJK language
775 // (but not in child documents)
776 if (maintext && !is_child
777 && bparams.encoding().package() == Encoding::CJK) {
778 os << "\\begin{CJK}{" << from_ascii(bparams.encoding().latexName())
779 << "}{" << from_ascii(bparams.fontsCJK) << "}%\n";
781 open_encoding_ = CJK;
783 // if "auto begin" is switched off, explicitely switch the
784 // language on at start
785 if (maintext && !lyxrc.language_auto_begin &&
786 !bparams.language->babel().empty()) {
788 os << from_utf8(subst(lyxrc.language_command_begin,
790 bparams.language->babel()))
795 ParagraphList::const_iterator lastpar;
797 while (par != endpar) {
799 // FIXME This check should not be needed. We should
800 // perhaps issue an error if it is.
801 Layout const & layout = par->forcePlainLayout() ?
802 tclass.plainLayout() :
805 if (layout.intitle) {
807 lyxerr << "Error in latexParagraphs: You"
808 " should not mix title layouts"
809 " with normal ones." << endl;
810 } else if (!was_title) {
812 if (tclass.titletype() == TITLE_ENVIRONMENT) {
814 << from_ascii(tclass.titlename())
819 } else if (was_title && !already_title) {
820 if (tclass.titletype() == TITLE_ENVIRONMENT) {
821 os << "\\end{" << from_ascii(tclass.titlename())
825 os << "\\" << from_ascii(tclass.titlename())
829 already_title = true;
833 if (layout.isEnvironment() ||
834 !par->params().leftIndent().zero()) {
835 par = TeXEnvironment(buf, text, par, os,
838 par = TeXOnePar(buf, text, par, os, texrow,
839 runparams, everypar);
841 if (distance(lastpar, par) >= distance(lastpar, endpar))
845 // It might be that we only have a title in this document
846 if (was_title && !already_title) {
847 if (tclass.titletype() == TITLE_ENVIRONMENT) {
848 os << "\\end{" << from_ascii(tclass.titlename())
852 os << "\\" << from_ascii(tclass.titlename())
858 // if "auto end" is switched off, explicitely close the language at the end
859 // but only if the last par is in a babel language
860 if (maintext && !lyxrc.language_auto_end && !bparams.language->babel().empty() &&
861 lastpar->getParLanguage(bparams)->encoding()->package() != Encoding::CJK) {
862 os << from_utf8(subst(lyxrc.language_command_end,
864 bparams.language->babel()))
869 // If the last paragraph is an environment, we'll have to close
870 // CJK at the very end to do proper nesting.
871 if (maintext && !is_child && open_encoding_ == CJK) {
872 os << "\\end{CJK}\n";
874 open_encoding_ = none;
877 // reset inherited encoding
878 if (cjk_inherited_ > 0) {
880 if (cjk_inherited_ == 0)
881 open_encoding_ = CJK;
886 pair<bool, int> switchEncoding(odocstream & os, BufferParams const & bparams,
887 OutputParams const & runparams, Encoding const & newEnc,
890 Encoding const & oldEnc = *runparams.encoding;
891 bool moving_arg = runparams.moving_arg;
892 if (!force && ((bparams.inputenc != "auto" && bparams.inputenc != "default")
894 return make_pair(false, 0);
896 // Do nothing if the encoding is unchanged.
897 if (oldEnc.name() == newEnc.name())
898 return make_pair(false, 0);
900 // FIXME We ignore encoding switches from/to encodings that do
901 // neither support the inputenc package nor the CJK package here.
902 // This does of course only work in special cases (e.g. switch from
903 // tis620-0 to latin1, but the text in latin1 contains ASCII only),
904 // but it is the best we can do
905 if (oldEnc.package() == Encoding::none
906 || newEnc.package() == Encoding::none)
907 return make_pair(false, 0);
909 LYXERR(Debug::LATEX, "Changing LaTeX encoding from "
910 << oldEnc.name() << " to " << newEnc.name());
911 os << setEncoding(newEnc.iconvName());
912 if (bparams.inputenc == "default")
913 return make_pair(true, 0);
915 docstring const inputenc_arg(from_ascii(newEnc.latexName()));
916 switch (newEnc.package()) {
918 case Encoding::japanese:
919 // shouldn't ever reach here, see above
920 return make_pair(true, 0);
921 case Encoding::inputenc: {
922 int count = inputenc_arg.length();
923 if (oldEnc.package() == Encoding::CJK &&
924 open_encoding_ == CJK) {
926 open_encoding_ = none;
929 else if (oldEnc.package() == Encoding::inputenc &&
930 open_encoding_ == inputenc) {
932 open_encoding_ = none;
935 if (runparams.local_font != 0
936 && oldEnc.package() == Encoding::CJK) {
937 // within insets, \inputenc switches need
938 // to be embraced within \bgroup...\egroup;
942 open_encoding_ = inputenc;
944 // with the japanese option, inputenc is omitted.
945 if (runparams.use_japanese)
946 return make_pair(true, count);
947 os << "\\inputencoding{" << inputenc_arg << '}';
948 return make_pair(true, count + 16);
950 case Encoding::CJK: {
951 int count = inputenc_arg.length();
952 if (oldEnc.package() == Encoding::CJK &&
953 open_encoding_ == CJK) {
957 if (oldEnc.package() == Encoding::inputenc &&
958 open_encoding_ == inputenc) {
962 os << "\\begin{CJK}{" << inputenc_arg << "}{"
963 << from_ascii(bparams.fontsCJK) << "}";
964 open_encoding_ = CJK;
965 return make_pair(true, count + 15);
968 // Dead code to avoid a warning:
969 return make_pair(true, 0);