]> git.lyx.org Git - lyx.git/blob - src/paragraph_funcs.C
5048bfa0632f640c0982343b7e8dbdb04c5d4fff
[lyx.git] / src / paragraph_funcs.C
1 /**
2  * \file paragraph_funcs.C
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 "paragraph_funcs.h"
14
15 #include "buffer.h"
16 #include "bufferparams.h"
17
18 #include "debug.h"
19 #include "encoding.h"
20 #include "errorlist.h"
21 #include "factory.h"
22 #include "gettext.h"
23 #include "iterators.h"
24 #include "language.h"
25 #include "lyxlex.h"
26 #include "lyxrc.h"
27 #include "paragraph_pimpl.h"
28 #include "sgml.h"
29 #include "texrow.h"
30 #include "vspace.h"
31
32 #include "insets/insetbibitem.h"
33 #include "insets/insethfill.h"
34 #include "insets/insetlatexaccent.h"
35 #include "insets/insetline.h"
36 #include "insets/insetnewline.h"
37 #include "insets/insetpagebreak.h"
38 #include "insets/insetoptarg.h"
39 #include "insets/insetspace.h"
40 #include "insets/insetspecialchar.h"
41 #include "insets/insettabular.h"
42
43 #include "support/filetools.h"
44 #include "support/lstrings.h"
45 #include "support/lyxlib.h"
46 #include "support/std_sstream.h"
47
48 #include <vector>
49
50 using lyx::pos_type;
51
52 using lyx::support::atoi;
53 using lyx::support::bformat;
54 using lyx::support::split;
55 using lyx::support::subst;
56
57 using std::endl;
58 using std::string;
59 using std::vector;
60 using std::istringstream;
61 using std::ostream;
62
63 extern string bibitemWidest(Buffer const &);
64
65
66 namespace {
67
68 bool moveItem(Paragraph & from, Paragraph & to,
69         BufferParams const & params, pos_type i, pos_type j)
70 {
71         char const tmpchar = from.getChar(i);
72         LyXFont tmpfont = from.getFontSettings(params, i);
73
74         if (tmpchar == Paragraph::META_INSET) {
75                 InsetOld * tmpinset = 0;
76                 if (from.getInset(i)) {
77                         // the inset is not in a paragraph anymore
78                         tmpinset = from.insetlist.release(i);
79                 }
80
81                 if (!to.insetAllowed(tmpinset->lyxCode()))
82                         return false;
83                 to.insertInset(j, tmpinset, tmpfont);
84         } else {
85                 if (!to.checkInsertChar(tmpfont))
86                         return false;
87                 to.insertChar(j, tmpchar, tmpfont);
88         }
89         return true;
90 }
91
92 }
93
94
95 void breakParagraph(BufferParams const & bparams,
96                     ParagraphList & paragraphs,
97                     ParagraphList::iterator par,
98                     pos_type pos,
99                     int flag)
100 {
101         // create a new paragraph, and insert into the list
102         ParagraphList::iterator tmp = paragraphs.insert(boost::next(par),
103                                                         Paragraph());
104
105         // without doing that we get a crash when typing <Return> at the
106         // end of a paragraph
107         tmp->layout(bparams.getLyXTextClass().defaultLayout());
108         // remember to set the inset_owner
109         tmp->setInsetOwner(par->inInset());
110
111         if (bparams.tracking_changes)
112                 tmp->trackChanges();
113
114         // this is an idea for a more userfriendly layout handling, I will
115         // see what the users say
116
117         // layout stays the same with latex-environments
118         if (flag) {
119                 tmp->layout(par->layout());
120                 tmp->setLabelWidthString(par->params().labelWidthString());
121         }
122
123         bool const isempty = (par->allowEmpty() && par->empty());
124
125         if (!isempty && (par->size() > pos || par->empty() || flag == 2)) {
126                 tmp->layout(par->layout());
127                 tmp->params().align(par->params().align());
128                 tmp->setLabelWidthString(par->params().labelWidthString());
129
130                 tmp->params().spaceBottom(par->params().spaceBottom());
131                 par->params().spaceBottom(VSpace(VSpace::NONE));
132
133                 tmp->params().depth(par->params().depth());
134                 tmp->params().noindent(par->params().noindent());
135
136                 // copy everything behind the break-position
137                 // to the new paragraph
138
139 #ifdef WITH_WARNINGS
140 #warning this seems wrong
141 #endif
142                 /* FIXME: if !keepempty, empty() == true, then we reach
143                  * here with size() == 0. So pos_end becomes - 1. Why
144                  * doesn't this cause problems ???
145                  */
146                 pos_type pos_end = par->size() - 1;
147                 pos_type i = pos;
148                 pos_type j = pos;
149
150                 for (; i <= pos_end; ++i) {
151                         Change::Type change = par->lookupChange(i);
152                         if (moveItem(*par, *tmp, bparams, i, j - pos)) {
153                                 tmp->setChange(j - pos, change);
154                                 ++j;
155                         }
156                 }
157
158                 for (i = pos_end; i >= pos; --i)
159                         par->eraseIntern(i);
160         }
161
162         if (pos)
163                 return;
164
165         tmp->params().spaceTop(par->params().spaceTop());
166         par->params().clear();
167
168         par->layout(bparams.getLyXTextClass().defaultLayout());
169
170         // layout stays the same with latex-environments
171         if (flag) {
172                 par->layout(tmp->layout());
173                 par->setLabelWidthString(tmp->params().labelWidthString());
174                 par->params().depth(tmp->params().depth());
175         }
176
177         // subtle, but needed to get empty pars working right
178         if (bparams.tracking_changes) {
179                 if (!par->size()) {
180                         par->cleanChanges();
181                 } else if (!tmp->size()) {
182                         tmp->cleanChanges();
183                 }
184         }
185 }
186
187
188 void breakParagraphConservative(BufferParams const & bparams,
189                                 ParagraphList & paragraphs,
190                                 ParagraphList::iterator par,
191                                 pos_type pos)
192 {
193         // create a new paragraph
194         ParagraphList::iterator tmp = paragraphs.insert(boost::next(par),
195                                                         Paragraph());
196         tmp->makeSameLayout(*par);
197
198         // When can pos > size()?
199         // I guess pos == size() is possible.
200         if (par->size() > pos) {
201                 // copy everything behind the break-position to the new
202                 // paragraph
203                 pos_type pos_end = par->size() - 1;
204
205                 for (pos_type i = pos, j = pos; i <= pos_end; ++i)
206                         if (moveItem(*par, *tmp, bparams, i, j - pos))
207                                 ++j;
208
209                 for (pos_type k = pos_end; k >= pos; --k)
210                         par->erase(k);
211         }
212 }
213
214
215 void mergeParagraph(BufferParams const & bparams,
216                     ParagraphList & paragraphs,
217                     ParagraphList::iterator par)
218 {
219         ParagraphList::iterator the_next = boost::next(par);
220
221         // first the DTP-stuff
222         par->params().spaceBottom(the_next->params().spaceBottom());
223
224         pos_type pos_end = the_next->size() - 1;
225         pos_type pos_insert = par->size();
226
227         // ok, now copy the paragraph
228         for (pos_type i = 0, j = 0; i <= pos_end; ++i)
229                 if (moveItem(*the_next, *par, bparams, i, pos_insert + j))
230                         ++j;
231
232         paragraphs.erase(the_next);
233 }
234
235
236 ParagraphList::iterator depthHook(ParagraphList::iterator pit,
237                                   ParagraphList const & plist,
238                                   Paragraph::depth_type depth)
239 {
240         ParagraphList::iterator newpit = pit;
241         ParagraphList::iterator beg = const_cast<ParagraphList&>(plist).begin();
242
243         if (newpit != beg)
244                 --newpit;
245
246         while (newpit != beg && newpit->getDepth() > depth) {
247                 --newpit;
248         }
249
250         if (newpit->getDepth() > depth)
251                 return pit;
252
253         return newpit;
254 }
255
256
257 ParagraphList::iterator outerHook(ParagraphList::iterator pit,
258                                   ParagraphList const & plist)
259 {
260         if (!pit->getDepth())
261                 return const_cast<ParagraphList&>(plist).end();
262         return depthHook(pit, plist,
263                          Paragraph::depth_type(pit->getDepth() - 1));
264 }
265
266
267 bool isFirstInSequence(ParagraphList::iterator pit,
268                        ParagraphList const & plist)
269 {
270         ParagraphList::iterator dhook = depthHook(pit, plist, pit->getDepth());
271         return (dhook == pit
272                 || dhook->layout() != pit->layout()
273                 || dhook->getDepth() != pit->getDepth());
274 }
275
276
277 int getEndLabel(ParagraphList::iterator p, ParagraphList const & plist)
278 {
279         ParagraphList::iterator pit = p;
280         Paragraph::depth_type par_depth = p->getDepth();
281         while (pit != const_cast<ParagraphList&>(plist).end()) {
282                 LyXLayout_ptr const & layout = pit->layout();
283                 int const endlabeltype = layout->endlabeltype;
284
285                 if (endlabeltype != END_LABEL_NO_LABEL) {
286                         if (boost::next(p) == const_cast<ParagraphList&>(plist).end())
287                                 return endlabeltype;
288
289                         Paragraph::depth_type const next_depth = boost::next(p)->getDepth();
290                         if (par_depth > next_depth ||
291                             (par_depth == next_depth &&
292                              layout != boost::next(p)->layout()))
293                                 return endlabeltype;
294                         break;
295                 }
296                 if (par_depth == 0)
297                         break;
298                 pit = outerHook(pit, plist);
299                 if (pit != const_cast<ParagraphList&>(plist).end())
300                         par_depth = pit->getDepth();
301         }
302         return END_LABEL_NO_LABEL;
303 }
304
305
306 namespace {
307
308 ParagraphList::iterator
309 TeXEnvironment(Buffer const & buf,
310                ParagraphList const & paragraphs,
311                ParagraphList::iterator pit,
312                ostream & os, TexRow & texrow,
313                LatexRunParams const & runparams);
314
315 ParagraphList::iterator
316 TeXOnePar(Buffer const & buf,
317           ParagraphList const & paragraphs,
318           ParagraphList::iterator pit,
319           ostream & os, TexRow & texrow,
320           LatexRunParams const & runparams,
321           string const & everypar = string());
322
323
324 ParagraphList::iterator
325 TeXDeeper(Buffer const & buf,
326           ParagraphList const & paragraphs,
327           ParagraphList::iterator pit,
328           ostream & os, TexRow & texrow,
329           LatexRunParams const & runparams)
330 {
331         lyxerr[Debug::LATEX] << "TeXDeeper...     " << &*pit << endl;
332         ParagraphList::iterator par = pit;
333
334         while (par != const_cast<ParagraphList&>(paragraphs).end() &&
335                      par->params().depth() == pit->params().depth()) {
336                 if (par->layout()->isEnvironment()) {
337                         par = TeXEnvironment(buf, paragraphs, par,
338                                              os, texrow, runparams);
339                 } else {
340                         par = TeXOnePar(buf, paragraphs, par,
341                                              os, texrow, runparams);
342                 }
343         }
344         lyxerr[Debug::LATEX] << "TeXDeeper...done " << &*par << endl;
345
346         return par;
347 }
348
349
350 ParagraphList::iterator
351 TeXEnvironment(Buffer const & buf,
352                ParagraphList const & paragraphs,
353                ParagraphList::iterator pit,
354                ostream & os, TexRow & texrow,
355                LatexRunParams const & runparams)
356 {
357         lyxerr[Debug::LATEX] << "TeXEnvironment...     " << &*pit << endl;
358
359         BufferParams const & bparams = buf.params();
360
361         LyXLayout_ptr const & style = pit->layout();
362
363         Language const * language = pit->getParLanguage(bparams);
364         Language const * doc_language = bparams.language;
365         Language const * previous_language =
366                 (pit != const_cast<ParagraphList&>(paragraphs).begin())
367                 ? boost::prior(pit)->getParLanguage(bparams)
368                 : doc_language;
369         if (language->babel() != previous_language->babel()) {
370
371                 if (!lyxrc.language_command_end.empty() &&
372                     previous_language->babel() != doc_language->babel()) {
373                         os << subst(lyxrc.language_command_end, "$$lang",
374                                     previous_language->babel())
375                            << endl;
376                         texrow.newline();
377                 }
378
379                 if (lyxrc.language_command_end.empty() ||
380                     language->babel() != doc_language->babel()) {
381                         os << subst(lyxrc.language_command_begin, "$$lang",
382                                     language->babel())
383                            << endl;
384                         texrow.newline();
385                 }
386         }
387
388         bool leftindent_open = false;
389         if (!pit->params().leftIndent().zero()) {
390                 os << "\\begin{LyXParagraphLeftIndent}{" <<
391                         pit->params().leftIndent().asLatexString() << "}\n";
392                 texrow.newline();
393                 leftindent_open = true;
394         }
395
396         if (style->isEnvironment()) {
397                 if (style->latextype == LATEX_LIST_ENVIRONMENT) {
398                         os << "\\begin{" << style->latexname() << "}{"
399                            << pit->params().labelWidthString() << "}\n";
400                 } else if (style->labeltype == LABEL_BIBLIO) {
401                         // ale970405
402                         os << "\\begin{" << style->latexname() << "}{"
403                            <<  bibitemWidest(buf)
404                            << "}\n";
405                 } else if (style->latextype == LATEX_ITEM_ENVIRONMENT) {
406                         os << "\\begin{" << style->latexname() << '}'
407                            << style->latexparam() << '\n';
408                 } else
409                         os << "\\begin{" << style->latexname() << '}'
410                            << style->latexparam() << '\n';
411                 texrow.newline();
412         }
413         ParagraphList::iterator par = pit;
414         do {
415                 par = TeXOnePar(buf, paragraphs, par, os, texrow, runparams);
416
417                 if (par != const_cast<ParagraphList&>(paragraphs).end() && par->params().depth() > pit->params().depth()) {
418                             if (par->layout()->isParagraph()) {
419
420                             // Thinko!
421                             // How to handle this? (Lgb)
422                             //&& !suffixIs(os, "\n\n")
423                                     //) {
424                                 // There should be at least one '\n' already
425                                 // but we need there to be two for Standard
426                                 // paragraphs that are depth-increment'ed to be
427                                 // output correctly.  However, tables can
428                                 // also be paragraphs so don't adjust them.
429                                 // ARRae
430                                 // Thinkee:
431                                 // Will it ever harm to have one '\n' too
432                                 // many? i.e. that we sometimes will have
433                                 // three in a row. (Lgb)
434                                 os << '\n';
435                                 texrow.newline();
436                         }
437                         par = TeXDeeper(buf, paragraphs, par, os, texrow,
438                                         runparams);
439                 }
440         } while (par != const_cast<ParagraphList&>(paragraphs).end()
441                  && par->layout() == pit->layout()
442                  && par->params().depth() == pit->params().depth()
443                  && par->params().leftIndent() == pit->params().leftIndent());
444
445         if (style->isEnvironment()) {
446                 os << "\\end{" << style->latexname() << "}\n";
447                 texrow.newline();
448         }
449
450         if (leftindent_open) {
451                 os << "\\end{LyXParagraphLeftIndent}\n";
452                 texrow.newline();
453         }
454
455         lyxerr[Debug::LATEX] << "TeXEnvironment...done " << &*par << endl;
456         return par;  // ale970302
457 }
458
459
460 InsetOptArg * optArgInset(Paragraph const & par)
461 {
462         // Find the entry.
463         InsetList::const_iterator it = par.insetlist.begin();
464         InsetList::const_iterator end = par.insetlist.end();
465         for (; it != end; ++it) {
466                 InsetOld * ins = it->inset;
467                 if (ins->lyxCode() == InsetOld::OPTARG_CODE) {
468                         return static_cast<InsetOptArg *>(ins);
469                 }
470         }
471         return 0;
472 }
473
474
475 ParagraphList::iterator
476 TeXOnePar(Buffer const & buf,
477           ParagraphList const & paragraphs,
478           ParagraphList::iterator pit,
479           ostream & os, TexRow & texrow,
480           LatexRunParams const & runparams,
481           string const & everypar)
482 {
483         lyxerr[Debug::LATEX] << "TeXOnePar...     " << &*pit << " '"
484                 << everypar << "'" << endl;
485         BufferParams const & bparams = buf.params();
486
487         InsetOld const * in = pit->inInset();
488         bool further_blank_line = false;
489         LyXLayout_ptr style;
490
491         // well we have to check if we are in an inset with unlimited
492         // length (all in one row) if that is true then we don't allow
493         // any special options in the paragraph and also we don't allow
494         // any environment other then "Standard" to be valid!
495         if (in == 0 || !in->forceDefaultParagraphs(in)) {
496                 style = pit->layout();
497
498                 if (pit->params().startOfAppendix()) {
499                         os << "\\appendix\n";
500                         texrow.newline();
501                 }
502
503                 if (!pit->params().spacing().isDefault()
504                         && (pit == const_cast<ParagraphList&>(paragraphs).begin()
505                             || !boost::prior(pit)->hasSameLayout(*pit)))
506                 {
507                         os << pit->params().spacing().writeEnvirBegin() << '\n';
508                         texrow.newline();
509                 }
510
511                 if (style->isCommand()) {
512                         os << '\n';
513                         texrow.newline();
514                 }
515
516                 if (pit->params().spaceTop().kind() != VSpace::NONE) {
517                         os << pit->params().spaceTop().asLatexCommand(bparams);
518                         further_blank_line = true;
519                 }
520
521                 if (further_blank_line) {
522                         os << '\n';
523                         texrow.newline();
524                 }
525         } else {
526                 style = bparams.getLyXTextClass().defaultLayout();
527         }
528
529         Language const * language = pit->getParLanguage(bparams);
530         Language const * doc_language = bparams.language;
531         Language const * previous_language =
532                 (pit != const_cast<ParagraphList&>(paragraphs).begin())
533                 ? boost::prior(pit)->getParLanguage(bparams)
534                 : doc_language;
535
536         if (language->babel() != previous_language->babel()
537             // check if we already put language command in TeXEnvironment()
538             && !(style->isEnvironment()
539                  && (pit == const_cast<ParagraphList&>(paragraphs).begin() ||
540                      (boost::prior(pit)->layout() != pit->layout() &&
541                       boost::prior(pit)->getDepth() <= pit->getDepth())
542                      || boost::prior(pit)->getDepth() < pit->getDepth())))
543         {
544                 if (!lyxrc.language_command_end.empty() &&
545                     previous_language->babel() != doc_language->babel())
546                 {
547                         os << subst(lyxrc.language_command_end, "$$lang",
548                                     previous_language->babel())
549                            << endl;
550                         texrow.newline();
551                 }
552
553                 if (lyxrc.language_command_end.empty() ||
554                     language->babel() != doc_language->babel())
555                 {
556                         os << subst(lyxrc.language_command_begin, "$$lang",
557                                     language->babel())
558                            << endl;
559                         texrow.newline();
560                 }
561         }
562
563         if (bparams.inputenc == "auto" &&
564             language->encoding() != previous_language->encoding()) {
565                 os << "\\inputencoding{"
566                    << language->encoding()->LatexName()
567                    << "}\n";
568                 texrow.newline();
569         }
570
571         switch (style->latextype) {
572         case LATEX_COMMAND:
573                 os << '\\' << style->latexname();
574
575                 // Separate handling of optional argument inset.
576                 if (style->optionalargs == 1) {
577                         InsetOptArg * it = optArgInset(*pit);
578                         if (it)
579                                 it->latexOptional(buf, os, runparams);
580                 }
581                 else
582                         os << style->latexparam();
583                 break;
584         case LATEX_ITEM_ENVIRONMENT:
585         case LATEX_LIST_ENVIRONMENT:
586                 os << "\\item ";
587                 break;
588         case LATEX_BIB_ENVIRONMENT:
589                 // ignore this, the inset will write itself
590                 break;
591         default:
592                 break;
593         }
594
595         os << everypar;
596         bool need_par = pit->simpleTeXOnePar(buf, bparams,
597                                              outerFont(pit, paragraphs),
598                                              os, texrow, runparams);
599
600         // Make sure that \\par is done with the font of the last
601         // character if this has another size as the default.
602         // This is necessary because LaTeX (and LyX on the screen)
603         // calculates the space between the baselines according
604         // to this font. (Matthias)
605         //
606         // Is this really needed ? (Dekel)
607         // We do not need to use to change the font for the last paragraph
608         // or for a command.
609         LyXFont const outerfont(outerFont(pit, paragraphs));
610
611         LyXFont const font =
612                 (pit->empty()
613                  ? pit->getLayoutFont(bparams, outerfont)
614                  : pit->getFont(bparams, pit->size() - 1, outerfont));
615
616         bool is_command = style->isCommand();
617
618         if (style->resfont.size() != font.size()
619             && boost::next(pit) != const_cast<ParagraphList&>(paragraphs).end()
620             && !is_command) {
621                 if (!need_par)
622                         os << '{';
623                 os << "\\" << font.latexSize() << " \\par}";
624         } else if (need_par) {
625                 os << "\\par}";
626         } else if (is_command)
627                 os << '}';
628
629         switch (style->latextype) {
630         case LATEX_ITEM_ENVIRONMENT:
631         case LATEX_LIST_ENVIRONMENT:
632                 if (boost::next(pit) != const_cast<ParagraphList&>(paragraphs).end()
633                     && (pit->params().depth() < boost::next(pit)->params().depth())) {
634                         os << '\n';
635                         texrow.newline();
636                 }
637                 break;
638         case LATEX_ENVIRONMENT: {
639                 // if its the last paragraph of the current environment
640                 // skip it otherwise fall through
641                 ParagraphList::iterator next = boost::next(pit);
642
643                 if (next != const_cast<ParagraphList&>(paragraphs).end()
644                     && (next->layout() != pit->layout()
645                         || next->params().depth() != pit->params().depth()))
646                         break;
647         }
648
649                 // fall through possible
650         default:
651                 // we don't need it for the last paragraph!!!
652                 if (boost::next(pit) != const_cast<ParagraphList&>(paragraphs).end()) {
653                         os << '\n';
654                         texrow.newline();
655                 }
656         }
657
658         if (in == 0 || !in->forceDefaultParagraphs(in)) {
659                 further_blank_line = false;
660
661                 if (pit->params().spaceBottom().kind() != VSpace::NONE) {
662                         os << pit->params().spaceBottom().asLatexCommand(bparams);
663                         further_blank_line = true;
664                 }
665
666                 if (further_blank_line) {
667                         os << '\n';
668                         texrow.newline();
669                 }
670
671                 if (!pit->params().spacing().isDefault()
672                         && (boost::next(pit) == const_cast<ParagraphList&>(paragraphs).end()
673                             || !boost::next(pit)->hasSameLayout(*pit)))
674                 {
675                         os << pit->params().spacing().writeEnvirEnd() << '\n';
676                         texrow.newline();
677                 }
678         }
679
680         // we don't need it for the last paragraph!!!
681         if (boost::next(pit) != const_cast<ParagraphList&>(paragraphs).end()) {
682                 os << '\n';
683                 texrow.newline();
684         } else {
685                 // Since \selectlanguage write the language to the aux file,
686                 // we need to reset the language at the end of footnote or
687                 // float.
688
689                 if (language->babel() != doc_language->babel()) {
690                         if (lyxrc.language_command_end.empty())
691                                 os << subst(lyxrc.language_command_begin,
692                                             "$$lang",
693                                             doc_language->babel())
694                                    << endl;
695                         else
696                                 os << subst(lyxrc.language_command_end,
697                                             "$$lang",
698                                             language->babel())
699                                    << endl;
700                         texrow.newline();
701                 }
702         }
703
704         lyxerr[Debug::LATEX] << "TeXOnePar...done " << &*boost::next(pit) << endl;
705         return ++pit;
706 }
707
708 } // anon namespace
709
710
711 //
712 // LaTeX all paragraphs from par to endpar, if endpar == 0 then to the end
713 //
714 void latexParagraphs(Buffer const & buf,
715                      ParagraphList const & paragraphs,
716                      ostream & os,
717                      TexRow & texrow,
718                      LatexRunParams const & runparams,
719                      string const & everypar)
720 {
721         bool was_title = false;
722         bool already_title = false;
723         LyXTextClass const & tclass = buf.params().getLyXTextClass();
724         ParagraphList::iterator par = const_cast<ParagraphList&>(paragraphs).begin();
725         ParagraphList::iterator endpar = const_cast<ParagraphList&>(paragraphs).end();
726
727         // if only_body
728         while (par != endpar) {
729                 InsetOld * in = par->inInset();
730                 // well we have to check if we are in an inset with unlimited
731                 // length (all in one row) if that is true then we don't allow
732                 // any special options in the paragraph and also we don't allow
733                 // any environment other then "Standard" to be valid!
734                 if (in == 0 || !in->forceDefaultParagraphs(in)) {
735                         LyXLayout_ptr const & layout = par->layout();
736
737                         if (layout->intitle) {
738                                 if (already_title) {
739                                         lyxerr <<"Error in latexParagraphs: You"
740                                                 " should not mix title layouts"
741                                                 " with normal ones." << endl;
742                                 } else if (!was_title) {
743                                         was_title = true;
744                                         if (tclass.titletype() == TITLE_ENVIRONMENT) {
745                                                 os << "\\begin{"
746                                                     << tclass.titlename()
747                                                     << "}\n";
748                                                 texrow.newline();
749                                         }
750                                 }
751                         } else if (was_title && !already_title) {
752                                 if (tclass.titletype() == TITLE_ENVIRONMENT) {
753                                         os << "\\end{" << tclass.titlename()
754                                             << "}\n";
755                                 }
756                                 else {
757                                         os << "\\" << tclass.titlename()
758                                             << "\n";
759                                 }
760                                 texrow.newline();
761                                 already_title = true;
762                                 was_title = false;
763                         }
764
765                         if (layout->is_environment) {
766                                 par = TeXOnePar(buf, paragraphs, par, os, texrow,
767                                                 runparams, everypar);
768                         } else if (layout->isEnvironment() ||
769                                 !par->params().leftIndent().zero())
770                         {
771                                 par = TeXEnvironment(buf, paragraphs, par, os,
772                                                      texrow, runparams);
773                         } else {
774                                 par = TeXOnePar(buf, paragraphs, par, os, texrow,
775                                                 runparams, everypar);
776                         }
777                 } else {
778                         par = TeXOnePar(buf, paragraphs, par, os, texrow,
779                                         runparams, everypar);
780                 }
781         }
782         // It might be that we only have a title in this document
783         if (was_title && !already_title) {
784                 if (tclass.titletype() == TITLE_ENVIRONMENT) {
785                         os << "\\end{" << tclass.titlename()
786                             << "}\n";
787                 }
788                 else {
789                         os << "\\" << tclass.titlename()
790                             << "\n";
791                                 }
792                 texrow.newline();
793         }
794 }
795
796
797 void linuxdocParagraphs(Buffer const & buf,
798                         ParagraphList const & paragraphs,
799                         ostream & os)
800 {
801         
802         Paragraph::depth_type depth = 0; // paragraph depth
803         string item_name;
804         vector<string> environment_stack(5);
805
806         ParagraphList::iterator pit = const_cast<ParagraphList&>(paragraphs).begin();
807         ParagraphList::iterator pend = const_cast<ParagraphList&>(paragraphs).end();
808         for (; pit != pend; ++pit) {
809                 LyXLayout_ptr const & style = pit->layout();
810                 // treat <toc> as a special case for compatibility with old code
811                 if (pit->isInset(0)) {
812                         InsetOld * inset = pit->getInset(0);
813                         InsetOld::Code lyx_code = inset->lyxCode();
814                         if (lyx_code == InsetOld::TOC_CODE) {
815                                 string const temp = "toc";
816                                 sgml::openTag(os, depth, false, temp);
817                                 continue;
818                         }
819                 }
820
821                 // environment tag closing
822                 for (; depth > pit->params().depth(); --depth) {
823                         sgml::closeTag(os, depth, false, environment_stack[depth]);
824                         environment_stack[depth].erase();
825                 }
826
827                 // write opening SGML tags
828                 switch (style->latextype) {
829                 case LATEX_PARAGRAPH:
830                         if (depth == pit->params().depth()
831                            && !environment_stack[depth].empty()) {
832                                 sgml::closeTag(os, depth, false, environment_stack[depth]);
833                                 environment_stack[depth].erase();
834                                 if (depth)
835                                         --depth;
836                                 else
837                                         os << "</p>";
838                         }
839                         sgml::openTag(os, depth, false, style->latexname());
840                         break;
841
842                 case LATEX_COMMAND:
843                         if (depth != 0)
844                                 //error(ErrorItem(_("Error:"), _("Wrong depth for LatexType Command.\n"), pit->id(), 0, pit->size()));
845                                 ;
846
847                         if (!environment_stack[depth].empty()) {
848                                 sgml::closeTag(os, depth, false, environment_stack[depth]);
849                                 os << "</p>";
850                         }
851
852                         environment_stack[depth].erase();
853                         sgml::openTag(os, depth, false, style->latexname());
854                         break;
855
856                 case LATEX_ENVIRONMENT:
857                 case LATEX_ITEM_ENVIRONMENT:
858                 case LATEX_BIB_ENVIRONMENT:
859                 {
860                         string const & latexname = style->latexname();
861
862                         if (depth == pit->params().depth()
863                             && environment_stack[depth] != latexname) {
864                                 sgml::closeTag(os, depth, false,
865                                              environment_stack[depth]);
866                                 environment_stack[depth].erase();
867                         }
868                         if (depth < pit->params().depth()) {
869                                depth = pit->params().depth();
870                                environment_stack[depth].erase();
871                         }
872                         if (environment_stack[depth] != latexname) {
873                                 if (depth == 0) {
874                                         sgml::openTag(os, depth, false, "p");
875                                 }
876                                 sgml::openTag(os, depth, false, latexname);
877
878                                 if (environment_stack.size() == depth + 1)
879                                         environment_stack.push_back("!-- --");
880                                 environment_stack[depth] = latexname;
881                         }
882
883                         if (style->latexparam() == "CDATA")
884                                 os << "<![CDATA[";
885
886                         if (style->latextype == LATEX_ENVIRONMENT) break;
887
888                         if (style->labeltype == LABEL_MANUAL)
889                                 item_name = "tag";
890                         else
891                                 item_name = "item";
892
893                         sgml::openTag(os, depth + 1, false, item_name);
894                 }
895                 break;
896
897                 default:
898                         sgml::openTag(os, depth, false, style->latexname());
899                         break;
900                 }
901
902                 pit->simpleLinuxDocOnePar(buf, os, outerFont(pit, paragraphs), depth);
903
904                 os << "\n";
905                 // write closing SGML tags
906                 switch (style->latextype) {
907                 case LATEX_COMMAND:
908                         break;
909                 case LATEX_ENVIRONMENT:
910                 case LATEX_ITEM_ENVIRONMENT:
911                 case LATEX_BIB_ENVIRONMENT:
912                         if (style->latexparam() == "CDATA")
913                                 os << "]]>";
914                         break;
915                 default:
916                         sgml::closeTag(os, depth, false, style->latexname());
917                         break;
918                 }
919         }
920
921         // Close open tags
922         for (int i = depth; i >= 0; --i)
923                 sgml::closeTag(os, depth, false, environment_stack[i]);
924 }
925
926
927 void docbookParagraphs(Buffer const & buf,
928                        ParagraphList const & paragraphs,
929                        ostream & os)
930 {
931         vector<string> environment_stack(10);
932         vector<string> environment_inner(10);
933         vector<string> command_stack(10);
934
935         bool command_flag = false;
936         Paragraph::depth_type command_depth = 0;
937         Paragraph::depth_type command_base = 0;
938         Paragraph::depth_type cmd_depth = 0;
939         Paragraph::depth_type depth = 0; // paragraph depth
940
941         string item_name;
942         string command_name;
943
944         ParagraphList::iterator par = const_cast<ParagraphList&>(paragraphs).begin();
945         ParagraphList::iterator pend = const_cast<ParagraphList&>(paragraphs).end();
946
947         for (; par != pend; ++par) {
948                 string sgmlparam;
949                 string c_depth;
950                 string c_params;
951                 int desc_on = 0; // description mode
952
953                 LyXLayout_ptr const & style = par->layout();
954
955                 // environment tag closing
956                 for (; depth > par->params().depth(); --depth) {
957                         if (!environment_inner[depth].empty()) 
958                         sgml::closeEnvTags(os, false, environment_inner[depth], 
959                                         command_depth + depth);
960                         sgml::closeTag(os, depth + command_depth, false, environment_stack[depth]);
961                         environment_stack[depth].erase();
962                         environment_inner[depth].erase();
963                 }
964
965                 if (depth == par->params().depth()
966                    && environment_stack[depth] != style->latexname()
967                    && !environment_stack[depth].empty()) {
968                                 sgml::closeEnvTags(os, false, environment_inner[depth], 
969                                         command_depth + depth);
970                         sgml::closeTag(os, depth + command_depth, false, environment_stack[depth]);
971
972                         environment_stack[depth].erase();
973                         environment_inner[depth].erase();
974                 }
975
976                 // Write opening SGML tags.
977                 switch (style->latextype) {
978                 case LATEX_PARAGRAPH:
979                         sgml::openTag(os, depth + command_depth,
980                                     false, style->latexname());
981                         break;
982
983                 case LATEX_COMMAND:
984                         if (depth != 0)
985                                 //error(ErrorItem(_("Error"), _("Wrong depth for LatexType Command."), par->id(), 0, par->size()));
986                                 ;
987                         
988                         command_name = style->latexname();
989
990                         sgmlparam = style->latexparam();
991                         c_params = split(sgmlparam, c_depth,'|');
992
993                         cmd_depth = atoi(c_depth);
994
995                         if (command_flag) {
996                                 if (cmd_depth < command_base) {
997                                         for (Paragraph::depth_type j = command_depth;
998                                              j >= command_base; --j) {
999                                                 sgml::closeTag(os, j, false, command_stack[j]);
1000                                                 os << endl;
1001                                         }
1002                                         command_depth = command_base = cmd_depth;
1003                                 } else if (cmd_depth <= command_depth) {
1004                                         for (int j = command_depth;
1005                                              j >= int(cmd_depth); --j) {
1006                                                 sgml::closeTag(os, j, false, command_stack[j]);
1007                                                 os << endl;
1008                                         }
1009                                         command_depth = cmd_depth;
1010                                 } else
1011                                         command_depth = cmd_depth;
1012                         } else {
1013                                 command_depth = command_base = cmd_depth;
1014                                 command_flag = true;
1015                         }
1016                         if (command_stack.size() == command_depth + 1)
1017                                 command_stack.push_back(string());
1018                         command_stack[command_depth] = command_name;
1019
1020                         // treat label as a special case for
1021                         // more WYSIWYM handling.
1022                         // This is a hack while paragraphs can't have
1023                         // attributes, like id in this case.
1024                         if (par->isInset(0)) {
1025                                 InsetOld * inset = par->getInset(0);
1026                                 InsetOld::Code lyx_code = inset->lyxCode();
1027                                 if (lyx_code == InsetOld::LABEL_CODE) {
1028                                         command_name += " id=\"";
1029                                         command_name += (static_cast<InsetCommand *>(inset))->getContents();
1030                                         command_name += '"';
1031                                         desc_on = 3;
1032                                 }
1033                         }
1034
1035                         sgml::openTag(os, depth + command_depth, false, command_name);
1036
1037                         item_name = c_params.empty() ? "title" : c_params;
1038                         sgml::openTag(os, depth + 1 + command_depth, false, item_name);
1039                         break;
1040
1041                 case LATEX_ENVIRONMENT:
1042                 case LATEX_ITEM_ENVIRONMENT:
1043                         if (depth < par->params().depth()) {
1044                                 depth = par->params().depth();
1045                                 environment_stack[depth].erase();
1046                         }
1047
1048                         if (environment_stack[depth] != style->latexname()) {
1049                                 if (environment_stack.size() == depth + 1) {
1050                                         environment_stack.push_back("!-- --");
1051                                         environment_inner.push_back("!-- --");
1052                                 }
1053                                 environment_stack[depth] = style->latexname();
1054                                 environment_inner[depth] = "!-- --";
1055                                 sgml::openTag(os, depth + command_depth, false, environment_stack[depth]);
1056                         } else {
1057                                         sgml::closeEnvTags(os, false, environment_inner[depth], 
1058                                                 command_depth + depth);
1059                         }
1060
1061                         if (style->latextype == LATEX_ENVIRONMENT) {
1062                                 if (!style->latexparam().empty()) {
1063                                         if (style->latexparam() == "CDATA")
1064                                                 os << "<![CDATA[";
1065                                         else
1066                                                 sgml::openTag(os, depth + command_depth, false, style->latexparam());
1067                                 }
1068                                 break;
1069                         }
1070
1071                         desc_on = (style->labeltype == LABEL_MANUAL);
1072
1073                         environment_inner[depth] = desc_on ? "varlistentry" : "listitem";
1074                         sgml::openTag(os, depth + 1 + command_depth,
1075                                     false, environment_inner[depth]);
1076
1077                         item_name = desc_on ? "term" : "para";
1078                         sgml::openTag(os, depth + 1 + command_depth,
1079                                     false, item_name);
1080                         break;
1081                 default:
1082                         sgml::openTag(os, depth + command_depth,
1083                                     false, style->latexname());
1084                         break;
1085                 }
1086
1087                 par->simpleDocBookOnePar(buf, os, outerFont(par, paragraphs), desc_on,
1088                                     depth + 1 + command_depth);
1089
1090                 string end_tag;
1091                 // write closing SGML tags
1092                 switch (style->latextype) {
1093                 case LATEX_COMMAND:
1094                         end_tag = c_params.empty() ? "title" : c_params;
1095                         sgml::closeTag(os, depth + command_depth,
1096                                      false, end_tag);
1097                         break;
1098                 case LATEX_ENVIRONMENT:
1099                         if (!style->latexparam().empty()) {
1100                                 if (style->latexparam() == "CDATA")
1101                                         os << "]]>";
1102                                 else
1103                                         sgml::closeTag(os, depth + command_depth, false, style->latexparam());
1104                         }
1105                         break;
1106                 case LATEX_ITEM_ENVIRONMENT:
1107                         if (desc_on == 1) break;
1108                         end_tag = "para";
1109                         sgml::closeTag(os, depth + 1 + command_depth, false, end_tag);
1110                         break;
1111                 case LATEX_PARAGRAPH:
1112                         sgml::closeTag(os, depth + command_depth, false, style->latexname());
1113                         break;
1114                 default:
1115                         sgml::closeTag(os, depth + command_depth, false, style->latexname());
1116                         break;
1117                 }
1118         }
1119
1120         // Close open tags
1121         for (int d = depth; d >= 0; --d) {
1122                 if (!environment_stack[depth].empty()) {
1123                                 sgml::closeEnvTags(os, false, environment_inner[depth], 
1124                                         command_depth + depth);
1125                 }
1126         }
1127
1128         for (int j = command_depth; j >= 0 ; --j)
1129                 if (!command_stack[j].empty()) {
1130                         sgml::closeTag(os, j, false, command_stack[j]);
1131                         os << endl;
1132                 }
1133 }
1134
1135 namespace {
1136
1137 int readParToken(Buffer & buf, Paragraph & par, LyXLex & lex, string const & token)
1138 {
1139         static LyXFont font;
1140         static Change change;
1141
1142         BufferParams const & bp = buf.params();
1143
1144         if (token[0] != '\\') {
1145                 string::const_iterator cit = token.begin();
1146                 for (; cit != token.end(); ++cit) {
1147                         par.insertChar(par.size(), (*cit), font, change);
1148                 }
1149         } else if (token == "\\begin_layout") {
1150                 lex.eatLine();
1151                 string layoutname = lex.getString();
1152
1153                 font = LyXFont(LyXFont::ALL_INHERIT, bp.language);
1154                 change = Change();
1155
1156                 LyXTextClass const & tclass = bp.getLyXTextClass();
1157
1158                 if (layoutname.empty()) {
1159                         layoutname = tclass.defaultLayoutName();
1160                 }
1161
1162                 bool hasLayout = tclass.hasLayout(layoutname);
1163
1164                 if (!hasLayout) {
1165                         lyxerr << "Layout '" << layoutname << "' does not"
1166                                << " exist in textclass '" << tclass.name()
1167                                << "'." << endl;
1168                         lyxerr << "Trying to use default layout instead."
1169                                << endl;
1170                         layoutname = tclass.defaultLayoutName();
1171                 }
1172
1173                 par.layout(bp.getLyXTextClass()[layoutname]);
1174
1175                 // Test whether the layout is obsolete.
1176                 LyXLayout_ptr const & layout = par.layout();
1177                 if (!layout->obsoleted_by().empty())
1178                         par.layout(bp.getLyXTextClass()[layout->obsoleted_by()]);
1179
1180                 par.params().read(lex);
1181
1182         } else if (token == "\\end_layout") {
1183                 lyxerr << "Solitary \\end_layout in line " << lex.getLineNo() << "\n"
1184                        << "Missing \\begin_layout?.\n";
1185         } else if (token == "\\end_inset") {
1186                 lyxerr << "Solitary \\end_inset in line " << lex.getLineNo() << "\n"
1187                        << "Missing \\begin_inset?.\n";
1188         } else if (token == "\\begin_inset") {
1189                 InsetOld * inset = readInset(lex, buf);
1190                 if (inset)
1191                         par.insertInset(par.size(), inset, font, change);
1192                 else {
1193                         lex.eatLine();
1194                         string line = lex.getString();
1195                         buf.error(ErrorItem(_("Unknown Inset"), line,
1196                                             buf.paragraphs().back().id(),
1197                                             0, par.size()));
1198                         return 1;
1199                 }
1200         } else if (token == "\\family") {
1201                 lex.next();
1202                 font.setLyXFamily(lex.getString());
1203         } else if (token == "\\series") {
1204                 lex.next();
1205                 font.setLyXSeries(lex.getString());
1206         } else if (token == "\\shape") {
1207                 lex.next();
1208                 font.setLyXShape(lex.getString());
1209         } else if (token == "\\size") {
1210                 lex.next();
1211                 font.setLyXSize(lex.getString());
1212         } else if (token == "\\lang") {
1213                 lex.next();
1214                 string const tok = lex.getString();
1215                 Language const * lang = languages.getLanguage(tok);
1216                 if (lang) {
1217                         font.setLanguage(lang);
1218                 } else {
1219                         font.setLanguage(bp.language);
1220                         lex.printError("Unknown language `$$Token'");
1221                 }
1222         } else if (token == "\\numeric") {
1223                 lex.next();
1224                 font.setNumber(font.setLyXMisc(lex.getString()));
1225         } else if (token == "\\emph") {
1226                 lex.next();
1227                 font.setEmph(font.setLyXMisc(lex.getString()));
1228         } else if (token == "\\bar") {
1229                 lex.next();
1230                 string const tok = lex.getString();
1231
1232                 if (tok == "under")
1233                         font.setUnderbar(LyXFont::ON);
1234                 else if (tok == "no")
1235                         font.setUnderbar(LyXFont::OFF);
1236                 else if (tok == "default")
1237                         font.setUnderbar(LyXFont::INHERIT);
1238                 else
1239                         lex.printError("Unknown bar font flag "
1240                                        "`$$Token'");
1241         } else if (token == "\\noun") {
1242                 lex.next();
1243                 font.setNoun(font.setLyXMisc(lex.getString()));
1244         } else if (token == "\\color") {
1245                 lex.next();
1246                 font.setLyXColor(lex.getString());
1247         } else if (token == "\\InsetSpace" || token == "\\SpecialChar") {
1248
1249                 // Insets don't make sense in a free-spacing context! ---Kayvan
1250                 if (par.isFreeSpacing()) {
1251                         if (token == "\\InsetSpace")
1252                                 par.insertChar(par.size(), ' ', font, change);
1253                         else if (lex.isOK()) {
1254                                 lex.next();
1255                                 string const next_token = lex.getString();
1256                                 if (next_token == "\\-")
1257                                         par.insertChar(par.size(), '-', font, change);
1258                                 else {
1259                                         lex.printError("Token `$$Token' "
1260                                                        "is in free space "
1261                                                        "paragraph layout!");
1262                                 }
1263                         }
1264                 } else {
1265                         InsetOld * inset = 0;
1266                         if (token == "\\SpecialChar" )
1267                                 inset = new InsetSpecialChar;
1268                         else
1269                                 inset = new InsetSpace;
1270                         inset->read(buf, lex);
1271                         par.insertInset(par.size(), inset, font, change);
1272                 }
1273         } else if (token == "\\i") {
1274                 InsetOld * inset = new InsetLatexAccent;
1275                 inset->read(buf, lex);
1276                 par.insertInset(par.size(), inset, font, change);
1277         } else if (token == "\\backslash") {
1278                 par.insertChar(par.size(), '\\', font, change);
1279         } else if (token == "\\newline") {
1280                 InsetOld * inset = new InsetNewline;
1281                 inset->read(buf, lex);
1282                 par.insertInset(par.size(), inset, font, change);
1283         } else if (token == "\\LyXTable") {
1284                 InsetOld * inset = new InsetTabular(buf);
1285                 inset->read(buf, lex);
1286                 par.insertInset(par.size(), inset, font, change);
1287         } else if (token == "\\bibitem") {
1288                 InsetCommandParams p("bibitem", "dummy");
1289                 InsetBibitem * inset = new InsetBibitem(p);
1290                 inset->read(buf, lex);
1291                 par.insertInset(par.size(), inset, font, change);
1292         } else if (token == "\\hfill") {
1293                 par.insertInset(par.size(), new InsetHFill, font, change);
1294         } else if (token == "\\lyxline") {
1295                 par.insertInset(par.size(), new InsetLine, font, change);
1296         } else if (token == "\\newpage") {
1297                 par.insertInset(par.size(), new InsetPagebreak, font, change);
1298         } else if (token == "\\change_unchanged") {
1299                 // Hack ! Needed for empty paragraphs :/
1300                 // FIXME: is it still ??
1301                 if (!par.size())
1302                         par.cleanChanges();
1303                 change = Change(Change::UNCHANGED);
1304         } else if (token == "\\change_inserted") {
1305                 lex.nextToken();
1306                 istringstream is(lex.getString());
1307                 int aid;
1308                 lyx::time_type ct;
1309                 is >> aid >> ct;
1310                 change = Change(Change::INSERTED, bp.author_map[aid], ct);
1311         } else if (token == "\\change_deleted") {
1312                 lex.nextToken();
1313                 istringstream is(lex.getString());
1314                 int aid;
1315                 lyx::time_type ct;
1316                 is >> aid >> ct;
1317                 change = Change(Change::DELETED, bp.author_map[aid], ct);
1318         } else {
1319                 lex.eatLine();
1320                 string const s = bformat(_("Unknown token: %1$s %2$s\n"),
1321                         token, lex.getString());
1322
1323                 buf.error(ErrorItem(_("Unknown token"), s,
1324                                     buf.paragraphs().back().id(),
1325                                     0, par.size()));
1326                 return 1;
1327         }
1328         return 0;
1329 }
1330
1331 }
1332
1333
1334 int readParagraph(Buffer & buf, Paragraph & par, LyXLex & lex)
1335 {
1336         int unknown = 0;
1337
1338         lex.nextToken();
1339         string token = lex.getString();
1340
1341         while (lex.isOK()) {
1342
1343                 unknown += readParToken(buf, par, lex, token);
1344
1345                 lex.nextToken();
1346                 token = lex.getString();
1347
1348                 if (token.empty())
1349                         continue;
1350
1351                 if (token == "\\end_layout") {
1352                         //Ok, paragraph finished
1353                         break;
1354                 }
1355
1356                 lyxerr[Debug::PARSER] << "Handling paragraph token: `"
1357                                       << token << '\'' << endl;
1358                 if (token == "\\begin_layout" || token == "\\end_document"
1359                     || token == "\\end_inset" || token == "\\begin_deeper"
1360                     || token == "\\end_deeper") {
1361                         lex.pushToken(token);
1362                         lyxerr << "Paragraph ended in line "
1363                                << lex.getLineNo() << "\n"
1364                                << "Missing \\end_layout.\n";
1365                         break;
1366                 }
1367         }
1368
1369         return unknown;
1370 }
1371
1372
1373 LyXFont const outerFont(ParagraphList::iterator pit,
1374                         ParagraphList const & plist)
1375 {
1376         Paragraph::depth_type par_depth = pit->getDepth();
1377         LyXFont tmpfont(LyXFont::ALL_INHERIT);
1378
1379         // Resolve against environment font information
1380         while (pit != const_cast<ParagraphList&>(plist).end() &&
1381                par_depth && !tmpfont.resolved()) {
1382                 pit = outerHook(pit, plist);
1383                 if (pit != const_cast<ParagraphList&>(plist).end()) {
1384                         tmpfont.realize(pit->layout()->font);
1385                         par_depth = pit->getDepth();
1386                 }
1387         }
1388
1389         return tmpfont;
1390 }
1391
1392
1393 ParagraphList::iterator outerPar(Buffer const & buf, InsetOld const * inset)
1394 {
1395         ParIterator pit = const_cast<Buffer &>(buf).par_iterator_begin();
1396         ParIterator end = const_cast<Buffer &>(buf).par_iterator_end();
1397         for ( ; pit != end; ++pit) {
1398
1399                 ParagraphList * plist;
1400                 // the second '=' below is intentional
1401                 for (int i = 0; (plist = inset->getParagraphs(i)); ++i)
1402                         if (plist == &pit.plist())
1403                                 return pit.outerPar();
1404
1405                 InsetList::iterator ii = pit->insetlist.begin();
1406                 InsetList::iterator iend = pit->insetlist.end();
1407                 for ( ; ii != iend; ++ii)
1408                         if (ii->inset == inset)
1409                                 return pit.outerPar();
1410         }
1411         lyxerr << "outerPar: should not happen" << endl;
1412         BOOST_ASSERT(false);
1413         return const_cast<Buffer &>(buf).paragraphs().end(); // shut up compiler
1414 }
1415
1416
1417 Paragraph const & ownerPar(Buffer const & buf, InsetOld const * inset)
1418 {
1419         ParConstIterator pit = buf.par_iterator_begin();
1420         ParConstIterator end = buf.par_iterator_end();
1421         for ( ; pit != end; ++pit) {
1422                 ParagraphList * plist;
1423                 // the second '=' below is intentional
1424                 for (int i = 0; (plist = inset->getParagraphs(i)); ++i)
1425                         if (plist == &pit.plist())
1426                                 return *pit.pit();
1427
1428                 InsetList::const_iterator ii = pit->insetlist.begin();
1429                 InsetList::const_iterator iend = pit->insetlist.end();
1430                 for ( ; ii != iend; ++ii)
1431                         if (ii->inset == inset)
1432                                 return *pit.pit();
1433         }
1434         lyxerr << "ownerPar: should not happen" << endl;
1435         BOOST_ASSERT(false);
1436         return buf.paragraphs().front(); // shut up compiler
1437 }