]> git.lyx.org Git - lyx.git/blob - src/output_latex.cpp
Cleanup: Replace a bunch of Cursor arguments with DocIterators.
[lyx.git] / src / output_latex.cpp
1 /**
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.
5  *
6  * \author Lars Gullik Bjønnes
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "output_latex.h"
14
15 #include "Buffer.h"
16 #include "BufferParams.h"
17 #include "Encoding.h"
18 #include "InsetList.h"
19 #include "Language.h"
20 #include "Layout.h"
21 #include "LyXRC.h"
22 #include "OutputParams.h"
23 #include "Paragraph.h"
24 #include "paragraph_funcs.h"
25 #include "ParagraphParameters.h"
26 #include "TextClass.h"
27 #include "TexRow.h"
28 #include "VSpace.h"
29
30 #include "insets/InsetBibitem.h"
31 #include "insets/InsetOptArg.h"
32
33 #include "support/lassert.h"
34 #include "support/debug.h"
35 #include "support/lstrings.h"
36
37 #include <boost/next_prior.hpp>
38
39 using namespace std;
40 using namespace lyx::support;
41
42
43 namespace lyx {
44
45 namespace {
46
47 enum OpenEncoding {
48                 none,
49                 inputenc,
50                 CJK
51 };
52
53 static int open_encoding_ = none;
54 static int cjk_inherited_ = 0;
55 Language const * prev_env_language_ = 0;
56
57
58 ParagraphList::const_iterator
59 TeXEnvironment(Buffer const & buf,
60                Text const & text,
61                ParagraphList::const_iterator pit,
62                odocstream & os, TexRow & texrow,
63                OutputParams const & runparams);
64
65
66 ParagraphList::const_iterator
67 TeXDeeper(Buffer const & buf,
68           Text const & text,
69           ParagraphList::const_iterator pit,
70           odocstream & os, TexRow & texrow,
71           OutputParams const & runparams)
72 {
73         LYXERR(Debug::LATEX, "TeXDeeper...     " << &*pit);
74         ParagraphList::const_iterator par = pit;
75
76         ParagraphList const & paragraphs = text.paragraphs();
77
78         bool const force_plain_layout = text.inset().forcePlainLayout();
79         while (par != paragraphs.end() &&
80                                         par->params().depth() == pit->params().depth()) {
81                 // FIXME This test should not be necessary.
82                 // We should perhaps issue an error if it is.
83                 Layout const & style = force_plain_layout
84                         ? buf.params().documentClass().plainLayout() : par->layout();
85                 if (style.isEnvironment()) {
86                         par = TeXEnvironment(buf, text, par,
87                                              os, texrow, runparams);
88                 } else {
89                         par = TeXOnePar(buf, text, par,
90                                              os, texrow, runparams);
91                 }
92         }
93         LYXERR(Debug::LATEX, "TeXDeeper...done ");
94
95         return par;
96 }
97
98
99 ParagraphList::const_iterator
100 TeXEnvironment(Buffer const & buf,
101                Text const & text,
102                ParagraphList::const_iterator pit,
103                odocstream & os, TexRow & texrow,
104                OutputParams const & runparams)
105 {
106         LYXERR(Debug::LATEX, "TeXEnvironment...     " << &*pit);
107
108         BufferParams const & bparams = buf.params();
109
110         // FIXME This test should not be necessary.
111         // We should perhaps issue an error if it is.
112         Layout const & style = text.inset().forcePlainLayout() ?
113                 bparams.documentClass().plainLayout() : pit->layout();
114
115         ParagraphList const & paragraphs = text.paragraphs();
116         ParagraphList::const_iterator const priorpit =
117                 pit == paragraphs.begin() ? pit : boost::prior(pit);
118
119         bool const use_prev_env_language = prev_env_language_ != 0
120                         && priorpit->layout().isEnvironment()
121                         && (priorpit->getDepth() > pit->getDepth()
122                             || (priorpit->getDepth() == pit->getDepth()
123                                 && priorpit->layout() != pit->layout()));
124
125         Encoding const * const prev_encoding = runparams.encoding;
126         Language const * const par_language = pit->getParLanguage(bparams);
127         Language const * const doc_language = bparams.language;
128         Language const * const prev_par_language =
129                 (pit != paragraphs.begin())
130                 ? (use_prev_env_language ? prev_env_language_
131                                          : priorpit->getParLanguage(bparams))
132                 : doc_language;
133         if (par_language->babel() != prev_par_language->babel()) {
134
135                 if (!lyxrc.language_command_end.empty() &&
136                     prev_par_language->babel() != doc_language->babel() &&
137                     !prev_par_language->babel().empty()) {
138                         os << from_ascii(subst(
139                                 lyxrc.language_command_end,
140                                 "$$lang",
141                                 prev_par_language->babel()))
142                            // the '%' is necessary to prevent unwanted whitespace
143                            << "%\n";
144                         texrow.newline();
145                 }
146
147                 if ((lyxrc.language_command_end.empty() ||
148                      par_language->babel() != doc_language->babel()) &&
149                     !par_language->babel().empty()) {
150                         os << from_ascii(subst(
151                                 lyxrc.language_command_begin,
152                                 "$$lang",
153                                 par_language->babel()))
154                            // the '%' is necessary to prevent unwanted whitespace
155                            << "%\n";
156                         texrow.newline();
157                 }
158         }
159
160         bool leftindent_open = false;
161         if (!pit->params().leftIndent().zero()) {
162                 os << "\\begin{LyXParagraphLeftIndent}{"
163                    << from_ascii(pit->params().leftIndent().asLatexString())
164                    << "}\n";
165                 texrow.newline();
166                 leftindent_open = true;
167         }
168
169         if (style.isEnvironment()) {
170                 os << "\\begin{" << from_ascii(style.latexname()) << '}';
171                 if (style.optionalargs > 0) {
172                         int ret = latexOptArgInsets(*pit, os, runparams,
173                                                     style.optionalargs);
174                         while (ret > 0) {
175                                 texrow.newline();
176                                 --ret;
177                         }
178                 }
179                 if (style.latextype == LATEX_LIST_ENVIRONMENT) {
180                         os << '{'
181                            << pit->params().labelWidthString()
182                            << "}\n";
183                 } else if (style.labeltype == LABEL_BIBLIO) {
184                         if (pit->params().labelWidthString().empty())
185                                 os << '{' << bibitemWidest(buf) << "}\n";
186                         else
187                                 os << '{'
188                                   << pit->params().labelWidthString()
189                                   << "}\n";
190                 } else
191                         os << from_ascii(style.latexparam()) << '\n';
192                 texrow.newline();
193         }
194
195         // in multilingual environments, the CJK tags have to be nested properly
196         bool cjk_nested = false;
197         if (par_language->encoding()->package() == Encoding::CJK &&
198             open_encoding_ != CJK && pit->isMultiLingual(bparams)) {
199                 if (prev_par_language->encoding()->package() == Encoding::CJK)
200                         os << "\\begin{CJK}{" << from_ascii(par_language->encoding()->latexName())
201                            << "}{" << from_ascii(bparams.fontsCJK) << "}%\n";
202                 open_encoding_ = CJK;
203                 cjk_nested = true;
204                 texrow.newline();
205         }
206
207         ParagraphList::const_iterator par = pit;
208         do {
209                 par = TeXOnePar(buf, text, par, os, texrow, runparams);
210
211                 if (par == paragraphs.end()) {
212                         // Make sure that the last paragraph is
213                         // correctly terminated (because TeXOnePar does
214                         // not add a \n in this case)
215                         os << '\n';
216                         texrow.newline();
217                 } else if (par->params().depth() > pit->params().depth()) {
218                         if (par->layout().isParagraph()) {
219                           // Thinko!
220                           // How to handle this? (Lgb)
221                           //&& !suffixIs(os, "\n\n")
222
223                                 // There should be at least one '\n' already
224                                 // but we need there to be two for Standard
225                                 // paragraphs that are depth-increment'ed to be
226                                 // output correctly.  However, tables can
227                                 // also be paragraphs so don't adjust them.
228                                 // ARRae
229                                 // Thinkee:
230                                 // Will it ever harm to have one '\n' too
231                                 // many? i.e. that we sometimes will have
232                                 // three in a row. (Lgb)
233                                 os << '\n';
234                                 texrow.newline();
235                         }
236                         par = TeXDeeper(buf, text, par, os, texrow,
237                                         runparams);
238                 }
239         } while (par != paragraphs.end()
240                  && par->layout() == pit->layout()
241                  && par->params().depth() == pit->params().depth()
242                  && par->params().leftIndent() == pit->params().leftIndent());
243
244         if (open_encoding_ == CJK && cjk_nested) {
245                 // We need to close the encoding even if it does not change
246                 // to do correct environment nesting
247                 os << "\\end{CJK}\n";
248                 texrow.newline();
249                 open_encoding_ = none;
250         }
251
252         if (style.isEnvironment()) {
253                 os << "\\end{" << from_ascii(style.latexname()) << "}\n";
254                 texrow.newline();
255                 prev_env_language_ = par_language;
256                 runparams.encoding = prev_encoding;
257         }
258
259         if (leftindent_open) {
260                 os << "\\end{LyXParagraphLeftIndent}\n";
261                 texrow.newline();
262                 prev_env_language_ = par_language;
263                 runparams.encoding = prev_encoding;
264         }
265
266         if (par != paragraphs.end())
267                 LYXERR(Debug::LATEX, "TeXEnvironment...done " << &*par);
268
269         return par;
270 }
271
272 } // namespace anon
273
274
275 int latexOptArgInsets(Paragraph const & par, odocstream & os,
276         OutputParams const & runparams, int number)
277 {
278         int lines = 0;
279
280         InsetList::const_iterator it = par.insetList().begin();
281         InsetList::const_iterator end = par.insetList().end();
282         for (; it != end && number > 0 ; ++it) {
283                 if (it->inset->lyxCode() == OPTARG_CODE) {
284                         InsetOptArg * ins =
285                                 static_cast<InsetOptArg *>(it->inset);
286                         lines += ins->latexOptional(os, runparams);
287                         --number;
288                 }
289         }
290         return lines;
291 }
292
293 // FIXME: this should be anonymous
294 ParagraphList::const_iterator TeXOnePar(Buffer const & buf,
295           Text const & text,
296           ParagraphList::const_iterator const pit,
297           odocstream & os, TexRow & texrow,
298           OutputParams const & runparams_in,
299           string const & everypar,
300           int start_pos, int end_pos)
301 {
302         LYXERR(Debug::LATEX, "TeXOnePar...     " << &*pit << " '"
303                 << everypar << "'");
304         BufferParams const & bparams = buf.params();
305         ParagraphList const & paragraphs = text.paragraphs();
306
307         ParagraphList::const_iterator const priorpit = 
308                 pit == paragraphs.begin() ? pit : boost::prior(pit);
309         ParagraphList::const_iterator const nextpit = 
310                 pit == paragraphs.end() ? pit : boost::next(pit);
311
312         OutputParams runparams = runparams_in;
313         runparams.isLastPar = nextpit == paragraphs.end();
314
315         if (runparams.verbatim) {
316                 int const dist = distance(paragraphs.begin(), pit);
317                 Font const outerfont = outerFont(dist, paragraphs);
318
319                 // No newline if only one paragraph in this lyxtext
320                 if (dist > 0) {
321                         os << '\n';
322                         texrow.newline();
323                 }
324
325                 /*bool need_par = */ pit->latex(bparams, outerfont,
326                         os, texrow, runparams, start_pos, end_pos);
327                 return nextpit;
328         }
329
330         // FIXME This check should not really be needed.
331         // Perhaps we should issue an error if it is.
332         Layout const style = text.inset().forcePlainLayout() ?
333                 bparams.documentClass().plainLayout() : pit->layout();
334
335         runparams.moving_arg |= style.needprotect;
336
337         bool const maintext = text.isMainText();
338         // we are at the beginning of an inset and CJK is already open;
339         // we count inheritation levels to get the inset nesting right.
340         if (pit == paragraphs.begin() && !maintext
341             && (cjk_inherited_ > 0 || open_encoding_ == CJK)) {
342                 cjk_inherited_ += 1;
343                 open_encoding_ = none;
344         }
345
346         // This paragraph's language
347         Language const * const par_language = pit->getParLanguage(bparams);
348         // The document's language
349         Language const * const doc_language = bparams.language;
350         // The language that was in effect when the environment this paragraph is
351         // inside of was opened
352         Language const * const outer_language =
353                 (runparams.local_font != 0) ?
354                         runparams.local_font->language() : doc_language;
355
356         // The previous language that was in effect is the language of the
357         // previous paragraph, unless the previous paragraph is inside an
358         // environment with nesting depth greater than (or equal to, but with
359         // a different layout) the current one. If there is no previous
360         // paragraph, the previous language is the outer language.
361         bool const use_prev_env_language = prev_env_language_ != 0
362                         && priorpit->layout().isEnvironment()
363                         && (priorpit->getDepth() > pit->getDepth()
364                             || (priorpit->getDepth() == pit->getDepth()
365                                 && priorpit->layout() != pit->layout()));
366         Language const * const prev_language =
367                 (pit != paragraphs.begin())
368                 ? (use_prev_env_language ? prev_env_language_
369                                          : priorpit->getParLanguage(bparams))
370                 : outer_language;
371
372         if (par_language->babel() != prev_language->babel()
373             // check if we already put language command in TeXEnvironment()
374             && !(style.isEnvironment()
375                  && (pit == paragraphs.begin() ||
376                      (priorpit->layout() != pit->layout() &&
377                       priorpit->getDepth() <= pit->getDepth())
378                      || priorpit->getDepth() < pit->getDepth())))
379         {
380                 if (!lyxrc.language_command_end.empty() &&
381                     prev_language->babel() != outer_language->babel() &&
382                     !prev_language->babel().empty())
383                 {
384                         os << from_ascii(subst(lyxrc.language_command_end,
385                                 "$$lang",
386                                 prev_language->babel()))
387                            // the '%' is necessary to prevent unwanted whitespace
388                            << "%\n";
389                         texrow.newline();
390                 }
391
392                 // We need to open a new language if we couldn't close the previous
393                 // one (because there's no language_command_end); and even if we closed
394                 // the previous one, if the current language is different than the
395                 // outer_language (which is currently in effect once the previous one
396                 // is closed).
397                 if ((lyxrc.language_command_end.empty() ||
398                      par_language->babel() != outer_language->babel()) &&
399                     !par_language->babel().empty()) {
400                         // If we're inside an inset, and that inset is within an \L or \R
401                         // (or equivalents), then within the inset, too, any opposite
402                         // language paragraph should appear within an \L or \R (in addition
403                         // to, outside of, the normal language switch commands).
404                         // This behavior is not correct for ArabTeX, though.
405                         if (    // not for ArabTeX
406                                         (par_language->lang() != "arabic_arabtex" &&
407                                          outer_language->lang() != "arabic_arabtex") &&
408                                         // are we in an inset?
409                                         runparams.local_font != 0 &&
410                                         // is the inset within an \L or \R?
411                                         //
412                                         // FIXME: currently, we don't check this; this means that
413                                         // we'll have unnnecessary \L and \R commands, but that
414                                         // doesn't seem to hurt (though latex will complain)
415                                         //
416                                         // is this paragraph in the opposite direction?
417                                         runparams.local_font->isRightToLeft() !=
418                                                 par_language->rightToLeft()
419                                 ) {
420                                 // FIXME: I don't have a working copy of the Arabi package, so
421                                 // I'm not sure if the farsi and arabic_arabi stuff is correct
422                                 // or not...
423                                 if (par_language->lang() == "farsi")
424                                         os << "\\textFR{";
425                                 else if (outer_language->lang() == "farsi")
426                                         os << "\\textLR{";
427                                 else if (par_language->lang() == "arabic_arabi")
428                                         os << "\\textAR{";
429                                 else if (outer_language->lang() == "arabic_arabi")
430                                         os << "\\textLR{";
431                                 // remaining RTL languages currently is hebrew
432                                 else if (par_language->rightToLeft())
433                                         os << "\\R{";
434                                 else
435                                         os << "\\L{";
436                         }
437                         // With CJK, the CJK tag has to be closed first (see below)
438                         if (runparams.encoding->package() != Encoding::CJK) {
439                                 os << from_ascii(subst(
440                                         lyxrc.language_command_begin,
441                                         "$$lang",
442                                         par_language->babel()))
443                                    // the '%' is necessary to prevent unwanted whitespace
444                                    << "%\n";
445                                 texrow.newline();
446                         }
447                 }
448         }
449
450         // Switch file encoding if necessary; no need to do this for "default"
451         // encoding, since this only affects the position of the outputted
452         // \inputencoding command; the encoding switch will occur when necessary
453         if (bparams.inputenc == "auto" &&
454             runparams.encoding->package() != Encoding::none) {
455                 // Look ahead for future encoding changes.
456                 // We try to output them at the beginning of the paragraph,
457                 // since the \inputencoding command is not allowed e.g. in
458                 // sections.
459                 for (pos_type i = 0; i < pit->size(); ++i) {
460                         char_type const c = pit->getChar(i);
461                         Encoding const * const encoding =
462                                 pit->getFontSettings(bparams, i).language()->encoding();
463                         if (encoding->package() != Encoding::CJK &&
464                             runparams.encoding->package() == Encoding::inputenc &&
465                             c < 0x80)
466                                 continue;
467                         if (pit->isInset(i))
468                                 break;
469                         // All characters before c are in the ASCII range, and
470                         // c is non-ASCII (but no inset), so change the
471                         // encoding to that required by the language of c.
472                         // With CJK, only add switch if we have CJK content at the beginning
473                         // of the paragraph
474                         if (encoding->package() != Encoding::CJK || i == 0) {
475                                 pair<bool, int> enc_switch = switchEncoding(os, bparams, runparams,
476                                         *encoding);
477                                 // the following is necessary after a CJK environment in a multilingual
478                                 // context (nesting issue).
479                                 if (par_language->encoding()->package() == Encoding::CJK &&
480                                     open_encoding_ != CJK && cjk_inherited_ == 0) {
481                                         os << "\\begin{CJK}{" << from_ascii(par_language->encoding()->latexName())
482                                            << "}{" << from_ascii(bparams.fontsCJK) << "}%\n";
483                                         open_encoding_ = CJK;
484                                         texrow.newline();
485                                 }
486                                 if (encoding->package() != Encoding::none && enc_switch.first) {
487                                         if (enc_switch.second > 0) {
488                                                 // the '%' is necessary to prevent unwanted whitespace
489                                                 os << "%\n";
490                                                 texrow.newline();
491                                         }
492                                         // With CJK, the CJK tag had to be closed first (see above)
493                                         if (runparams.encoding->package() == Encoding::CJK) {
494                                                 os << from_ascii(subst(
495                                                         lyxrc.language_command_begin,
496                                                         "$$lang",
497                                                         par_language->babel()))
498                                                 // the '%' is necessary to prevent unwanted whitespace
499                                                 << "%\n";
500                                                 texrow.newline();
501                                         }
502                                         runparams.encoding = encoding;
503                                 }
504                                 break;
505                         }
506                 }
507         }
508
509         Encoding const * const prev_encoding = runparams.encoding;
510
511         bool const useSetSpace = bparams.documentClass().provides("SetSpace");
512         if (pit->allowParagraphCustomization()) {
513                 if (pit->params().startOfAppendix()) {
514                         os << "\\appendix\n";
515                         texrow.newline();
516                 }
517
518                 if (!pit->params().spacing().isDefault()
519                         && (pit == paragraphs.begin()
520                             || !priorpit->hasSameLayout(*pit)))
521                 {
522                         os << from_ascii(pit->params().spacing().writeEnvirBegin(useSetSpace))
523                             << '\n';
524                         texrow.newline();
525                 }
526
527                 if (style.isCommand()) {
528                         os << '\n';
529                         texrow.newline();
530                 }
531         }
532
533         switch (style.latextype) {
534         case LATEX_COMMAND:
535                 os << '\\' << from_ascii(style.latexname());
536
537                 // Separate handling of optional argument inset.
538                 if (style.optionalargs > 0) {
539                         int ret = latexOptArgInsets(*pit, os, runparams,
540                                                     style.optionalargs);
541                         while (ret > 0) {
542                                 texrow.newline();
543                                 --ret;
544                         }
545                 }
546                 else
547                         os << from_ascii(style.latexparam());
548                 break;
549         case LATEX_ITEM_ENVIRONMENT:
550         case LATEX_LIST_ENVIRONMENT:
551                 os << "\\item ";
552                 break;
553         case LATEX_BIB_ENVIRONMENT:
554                 // ignore this, the inset will write itself
555                 break;
556         default:
557                 break;
558         }
559
560         Font const outerfont = outerFont(distance(paragraphs.begin(), pit),
561                           paragraphs);
562
563         // FIXME UNICODE
564         os << from_utf8(everypar);
565         bool need_par = pit->latex(bparams, outerfont,
566                                              os, texrow, runparams, start_pos, end_pos);
567
568         // Make sure that \\par is done with the font of the last
569         // character if this has another size as the default.
570         // This is necessary because LaTeX (and LyX on the screen)
571         // calculates the space between the baselines according
572         // to this font. (Matthias)
573         //
574         // Is this really needed ? (Dekel)
575         // We do not need to use to change the font for the last paragraph
576         // or for a command.
577
578         Font const font = pit->empty()
579                  ? pit->getLayoutFont(bparams, outerfont)
580                  : pit->getFont(bparams, pit->size() - 1, outerfont);
581
582         bool const is_command = style.isCommand();
583
584         if (style.resfont.size() != font.fontInfo().size()
585             && nextpit != paragraphs.end()
586             && !is_command) {
587                 if (!need_par)
588                         os << '{';
589                 os << "\\" << from_ascii(font.latexSize()) << " \\par}";
590         } else if (need_par) {
591                 os << "\\par}";
592         } else if (is_command) {
593                 os << '}';
594                 runparams.encoding = prev_encoding;
595         }
596
597         bool pending_newline = false;
598         switch (style.latextype) {
599         case LATEX_ITEM_ENVIRONMENT:
600         case LATEX_LIST_ENVIRONMENT:
601                 if (nextpit != paragraphs.end()
602                     && (pit->params().depth() < nextpit->params().depth()))
603                         pending_newline = true;
604                 break;
605         case LATEX_ENVIRONMENT: {
606                 // if its the last paragraph of the current environment
607                 // skip it otherwise fall through
608                 if (nextpit != paragraphs.end() && 
609                     (nextpit->layout() != pit->layout()
610                      || nextpit->params().depth() != pit->params().depth()))
611                         break;
612         }
613
614         // fall through possible
615         default:
616                 // we don't need it for the last paragraph!!!
617                 if (nextpit != paragraphs.end())
618                         pending_newline = true;
619         }
620
621         if (pit->allowParagraphCustomization()) {
622                 if (!pit->params().spacing().isDefault()
623                         && (nextpit == paragraphs.end() || !nextpit->hasSameLayout(*pit)))
624                 {
625                         if (pending_newline) {
626                                 os << '\n';
627                                 texrow.newline();
628                         }
629                         os << from_ascii(pit->params().spacing().writeEnvirEnd(useSetSpace));
630                         pending_newline = true;
631                 }
632         }
633
634         // Closing the language is needed for the last paragraph; it is also
635         // needed if we're within an \L or \R that we may have opened above (not
636         // necessarily in this paragraph) and are about to close.
637         bool closing_rtl_ltr_environment =
638                 // not for ArabTeX
639                 (par_language->lang() != "arabic_arabtex" &&
640                  outer_language->lang() != "arabic_arabtex") &&
641                 // have we opened and \L or \R environment?
642                 runparams.local_font != 0 &&
643                 runparams.local_font->isRightToLeft() != par_language->rightToLeft() &&
644                 // are we about to close the language?
645                 ((nextpit != paragraphs.end() &&
646                   par_language->babel() !=
647                     (nextpit->getParLanguage(bparams))->babel()) ||
648                   (nextpit == paragraphs.end() &&
649                     par_language->babel() != outer_language->babel()));
650
651         if (closing_rtl_ltr_environment || (nextpit == paragraphs.end()
652             && par_language->babel() != outer_language->babel())) {
653                 // Since \selectlanguage write the language to the aux file,
654                 // we need to reset the language at the end of footnote or
655                 // float.
656
657                 if (pending_newline) {
658                         os << '\n';
659                         texrow.newline();
660                 }
661                 // when the paragraph uses CJK, the language has to be closed earlier
662                 if (font.language()->encoding()->package() != Encoding::CJK) {
663                         if (lyxrc.language_command_end.empty()) {
664                                 if (!prev_language->babel().empty()) {
665                                         os << from_ascii(subst(
666                                                 lyxrc.language_command_begin,
667                                                 "$$lang",
668                                                 prev_language->babel()));
669                                         pending_newline = true;
670                                 }
671                         } else if (!par_language->babel().empty()) {
672                                 os << from_ascii(subst(
673                                         lyxrc.language_command_end,
674                                         "$$lang",
675                                         par_language->babel()));
676                                 pending_newline = true;
677                         }
678                 }
679         }
680         if (closing_rtl_ltr_environment)
681                 os << "}";
682
683         if (pending_newline) {
684                 os << '\n';
685                 texrow.newline();
686         }
687
688         // if this is a CJK-paragraph and the next isn't, close CJK
689         // also if the next paragraph is a multilingual environment (because of nesting)
690         if (nextpit != paragraphs.end() && open_encoding_ == CJK &&
691             (nextpit->getParLanguage(bparams)->encoding()->package() != Encoding::CJK ||
692              (nextpit->layout().isEnvironment() && nextpit->isMultiLingual(bparams)))
693              // inbetween environments, CJK has to be closed later (nesting!)
694              && (!style.isEnvironment() || !nextpit->layout().isEnvironment())) {
695                 os << "\\end{CJK}\n";
696                 open_encoding_ = none;
697         }
698
699         // If this is the last paragraph, close the CJK environment
700         // if necessary. If it's an environment, we'll have to \end that first.
701         if (nextpit == paragraphs.end() && !style.isEnvironment()) {
702                 switch (open_encoding_) {
703                         case CJK: {
704                                 // do nothing at the end of child documents
705                                 if (maintext && buf.masterBuffer() != &buf)
706                                         break;
707                                 // end of main text
708                                 if (maintext) {
709                                         os << '\n';
710                                         texrow.newline();
711                                         os << "\\end{CJK}\n";
712                                         texrow.newline();
713                                 // end of an inset
714                                 } else
715                                         os << "\\end{CJK}";
716                                 open_encoding_ = none;
717                                 break;
718                         }
719                         case inputenc: {
720                                 os << "\\egroup";
721                                 open_encoding_ = none;
722                                 break;
723                         }
724                         case none:
725                         default:
726                                 // do nothing
727                                 break;
728                 }
729         }
730
731         // If this is the last paragraph, and a local_font was set upon entering
732         // the inset, and we're using "auto" or "default" encoding, the encoding
733         // should be set back to that local_font's encoding.
734         // However, do not change the encoding when XeTeX is used.
735         if (nextpit == paragraphs.end() && runparams_in.local_font != 0
736             && runparams_in.encoding != runparams_in.local_font->language()->encoding()
737             && (bparams.inputenc == "auto" || bparams.inputenc == "default")
738             && (!bparams.useXetex)) {
739                 runparams_in.encoding = runparams_in.local_font->language()->encoding();
740                 os << setEncoding(runparams_in.encoding->iconvName());
741         }
742         // Otherwise, the current encoding should be set for the next paragraph.
743         else
744                 runparams_in.encoding = runparams.encoding;
745
746
747         // we don't need a newline for the last paragraph!!!
748         // Note from JMarc: we will re-add a \n explicitly in
749         // TeXEnvironment, because it is needed in this case
750         if (nextpit != paragraphs.end()) {
751                 Layout const & next_layout = nextpit->layout();
752                 if (style == next_layout
753                     // no blank lines before environments!
754                     || !next_layout.isEnvironment()
755                     // unless there's a depth change
756                     // FIXME What we really want to do here is put every \begin and \end
757                     // tag on a new line (which was not the case with nested environments).
758                     // But in the present state of play, we don't have access to the
759                     // information whether the current TeX row is empty or not.
760                     // For some ideas about how to fix this, see this thread:
761                     // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg145787.html
762                     || nextpit->params().depth() != pit->params().depth()) {
763                         os << '\n';
764                         texrow.newline();
765                 }
766         }
767
768         if (nextpit != paragraphs.end())
769                 LYXERR(Debug::LATEX, "TeXOnePar...done " << &*nextpit);
770
771         return nextpit;
772 }
773
774
775 // LaTeX all paragraphs
776 void latexParagraphs(Buffer const & buf,
777                      Text const & text,
778                      odocstream & os,
779                      TexRow & texrow,
780                      OutputParams const & runparams,
781                      string const & everypar)
782 {
783         bool was_title = false;
784         bool already_title = false;
785         BufferParams const & bparams = buf.params();
786         DocumentClass const & tclass = bparams.documentClass();
787         ParagraphList const & paragraphs = text.paragraphs();
788         ParagraphList::const_iterator par = paragraphs.begin();
789         ParagraphList::const_iterator endpar = paragraphs.end();
790
791         LASSERT(runparams.par_begin <= runparams.par_end, /**/);
792         // if only part of the paragraphs will be outputed
793         if (runparams.par_begin !=  runparams.par_end) {
794                 par = boost::next(paragraphs.begin(), runparams.par_begin);
795                 endpar = boost::next(paragraphs.begin(), runparams.par_end);
796                 // runparams will be passed to nested paragraphs, so
797                 // we have to reset the range parameters.
798                 const_cast<OutputParams&>(runparams).par_begin = 0;
799                 const_cast<OutputParams&>(runparams).par_end = 0;
800         }
801
802         bool const maintext = text.isMainText();
803         bool const is_child = buf.masterBuffer() != &buf;
804
805         // Open a CJK environment at the beginning of the main buffer
806         // if the document's language is a CJK language
807         // (but not in child documents)
808         if (maintext && !is_child
809             && bparams.encoding().package() == Encoding::CJK) {
810                 os << "\\begin{CJK}{" << from_ascii(bparams.encoding().latexName())
811                 << "}{" << from_ascii(bparams.fontsCJK) << "}%\n";
812                 texrow.newline();
813                 open_encoding_ = CJK;
814         }
815         // if "auto begin" is switched off, explicitely switch the
816         // language on at start
817         if (maintext && !lyxrc.language_auto_begin &&
818             !bparams.language->babel().empty()) {
819                 // FIXME UNICODE
820                 os << from_utf8(subst(lyxrc.language_command_begin,
821                                         "$$lang",
822                                         bparams.language->babel()))
823                         << '\n';
824         texrow.newline();
825         }
826
827         ParagraphList::const_iterator lastpar;
828         // if only_body
829         while (par != endpar) {
830                 lastpar = par;
831                 // FIXME This check should not be needed. We should
832                 // perhaps issue an error if it is.
833                 Layout const & layout = text.inset().forcePlainLayout() ?
834                                 tclass.plainLayout() : par->layout();
835
836                 if (layout.intitle) {
837                         if (already_title) {
838                                 lyxerr << "Error in latexParagraphs: You"
839                                         " should not mix title layouts"
840                                         " with normal ones." << endl;
841                         } else if (!was_title) {
842                                 was_title = true;
843                                 if (tclass.titletype() == TITLE_ENVIRONMENT) {
844                                         os << "\\begin{"
845                                                         << from_ascii(tclass.titlename())
846                                                         << "}\n";
847                                         texrow.newline();
848                                 }
849                         }
850                 } else if (was_title && !already_title) {
851                         if (tclass.titletype() == TITLE_ENVIRONMENT) {
852                                 os << "\\end{" << from_ascii(tclass.titlename())
853                                                 << "}\n";
854                         }
855                         else {
856                                 os << "\\" << from_ascii(tclass.titlename())
857                                                 << "\n";
858                         }
859                         texrow.newline();
860                         already_title = true;
861                         was_title = false;
862                 }
863
864                 if (layout.isEnvironment() ||
865                                         !par->params().leftIndent().zero()) {
866                         par = TeXEnvironment(buf, text, par, os,
867                                                                 texrow, runparams);
868                 } else {
869                         par = TeXOnePar(buf, text, par, os, texrow,
870                                         runparams, everypar);
871                 }
872                 if (distance(lastpar, par) >= distance(lastpar, endpar))
873                         break;
874         }
875
876         // It might be that we only have a title in this document
877         if (was_title && !already_title) {
878                 if (tclass.titletype() == TITLE_ENVIRONMENT) {
879                         os << "\\end{" << from_ascii(tclass.titlename())
880                             << "}\n";
881                 }
882                 else {
883                         os << "\\" << from_ascii(tclass.titlename())
884                             << "\n";
885                                 }
886                 texrow.newline();
887         }
888
889         // if "auto end" is switched off, explicitely close the language at the end
890         // but only if the last par is in a babel language
891         if (maintext && !lyxrc.language_auto_end && !bparams.language->babel().empty() &&
892                 lastpar->getParLanguage(bparams)->encoding()->package() != Encoding::CJK) {
893                 os << from_utf8(subst(lyxrc.language_command_end,
894                                         "$$lang",
895                                         bparams.language->babel()))
896                         << '\n';
897                 texrow.newline();
898         }
899
900         // If the last paragraph is an environment, we'll have to close
901         // CJK at the very end to do proper nesting.
902         if (maintext && !is_child && open_encoding_ == CJK) {
903                 os << "\\end{CJK}\n";
904                 texrow.newline();
905                 open_encoding_ = none;
906         }
907
908         // reset inherited encoding
909         if (cjk_inherited_ > 0) {
910                 cjk_inherited_ -= 1;
911                 if (cjk_inherited_ == 0)
912                         open_encoding_ = CJK;
913         }
914 }
915
916
917 pair<bool, int> switchEncoding(odocstream & os, BufferParams const & bparams,
918                    OutputParams const & runparams, Encoding const & newEnc,
919                    bool force)
920 {
921         Encoding const & oldEnc = *runparams.encoding;
922         bool moving_arg = runparams.moving_arg;
923         if (!force && ((bparams.inputenc != "auto" && bparams.inputenc != "default")
924                 || moving_arg))
925                 return make_pair(false, 0);
926
927         // Do nothing if the encoding is unchanged.
928         if (oldEnc.name() == newEnc.name())
929                 return make_pair(false, 0);
930
931         // FIXME We ignore encoding switches from/to encodings that do
932         // neither support the inputenc package nor the CJK package here.
933         // This does of course only work in special cases (e.g. switch from
934         // tis620-0 to latin1, but the text in latin1 contains ASCII only),
935         // but it is the best we can do
936         if (oldEnc.package() == Encoding::none
937                 || newEnc.package() == Encoding::none)
938                 return make_pair(false, 0);
939
940         LYXERR(Debug::LATEX, "Changing LaTeX encoding from "
941                 << oldEnc.name() << " to " << newEnc.name());
942         os << setEncoding(newEnc.iconvName());
943         if (bparams.inputenc == "default")
944                 return make_pair(true, 0);
945
946         docstring const inputenc_arg(from_ascii(newEnc.latexName()));
947         switch (newEnc.package()) {
948                 case Encoding::none:
949                 case Encoding::japanese:
950                         // shouldn't ever reach here, see above
951                         return make_pair(true, 0);
952                 case Encoding::inputenc: {
953                         int count = inputenc_arg.length();
954                         if (oldEnc.package() == Encoding::CJK &&
955                             open_encoding_ == CJK) {
956                                 os << "\\end{CJK}";
957                                 open_encoding_ = none;
958                                 count += 9;
959                         }
960                         else if (oldEnc.package() == Encoding::inputenc &&
961                                  open_encoding_ == inputenc) {
962                                 os << "\\egroup";
963                                 open_encoding_ = none;
964                                 count += 7;
965                         }
966                         if (runparams.local_font != 0
967                             &&  oldEnc.package() == Encoding::CJK) {
968                                 // within insets, \inputenc switches need
969                                 // to be embraced within \bgroup...\egroup;
970                                 // else CJK fails.
971                                 os << "\\bgroup";
972                                 count += 7;
973                                 open_encoding_ = inputenc;
974                         }
975                         // with the japanese option, inputenc is omitted.
976                         if (runparams.use_japanese)
977                                 return make_pair(true, count);
978                         os << "\\inputencoding{" << inputenc_arg << '}';
979                         return make_pair(true, count + 16);
980                 }
981                 case Encoding::CJK: {
982                         int count = inputenc_arg.length();
983                         if (oldEnc.package() == Encoding::CJK &&
984                             open_encoding_ == CJK) {
985                                 os << "\\end{CJK}";
986                                 count += 9;
987                         }
988                         if (oldEnc.package() == Encoding::inputenc &&
989                             open_encoding_ == inputenc) {
990                                 os << "\\egroup";
991                                 count += 7;
992                         }
993                         os << "\\begin{CJK}{" << inputenc_arg << "}{"
994                            << from_ascii(bparams.fontsCJK) << "}";
995                         open_encoding_ = CJK;
996                         return make_pair(true, count + 15);
997                 }
998         }
999         // Dead code to avoid a warning:
1000         return make_pair(true, 0);
1001
1002 }
1003
1004 } // namespace lyx